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-nightswimming-logger

v0.1.1

Published

SignalK plugin that buffers vessel data offline on the boat and pushes batched samples to the NightSwimming NAS backend. Custom built for my boat.

Readme

signalk-nightswimming-logger

Plugin SignalK per il diario di bordo della barca a vela NightSwimming. Vive sul Cerbo GX, sottoscrive i path SignalK, li bufferizza in SQLite locale, e li flusha a batch verso il backend NAS NightSwimming.

Componente A) dell'architettura del diario. Vedi nightswimming-logbook-requirements.md e ADR-011 nel monorepo NightSwimming.

Filosofia

Plugin leggero per scelta progettuale. Trasporta dati, non li interpreta. Tutta la logica analitica (detection trip, classificazione stays, statistiche, reverse geocoding) sta sul NAS. Il plugin fa tre cose e basta:

  1. Subscribe ai path SignalK configurati
  2. Buffer in SQLite locale (/data/nightswimming-logger.db)
  3. Push batch HTTP al NAS quando connettività disponibile

ADR-011 vieta fork o dipendenza runtime da Saillogger. Saillogger resta come reference didattico: studiamo i loro path, le loro soglie, il loro pattern di buffer + flush, ma il codice è scritto da zero.

Installazione

Dal SignalK Admin UI (raccomandato)

  1. Builda localmente: npm install && npm run build
  2. Comprimi la cartella: npm pack produce signalk-nightswimming-logger-X.Y.Z.tgz
  3. SignalK Admin UI → AppstoreInstall local plugin → carica il .tgz

Da git clone direttamente

cd ~/.signalk/node_modules
git clone <repo-url> signalk-nightswimming-logger
cd signalk-nightswimming-logger
npm install
npm run build
# riavvia SignalK server

Nota Cerbo Venus OS: better-sqlite3 è una dipendenza nativa. I prebuild upstream coprono Linux ARM64, ma su Venus OS specifico (basato su buildroot) potrebbe servire ricompilare. Se l'install fallisce con errori di link, vedi sezione Troubleshooting.

Configurazione

Tutti i parametri sono visibili e modificabili dall'admin UI di SignalK, sotto Server → Plugin Config → NightSwimming Logger.

| Campo | Default | Note | |---|---|---| | endpointUrl | https://api.teodorolio.com/api/logbook/ingest | Backend NAS | | authToken | (vuoto) | Bearer token. Senza questo, il NAS rifiuterà i POST con 401. | | sampleIntervalSec | 30 | Snapshot ogni N secondi. Min 5. | | flushIntervalSec | 60 | Push batch ogni N secondi. Min 30. | | flushBatchSize | 200 | Punti per POST. Min 10. | | maxBufferSizeMb | 50 | Cap circular buffer SQLite. Min 10. ~30 giorni a 30s/snapshot. | | pathsToSubscribe | (8 path nautici di base) | Vedi sotto. | | pluginInstanceId | (auto) | UUID generato e persistito al primo start. |

Path sottoscritti di default

navigation.position
navigation.speedOverGround
navigation.courseOverGroundTrue
navigation.headingTrue
environment.wind.speedTrue
environment.wind.angleTrueWater
environment.depth.belowKeel
environment.outside.pressure

Path mancanti (es. niente trasduttore di profondità, vento reale che richiede signalk-derived-data) restano null nello snapshot — nessun errore. Per aggiungerne altri (RPM motore, batterie, tank levels) basta inserirli nel campo pathsToSubscribe dell'admin UI; il NAS li riceverà come campi extra nel JSON.

Come funziona

SignalK delta stream  ──►  lastValues Map (in-memory, sticky)
                                │
                                ▼  (ogni sampleIntervalSec)
                          takeSnapshot()  ──►  SQLite buffer
                                                    │
                                                    ▼  (ogni flushIntervalSec)
                                            POST /api/logbook/ingest  ──►  NAS
                                                    │
                                            errore? backoff 60→900s
                                            success? markFlushed

Il subscribe handler aggiorna una mappa in memoria lastValues ad ogni delta. Il timer di snapshot ogni N secondi prende l'ultimo valore noto di ogni path e lo scrive come singolo record nel buffer SQLite. Il flusher ogni M secondi tenta un POST batch al NAS. In caso di errore di rete, backoff esponenziale capped a 15 minuti. In caso di 4xx (richiesta malformata o auth errata) droppa il batch per non loopare e logga in modo molto visibile.

Il pluginInstanceId è un UUID generato al primo start e persistito (sia in savePluginOptions se il server lo espone, sia in instance-id.json come fallback). Serve al NAS come parte della chiave di idempotency (pluginInstanceId, ts): un batch ricevuto due volte non duplica record.

Troubleshooting

NAS unreachable, retry in N min permanente

  • Verifica connettività da Cerbo: ping <NAS hostname o IP>
  • Verifica che il NAS sia in Tailscale e raggiungibile da bordo
  • Verifica che endpointUrl sia corretto (incluso /api/logbook/ingest)
  • Verifica certificato SSL valido se usi HTTPS

Auth/payload error 401

  • Token vuoto o sbagliato. Sostituiscilo nell'admin UI e riavvia il plugin.

Auth/payload error 400

  • Il backend ha rifiutato il payload. Disallineamento di schema fra plugin e backend (probabile bug). Il batch viene droppato per non loopare; controlla i log del backend per il dettaglio dell'errore.

Buffer non si svuota mai

  • Conta righe pendenti via SQLite CLI:
    sqlite3 /path/to/nightswimming-logger.db 'SELECT COUNT(*) FROM points;'
  • Se cresce indefinitamente: il flusher è in errore. Guarda i log SignalK.

Errori di build di better-sqlite3 su Venus OS

  • Prova npm install --build-from-source better-sqlite3
  • Verifica di avere python3, make, g++ installati nell'environment di build
  • In ultima istanza, builda il .tgz su una macchina simile (Debian ARM64) e copialo sul Cerbo

Resettare l'instance ID

  • Cancella instance-id.json da app.getDataDirPath() (di solito ~/.signalk/plugin-config-data/signalk-nightswimming-logger/) e riavvia.
  • Effetto: il NAS tratterà i prossimi batch come da una nuova identità di logger. I dati esistenti restano, vengono solo deduplicati indipendentemente.

Riferimenti

  • ADR-011 in documentation/nightswimming-adr.md (monorepo NswmApp) — decisione "plugin custom da zero, no fork Saillogger"
  • Requirements completi in documentation/nightswimming-logbook-requirements.md — sezioni 3 (architettura), 4.1 (path), 6.1 (questo plugin), 6.4 (riconciliazione con Livello 3 VRM)
  • SignalK Plugin API — https://demo.signalk.org/documentation/develop/plugins/server_plugin_api.html
  • Saillogger (reference didattico, non dipendenza) — https://github.com/Saillogger/signalk-saillogger

Licenza

MIT — Teodoro Lio