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:
116
src/signalk.rs
116
src/signalk.rs
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user