/// implementation of traits to query zugportal.de /// (available at least in the Munich S-Bahn, maybe other trains) use chrono::{DateTime, Utc}; use serde::Deserialize; use crate::onboard; use crate::onboard::{OnBoardAPI, OnBoardInfo}; use crate::{traits::*, travelynx::TrainRef}; pub struct Zugportal {} #[derive(Deserialize, Debug)] #[serde(rename_all = "camelCase")] pub struct Journey { name: String, // the line's name, e.g. S 8 no: i64, stops: Vec } #[derive(Deserialize, Debug)] #[serde(rename_all = "camelCase")] pub struct Stop { station: Station, status: String, // one of "Normal", ...? track: Track, messages: Vec, arrival_time: Option, departure_time: Option } #[derive(Deserialize, Debug)] #[serde(rename_all = "camelCase")] struct Station { eva_no: String, name: String } #[derive(Deserialize, Debug)] #[serde(rename_all = "camelCase")] struct Track { target: String, prediction: String } #[derive(Deserialize, Debug)] #[serde(rename_all = "camelCase")] struct DepartureTime { target: DateTime, predicted: DateTime, time_type: String, // one of REAL, PREVIEW, ..? diff: i64 // diff in minutes? // NOTE: also sends predictedTimeInMs and targetTimeInMs; these might be unix times } impl IsStation for Stop { fn name(&self) -> &str { &self.station.name } fn scheduled_arrival(&self) -> Option<&chrono::DateTime> { self.arrival_time.as_ref().map(|t| &t.target) } fn real_arrival(&self) -> Option<&chrono::DateTime> { self.arrival_time.as_ref().map(|t| &t.predicted) } fn ds100(&self) -> &str { "??" } } impl std::fmt::Display for Stop { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.station.name) } } impl OnBoardInfo for Journey { fn guess_last_station(&self) -> Option<&dyn IsStation> { todo!() } fn get_train_ref(&self) -> TrainRef { TrainRef { _type: self.name.clone(), no: self.no.to_string().clone() } } fn stops<'a>( &'a self ) -> Box + 'a> { Box::new(self.stops.iter().map(|s| s as &dyn IsStation)) } } impl OnBoardAPI for Zugportal { fn apiurl(&self) -> &'static str { "https://zugportal.de/prd/zupo-travel-information/api/public/ri/journey" } fn request( &self, debug: bool ) -> Result, serde_json::Error> { onboard::request::<_, Journey>(self, debug) } }