From 1d2d099a22be18853d7d0033f953bb9b0102f891 Mon Sep 17 00:00:00 2001 From: Evan Feenstra Date: Wed, 22 Jun 2022 09:34:14 -0700 Subject: [PATCH 1/5] top Status enum, separate thread for LED states --- sphinx-key/src/core/events.rs | 21 +++++++++++++++++++++ sphinx-key/src/main.rs | 19 +++++++++---------- sphinx-key/src/periph/led.rs | 11 +++++++++++ 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/sphinx-key/src/core/events.rs b/sphinx-key/src/core/events.rs index 4c59eb9..738d4ba 100644 --- a/sphinx-key/src/core/events.rs +++ b/sphinx-key/src/core/events.rs @@ -18,12 +18,24 @@ pub enum Event { Message(Vec), } +#[derive(Debug)] +pub enum Status { + WifiAccessPoint, + WifiAccessPointClientConnected, + ConnectingToWifi, + ConnectingToMqtt, + ConnectedToMqtt, + MessageReceived, +} + +// the main event loop #[cfg(not(feature = "pingpong"))] pub fn make_event_loop( mut mqtt: EspMqttClient>, rx: mpsc::Receiver, network: Network, do_log: bool, + led_tx: mpsc::Sender ) -> Result<()> { // initialize the RootHandler let root_handler = loop { @@ -33,6 +45,7 @@ pub fn make_event_loop( log::info!("SUBSCRIBE to {}", TOPIC); mqtt.subscribe(TOPIC, QOS) .expect("could not MQTT subscribe"); + led_tx.send(Status::ConnectedToMqtt).unwrap(); } Event::Message(ref msg_bytes) => { let InitResponse { @@ -44,6 +57,7 @@ pub fn make_event_loop( break root_handler; } Event::Disconnected => { + led_tx.send(Status::ConnectingToMqtt).unwrap(); log::info!("GOT an early Event::Disconnected msg!"); } } @@ -58,8 +72,10 @@ pub fn make_event_loop( log::info!("SUBSCRIBE TO {}", TOPIC); mqtt.subscribe(TOPIC, QOS) .expect("could not MQTT subscribe"); + led_tx.send(Status::ConnectedToMqtt).unwrap(); } Event::Message(ref msg_bytes) => { + led_tx.send(Status::MessageReceived).unwrap(); let _ret = match sphinx_key_signer::handle( &root_handler, msg_bytes.clone(), @@ -73,6 +89,7 @@ pub fn make_event_loop( }; } Event::Disconnected => { + led_tx.send(Status::ConnectingToMqtt).unwrap(); log::info!("GOT A Event::Disconnected msg!"); } } @@ -87,16 +104,19 @@ pub fn make_event_loop( rx: mpsc::Receiver, _network: Network, do_log: bool, + led_tx: mpsc::Sender ) -> Result<()> { log::info!("About to subscribe to the mpsc channel"); while let Ok(event) = rx.recv() { match event { Event::Connected => { + led_tx.send(Status::ConnectedToMqtt).unwrap(); log::info!("SUBSCRIBE TO {}", TOPIC); mqtt.subscribe(TOPIC, QOS) .expect("could not MQTT subscribe"); } Event::Message(msg_bytes) => { + led_tx.send(Status::MessageReceived).unwrap(); let b = sphinx_key_signer::parse_ping_and_form_response(msg_bytes); if do_log { log::info!("GOT A PING MESSAGE! returning pong now..."); @@ -105,6 +125,7 @@ pub fn make_event_loop( .expect("could not publish ping response"); } Event::Disconnected => { + led_tx.send(Status::ConnectingToMqtt).unwrap(); log::info!("GOT A Event::Disconnected msg!"); } } diff --git a/sphinx-key/src/main.rs b/sphinx-key/src/main.rs index 886c9cb..fae467f 100644 --- a/sphinx-key/src/main.rs +++ b/sphinx-key/src/main.rs @@ -4,7 +4,7 @@ mod core; mod periph; use crate::core::{events::*, config::*}; -use crate::periph::led::Led; +use crate::periph::led::{Led, led_control_loop}; use esp_idf_sys as _; // If using the `binstart` feature of `esp-idf-sys`, always keep this module imported use std::thread; @@ -50,16 +50,22 @@ fn main() -> Result<()> { thread::sleep(Duration::from_secs(1)); + let (led_tx, led_rx) = mpsc::channel(); + // LED control thread + led_control_loop(led_rx); + let default_nvs = Arc::new(EspDefaultNvs::new()?); let mut store = EspNvsStorage::new_default(default_nvs.clone(), "sphinx", true).expect("no storage"); let existing: Option = store.get("config").expect("failed"); if let Some(exist) = existing { println!("=============> START CLIENT NOW <============== {:?}", exist); // store.remove("config").expect("couldnt remove config"); + led_tx.send(Status::ConnectingToWifi).unwrap(); let wifi = start_wifi_client(default_nvs.clone(), &exist)?; let (tx, rx) = mpsc::channel(); + led_tx.send(Status::ConnectingToMqtt).unwrap(); // _conn needs to stay in scope or its dropped let (mqtt, connection) = conn::mqtt::make_client(&exist.broker, CLIENT_ID)?; let mqtt_client = conn::mqtt::start_listening(mqtt, connection, tx)?; @@ -67,17 +73,10 @@ fn main() -> Result<()> { // this blocks forever... the "main thread" log::info!(">>>>>>>>>>> blocking forever..."); let do_log = true; - make_event_loop(mqtt_client, rx, network, do_log)?; + make_event_loop(mqtt_client, rx, network, do_log, led_tx)?; - let mut blue = Led::new(0x000001, 100); - println!("{:?}", wifi.get_status()); - loop { - log::info!("Listening..."); - blue.blink(); - thread::sleep(Duration::from_secs(1)); - } - // drop(wifi); } else { + led_tx.send(Status::WifiAccessPoint).unwrap(); println!("=============> START SERVER NOW AND WAIT <=============="); if let Ok((wifi, config)) = start_config_server_and_wait(default_nvs.clone()) { store.put("config", &config).expect("could not store config"); diff --git a/sphinx-key/src/periph/led.rs b/sphinx-key/src/periph/led.rs index b6ca157..ca0bcd4 100644 --- a/sphinx-key/src/periph/led.rs +++ b/sphinx-key/src/periph/led.rs @@ -1,3 +1,4 @@ +use crate::core::events::Status; use core::time::Duration; use embedded_hal::delay::blocking::DelayUs; use esp_idf_hal::delay::Ets; @@ -5,6 +6,8 @@ use esp_idf_hal::gpio::Gpio8; use esp_idf_hal::peripherals::Peripherals; use esp_idf_hal::rmt::config::TransmitConfig; use esp_idf_hal::rmt::{FixedLengthSignal, PinState, Pulse, Transmit}; +use std::sync::mpsc; +use std::thread; use std::sync::{LazyLock, Mutex}; @@ -21,6 +24,14 @@ pub struct Led { blink_length: u32, } +pub fn led_control_loop(rx: mpsc::Receiver) { + thread::spawn(move || { + while let Ok(status) = rx.recv() { + log::info!("LED STATUS: {:?}", status); + } + }); +} + impl Led { pub fn new(rgb: u32, blink_length: u32) -> Led { Led { From ae3d9469126e27c8a01115bd97788698266f3f1d Mon Sep 17 00:00:00 2001 From: Evan Feenstra Date: Wed, 22 Jun 2022 16:08:45 -0700 Subject: [PATCH 2/5] try_recv for changing led status --- sphinx-key/src/core/events.rs | 7 ++++--- sphinx-key/src/main.rs | 8 ++++---- sphinx-key/src/periph/led.rs | 13 ++++++++++--- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/sphinx-key/src/core/events.rs b/sphinx-key/src/core/events.rs index 738d4ba..77f2208 100644 --- a/sphinx-key/src/core/events.rs +++ b/sphinx-key/src/core/events.rs @@ -20,11 +20,12 @@ pub enum Event { #[derive(Debug)] pub enum Status { + Starting, WifiAccessPoint, WifiAccessPointClientConnected, ConnectingToWifi, ConnectingToMqtt, - ConnectedToMqtt, + Connected, MessageReceived, } @@ -45,7 +46,7 @@ pub fn make_event_loop( log::info!("SUBSCRIBE to {}", TOPIC); mqtt.subscribe(TOPIC, QOS) .expect("could not MQTT subscribe"); - led_tx.send(Status::ConnectedToMqtt).unwrap(); + led_tx.send(Status::Connected).unwrap(); } Event::Message(ref msg_bytes) => { let InitResponse { @@ -72,7 +73,7 @@ pub fn make_event_loop( log::info!("SUBSCRIBE TO {}", TOPIC); mqtt.subscribe(TOPIC, QOS) .expect("could not MQTT subscribe"); - led_tx.send(Status::ConnectedToMqtt).unwrap(); + led_tx.send(Status::Connected).unwrap(); } Event::Message(ref msg_bytes) => { led_tx.send(Status::MessageReceived).unwrap(); diff --git a/sphinx-key/src/main.rs b/sphinx-key/src/main.rs index fae467f..16ad9ab 100644 --- a/sphinx-key/src/main.rs +++ b/sphinx-key/src/main.rs @@ -29,6 +29,10 @@ const NETWORK: Option<&'static str> = option_env!("NETWORK"); fn main() -> Result<()> { + // Temporary. Will disappear once ESP-IDF 4.4 is released, but for now it is necessary to call this function once, + // or else some patches to the runtime implemented by esp-idf-sys might not link properly. + esp_idf_sys::link_patches(); + let network: Network = if let Some(n) = NETWORK { match n { "bitcoin" => Network::Bitcoin, @@ -42,10 +46,6 @@ fn main() -> Result<()> { Network::Regtest }; - // Temporary. Will disappear once ESP-IDF 4.4 is released, but for now it is necessary to call this function once, - // or else some patches to the runtime implemented by esp-idf-sys might not link properly. - esp_idf_sys::link_patches(); - esp_idf_svc::log::EspLogger::initialize_default(); thread::sleep(Duration::from_secs(1)); diff --git a/sphinx-key/src/periph/led.rs b/sphinx-key/src/periph/led.rs index ca0bcd4..620dc5a 100644 --- a/sphinx-key/src/periph/led.rs +++ b/sphinx-key/src/periph/led.rs @@ -1,5 +1,4 @@ use crate::core::events::Status; -use core::time::Duration; use embedded_hal::delay::blocking::DelayUs; use esp_idf_hal::delay::Ets; use esp_idf_hal::gpio::Gpio8; @@ -8,6 +7,7 @@ use esp_idf_hal::rmt::config::TransmitConfig; use esp_idf_hal::rmt::{FixedLengthSignal, PinState, Pulse, Transmit}; use std::sync::mpsc; use std::thread; +use std::time::Duration; use std::sync::{LazyLock, Mutex}; @@ -26,8 +26,15 @@ pub struct Led { pub fn led_control_loop(rx: mpsc::Receiver) { thread::spawn(move || { - while let Ok(status) = rx.recv() { - log::info!("LED STATUS: {:?}", status); + let mut state: Status = Status::Starting; + // each iteration: check if theres a new status, and change the color if so + // if not, continue the current status blink color/time + loop { + if let Ok(status) = rx.try_recv() { + log::info!("LED STATUS: {:?}", status); + state = status; + } + thread::sleep(Duration::from_millis(100)); } }); } From cfcdf928741b5ebb04a5b8cfe049f95113a793c2 Mon Sep 17 00:00:00 2001 From: Evan Feenstra Date: Wed, 22 Jun 2022 22:55:24 -0700 Subject: [PATCH 3/5] status state machine --- sphinx-key/src/core/events.rs | 10 ++++----- sphinx-key/src/periph/led.rs | 38 +++++++++++++++++++++++++++-------- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/sphinx-key/src/core/events.rs b/sphinx-key/src/core/events.rs index 77f2208..aa8ce09 100644 --- a/sphinx-key/src/core/events.rs +++ b/sphinx-key/src/core/events.rs @@ -18,15 +18,15 @@ pub enum Event { Message(Vec), } -#[derive(Debug)] +#[derive(Debug, Ord, PartialOrd, Eq, PartialEq)] pub enum Status { Starting, WifiAccessPoint, - WifiAccessPointClientConnected, + Configuring, ConnectingToWifi, ConnectingToMqtt, Connected, - MessageReceived, + Signing, } // the main event loop @@ -76,7 +76,7 @@ pub fn make_event_loop( led_tx.send(Status::Connected).unwrap(); } Event::Message(ref msg_bytes) => { - led_tx.send(Status::MessageReceived).unwrap(); + led_tx.send(Status::Signing).unwrap(); let _ret = match sphinx_key_signer::handle( &root_handler, msg_bytes.clone(), @@ -117,7 +117,7 @@ pub fn make_event_loop( .expect("could not MQTT subscribe"); } Event::Message(msg_bytes) => { - led_tx.send(Status::MessageReceived).unwrap(); + led_tx.send(Status::Signing).unwrap(); let b = sphinx_key_signer::parse_ping_and_form_response(msg_bytes); if do_log { log::info!("GOT A PING MESSAGE! returning pong now..."); diff --git a/sphinx-key/src/periph/led.rs b/sphinx-key/src/periph/led.rs index 620dc5a..550ba3c 100644 --- a/sphinx-key/src/periph/led.rs +++ b/sphinx-key/src/periph/led.rs @@ -8,6 +8,7 @@ use esp_idf_hal::rmt::{FixedLengthSignal, PinState, Pulse, Transmit}; use std::sync::mpsc; use std::thread; use std::time::Duration; +use std::collections::BTreeMap; use std::sync::{LazyLock, Mutex}; @@ -19,34 +20,55 @@ static TX: LazyLock, esp_idf_hal Mutex::new(Transmit::new(led, channel, &config).unwrap()) }); +type Color = u32; +type Time = u32; + pub struct Led { - brg: u32, - blink_length: u32, + brg: Color, + blink_length: Time, +} + +fn states() -> BTreeMap { + let mut s = BTreeMap::new(); + s.insert(Status::Starting, (0x000001, 100)); + s.insert(Status::WifiAccessPoint, (0x000100, 100)); + s.insert(Status::Configuring, (0x010000, 20)); + s.insert(Status::ConnectingToWifi, (0x010100, 350)); + s.insert(Status::ConnectingToMqtt, (0x010001, 100)); + s.insert(Status::Connected, (0x000101, 400)); + s.insert(Status::Signing, (0x111111, 100)); + s } pub fn led_control_loop(rx: mpsc::Receiver) { thread::spawn(move || { - let mut state: Status = Status::Starting; - // each iteration: check if theres a new status, and change the color if so - // if not, continue the current status blink color/time + let mut led = Led::new(0x000001, 100); loop { if let Ok(status) = rx.try_recv() { log::info!("LED STATUS: {:?}", status); - state = status; + if let Some(s) = states().get(&status) { + led.set(s.0, s.1); + } } - thread::sleep(Duration::from_millis(100)); + led.blink(); + thread::sleep(Duration::from_millis(400)); } }); } impl Led { - pub fn new(rgb: u32, blink_length: u32) -> Led { + pub fn new(rgb: Color, blink_length: Time) -> Led { Led { brg: rotate_rgb(rgb), blink_length, } } + pub fn set(&mut self, rgb: Color, blink_length: Time) { + self.brg = rotate_rgb(rgb); + self.blink_length = blink_length; + } + pub fn blink(&mut self) { let mut tx = TX.lock().unwrap(); // Prepare signal From 3e498f7195dd75daa28926059214fbe97a280105 Mon Sep 17 00:00:00 2001 From: Evan Feenstra Date: Thu, 23 Jun 2022 08:56:34 -0700 Subject: [PATCH 4/5] dont init the btreemap each loop iteration --- sphinx-key/src/periph/led.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sphinx-key/src/periph/led.rs b/sphinx-key/src/periph/led.rs index 550ba3c..1820b9a 100644 --- a/sphinx-key/src/periph/led.rs +++ b/sphinx-key/src/periph/led.rs @@ -43,12 +43,13 @@ fn states() -> BTreeMap { pub fn led_control_loop(rx: mpsc::Receiver) { thread::spawn(move || { let mut led = Led::new(0x000001, 100); + let states = states(); loop { if let Ok(status) = rx.try_recv() { log::info!("LED STATUS: {:?}", status); - if let Some(s) = states().get(&status) { + if let Some(s) = states.get(&status) { led.set(s.0, s.1); - } + } } led.blink(); thread::sleep(Duration::from_millis(400)); From 5a8d14770d518a8a3c7690052397edbfd862852d Mon Sep 17 00:00:00 2001 From: Evan Feenstra Date: Tue, 28 Jun 2022 17:56:32 -0700 Subject: [PATCH 5/5] pass in peripherals to led control loop, no synclazy --- sphinx-key/src/main.rs | 15 +++++++++++---- sphinx-key/src/periph/led.rs | 36 ++++++++++++++++-------------------- sphinx-key/src/periph/mod.rs | 1 + sphinx-key/src/periph/sd.rs | 6 ++++++ 4 files changed, 34 insertions(+), 24 deletions(-) create mode 100644 sphinx-key/src/periph/sd.rs diff --git a/sphinx-key/src/main.rs b/sphinx-key/src/main.rs index fc69875..3f5e11f 100644 --- a/sphinx-key/src/main.rs +++ b/sphinx-key/src/main.rs @@ -4,7 +4,8 @@ mod core; mod periph; use crate::core::{events::*, config::*}; -use crate::periph::led::{Led, led_control_loop}; +use crate::periph::led::led_control_loop; +use crate::periph::sd::sd_card; use esp_idf_sys as _; // If using the `binstart` feature of `esp-idf-sys`, always keep this module imported use std::thread; @@ -15,7 +16,7 @@ use anyhow::Result; use esp_idf_svc::nvs::*; use esp_idf_svc::nvs_storage::EspNvsStorage; use embedded_svc::storage::Storage; -use embedded_svc::wifi::Wifi; +use esp_idf_hal::peripherals::Peripherals; use sphinx_key_signer::lightning_signer::bitcoin::Network; @@ -51,9 +52,15 @@ fn main() -> Result<()> { thread::sleep(Duration::from_secs(1)); log::info!("Network set to {:?}", network); + let peripherals = Peripherals::take().unwrap(); + let pins = peripherals.pins; + let (led_tx, led_rx) = mpsc::channel(); // LED control thread - led_control_loop(led_rx); + led_control_loop(pins.gpio8, peripherals.rmt.channel0, led_rx); + + // sd card + sd_card(peripherals.spi2); let default_nvs = Arc::new(EspDefaultNvs::new()?); let mut store = EspNvsStorage::new_default(default_nvs.clone(), "sphinx", true).expect("no storage"); @@ -62,7 +69,7 @@ fn main() -> Result<()> { println!("=============> START CLIENT NOW <============== {:?}", exist); // store.remove("config").expect("couldnt remove config"); led_tx.send(Status::ConnectingToWifi).unwrap(); - let wifi = start_wifi_client(default_nvs.clone(), &exist)?; + let _wifi = start_wifi_client(default_nvs.clone(), &exist)?; let (tx, rx) = mpsc::channel(); diff --git a/sphinx-key/src/periph/led.rs b/sphinx-key/src/periph/led.rs index 1820b9a..8b25c00 100644 --- a/sphinx-key/src/periph/led.rs +++ b/sphinx-key/src/periph/led.rs @@ -1,25 +1,14 @@ use crate::core::events::Status; use embedded_hal::delay::blocking::DelayUs; use esp_idf_hal::delay::Ets; -use esp_idf_hal::gpio::Gpio8; -use esp_idf_hal::peripherals::Peripherals; +use esp_idf_hal::{gpio, rmt}; use esp_idf_hal::rmt::config::TransmitConfig; use esp_idf_hal::rmt::{FixedLengthSignal, PinState, Pulse, Transmit}; -use std::sync::mpsc; +use std::sync::{mpsc, Arc, Mutex}; use std::thread; use std::time::Duration; use std::collections::BTreeMap; -use std::sync::{LazyLock, Mutex}; - -static TX: LazyLock, esp_idf_hal::rmt::CHANNEL0>>> = LazyLock::new(|| { - let peripherals = Peripherals::take().unwrap(); - let led = peripherals.pins.gpio8.into_output().unwrap(); - let channel = peripherals.rmt.channel0; - let config = TransmitConfig::new().clock_divider(1); - Mutex::new(Transmit::new(led, channel, &config).unwrap()) -}); - type Color = u32; type Time = u32; @@ -40,7 +29,14 @@ fn states() -> BTreeMap { s } -pub fn led_control_loop(rx: mpsc::Receiver) { +pub fn led_control_loop( + gpio8: gpio::Gpio8, + channel0: rmt::CHANNEL0, + rx: mpsc::Receiver +) { + let led = gpio8.into_output().unwrap(); + let config = TransmitConfig::new().clock_divider(1); + let transmit = Arc::new(Mutex::new(Transmit::new(led, channel0, &config).unwrap())); thread::spawn(move || { let mut led = Led::new(0x000001, 100); let states = states(); @@ -51,7 +47,7 @@ pub fn led_control_loop(rx: mpsc::Receiver) { led.set(s.0, s.1); } } - led.blink(); + led.blink(transmit.clone()); thread::sleep(Duration::from_millis(400)); } }); @@ -70,10 +66,10 @@ impl Led { self.blink_length = blink_length; } - pub fn blink(&mut self) { - let mut tx = TX.lock().unwrap(); + pub fn blink(&mut self, transmit: Arc, rmt::CHANNEL0>>>) { // Prepare signal - let ticks_hz = (*tx).counter_clock().unwrap(); + let mut tx = transmit.lock().unwrap(); + let ticks_hz = tx.counter_clock().unwrap(); let t0h = Pulse::new_with_duration(ticks_hz, PinState::High, &ns(350)).unwrap(); let t0l = Pulse::new_with_duration(ticks_hz, PinState::Low, &ns(800)).unwrap(); let t1h = Pulse::new_with_duration(ticks_hz, PinState::High, &ns(700)).unwrap(); @@ -86,7 +82,7 @@ impl Led { signal.set(i as usize, &(high_pulse, low_pulse)).unwrap(); } // Set high and wait - (*tx).start_blocking(&signal).unwrap(); + tx.start_blocking(&signal).unwrap(); Ets.delay_ms(self.blink_length).unwrap(); // Set low let mut signal = FixedLengthSignal::<24>::new(); @@ -95,7 +91,7 @@ impl Led { let (high_pulse, low_pulse) = if bit { (t1h, t1l) } else { (t0h, t0l) }; signal.set(i as usize, &(high_pulse, low_pulse)).unwrap(); } - (*tx).start_blocking(&signal).unwrap(); + tx.start_blocking(&signal).unwrap(); } } diff --git a/sphinx-key/src/periph/mod.rs b/sphinx-key/src/periph/mod.rs index 157af18..aaf195a 100644 --- a/sphinx-key/src/periph/mod.rs +++ b/sphinx-key/src/periph/mod.rs @@ -1 +1,2 @@ pub mod led; +pub mod sd; \ No newline at end of file diff --git a/sphinx-key/src/periph/sd.rs b/sphinx-key/src/periph/sd.rs new file mode 100644 index 0000000..6067fcc --- /dev/null +++ b/sphinx-key/src/periph/sd.rs @@ -0,0 +1,6 @@ + +use esp_idf_hal::spi; + +pub fn sd_card(_spi: spi::SPI2) { + log::info!("sd_card"); +} \ No newline at end of file