Skip to main content

Module units

Module units 

Source
Expand description

A mariner’s own display units, as signalk-server’s unitpreferences feature states them.

Signal K itself is SI on the wire and says nothing about how a value should be shown – that is what unitpreferences is for, a signalk-server feature (not part of the core specification, the same already-observed-convention standing this crate already gives crate::AisTargetStatus and crate::NotificationSeverity) that lets a mariner pick nautical miles, kilometres or statute miles for distance, once, on the server, for every client to honour alike.

§Why this does not read the server’s own conversion formula

GET /signalk/v1/unitpreferences/active answers with a formula and inverseFormula per category – a short expression, "value * 1.94384", meant to be evaluated. This crate deliberately never evaluates it: doing so needs a small expression interpreter, which is new conversion math of exactly the kind this workspace exists to avoid growing twice. Instead, conversions below is a table of (scale, offset) pairs – one row per target = value * scale + offset – computed once, by hand, from every formula string GET /signalk/v1/unitpreferences/definitions answered on a real signalk-server (confirmed live; see crates/signalk/testdata/unitpreferences.json, the fixture this table is checked against, and this module’s own tests). What is read from a server at runtime is only which row a mariner’s preference names – never a formula to evaluate.

§What is not covered

Every target unit signalk-server ships is in conversions, with two exceptions, both left unread the same way an unrecognised path is anywhere else in this crate – skipped, not refused:

  • Beaufort (m/s -> Bf), the one target in the entire catalogue whose own formula is not affine – (value / 0.836)^(2/3), a power law. Modelling it would mean either a second kind of table entry for one row, or the interpreter this module exists to avoid; a mariner who picks Beaufort for wind speed gets the same “not a reading this crate understands” Preferences::convert already gives any other unrecognised target.
  • Duration formatters (s -> HH:MM:SS and six siblings), which are not a numeric scale at all – formatDurationHMS(value) turns a seconds count into a clock-formatted string, which is a formatting concern, not a unit conversion, and not this module’s to grow into. The plain decimal ones (s -> hour, minute, day, …) are ordinary affine conversions and are covered.

Three base units are themselves formats rather than physical quantities – RFC 3339 (UTC) and Epoch Seconds (the dateTime/ epoch categories’ own timestamp representations) and bool (the boolean category) – each with exactly one target, itself. The target-equals-base rule Preferences::convert applies before ever consulting conversions already answers that trivially and correctly (the value passes through unchanged), without this module needing to know or care that a category is not really a measurement.

§The target-equals-base rule

A preference whose targetUnit is exactly the category’s own Signal K base unit ("m" for length, "K" for temperature, …) means “no conversion” – confirmed live: signalk-server sends that literal string, not the differently-spelled identity row its own conversions table happens to carry for some base units (m’s own identity entry is named "meter", never "m"; several base units – V, A, bool, tr, the two timestamp formats – carry no entry but their own name at all). Preferences::convert checks this before ever looking a target up in conversions, so every category has a correct identity regardless of which, if either, spelling the table itself happens to carry.

Structs§

Preferences
What a server’s unitpreferences states, as far as this crate reads it – every category category_base_unit names a Signal K base unit for, present once the server has stated a target unit this crate converts (see this module’s own top doc for the two kinds of target that leaves out), absent otherwise. Default is every category absent, which is exactly the state a caller should fall back to its own default unit for – the same value Self::parse returns for an unreadable answer.

Functions§

localized_symbol
symbol in lang’s own words, when this crate knows one – symbol unchanged otherwise, the same “unrecognised passes through” discipline Preferences::parse itself already keeps. signalk-server states every symbol in English regardless of who is reading it (confirmed live: a mariner’s own distance preference set to nautical miles comes back with "symbol":"nmi" whatever locale the request was made under) – this is the one place that turns it into something else.