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-sailorwind-plugin

v0.3.0

Published

SignalK server plugin that pushes weather observations to sailorwind.net

Readme

signalk-sailorwind-plugin

A SignalK server plugin that pushes weather observations from a boat's SignalK server to the sailorwind marine-weather observation service. Once installed and configured with a device token, it aggregates the last 10 minutes of wind / pressure / temperature / humidity samples for the self vessel and POSTs them — fully offline-tolerant, with a persistent retry queue so a flaky cellular link doesn't drop data.

Prerequisites

  • A SignalK Node server (>= v1.x). Tested against the standard appstore install.
  • A sailorwind account.
  • A device token — generate one at https://sailorwind.net/settings/api-tokens. Tokens are prefixed slw_dev_ and should be treated as secrets.

Install

In the SignalK admin UI:

  1. Open the Appstore tab.
  2. Search for sailorwind.
  3. Click Install on signalk-sailorwind-plugin.
  4. Open the Server → Plugin Config tab and find sailorwind weather submission.

Or from the command line on the SignalK server host:

cd ~/.signalk
npm install signalk-sailorwind-plugin
# then restart the SK server

Configure

In Server → Plugin Config → sailorwind weather submission:

| Field | Notes | | --- | --- | | sailorwind API base URL | Default https://sailorwind.net. Leave as-is unless you've been told otherwise (e.g. during a private test deployment). | | Device token | Paste the slw_dev_... value from the sailorwind settings page. Treat as a secret. | | Fields to submit | Check the boxes for the observations you want to share. Position is always included — it's required by the API and is what makes an observation useful. |

Hit Submit, then toggle the plugin Enabled.

What gets sent

Every 10 minutes (not user-configurable in v1), the plugin computes one aggregated observation from the samples received during the window and POSTs it to /v1/observations:

  • position — latest GPS fix in the window (from navigation.position)
  • wind speed — arithmetic mean of environment.wind.speedTrue (m/s)
  • wind gust — max of environment.wind.speedTrue over the window
  • wind direction — a true compass bearing the wind is from (degrees TRUE, meteorological convention), resolved from whatever your stack publishes (see below)
  • pressure — latest environment.outside.pressure (Pa → hPa)
  • air temp — latest environment.outside.temperature (K → °C)
  • water temp — latest environment.water.temperature (K → °C)
  • humidity — latest environment.outside.humidity (0..1 → %)

How wind direction is resolved

Boats expose wind direction in different shapes, so the plugin tries, in order, and stops at the first that works — using the least derivation possible and trusting any value you already provide:

  1. environment.wind.directionTrue — used directly.
  2. environment.wind.directionMagnetic + magnetic variation → true.
  3. A true wind angle off the bow (environment.wind.angleTrueWater / …Damped) + boat heading → true bearing. Each wind sample is paired with the nearest-in-time heading, so a mid-window tack is handled correctly.

Heading comes from navigation.headingTrue if present, otherwise navigation.headingMagnetic lifted to true. Magnetic variation comes from navigation.magneticVariation if your GPS publishes it, otherwise it is computed from your position and the date using the World Magnetic Model (WMM2025) — so no manual variation input is ever required.

If a window genuinely yields no resolvable true direction (e.g. a wind angle but no heading source at all), the plugin skips that submission rather than send an un-renderable, direction-less observation. It never substitutes a forecast or guessed direction. Enable both wind speed and wind direction in the config — the server requires both on every observation.

Offline behaviour

  • Observations are queued to a JSON file under the plugin's data directory (~/.signalk/plugin-config-data/sailorwind/queue.json on a typical install).
  • Up to 100 entries (~16 hours of submissions at 10-minute cadence) are buffered. When the cap is hit, oldest entries are dropped first.
  • On reconnect, the queue drains FIFO at the next 10-minute tick.
  • Each entry carries a stable idempotency key, so a retry after a successful-but-unack'd send is deduped server-side.

Status

The status line in the plugin admin UI tells you everything:

  • Awaiting first submission — plugin is up but the first 10-minute window hasn't fired yet.
  • Last sent 2 min ago • queue: 0 — healthy; data is reaching sailorwind.
  • Last sent 47 min ago • queue: 5 — queue is growing; the API is unreachable (offline, DNS, TLS, or server outage). Will drain on reconnect.
  • Misconfigured: missing apiToken — token is empty; paste your device token.

Troubleshooting

Where are the plugin logs?

SignalK writes plugin logs to its main log (commonly ~/.signalk/signalk-server.log or via journalctl -u signalk on a service install). Look for lines starting with sailorwind.

permanent 401 dropping entry

The API rejected your token. Most common causes:

  • Token typo on paste (extra space, missing prefix).
  • Token was revoked in the sailorwind UI.
  • Token belongs to a different account than the vessel you're trying to submit for.

Generate a fresh token at https://sailorwind.net/settings/api-tokens and paste it in.

permanent 400

The server rejected the body shape. Usually means a value is out of range (e.g. wind speed > 100 m/s from a stuck anemometer). The full error body is logged. Check your sensors.

network error, will retry

Transient — the plugin couldn't reach the server. It will retry at the next 10-minute tick. No action needed; check connectivity if it persists.

Submission cadence is wrong for me

The 10-minute cadence is fixed in v1. The aggregation window matches sailorwind's grid coarsening — sending faster doesn't get you finer-grained data on the map.

Data, privacy, and license

Observations submitted via this plugin are public data on sailorwind, subject to position coarsening as described in the sailorwind data license. The plugin itself transmits only what you opted into via the Fields to submit checkboxes, plus position (always required) and an observation timestamp.

The device token is stored in plain text in your SignalK server's config (the same place every other SK plugin stores its config). Don't share screenshots of your plugin-config UI with the token visible.

Internal dependency

This plugin imports its aggregation / submission pipeline from the sibling internal package sailorwind-integration-core (the same code path the upcoming Capacitor mobile wrap will use). The dep is wired via file:../shared for monorepo dev; for an npm release the shared lib is bundled into the plugin's dist/ before publish. End users installing from the SignalK appstore don't need to know it's there.

License

Apache-2.0. See LICENSE or https://www.apache.org/licenses/LICENSE-2.0.

Homepage

https://sailorwind.net