signalk-chiplog 2.5.1 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,64 @@ All notable changes to Chiplog are documented here. The format follows
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [2.7.0] - 2026-09-22
10
+
11
+ ### Added
12
+
13
+ - **Heading changes are logged automatically.** A turn of 30° or more (configurable), held steady for a minute above 2
14
+ knots, is added to the timeline as the average heading it settled on. Can be turned off in settings.
15
+
16
+ - **The retrospective analysis can read the Signal K History API.** Instead of connecting to an InfluxDB 1.x database
17
+ itself, Chiplog can now read whichever history provider the server has registered — signalk-to-influxdb2, QuestDB,
18
+ TimescaleDB — with no database credentials to set. Pick it with **History source** in the settings; InfluxDB 1.x stays
19
+ the default, so an existing installation is untouched.
20
+ - **Engine and sail segments are reconstructed from an InfluxDB 1.x history too.** The retrospective analysis read the
21
+ engine RPMs but never listed the boat's engines, so a reconstructed passage carried no propulsion segment and no
22
+ engine hours.
23
+
24
+ ### Changed
25
+
26
+ - **The 3D animation starts on the medium boat size.** The 3D view opened with the smallest of the three; it now opens
27
+ on the middle one, where the boat is large enough to be read. **Boat size** still offers all three.
28
+
29
+ - **The 3D animation's boat is drawn as a cartoon.** The generated sailboat has been rebuilt: a fuller hull with a
30
+ proper sheer and overhangs, a planked deck with a covering board, a coachroof with portholes, a cockpit with a crew on
31
+ the weather rail, a roached mainsail with a stripe and a burgee at the masthead — all in flat colours with an inked
32
+ silhouette, so it still reads when the boat is only a hundred pixels long. Nothing changes for a crew who load their
33
+ own `.glb`.
34
+
35
+ - **`navigation.state` is followed whatever its source.** Chiplog no longer prefers signalk-autostate's value over
36
+ another source of the same path: it uses the one Signal K resolves the path to. On a boat where the AIS transponder
37
+ and signalk-autostate both publish it, which one wins is settled in the server's source priorities — that is also
38
+ where a transponder left at "under way using engine" while moored is corrected.
39
+
40
+ ## [2.6.0] - 2026-09-20
41
+
42
+ ### Changed
43
+
44
+ - **The animation's date range is kept in the address.** Picking a period updates the page's URL, so reloading the page
45
+ or sharing the link keeps the same dates.
46
+ - **The boat no longer disappears when a passage leaves from where the last one arrived.** There is then no camera move
47
+ at all: the boat stays in the frame through the short rest and the next passage starts from it. It is still hidden
48
+ while the camera flies between two different places.
49
+ - **The animation opens and closes on the whole navigation.** It starts on a view of everything that will be sailed,
50
+ zooms down to the first position in two seconds, and after the last arrival pulls back out to the whole navigation in
51
+ two seconds, the boat not drawn during either move: it appears where the sailing begins. The rest at the end of each
52
+ passage is shortened to a beat (0.3 s at ×1), so the boat no longer stands still for a second or more between
53
+ passages.
54
+
55
+ ### Added
56
+
57
+ - **A 3D view of the animation.** The Animation page has a new _View_ switch: the same film, at the map's own scale and
58
+ with north at the top, seen by a camera tilted down onto a 3D sailboat, with the map laid flat under it. The boat
59
+ follows the general direction of the track rather than every sampled heading, yet turns with it at a tack or a
60
+ headland, heels and trims its sails to the wind, rides the waves with a pitch and a light roll, and you can frame it
61
+ closer or wider than the map and choose the boat's size. Load your own boat as a `.glb` file and it is used instead —
62
+ with its sails trimmed to the wind too, if their nodes are named `Mainsail` and `Jib` (the README has a guide to
63
+ preparing a model) — kept in that browser. **Export the video** films whichever view is showing (`-3d` in the file
64
+ name). The 3D view needs WebGL 2 and is loaded only when asked for; without it, the map view is used. It adds three.js
65
+ to the vendored libraries (about 600 KB, MIT).
66
+
9
67
  ## [2.5.1] - 2026-09-19
10
68
 
11
69
  ### Fixed
@@ -325,7 +383,9 @@ First release.
325
383
  - REST API under `/plugins/signalk-chiplog/api`, documented in [docs/API.md](docs/API.md).
326
384
  - Single SQLite database through Node's built-in `node:sqlite`: no native module to build.
327
385
 
328
- [Unreleased]: https://github.com/ricard33/signalk-chiplog/compare/v2.5.1...HEAD
386
+ [Unreleased]: https://github.com/ricard33/signalk-chiplog/compare/v2.7.0...HEAD
387
+ [2.7.0]: https://github.com/ricard33/signalk-chiplog/compare/v2.6.0...v2.7.0
388
+ [2.6.0]: https://github.com/ricard33/signalk-chiplog/compare/v2.5.1...v2.6.0
329
389
  [2.5.1]: https://github.com/ricard33/signalk-chiplog/compare/v2.5.0...v2.5.1
