From cd5c0f8dd1b8da2dfdbede3b0a20132db2085c0a Mon Sep 17 00:00:00 2001 From: Ollo Date: Sat, 28 Feb 2026 21:26:43 +0100 Subject: [PATCH] request station_id via new integrated function --- src/main.rs | 32 ++++++++++++++++++++++++---- src/straba.rs | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index 45fc311..af6abae 100644 --- a/src/main.rs +++ b/src/main.rs @@ -31,10 +31,14 @@ async fn main() -> Result<(), Box> { let (client, mut eventloop) = AsyncClient::new(mqttoptions, 100); - - let mut last_request = Instant::now(); + //FIXME Set last_request initially to 1 hour before now + let mut last_request = Instant::now() - Duration::from_secs(3600); let interval = Duration::from_secs(args.interval as u64); - let mut departure_data = tokio::task::spawn_blocking(|| straba::fetch_data(2494, Some(true))) + let station_id = tokio::task::spawn_blocking(|| straba::lookup_station_id("Lettestr")) + .await + .unwrap() + .expect("Failed to lookup station ID"); + let mut departure_data = tokio::task::spawn_blocking(move || straba::fetch_data(station_id, Some(true))) .await .unwrap(); let mut data_published = false; @@ -44,7 +48,7 @@ async fn main() -> Result<(), Box> { if now.duration_since(last_request) > interval { data_published = false; last_request = Instant::now(); - departure_data = tokio::task::spawn_blocking(|| straba::fetch_data(2494, Some(false))) + departure_data = tokio::task::spawn_blocking(move || straba::fetch_data(station_id, Some(false))) .await .unwrap(); if departure_data.failure { @@ -68,6 +72,26 @@ async fn main() -> Result<(), Box> { Ok(Event::Incoming(Packet::Publish(_))) => {} Ok(Event::Incoming(Packet::ConnAck(_))) => { println!("Connected to MQTT broker"); + if data_published == false + { + client + .publish("departure/station", QoS::AtLeastOnce, false, departure_data.station_name.as_bytes()) + .await?; + client + .publish("departure/outbound/station", QoS::AtLeastOnce, false, departure_data.outbound_station.as_bytes()) + .await?; + + client + .publish("departure/outbound/diff", QoS::AtLeastOnce, false, format!("{}", departure_data.outbound_diff)) + .await?; + client + .publish("departure/inbound/station", QoS::AtLeastOnce, false, departure_data.inbound_station.as_bytes()) + .await?; + client + .publish("departure/inbound/diff", QoS::AtLeastOnce, false, format!("{}", departure_data.inbound_diff)) + .await?; + data_published = true; + } } Ok(_) => { if data_published == false diff --git a/src/straba.rs b/src/straba.rs index 9731324..ebd05b8 100644 --- a/src/straba.rs +++ b/src/straba.rs @@ -8,6 +8,10 @@ const LOOKUP_STATION_URL: &str = "https://www.rnv-online.de/rest/stop?name="; const STATION_URL: &str = "https://www.rnv-online.de/rest/departure/"; /* ******************** JSON Description ****************************** */ +/******************************************************** +* Used to decode Timetable response +********************************************************/ + #[derive(Default, Debug, Clone, PartialEq, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Station { @@ -81,6 +85,61 @@ pub struct NextDeparture { pub failure: bool, } +/******************************************************** +* Used to decode Station Lookup +********************************************************/ + +#[derive(Default, Debug, Clone, PartialEq, Deserialize)] +pub struct StationLookupResponse { + pub results: Vec, +} + +#[derive(Default, Debug, Clone, PartialEq, Deserialize)] +pub struct StationLookupRegion { + pub children: Vec, +} + +#[derive(Default, Debug, Clone, PartialEq, Deserialize)] +pub struct StationLookupItem { + pub id: String, +} + +/******************************************************** +* Global Functions +********************************************************/ + +pub fn lookup_station_id(station_name: &str) -> Option { + let url = format!("{}{}", LOOKUP_STATION_URL, station_name); + let result = reqwest::blocking::get(&url).ok()?; + let text = result.text().ok()?; + let body: StationLookupResponse = serde_json::from_str(&text).ok()?; + + /** Example https://www.rnv-online.de/rest/stop?name=Lettestr + { + "results": [ + { + "text": "Mannheim", + "children": [ + { + "id": "2494", + "triasId": "de:08222:2494", + "text": "Mannheim, Lettestraße", + "value": "https://www.rnv-online.de/rest/station/2494" + } + ] + } + ], + "cached": false, + "lifetime": 3600 + } + */ + body.results + .iter() + .flat_map(|r| r.children.iter()) + .next() + .and_then(|s| s.id.parse().ok()) +} + pub fn fetch_data(station_id: u64, debug_print: Option) -> NextDeparture { let st_now = SystemTime::now(); let seconds = st_now.duration_since(UNIX_EPOCH).unwrap().as_secs();