diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..d4ab457 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,10 @@ +stages: + - build + +rust-latest: + stage: build + image: rust:latest + script: + - cargo build --verbose + - cargo test --verbose + diff --git a/Cargo.lock b/Cargo.lock index 484d7e7..be39e8f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -89,6 +89,7 @@ checksum = "942f72db697d8767c22d46a598e01f2d3b475501ea43d0db4f16d90259182d0b" dependencies = [ "num-integer", "num-traits", + "serde", "time", ] diff --git a/Cargo.toml b/Cargo.toml index d0bc117..4ecfa7a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ rppal = "0.11.3" image = "*" imageproc = "*" arrayref = "*" -chrono = "*" +chrono = { version = "*", features = [ "serde" ] } chrono-tz = "*" euclid = "*" log = "*" diff --git a/src/main.rs b/src/main.rs index c1e41b8..b22e015 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,8 +25,8 @@ mod signalk; mod vesseldata; use vesseldata::VesselDataEventSource; -pub struct HelmsDisplay<'a> { - font: Font<'a>, +pub struct HelmsDisplay { + font: Font<'static>, boat: forms::Form, compassrose: forms::Form, cog: forms::Form, @@ -36,9 +36,9 @@ pub struct HelmsDisplay<'a> { course_screen: forms::Screen, } -impl<'a> HelmsDisplay<'a> { +impl HelmsDisplay { - pub fn new() -> HelmsDisplay<'a> { + pub fn new() -> HelmsDisplay { // in the future, this method should probably take some sort of // configuration object. let mut loader = forms::Loader::new("/root/helms-display".to_string()); @@ -60,52 +60,52 @@ impl<'a> HelmsDisplay<'a> { } } - pub fn render_gps (&mut self, loc: Option) { + pub fn render_no_gps (&mut self) { self.gps_screen.clear(); - match loc { - None => self.gps_screen.text_c(&self.font, " --\u{00B0}--\u{2032}--\u{2033} --\u{00B0}--\u{2032}--\u{2033}", 32.0, 200, 5), - Some(vesseldata::VesselDataEvent::Location(lat,lon)) => { - - // format with unicodes for degrees, minutes and seconds. - let (latitude, lat_ew) = { - if lat < 0.0 { - (-lat, 'W') - } else if lat > 0.0 { - (lat, 'E') - } else { - (0.0, '-') - } - }; - - let (longitude, long_ns) = { - if lon < 0.0 { - (-lon, 'S') - } else if lon > 0.0 { - (lon, 'N') - } else { - (0.0, '-') - } - }; - - let long_d: u8 = longitude.trunc() as u8; - let longitude = longitude.fract() * 60.0; - let long_m: u8 = longitude.trunc() as u8; - let longitude = longitude.fract() * 60.0; - let long_s: u8 = longitude.round() as u8; - - let lat_d: u8 = latitude.trunc() as u8; - let latitude = latitude.fract() * 60.0; - let lat_m: u8 = latitude.trunc() as u8; - let latitude = latitude.fract() * 60.0; - let lat_s: u8 = latitude.round() as u8; - self.gps_screen.text_c(&self.font, - format!("{}{:02}\u{00B0}{:02}\u{2032}{:02}\u{2033} {}{:02}\u{00B0}{:02}\u{2032}{:02}\u{2033}", - long_ns, long_d, long_m, long_s, lat_ew, lat_d, lat_m, lat_s).as_str(), 32.0, 200, 5); - }, - _ => (), - } + self.gps_screen.text_c(&self.font, " --\u{00B0}--\u{2032}--\u{2033} --\u{00B0}--\u{2032}--\u{2033}", 32.0, 200, 5); } + pub fn render_gps (&mut self, lat: f32, lon: f32) { + self.gps_screen.clear(); + + // format with unicodes for degrees, minutes and seconds. + let (latitude, lat_ew) = { + if lat < 0.0 { + (-lat, 'W') + } else if lat > 0.0 { + (lat, 'E') + } else { + (0.0, '-') + } + }; + + let (longitude, long_ns) = { + if lon < 0.0 { + (-lon, 'S') + } else if lon > 0.0 { + (lon, 'N') + } else { + (0.0, '-') + } + }; + + let long_d: u8 = longitude.trunc() as u8; + let longitude = longitude.fract() * 60.0; + let long_m: u8 = longitude.trunc() as u8; + let longitude = longitude.fract() * 60.0; + let long_s: u8 = longitude.round() as u8; + + let lat_d: u8 = latitude.trunc() as u8; + let latitude = latitude.fract() * 60.0; + let lat_m: u8 = latitude.trunc() as u8; + let latitude = latitude.fract() * 60.0; + let lat_s: u8 = latitude.round() as u8; + self.gps_screen.text_c(&self.font, + format!("{}{:02}\u{00B0}{:02}\u{2032}{:02}\u{2033} {}{:02}\u{00B0}{:02}\u{2032}{:02}\u{2033}", + long_ns, long_d, long_m, long_s, lat_ew, lat_d, lat_m, lat_s).as_str(), 32.0, 200, 5); + } + + pub fn render_time (&mut self) { let tz: Tz = "Europe/Copenhagen".parse().unwrap(); let now = Utc::now().with_timezone(&tz); @@ -114,13 +114,12 @@ impl<'a> HelmsDisplay<'a> { self.time_screen.text_c(&self.font, now.format("%Y-%m-%d").to_string().as_str(), 16.0, 100, 43); } - pub fn render_course (&mut self, cog: Option, magnetic: Option, wind: Option) { - let rad = (6 as f32) * 2.0*PI / 100.0; + pub fn render_course (&mut self, cog: Option, magnetic: Option, wind: Option) { self.course_screen.clear(); // render course over ground if present match cog { - Some(vesseldata::VesselDataEvent::CourseOverGround(c)) => { + Some(c) => { self.course_screen.render(&self.cog, c, 500, 500); }, _ => (), @@ -128,15 +127,21 @@ impl<'a> HelmsDisplay<'a> { // render wind if present match wind { - Some(vesseldata::VesselDataEvent::WindOrigin(o)) => { + Some(o) => { self.course_screen.render(&self.wind, o, 500, 500); }, _ => (), }; // render compass rose + match magnetic { + Some(m) => { + self.course_screen.render(&self.compassrose, m, 500, 500); + }, + _ => (), + }; - self.course_screen.render(&self.compassrose, rad, 500, 500); + // render boat self.course_screen.render(&self.boat, 0.0, 500, 500); } @@ -194,7 +199,7 @@ fn main() -> Result<(), Box> { e.put_image(&(sog_screen.image), (0, 50)); */ - helms.render_gps(None); + helms.render_no_gps(); e.put_image(&(helms.gps_screen.image), (40,0)); helms.render_time(); @@ -203,6 +208,10 @@ fn main() -> Result<(), Box> { println!("Display has been rendered now, sleeping for 5s"); let vd = signalk::SignalK::connect(); + for i in 0..9 { + + }; + thread::sleep(Duration::from_millis(15000)); e.turn_off(); diff --git a/src/signalk.rs b/src/signalk.rs index ca2fd4d..169a37e 100644 --- a/src/signalk.rs +++ b/src/signalk.rs @@ -6,6 +6,7 @@ use serde::Deserialize; use serde_json::Value as JValue; use std::sync::mpsc::{Sender, Receiver}; use std::sync::mpsc; +use chrono::{DateTime, Utc}; use crate::vesseldata::{VesselDataEvent, VesselDataEventSource}; @@ -31,7 +32,7 @@ struct Value { struct Update { #[serde(rename = "$source")] dsource: String, - timestamp: String, + timestamp: DateTime, values: Vec, } diff --git a/src/vesseldata.rs b/src/vesseldata.rs index e577e57..3202bf4 100644 --- a/src/vesseldata.rs +++ b/src/vesseldata.rs @@ -4,6 +4,7 @@ use tungstenite::connect; use url::Url; use serde_json::{Result, Value}; use std::sync::mpsc::Receiver; +use std::time::Instant; // Model the data sent over SignalK Websocket // that I'm interested in