diff options
Diffstat (limited to 'src/onboard/iceportal.rs')
-rw-r--r-- | src/onboard/iceportal.rs | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/src/onboard/iceportal.rs b/src/onboard/iceportal.rs new file mode 100644 index 0000000..04ec291 --- /dev/null +++ b/src/onboard/iceportal.rs @@ -0,0 +1,126 @@ +/// implementation of traits to query the iceportal.de +/// (available in high speed trains in DE) +use chrono::{DateTime, Utc}; +use serde::Deserialize; +use serde_json::Value; + +use crate::onboard; +use crate::onboard::{OnBoardAPI, OnBoardInfo}; +use crate::{serde::*, traits::*, travelynx::TrainRef}; + +pub struct Iceportal {} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct TripInfo { + trip: Trip, + connection: Option<Value>, + selected_route: Option<Value>, + active: Option<Value> +} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +struct Trip { + train_type: String, + vzn: String, // train number + // some position info here + actual_position: u64, // distance along track, presumably + stops: Vec<Stop> +} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct Stop { + info: StopInfo, + station: Station, + timetable: Timetable +} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +struct StopInfo { + distance_from_start: u64, + position_status: String // one of "departed", "future", ... ? +} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +struct Station { + eva_nr: String, + name: String +} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +struct Timetable { + #[serde(deserialize_with = "option_naive_read_unixtime_db")] + scheduled_arrival_time: Option<DateTime<Utc>>, + #[serde(deserialize_with = "option_naive_read_unixtime_db")] + actual_arrival_time: Option<DateTime<Utc>> +} + +impl IsStation for Stop { + fn name(&self) -> &str { + &self.station.name + } + + fn scheduled_arrival(&self) -> Option<&chrono::DateTime<Utc>> { + self.timetable.scheduled_arrival_time.as_ref() + } + + fn real_arrival(&self) -> Option<&chrono::DateTime<Utc>> { + self.timetable.scheduled_arrival_time.as_ref() + } + + fn ds100(&self) -> &str { + "??" + } +} + +impl OnBoardInfo for TripInfo { + fn guess_last_station(&self) -> Option<&dyn IsStation> { + let current_pos = self.trip.actual_position; + self + .trip + .stops + .iter() + .rev() + .map(|stop| (stop.info.distance_from_start, stop)) + .filter(|(dist, _)| dist <= ¤t_pos) + .next() + .map(|(_, stop)| stop as &dyn IsStation) + } + + fn get_train_ref(&self) -> TrainRef { + TrainRef { + _type: self.trip.train_type.clone(), + no: self.trip.vzn.clone() + } + } + + fn stops<'a>( + &'a self + ) -> Box<dyn std::iter::Iterator<Item = &'a dyn IsStation> + 'a> { + Box::new(self.trip.stops.iter().map(|s| s as &dyn IsStation)) + } +} + +impl std::fmt::Display for Stop { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.station.name) + } +} + +impl OnBoardAPI for Iceportal { + fn apiurl(&self) -> &'static str { + "https://iceportal.de/api1/rs/tripInfo/trip" + } + + fn request( + &self, + debug: bool + ) -> Result<Box<dyn OnBoardInfo>, serde_json::Error> { + onboard::request::<_, TripInfo>(self, debug) + } +} |