signalk-pypilot-newui 2.0.4 → 2.2.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
@@ -1,5 +1,456 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.2.0 — 2026-08-31 — Rev88..Rev127
4
+
5
+ Forty in-session Revs of navigation-oriented features on top of the
6
+ 2.1.0 visual foundation. Themes: turn the plugin into an intelligence
7
+ layer over pypilot (historian → KPIs → alarms → Doctor → pre-departure
8
+ check), give sail-raising its own AP mode ("Aproado"), and rebuild the
9
+ Setup tab as an app-launcher grid of fullscreen tiles.
10
+
11
+ ### English
12
+
13
+ **Added**
14
+
15
+ - **Aproado pseudo-mode** (Rev87-92) — a new "raise the sails"
16
+ autopilot mode not in pypilot upstream. Pick BY BOW / BY STERN
17
+ via a 5 s modal, the plugin switches pypilot to wind mode with
18
+ target 0° (head to wind), and a floating HUD over the boat shows
19
+ elapsed time, straight-line distance from the start and the
20
+ compass heading captured at activation. SALIR restores the
21
+ previous mode + target + engaged state. The BY STERN branch
22
+ forces a stern-through swing by walking a chain of intermediate
23
+ targets 60° apart so pypilot cannot shortcut through the bow.
24
+ - **Telemetry historian + Chart tab** (Rev93-96) — RAM ring buffer
25
+ at 1 Hz for the last 30 min (backend, Pi 5 friendly). New Chart
26
+ tab shows nine Trip Stats cards (AP engaged time, distance,
27
+ energy, mean/RMS/p95 heading error, servo runtime, tacks/gybes,
28
+ peak servo A) all fed live via SK paths, plus a canvas history
29
+ with 30 s / 2 min / 10 min windows and per-path chips.
30
+ - **Sensor Quality panel** (Rev97-98) — age / observed Hz / jitter /
31
+ source for every critical SK path the AP depends on, with a
32
+ green / amber / red pill. Endpoint `/quality` and a poll while
33
+ Setup is visible.
34
+ - **Servo Health card** (Rev99) — baseline current learned from
35
+ the first ~10 min of engaged navigation, then a live deviation
36
+ ratio flags "elevated" (>1.20×) or "high" (>1.65×) — early
37
+ warning for a hard rudder, fouling, or a stiffened linkage. Six
38
+ new SK paths under `steering.autopilot.pypilot.servo.health.*`.
39
+ - **Alarm engine** (Rev100-101) — seven built-in rules (heading
40
+ deviation, unable to steer, servo overcurrent / temp, low
41
+ voltage, sensor lost, pypilot disconnected) publishing
42
+ canonical SK notifications `notifications.autopilot.*`. Sticky
43
+ banner in the visor with ACK + close, WebAudio beeps +
44
+ speech-synthesis of the message, and a full config panel in
45
+ Setup (enable / mute / status per rule).
46
+ - **Pre-departure check** (Rev102) — a single verdict card
47
+ (READY / READY-WITH-CAVEATS / DO-NOT-ENGAGE) that aggregates
48
+ connectivity, sensor quality, servo health and voltage into one
49
+ answer before you leave the dock.
50
+ - **Pypilot Doctor** (Rev103-104, Rev120-121) — press DIAGNOSE,
51
+ the plugin records 2-3 min with the AP engaged, runs heuristic
52
+ rules on the heading error stream (bias / oscillation / low
53
+ authority) and proposes P / I / D adjustments with a plain
54
+ explanation of why and what to expect. Nothing is applied
55
+ automatically — each suggestion has Apply and Discard buttons.
56
+ Rev120: the first Apply of a session forks the current pypilot
57
+ profile into a new `doctor-YYYYMMDD-HHMM` profile so the
58
+ previous gains stay one profile-select away.
59
+ - **Setup as a launcher grid** (Rev105-119, 124) — every setup
60
+ block is now a square tile in a 2 / 3 / 4-column grid. Tap
61
+ opens fullscreen with a small X to close and ESC support.
62
+ Body scroll is locked while a tile is fullscreen. Live summary
63
+ pill on every tile so the state reads at a glance without
64
+ expanding. Connection consolidated (status + LAN scan + manual
65
+ host + Autopilot Provider in one card). "Emergency" renamed to
66
+ "Remote Control Console".
67
+ - **Interactive SSH console** (Rev113-115) — free-form command
68
+ input with on-screen arrow buttons for mobile history
69
+ navigation, accumulative output textarea, clipboard fallback
70
+ for HTTP LAN, and 14 preset buttons with plain human labels
71
+ (Memory / IP table / WiFi / Temperature / Who is connected /
72
+ ...). BusyBox / piCore-safe fallbacks for every command.
73
+ - **Full RangeSetting sliders in Calibration** (Rev116-119) —
74
+ every pypilot `RangeSetting` grouped by category (rudder /
75
+ servo / imu / ap / other) with the same look as the Tune tab,
76
+ a lock checkbox with the padlock emoji, a frozen "before:"
77
+ baseline that never moves as you drag, and a per-slider ↺
78
+ restore button that snaps back to the baseline.
79
+ - **Nudge steps moved inside Calibration** (Rev124) — one card
80
+ less in the launcher grid; heading trim buttons live where
81
+ they belong conceptually.
82
+
83
+ **Changed**
84
+
85
+ - **Gota Chain shapes SWAP** (Rev122-126) — after several iterations
86
+ with Carlos on Tunatunes: the AMBER "A" arrow (apparent wind) is
87
+ now the LARGE piece (its tip reaches deep into the rose), and
88
+ the TEAL "T" arrow (true wind) is the SMALL outer one. Colors
89
+ and letters kept their canonical meaning; only the SVG paths
90
+ moved so the amber piece is visually the dominant one.
91
+ - **Alarm summary semantics** (Rev107-108) — "activa" (fired) was
92
+ ambiguous with "activada" (enabled). New wording separates
93
+ `firing / sonando` (fired now) from `watching / vigilando`
94
+ (enabled and healthy). Summary always shows both counts.
95
+ - **i18n audit** (Rev105, Rev112, Rev121) — every hard-coded
96
+ English string in the ES bundle purged ("engagear" → "activar",
97
+ KIP paths table fully translated, alarm messages), backend
98
+ suggestion reason / effect exposed as i18n keys + args so the
99
+ frontend renders in the user's language.
100
+ - **Sensor Quality thresholds** (Rev98) — dropped `minHz` from the
101
+ defaults; the 1 Hz sampler capped observed Hz, so the threshold
102
+ produced spurious "degraded" flags. Freshness (`age`) is now
103
+ the only signal that penalises status.
104
+
105
+ **Fixed**
106
+
107
+ - **Fullscreen tile portal** (Rev110-111) — Setup fullscreen tiles
108
+ are now portaled to `<body>` so the `.tab-panel` transform
109
+ (used by the tab animation) cannot break `position: fixed`.
110
+ Fullscreen always covers the viewport now, no matter which
111
+ card was scrolled into.
112
+ - **Copy button on HTTP** (Rev114) — `navigator.clipboard` is a
113
+ secure-context API; on plain http://192.168.x.y it silently
114
+ no-ops. Compat helper falls back to `document.execCommand("copy")`.
115
+ - **Doctor `elapsedSec`** (Rev104) — was counting past the target
116
+ duration once the session completed. Now freezes at the target.
117
+ - **Sliders baseline eaten by refresh** (Rev117-118) — the
118
+ Calibration "before:" value used to reset to the just-edited
119
+ number on every `/values` poll. Now captured once per name and
120
+ kept frozen across renders.
121
+ - **Aproado restore** (Rev90) — mode / target / engaged restore on
122
+ SALIR was skipping steps after one failure. Now each step is
123
+ guarded independently and logged in the console.
124
+ - **Sensor Quality parsing** (Rev94) — `navigation.attitude` is a
125
+ composite `{pitch, roll, yaw}` object, not a scalar path.
126
+ Custom subfield reader added for heel.
127
+ - Cosmetic Firefox warnings (`::-moz-focus-inner`, comment-nested
128
+ `*/`) purged (Rev95-106).
129
+
130
+ ### Español
131
+
132
+ **Nuevo**
133
+
134
+ - **Modo Aproado** (Rev87-92): pseudo-modo AP para subir velas.
135
+ Elige POR PROA / POR POPA en un modal de 5 s, el plugin pasa
136
+ pypilot a modo viento con objetivo 0° (proa al viento), y un
137
+ HUD flotante sobre el barco muestra tiempo transcurrido,
138
+ distancia lineal desde el arranque y el rumbo compás capturado
139
+ al activar. SALIR restaura modo + objetivo + engaged previos.
140
+ POR POPA fuerza el swing por popa con una cadena de objetivos
141
+ intermedios cada 60° para que pypilot no atajaje por proa.
142
+ - **Historian de telemetría + pestaña Gráfica** (Rev93-96):
143
+ buffer circular en RAM a 1 Hz durante 30 min (backend, Pi 5).
144
+ Nueva pestaña Gráfica con 9 tarjetas de estadísticas de sesión
145
+ (tiempo activo, distancia, energía, error medio / RMS / p95,
146
+ servo activo, viradas / trasluchadas, pico servo A) y canvas
147
+ con ventanas 30 s / 2 min / 10 min.
148
+ - **Panel Calidad de sensores** (Rev97-98): edad / Hz / jitter /
149
+ fuente por cada ruta SK crítica con semáforo verde / ámbar /
150
+ rojo.
151
+ - **Tarjeta Salud del servo** (Rev99): baseline aprendido de los
152
+ primeros ~10 min de navegación activa, luego ratio de
153
+ desviación marca "elevated" (>1.20×) o "high" (>1.65×) —
154
+ alerta temprana de timón duro, incrustaciones o rozamientos.
155
+ - **Motor de alarmas** (Rev100-101): 7 reglas built-in
156
+ (desviación de rumbo, incapaz de gobernar, sobrecorriente
157
+ servo, temperatura servo, batería baja, sensor perdido,
158
+ pypilot desconectado) publicando notifications SK canónicas.
159
+ Banner sticky en el visor con ACK y cierre X, beeps WebAudio
160
+ + speechSynthesis del mensaje, panel de configuración en
161
+ Setup (enable / mute / estado por regla).
162
+ - **Comprobación del piloto** (Rev102): tarjeta única con
163
+ veredicto (LISTO / LISTO CON RESERVAS / NO ACTIVAR) que
164
+ agrega conectividad, calidad de sensores, salud del servo y
165
+ voltaje.
166
+ - **Asesoramiento y diagnóstico** (Rev103-104, Rev120-121):
167
+ botón DIAGNOSTICAR, el plugin graba 2-3 min con el AP activo,
168
+ aplica reglas heurísticas (sesgo / oscilación / autoridad) y
169
+ propone ajustes P / I / D con explicación clara del porqué y
170
+ del efecto esperado. Nada se aplica automáticamente — cada
171
+ sugerencia tiene botones Aplicar y Descartar. Rev120: el
172
+ primer Aplicar de la sesión duplica el perfil actual en uno
173
+ nuevo `doctor-AAAAMMDD-HHMM` para que el original quede
174
+ intacto a un toque en Ajustes → Perfil.
175
+ - **Setup como launcher grid** (Rev105-119, 124): cada bloque
176
+ de Setup es un tile cuadrado en un grid 2 / 3 / 4 columnas.
177
+ Tap abre pantalla completa con X para cerrar, header sticky
178
+ y bloqueo de scroll de fondo. Etiqueta resumen en vivo en
179
+ cada tile. Conexión pypilot une 4 secciones. "Emergencia"
180
+ renombrada a "Consola control remoto".
181
+ - **Consola SSH interactiva** (Rev113-115): input libre con
182
+ botones ↑▲ ↓▼ para navegar el historial en móvil, textarea
183
+ acumulativo, fallback de portapapeles para LAN HTTP y 14
184
+ presets con etiquetas humanas (Memoria RAM / Tabla IP / WiFi
185
+ / Temperatura / Quien está conectado / ...). Todos los
186
+ comandos con fallbacks BusyBox / piCore.
187
+ - **Sliders completos de calibración** (Rev116-119): todos los
188
+ `RangeSetting` de pypilot agrupados por categoría (timón /
189
+ servo / imu / piloto / otros) con la misma apariencia que
190
+ Ajustes, candado azul con emoji, valor "antes:" congelado
191
+ que NUNCA se mueve al arrastrar, y un botón ↺ por slider
192
+ para restaurar el valor original.
193
+ - **Botones corrección rumbo dentro de Calibración** (Rev124):
194
+ una tarjeta menos en el grid; los pasos ±1 / ±10 quedan
195
+ donde corresponde conceptualmente.
196
+
197
+ **Cambiado**
198
+
199
+ - **Swap de formas en la Gota Chain** (Rev122-126): tras varias
200
+ iteraciones con Carlos en Tunatunes, la flecha AMARILLA "A"
201
+ (viento aparente) es ahora la GRANDE (su punta llega hasta
202
+ el centro de la rosa) y la flecha VERDE "T" (viento real)
203
+ es la PEQUEÑA externa. Colores y letras mantienen su
204
+ significado canónico; solo se movieron los paths SVG para
205
+ que la amarilla domine visualmente.
206
+ - **Semántica de alarmas** (Rev107-108): "activa" era ambiguo.
207
+ Nueva jerga separa `sonando` (disparada ahora) de `vigilando`
208
+ (habilitada y OK). El resumen muestra siempre ambos contadores.
209
+ - **Auditoría i18n** (Rev105, Rev112, Rev121): purga de cadenas
210
+ inglesas hardcoded en el bundle ES ("engagear" → "activar",
211
+ tabla de KIP totalmente traducida, mensajes de alarma).
212
+ Reason / effect de las sugerencias del Doctor expuestos como
213
+ claves i18n para render en el idioma del visor.
214
+ - **Umbrales Calidad de sensores** (Rev98): quitado `minHz` de
215
+ los defaults; el sampler a 1 Hz capaba la Hz observada y
216
+ generaba "degraded" falsos.
217
+
218
+ **Corregido**
219
+
220
+ - **Portal de tile fullscreen** (Rev110-111): tiles fullscreen
221
+ ahora se mueven al `<body>` para que el `transform` de
222
+ `.tab-panel` (animación entre pestañas) no rompa `position:
223
+ fixed`.
224
+ - **Botón Copiar en HTTP** (Rev114): `navigator.clipboard`
225
+ requiere secure context. Fallback a `document.execCommand("copy")`.
226
+ - **Doctor `elapsedSec`** (Rev104): contaba pasado el objetivo.
227
+ Ahora congela al final.
228
+ - **Baseline de sliders comido por refresh** (Rev117-118): el
229
+ valor "antes" se reseteaba a lo recién editado en cada poll.
230
+ Ahora se captura una vez y no se toca.
231
+ - **Restore de Aproado** (Rev90): SALIR saltaba pasos tras un
232
+ fallo. Ahora cada paso protegido por su try/catch.
233
+ - **Parsing Calidad de sensores** (Rev94): `navigation.attitude`
234
+ es objeto compuesto, no path escalar. Fix del subfield heel.
235
+ - Warnings cosméticos Firefox (`::-moz-focus-inner`, `*/` en
236
+ comentarios) purgados (Rev95-106).
237
+
238
+ ### Français
239
+
240
+ **Ajouté**
241
+
242
+ - **Mode Aproado** (Rev87-92) : pseudo-mode AP pour hisser les
243
+ voiles. PAR AVANT / PAR ARRIÈRE, l'AP passe en mode vent avec
244
+ cible 0° (nez au vent), HUD flottant avec temps, distance et
245
+ cap boussole capturé. SORTIR restaure mode / cible / engagé
246
+ précédents. PAR ARRIÈRE force le virage par l'arrière avec
247
+ une chaîne d'objectifs intermédiaires de 60°.
248
+ - **Historian de télémétrie + onglet Graphique** (Rev93-96) :
249
+ buffer 30 min en RAM à 1 Hz, canvas d'historique et 9 cartes
250
+ Trip Stats.
251
+ - **Panneau Qualité des capteurs** (Rev97-98) : âge / Hz /
252
+ jitter / source par chaque chemin SK critique.
253
+ - **Carte Santé du servo** (Rev99) : baseline appris + ratio de
254
+ déviation avec alertes "elevated" et "high".
255
+ - **Moteur d'alarmes** (Rev100-101) : 7 règles built-in,
256
+ notifications SK canoniques, banner avec ACK et fermeture,
257
+ audio WebAudio + parole synthétique, config par règle.
258
+ - **Vérification pré-départ** (Rev102) : verdict READY / avec
259
+ caveats / NE PAS ENGAGER.
260
+ - **Docteur pypilot** (Rev103-104, Rev120-121) : 2-3 min
261
+ d'enregistrement, règles heuristiques, propositions P / I / D
262
+ avec Appliquer et Rejeter. Le premier Appliquer crée un
263
+ nouveau profil `doctor-AAAAMMJJ-HHMM`.
264
+ - **Setup en grille launcher** (Rev105-119, 124) : tiles carrés,
265
+ fullscreen par tap, résumé en direct, connexion consolidée,
266
+ "Consola contrôle remote" (renommé).
267
+ - **Console SSH interactive** (Rev113-115) : entrée libre,
268
+ historique navigable au mobile, 14 presets aux noms humains,
269
+ fallbacks BusyBox / piCore.
270
+ - **Sliders complets de calibration** (Rev116-119) : chaque
271
+ RangeSetting groupé, cadenas, baseline gelée, bouton restaurer.
272
+ - **Boutons correction cap dans Calibration** (Rev124).
273
+
274
+ **Modifié**
275
+
276
+ - **Swap des formes Gota Chain** (Rev122-126) : la flèche AMBRE
277
+ "A" (vent apparent) est maintenant la GRANDE, la TEAL "T"
278
+ (vent réel) la petite. Couleurs et lettres conservent leur
279
+ sens canonique.
280
+ - **Sémantique alarmes** (Rev107-108) : `sonando` vs
281
+ `vigilando`, résumé affiche les deux compteurs.
282
+ - **Audit i18n** (Rev105, Rev112, Rev121) : purge de l'anglais
283
+ dans les bundles ES / FR / DE.
284
+ - **Seuils Qualité capteurs** (Rev98) : `minHz` supprimé.
285
+
286
+ **Corrigé**
287
+
288
+ - Portal du tile fullscreen (Rev110-111).
289
+ - Bouton Copier en HTTP (Rev114).
290
+ - Doctor `elapsedSec` gelé au final (Rev104).
291
+ - Baseline des sliders congelée (Rev117-118).
292
+ - Restore Aproado protégé par try/catch (Rev90).
293
+ - Lecture composite de `navigation.attitude` (Rev94).
294
+ - Warnings cosmétiques Firefox purgés (Rev95-106).
295
+
296
+ ### Deutsch
297
+
298
+ **Neu**
299
+
300
+ - **Aproado-Pseudomodus** (Rev87-92) — AP-Modus zum Segelhissen.
301
+ ÜBER BUG / ÜBER HECK, AP schaltet in Wind-Modus mit Ziel 0°,
302
+ HUD über dem Boot mit Zeit / Distanz / Kompass-Kurs. AUS
303
+ stellt Modus / Ziel / Engaged wieder her. ÜBER HECK erzwingt
304
+ den langen Schwenk mit Zwischen-Zielen alle 60°.
305
+ - **Telemetrie-Historian + Chart-Tab** (Rev93-96) — Ringpuffer
306
+ 30 min RAM bei 1 Hz, 9 Trip-Stats-Karten, Canvas mit Fenstern
307
+ 30 s / 2 min / 10 min.
308
+ - **Sensor-Qualität-Panel** (Rev97-98).
309
+ - **Servo-Health-Karte** (Rev99) — gelernter Baseline mit
310
+ Alarmen "elevated" / "high".
311
+ - **Alarm-Engine** (Rev100-101) — 7 built-in Regeln, SK
312
+ Notifications, Banner mit ACK und X, WebAudio + Sprache,
313
+ Config-Panel.
314
+ - **Pre-Departure-Check** (Rev102).
315
+ - **Pypilot Doctor** (Rev103-104, Rev120-121) — Diagnose-
316
+ Sitzung, Heuristik-Regeln, P/I/D-Vorschläge mit Anwenden /
317
+ Verwerfen. Erstes Anwenden erzeugt neues Profil.
318
+ - **Setup als Launcher-Grid** (Rev105-119, 124) — quadratische
319
+ Tiles, Vollbild-Tap, Live-Zusammenfassung.
320
+ - **Interaktive SSH-Konsole** (Rev113-115) — freie Eingabe,
321
+ Pfeil-Buttons mobil, 14 Presets mit menschlichen Labels.
322
+ - **Vollständige RangeSetting-Slider in Kalibrierung**
323
+ (Rev116-119) — Schloss, eingefrorene Baseline,
324
+ Wiederherstellen-Knopf pro Slider.
325
+ - **Nudge-Buttons in Kalibrierung** (Rev124).
326
+
327
+ **Geändert**
328
+
329
+ - **Gota-Chain-Form-SWAP** (Rev122-126).
330
+ - **Alarm-Semantik** (Rev107-108) — `sonando` / `vigilando`.
331
+ - **i18n-Audit** (Rev105, Rev112, Rev121).
332
+ - **Sensor-Qualität-Schwellen** (Rev98) — `minHz` entfernt.
333
+
334
+ **Behoben**
335
+
336
+ - Fullscreen-Tile-Portal (Rev110-111).
337
+ - Copy-Button auf HTTP (Rev114).
338
+ - Doctor `elapsedSec` (Rev104).
339
+ - Slider-Baseline eingefroren (Rev117-118).
340
+ - Aproado-Restore geschützt (Rev90).
341
+ - `navigation.attitude`-Zusammensetzung (Rev94).
342
+ - Kosmetische Firefox-Warnungen (Rev95-106).
343
+
344
+ ## 2.1.0 — 2026-08-25 — Rev68..Rev87
345
+
346
+ Twenty in-session Revs of iterative visual + reliability work rolled up
347
+ into a proper minor release. Themes: a full redesign of the compass-rose
348
+ autopilot overlays ("Gota Chain"), a hard-earned fix for AP mutations
349
+ racing each other across the SignalK bus, and a permanent seamless-auth
350
+ story so a Signal K restart never again silently disables the visor's
351
+ mutation buttons.
352
+
353
+ ### Added
354
+
355
+ - **Gota Chain overlay** — the target diamond and the AWA/TWA wind
356
+ arrows are now three concentric SVG pieces that interlock into one
357
+ clean droplet when `target ≡ AWA ≡ TWA`. Each piece carries its own
358
+ letter (A / T) and its own color ring-tick that marks the exact
359
+ angle on the compass. When any of the three drifts, its V-hembra
360
+ opens as a visible hollow. Iterated over 12 Revs (Rev68..Rev82)
361
+ with Carlos on Tunatunes.
362
+ - **COG line** — chain of yellow chevrons from the bow toward the
363
+ course-over-ground direction. Visible only when `SOG > 0.15 kn`.
364
+ - **Current vector** — two parallel wavy blue lines with three
365
+ triangles pointing at the boat. Computed as `SOG − SOW` (added
366
+ new `navigation.speedThroughWater` subscription). Visible when
367
+ `|current| > 0.2 kn`.
368
+ - **4-card overlay selector** — long-press any rose corner OR the
369
+ boat sprite to open the popup with the four toggle cards (AWA,
370
+ TWA, COG, Current), each with a large preview and a data-
371
+ requirement line ("Needs a wind sensor", "Only shows when SOG >
372
+ 0.15 kn", etc). Toggles persist in `localStorage`.
373
+ - **Rose cardinals colour-coded**: N orange, E green, S blue, W red.
374
+ All at the same radius `r = 70`. Thin black stroke around each
375
+ letter for legibility on any background.
376
+ - **Seamless auth via SK Access Request** — the visor now uses a
377
+ device-scoped, permanent SK token instead of a short-lived JWT.
378
+ On first install the user approves once from `SK admin → Security
379
+ → Access Requests`; from then on the token survives every SK
380
+ server restart, every plugin redeploy, and every browser reload,
381
+ so mutations (engage / mode / target) NEVER silently 401 again.
382
+ - **`.\deploy.ps1 -FrontOnly`** — new script flag that syncs
383
+ `public/` only (no build, no npm install, no `systemctl restart
384
+ signalk`). Use it when the diff is HTML / CSS / JS only —
385
+ `Ctrl+F5` in the browser picks it up. Avoids the plugin-socket
386
+ reconnect to `pypilot_web` on the Pi Zero W that pushed the
387
+ TinyPilot to hang after a big batch of deploys.
388
+
389
+ ### Fixed
390
+
391
+ - **AP mutation race (`DIA jumps to a stale target for a beat`).**
392
+ Frontend used to `Promise.all([engage, target])` and the backend's
393
+ `pushAutopilotUpdate` published ALL SK autopilot fields on every
394
+ notify — so whichever POST landed first emitted a delta that
395
+ carried the OTHER field's STALE value (typically an old target
396
+ from the previous session, e.g. `115°` when the intent was `75°`).
397
+ Fixed by refactoring `AutopilotProvider.notifyChanged(fields)` to
398
+ accept `"engaged" | "target" | "all"` and `pushAutopilotUpdate` to
399
+ only emit the paths that actually changed. Parallel POSTs no
400
+ longer clobber each other with stale copies.
401
+ - **Wind-mode target capture on engage.** `doEngage` always sent
402
+ `state.heading` as the target regardless of mode; pypilot in wind
403
+ mode interpreted that compass value as a wind angle and steered
404
+ the boat toward nonsense. Now captures `state.windAngle` (apparent)
405
+ or `state.windAngleTrue` (true wind) when the active mode contains
406
+ "wind"; falls back to heading only for compass / gps / nav.
407
+ - **AP button "click missed" and engage / disengage bounce**
408
+ hardened: switched from `click` to `pointerdown` (fires once per
409
+ press on both touch and mouse without waiting for the
410
+ browser-synthesised `click`), swallow the trailing `click` with
411
+ `preventDefault + stopPropagation`, `touch-action: manipulation`
412
+ on the button, plus an 800 ms cooldown gate that survives the
413
+ ~200 ms POST round-trip. Ghost taps from `touchend` no longer
414
+ produce a phantom second engage.
415
+ - **Wind speed chip tap regressions.** Chip was picked up by the
416
+ corner-selector `forEach` (auto-attached its 500 ms long-press
417
+ timer → opened the wrong popup) AND the `<main>` tab-swipe
418
+ handler treated any tap-with-drift on it as a horizontal swipe
419
+ → the chip appeared to slide right. Renamed the chip class to
420
+ `.wind-chip` so the forEach ignores it and replaced the shared
421
+ handler with a bespoke `pointerdown/up` short-tap detector that
422
+ stops touch propagation.
423
+ - **HDG chip / compass labels covered by DIA** on engage: reordered
424
+ the SVG stack so the compass card and HDG chip render AFTER the
425
+ gota pieces, never behind them.
426
+ - **DIA arc rendering asymmetry** ("bump on one side") when
427
+ rotated: `stroke-linejoin` switched from `round` to `miter`,
428
+ raya `stroke-linecap` switched from `round` to `butt` to remove
429
+ the semi-circle that overshot the ring line.
430
+
431
+ ### Changed
432
+
433
+ - **Wind speed chip moved from an SVG group to a positioned HTML
434
+ `.wind-chip` div** overlaid on the rose bottom-center. Text
435
+ baseline now aligns with the two bottom corner cells so all
436
+ three values (BL / BC / BR) read as one row.
437
+ - **SVG stacking order** finalised (bottom → top): ring · wind
438
+ sectors · boat sprite · TWA · AWA · DIA · raya · AWA / TWA
439
+ colour ring-ticks · COG line · current vector · compass card ·
440
+ HDG chip. Wind chip is a separate HTML overlay above the SVG.
441
+ - **Restart engine** already switched to `sv restart` (piCore
442
+ runit) in 2.0.4; the docs, i18n text and Info-tab quick-start
443
+ now match — the earlier "three escalated restarts" wording was
444
+ outdated (Emergency section has been 2 buttons since Rev66:
445
+ `RESTART pypilot` + `reboot Pi`; the safe `restart pypilot_web`
446
+ lives in the Debug console).
447
+ - **Info-tab quick-start** rewritten in EN + ES to describe the
448
+ Gota Chain, the 4-card overlay selector, the new cardinal
449
+ colors, and boat-long-press as an alternative selector opener.
450
+ - **README** overview and "Remote restart / reboot" section
451
+ rewritten to match the current 2-button + Debug-console layout,
452
+ and to describe the Gota Chain + optional overlays.
453
+
3
454
  ## 2.0.4 — 2026-08-21 — Rev67
