npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@signalk/nmea0183-utilities

v1.1.1

Published

Various utilities for transforming NMEA0183 units into SI units for use in SK.

Readme

@signalk/nmea0183-utilities

CI npm version License

Small, strictly-typed TypeScript helpers for parsing NMEA 0183 sentences into Signal K-flavoured SI units. Used under the hood by @signalk/nmea0183-signalk and available standalone for plugin authors.

Installation

npm install @signalk/nmea0183-utilities

Requires Node >=22.

Quick tour

import utils from '@signalk/nmea0183-utilities'
// Or: const utils = require('@signalk/nmea0183-utilities')
// Or: import { valid, transform, coordinate } from '@signalk/nmea0183-utilities'

// 1. Validate a sentence and its *XX checksum
utils.valid('$GPBOD,045.,T,023.,M,DEST,START*01') // -> true
utils.valid('$GPBOD,045.,T,023.,M,DEST,START*AA') // -> false (bad checksum)
utils.valid('$GPBOD,045.,T,023.,M,DEST,START', false) // -> true (skip checksum)

// 2. Compute and append a *XX checksum
utils.appendChecksum('$GPBOD,045.,T,023.,M,DEST,START')
// -> '$GPBOD,045.,T,023.,M,DEST,START*01'

// 3. Convert between units (SI-first)
utils.transform(10, 'knots', 'ms') // -> 5.144... m/s
utils.transform(100, 'c', 'k') // -> 373.15 K
utils.transform(33, 'ft', 'm') // -> 10.058... m

// 4. Parse a latitude/longitude pair
utils.coordinate('5222.3277', 'N') // -> 52.372128... (decimal degrees)
utils.coordinate('00454.5824', 'W') // -> -4.909706... (W/S negative)

// 5. Sanity-check a position
utils.isValidPosition(52.37, -4.91) // -> true
utils.isValidPosition(NaN, 0) // -> false

// 6. Build an ISO-8601 timestamp from NMEA time (HHMMSS[.FFF]) + date (DDMMYY)
utils.timestamp('173456.75', '050426') // -> '2026-04-05T17:34:56.750Z'
utils.timestamp() // -> current UTC as ISO string

// 7. Decode a magnetic-variation field
utils.magneticVariation(3.5, 'E') // -> 3.5    (east positive)
utils.magneticVariation(3.5, 'W') // -> -3.5   (west negative)

// 8. Build the `source` object Signal K deltas expect
utils.source('GPGGA')
// -> { type: 'NMEA0183', label: 'signalk-parser-nmea0183', sentence: 'GPGGA' }

API

All functions are named exports; a default export aggregates them so import utils from '@signalk/nmea0183-utilities' works as well.

Validation

valid(sentence, validateChecksum?) => boolean

Returns true if sentence looks like a well-formed NMEA 0183 frame. Requires a $ or ! prefix and, when validateChecksum is true (the default), a matching *XX checksum suffix. Pass false to accept prefix-only frames.

appendChecksum(sentence) => string

Returns sentence with a computed *XX suffix appended, uppercase hex, zero-padded. Returns the input unchanged if it already contains *, doesn't start with $/!, or is an unsupported shape.

Unit conversion

transform(value, from, to) => number

Converts value between the units below. value may be a number or a numeric string (it's coerced via float). from and to are typed as UnitFormat and are case-sensitive in TypeScript callers — pass an unknown pair and it throws unsupported conversion: <from> -> <to>.

| Family | Units | | ----------- | --------------------------- | | Distance | km, nm, m, ft, fa | | Speed | knots, kph, ms, mph | | Angle | deg, rad | | Temperature | c, k, f |

All combinations within each family are supported. Same-unit transform(x, 'm', 'm') short-circuits.

RATIOS

The lookup table used internally — exported for downstream code that needs the raw constants (e.g. RATIOS.NM_IN_KM === 1.852).

Coordinates & position

coordinate(value, pole) => number

Parses an NMEA coordinate (DDDMM.MMMM, DDMM.MMMM) to decimal degrees. pole is a Pole ('N' | 'S' | 'E' | 'W', uppercase only per IEC 61162-1). 'S' and 'W' flip the sign. Unknown pole letters throw unsupported pole: <value>.

isValidPosition(latitude, longitude) => boolean

true iff both inputs are finite numbers within [-90, 90] / [-180, 180]. Rejects NaN and ±Infinity.

magneticVariation(degrees, pole) => number

degrees is the magnitude; pole is a Pole. East is positive, West is negative; 'N' | 'E' pass through, 'S' | 'W' negate. Unknown pole letters throw.

Timestamp

timestamp(time?, date?) => string

Assembles an ISO-8601 UTC string from the two fields NMEA sentences carry.

  • time is HHMMSS with an optional fractional tail (HHMMSS.sss). The first three digits of the tail become milliseconds; extra digits are truncated, a missing or non-digit tail falls through to .000Z. When omitted, the current wall-clock time is used.
  • date is DDMMYY. 2-digit years follow IEC 61162-1: YY < 8020YY, YY >= 8019YY. When omitted, today's UTC date is used.

Sentence metadata

source(sentence?) => SignalKSource

Returns the source sub-object Signal K deltas expect:

{ type: 'NMEA0183', label: 'signalk-parser-nmea0183', sentence: <sentence> }

sentence defaults to '' when the argument is falsy.

Numeric parsing

int(n) => number

parseInt(n, 10) that returns 0 instead of NaN when the input doesn't parse. Accepts unknown so int(null), int(undefined), int('abc'), int(NaN) all return 0.

float(n) => number

Same idea for parseFloat. Accepts numbers or numeric strings. Returns 0.0 on parse failure.

intOrNull(n) => number | null / floatOrNull(n) => number | null

Null-preserving variants of int / float. An NMEA 0183 null field (IEC 61162-1 §7.2.3.4) signals "sensor working, value not available" and must not be confused with a legitimate zero. intOrNull(''), intOrNull(null), intOrNull('abc') all return null; intOrNull('0') returns 0. Prefer these over int/float when the caller wants to pass the not-available semantic through to Signal K (which treats null the same way).

transformOrNull(value, from, to) => number | null

Null-short-circuiting unit conversion. Identical to transform for real input; returns null when value is empty / null / undefined / non-numeric. Unsupported unit pairs still throw — the null short-circuit runs first, so a missing field with an unknown unit pair is still null, not an error.

magneticVariationOrNull(degrees, pole) => number | null

Null-preserving magnetic variation. Returns null when degrees or pole is missing or unparseable (including unknown / lowercase pole letters), rather than throwing or silently returning 0. 0 with a valid pole returns 0, not null.

zero(n) => string

Width-2 left-pad for integer date/time components. zero(2) === '02', zero(42) === '42', zero(-5) === '-05'. Throws TypeError on non-finite or non-integer input — feed it Math.trunc(n) if you have a float.

TypeScript

Full types ship in the package. The useful ones:

import type {
  UnitFormat, // 'km' | 'nm' | 'm' | 'ft' | 'fa' | 'knots' | ... | 'c' | 'k' | 'f'
  Pole, // 'N' | 'S' | 'E' | 'W'
  SignalKSource
} from '@signalk/nmea0183-utilities'

Both named and default imports are supported; the default is a plain object whose keys are the named exports.

License

Apache-2.0. See LICENSE.