330
390
  [2.5.0]: https://github.com/ricard33/signalk-chiplog/compare/v2.4.0...v2.5.0
331
391
  [2.4.0]: https://github.com/ricard33/signalk-chiplog/compare/v2.3.1...v2.4.0
package/README.md CHANGED
@@ -8,7 +8,7 @@ sensors cannot know from a tablet at the helm: manoeuvres, notes and handwriting
8
8
  such as a lock or a lunch anchorage.
9
9
  - **GPS track**, distance, time under engine and under sail.
10
10
  - **Hourly instrument readings**, as on a paper log, plus readings at departure, arrival and each manoeuvre.
11
- - **Automatic events**: alarms, autopilot changes, strong wind, falling barometer.
11
+ - **Automatic events**: alarms, autopilot changes, strong wind, falling barometer, held heading changes.
12
12
  - **Departure and arrival names**, looked up online and corrected once for good.
13
13
  - **Consultation webapp**: logbook by day, map, timeline, corrections, export.
14
14
  - **Replay a range of passages** on the map — an hour of sailing per second — and save it as an MP4 for a phone, a
@@ -87,9 +87,9 @@ A **passage** is one logbook entry: from leaving a berth or anchorage to arrivin
87
87
  which carries on once the boat moves.
88
88
  - **Power cuts and restarts.** If the server comes back after the boat has been still for longer than the tolerance, the
89
89
  passage is closed at its last movement. A short restart carries on with the same passage.
90
- - **Under way or stopped** comes from `navigation.state` when signalk-autostate provides it. Otherwise Chiplog averages
91
- speed over ground over 3 minutes: under way above 1 knot, stopped below half a knot. This keeps a boat swinging at
92
- anchor from starting passages.
90
+ - **Under way or stopped** comes from `navigation.state` when something publishes it — signalk-autostate, typically.
91
+ Otherwise Chiplog averages speed over ground over 3 minutes: under way above 1 knot, stopped below half a knot. This
92
+ keeps a boat swinging at anchor from starting passages.
93
93
 
94
94
  A passage that was split in two — a stop just longer than the tolerance, for instance — can be merged back from the
95
95
  logbook webapp. The stop the merge folds away is kept on the timeline as its own line, naming the place, since it would
@@ -131,6 +131,8 @@ Added to the timeline without anyone touching anything:
131
131
  - **Wind** — true wind, averaged over 2 minutes, rising above 20 and 30 knots and falling back below them
132
132
  (configurable).
133
133
  - **Barometer** — a fall of 4 hPa or more over 3 hours (configurable).
134
+ - **Heading changes** — a turn of 30° or more, held steady for a minute, above 2 knots (configurable, and can be turned
135
+ off).
134
136
 
135
137
  An alarm at anchor between two passages goes to the passage that ended there, as long as the boat is within 1 nautical
136
138
  mile of that arrival.
@@ -227,13 +229,19 @@ Open **Chiplog** from the Signal K webapps, or `/signalk-chiplog/`. Reading need
227
229
  distance and time, the flags of the countries visited, and the top 5 passages by duration, distance, average speed,
228
230
  top speed and wind. Countries come from the place names, so they need geocoding enabled and the boat online now and
229
231
  then; places named before this existed fill in by themselves.
