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:
2020-09-26 09:33:20 +00:00
parent 9abffb71ba
commit ea695afc99
8 changed files with 778 additions and 267 deletions

View File

@@ -1,32 +1,65 @@
use std::thread;
use std::io::{BufReader, Read};
use tungstenite::connect;
use url::Url;
use serde_json::{Result, Value};
use serde::Deserialize;
use serde_json::Value as JValue;
use std::sync::mpsc::{Sender, Receiver};
use std::sync::mpsc;
use crate::vesseldata::{VesselDataEvent, VesselDataEventSource};
// Model the data sent over SignalK Websocket
// that I'm interested in
pub enum SignalKEvent {
SpeedOverGround(f32),
SpeedThroughWater(f32),
Location(f32, f32),
CourseOverGround(f32),
TrueCompassCourse(f32),
AISVessel(String, f32, f32, f32), // Name, lat, long, speed
BatteryLevel(u8, u8), // Bank#, percentage
FuelLevel(u8), // percentage
#[derive(Debug, Deserialize)]
#[serde()]
struct Source {
sentence: String,
talker: String,
#[serde(rename = "type")]
k_type: String,
label: String,
}
pub struct SignalKData {
latitude: f32,
longitude: f32,
position_timestamp: u64,
#[derive(Debug, Deserialize)]
#[serde()]
struct Value {
path: String,
value: JValue,
}
impl SignalKData {
#[derive(Debug, Deserialize)]
#[serde()]
struct Update {
#[serde(rename = "$source")]
dsource: String,
timestamp: String,
values: Vec<Value>,
}
pub fn parseJson (json: String) -> Vec<SignalKEvent> {
let res = Vec::<SignalKEvent>::new();
#[derive(Debug, Deserialize)]
#[serde()]
struct SignalKEventData {
context: String,
updates: Vec<Update>,
}
#[derive(Debug, Deserialize)]
#[serde()]
struct SignalKHeader {
name: String,
version: String,
#[serde(rename="self")]
k_self: String,
roles: Vec<String>,
timestamp: String,
}
pub struct SignalK {
}
impl SignalK {
fn parse_json (json: String) -> Vec<SignalKEventData> {
let res = Vec::<SignalKEventData>::new();
let v: Value = match serde_json::from_str(&json) {
Ok(value) => value,
Err(_) => return res,
@@ -37,22 +70,43 @@ impl SignalKData {
res
}
pub fn connect() -> SignalKData {
let mut data = SignalKData {
latitude: f32::NAN,
longitude: f32::NAN,
position_timestamp: 0,
};
let handle = thread::spawn(|| {
fn value_to_vesseldata (val: Value) -> Option<VesselDataEvent> {
match val.path.as_str() {
"navigation.position" => return Some(VesselDataEvent::Location(val.value["latitude"].as_f64().unwrap() as f32, val.value["longitude"].as_f64().unwrap() as f32)),
"navigation.headingMagnetic" => return Some(VesselDataEvent::TrueCompassCourse(val.value.as_f64().unwrap() as f32)),
"navigation.courseOverGroundTrue" => return Some(VesselDataEvent::CourseOverGround(val.value.as_f64().unwrap() as f32)),
"navigation.speedOverGround" => return Some(VesselDataEvent::SpeedOverGround(val.value.as_f64().unwrap() as f32)),
_ => return None,
}
}
}
impl VesselDataEventSource for SignalK {
fn connect() -> Receiver<VesselDataEvent> {
let (tx, rx): (Sender<VesselDataEvent>, Receiver<VesselDataEvent>) = mpsc::channel();
let handle = thread::spawn(move || {
let (mut socket, response) = connect(Url::parse("ws://localhost:3000/signalk/v1/stream?subscribe=self").unwrap()).expect("Can't connect");
let header: SignalKHeader = serde_json::from_str(socket.read_message().unwrap().to_text().unwrap()).unwrap();
if header.version != "1.33.0" {
warn!("SignalK parser has only been tested with Signal K Server version 1.33.0");
}
loop {
let msg = socket.read_message().expect("Error reading message");
if msg.is_text() {
println!("{}", msg.into_text().unwrap());
let message = socket.read_message().unwrap();
if message.is_text() {
let data: SignalKEventData = serde_json::from_str(message.to_text().unwrap()).unwrap();
for u in data.updates {
for v in u.values {
match SignalK::value_to_vesseldata(v) {
Some(vd) => tx.send(vd).unwrap(),
_ => (),
}
}
}
}
}
});
data
rx
}
}