4
455
 
5
456
  Reintroduces (with proper QA) the UI polish + reliability work that was
package/README.md CHANGED
@@ -22,18 +22,28 @@ dashboards wired to 1.0.0 paths, see the full migration table in
22
22
  - `.calibration.rudderRange` (rad) -> `.rudder.range` (deg)
23
23
  - `.gains.<pilot>.<gain>` -> `.ap.pilot.<pilot>.<gain>`
24
24
 
25
- Also new in 2.0.0: three escalated **restart / reboot levels** in
26
- Setup -> Emergency, all guarded by a helm-manned confirmation modal, and
27
- a **Debug console** with an SSH-based whitelist of preset diagnostic
28
- commands (logs, dmesg, top, uptime, df, pypilot version).
25
+ Setup -> Emergency ships **two remote restart buttons** (`RESTART pypilot`
26
+ and `reboot Pi`), both guarded by a helm-manned confirmation modal.
27
+ `restart pypilot_web` (the safe web-only restart that does not interrupt
28
+ steering) lives as a preset in the **Debug console** — an SSH-based
29
+ whitelist of preset diagnostic commands (logs, dmesg, top, uptime, df,
30
+ pypilot version, restart pypilot_web).
29
31
 
30
32
  ## What it does
31
33
 
32
34
  **Touch webapp** (mobile / tablet / chart-plotter, dark theme):
