Expand description
Signal K deltas in and out of the KINAVIS navigation crates.
A Signal K server merges a vessel’s NMEA 0183,
NMEA 2000 and AIS into one JSON model and streams changes as deltas. This
crate reads those deltas into a Picture of own vessel and every
target, and a Watch assesses the picture: CPA and TCPA of each target
(kinavis-traffic), and for a dangerous or developing approach the
COLREGs ruling (kinavis-colregs): the encounter, who gives way and what
each may do. The results go back to the server as
navigation.closestApproach deltas in each target’s context and as
notifications on own vessel.
Signal K units are SI: radians, metres, metres per second. The crate converts at the boundary; everything inside is KINAVIS types.
use kinavis_signalk::{parse_timestamp, Emission, Level, Watch, WatchConfig};
let mut watch = Watch::new(WatchConfig::default());
// Own vessel steering north at 6 knots (3.087 m/s)...
watch.ingest(r#"{"context":"vessels.self","updates":[{"timestamp":"2026-09-25T12:00:00Z","values":[
{"path":"navigation.position","value":{"latitude":53.0,"longitude":5.0}},
{"path":"navigation.courseOverGroundTrue","value":0.0},
{"path":"navigation.speedOverGround","value":3.087}]}]}"#)?;
// ...and a motor vessel a mile and a half north and east, steering west at 6 knots.
watch.ingest(r#"{"context":"vessels.urn:mrn:imo:mmsi:244000001","updates":[{"timestamp":"2026-09-25T12:00:00Z","values":[
{"path":"","value":{"name":"ANNA"}},
{"path":"navigation.position","value":{"latitude":53.025,"longitude":5.04155}},
{"path":"navigation.courseOverGroundTrue","value":4.712389},
{"path":"navigation.speedOverGround","value":3.087},
{"path":"navigation.state","value":"motoring"}]}]}"#)?;
let now = parse_timestamp("2026-09-25T12:00:01Z").unwrap();
let (reports, emissions) = watch.assess(now);
assert_eq!(reports[0].level, Level::Alarm);
let Some(Emission::Notification { path, value }) = emissions.last() else { panic!() };
assert_eq!(path, "notifications.navigation.closestApproach.urn:mrn:imo:mmsi:244000001");
assert_eq!(value["state"], "alarm");
assert!(value["message"].as_str().unwrap().contains("give way (Rule 15)"));Requires the standard library: JSON, and a picture as large as the server’s.
Structs§
- Delta
- One delta message.
- Instant
- The clock
Watch::assesstakes. Instant on one time scale, nanosecond resolution. - Path
Value - A value at a path.
- Picture
- Every vessel seen, by context.
- Target
Report - One target’s assessment.
- Update
- Values from one source at one time.
- Utc
- The clock
Watch::assesstakes. Coordinated Universal Time, with leap seconds. - Vessel
State - Last known state of one vessel.
- Watch
- The watch: the picture, and the level each target’s notification stands at.
- Watch
Config - Watch settings: vessel decisions, with defaults for a small vessel in
open water. Read from the plugin configuration,
camelCase.
Enums§
- Category
- What a vessel is, for the steering rules.
- Emission
- What to send to the server after an assessment.
- Level
- Severity of a target’s approach, as a Signal K notification state.
Constants§
- NOTIFICATION_
PATH - Path of the notification for a target, followed by
.and the target’s context withoutvessels.. - SELF_
CONTEXT - Context of own vessel in Signal K.
Functions§
- message
- Notification text: the approach, and the ruling if there is one.
- parse_
timestamp - Instant of a Signal K timestamp;
Noneif it is not one.