Compare commits

...

4 commits

Author SHA1 Message Date
e2a28d43f0
added admin panel 2024-12-07 01:15:08 -05:00
20fdd480dd
frontend 2024-12-06 01:20:30 -05:00
1b140607d7
log badges to disk 2024-12-05 21:47:47 -05:00
0d5fb05abe
set badge names from desktop client 2024-12-05 20:50:52 -05:00
9 changed files with 863 additions and 54 deletions

View file

@ -2,14 +2,15 @@
use serde::Deserialize;
use serde::Serialize;
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Debug)]
pub enum Request {
RecentBadge,
SetRecentBadge(Name),
SetBadge(Name, u64),
SetVolume(u8),
}
#[derive(Clone, Copy, Serialize, Deserialize)]
#[derive(Clone, Copy, Serialize, Deserialize, Debug)]
#[repr(u8)]
pub enum Name {
Andy,

View file

@ -1,4 +1,5 @@
/// no_std, no_alloc map
#[derive(Debug)]
pub struct ArrayMap<const N: usize, K,V> {
keys: [Option<K>; N],
values: [Option<V>; N],

View file

@ -1,5 +1,5 @@
use crate::music::{MusicCommand, COMMANDS};
use crate::server::NAMES;
use crate::server::{LAST_BADGE, NAMES};
use common::Name;
use embassy_net::{IpEndpoint, Ipv4Address};
@ -27,6 +27,8 @@ impl Authorized for Name {
Name::Andy => true,
Name::Evan => true,
Name::Michael => true,
Name::Felix => true,
Name::Phil => true,
_ => false,
}
}
@ -50,11 +52,12 @@ pub async fn send_badge(channel: Receiver<'static,CriticalSectionRawMutex,u64,1>
loop {
let card = channel.receive().await;
*LAST_BADGE.lock().await.borrow_mut() = card;
let name = Name::from_badge(card).await;
COMMANDS.send(MusicCommand::Introduce(name, name.authorized())).await;
// this is also checked on the backend (TODO)
if !name.authorized() {
COMMANDS.send(MusicCommand::Introduce(name, name.authorized())).await;
continue;
}
@ -85,5 +88,7 @@ pub async fn send_badge(channel: Receiver<'static,CriticalSectionRawMutex,u64,1>
socket.close();
info!("disconnected");
COMMANDS.send(MusicCommand::Introduce(name, name.authorized())).await;
}
}

View file

@ -152,7 +152,7 @@ async fn button_manager(pin: PIN_22) -> ! {
let mut button = Input::new(pin, embassy_rp::gpio::Pull::Up);
loop {
button.wait_for_rising_edge().await;
COMMANDS.send(music::MusicCommand::Play("d5")).await; // TODO: record
COMMANDS.send(music::MusicCommand::Play("a1")).await; // TODO: record
Timer::after_millis(800).await;
}
}

View file

@ -157,7 +157,7 @@ async fn play_song<'a>(prefix: &str, index: Option<u8>, uart: &mut BufferedUart<
let output = read_line(&mut buffer, uart).await;
if let Ok(length) = output.trim().parse::<u64>() {
WAGS.store(length as u8, core::sync::atomic::Ordering::SeqCst);
WAGS.store((length as u8) * 2 + 1, core::sync::atomic::Ordering::SeqCst);
Timer::after_secs(length).await;
}
}

View file

@ -14,6 +14,9 @@ use crate::{arraymap::ArrayMap, music::{COMMANDS}, scanner::READ_CARD};
pub static NAMES: Mutex<CriticalSectionRawMutex, RefCell<ArrayMap<64, u64, Name>>> =
Mutex::new(RefCell::new(ArrayMap::new()));
pub static LAST_BADGE: Mutex<CriticalSectionRawMutex, RefCell<u64>> =
Mutex::new(RefCell::new(0));
#[embassy_executor::task]
pub async fn server_task(stack: embassy_net::Stack<'static>) {
let mut rx_buffer = [0; 4096];
@ -44,52 +47,33 @@ pub async fn server_task(stack: embassy_net::Stack<'static>) {
}
};
info!("rxd: {:?}", from_bytes::<Request>(&buf[..n]));
match from_bytes::<Request>(&buf[..n]) {
Ok(Request::RecentBadge) => {
let card = critical_section::with(|cs| {
READ_CARD.borrow(cs).clone().into_inner()
});
let lock = LAST_BADGE.lock().await;
let mut borrow_mut = lock.borrow_mut();
let card = borrow_mut.clone();
*borrow_mut = 0;
socket.write_all(itoa::Buffer::new().format(card).as_bytes()).await.unwrap();
socket.write_all(&card.to_be_bytes()).await.unwrap();
socket.flush().await.unwrap();
},
Ok(Request::SetRecentBadge(name)) => {
let card = critical_section::with(|cs| {
READ_CARD.borrow(cs).clone().into_inner()
});
let card = LAST_BADGE.lock().await.borrow().clone();
NAMES.lock().await.borrow_mut().insert(card, name);
info!("names: {:?}", NAMES.lock().await.borrow());
}
Ok(Request::SetBadge(name, card)) => {
info!("setting {name:?} to {card}");
NAMES.lock().await.borrow_mut().insert(card, name);
}
Ok(Request::SetVolume(vol)) => {
COMMANDS.send(crate::music::MusicCommand::SetVolume(vol)).await;
}
Err(e) => { info!("parse error: {e}") }
}
info!("rxd {}", from_utf8(&buf[..n]).unwrap());
/*let mut segs = buf[..n].trim_ascii().split(|c| *c == ' ' as u8);
match char::from_u32(segs.next().unwrap()[0] as u32).unwrap() {
'B' => {
let card = critical_section::with(|cs| {
READ_CARD.borrow(cs).clone().into_inner()
});
socket.write_all(itoa::Buffer::new().format(card).as_bytes()).await.unwrap();
},
'R' => {
let card = critical_section::with(|cs| {
READ_CARD.borrow(cs).clone().into_inner()
});
NAMES.lock().await.borrow_mut().insert(card, Name::Unknown);
},
_ => {}
}
*/
}
}
}

