sailkick-boat 0.20.0 → 0.20.1
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/README.md +6 -2
- package/lib/history/ring.js +30 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -257,8 +257,12 @@ worth designing properly rather than guessing at, so for now they are simply sep
|
|
|
257
257
|
## Local history (offline Trends + track)
|
|
258
258
|
**One source: a live ring**, sampled from the same BoatState that feeds `/ws/telemetry`
|
|
259
259
|
— no database, works on a Victron GX with nothing else installed. `historyAvailable` is
|
|
260
|
-
forced on so the app shows the Trends panel, and the
|
|
261
|
-
serves,
|
|
260
|
+
forced on so the app shows the Trends panel, and the **nineteen channels match what the
|
|
261
|
+
cloud serves** — wind (true/apparent, speed/angle/direction), SOG/STW/COG/heading, depth,
|
|
262
|
+
VMG, sea and air temperature, port and starboard revs, and the four active-waypoint
|
|
263
|
+
values. So an instrument cell's history flyout shows the same thing whichever provider is
|
|
264
|
+
answering. A channel with no data is simply absent: a boat with no paddlewheel has no
|
|
265
|
+
`stw`, and the waypoint channels appear only while a destination is active.
|
|
262
266
|
|
|
263
267
|
There is deliberately **no way to point this at a local InfluxDB**. Until v0.15.0 a read
|
|
264
268
|
token did exactly that, and it was a trap: the app only ever asks for a *relative* window
|
package/lib/history/ring.js
CHANGED
|
@@ -21,6 +21,23 @@ const fsp = fs.promises
|
|
|
21
21
|
const path = require('path')
|
|
22
22
|
|
|
23
23
|
const DEG = Math.PI / 180
|
|
24
|
+
|
|
25
|
+
// The channel set the Trends panel and the instrument history flyouts expect. It must
|
|
26
|
+
// match the cloud's provider (sailkick server/history/influx-provider.js MAP + the
|
|
27
|
+
// three active-waypoint prefixes), so the same cell shows the same history whether the
|
|
28
|
+
// boat or the cloud is answering.
|
|
29
|
+
//
|
|
30
|
+
// This drifted once already: it was frozen at the eight channels that existed before
|
|
31
|
+
// v0.18.6, while the app grew cells for true wind angle, VMG, temperatures, engine revs
|
|
32
|
+
// and the four waypoint values — and `cog` was sampled into the ring but left out of the
|
|
33
|
+
// output entirely. Eleven of nineteen cells had a live number and an empty flyout.
|
|
34
|
+
// test/history-ring.test.js pins this list against the app's own channel names.
|
|
35
|
+
const CHANNELS = [
|
|
36
|
+
'tws', 'twd', 'aws', 'awa', 'twa', 'vmg',
|
|
37
|
+
'sog', 'stw', 'cog', 'heading', 'depth',
|
|
38
|
+
'seaTemp', 'airTemp', 'rpmPort', 'rpmStbd',
|
|
39
|
+
'wptBrg', 'wptDist', 'wptVmg', 'wptTtg'
|
|
40
|
+
]
|
|
24
41
|
const wrap360 = (d) => ((d % 360) + 360) % 360
|
|
25
42
|
const MAX_SAMPLES = 50000
|
|
26
43
|
|
|
@@ -51,7 +68,7 @@ function trueWind (s) {
|
|
|
51
68
|
class RingHistoryProvider {
|
|
52
69
|
constructor ({ source, sampleSec, windowSec, persistFile } = {}) {
|
|
53
70
|
this._source = source
|
|
54
|
-
this._ring = [] // [{ t,
|
|
71
|
+
this._ring = [] // [{ t, ...CHANNELS, lat, lon }]
|
|
55
72
|
const win = windowSec || 3600
|
|
56
73
|
this._windowMs = win * 1000
|
|
57
74
|
this._persistFile = persistFile || null
|
|
@@ -80,6 +97,16 @@ class RingHistoryProvider {
|
|
|
80
97
|
stw: num(s.stwKt),
|
|
81
98
|
aws: num(s.awsKt), awa: num(s.awaDeg), depth: num(s.depthM),
|
|
82
99
|
tws: tw ? tw.tws : null, twd: tw ? tw.twd : null,
|
|
100
|
+
// Everything below arrived in BoatState with v0.18.6 but was never sampled here,
|
|
101
|
+
// so these instrument cells had a live value and an empty history flyout.
|
|
102
|
+
twa: num(s.twaDeg), vmg: num(s.vmgKt),
|
|
103
|
+
seaTemp: num(s.seaTempC), airTemp: num(s.airTempC),
|
|
104
|
+
rpmPort: num(s.rpmPort), rpmStbd: num(s.rpmStbd),
|
|
105
|
+
// Waypoint channels are legitimately null when no destination is active — num()
|
|
106
|
+
// maps that to null and CHANNELS omits empty ones, so the flyout stays blank
|
|
107
|
+
// rather than showing a flat line at zero.
|
|
108
|
+
wptBrg: num(s.wptBrgDeg), wptDist: num(s.wptDistNm),
|
|
109
|
+
wptVmg: num(s.wptVmgKt), wptTtg: num(s.wptTtgSec),
|
|
83
110
|
lat: num(s.lat), lon: num(s.lon)
|
|
84
111
|
}
|
|
85
112
|
this._ring.push(row)
|
|
@@ -97,12 +124,8 @@ class RingHistoryProvider {
|
|
|
97
124
|
|
|
98
125
|
getSeries ({ windowSec } = {}) {
|
|
99
126
|
const rows = this._window(windowSec)
|
|
100
|
-
// Matches the InfluxDB provider's channel set exactly (lib/history/index.js MAP), so
|
|
101
|
-
// the Trends panel looks the same whichever provider is serving. Empty channels are
|
|
102
|
-
// omitted, so a boat with no paddlewheel simply has no `stw` key.
|
|
103
|
-
const chans = ['tws', 'twd', 'aws', 'awa', 'sog', 'stw', 'heading', 'depth']
|
|
104
127
|
const series = {}
|
|
105
|
-
for (const c of
|
|
128
|
+
for (const c of CHANNELS) {
|
|
106
129
|
const pts = rows.filter((r) => r[c] != null).map((r) => [r.t, r[c]])
|
|
107
130
|
if (pts.length) series[c] = pts
|
|
108
131
|
}
|
|
@@ -179,4 +202,4 @@ class RingHistoryProvider {
|
|
|
179
202
|
}
|
|
180
203
|
}
|
|
181
204
|
|
|
182
|
-
module.exports = { RingHistoryProvider, MAX_SAMPLES }
|
|
205
|
+
module.exports = { RingHistoryProvider, MAX_SAMPLES, CHANNELS }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sailkick-boat",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.1",
|
|
4
4
|
"description": "Run the sailkick app on board with no internet: charts, weather, climatology, trends and AIS all served from the boat itself. With a sailkick account it also syncs your metrics to the cloud in real time. Alpha, invite-only \u2014 info@sailkick.io",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|