Compare commits

...

2 Commits

Author SHA1 Message Date
Martin Quarda
d7c5f0f048 POC in Rust get db from websocket 2025-05-10 19:59:24 +02:00
Martin Quarda
2a89528b8f POC in Rust remove authorization in /api/station/register 2025-05-10 17:56:17 +02:00
6 changed files with 73 additions and 26 deletions

View File

@ -4,6 +4,7 @@ version = "0.1.0"
edition = "2024"
[dependencies]
async-tungstenite = {version="0.29.1", features=["tokio-rustls-webpki-roots"]}
chrono = "0.4.41"
env_logger = "0.11.8"
futures-lite = "2.6.0"
@ -12,6 +13,7 @@ lazy_static = "1.5.0"
nusb = "0.1.13"
reqwest = { version = "0.12.15", features = ["json", "multipart", "http2", "cookies"] }
reqwest-middleware = "0.4.2"
rustls = "0.23.27"
serde = {version = "1.0.219", features=["derive"]}
serde_json = "1.0.140"
tokio = {version = "1.45.0", features=["time", "fs", "io-util", "macros"]}

View File

@ -3,6 +3,5 @@
"SAVING_INTERVAL": 60,
"STATION_ID": 2,
"HOST": "https://beta.alkator.cz",
"LOGIN": "station_register@alkator.cz",
"PASSWORD": "password_heslo"
"WSS_HOST": "wss://beta.alkator.cz"
}

View File

@ -12,8 +12,7 @@ pub struct Config {
pub SAVING_INTERVAL: u64,
pub STATION_ID: usize,
pub HOST: String,
pub LOGIN: String,
pub PASSWORD: String,
pub WSS_HOST: String,
}
fn read_config_from_file<P: AsRef<Path>>(path: P) -> Result<Config, Box<dyn Error>> {

View File

@ -0,0 +1,50 @@
use iced::futures;
use iced::task::{Never, Sipper, sipper};
use futures::stream::StreamExt;
use async_tungstenite::tungstenite;
use crate::config::CONFIG;
pub fn connect() -> impl Sipper<Never, Event> {
sipper(async |mut output| {
let endpoint_addr: String = CONFIG.WSS_HOST.clone() + "/api/live/racers";
loop {
let mut websocket =
match async_tungstenite::tokio::connect_async(endpoint_addr.as_str()).await
{
Ok((websocket, _)) => {
websocket.fuse()
}
Err(_) => {
tokio::time::sleep(tokio::time::Duration::from_secs(1))
.await;
continue;
}
};
println!("Websocket Connected!");
loop {
futures::select! {
received = websocket.select_next_some() => {
match received {
Ok(tungstenite::Message::Text(message)) => {
output.send(Event::MessageReceived(String::from(message.as_str()))).await;
}
Err(_) => {
println!("Websocket Disconnected!");
break;
}
Ok(_) => {},
}
}
}
}
}
})
}
#[derive(Debug, Clone)]
pub enum Event {
MessageReceived(String),
}

View File

@ -57,38 +57,31 @@ struct RegisterRacer{
}
async fn station_register(card_id: usize, time: DateTime::<Local>) -> Result<(), reqwest::Error>{
let client = reqwest::Client::builder()
.cookie_store(true)
.build()
.unwrap();
let result = client
.post(CONFIG.HOST.clone() + "/api/login")
.form(&[
("login", CONFIG.LOGIN.as_str()),
("password", CONFIG.PASSWORD.as_str()),
]);
.send()
.await?;
let register_racer = RegisterRacer{
card_id: card_id,
station_id: CONFIG.STATION_ID,
time: format!("{}", time.format("%d.%m.%Y %H:%M:%S.%f")),
time: format!("{}", time.format("%d.%m.%Y %H:%M:%S.%6f")),
};
client
Client::new()
.post(CONFIG.HOST.clone() + "/api/station/register")
.json(&register_racer)
.send()
.await?;
// Result can be error (400 and so on), whatever for now
Ok(())
}
impl State{
fn update(&mut self, message: Message) -> Task<Message>{
match message {
Message::RacerAdded(racer) => {
self.db.insert(racer.card_id, racer);
Task::none()
},
Message::RacerRecieved(event) => {
match event {
db_update::Event::MessageReceived(s) => {
let racer: Racer = serde_json::from_str(s.as_str()).unwrap();
self.db.insert(racer.card_id, racer);
},
};
}
Message::Tick(time) => {
if let Some(racer_time) = self.racers.iter().next() {
if time - racer_time.time > Duration::new(CONFIG.DURATION + 10, 0){
@ -107,8 +100,10 @@ impl State{
let time = Instant::now();
let datetime = Local::now();
if let Some(racer) = self.db.get(&card_id){
let racer_time = RacerTime{time, racer: racer.clone()};
self.racers.push(racer_time);
if !self.racers.iter().any(|rt| rt.racer.card_id == card_id){
let racer_time = RacerTime{time, racer: racer.clone()};
self.racers.push(racer_time);
}
}else{
println!("Racer {} not found in db!", card_id)
}
@ -165,6 +160,7 @@ impl State{
time::every(milliseconds(10)).map(Message::Tick),
time::every(seconds(CONFIG.SAVING_INTERVAL)).map(Message::DumpState),
Subscription::run(card_reader::connect).map(Message::CardReader),
Subscription::run(db_update::connect).map(Message::RacerRecieved)
])
}
fn theme(&self) -> Theme {
@ -180,7 +176,7 @@ struct Racer{
enum Message{
CardReader(card_reader::Event),
RacerAdded(Racer),
RacerRecieved(db_update::Event),
Tick(Instant),
DumpState(Instant),
Nothing,
@ -197,6 +193,7 @@ impl std::fmt::Debug for Message {
pub fn main() -> iced::Result {
let init_state = || -> State {read_to_string("state.json").ok().map(|s| serde_json::from_str(&s).ok()).flatten().unwrap_or_else(||Default::default())} ;
env_logger::init();
rustls::crypto::aws_lc_rs::default_provider().install_default().unwrap();
iced::application(init_state, State::update, State::view)
.subscription(State::subscription)
.theme(State::theme)

View File

@ -1 +1 @@
[]
[{"url": "https://beta.alkator.cz/api/card/register", "json": {"racer_id": 60, "starting_number": 2, "card_id": 1364550814, "time": "10.05.2025 17:40:13.486403"}}, {"url": "https://beta.alkator.cz/api/station/register", "json": {"card_id": 1364550814, "time": "10.05.2025 17:42:45.425016", "station_id": 1}}]