Major rewrites, signalk support almost there
Font and forms refactored, but not working yet, will explore Rusttype lifetime issues in seperate project
This commit is contained in:
175
src/main.rs
175
src/main.rs
@@ -6,7 +6,11 @@ use std::time::Duration;
|
||||
use std::f32::consts::PI;
|
||||
use chrono::{DateTime, Utc};
|
||||
use chrono_tz::Tz;
|
||||
use rusttype::Font;
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
use log4rs;
|
||||
|
||||
use image::{
|
||||
Rgb,
|
||||
@@ -18,12 +22,134 @@ use imageproc::drawing::draw_filled_rect_mut;
|
||||
mod ilidisplay;
|
||||
mod forms;
|
||||
mod signalk;
|
||||
mod vesseldata;
|
||||
use vesseldata::VesselDataEventSource;
|
||||
|
||||
pub struct HelmsDisplay {
|
||||
font: Box<Font<'static>>,
|
||||
boat: forms::Form,
|
||||
compassrose: forms::Form,
|
||||
cog: forms::Form,
|
||||
wind: forms::Form,
|
||||
gps_screen: forms::Screen,
|
||||
time_screen: forms::Screen,
|
||||
course_screen: forms::Screen,
|
||||
}
|
||||
|
||||
impl HelmsDisplay {
|
||||
|
||||
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());
|
||||
let boat = loader.load_form("boat.svg").unwrap();
|
||||
let compassrose = loader.load_form("compass-rose.svg").unwrap();
|
||||
let cog = loader.load_form("cog.svg").unwrap();
|
||||
let wind = loader.load_form("wind.svg").unwrap();
|
||||
let f = loader.load_font("font.ttf").unwrap();
|
||||
let font = Box::new(f);
|
||||
|
||||
HelmsDisplay {
|
||||
font: font,
|
||||
boat: boat,
|
||||
compassrose: compassrose,
|
||||
cog: cog,
|
||||
wind: wind,
|
||||
gps_screen: forms::Screen::new(400, 40),
|
||||
time_screen: forms::Screen::new(200, 60),
|
||||
course_screen: forms::Screen::new(200, 200),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_gps (&mut self, loc: Option<vesseldata::VesselDataEvent>) {
|
||||
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);
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_time (&mut self) {
|
||||
let tz: Tz = "Europe/Copenhagen".parse().unwrap();
|
||||
let now = Utc::now().with_timezone(&tz);
|
||||
self.time_screen.text_c(&self.font, now.format("%H:%M:%S %Z").to_string().as_str(), 24.0, 100, 1);
|
||||
self.time_screen.text_c(&self.font, "Europe/Copenhagen", 16.0, 100, 25);
|
||||
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<vesseldata::VesselDataEvent>, magnetic: Option<vesseldata::VesselDataEvent>, wind: Option<vesseldata::VesselDataEvent>) {
|
||||
let rad = (6 as f32) * 2.0*PI / 100.0;
|
||||
self.course_screen.clear();
|
||||
|
||||
// render course over ground if present
|
||||
match cog {
|
||||
Some(vesseldata::VesselDataEvent::CourseOverGround(c)) => {
|
||||
self.course_screen.render(&self.cog, c, 500, 500);
|
||||
},
|
||||
_ => (),
|
||||
};
|
||||
|
||||
// render wind if present
|
||||
match wind {
|
||||
Some(vesseldata::VesselDataEvent::WindOrigin(o)) => {
|
||||
self.course_screen.render(&self.wind, o, 500, 500);
|
||||
},
|
||||
_ => (),
|
||||
};
|
||||
|
||||
// render compass rose
|
||||
|
||||
self.course_screen.render(&self.compassrose, rad, 500, 500);
|
||||
self.course_screen.render(&self.boat, 0.0, 500, 500);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
|
||||
// init log library
|
||||
log4rs::init_file("log4rs.yml", Default::default()).unwrap();
|
||||
|
||||
let mut course_screen = forms::Screen::new(200, 200);
|
||||
let mut sog_screen = forms::Screen::new(160,60);
|
||||
let mut gps_screen = forms::Screen::new(400, 40);
|
||||
let mut time_screen = forms::Screen::new(200, 60);
|
||||
|
||||
let mut loader = forms::Loader::new("/root/helms-display".to_string());
|
||||
@@ -32,8 +158,10 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
let b = loader.load_form("boat.svg").unwrap();
|
||||
let cog = loader.load_form("cog.svg").unwrap();
|
||||
let wind = loader.load_form("wind.svg").unwrap();
|
||||
let font = loader.load_font("font.ttf").unwrap();
|
||||
//let font = loader.load_font("font.ttf").unwrap();
|
||||
let f2 = loader.load_font("font.ttf").unwrap();
|
||||
|
||||
let mut helms = HelmsDisplay::new();
|
||||
/*
|
||||
let mut img = RgbImage::new(480, 320);
|
||||
let thickness = 10;
|
||||
@@ -54,8 +182,9 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
course_screen.render(&wind, rad*2.0, 500, 500);
|
||||
course_screen.render(&c, rad, 500, 500);
|
||||
course_screen.render(&b, 0.0, 500, 500);
|
||||
e.put_image(&(course_screen.image), (160, (160-100)));
|
||||
e.put_image(&(course_screen.image), (140, (160-110)));
|
||||
|
||||
/*
|
||||
sog_screen.clear();
|
||||
sog_screen.text(&font, "SOG", 32.0, 5, 5);
|
||||
sog_screen.text(&font, "speed over ground", 12.0, 5, 38);
|
||||
@@ -63,41 +192,21 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
let speed_over_ground = speed_over_ground * 1.9438612860586; // now in nautic miles per hour
|
||||
sog_screen.text_rj(&font, format!("{:.1}", speed_over_ground).as_str(), 32.0, 138, 5);
|
||||
sog_screen.fraction(&font, "nm", "h", 14.0, 140, 6);
|
||||
e.put_image(&(sog_screen.image), (0, 0));
|
||||
e.put_image(&(sog_screen.image), (0, 50));
|
||||
*/
|
||||
|
||||
gps_screen.clear();
|
||||
// format with unicodes for degrees, minutes and seconds.
|
||||
let longitude: f32 = 55.658863;
|
||||
let latitude: f32 = 12.480960;
|
||||
helms.render_gps(None);
|
||||
e.put_image(&(helms.gps_screen.image), (40,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 long_ns: char = 'N';
|
||||
|
||||
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;
|
||||
let lat_ew: char = 'E';
|
||||
gps_screen.text_c(&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);
|
||||
e.put_image(&(gps_screen.image), (240,370));
|
||||
|
||||
time_screen.clear();
|
||||
let tz: Tz = "Europe/Copenhagen".parse().unwrap();
|
||||
let now = Utc::now().with_timezone(&tz);
|
||||
time_screen.text_c(&font, now.format("%H:%M:%S %Z").to_string().as_str(), 24.0, 100, 1);
|
||||
time_screen.text_c(&font, "Europe/Copenhagen", 16.0, 100, 25);
|
||||
time_screen.text_c(&font, now.format("%Y-%m-%d").to_string().as_str(), 16.0, 100, 43);
|
||||
time_screen.save();
|
||||
helms.render_time();
|
||||
e.put_image(&(helms.time_screen.image), (140,260));
|
||||
|
||||
|
||||
println!("Display has been rendered now, sleeping for 5s");
|
||||
signalk::SignalKData::connect();
|
||||
thread::sleep(Duration::from_millis(5000));
|
||||
let vd = signalk::SignalK::connect();
|
||||
|
||||
thread::sleep(Duration::from_millis(15000));
|
||||
e.turn_off();
|
||||
Ok(())
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user