Merge branch 'master' into ollo-dev
This commit is contained in:
		| @@ -1,6 +1,6 @@ | |||||||
|  |  | ||||||
| [package] | [package] | ||||||
| name = "LEDboardClient" | name = "ledboard_client" | ||||||
| version = "0.1.0" | version = "0.1.0" | ||||||
| edition = "2021" | edition = "2021" | ||||||
|  |  | ||||||
| @@ -10,7 +10,7 @@ embedded-graphics = "0.8.0" | |||||||
| substring = "1.4.5" | substring = "1.4.5" | ||||||
| tinybmp = "0.5.0" | tinybmp = "0.5.0" | ||||||
| openweathermap = { path = "../openweathermap" } | openweathermap = { path = "../openweathermap" } | ||||||
| chrono = { version = "0.4.23", default-features = false , features = ["iana-time-zone"] } | chrono = { version = "0.4.23", default-features = false , features = ["clock", "std","iana-time-zone"] } | ||||||
| chrono-tz = "0.8.0" | chrono-tz = "0.8.0" | ||||||
| colored = "2.0.0" | colored = "2.0.0" | ||||||
| datetime = "0.5.2" | datetime = "0.5.2" | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| use std::time::Duration; | use std::{time::Duration, fmt::format}; | ||||||
|  | use str; | ||||||
| use bit::BitIndex; | use bit::BitIndex; | ||||||
| use chrono_tz::Europe::Berlin; | use chrono_tz::Europe::Berlin; | ||||||
| use chrono::{DateTime, NaiveDateTime, Utc, Timelike}; | use chrono::{DateTime, NaiveDateTime, Utc, Timelike}; | ||||||
| @@ -9,20 +10,19 @@ use tinybmp::Bmp; | |||||||
| use core::time; | use core::time; | ||||||
| use embedded_graphics::{ | use embedded_graphics::{ | ||||||
|     image::Image, |     image::Image, | ||||||
|     mono_font::{iso_8859_1::FONT_6X10, iso_8859_1::FONT_5X8, MonoTextStyle}, |     mono_font::{iso_8859_1::FONT_6X10, iso_8859_1::FONT_5X8, iso_8859_1::FONT_4X6, MonoTextStyle}, | ||||||
|     pixelcolor::BinaryColor, |     pixelcolor::BinaryColor, | ||||||
|     prelude::*, |     prelude::*, | ||||||
|     primitives::PrimitiveStyle, |  | ||||||
|     text::Text, |     text::Text, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| use std::net::UdpSocket; | use std::net::UdpSocket; | ||||||
| use std::{env, thread}; | use std::{env, thread}; | ||||||
| use std::io; | use std::io; | ||||||
|  | use std::process::ExitCode; | ||||||
|  |  | ||||||
| use openweathermap::forecast::Forecast; | use openweathermap::forecast::Forecast; | ||||||
| use straba::NextDeparture; | use straba::NextDeparture; | ||||||
| use ping; |  | ||||||
| // This declaration will look for a file named `straba.rs` and will | // This declaration will look for a file named `straba.rs` and will | ||||||
| // insert its contents inside a module named `straba` under this scope | // insert its contents inside a module named `straba` under this scope | ||||||
| mod straba; | mod straba; | ||||||
| @@ -36,10 +36,6 @@ const IMAGE_HEIGHT_BYTE: u32 = 40; | |||||||
| const IMAGE_LENGTH: usize = (IMAGE_WIDTH_BYTE * IMAGE_HEIGHT_BYTE) as usize; | const IMAGE_LENGTH: usize = (IMAGE_WIDTH_BYTE * IMAGE_HEIGHT_BYTE) as usize; | ||||||
| const PACKAGE_LENGTH: usize = (IMAGE_LENGTH + 1) as usize; | const PACKAGE_LENGTH: usize = (IMAGE_LENGTH + 1) as usize; | ||||||
|  |  | ||||||
| const PRIMITIVE_STYLE:PrimitiveStyle<BinaryColor> = PrimitiveStyle::with_stroke(BinaryColor::On, 1); |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| struct UdpDisplay { | struct UdpDisplay { | ||||||
|     image: [u8; IMAGE_SIZE_BYTE], |     image: [u8; IMAGE_SIZE_BYTE], | ||||||
| @@ -131,6 +127,7 @@ fn render_weather(display: &mut UdpDisplay ,data: &Option<Result<Forecast, Strin | |||||||
|                 println!("{}", &error); |                 println!("{}", &error); | ||||||
|             } |             } | ||||||
|             Ok(result) => { |             Ok(result) => { | ||||||
|  |                 let mut temp:&f64 = &-1_f64; | ||||||
|                 if !result.list.is_empty() { |                 if !result.list.is_empty() { | ||||||
|                     let mut max:f64 = 0_f64; |                     let mut max:f64 = 0_f64; | ||||||
|                     let mut best = &result.list[0]; |                     let mut best = &result.list[0]; | ||||||
| @@ -143,11 +140,14 @@ fn render_weather(display: &mut UdpDisplay ,data: &Option<Result<Forecast, Strin | |||||||
|                         let hour = europe_time.hour(); |                         let hour = europe_time.hour(); | ||||||
|                         let minute = europe_time.minute(); |                         let minute = europe_time.minute(); | ||||||
|  |  | ||||||
|                         let cur_time = DateTime::<Utc>::default(); |                         let cur_time = chrono::offset::Utc::now(); | ||||||
|                         if zoned_time > cur_time { |                         if zoned_time > cur_time { | ||||||
|                             println!("Skipping old result {hour}:{minute} @{time_s}"); |                             println!("Skipping old result {hour}:{minute} @{time_s}"); | ||||||
|                         } |                         } | ||||||
|  |  | ||||||
|  |                         temp = &forecast.main.temp; | ||||||
|  |                         println!("Forecast Temp is {temp}°C"); | ||||||
|  |  | ||||||
|                         match &forecast.rain { |                         match &forecast.rain { | ||||||
|                             Some(x) => { |                             Some(x) => { | ||||||
|                                 let rain_v = x.three_hours; |                                 let rain_v = x.three_hours; | ||||||
| @@ -160,7 +160,6 @@ fn render_weather(display: &mut UdpDisplay ,data: &Option<Result<Forecast, Strin | |||||||
|                             None    => println!("No rain at {hour}:{minute}"), |                             None    => println!("No rain at {hour}:{minute}"), | ||||||
|                         } |                         } | ||||||
|                          |                          | ||||||
|                          |  | ||||||
|                     } |                     } | ||||||
|                      |                      | ||||||
|                     let condition = best.weather[0].to_owned(); |                     let condition = best.weather[0].to_owned(); | ||||||
| @@ -169,6 +168,13 @@ fn render_weather(display: &mut UdpDisplay ,data: &Option<Result<Forecast, Strin | |||||||
|                     println!("Weather info: {} desc: {} icon {}", condition.main, condition.description, condition.icon); |                     println!("Weather info: {} desc: {} icon {}", condition.main, condition.description, condition.icon); | ||||||
|  |  | ||||||
|                     render_weather_icon(&condition, display); |                     render_weather_icon(&condition, display); | ||||||
|  |                      | ||||||
|  |  | ||||||
|  |                     let text_style = MonoTextStyle::new(&FONT_6X10, BinaryColor::On); | ||||||
|  |                         let temp_string = format!("{temp:.0}°C"); | ||||||
|  |                         Text::new(&temp_string, Point::new((IMAGE_WIDTH-60) as i32, 7), text_style) | ||||||
|  |                         .draw(display) | ||||||
|  |                         .unwrap(); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
| @@ -224,9 +230,59 @@ fn render_weather_icon(condition: &Weather, display: &mut UdpDisplay ){ | |||||||
|     Image::new(&icon_image.unwrap(), Point::new((IMAGE_WIDTH-40) as i32, 0)).draw(display).unwrap(); |     Image::new(&icon_image.unwrap(), Point::new((IMAGE_WIDTH-40) as i32, 0)).draw(display).unwrap(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | fn render_clock(display: &mut UdpDisplay){ | ||||||
|  |     let time = chrono::offset::Utc::now(); | ||||||
|  |     let europe_time = time.with_timezone(&Berlin); | ||||||
|  |     let hour = europe_time.hour(); | ||||||
|  |     let minute = europe_time.minute(); | ||||||
|  |     let second = europe_time.second(); | ||||||
|  |     let time = format!("{hour:0>2}:{minute:0>2}:{second:0>2}"); | ||||||
|  |     let text_style = MonoTextStyle::new(&FONT_6X10, BinaryColor::On); | ||||||
|  |     Text::new(&time, Point::new((1) as i32, 7), text_style) | ||||||
|  |     .draw(display) | ||||||
|  |     .unwrap(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn render_strab_partial(display: &mut UdpDisplay, station: &String, diff: i64, height: i32) { | ||||||
|  |     let text_style = MonoTextStyle::new(&FONT_6X10, BinaryColor::On); | ||||||
|  |     let mut diff_str = format!("{}min", (diff / 60)); | ||||||
|  |     if diff < 60 { | ||||||
|  |         diff_str = String::from("sofort"); | ||||||
|  |     } | ||||||
|  |     let station_short: String; | ||||||
|  |     if str::len(&station) > 13 { | ||||||
|  |         station_short = station | ||||||
|  |             .replace("Straße", "Str") | ||||||
|  |             .replace("straße", "str") | ||||||
|  |             .replace("Platz", "Pl") | ||||||
|  |             .replace("platz", "pl") | ||||||
|  |             .replace("Hauptbahnhof", "Hbf") | ||||||
|  |             .replace("Bahnhof", "Bf"); | ||||||
|  |     } else { | ||||||
|  |         station_short = station.to_string(); | ||||||
|  |     } | ||||||
|  |     let station_clip: String; | ||||||
|  |     if str::len(&station_short) > 13 { | ||||||
|  |         station_clip = station_short[0..12].to_string(); | ||||||
|  |     } else { | ||||||
|  |         station_clip = station_short.to_string(); | ||||||
|  |     } | ||||||
|  |     Text::new(&station_clip, Point::new(1, height), text_style) | ||||||
|  |             .draw(display) | ||||||
|  |             .unwrap(); | ||||||
|  |     Text::new(&diff_str, Point::new(80, height), text_style) | ||||||
|  |             .draw(display) | ||||||
|  |             .unwrap(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn render_strab(display: &mut UdpDisplay, straba_res: &NextDeparture) { | ||||||
|  |     render_strab_partial(display, &straba_res.outbound_station, straba_res.outbound_diff, 17); | ||||||
|  |     render_strab_partial(display, &straba_res.inbound_station, straba_res.inbound_diff, 27); | ||||||
|  | } | ||||||
|  |  | ||||||
| fn send_package(ipaddress: String,  | fn send_package(ipaddress: String,  | ||||||
|                 data: &Option<Result<Forecast, String>>, |                 data: &Option<Result<Forecast, String>>, | ||||||
|                 strabaRes: &NextDeparture) { |                 straba_res: &NextDeparture) { | ||||||
|     let mut package: [u8; PACKAGE_LENGTH] = [0; PACKAGE_LENGTH]; |     let mut package: [u8; PACKAGE_LENGTH] = [0; PACKAGE_LENGTH]; | ||||||
|  |  | ||||||
|     // Brightness |     // Brightness | ||||||
| @@ -236,37 +292,16 @@ fn send_package(ipaddress: String, | |||||||
|         image: [0; IMAGE_SIZE_BYTE], |         image: [0; IMAGE_SIZE_BYTE], | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     if (data.is_some()) { |     if data.is_some() { | ||||||
|         render_weather(&mut display, data);                    |         render_weather(&mut display, data);                    | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if strabaRes.failure == false { |     if straba_res.failure == false { | ||||||
|         let text_style = MonoTextStyle::new(&FONT_6X10, BinaryColor::On); |         render_strab(&mut display, straba_res); | ||||||
|         let text_style_station = MonoTextStyle::new(&FONT_5X8, BinaryColor::On); |  | ||||||
|         let mut outbound = format!("+{}min", (strabaRes.outbound_diff / 60)); |  | ||||||
|         if (strabaRes.outbound_diff < 60) { |  | ||||||
|             outbound = String::from("sofort"); |  | ||||||
|         } |  | ||||||
|         Text::new(&strabaRes.outbound_station, Point::new(1, 15), text_style_station) |  | ||||||
|                 .draw(&mut display) |  | ||||||
|                 .unwrap(); |  | ||||||
|         Text::new(&outbound, Point::new(80, 15), text_style) |  | ||||||
|                 .draw(&mut display) |  | ||||||
|                 .unwrap(); |  | ||||||
|  |  | ||||||
|         let mut inbound = format!("+{}min", (strabaRes.inbound_diff / 60)); |  | ||||||
|         if (strabaRes.inbound_diff < 60) { |  | ||||||
|             inbound = String::from("sofort"); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     render_clock(&mut display); | ||||||
|  |  | ||||||
|         Text::new(&strabaRes.inbound_station, Point::new(1, 25), text_style_station) |  | ||||||
|                 .draw(&mut display) |  | ||||||
|                 .unwrap(); |  | ||||||
|         Text::new(&inbound, Point::new(80, 24), text_style) |  | ||||||
|                 .draw(&mut display) |  | ||||||
|                 .unwrap(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     package[1..PACKAGE_LENGTH].copy_from_slice(&display.image); |     package[1..PACKAGE_LENGTH].copy_from_slice(&display.image); | ||||||
|     // client need to bind to client port (1 before 4242) |     // client need to bind to client port (1 before 4242) | ||||||
| @@ -286,12 +321,12 @@ LEDboardClient <ip address>" | |||||||
| } | } | ||||||
|  |  | ||||||
| fn check_connection(ipaddress: String) -> bool { | fn check_connection(ipaddress: String) -> bool { | ||||||
|     let mut device_online = false; |     let device_online; | ||||||
|     // generate a faulty package length |     // generate a faulty package length | ||||||
|     let mut package: [u8; PACKAGE_LENGTH/2] = [0; PACKAGE_LENGTH/2]; |     let mut package: [u8; PACKAGE_LENGTH/2] = [0; PACKAGE_LENGTH/2]; | ||||||
|     // client need to bind to client port (1 before 4242) |     // client need to bind to client port (1 before 4242) | ||||||
|     let socket = UdpSocket::bind("0.0.0.0:14242").expect("couldn't bind to address"); |     let socket = UdpSocket::bind("0.0.0.0:14242").expect("couldn't bind to address"); | ||||||
|     socket.set_read_timeout(Some(Duration::from_secs(10))); /* 10 seconds timeout */ |     socket.set_read_timeout(Some(Duration::from_secs(10))).unwrap(); /* 10 seconds timeout */ | ||||||
|     socket |     socket | ||||||
|         .send_to(&package, ipaddress + ":4242") |         .send_to(&package, ipaddress + ":4242") | ||||||
|         .expect("couldn't send data"); |         .expect("couldn't send data"); | ||||||
| @@ -299,28 +334,28 @@ fn check_connection(ipaddress: String) -> bool { | |||||||
|     // self.recv_buff is a [u8; 8092] |     // self.recv_buff is a [u8; 8092] | ||||||
|     let answer = socket.recv_from(&mut package); |     let answer = socket.recv_from(&mut package); | ||||||
|     match answer { |     match answer { | ||||||
|         Ok((n, addr)) => { |         Ok((_n, _addr)) => { | ||||||
|             //println!("{} bytes response from {:?} {:?}", n, addr, &package[..n]); |             //println!("{} bytes response from {:?} {:?}", n, addr, &package[..n]); | ||||||
|             device_online = true; |             device_online = true; | ||||||
|         } |         } | ||||||
|         Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { |         Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { | ||||||
|             device_online = false; |             device_online = false; | ||||||
|         } |         } | ||||||
|         Err(e) => { |         Err(_e) => { | ||||||
|             device_online = false; |             device_online = false; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     return device_online; |     return device_online; | ||||||
| } | } | ||||||
|  |  | ||||||
| fn main() { | fn main() -> ExitCode { | ||||||
|     let args: Vec<String> = env::args().collect(); |     let args: Vec<String> = env::args().collect(); | ||||||
|  |  | ||||||
|     match args.len() { |     match args.len() { | ||||||
|         // no arguments passed |         // no arguments passed | ||||||
|         1 => { |         1 => { | ||||||
|             // show a help message |             // show a help message | ||||||
|             help(); |             help(); | ||||||
|  |             return ExitCode::SUCCESS; | ||||||
|         } |         } | ||||||
|         // one argument passed |         // one argument passed | ||||||
|         2 => { |         2 => { | ||||||
| @@ -328,9 +363,9 @@ fn main() { | |||||||
|  |  | ||||||
|  |  | ||||||
|             let mut device_online = check_connection(ip.to_string()); |             let mut device_online = check_connection(ip.to_string()); | ||||||
|             if (!device_online) { |             if !device_online { | ||||||
|                 println!("{} not online", ip); |                 println!("{} not online", ip); | ||||||
|                 return |                 return ExitCode::FAILURE; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             let receiver = openweathermap::init_forecast("Mannheim", |             let receiver = openweathermap::init_forecast("Mannheim", | ||||||
| @@ -342,16 +377,16 @@ fn main() { | |||||||
|             let mut last_data = Option::None; |             let mut last_data = Option::None; | ||||||
|              |              | ||||||
|             // Test Webcrawler for public transportataion |             // Test Webcrawler for public transportataion | ||||||
|             let mut strabaRes = straba::fetch_data(Some(true)); |             let mut straba_res = straba::fetch_data(Some(true)); | ||||||
|             println!("{:?} {:?}s", strabaRes.outbound_station, strabaRes.outbound_diff); |             println!("{:?} {:?}s", straba_res.outbound_station, straba_res.outbound_diff); | ||||||
|             println!("{:?} {:?}s", strabaRes.inbound_station , strabaRes.inbound_diff); |             println!("{:?} {:?}s", straba_res.inbound_station , straba_res.inbound_diff); | ||||||
|  |  | ||||||
|             // Render start |             // Render start | ||||||
|             send_package(ip.to_string(), &last_data, &strabaRes); |             send_package(ip.to_string(), &last_data, &straba_res); | ||||||
|             loop { |             loop { | ||||||
|                 let st_now = SystemTime::now(); |                 let st_now = SystemTime::now(); | ||||||
|                 let seconds = st_now.duration_since(UNIX_EPOCH).unwrap().as_secs(); |                 let seconds = st_now.duration_since(UNIX_EPOCH).unwrap().as_secs(); | ||||||
|                 let delay = time::Duration::from_millis(10000); |                 let delay = time::Duration::from_millis(500); | ||||||
|                 thread::sleep(delay); |                 thread::sleep(delay); | ||||||
|                 // Only request, if the device is present |                 // Only request, if the device is present | ||||||
|                 if device_online == true { |                 if device_online == true { | ||||||
| @@ -366,19 +401,19 @@ fn main() { | |||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 if (strabaRes.request_time + 60) < seconds as i64 { |                 if (straba_res.request_time + 50) < seconds as i64 { | ||||||
|                     device_online = check_connection(ip.to_string()); |                     device_online = check_connection(ip.to_string()); | ||||||
|                     // request once a minute new data |                     // request once a minute new data | ||||||
|                     if device_online == true { |                     if device_online == true { | ||||||
|                         strabaRes = straba::fetch_data(None); |                         straba_res = straba::fetch_data(None); | ||||||
|                         println!("Update {:?} {:?}s", strabaRes.outbound_station, strabaRes.outbound_diff); |                         println!("Update {:?} {:?}s", straba_res.outbound_station, straba_res.outbound_diff); | ||||||
|                         println!("Update {:?} {:?}s", strabaRes.inbound_station , strabaRes.inbound_diff); |                         println!("Update {:?} {:?}s", straba_res.inbound_station , straba_res.inbound_diff); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 if device_online == true { |                 if device_online == true { | ||||||
|                     // Render new image |                     // Render new image | ||||||
|                     send_package(ip.to_string(), &last_data, &strabaRes); |                     send_package(ip.to_string(), &last_data, &straba_res); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @@ -386,6 +421,7 @@ fn main() { | |||||||
|         _ => { |         _ => { | ||||||
|             // show a help message |             // show a help message | ||||||
|             help(); |             help(); | ||||||
|  |             return ExitCode::SUCCESS; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,11 +1,6 @@ | |||||||
| use chrono::DateTime; | use chrono::DateTime; | ||||||
| use std::time::{SystemTime, UNIX_EPOCH}; | use std::time::{SystemTime, UNIX_EPOCH}; | ||||||
| use chrono_tz::Europe::Berlin; | use chrono::Local; | ||||||
|  |  | ||||||
| /* @file straba.rs |  | ||||||
|  * @brief fetch next depature of light rail vehicle |  | ||||||
|  */ |  | ||||||
| use serde_json::Value; |  | ||||||
| use serde::Deserialize; | use serde::Deserialize; | ||||||
|  |  | ||||||
| const STATION_URL:&str = "https://www.rnv-online.de/rest/departure/2494"; | const STATION_URL:&str = "https://www.rnv-online.de/rest/departure/2494"; | ||||||
| @@ -16,7 +11,8 @@ const STATION_URL:&str = "https://www.rnv-online.de/rest/departure/2494"; | |||||||
| pub struct Station { | pub struct Station { | ||||||
|     pub id: String, |     pub id: String, | ||||||
|     pub name: String, |     pub name: String, | ||||||
|     pub graphQL: GraphQL, |     #[serde(alias = "graphQL")] | ||||||
|  |     pub graph_ql: GraphQL, | ||||||
| } | } | ||||||
|  |  | ||||||
| #[derive(Default, Debug, Clone, PartialEq, Deserialize)] | #[derive(Default, Debug, Clone, PartialEq, Deserialize)] | ||||||
| @@ -41,7 +37,7 @@ pub struct JourneysElement { | |||||||
| #[derive(Default, Debug, Clone, PartialEq, Deserialize)] | #[derive(Default, Debug, Clone, PartialEq, Deserialize)] | ||||||
| #[serde(rename_all = "camelCase")] | #[serde(rename_all = "camelCase")] | ||||||
| pub struct Line { | pub struct Line { | ||||||
|     pub lineGroup: LineGroup, |     pub line_group: LineGroup, | ||||||
| } | } | ||||||
|  |  | ||||||
| #[derive(Default, Debug, Clone, PartialEq, Deserialize)] | #[derive(Default, Debug, Clone, PartialEq, Deserialize)] | ||||||
| @@ -61,15 +57,15 @@ pub struct Journey { | |||||||
| #[derive(Default, Debug, Clone, PartialEq, Deserialize)] | #[derive(Default, Debug, Clone, PartialEq, Deserialize)] | ||||||
| #[serde(rename_all = "camelCase")] | #[serde(rename_all = "camelCase")] | ||||||
| pub struct StopsElement { | pub struct StopsElement { | ||||||
|     pub destinationLabel:   String, |     pub destination_label:   String, | ||||||
|     pub plannedDeparture:   IsoStringDateTime, |     pub planned_departure:   IsoStringDateTime, | ||||||
|     pub realtimeDeparture:  IsoStringDateTime, |     pub realtime_departure:  IsoStringDateTime, | ||||||
| } | } | ||||||
|  |  | ||||||
| #[derive(Default, Debug, Clone, PartialEq, Deserialize)] | #[derive(Default, Debug, Clone, PartialEq, Deserialize)] | ||||||
| #[serde(rename_all = "camelCase")] | #[serde(rename_all = "camelCase")] | ||||||
| pub struct IsoStringDateTime { | pub struct IsoStringDateTime { | ||||||
|     pub isoString: Option<String>, |     pub iso_string: Option<String>, | ||||||
| } | } | ||||||
|  |  | ||||||
| // Return value | // Return value | ||||||
| @@ -83,13 +79,14 @@ pub struct NextDeparture { | |||||||
| } | } | ||||||
|  |  | ||||||
| pub fn fetch_data(debug_print : Option<bool>) -> NextDeparture { | pub fn fetch_data(debug_print : Option<bool>) -> NextDeparture { | ||||||
|  |     let date = Local::now(); | ||||||
|     let st_now = SystemTime::now(); |     let st_now = SystemTime::now(); | ||||||
|     let seconds = st_now.duration_since(UNIX_EPOCH).unwrap().as_secs(); |     let seconds = st_now.duration_since(UNIX_EPOCH).unwrap().as_secs(); | ||||||
|     let url = &format!("{}?datetime={}", STATION_URL, seconds); |     let timeString = date.format("%Y-%m-%d %H:%M:%S"); | ||||||
|  |     let url = &format!("{}?datetime={}", STATION_URL, timeString); | ||||||
|     let result = reqwest::blocking::get(url); |     let result = reqwest::blocking::get(url); | ||||||
|      |      | ||||||
|     let mut returnValue = NextDeparture { |     let mut return_value = NextDeparture { | ||||||
|         failure  : false, |         failure  : false, | ||||||
|         outbound_station  : String::from(""), |         outbound_station  : String::from(""), | ||||||
|         outbound_diff : 10000, |         outbound_diff : 10000, | ||||||
| @@ -100,64 +97,86 @@ pub fn fetch_data(debug_print : Option<bool>) -> NextDeparture { | |||||||
|  |  | ||||||
|     if result.is_err() { |     if result.is_err() { | ||||||
|         println!("Could not read station response {:?}", result.err()); |         println!("Could not read station response {:?}", result.err()); | ||||||
|         returnValue.failure = true; |         return_value.failure = true; | ||||||
|         return returnValue; |         return return_value; | ||||||
|     } |     } | ||||||
|     let text = result.unwrap().text(); |     let text = result.unwrap().text(); | ||||||
|     if text.is_err() { |     if text.is_err() { | ||||||
|         println!("Could not convert response {:?}", text.err()); |         println!("Could not convert response {:?}", text.err()); | ||||||
|         returnValue.failure = true; |         return_value.failure = true; | ||||||
|         return returnValue; |         return return_value; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     let rawText = &text.unwrap(); |     let raw_text = &text.unwrap(); | ||||||
|     let body: std::result::Result<Station, serde_json::Error> = serde_json::from_str(&rawText); |     let body: std::result::Result<Station, serde_json::Error> = serde_json::from_str(&raw_text); | ||||||
|  |  | ||||||
|     if body.is_err() { |     if body.is_err() { | ||||||
|         println!("Could not parse json {:?}", body.err());   |         println!("Could not parse json {:?}", body.err());   | ||||||
|         println!("------------------------- %< ----------------------------"); |         println!("------------------------- %< ----------------------------"); | ||||||
|         println!("{}", &rawText); |         println!("{}", &raw_text); | ||||||
|         println!("------------------------- %< ----------------------------"); |         println!("------------------------- %< ----------------------------"); | ||||||
|         returnValue.failure = true; |         return_value.failure = true; | ||||||
|         return returnValue; |         return return_value; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     if debug_print.is_some() && debug_print.unwrap() == true { | ||||||
|  |         println!("----------- Seconds {:} {:} requesting ... -----------", seconds, timeString); | ||||||
|  |     } | ||||||
|     // parse JSON result.. search of both directions |     // parse JSON result.. search of both directions | ||||||
|     let json = body.unwrap(); |     let json = body.unwrap(); | ||||||
|     for el in (json.graphQL.response.journeys.elements) { |      | ||||||
|         if (debug_print.is_some() && debug_print.unwrap() == true) { |     if debug_print.is_some() && debug_print.unwrap() == true { | ||||||
|             println!("Line {:}", el.line.lineGroup.label);   |         println!("Requesting {:}", json.graph_ql.response.name); | ||||||
|  |         println!("Elements {:}", json.graph_ql.response.journeys.elements.len() ); | ||||||
|  |         println!("------------------------- %< ----------------------------"); | ||||||
|  |         println!("{}", &raw_text); | ||||||
|  |         println!("------------------------- %< ----------------------------"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     for el in json.graph_ql.response.journeys.elements { | ||||||
|  |  | ||||||
|  |         if debug_print.is_some() && debug_print.unwrap() == true { | ||||||
|  |             println!("Requesting {:}", json.graph_ql.response.name); | ||||||
|  |             println!("Line {:}", el.line.line_group.label); | ||||||
|         } |         } | ||||||
|         for stop in el.stops { |         for stop in el.stops { | ||||||
|             // use only valid data |             // use only valid data | ||||||
|             if stop.realtimeDeparture.isoString.is_some() &&  |             if stop.realtime_departure.iso_string.is_some() &&  | ||||||
|                 stop.destinationLabel != "" { |                 stop.destination_label != "" { | ||||||
|                 let txt_departure = stop.realtimeDeparture.isoString.unwrap(); |                 let txt_departure = stop.realtime_departure.iso_string.unwrap(); | ||||||
|                 let next_departure = DateTime::parse_from_rfc3339(&txt_departure).unwrap(); |                 let next_departure = DateTime::parse_from_rfc3339(&txt_departure).unwrap(); | ||||||
|                  |                  | ||||||
|                 let diff = next_departure.timestamp() - (seconds  as i64); |                 let diff = next_departure.timestamp() - (seconds  as i64); | ||||||
|                 if (debug_print.is_some() && debug_print.unwrap() == true) { |                 if debug_print.is_some() && debug_print.unwrap() == true { | ||||||
|                     println!("To      {:} {:} (in {:} seconds)", stop.destinationLabel, txt_departure, diff ); |                     println!("To      {:} {:} (in {:} seconds)", stop.destination_label, txt_departure, diff ); | ||||||
|                 } |                 } | ||||||
|                  |                  | ||||||
|                 if stop.destinationLabel.contains("Rheinau") { |                 if stop.destination_label.contains("Rheinau") { | ||||||
|                     if (diff <  returnValue.outbound_diff) { |                     if diff <  return_value.outbound_diff { | ||||||
|                         returnValue.outbound_station = stop.destinationLabel; |                         return_value.outbound_station = stop.destination_label; | ||||||
|                         returnValue.outbound_diff = diff; |                         return_value.outbound_diff = diff; | ||||||
|  |                     } else if debug_print.is_some() && debug_print.unwrap() == true { | ||||||
|  |                         println!("Unkown diff Stop   {:} {:} (in {:} seconds)", stop.destination_label, txt_departure, diff ); | ||||||
|                     } |                     } | ||||||
|                 } else if stop.destinationLabel.contains("Hochschule") || |                 } else if stop.destination_label.contains("Hochschule") || | ||||||
|                             stop.destinationLabel.contains("Hauptbahnhof") || |                             stop.destination_label.contains("Hauptbahnhof") || | ||||||
|                             stop.destinationLabel.contains("Schönau") { |                             stop.destination_label.contains("Schönau") { | ||||||
|                     if (diff <  returnValue.inbound_diff) { |                     if diff <  return_value.inbound_diff { | ||||||
|                         returnValue.inbound_station = stop.destinationLabel; |                         return_value.inbound_station = stop.destination_label; | ||||||
|                         returnValue.inbound_diff = diff; |                         return_value.inbound_diff = diff; | ||||||
|  |                     } else if debug_print.is_some() && debug_print.unwrap() == true { | ||||||
|  |                         println!("Unkown diff Stop   {:} {:} (in {:} seconds)", stop.destination_label, txt_departure, diff ); | ||||||
|                     } |                     } | ||||||
|  |                 } else if debug_print.is_some() && debug_print.unwrap() == true { | ||||||
|  |                     println!("Unkown Stop   {:} {:} (in {:} seconds)", stop.destination_label, txt_departure, diff ); | ||||||
|                 } |                 } | ||||||
|             } else { |             } else { | ||||||
|                 println!("Planned {:} {:?}", stop.destinationLabel, stop.plannedDeparture.isoString) |                 println!("Planned {:} {:?}", stop.destination_label, stop.planned_departure.iso_string) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |     if debug_print.is_some() && debug_print.unwrap() == true { | ||||||
|     returnValue |         println!("----------- end of straba.rs -----------"); | ||||||
|  |     } | ||||||
|  |     return_value | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										0
									
								
								client/openweathermap/src/lib.rs
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								client/openweathermap/src/lib.rs
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							| @@ -22,6 +22,7 @@ MainWindow::~MainWindow() | |||||||
| } | } | ||||||
|  |  | ||||||
| void MainWindow::drawImage(QImage *target) { | void MainWindow::drawImage(QImage *target) { | ||||||
|  |     (void)target; /* handle unused variable ;-) */ | ||||||
|     this->mScene=new QGraphicsScene() ; |     this->mScene=new QGraphicsScene() ; | ||||||
|     QGraphicsView *graphicsView = new QGraphicsView(); |     QGraphicsView *graphicsView = new QGraphicsView(); | ||||||
|     graphicsView->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); |     graphicsView->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ | |||||||
| #include "settings.h" | #include "settings.h" | ||||||
| #include <QUdpSocket> | #include <QUdpSocket> | ||||||
| #include <QNetworkDatagram> | #include <QNetworkDatagram> | ||||||
|  | #include <ostream> | ||||||
| #include "mainwindow.h" | #include "mainwindow.h" | ||||||
|  |  | ||||||
| #define UDP_IMAGE_PORT  4242 | #define UDP_IMAGE_PORT  4242 | ||||||
| @@ -49,6 +50,7 @@ void UdpLedServer ::readPendingDatagrams() | |||||||
|  |  | ||||||
| void UdpLedServer::processTheDatagram(QNetworkDatagram datagram) { | void UdpLedServer::processTheDatagram(QNetworkDatagram datagram) { | ||||||
|     if (datagram.isValid() && datagram.data().length() == PACKET_LENGTH) { |     if (datagram.isValid() && datagram.data().length() == PACKET_LENGTH) { | ||||||
|  |         qInfo("Received regular datagram."); | ||||||
|         uint8_t brightness = datagram.data().at(PACKET_INDEX_BRIGHTNESS); |         uint8_t brightness = datagram.data().at(PACKET_INDEX_BRIGHTNESS); | ||||||
|         int currentIndex = PACKET_INDEX_PANEL0; |         int currentIndex = PACKET_INDEX_PANEL0; | ||||||
|  |  | ||||||
| @@ -70,5 +72,13 @@ void UdpLedServer::processTheDatagram(QNetworkDatagram datagram) { | |||||||
|  |  | ||||||
|         qDebug() << "Received datagram:" << brightness; |         qDebug() << "Received datagram:" << brightness; | ||||||
|  |  | ||||||
|  |     } else if (datagram.isValid() && datagram.data().length() != PACKET_LENGTH) { | ||||||
|  |         qDebug("Received status-check datagram."); | ||||||
|  |         //socket = new QUdpSocket(this); | ||||||
|  |         this->mUdpSocket->writeDatagram(datagram.data(), sizeof(datagram.data()), datagram.senderAddress(), datagram.senderPort()); | ||||||
|  |         //this->mUdpSocket->writeDatagram(datagram); | ||||||
|  |         qDebug("Returned datagram"); | ||||||
|  |     } else { | ||||||
|  |         qDebug("Received invalid datagram."); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user