Documentation
¶
Overview ¶
Package units provides type-safe unit conversion for physical quantities commonly encountered in marine (NMEA 2000) and general-purpose sensor systems.
Architecture overview:
Each physical quantity (distance, velocity, pressure, etc.) is represented by its own struct type (e.g., Distance, Velocity, Pressure) that wraps a numeric value and a unit enum. This ensures type safety at compile time -- you cannot accidentally add a Distance to a Velocity.
Most unit types use a "table-based conversion" approach (see tablebasedconversion.go) where each unit has a numeric ratio relative to a common reference unit. Conversion between any two units is done by multiplying: value * (newConv / oldConv). This works for all linear unit relationships. Temperature is the notable exception, as Fahrenheit/Celsius conversions involve offsets (not just ratios), so Temperature uses custom conversion logic.
Each unit type provides:
- A constructor (e.g., NewDistance)
- Convert() to change units
- Add() and Sub() for arithmetic that handles mixed units
- MarshalJSON() for serialization with unit type metadata
The UnitType enum is used in JSON serialization to identify which physical quantity a value represents, enabling generic handling by user interfaces, telemetry services, and stored data formats.
Relationship to PGN decoding: this package is not currently consumed by the pgn decode path. Decoded PGN struct fields hold raw wire ticks (*uint64/*int64); pgn.PhysicalValue applies a field's Resolution and Offset to produce a plain float64 physical value plus a unit string, but it does not construct units types, and no PGN struct field uses a units type. Integrating units into decoding would mean switching PGN struct fields from raw-tick integers to float-based quantities (each Unit[T] wraps a float32), which is a larger, cross-cutting change to the generated struct shapes and is deliberately deferred; for now, callers that want a units value construct one themselves from pgn.PhysicalValue's (float64, unit string) result.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrInvalidDistanceUnit = errors.New("not a valid DistanceUnit")
var ErrInvalidFlowUnit = errors.New("not a valid FlowUnit")
var ErrInvalidPressureUnit = errors.New("not a valid PressureUnit")
var ErrInvalidTemperatureUnit = errors.New("not a valid TemperatureUnit")
var ErrInvalidUnitType = errors.New("not a valid UnitType")
var ErrInvalidVelocityUnit = errors.New("not a valid VelocityUnit")
var ErrInvalidVolumeUnit = errors.New("not a valid VolumeUnit")
Functions ¶
This section is empty.
Types ¶
type Distance ¶
type Distance Unit[DistanceUnit]
Distance is a type-safe unit structure that represents a distance/length measurement. It combines a numeric value with a DistanceUnit to ensure correct unit handling.
func NewDistance ¶
func NewDistance(u DistanceUnit, value float32) Distance
NewDistance creates a new Distance value with the given unit and magnitude.
Parameters:
- u: the distance unit (Meter, Foot, Mile, NauticalMile, or Fathom)
- value: the numeric magnitude in the specified unit
func (Distance) Add ¶
Add adds another Distance to this one, returning a new Distance in this value's unit. If the other Distance is in a different unit, it is automatically converted before adding. The result preserves the receiver's unit.
func (Distance) Convert ¶
func (p Distance) Convert(newUnit DistanceUnit) Distance
Convert converts this distance value to a different distance unit, returning a new Distance. Uses the table-based conversion system (distanceConversions) for the math.
Parameters:
- newUnit: the target distance unit to convert to
Returns a new Distance in the requested unit.
func (Distance) MarshalJSON ¶
MarshalJSON implements a custom JSON marshaler that includes the UnitType discriminator. The output includes "value", "unit" (as the integer enum value), and "unitType" (as the UnitType enum value for Distance). This allows JSON consumers to identify this as a distance measurement and determine the specific unit.
type DistanceUnit ¶
type DistanceUnit int
DistanceUnit is an enum for all supported distance/length unit types. ENUM(Meter, Foot, Mile, NauticalMile, Fathom) Meter is a meter Foot is a foot Mile is a mile NauticalMile is a nautical mile Fathom is a fathom
const ( // Meter is a DistanceUnit of type Meter. Meter DistanceUnit = iota // Foot is a DistanceUnit of type Foot. Foot // Mile is a DistanceUnit of type Mile. Mile // NauticalMile is a DistanceUnit of type NauticalMile. NauticalMile // Fathom is a DistanceUnit of type Fathom. Fathom )
func DistanceUnitValues ¶
func DistanceUnitValues() []DistanceUnit
DistanceUnitValues returns a list of the values for DistanceUnit
func ParseDistanceUnit ¶
func ParseDistanceUnit(name string) (DistanceUnit, error)
ParseDistanceUnit attempts to convert a string to a DistanceUnit.
func (DistanceUnit) IsValid ¶
func (x DistanceUnit) IsValid() bool
IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values
func (DistanceUnit) String ¶
func (x DistanceUnit) String() string
String implements the Stringer interface.
type Flow ¶
Flow is a type-safe unit structure that represents a flow rate measurement (volume over time). It combines a numeric value with a FlowUnit to ensure correct unit handling. This is commonly used for fuel flow rates in marine applications.
func NewFlow ¶
NewFlow creates a new Flow value with the given unit and magnitude.
Parameters:
- u: the flow unit (LitersPerHour, GallonsPerMinute, or GallonsPerHour)
- value: the numeric magnitude in the specified unit
func (Flow) Add ¶
Add adds another Flow to this one, returning a new Flow in this value's unit. If the other Flow is in a different unit, it is automatically converted before adding. The result preserves the receiver's unit.
func (Flow) Convert ¶
Convert converts this flow value to a different flow unit, returning a new Flow. Uses the table-based conversion system (flowConversions) for the math.
Parameters:
- newUnit: the target flow unit to convert to
Returns a new Flow in the requested unit.
func (Flow) MarshalJSON ¶
MarshalJSON implements a custom JSON marshaler that includes the UnitType discriminator. The output includes "value", "unit" (as the integer enum value), and "unitType" (as the UnitType enum value for Flow). This allows JSON consumers to identify this as a flow rate measurement and determine the specific unit.
type FlowUnit ¶
type FlowUnit int
FlowUnit is an enum for all supported flow rate unit types. ENUM(LitersPerHour, GallonsPerMinute, GallonsPerHour) LitersPerHour is L/hr GallonsPerMinute is Gal/min GallonsPerHour is Gal/hr
func FlowUnitValues ¶
func FlowUnitValues() []FlowUnit
FlowUnitValues returns a list of the values for FlowUnit
func ParseFlowUnit ¶
ParseFlowUnit attempts to convert a string to a FlowUnit.
type Pressure ¶
type Pressure Unit[PressureUnit]
Pressure is a type-safe unit structure that represents a pressure measurement. It combines a numeric value with a PressureUnit to ensure correct unit handling.
func NewPressure ¶
func NewPressure(u PressureUnit, value float32) Pressure
NewPressure creates a new Pressure value with the given unit and magnitude.
Parameters:
- u: the pressure unit (Pa, Psi, or Hpa)
- value: the numeric magnitude in the specified unit
func (Pressure) Add ¶
Add adds another Pressure to this one, returning a new Pressure in this value's unit. If the other Pressure is in a different unit, it is automatically converted before adding. The result preserves the receiver's unit.
func (Pressure) Convert ¶
func (p Pressure) Convert(newUnit PressureUnit) Pressure
Convert converts this pressure value to a different pressure unit, returning a new Pressure. Uses the table-based conversion system (pressureConversions) for the math.
Parameters:
- newUnit: the target pressure unit to convert to
Returns a new Pressure in the requested unit.
func (Pressure) MarshalJSON ¶
MarshalJSON implements a custom JSON marshaler that includes the UnitType discriminator. The output includes "value", "unit" (as the integer enum value), and "unitType" (as the UnitType enum value for Pressure). This allows JSON consumers to identify this as a pressure measurement and determine the specific unit.
type PressureUnit ¶
type PressureUnit int
PressureUnit is an enum for all supported pressure unit types. ENUM(Pa, Psi, Hpa) Psi is PSI (pounds per square inch) Hpa is HectoPascals (100 Pascals) Pa is Pascals
const ( // Pa is a PressureUnit of type Pa. Pa PressureUnit = iota // Psi is a PressureUnit of type Psi. Psi // Hpa is a PressureUnit of type Hpa. Hpa )
func ParsePressureUnit ¶
func ParsePressureUnit(name string) (PressureUnit, error)
ParsePressureUnit attempts to convert a string to a PressureUnit.
func PressureUnitValues ¶
func PressureUnitValues() []PressureUnit
PressureUnitValues returns a list of the values for PressureUnit
func (PressureUnit) IsValid ¶
func (x PressureUnit) IsValid() bool
IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values
func (PressureUnit) String ¶
func (x PressureUnit) String() string
String implements the Stringer interface.
type Temperature ¶
type Temperature Unit[TemperatureUnit]
Temperature is a type-safe unit structure that represents a temperature measurement. Unlike other unit types in this package, Temperature does NOT use the table-based conversion system because temperature conversions involve offsets (not just ratios). For example, Celsius = Kelvin - 273.15 and Fahrenheit = Kelvin * 9/5 - 459.67. These cannot be expressed as simple ratio tables.
func NewTemperature ¶
func NewTemperature(u TemperatureUnit, value float32) Temperature
NewTemperature creates a new Temperature value with the given unit and magnitude.
Parameters:
- u: the temperature unit (Kelvin, Fahrenheit, or Celsius)
- value: the numeric magnitude in the specified unit
func (Temperature) Convert ¶
func (p Temperature) Convert(newUnit TemperatureUnit) Temperature
Convert converts this temperature value to a different temperature unit, returning a new Temperature.
Unlike other unit types that use table-based conversion (simple ratio multiplication), temperature conversion requires a two-step process using Kelvin as the intermediate/base unit:
- Convert the current value to Kelvin (the SI base unit for temperature)
- Convert from Kelvin to the target unit
Conversion formulas:
- Celsius to Kelvin: K = C + 273.15
- Fahrenheit to Kelvin: K = (F + 459.67) * 5/9
- Kelvin to Celsius: C = K - 273.15
- Kelvin to Fahrenheit: F = K * 9/5 - 459.67
Parameters:
- newUnit: the target temperature unit to convert to
Returns a new Temperature in the requested unit. Panics if either the current or target unit is an unknown TemperatureUnit value.
func (Temperature) MarshalJSON ¶
func (u Temperature) MarshalJSON() ([]byte, error)
MarshalJSON implements a custom JSON marshaler that includes the UnitType discriminator. The output includes "value", "unit" (as the integer enum value), and "unitType" (as the UnitType enum value for Temperature). This allows JSON consumers to identify this as a temperature measurement and determine the specific unit.
type TemperatureUnit ¶
type TemperatureUnit int
TemperatureUnit is an enum for all supported temperature unit types. ENUM(Kelvin, Fahrenheit, Celsius)
const ( // Kelvin is a TemperatureUnit of type Kelvin. Kelvin TemperatureUnit = iota // Fahrenheit is a TemperatureUnit of type Fahrenheit. Fahrenheit // Celsius is a TemperatureUnit of type Celsius. Celsius )
func ParseTemperatureUnit ¶
func ParseTemperatureUnit(name string) (TemperatureUnit, error)
ParseTemperatureUnit attempts to convert a string to a TemperatureUnit.
func TemperatureUnitValues ¶
func TemperatureUnitValues() []TemperatureUnit
TemperatureUnitValues returns a list of the values for TemperatureUnit
func (TemperatureUnit) IsValid ¶
func (x TemperatureUnit) IsValid() bool
IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values
func (TemperatureUnit) String ¶
func (x TemperatureUnit) String() string
String implements the Stringer interface.
type Unit ¶
type Unit[T ~int] struct { // Value is the numeric magnitude of the measurement in whatever unit Unit specifies. Value float32 // Unit identifies which unit the Value is expressed in (e.g., Meter, Foot, Knots, etc.). // The catalog type depends on the physical quantity (DistanceUnit, VelocityUnit, etc.). Unit T }
Unit is the generic base type that all specific unit structs (Distance, Velocity, etc.) are built from. It pairs a numeric value with a unit enum.
The type parameter T is constrained to ~int, which means it must be an int-based enum type (like DistanceUnit, VelocityUnit, etc.). This enables compile-time type safety: each physical quantity uses its own enum type, preventing accidental mixing.
type UnitType ¶
type UnitType int
UnitType is an enum that identifies the category of physical quantity (distance, flow, etc.). It is included in JSON output so consumers can determine what kind of unit a value represents without needing to know the specific unit variant.
ENUM(Distance,Flow,Pressure,Temperature,Velocity,Volume)
const ( // UnitTypeDistance is a UnitType of type Distance. UnitTypeDistance UnitType = iota // UnitTypeFlow is a UnitType of type Flow. UnitTypeFlow // UnitTypePressure is a UnitType of type Pressure. UnitTypePressure // UnitTypeTemperature is a UnitType of type Temperature. UnitTypeTemperature // UnitTypeVelocity is a UnitType of type Velocity. UnitTypeVelocity // UnitTypeVolume is a UnitType of type Volume. UnitTypeVolume )
func ParseUnitType ¶
ParseUnitType attempts to convert a string to a UnitType.
func UnitTypeValues ¶
func UnitTypeValues() []UnitType
UnitTypeValues returns a list of the values for UnitType
type Velocity ¶
type Velocity Unit[VelocityUnit]
Velocity is a type-safe unit structure that represents a speed/velocity measurement. It combines a numeric value with a VelocityUnit to ensure correct unit handling.
func NewVelocity ¶
func NewVelocity(u VelocityUnit, value float32) Velocity
NewVelocity creates a new Velocity value with the given unit and magnitude.
Parameters:
- u: the velocity unit (MetersPerSecond, Knots, Mph, or Kph)
- value: the numeric magnitude in the specified unit
func (Velocity) Add ¶
Add adds another Velocity to this one, returning a new Velocity in this value's unit. If the other Velocity is in a different unit, it is automatically converted before adding. The result preserves the receiver's unit.
func (Velocity) Convert ¶
func (p Velocity) Convert(newUnit VelocityUnit) Velocity
Convert converts this velocity value to a different velocity unit, returning a new Velocity. Uses the table-based conversion system (velocityConversions) for the math.
Parameters:
- newUnit: the target velocity unit to convert to
Returns a new Velocity in the requested unit.
func (Velocity) MarshalJSON ¶
MarshalJSON implements a custom JSON marshaler that includes the UnitType discriminator. The output includes "value", "unit" (as the integer enum value), and "unitType" (as the UnitType enum value for Velocity). This allows JSON consumers to identify this as a velocity measurement and determine the specific unit.
func (Velocity) Sub ¶
Sub subtracts another Velocity from this one, returning a new Velocity in this value's unit. If the other Velocity is in a different unit, it is automatically converted before subtracting. The result preserves the receiver's unit.
func (Velocity) TimesTime ¶
TimesTime computes a distance by multiplying this velocity by a duration in seconds. This implements the physics formula: distance = velocity * time.
The calculation works by first converting the velocity to knots, then multiplying by the time in hours (seconds / 3600) to get a distance in nautical miles. This is the natural unit pairing for marine applications: knots * hours = nautical miles.
Parameters:
- seconds: the duration in seconds to multiply by
Returns a Distance in NauticalMile units.
Example: 10 knots * 1800 seconds (30 minutes) = 5 nautical miles
type VelocityUnit ¶
type VelocityUnit int
VelocityUnit is an enum for all supported velocity/speed unit types. ENUM(MetersPerSecond, Knots, Mph, Kph)
const ( // MetersPerSecond is a VelocityUnit of type MetersPerSecond. MetersPerSecond VelocityUnit = iota // Knots is a VelocityUnit of type Knots. Knots // Mph is a VelocityUnit of type Mph. Mph // Kph is a VelocityUnit of type Kph. Kph )
func ParseVelocityUnit ¶
func ParseVelocityUnit(name string) (VelocityUnit, error)
ParseVelocityUnit attempts to convert a string to a VelocityUnit.
func VelocityUnitValues ¶
func VelocityUnitValues() []VelocityUnit
VelocityUnitValues returns a list of the values for VelocityUnit
func (VelocityUnit) IsValid ¶
func (x VelocityUnit) IsValid() bool
IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values
func (VelocityUnit) String ¶
func (x VelocityUnit) String() string
String implements the Stringer interface.
type Volume ¶
type Volume Unit[VolumeUnit]
Volume is a type-safe unit structure that represents a volume/capacity measurement. It combines a numeric value with a VolumeUnit to ensure correct unit handling.
func NewVolume ¶
func NewVolume(u VolumeUnit, value float32) Volume
NewVolume creates a new Volume value with the given unit and magnitude.
Parameters:
- u: the volume unit (Liter, MetersCubed, or Gallon)
- value: the numeric magnitude in the specified unit
func (Volume) Add ¶
Add adds another Volume to this one, returning a new Volume in this value's unit. If the other Volume is in a different unit, it is automatically converted before adding. The result preserves the receiver's unit.
func (Volume) Convert ¶
func (p Volume) Convert(newUnit VolumeUnit) Volume
Convert converts this volume value to a different volume unit, returning a new Volume. Uses the table-based conversion system (volumeConversions) for the math.
Parameters:
- newUnit: the target volume unit to convert to
Returns a new Volume in the requested unit.
func (Volume) MarshalJSON ¶
MarshalJSON implements a custom JSON marshaler that includes the UnitType discriminator. The output includes "value", "unit" (as the integer enum value), and "unitType" (as the UnitType enum value for Volume). This allows JSON consumers to identify this as a volume measurement and determine the specific unit.
type VolumeUnit ¶
type VolumeUnit int
VolumeUnit is an enum for all supported volume/capacity unit types. ENUM(Liter, MetersCubed, Gallon)
const ( // Liter is a VolumeUnit of type Liter. Liter VolumeUnit = iota // MetersCubed is a VolumeUnit of type MetersCubed. MetersCubed // Gallon is a VolumeUnit of type Gallon. Gallon )
func ParseVolumeUnit ¶
func ParseVolumeUnit(name string) (VolumeUnit, error)
ParseVolumeUnit attempts to convert a string to a VolumeUnit.
func VolumeUnitValues ¶
func VolumeUnitValues() []VolumeUnit
VolumeUnitValues returns a list of the values for VolumeUnit
func (VolumeUnit) IsValid ¶
func (x VolumeUnit) IsValid() bool
IsValid provides a quick way to determine if the typed value is part of the allowed enumerated values
func (VolumeUnit) String ¶
func (x VolumeUnit) String() string
String implements the Stringer interface.