33
35
 
34
- - Compass rose with heading readout, cardinals + degree ticks, hull-fixed
35
- green/red sailing wedges, AWA + TWA arrows (independent, toggleable), cyan
36
- target diamond, and 4 configurable corner tiles (long-press to reconfigure).
36
+ - Compass rose with HDG readout, colour-coded cardinals (N orange, E green,
37
+ S blue, W red) + degree ticks, hull-fixed green/red sailing wedges, and 4
38
+ configurable corner tiles (long-press to reconfigure).
39
+ - **Gota Chain** overlay: three concentric arrow pieces on the rose — cyan
40
+ target diamond, amber `A` (AWA), sea-green `T` (TWA). Interlock into one
41
+ clean droplet when all three angles coincide; the V-hembra of any piece
42
+ that drifts opens up as a visible hollow, and a colour ring-tick marks
43
+ the exact angle on the compass. Optional **COG line** from the bow
44
+ (yellow chevrons) and **current vector** (SOG − SOW, blue wavy arrow)
45
+ can be toggled from a 4-card selector opened by long-press on any
46
+ corner or on the boat sprite.
37
47
  - Big-touch AP engage / disengage with optimistic UI + auto-retry over
38
48
  flaky links (Tailscale-safe).
39
49
  - Tack port / starboard, mode selector (compass / GPS / wind / true wind / nav),