230
- - **Animation** — pick a period and every passage in it replays on the map, one after another, the port time skipped.
231
- The map follows the boat at a scale chosen for each passage — a short hop kept readable rather than magnified, a long
232
- crossing allowed a wider view but never so wide the boat crawls across empty water — while a bubble shows the speed,
233
- the distance covered since the start and the date. Play, pause and a slider over the animation's own time, at ×0,5,
234
- ×1, ×2 or ×4. **Export MP4** saves it as a video in one of five shapes (Mobile 9:16, Portrait 3:4, Square 1:1,
235
- Landscape 4:3, Widescreen 16:9). Everything happens in the browser: nothing is rendered or encoded on the Signal K
236
- server, and the map tiles are the only thing downloaded.
232
+ - **Animation** — pick a period (kept in the page's address, so a reload or a shared link keeps it) and every passage in
233
+ it replays on the map, one after another, the port time skipped. The film opens on the whole navigation and zooms down
234
+ to the first position in two seconds, and pulls back out to the whole navigation at the end. The map follows the boat
235
+ at a scale chosen for each passage — a short hop kept readable rather than magnified, a long crossing allowed a wider
236
+ view but never so wide the boat crawls across empty water — while a bubble shows the speed, the distance covered since
237
+ the start and the date. Play, pause and a slider over the animation's own time, at ×0,5, ×1, ×2 or ×4. **Export MP4**
238
+ saves it as a video in one of five shapes (Mobile 9:16, Portrait 3:4, Square 1:1, Landscape 4:3, Widescreen 16:9).
239
+ Everything happens in the browser: nothing is rendered or encoded on the Signal K server, and the map tiles are the
240
+ only thing downloaded. **View → 3D** shows the same film, at the map's own scale and with north still at the top, as a
241
+ camera tilted down onto a cartoon sailboat that heels and trims its sails to the wind and rides the waves, with the
242
+ map laid flat under it; frame it closer or wider than the map and pick the boat's size if you like, and load your own
243
+ boat as a `.glb` file — sails included — if you would rather see it (see
244
+ [Your own boat](#your-own-boat-in-the-3d-animation-)). The MP4 export then films the 3D view.
237
245
  - **Export** — download the whole logbook or a date range as a PDF logbook to print, JSON, CSV or GPX, and write the
238
246
  abandon-ship copy to the USB drive now (admin). The PDF is written in the webapp's language and the device's time
239
247
  zone.
@@ -246,6 +254,85 @@ shortcuts beside it; where any date is allowed, the calendar has an _Any date_ b
246
254
 
247
255
  **Helm entry** in the top bar opens the tablet entry app.
248
256
 
257
+ ### Your own boat in the 3D animation ⛵
258
+
259
+ The 3D view draws a cartoon sailboat. To see yours instead, use **Boat → Use my own boat…** under the animation and pick
260
+ a `.glb` file. The model is kept in **that browser only** (it is never sent to the logbook or the Signal K server), so
261
+ it has to be loaded again on another device; **Use the default boat** puts the generic one back.
262
+
263
+ **The file**
264
+
265
+ | | |
266
+ | ------------- | --------------------------------------------------------------------------------------------------------------------------------- |
267
+ | Format | Binary glTF 2.0 (`.glb`), one self-contained file — textures embedded |
268
+ | Size | 30 MB at most (a few MB is plenty: the boat is small on the film) |
269
+ | Not supported | Draco, Meshopt or KTX2 compression. Animations, cameras and lights inside the file are ignored — the view lights the scene itself |
270
+ | Materials | Ordinary glTF materials. Make the sails **double-sided**, or one face vanishes as they swing |
271
+
272
+ **Orientation, size and waterline**
273
+
274
+ - **Y is up and the bow points towards +Z** — the glTF convention. Nothing else says which end is the front, so a boat
275
+ that sails backwards needs a half turn about the vertical axis before it is exported.
276
+ - **Any unit.** The model is scaled so that its longest horizontal extent — length, or width if that is larger,
277
+ including a boom or a bowsprit — is one boat length, and centred in plan. A stray helper object far from the boat (a
278
+ ground plane, a light) enlarges that box and shrinks the boat: delete them before exporting.
279
+ - **The lowest point of the model is taken as the bottom of the keel** and placed a twentieth of the boat's length under
280
+ the waterline, everything else above. The sea is drawn behind the boat and never cuts into it, so the hull is always
281
+ whole.
282
+ - **The whole boat turns, heels, pitches and rides the waves** with no work on your part. Its size on screen is set by
283
+ the _Boat size_ buttons, not by the model.
284
+
285
+ **Sails that move to the wind**
286
+
287
+ Name the sail nodes and the view trims them like the default boat's: let out as the wind comes aft, and on the side away
288
+ from it.
289
+
290
+ | Sail | Names recognised | Origin of the node | Turns by |
291
+ | -------- | ------------------------------------------------------------------- | ------------------------------------ | ------------------- |
292
+ | Mainsail | `Mainsail`, `Main`, `Sail_Main`, `GrandVoile`, `GV` | On the mast, at the foot of the sail | The full sail angle |
293
+ | Headsail | `Jib`, `Genoa`, `Headsail`, `Foresail`, `Sail_Jib`, `Foc`, `Génois` | On the forestay, at the tack | 0.8 of it |
294
+
295
+ Case, spaces, punctuation and the number a modelling tool adds to a copy (`Mainsail.001`) do not matter.
296
+
297
+ - **The sail is rotated about the vertical axis through the origin of its node.** Put that origin where the sail should
298
+ pivot — the mast, or the bow fitting for a jib — not at the middle of the cloth, or it will swing sideways.
299
+ - **Model it at rest on the centreline**, the boom pointing aft (−Z). The view adds the trim angle to whatever rotation
300
+ the node already has.
301
+ - **The angle** is about half the apparent wind angle, at least 4° and at most 88°, smoothed like the boat's heading.
302
+ The wind on the starboard side puts the sail to port, and the other way round. Where the track has no wind reading the
303
+ sails stay on the centreline.
304
+ - **Put the boom, the sail and its fittings inside the sail node** so they turn together. Only the outermost node with a
305
+ recognised name is turned; anything nested in it goes along.
306
+ - **The cloth is rigid.** It does not billow, and a camber does not swap sides with the tack: model it flat or
307
+ symmetrical.
308
+ - **Nothing else is animated** — no flag, rudder or propeller.
309
+
310
+ **From Blender**
311
+
312
+ 1. Model the boat with its bow towards **−Y** and Z up — Blender's own front — so it comes out towards +Z with Y up.
313
+ 2. Name the sail objects `Mainsail` and `Jib`.
314
+ 3. For each sail, put the 3D cursor on the mast foot (or the tack) and use **Object ▸ Set Origin ▸ Origin to 3D
315
+ Cursor**. Apply rotation and scale (**Ctrl+A**).
316
+ 4. Set the sail material to double-sided (**Backface Culling** off).
317
+ 5. **File ▸ Export ▸ glTF 2.0**, format **glTF Binary (.glb)**, **+Y Up** ticked, compression off; lights and cameras
318
+ need not be included.
319
+ 6. Load the file in the animation. The line under the boat says which sails were found — _Sails trimmed to the wind:
320
+ mainsail, jib_ — or _No sail recognised_ if a name is off.
321
+
322
+ **When something is wrong**
323
+
324
+ | What you see | Why, and what to do |
325
+ | -------------------------------- | ------------------------------------------------------------------------------------------------------------- |
326
+ | The boat sails backwards | The bow points towards −Z. Turn the model 180° about the vertical axis and export again |
327
+ | The boat lies on its side | Exported with Z up. Export with **+Y Up** |
328
+ | The boat is tiny | Something far from it is in the file — a ground plane, a light. Remove it |
329
+ | _No sail recognised_ | The nodes are not named as in the table, or a wrapper node above them has a sail name and hides them |
330
+ | The sails do not move | The track has no wind readings (there is no apparent wind angle), or the sail nodes are called something else |
331
+ | A sail swings about an odd point | Its origin is not on the mast or the tack |
332
+ | One face of a sail disappears | The material is single-sided |
333
+ | _That file could not be read_ | It is not a `.glb`, or it uses Draco, Meshopt or KTX2 compression |
334
+ | The model is gone next time | The browser's site data was cleared, or it is another browser or device. Load it again |
335
+
249
336
  ## The tablet entry app 📱
250
337
 
251
338
  Open `/signalk-chiplog/entry/` on the tablet, or follow **Helm entry** from the logbook. For an app-like, full-screen
@@ -333,36 +420,43 @@ a regular Signal K user account.
333
420
 
334
421
  In the Signal K admin, **Apps & Plugins → Configuration → Chiplog**.
335
422
 
336
- | Setting | Default | What it does |
337
- | ---------------------------------------------------------------- | --------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
338
- | Stop duration within which a new departure continues the passage | 30 min | A passage closes when the boat stops; leaving again sooner reopens it, the stop kept as a stopover. |
339
- | Under-way speed without navigation.state | 1 kn | Used only without signalk-autostate: under way above it, stopped below half of it. |
340
- | Propulsion assumed without engine data | sail | When nothing says whether the engine is running. Set to engine on a motorboat. |
341
- | Instrument snapshot interval | 60 min | Readings on this clock boundary during a passage. |
342
- | Track point interval | 15 s | A track point at least this often while moving. |
343
- | Place matching radius | 200 m | A departure or arrival this close to a known place takes its name. |
344
- | Name departures and arrivals with online geocoding | on | Turn off to never send positions online; places are then named after their coordinates until corrected. |
345
- | Geocoding service | `https://nominatim.openstreetmap.org` | Any Nominatim-compatible service, e.g. a self-hosted one. |
346
- | Read each journal line against the nearest landmark | on | Fetches the landmarks of the areas sailed through from OpenStreetMap, so each position is also given as a bearing and distance from one. Turn off to keep the coordinates alone. |
347
- | Landmark service (Overpass API) | `https://overpass-api.de/api/interpreter` | Any Overpass-compatible service, e.g. a self-hosted one. |
348
- | Fetch the tide forecast at departure | on | Turn off to never send the departure position online; the passage page then shows no tide. |
349
- | Marine service | `https://marine-api.open-meteo.com/v1/marine` | Any Open-Meteo Marine-compatible service, e.g. a self-hosted one. Serves the tide, and the sea state and current of the weather forecast. |
350
- | Fetch the marine weather forecast at departure | on | Turn off to never send the departure position to the weather services; the passage page and the PDF then show no forecast. |
351
- | Weather service | `https://api.open-meteo.com/v1/forecast` | Any Open-Meteo-compatible forecast service, e.g. a self-hosted one. |
352
- | USB export directory | — | Where the abandon-ship copy is written, e.g. `/media/usb`. Empty turns the USB copy off. |
353
- | Automatic USB copy interval | 15 min | How often the USB copy is brought up to date. 0 turns the periodic copy off. |
354
- | Copy to the USB drive at each arrival | on | Brings the USB copy up to date as soon as a passage ends. |
355
- | Logbook language (PDF) | en | Language of the PDF logbooks on the USB drive (English or French). |
356
- | Ship's time zone (PDF) | the server's | Time zone of the PDF logbooks on the USB drive, e.g. `Europe/Paris`. |
357
- | Wind speed thresholds | 20, 30 kn | Logged when the 2-minute average true wind crosses them. |
358
- | Barometric drop warning | 4 hPa / 3 h | 0 turns it off. |
359
- | InfluxDB host (retrospective analysis) | — | Local or remote host of the InfluxDB 1.x database signalk-to-influxdb writes to. Empty turns the retrospective analysis page off. |
360
- | InfluxDB port | 8086 | |
361
- | InfluxDB database | — | |
362
- | InfluxDB username / password | — | Leave empty if the database needs none. |
363
- | InfluxDB protocol | http | `http` or `https`. |
364
- | InfluxDB query timeout | 30 s | Each retrospective query gives up and reports an error past this, instead of hanging against an unreachable or overloaded database. |
365
- | InfluxDB vessel context | this server's own | Only needed running the replay from a different Signal K server than the one that wrote the history, e.g. development pointed at a production database. |
423
+ | Setting | Default | What it does |
424
+ | ---------------------------------------------------------------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
425
+ | Stop duration within which a new departure continues the passage | 30 min | A passage closes when the boat stops; leaving again sooner reopens it, the stop kept as a stopover. |
426
+ | Under-way speed without navigation.state | 1 kn | Used only without signalk-autostate: under way above it, stopped below half of it. |
427
+ | Propulsion assumed without engine data | sail | When nothing says whether the engine is running. Set to engine on a motorboat. |
428
+ | Instrument snapshot interval | 60 min | Readings on this clock boundary during a passage. |
429
+ | Track point interval | 15 s | A track point at least this often while moving. |
430
+ | Place matching radius | 200 m | A departure or arrival this close to a known place takes its name. |
431
+ | Name departures and arrivals with online geocoding | on | Turn off to never send positions online; places are then named after their coordinates until corrected. |
432
+ | Geocoding service | `https://nominatim.openstreetmap.org` | Any Nominatim-compatible service, e.g. a self-hosted one. |
433
+ | Read each journal line against the nearest landmark | on | Fetches the landmarks of the areas sailed through from OpenStreetMap, so each position is also given as a bearing and distance from one. Turn off to keep the coordinates alone. |
434
+ | Landmark service (Overpass API) | `https://overpass-api.de/api/interpreter` | Any Overpass-compatible service, e.g. a self-hosted one. |
435
+ | Fetch the tide forecast at departure | on | Turn off to never send the departure position online; the passage page then shows no tide. |
436
+ | Marine service | `https://marine-api.open-meteo.com/v1/marine` | Any Open-Meteo Marine-compatible service, e.g. a self-hosted one. Serves the tide, and the sea state and current of the weather forecast. |
437
+ | Fetch the marine weather forecast at departure | on | Turn off to never send the departure position to the weather services; the passage page and the PDF then show no forecast. |
438
+ | Weather service | `https://api.open-meteo.com/v1/forecast` | Any Open-Meteo-compatible forecast service, e.g. a self-hosted one. |
439
+ | USB export directory | — | Where the abandon-ship copy is written, e.g. `/media/usb`. Empty turns the USB copy off. |
440
+ | Automatic USB copy interval | 15 min | How often the USB copy is brought up to date. 0 turns the periodic copy off. |
441
+ | Copy to the USB drive at each arrival | on | Brings the USB copy up to date as soon as a passage ends. |
442
+ | Logbook language (PDF) | en | Language of the PDF logbooks on the USB drive (English or French). |
443
+ | Ship's time zone (PDF) | the server's | Time zone of the PDF logbooks on the USB drive, e.g. `Europe/Paris`. |
444
+ | Wind speed thresholds | 20, 30 kn | Logged when the 2-minute average true wind crosses them. |
445
+ | Barometric drop warning | 4 hPa / 3 h | 0 turns it off. |
446
+ | Log heading changes | on | Turn off to leave heading changes out of the log. |
447
+ | Heading change threshold | 30° | A change must be at least this large to be logged. |
448
+ | Heading change tolerance | 10° | How much the new heading may wander while holding and still count as steady. |
449
+ | Heading change hold time | 60 s | How long the new heading must hold before it is logged. |
450
+ | Heading change minimum speed | 2 kn | Below this speed over ground, the course is too noisy to log a change. |
451
+ | Heading change cooldown | 5 min | A new change is logged only once the last one is at least this old. |
452
+ | History source (retrospective analysis) | InfluxDB 1.x | Select Signal K History API to read the server's own history provider, such as signalk-to-influxdb2 — no database connection needed. InfluxDB 1.x stays the default so existing installations are untouched. |
453
+ | InfluxDB host (retrospective analysis) | — | Shown only for the InfluxDB 1.x legacy source. Local or remote host of the database signalk-to-influxdb writes to. Empty turns the retrospective analysis page off. |
454
+ | InfluxDB port | 8086 | |
455
+ | InfluxDB database | — | |
456
+ | InfluxDB username / password | — | Leave empty if the database needs none. |
457
+ | InfluxDB protocol | http | `http` or `https`. |
458
+ | Retrospective query timeout | 30 s | Each retrospective query gives up and reports an error past this, instead of hanging against an unreachable or overloaded history. Applies to either source. |
459
+ | Vessel context (retrospective analysis) | this server's own | Only needed running the replay from a different Signal K server than the one that wrote the history, e.g. development pointed at a production database. Applies to either source. |
366
460
 
367
461
  ## Signal K data used 🔌
368
462
 
@@ -374,7 +468,7 @@ None of these is required except position and speed over ground; each feature us
374
468
  | Engine or sail | `propulsion.*.revolutions`, `propulsion.*.state`, `navigation.state` |
375
469
  | Readings | `navigation.headingTrue` (or `headingMagnetic` + `magneticVariation`), `navigation.speedThroughWater`, `environment.wind.*`, `environment.depth.belowSurface` (or `belowTransducer`), `environment.outside.pressure`, `environment.outside.temperature`, `environment.water.temperature`, `navigation.log`, `propulsion.*.runTime` |
376
470
  | Boat status | `tanks.*.*.currentLevel`, `.currentVolume`, `.capacity`, `.name`, `electrical.batteries.*.voltage`, `.current`, `.capacity.stateOfCharge`, `.temperature`, `.name` |
377
- | Events | `notifications.*`, `steering.autopilot.state`, `.mode`, `.engaged`, `.target`, `environment.wind.speedTrue`, `environment.outside.pressure` |
471
+ | Events | `notifications.*`, `steering.autopilot.state`, `.mode`, `.engaged`, `.target`, `environment.wind.speedTrue`, `environment.outside.pressure`, `navigation.headingTrue` (or `headingMagnetic` + `magneticVariation`) |
378
472
 
379
473
  ## Backups and abandon ship 🛟
380
474
 
@@ -400,9 +494,13 @@ stopped? The **Retrospective** page (admin access) reconstructs those passages f
400
494
  Chiplog runs live — the same thresholds, so a reconstructed passage is one Chiplog would have logged had it been running
401
495
  at the time.
402
496
 
403
- - **Requires [signalk-to-influxdb](https://github.com/tkurki/signalk-to-influxdb)** (a recommended companion plugin)
404
- already having written the boat's data into an InfluxDB 1.x database — local or on another machine, set in **Apps &
405
- Plugins → Configuration**: host, port, database, and a username/password if it needs one.
497
+ - Choose a history source in **Apps & Plugins → Configuration**:
498
+ - **Signal K History API** (recommended) reads the server's active history provider, such as
499
+ [signalk-to-influxdb2](https://github.com/tkurki/signalk-to-influxdb2), without database credentials or storage
500
+ schema assumptions.
501
+ - **InfluxDB 1.x (legacy)** requires [signalk-to-influxdb](https://github.com/tkurki/signalk-to-influxdb) to have
502
+ written the boat's data into an InfluxDB 1.x database — local or on another machine — set with host, port, database,
503
+ and a username/password if it needs one.
406
504
  - Pick a **from** and **to** date on the Retrospective page and start it. It runs in the background — the page shows its
407
505
  progress — and can be cancelled at any point; a first quick pass finds when the boat moved, and only those stretches
408
506
  are then fetched and reconstructed, so weeks in port take next to no time. Once done, the page sums up what it added:
@@ -482,9 +580,10 @@ Chiplog works, but departures and arrivals are decided from speed only. The mess
482
580
  - **"has not been updated since…"** — the source named stopped publishing. signalk-autostate republishes every 10
483
581
  minutes while it receives position and speed: check that the GPS data reaches the server, and that the plugin is
484
582
  enabled.
485
- - **"is “default” (from nmea0183.AI)"** — another device publishes a navigational status Chiplog does not use, typically
486
- the boat's own AIS transponder, and signalk-autostate's value is not there to take over. Check that signalk-autostate
487
- is enabled; Chiplog prefers its value over any other source.
583
+ - **"is “default” (from nmea0183.AI)"** — the source Signal K resolved `navigation.state` to publishes a navigational
584
+ status Chiplog does not use, typically the boat's own AIS transponder. Chiplog follows whichever source the server
585
+ picks, so the fix is on the server: check that signalk-autostate is enabled, and give it priority over the transponder
586
+ in Signal K's source priorities.
488
587
 
489
588
  ### Passages are not opening
490
589
 
@@ -539,10 +638,10 @@ context** in the plugin configuration.
539
638
  ### A retrospective analysis takes minutes then fails with no clear reason
540
639
 
541
640
  The InfluxDB server did not answer — unreachable, overloaded, a firewall or a VPN not connected. Each query now gives up
542
- after **InfluxDB query timeout** (30 seconds by default) with the connection problem it ran into, rather than hanging
543
- until some far longer, less informative failure; check that the server named in the plugin configuration is reachable
544
- from wherever Signal K runs, and that it is not overloaded — or raise the timeout if it is simply slow to answer a
545
- six-hour chunk.
641
+ after **Retrospective query timeout** (30 seconds by default) with the connection problem it ran into, rather than
642
+ hanging until some far longer, less informative failure; check that the server named in the plugin configuration is
643
+ reachable from wherever Signal K runs, and that it is not overloaded — or raise the timeout if it is simply slow to
644
+ answer a six-hour chunk.
546
645
 
547
646
  ### A retrospective analysis over several days makes the InfluxDB server unresponsive
548
647
 
@@ -565,6 +664,9 @@ between attempts; nothing is lost, it just takes longer to resolve.
565
664
  - **Offline charts** are not provided; the animation draws the tracks on a blank sea when there is no connection.
566
665
  - **The MP4 export needs a browser with WebCodecs** — Chrome, Edge, Safari 17 or Firefox 130 and later. Without it the
567
666
  animation still plays on screen, and the export button is simply not offered.
667
+ - **The 3D view needs WebGL 2.** Without it the switch is greyed out and the map view is used. Heel, pitch and sail trim
668
+ are estimated from the wind — the logbook records none of them — and a boat model you load stays in that browser only,
669
+ so it has to be loaded again on another device.
568
670
  - **A long animation takes a while to export**: every frame waits for its map before it is drawn, so the video is the
569
671
  same whatever the connection was doing, but a long range means a lot of tiles. Turning the seamarks off halves them.
570
672
  - **One vessel per Signal K server**, and no per-crew-member authorship.
package/index.js CHANGED
@@ -225,50 +225,121 @@ module.exports = function (app) {
225
225
  default: EVENT_DEFAULTS.pressureDropThreshold,
226
226
  minimum: 0
227
227
  },
228
- influxHost: {
229
- type: 'string',
230
- title: 'InfluxDB host (retrospective analysis)',
228
+ headingChangeEnabled: {
229
+ type: 'boolean',
230
+ title: 'Log heading changes',
231
231
  description:
232
- 'For reconstructing past passages from a signalk-to-influxdb history (InfluxDB 1.x), local or remote. Leave empty to turn that feature off'
232
+ 'Records a course change once it is held; turn off to leave heading changes out of the log',
233
+ default: EVENT_DEFAULTS.headingChangeEnabled
233
234
  },
234
- influxPort: {
235
+ headingChangeThreshold: {
235
236
  type: 'number',
236
- title: 'InfluxDB port',
237
- default: INFLUX_DEFAULTS.influxPort
237
+ title: 'Heading change threshold (degrees)',
238
+ description: 'A change must be at least this large to be logged',
239
+ default: EVENT_DEFAULTS.headingChangeThreshold,
240
+ minimum: 1,
241
+ maximum: 180
238
242
  },
239
- influxDatabase: {
240
- type: 'string',
241
- title: 'InfluxDB database'
243
+ headingChangeTolerance: {
244
+ type: 'number',
245
+ title: 'Heading change tolerance (degrees)',
246
+ description: 'How much the new heading may wander while holding and still count as steady',
247
+ default: EVENT_DEFAULTS.headingChangeTolerance,
248
+ minimum: 0
242
249
  },
243
- influxUsername: {
244
- type: 'string',
245
- title: 'InfluxDB username',
246
- description: 'Leave empty if the database needs none'
250
+ headingChangeHoldSeconds: {
251
+ type: 'number',
252
+ title: 'Heading change hold time (seconds)',
253
+ description: 'How long the new heading must hold before it is logged',
254
+ default: EVENT_DEFAULTS.headingChangeHoldSeconds,
255
+ minimum: 1
247
256
  },
248
- influxPassword: {
249
- type: 'string',
250
- title: 'InfluxDB password',
251
- format: 'password'
257
+ headingChangeMinSpeed: {
258
+ type: 'number',
259
+ title: 'Heading change minimum speed (knots)',
260
+ description: 'Below this speed over ground, the course is too noisy to log a change',
261
+ default: EVENT_DEFAULTS.headingChangeMinSpeed,
262
+ minimum: 0
263
+ },
264
+ headingChangeCooldownMinutes: {
265
+ type: 'number',
266
+ title: 'Heading change cooldown (minutes)',
267
+ description: 'A new change is logged only once the last one is at least this old',
268
+ default: EVENT_DEFAULTS.headingChangeCooldownMinutes,
269
+ minimum: 0
252
270
  },
253
- influxProtocol: {
271
+ retrospectiveHistorySource: {
254
272
  type: 'string',
255
- title: 'InfluxDB protocol',
256
- enum: ['http', 'https'],
257
- default: INFLUX_DEFAULTS.influxProtocol
273
+ title: 'History source for retrospective analysis',
274
+ description:
275
+ 'Signal K reads the server’s own History API provider (signalk-to-influxdb2, for example), needing no database connection of its own — the better choice on a new installation. InfluxDB 1.x keeps the legacy direct database reader, and stays the default so installations already set up that way go on working untouched.',
276
+ enum: ['influxdb1', 'signalk'],
277
+ enumNames: ['InfluxDB 1.x (legacy)', 'Signal K History API'],
278
+ default: 'influxdb1'
258
279
  },
259
280
  influxQueryTimeoutSeconds: {
260
281
  type: 'number',
261
- title: 'InfluxDB query timeout (seconds)',
282
+ title: 'Retrospective query timeout (seconds)',
262
283
  description:
263
- 'Each retrospective query is given up on and reported as an error past this, rather than hanging indefinitely against an unreachable or overloaded database',
284
+ 'Each retrospective query is given up on and reported as an error past this, rather than hanging indefinitely against an unreachable or overloaded history. Applies to either history source',
264
285
  default: INFLUX_DEFAULTS.influxQueryTimeoutSeconds,
265
286
  minimum: 1
266
287
  },
267
288
  influxSelfContext: {
268
289
  type: 'string',
269
- title: 'InfluxDB vessel context',
290
+ title: 'Vessel context (retrospective analysis)',
270
291
  description:
271
- 'Only needed running the replay from a different Signal K server than the one that wrote the history — e.g. a development instance pointed at a boat’s production database. The vessel context the data was tagged with, such as "vessels.urn:mrn:imo:mmsi:123456789"; a failed replay names the contexts actually found. Leave empty to use this server’s own (Signal K → Server → Vessel Identity)'
292
+ 'Only needed running the replay from a different Signal K server than the one that wrote the history — e.g. a development instance pointed at a boat’s production database. The vessel context the data was tagged with, such as "vessels.urn:mrn:imo:mmsi:123456789"; a failed replay names the contexts actually found. Leave empty to use this server’s own (Signal K → Server → Vessel Identity). Applies to either history source'
293
+ }
294
+ },
295
+ // RJSF evaluates dependencies each time the selector changes. Keeping the
296
+ // InfluxDB fields out of the top-level properties hides them in History
297
+ // API mode and inserts them immediately after the source selector.
298
+ dependencies: {
299
+ retrospectiveHistorySource: {
300
+ oneOf: [
301
+ {
302
+ properties: {
303
+ retrospectiveHistorySource: { const: 'influxdb1' },
304
+ influxHost: {
305
+ type: 'string',
306
+ title: 'InfluxDB host (retrospective analysis)',
307
+ description:
308
+ 'For reconstructing past passages from a signalk-to-influxdb history (InfluxDB 1.x), local or remote. Leave empty to turn that feature off'
309
+ },
310
+ influxPort: {
311
+ type: 'number',
312
+ title: 'InfluxDB port',
313
+ default: INFLUX_DEFAULTS.influxPort
314
+ },
315
+ influxDatabase: {
316
+ type: 'string',
317
+ title: 'InfluxDB database'
318
+ },
319
+ influxUsername: {
320
+ type: 'string',
321
+ title: 'InfluxDB username',
322
+ description: 'Leave empty if the database needs none'
323
+ },
324
+ influxPassword: {
325
+ type: 'string',
326
+ title: 'InfluxDB password',
327
+ format: 'password'
328
+ },
329
+ influxProtocol: {
330
+ type: 'string',
331
+ title: 'InfluxDB protocol',
332
+ enum: ['http', 'https'],
333
+ default: INFLUX_DEFAULTS.influxProtocol
334
+ }
335
+ }
336
+ },
337
+ {
338
+ properties: {
339
+ retrospectiveHistorySource: { const: 'signalk' }
340
+ }
341
+ }
342
+ ]
272
343
  }
273
344
  }
274
345
  };
@@ -400,6 +471,16 @@ module.exports = function (app) {
400
471
  logbookTimeZone: config.logbookTimeZone || null,
401
472
  windSpeedThresholds: config.windSpeedThresholds ?? EVENT_DEFAULTS.windSpeedThresholds,
402
473
  pressureDropThreshold: config.pressureDropThreshold ?? EVENT_DEFAULTS.pressureDropThreshold,
474
+ headingChangeEnabled: config.headingChangeEnabled ?? EVENT_DEFAULTS.headingChangeEnabled,
475
+ headingChangeThreshold:
476
+ config.headingChangeThreshold ?? EVENT_DEFAULTS.headingChangeThreshold,
477
+ headingChangeTolerance:
478
+ config.headingChangeTolerance ?? EVENT_DEFAULTS.headingChangeTolerance,
479
+ headingChangeHoldSeconds:
480
+ config.headingChangeHoldSeconds ?? EVENT_DEFAULTS.headingChangeHoldSeconds,
481
+ headingChangeMinSpeed: config.headingChangeMinSpeed ?? EVENT_DEFAULTS.headingChangeMinSpeed,
482
+ headingChangeCooldownMinutes:
483
+ config.headingChangeCooldownMinutes ?? EVENT_DEFAULTS.headingChangeCooldownMinutes,
403
484
  influxHost: config.influxHost || null,
404
485
  influxPort: config.influxPort ?? INFLUX_DEFAULTS.influxPort,
405
486
  influxDatabase: config.influxDatabase || null,
@@ -408,7 +489,9 @@ module.exports = function (app) {
408
489
  influxProtocol: config.influxProtocol || INFLUX_DEFAULTS.influxProtocol,
409
490
  influxQueryTimeoutSeconds:
410
491
  config.influxQueryTimeoutSeconds ?? INFLUX_DEFAULTS.influxQueryTimeoutSeconds,
411
- influxSelfContext: config.influxSelfContext || null
492
+ influxSelfContext: config.influxSelfContext || null,
493
+ retrospectiveHistorySource:
494
+ config.retrospectiveHistorySource === 'signalk' ? 'signalk' : 'influxdb1'
412
495
  };
413
496
 
414
497
  if (settings.logbookTimeZone && !isTimeZone(settings.logbookTimeZone)) {