Skip to content

Commit

Permalink
Pass Wifi to UI and wait for network to come up
Browse files Browse the repository at this point in the history
  • Loading branch information
zargony committed Sep 24, 2024
1 parent a5f5a9b commit 3dd6ea2
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 5 deletions.
2 changes: 1 addition & 1 deletion firmware/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ git2 = { version = "0.19", default-features = false }
[dependencies]
display-interface = "0.5"
embassy-embedded-hal = "0.2"
embassy-executor = { version = "0.6", features = ["task-arena-size-6144"] }
embassy-executor = { version = "0.6", features = ["task-arena-size-20480"] }
embassy-futures = "0.1"
embassy-net = { version = "0.4", features = ["dhcpv4", "dns", "proto-ipv4", "tcp"] }
embassy-sync = "0.6"
Expand Down
7 changes: 5 additions & 2 deletions firmware/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ async fn main(spawner: Spawner) {

// Initialize Wifi
let timg0 = TimerGroup::new(peripherals.TIMG0, &clocks);
let _wifi = match wifi::Wifi::new(
let wifi = match wifi::Wifi::new(
timg0.timer0,
rng,
peripherals.RADIO_CLK,
Expand All @@ -175,11 +175,14 @@ async fn main(spawner: Spawner) {
let _ = buzzer.startup().await;

// Create UI
let mut ui = ui::Ui::new(display, keypad, nfc, buzzer);
let mut ui = ui::Ui::new(display, keypad, nfc, buzzer, wifi);

// Show splash screen for a while, ignore any error
let _ = ui.show_splash_screen().await;

// Wait for network to become available (if not already), ignore any error
let _ = ui.wait_network_up().await;

loop {
match ui.run().await {
// Success: start over again
Expand Down
29 changes: 29 additions & 0 deletions firmware/src/screen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,35 @@ impl Screen for Splash {
}
}

/// Wait for network to become available
pub struct WifiConnecting;

impl Screen for WifiConnecting {
fn draw<D: DrawTarget<Color = BinaryColor>>(
&self,
target: &mut D,
) -> Result<(), Error<D::Error>> {
TITLE_FONT.render_aligned(
"Stand By...",
Point::new(63, 26),
VerticalPosition::Baseline,
HorizontalAlignment::Center,
FontColor::Transparent(BinaryColor::On),
target,
)?;
SMALL_FONT.render_aligned(
"WLAN Verbindung\nwird aufgebaut",
Point::new(63, 27 + 12),
VerticalPosition::Baseline,
HorizontalAlignment::Center,
FontColor::Transparent(BinaryColor::On),
target,
)?;
Footer::new("* Abbruch", "").draw(target)?;
Ok(())
}
}

/// Prompt to scan id card
pub struct ScanId;

Expand Down
31 changes: 31 additions & 0 deletions firmware/src/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::display::{self, Display};
use crate::keypad::{Key, Keypad};
use crate::nfc::{self, Nfc, Uid};
use crate::screen;
use crate::wifi::Wifi;
use core::convert::Infallible;
use embassy_futures::select::{select, Either};
use embassy_time::{with_timeout, Duration, TimeoutError};
Expand All @@ -16,6 +17,9 @@ const PRICE: f32 = 1.0;
/// How long to show the splash screen if no key is pressed
const SPLASH_TIMEOUT: Duration = Duration::from_secs(5);

/// How long to wait for network to become available
const NETWORK_TIMEOUT: Duration = Duration::from_secs(30);

/// Timeout for user input. Actions are cancelled if the user does nothing for this duration.
#[cfg(not(debug_assertions))]
const USER_TIMEOUT: Duration = Duration::from_secs(60);
Expand Down Expand Up @@ -43,6 +47,8 @@ pub enum Error {
Cancel,
/// User interaction timeout
UserTimeout,
/// No network connection
NoNetwork,
}

impl From<display::Error> for Error {
Expand All @@ -69,6 +75,7 @@ pub struct Ui<'a, I2C, IRQ> {
keypad: Keypad<'a, 3, 4>,
nfc: Nfc<I2C, IRQ>,
buzzer: Buzzer<'a>,
wifi: Wifi,
}

impl<'a, I2C: I2c, IRQ: Wait<Error = Infallible>> Ui<'a, I2C, IRQ> {
Expand All @@ -78,12 +85,14 @@ impl<'a, I2C: I2c, IRQ: Wait<Error = Infallible>> Ui<'a, I2C, IRQ> {
keypad: Keypad<'a, 3, 4>,
nfc: Nfc<I2C, IRQ>,
buzzer: Buzzer<'a>,
wifi: Wifi,
) -> Self {
Self {
display,
keypad,
nfc,
buzzer,
wifi,
}
}

Expand All @@ -102,6 +111,26 @@ impl<'a, I2C: I2c, IRQ: Wait<Error = Infallible>> Ui<'a, I2C, IRQ> {
Ok(())
}

/// Wait for network to become available (if not already). Show a waiting screen and allow to
/// cancel
pub async fn wait_network_up(&mut self) -> Result<(), Error> {
if self.wifi.is_up() {
return Ok(());
}

self.display.screen(&screen::WifiConnecting).await?;

let wait_cancel = async { while self.keypad.read().await != Key::Cancel {} };
match with_timeout(NETWORK_TIMEOUT, select(self.wifi.wait_up(), wait_cancel)).await {
// Network has become available
Ok(Either::First(())) => Ok(()),
// Cancel key cancels
Ok(Either::Second(())) => Err(Error::Cancel),
// Timeout waiting for network
Err(TimeoutError) => Err(Error::NoNetwork),
}
}

/// Run the user interface flow
pub async fn run(&mut self) -> Result<(), Error> {
// Wait for id card and verify identification
Expand All @@ -113,6 +142,8 @@ impl<'a, I2C: I2c, IRQ: Wait<Error = Infallible>> Ui<'a, I2C, IRQ> {
let total_price = PRICE * num_drinks as f32;
// Show total price and ask for confirmation
self.confirm_purchase(num_drinks, total_price).await?;
// Wait for network to become available (if not already)
self.wait_network_up().await?;

// TODO: Process payment
let _ = screen::Success::new(num_drinks);
Expand Down
8 changes: 6 additions & 2 deletions firmware/src/wifi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,14 @@ impl Wifi {
Ok(Self { stack })
}

/// Returns whether network stack is up (Wifi connected and IP address obtained)
pub fn is_up(&self) -> bool {
self.stack.is_link_up() && self.stack.is_config_up()
}

/// Wait for network stack to come up (Wifi connected and IP address obtained)
#[allow(dead_code)]
pub async fn wait_up(&self) {
if self.stack.is_link_up() && self.stack.is_config_up() {
if self.is_up() {
return;
}

Expand Down

0 comments on commit 3dd6ea2

Please sign in to comment.