Merge pull request #41 from stakwork/feat/leds

Feat/leds
This commit is contained in:
Evan Feenstra
2022-06-29 09:20:36 -07:00
committed by GitHub
5 changed files with 108 additions and 36 deletions

View File

@@ -18,12 +18,25 @@ pub enum Event {
Message(Vec<u8>),
}
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq)]
pub enum Status {
Starting,
WifiAccessPoint,
Configuring,
ConnectingToWifi,
ConnectingToMqtt,
Connected,
Signing,
}
// the main event loop
#[cfg(not(feature = "pingpong"))]
pub fn make_event_loop(
mut mqtt: EspMqttClient<ConnState<MessageImpl, EspError>>,
rx: mpsc::Receiver<Event>,
network: Network,
do_log: bool,
led_tx: mpsc::Sender<Status>
) -> Result<()> {
// initialize the RootHandler
let root_handler = loop {
@@ -33,6 +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::Connected).unwrap();
}
Event::Message(ref msg_bytes) => {
let InitResponse {
@@ -44,6 +58,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 +73,10 @@ pub fn make_event_loop(
log::info!("SUBSCRIBE TO {}", TOPIC);
mqtt.subscribe(TOPIC, QOS)
.expect("could not MQTT subscribe");
led_tx.send(Status::Connected).unwrap();
}
Event::Message(ref msg_bytes) => {
led_tx.send(Status::Signing).unwrap();
let _ret = match sphinx_key_signer::handle(
&root_handler,
msg_bytes.clone(),
@@ -73,6 +90,7 @@ pub fn make_event_loop(
};
}
Event::Disconnected => {
led_tx.send(Status::ConnectingToMqtt).unwrap();
log::info!("GOT A Event::Disconnected msg!");
}
}
@@ -87,16 +105,19 @@ pub fn make_event_loop(
rx: mpsc::Receiver<Event>,
_network: Network,
do_log: bool,
led_tx: mpsc::Sender<Status>
) -> 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::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...");
@@ -105,6 +126,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!");
}
}

View File

@@ -4,7 +4,8 @@ mod core;
mod periph;
use crate::core::{events::*, config::*};
use crate::periph::led::Led;
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;
@@ -29,6 +30,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,25 +47,33 @@ 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));
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(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");
let existing: Option<Config> = store.get("config").expect("failed");
if let Some(exist) = existing {
println!("=============> START CLIENT NOW <============== {:?}", exist);
// store.remove("config").expect("couldnt remove config");
let wifi = start_wifi_client(default_nvs.clone(), &exist)?;
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)?;
@@ -68,17 +81,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");

View File

@@ -1,38 +1,75 @@
use core::time::Duration;
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, Arc, Mutex};
use std::thread;
use std::time::Duration;
use std::collections::BTreeMap;
use std::sync::{LazyLock, Mutex};
static TX: LazyLock<Mutex<Transmit<Gpio8<esp_idf_hal::gpio::Output>, 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;
pub struct Led {
brg: u32,
blink_length: u32,
brg: Color,
blink_length: Time,
}
fn states() -> BTreeMap<Status, (Color, Time)> {
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(
gpio8: gpio::Gpio8<gpio::Unknown>,
channel0: rmt::CHANNEL0,
rx: mpsc::Receiver<Status>
) {
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();
loop {
if let Ok(status) = rx.try_recv() {
log::info!("LED STATUS: {:?}", status);
if let Some(s) = states.get(&status) {
led.set(s.0, s.1);
}
}
led.blink(transmit.clone());
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 blink(&mut self) {
let mut tx = TX.lock().unwrap();
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, transmit: Arc<Mutex<Transmit<gpio::Gpio8<gpio::Output>, 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();
@@ -45,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();
@@ -54,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();
}
}

View File

@@ -1 +1,2 @@
pub mod led;
pub mod sd;

View File

@@ -0,0 +1,6 @@
use esp_idf_hal::spi;
pub fn sd_card(_spi: spi::SPI2) {
log::info!("sd_card");
}