@@ -116,28 +126,29 @@ register the same ID and behaviour is undefined). Valid setups:
116
126
 
117
127
  Absorb mode lives in **Setup → Autopilot Provider (one-socket mode)**.
118
128
 
119
- ## Remote restart / reboot triad + Debug console
120
-
121
- When the autopilot process on the TinyPilot gets wedged you don't need to open
122
- an SSH session by hand. In **Setup → Emergency**, save the TinyPilot's SSH user
123
- + password once. From then on you get three escalated actions, colour-coded
124
- from safest to loudest, each guarded by a helm-manned confirmation modal that
125
- asks whether someone is at the helm before executing:
126
-
127
- 1. **restart pypilot_web** (~3-5 s) - only the web server restarts. The AP
128
- core keeps steering. Use when the visor gets stuck but the pilot is fine.
129
- 2. **RESTART pypilot** (~10-15 s) - restarts pypilot core + web. The AP drops
130
- the heading briefly and re-engages when it comes back up.
131
- 3. **reboot Pi** (~35-60 s) - full `sudo reboot` of the Raspberry Pi. No
132
- autopilot for almost a minute. Last-resort when the box is in a bad state.
133
-
134
- Underneath the triad there is a **Debug console** that runs a closed
135
- whitelist of preset diagnostic commands over the same SSH session:
136
- `logs pypilot`, `logs pypilot_web`, `dmesg`, `top`, `uptime`, `df`,
137
- `pypilot --version`. Output goes into a scrollable textarea, a "Follow
138
- logs" toggle polls `journalctl --since '30 s ago'` every 3 seconds, and
139
- Copy / Share buttons let you paste the dump straight into a GitHub
140
- issue or a WhatsApp / email conversation with your friendly rigger.
129
+ ## Remote restart / reboot + Debug console
130
+
131
+ When the autopilot process on the TinyPilot gets wedged you don't need to
132
+ open an SSH session by hand. In **Setup → Emergency**, save the TinyPilot's
133
+ SSH user + password once. From then on you get **two big restart buttons**,
134
+ each guarded by a helm-manned confirmation modal that asks whether someone
135
+ is at the helm before executing:
136
+
137
+ 1. **RESTART pypilot** (~10-15 s) — `sv restart` of the pypilot core + web
138
+ (runit under piCore). The AP drops the heading briefly and re-engages
139
+ when it comes back up.
140
+ 2. **reboot Pi** (~35-60 s) — full `sudo reboot` of the Raspberry Pi. No
141
+ autopilot for almost a minute. Last-resort when the box is in a bad
142
+ state.
143
+
144
+ The safe **restart pypilot_web** (web server only, does not interrupt
145
+ steering) lives as a preset button in the **Debug console** below,
146
+ alongside a closed whitelist of preset diagnostic commands over the same
147
+ SSH session: `logs pypilot`, `logs pypilot_web`, `dmesg`, `top`, `uptime`,
148
+ `df`, `pypilot --version`. Output goes into a scrollable textarea, a
149
+ "Follow logs" toggle polls `journalctl --since '30 s ago'` every 3
150
+ seconds, and Copy / Share buttons let you paste the dump straight into a
151
+ GitHub issue or a WhatsApp / email conversation with your friendly rigger.
141
152
 
