signalk-chiplog 2.2.0 → 2.3.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 +19 -1
- package/README.md +7 -5
- package/index.js +10 -0
- package/lib/detection.js +9 -4
- package/lib/influx-history.js +9 -4
- package/lib/replay-job.js +1 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,23 @@ All notable changes to Chiplog are documented here. The format follows
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [2.3.0] - 2026-09-18
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **InfluxDB query timeout** setting (`influxQueryTimeoutSeconds`, 30 s by default): how long a retrospective replay
|
|
14
|
+
waits for the InfluxDB server to answer before giving up on it as unreachable or overloaded, now configurable instead
|
|
15
|
+
of a fixed 30 seconds — useful against a Raspberry Pi that is simply slow to answer a six-hour chunk.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- **Retrospective replay backfilling a gap before passages already logged live** no longer dated every reconstructed
|
|
20
|
+
passage to the most recent existing passage's end time. Detection's guard against an out-of-order departure looked at
|
|
21
|
+
the latest `end_time` in the whole logbook rather than only at passages that actually preceded the new one, so filling
|
|
22
|
+
in an earlier gap — installing Chiplog after the fact, or after a stop — pinned every reconstructed departure to that
|
|
23
|
+
unrelated, later date, and the replay summary reported no passage found for the requested period even though entries
|
|
24
|
+
had been created.
|
|
25
|
+
|
|
9
26
|
## [2.2.0] - 2026-09-18
|
|
10
27
|
|
|
11
28
|
### Added
|
|
@@ -249,7 +266,8 @@ First release.
|
|
|
249
266
|
- REST API under `/plugins/signalk-chiplog/api`, documented in [docs/API.md](docs/API.md).
|
|
250
267
|
- Single SQLite database through Node's built-in `node:sqlite`: no native module to build.
|
|
251
268
|
|
|
252
|
-
[Unreleased]: https://github.com/ricard33/signalk-chiplog/compare/v2.
|
|
269
|
+
[Unreleased]: https://github.com/ricard33/signalk-chiplog/compare/v2.3.0...HEAD
|
|
270
|
+
[2.3.0]: https://github.com/ricard33/signalk-chiplog/compare/v2.2.0...v2.3.0
|
|
253
271
|
[2.2.0]: https://github.com/ricard33/signalk-chiplog/compare/v2.1.0...v2.2.0
|
|
254
272
|
[2.1.0]: https://github.com/ricard33/signalk-chiplog/compare/v2.0.0...v2.1.0
|
|
255
273
|
[2.0.0]: https://github.com/ricard33/signalk-chiplog/compare/v1.2.0...v2.0.0
|
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Chiplog
|
|
2
2
|
|
|
3
|
-
An automated logbook for [Signal K](https://signalk.org). Chiplog writes the logbook from the data already on
|
|
4
|
-
boat's Signal K server — passages, track, engine and sail, instrument readings, alarms — and lets the crew add what
|
|
3
|
+
An automated nautical logbook for [Signal K](https://signalk.org). Chiplog writes the logbook from the data already on
|
|
4
|
+
your boat's Signal K server — passages, track, engine and sail, instrument readings, alarms — and lets the crew add what
|
|
5
5
|
sensors cannot know from a tablet at the helm: manoeuvres, notes and handwriting.
|
|
6
6
|
|
|
7
7
|
- **One entry per passage**, opened when the boat leaves and closed as soon as it arrives, carrying on after short stops
|
|
@@ -348,6 +348,7 @@ In the Signal K admin, **Apps & Plugins → Configuration → Chiplog**.
|
|
|
348
348
|
| InfluxDB database | — | |
|
|
349
349
|
| InfluxDB username / password | — | Leave empty if the database needs none. |
|
|
350
350
|
| InfluxDB protocol | http | `http` or `https`. |
|
|
351
|
+
| 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. |
|
|
351
352
|
| 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. |
|
|
352
353
|
|
|
353
354
|
## Signal K data used 🔌
|
|
@@ -497,9 +498,10 @@ context** in the plugin configuration.
|
|
|
497
498
|
### A retrospective analysis takes minutes then fails with no clear reason
|
|
498
499
|
|
|
499
500
|
The InfluxDB server did not answer — unreachable, overloaded, a firewall or a VPN not connected. Each query now gives up
|
|
500
|
-
after 30 seconds with the connection problem it ran into, rather than hanging
|
|
501
|
-
failure; check that the server named in the plugin configuration is reachable
|
|
502
|
-
is not overloaded
|
|
501
|
+
after **InfluxDB query timeout** (30 seconds by default) with the connection problem it ran into, rather than hanging
|
|
502
|
+
until some far longer, less informative failure; check that the server named in the plugin configuration is reachable
|
|
503
|
+
from wherever Signal K runs, and that it is not overloaded — or raise the timeout if it is simply slow to answer a
|
|
504
|
+
six-hour chunk.
|
|
503
505
|
|
|
504
506
|
### A retrospective analysis over several days makes the InfluxDB server unresponsive
|
|
505
507
|
|
package/index.js
CHANGED
|
@@ -256,6 +256,14 @@ module.exports = function (app) {
|
|
|
256
256
|
enum: ['http', 'https'],
|
|
257
257
|
default: INFLUX_DEFAULTS.influxProtocol
|
|
258
258
|
},
|
|
259
|
+
influxQueryTimeoutSeconds: {
|
|
260
|
+
type: 'number',
|
|
261
|
+
title: 'InfluxDB query timeout (seconds)',
|
|
262
|
+
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',
|
|
264
|
+
default: INFLUX_DEFAULTS.influxQueryTimeoutSeconds,
|
|
265
|
+
minimum: 1
|
|
266
|
+
},
|
|
259
267
|
influxSelfContext: {
|
|
260
268
|
type: 'string',
|
|
261
269
|
title: 'InfluxDB vessel context',
|
|
@@ -384,6 +392,8 @@ module.exports = function (app) {
|
|
|
384
392
|
influxUsername: config.influxUsername || null,
|
|
385
393
|
influxPassword: config.influxPassword || null,
|
|
386
394
|
influxProtocol: config.influxProtocol || INFLUX_DEFAULTS.influxProtocol,
|
|
395
|
+
influxQueryTimeoutSeconds:
|
|
396
|
+
config.influxQueryTimeoutSeconds ?? INFLUX_DEFAULTS.influxQueryTimeoutSeconds,
|
|
387
397
|
influxSelfContext: config.influxSelfContext || null
|
|
388
398
|
};
|
|
389
399
|
|
package/lib/detection.js
CHANGED
|
@@ -314,11 +314,16 @@ function createPassageDetector({ db, readSelfPath, settings, clock = Date.now })
|
|
|
314
314
|
}
|
|
315
315
|
|
|
316
316
|
function openPassage(now, position, departure) {
|
|
317
|
+
const startIso = iso(departure.time);
|
|
318
|
+
// Only a passage that actually precedes this departure can push it later
|
|
319
|
+
// -- not just whichever entry happens to hold the latest end_time. A
|
|
320
|
+
// retrospective replay filling a gap before passages logged live (SPEC
|
|
321
|
+
// §4.10) would otherwise have every reconstructed departure clamped to
|
|
322
|
+
// the most recent (unrelated, later) passage's end.
|
|
317
323
|
const previousEnd = db
|
|
318
|
-
.prepare('SELECT MAX(end_time) AS endTime FROM log_entries')
|
|
319
|
-
.get().endTime;
|
|
320
|
-
const startTime =
|
|
321
|
-
previousEnd && iso(departure.time) < previousEnd ? previousEnd : iso(departure.time);
|
|
324
|
+
.prepare('SELECT MAX(end_time) AS endTime FROM log_entries WHERE start_time < ?')
|
|
325
|
+
.get(startIso).endTime;
|
|
326
|
+
const startTime = previousEnd && startIso < previousEnd ? previousEnd : startIso;
|
|
322
327
|
const start = departure.position ?? position;
|
|
323
328
|
const place = initialPlaceName(db, start, settings.placeMatchRadius);
|
|
324
329
|
|
package/lib/influx-history.js
CHANGED
|
@@ -12,7 +12,9 @@ const { AUTOSTATE_SOURCE_PREFIX, MAX_AGE_MS, UNDERWAY_STATES } = require('./dete
|
|
|
12
12
|
// packets, a VPN not connected) can otherwise hang far longer than this --
|
|
13
13
|
// Node's fetch has no default timeout of its own -- for an error that is no
|
|
14
14
|
// clearer once it finally arrives, so `query` bounds every request itself.
|
|
15
|
-
|
|
15
|
+
// Configurable (`influxQueryTimeoutSeconds`): a Raspberry Pi under load can
|
|
16
|
+
// need longer than the default to answer a six-hour chunk.
|
|
17
|
+
const DEFAULT_QUERY_TIMEOUT_SECONDS = 30;
|
|
16
18
|
|
|
17
19
|
// A resource-constrained host (a Raspberry Pi running both Signal K and
|
|
18
20
|
// InfluxDB) can be brought down by one query spanning weeks across every
|
|
@@ -34,7 +36,8 @@ const INFLUX_DEFAULTS = {
|
|
|
34
36
|
influxPort: 8086,
|
|
35
37
|
influxDatabase: '',
|
|
36
38
|
influxUsername: '',
|
|
37
|
-
influxPassword: ''
|
|
39
|
+
influxPassword: '',
|
|
40
|
+
influxQueryTimeoutSeconds: DEFAULT_QUERY_TIMEOUT_SECONDS
|
|
38
41
|
};
|
|
39
42
|
|
|
40
43
|
// Everything detection, track recording and observations read live (SPEC
|
|
@@ -107,9 +110,11 @@ function createInfluxHistory({
|
|
|
107
110
|
username,
|
|
108
111
|
password,
|
|
109
112
|
selfContext,
|
|
113
|
+
queryTimeoutSeconds = INFLUX_DEFAULTS.influxQueryTimeoutSeconds,
|
|
110
114
|
fetch = globalThis.fetch,
|
|
111
115
|
signal
|
|
112
116
|
}) {
|
|
117
|
+
const queryTimeoutMs = queryTimeoutSeconds * 1000;
|
|
113
118
|
// path -> [{ time, node }], ascending by time; `node` is what readSelfPath
|
|
114
119
|
// answers, built once here rather than on every read.
|
|
115
120
|
const series = new Map();
|
|
@@ -131,7 +136,7 @@ function createInfluxHistory({
|
|
|
131
136
|
epoch: 'ms',
|
|
132
137
|
q: statements.join(';')
|
|
133
138
|
});
|
|
134
|
-
const timeout = AbortSignal.timeout(
|
|
139
|
+
const timeout = AbortSignal.timeout(queryTimeoutMs);
|
|
135
140
|
let response;
|
|
136
141
|
try {
|
|
137
142
|
response = await fetch(url, {
|
|
@@ -146,7 +151,7 @@ function createInfluxHistory({
|
|
|
146
151
|
}
|
|
147
152
|
if (err.name === 'TimeoutError') {
|
|
148
153
|
throw new Error(
|
|
149
|
-
`InfluxDB at ${protocol}://${host}:${port} did not answer within ${
|
|
154
|
+
`InfluxDB at ${protocol}://${host}:${port} did not answer within ${queryTimeoutSeconds}s`,
|
|
150
155
|
{ cause: err }
|
|
151
156
|
);
|
|
152
157
|
}
|
package/lib/replay-job.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "signalk-chiplog",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.3.0",
|
|
4
|
+
"description": "Nautical logbook for Signal K: automatic entries, handwritten notes",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"files": [
|
|
7
7
|
"index.js",
|