553
server/Cargo.lock generated
View file

@ -23,6 +23,17 @@ version = "1.0.94"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7"
[[package]]
name = "async-trait"
version = "0.1.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "atomic-polyfill"
version = "1.0.3"
@ -38,6 +49,61 @@ version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "axum"
version = "0.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f"
dependencies = [
"async-trait",
"axum-core",
"bytes",
"futures-util",
"http",
"http-body",
"http-body-util",
"hyper",
"hyper-util",
"itoa",
"matchit",
"memchr",
"mime",
"percent-encoding",
"pin-project-lite",
"rustversion",
"serde",
"serde_json",
"serde_path_to_error",
"serde_urlencoded",
"sync_wrapper 1.0.2",
"tokio",
"tower",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "axum-core"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199"
dependencies = [
"async-trait",
"bytes",
"futures-util",
"http",
"http-body",
"http-body-util",
"mime",
"pin-project-lite",
"rustversion",
"sync_wrapper 1.0.2",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "backtrace"
version = "0.3.74"
@ -96,6 +162,30 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
[[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-utils"
version = "0.8.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
[[package]]
name = "deranged"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
dependencies = [
"powerfmt",
]
[[package]]
name = "embedded-io"
version = "0.4.0"
@ -108,6 +198,54 @@ version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d"
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[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 = "futures-channel"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
dependencies = [
"futures-core",
]
[[package]]
name = "futures-core"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
[[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 = "gimli"
version = "0.31.1"
@ -137,6 +275,99 @@ dependencies = [
"stable_deref_trait",
]
[[package]]
name = "http"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea"
dependencies = [
"bytes",
"fnv",
"itoa",
]
[[package]]
name = "http-body"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
dependencies = [
"bytes",
"http",
]
[[package]]
name = "http-body-util"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f"
dependencies = [
"bytes",
"futures-util",
"http",
"http-body",
"pin-project-lite",
]
[[package]]
name = "httparse"
version = "1.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946"
[[package]]
name = "httpdate"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "hyper"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97818827ef4f364230e16705d4706e2897df2bb60617d6ca15d598025a3c481f"
dependencies = [
"bytes",
"futures-channel",
"futures-util",
"http",
"http-body",
"httparse",
"httpdate",
"itoa",
"pin-project-lite",
"smallvec",
"tokio",
]
[[package]]
name = "hyper-util"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4"
dependencies = [
"bytes",
"futures-util",
"http",
"http-body",
"hyper",
"pin-project-lite",
"tokio",
"tower-service",
]
[[package]]
name = "itoa"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
[[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.167"
@ -153,12 +384,30 @@ dependencies = [
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "matchit"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "mime"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "miniz_oxide"
version = "0.8.0"
@ -179,6 +428,22 @@ dependencies = [
"windows-sys",
]
[[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-conv"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
[[package]]
name = "object"
version = "0.36.5"
@ -188,6 +453,18 @@ dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
version = "1.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
[[package]]
name = "overload"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]]
name = "parking_lot"
version = "0.12.3"
@ -211,12 +488,24 @@ dependencies = [
"windows-targets",
]
[[package]]
name = "percent-encoding"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "pin-project-lite"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff"
[[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.1.1"
@ -230,6 +519,12 @@ dependencies = [
"serde",
]
[[package]]
name = "powerfmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]]
name = "proc-macro2"
version = "1.0.92"
@ -272,6 +567,18 @@ dependencies = [
"semver",
]
[[package]]
name = "rustversion"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248"
[[package]]
name = "ryu"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]]
name = "scopeguard"
version = "1.2.0"
@ -304,15 +611,62 @@ dependencies = [
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.133"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377"
dependencies = [
"itoa",
"memchr",
"ryu",
"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",
"serde",
]
[[package]]
name = "serde_urlencoded"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
dependencies = [
"form_urlencoded",
"itoa",
"ryu",
"serde",
]
[[package]]
name = "server"
version = "0.1.0"
dependencies = [
"anyhow",
"axum",
"common",
"postcard",
"serde",
"tokio",
"tracing",
"tracing-appender",
"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]]
@ -366,6 +720,79 @@ dependencies = [
"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"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
[[package]]
name = "thiserror"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
dependencies = [
"thiserror-impl",
]
[[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",
]
[[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 = "time"
version = "0.3.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21"
dependencies = [
"deranged",
"itoa",
"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.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de"
dependencies = [
"num-conv",
"time-core",
]
[[package]]
name = "tokio"
version = "1.42.0"
@ -395,18 +822,144 @@ dependencies = [
"syn",
]
[[package]]
name = "tower"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f"
dependencies = [
"futures-core",
"futures-util",
"pin-project-lite",
"sync_wrapper 0.1.2",
"tokio",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "tower-layer"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e"
[[package]]
name = "tower-service"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
[[package]]
name = "tracing"
version = "0.1.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
dependencies = [
"log",
"pin-project-lite",
"tracing-attributes",
"tracing-core",
]
[[package]]
name = "tracing-appender"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf"
dependencies = [
"crossbeam-channel",
"thiserror",
"time",
"tracing-subscriber",
]
[[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",
]
[[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-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 = [
"nu-ansi-term",
"sharded-slab",
"smallvec",
"thread_local",
"tracing-core",
"tracing-log",
]
[[package]]
name = "unicode-ident"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
[[package]]
name = "valuable"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[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.52.0"

View file

@ -5,7 +5,11 @@ edition = "2021"
[dependencies]
anyhow = "1.0.94"
axum = "0.7.9"
common = {path = "../common"}
postcard = {version = "1.0.0", features = ["alloc"]}
serde = "*"
tokio = { version = "1.42.0", features = ["full"] }
tracing = "0.1.41"
tracing-appender = "0.2.3"
tracing-subscriber = "0.3.19"

View file

@ -1,27 +1,288 @@
use common::Request;
use postcard::{to_allocvec, to_vec};
use tokio::{io::{AsyncReadExt, AsyncWriteExt}, net::TcpStream};
use anyhow::Result;
use std::{sync::Arc, time::Duration};
use axum::{extract::State, http::StatusCode, response::Html, routing::{get, post}, serve, Form, Router};
use common::{Name, Request};
use postcard::to_allocvec;
use tokio::{fs, io::{AsyncReadExt, AsyncWriteExt}, net::TcpStream, sync::{RwLock, Semaphore}, time::{self, sleep, Instant}};
use anyhow::{Ok, Result};
use tracing::{error, info, trace, Level};
use tracing_subscriber::{filter, layer::{Filter, SubscriberExt}, util::SubscriberInitExt, Layer};
const FISH: &'static str = "169.254.2.1:1234";
const DOOR: &'static str = "169.254.1.1:1234";
#[derive(Clone)]
struct AppState {
fish: Arc<Semaphore>,
last_badge: Arc<RwLock<(u64,Instant)>>,
}
#[tokio::main]
async fn main() -> Result<()>{
println!("Hello, world!");
let mut conn = TcpStream::connect("169.254.2.1:1234").await?;
let log = fs::OpenOptions::new().append(true).create(true).open("john.log").await?;
let (non_blocking, _guard) = tracing_appender::non_blocking(log.into_std().await);
let filter = filter::Targets::new()
.with_target("server", Level::INFO);
let stdout = tracing_subscriber::fmt::layer()
.compact()
.with_file(true)
.with_target(true);
let log = tracing_subscriber::fmt::layer()
.compact()
.with_file(false)
.with_target(true)
.with_writer(non_blocking)
.with_filter(filter);
let reg = tracing_subscriber::registry()
.with(stdout)
.with(log);
reg.try_init()?;
let fish = Arc::new(Semaphore::new(1));
let last_badge = Arc::new(RwLock::new((0u64,Instant::now())));
info!("starting");
let app: Router = Router::new()
.route("/names", get(root))
.route("/admin", get(control))
.route("/phil", get(phil))
.route("/recent", get(recent_badge))
.route("/setLast", post(set_last))
.route("/openDoor", post(open_door))
.route("/setVolume", post(set_volume))
//.route("/map", post(set_badge))
.with_state(AppState {
fish: fish.clone(),
last_badge: last_badge.clone()
});
let listener = tokio::net::TcpListener::bind("0.0.0.0:8080").await.unwrap();
tokio::spawn(async {serve(listener, app).await.unwrap()});
let fish_ = fish.clone();
tokio::spawn(async move {
loop {
match get_recent_badge(fish_.clone()).await {
Result::Ok(badge) => {
*last_badge.write().await = (badge, Instant::now());
},
Err(e) => {
trace!("badge read fail: {e}");
}
}
sleep(Duration::from_secs(1)).await;
}
});
/*{
let _permit = fish.acquire().await?;
let mut conn = TcpStream::connect(FISH).await?;
let req = Request::RecentBadge;
conn.write_all(&to_allocvec(&req)?).await?;
conn.flush().await?;
let badge = conn.read_u64().await?;
info!("read: {badge}");
if badge != 0 {
let req = Request::SetBadge(common::Name::Evan, badge);
conn.write_all(&to_allocvec(&req)?).await?;
conn.flush().await?;
}
let req = Request::SetVolume(30);
conn.write_all(&to_allocvec(&req)?).await?;
}*/
loop {
sleep(Duration::from_secs(2)).await;
}
}
async fn get_recent_badge(fish: Arc<Semaphore>) -> Result<u64> {
let _permit = fish.acquire().await?;
let mut conn = TcpStream::connect(FISH).await?;
let req = Request::RecentBadge;
conn.write_all(&to_allocvec(&req)?).await?;
let req = Request::SetVolume(23);
println!("{:?}", to_allocvec(&req).unwrap());
conn.write_all(&to_allocvec(&req)?).await?;
conn.flush().await?;
let mut buf = String::new();
conn.read_to_string(&mut buf).await?;
println!("recv: {}", buf.trim());
let badge = conn.read_u64().await?;
Ok(())
if badge != 0 {
info!("new badge: {badge:#0x}");
Ok(badge)
} else {
Err(anyhow::anyhow!("no badge present"))
}
}
async fn root(state: State<AppState>) -> Html<String> {
let (last_badge, time) = *state.last_badge.read().await;
let time = time.elapsed();
let mut page = format!(r#"
<p>
most recent badge {last_badge:#0x}<br>
{time:?} ago
</p>
<h1>set last badge</h1>
"#);
for name in [
"Tess",
"Amaia",
"Prueky",
"David",
"Nathaniel",
"Thia",
"Michael",
"Zoey",
] {
page.push_str(&format!(r#"
<form target="output" style="display:inline; margin-right:10px; " action="setLast" method="post" id="myForm">
<button style="font-size:40px;" type="submit" name="name" value="{name}" target="output">{name}</button>
</form>
"#));
}
page.push_str(&format!(r#"
<form target="output" style="margin-top:10px;" action="setLast" method="post" id="myForm">
<input style="font-size:40px;" name="name" placeholder="other" "type="text"></input>
<button style="font-size:40px;" type="submit" target="output">other</button>
</form>
<iframe name="output"></iframe>
"#));
Html::from(page)
}
async fn control(state: State<AppState>) -> Html<String> {
let (last_badge, time) = *state.last_badge.read().await;
let time = time.elapsed();
let page = format!(r#"
<head><title>JOHNADMIN</title></head>
<h1>JOHN ADMIN PANEL</h1>
<form target="output" action="openDoor" method="post" id="myForm">
<button style="font-size:40px;" type="submit" name="name" value="open" target="output">Open noor</button>
</form>
<form target="output" action="setVolume" method="post" id="myForm">
<input type="range" min="0" max="30" value="0" name="volume" class="slider" id="volume">
<button style="font-size:30px;" type="submit" target="output">set volume</button>
</form>
<p>
most recent badge {last_badge:#0x}<br>
{time:?} ago
</p>
<iframe name="output"></iframe>
"#);
Html::from(page)
}
#[derive(serde::Deserialize)]
struct Volume {
volume: u8,
}
async fn open_door(state: State<AppState>) -> Html<&'static str> {
info!("opening door");
let mut conn = TcpStream::connect(DOOR).await.unwrap();
conn.write_all(b"B f7c31d1603000000 \r\n").await.unwrap();
conn.flush().await.unwrap();
Html::from("<p>opening the noor</p>")
}
async fn set_volume(
state: State<AppState>,
Form(input): Form<Volume>) -> Html<String> {
info!("setting volume to {}", input.volume);
let _fish = state.fish.acquire().await.unwrap();
let mut conn = TcpStream::connect(FISH).await.unwrap();
let req = Request::SetVolume(input.volume);
conn.write_all(&to_allocvec(&req).unwrap()).await.unwrap();
conn.flush().await.unwrap();
Html::from(format!("<p>volume is now {}</p></br><a href=\"/\">back</a>", input.volume))
}
#[derive(serde::Deserialize)]
struct NameForm {
name: String,
}
async fn set_last(
state: State<AppState>,
Form(input): Form<NameForm>) -> Html<String> {
let name_e = match input.name.as_str() {
"Tess" => Name::Tess,
"Amaia" => Name::Amaia,
"Prueky" => Name::Prueky,
"David" => Name::David,
"Nathaniel" => Name::Nathaniel,
"Thia" => Name::Thia,
"Michael" => Name::Michael,
"Zoey" => Name::Zoey,
_ => Name::Unknown,
};
let (last_badge, _) = *state.last_badge.read().await;
info!("setting {} ({name_e:?}) to {last_badge:#0x}", input.name);
let _fish = state.fish.acquire().await.unwrap();
let mut conn = TcpStream::connect(FISH).await.unwrap();
if last_badge == 0 {
return Html::from("<h1>failed, no badge scanned</h1>".to_string());
}
let req = Request::SetBadge(name_e, last_badge);
conn.write_all(&to_allocvec(&req).unwrap()).await.unwrap();
conn.flush().await.unwrap();
Html::from(format!("<p>{last_badge:#0x} is now {}</p></br><a href=\"/\">back</a>", input.name))
}
async fn recent_badge(state: State<AppState>) -> String {
let (last_badge, time) = *state.last_badge.read().await;
format!("id: {last_badge:#0x}, scanned {:?} ago", time.elapsed())
}
async fn phil(state: State<AppState>) -> String {
let _fish = state.fish.acquire().await.unwrap();
let (last_badge, time) = *state.last_badge.read().await;
info!("id: {last_badge:#0x}, scanned {:?} ago", time.elapsed());
let mut conn = TcpStream::connect(FISH).await.unwrap();
if last_badge != 0 {
let req = Request::SetBadge(common::Name::Phil, last_badge);
conn.write_all(&to_allocvec(&req).unwrap()).await.unwrap();
conn.flush().await.unwrap();
}
String::from(format!("{last_badge:#0x} is now phil"))
}