142
153
  The endpoint (`POST /plugins/*/debug-cmd`) refuses any command that is
143
154
  not in the whitelist, so a leaked JWT cannot be used to run arbitrary
@@ -156,8 +167,8 @@ that isolated TinyPilot.
156
167
  | `GET` | `/plugins/signalk-pypilot-newui/paths` | Live list of published SK paths with GET / PUT URLs and units |
157
168
  | `GET` | `/plugins/signalk-pypilot-newui/catalog` | Raw pypilot catalog (all values + metadata) |
158
169
  | `PUT` | `/plugins/signalk-pypilot-newui/raw` | Send raw `name=value` to pypilot (protected by `allowWrites`) |
159
- | `POST` | `/plugins/signalk-pypilot-newui/restart-pypilot` | SSH remote restart (level 2 of the triad), uses `sshUser` + `sshPassword` from plugin config |
160
- | `POST` | `/plugins/signalk-pypilot-newui/debug-cmd` | Run one of a closed whitelist of preset diagnostic / restart commands over SSH (levels 1 and 3 of the triad + logs / dmesg / top / etc). Body: `{ "preset": "<name>" }` |
170
+ | `POST` | `/plugins/signalk-pypilot-newui/restart-pypilot` | SSH `sv restart` of pypilot core+web on the TinyPilot, uses `sshUser` + `sshPassword` from plugin config |
171
+ | `POST` | `/plugins/signalk-pypilot-newui/debug-cmd` | Run one of a closed whitelist of preset diagnostic / restart commands over SSH (`restart.web`, `reboot.pi`, `logs.pypilot`, `logs.web`, `dmesg`, `top`, `uptime`, `df`, `pypilot.version`). Body: `{ "preset": "<name>" }` |
161
172
  | `POST` | `/plugins/signalk-pypilot-newui/pause` | Disconnect local socket (for scripts) |
162
173
  | `POST` | `/plugins/signalk-pypilot-newui/resume` | Reconnect local socket (for scripts) |
163
174