signalk-tides 1.5.0 → 2.0.0-beta.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/.github/workflows/ci.yml +28 -2
- package/.playwright-mcp/console-2026-06-06T09-48-18-232Z.log +1 -0
- package/.playwright-mcp/console-2026-06-12T13-01-03-706Z.log +1 -0
- package/.playwright-mcp/console-2026-06-12T13-15-30-205Z.log +44 -0
- package/.playwright-mcp/console-2026-06-12T13-16-00-389Z.log +1 -0
- package/.playwright-mcp/console-2026-06-12T14-41-49-989Z.log +60 -0
- package/.playwright-mcp/console-2026-06-12T14-51-31-609Z.log +5 -0
- package/README.md +27 -187
- package/dist/calculations.js +33 -20
- package/dist/index.js +103 -59
- package/dist/middleware.js +49 -0
- package/dist/routes.js +176 -0
- package/dist/sources/neaps.js +39 -31
- package/dist/sources/noaa.js +241 -80
- package/dist/sources/stormglass.js +188 -39
- package/dist/sources/worldtides.js +211 -39
- package/package.json +35 -19
- package/public/assets/index-COM80frb.css +1 -0
- package/public/assets/index-TySP7WUU.js +12 -0
- package/public/assets/maplibre-gl-Nnrw_cBX.js +748 -0
- package/public/index.html +3 -3
- package/tides-dev-server.ts +119 -0
- package/tsconfig.json +2 -1
- package/tsconfig.test.json +8 -0
- package/vitest.config.browser.ts +27 -0
- package/vitest.config.node.ts +18 -0
- package/public/assets/index-ClNCI7kN.js +0 -9
- package/public/assets/index-D8qkCL0i.css +0 -1
package/.github/workflows/ci.yml
CHANGED
|
@@ -20,8 +20,8 @@ jobs:
|
|
|
20
20
|
- name: Run linter
|
|
21
21
|
run: npm run lint
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
name:
|
|
23
|
+
test:
|
|
24
|
+
name: Test
|
|
25
25
|
runs-on: ubuntu-latest
|
|
26
26
|
env:
|
|
27
27
|
CI: true
|
|
@@ -35,5 +35,31 @@ jobs:
|
|
|
35
35
|
- name: Install dependencies
|
|
36
36
|
run: npm install
|
|
37
37
|
|
|
38
|
+
- name: Install Playwright browsers
|
|
39
|
+
run: npx playwright install chromium
|
|
40
|
+
|
|
38
41
|
- name: Run build
|
|
39
42
|
run: npm run build
|
|
43
|
+
|
|
44
|
+
- name: Run Tests
|
|
45
|
+
run: npm run test
|
|
46
|
+
|
|
47
|
+
publish:
|
|
48
|
+
needs: [lint, test]
|
|
49
|
+
runs-on: ubuntu-latest
|
|
50
|
+
permissions:
|
|
51
|
+
id-token: write
|
|
52
|
+
pull-requests: write
|
|
53
|
+
steps:
|
|
54
|
+
- uses: actions/checkout@v6
|
|
55
|
+
|
|
56
|
+
- uses: actions/setup-node@v6
|
|
57
|
+
|
|
58
|
+
- name: Install modules
|
|
59
|
+
run: npm install
|
|
60
|
+
|
|
61
|
+
- name: Build
|
|
62
|
+
run: npm run build
|
|
63
|
+
|
|
64
|
+
- name: Publish to pkg.pr.new
|
|
65
|
+
run: npx pkg-pr-new publish
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[ 2058ms] [ERROR] Failed to load resource: net::ERR_NETWORK_IO_SUSPENDED @ https://docs.stormglass.io/_media/logo.svg:0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[ 239ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:3000/signalk-tides/assets/icon.svg:0
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
[ 260ms] [LOG] [ConnectionStateMachine] Service initialized @ http://localhost:3000/@mxtommy/kip/chunk-2TP7C66X.js:0
|
|
2
|
+
[ 265ms] [LOG] [AppInit Network Service] Connection Configuration not found. Creating configuration using Auto-Discovery URL: http://localhost:3000 @ http://localhost:3000/@mxtommy/kip/main-UBENKC2D.js:0
|
|
3
|
+
[ 268ms] [LOG] [ConnectionStateMachine] Starting HTTP discovery: Connecting to http://localhost:3000 @ http://localhost:3000/@mxtommy/kip/chunk-2TP7C66X.js:0
|
|
4
|
+
[ 268ms] [LOG] [Connection Service] Connecting to: http://localhost:3000 @ http://localhost:3000/@mxtommy/kip/chunk-2TP7C66X.js:0
|
|
5
|
+
[ 279ms] [LOG] [ConnectionStateMachine] HTTP discovery successful @ http://localhost:3000/@mxtommy/kip/chunk-2TP7C66X.js:0
|
|
6
|
+
[ 279ms] [LOG] [AppSettings Service] Service startup... @ http://localhost:3000/@mxtommy/kip/chunk-2TP7C66X.js:3
|
|
7
|
+
[ 279ms] [LOG] [AppSettings Service] LocalStorage enabled @ http://localhost:3000/@mxtommy/kip/chunk-2TP7C66X.js:4
|
|
8
|
+
[ 279ms] [LOG] [AppSettings Service] Error loading appConfig config. Force loading appConfig defaults @ http://localhost:3000/@mxtommy/kip/chunk-2TP7C66X.js:4
|
|
9
|
+
[ 279ms] [LOG] [AppSettings Service] Error loading dashboardsConfig config. Force loading dashboardsConfig defaults @ http://localhost:3000/@mxtommy/kip/chunk-2TP7C66X.js:4
|
|
10
|
+
[ 279ms] [LOG] [AppSettings Service] Error loading themeConfig config. Force loading themeConfig defaults @ http://localhost:3000/@mxtommy/kip/chunk-2TP7C66X.js:4
|
|
11
|
+
[ 280ms] [LOG] [AppSettings Service] Saving Application config to LocalStorage @ http://localhost:3000/@mxtommy/kip/chunk-2TP7C66X.js:4
|
|
12
|
+
[ 280ms] [LOG] [DatasetStreamService] Auto Starting 0 Datasets @ http://localhost:3000/@mxtommy/kip/chunk-5SMHTIVS.js:0
|
|
13
|
+
[ 280ms] [LOG] [AppInit Network Service] Initialization completed @ http://localhost:3000/@mxtommy/kip/main-UBENKC2D.js:0
|
|
14
|
+
[ 280ms] [LOG] [ConnectionStateMachine] WebSocket mode enabled @ http://localhost:3000/@mxtommy/kip/chunk-2TP7C66X.js:0
|
|
15
|
+
[ 280ms] [LOG] [AppInit Network Service] Starting WebSocket connection after initialization @ http://localhost:3000/@mxtommy/kip/main-UBENKC2D.js:0
|
|
16
|
+
[ 280ms] [LOG] [ConnectionStateMachine] Starting WebSocket connection @ http://localhost:3000/@mxtommy/kip/chunk-2TP7C66X.js:0
|
|
17
|
+
[ 280ms] [LOG] [Delta Service] ConnectionStateMachine request: WebSocket opening... @ http://localhost:3000/@mxtommy/kip/chunk-IXUKD73N.js:0
|
|
18
|
+
[ 287ms] [WARNING] [Dashboard Service] No dashboards found in settings, creating blank dashboard @ http://localhost:3000/@mxtommy/kip/chunk-5SMHTIVS.js:0
|
|
19
|
+
[ 289ms] [LOG] [Remote Dashboards] Cleaning paths on server @ http://localhost:3000/@mxtommy/kip/main-UBENKC2D.js:0
|
|
20
|
+
[ 290ms] [LOG] [UI Event Service] PWA mode: false @ http://localhost:3000/@mxtommy/kip/chunk-5SMHTIVS.js:49
|
|
21
|
+
[ 300ms] [LOG] *********** KIP Version Information *********** @ http://localhost:3000/@mxtommy/kip/chunk-NS2OV2OW.js:0
|
|
22
|
+
[ 300ms] [LOG] ** App Version: 4.8.0 @ http://localhost:3000/@mxtommy/kip/chunk-NS2OV2OW.js:0
|
|
23
|
+
[ 300ms] [LOG] ** Browser Version: Chrome 149 @ http://localhost:3000/@mxtommy/kip/chunk-NS2OV2OW.js:0
|
|
24
|
+
[ 300ms] [LOG] ** OS Version: macOS @ http://localhost:3000/@mxtommy/kip/chunk-NS2OV2OW.js:0
|
|
25
|
+
[ 300ms] [LOG] *********************************************** @ http://localhost:3000/@mxtommy/kip/chunk-NS2OV2OW.js:0
|
|
26
|
+
[ 305ms] [LOG] [AppSettings Service] Saving Dashboard config to LocalStorage @ http://localhost:3000/@mxtommy/kip/chunk-2TP7C66X.js:4
|
|
27
|
+
[ 323ms] [LOG] [Delta Service] WebSocket connected without Authorization Token @ http://localhost:3000/@mxtommy/kip/chunk-IXUKD73N.js:0
|
|
28
|
+
[ 324ms] [LOG] [ConnectionStateMachine] WebSocket connected @ http://localhost:3000/@mxtommy/kip/chunk-2TP7C66X.js:0
|
|
29
|
+
[ 324ms] [LOG] [Connection Service] Server Name: signalk-server, Version: 2.23.0-beta.1, Roles: ["master","main"] @ http://localhost:3000/@mxtommy/kip/chunk-2TP7C66X.js:0
|
|
30
|
+
[ 437ms] [WARNING] [Request Service] Status Code: 403 - DENIED: Authorization with R/W or Admin permission level is required to send commands. Configure Sign In credential. @ http://localhost:3000/@mxtommy/kip/chunk-W6MCE3GH.js:0
|
|
31
|
+
[ 437ms] [WARNING] [Request Service] Status Code: 403 - DENIED: Authorization with R/W or Admin permission level is required to send commands. Configure Sign In credential. @ http://localhost:3000/@mxtommy/kip/chunk-W6MCE3GH.js:0
|
|
32
|
+
[ 437ms] [WARNING] [Request Service] Status Code: 403 - DENIED: Authorization with R/W or Admin permission level is required to send commands. Configure Sign In credential. @ http://localhost:3000/@mxtommy/kip/chunk-W6MCE3GH.js:0
|
|
33
|
+
[ 450ms] [WARNING] An iframe which has both allow-scripts and allow-same-origin for its sandbox attribute can escape its sandboxing. @ http://localhost:3000/@mxtommy/kip/chunk-LEY6MANN.js:3
|
|
34
|
+
[ 515ms] [WARNING] An iframe which has both allow-scripts and allow-same-origin for its sandbox attribute can escape its sandboxing. @ http://localhost:3000/@signalk/freeboard-sk/:0
|
|
35
|
+
[ 1311ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:3000/plugins/freeboard-sk:0
|
|
36
|
+
[ 1387ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:3000/plugins/kip:0
|
|
37
|
+
[ 1387ms] [LOG] [KipSeriesApiClientService] POST http://localhost:3000/plugins/kip/series/reconcile (0 series) @ http://localhost:3000/@mxtommy/kip/chunk-6ZR3M3IQ.js:2
|
|
38
|
+
[ 1403ms] [INFO] Internet connection detected. @ http://localhost:3000/@signalk/freeboard-sk/main-YHMZXR5G.js:249
|
|
39
|
+
[ 1414ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:3000/plugins/kip/series/reconcile:0
|
|
40
|
+
[ 1414ms] [ERROR] [KipSeriesApiClientService] Series reconcile request failed: Ar @ http://localhost:3000/@mxtommy/kip/chunk-6ZR3M3IQ.js:2
|
|
41
|
+
[ 1517ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:3000/signalk/v1/api/vessels/self/navigation/anchor:0
|
|
42
|
+
[ 1784ms] [WARNING] Blocked aria-hidden on an element because its descendant retained focus. The focus must not be hidden from assistive technology users. Avoid using aria-hidden on a focused element or its ancestor. Consider using the inert attribute instead, which will also prevent focus. For more details, see the aria-hidden section of the WAI-ARIA specification at https://w3c.github.io/aria/#aria-hidden.
|
|
43
|
+
Element with focus: <div>
|
|
44
|
+
Ancestor with aria-hidden: <app-root> @ http://localhost:3000/@signalk/freeboard-sk/:0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[ 68ms] [LOG] [Delta Service] App suspended @ http://localhost:3000/@mxtommy/kip/chunk-IXUKD73N.js:0
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
[ 188ms] [LOG] [ConnectionStateMachine] Service initialized @ http://localhost:3000/@mxtommy/kip/chunk-2TP7C66X.js:0
|
|
2
|
+
[ 191ms] [LOG] [ConnectionStateMachine] Starting HTTP discovery: Connecting to http://localhost:3000 @ http://localhost:3000/@mxtommy/kip/chunk-2TP7C66X.js:0
|
|
3
|
+
[ 192ms] [LOG] [Connection Service] Connecting to: http://localhost:3000 @ http://localhost:3000/@mxtommy/kip/chunk-2TP7C66X.js:0
|
|
4
|
+
[ 213ms] [LOG] [ConnectionStateMachine] HTTP discovery successful @ http://localhost:3000/@mxtommy/kip/chunk-2TP7C66X.js:0
|
|
5
|
+
[ 214ms] [LOG] [AppSettings Service] Service startup... @ http://localhost:3000/@mxtommy/kip/chunk-2TP7C66X.js:3
|
|
6
|
+
[ 214ms] [LOG] [AppSettings Service] LocalStorage enabled @ http://localhost:3000/@mxtommy/kip/chunk-2TP7C66X.js:4
|
|
7
|
+
[ 214ms] [LOG] [DatasetStreamService] Auto Starting 0 Datasets @ http://localhost:3000/@mxtommy/kip/chunk-5SMHTIVS.js:0
|
|
8
|
+
[ 214ms] [LOG] [AppInit Network Service] Initialization completed @ http://localhost:3000/@mxtommy/kip/main-UBENKC2D.js:0
|
|
9
|
+
[ 214ms] [LOG] [ConnectionStateMachine] WebSocket mode enabled @ http://localhost:3000/@mxtommy/kip/chunk-2TP7C66X.js:0
|
|
10
|
+
[ 214ms] [LOG] [AppInit Network Service] Starting WebSocket connection after initialization @ http://localhost:3000/@mxtommy/kip/main-UBENKC2D.js:0
|
|
11
|
+
[ 214ms] [LOG] [ConnectionStateMachine] Starting WebSocket connection @ http://localhost:3000/@mxtommy/kip/chunk-2TP7C66X.js:0
|
|
12
|
+
[ 215ms] [LOG] [Delta Service] ConnectionStateMachine request: WebSocket opening... @ http://localhost:3000/@mxtommy/kip/chunk-IXUKD73N.js:0
|
|
13
|
+
[ 220ms] [LOG] [Remote Dashboards] Cleaning paths on server @ http://localhost:3000/@mxtommy/kip/main-UBENKC2D.js:0
|
|
14
|
+
[ 221ms] [LOG] [UI Event Service] PWA mode: false @ http://localhost:3000/@mxtommy/kip/chunk-5SMHTIVS.js:49
|
|
15
|
+
[ 226ms] [LOG] *********** KIP Version Information *********** @ http://localhost:3000/@mxtommy/kip/chunk-NS2OV2OW.js:0
|
|
16
|
+
[ 226ms] [LOG] ** App Version: 4.8.0 @ http://localhost:3000/@mxtommy/kip/chunk-NS2OV2OW.js:0
|
|
17
|
+
[ 226ms] [LOG] ** Browser Version: Chrome 149 @ http://localhost:3000/@mxtommy/kip/chunk-NS2OV2OW.js:0
|
|
18
|
+
[ 226ms] [LOG] ** OS Version: macOS @ http://localhost:3000/@mxtommy/kip/chunk-NS2OV2OW.js:0
|
|
19
|
+
[ 226ms] [LOG] *********************************************** @ http://localhost:3000/@mxtommy/kip/chunk-NS2OV2OW.js:0
|
|
20
|
+
[ 229ms] [LOG] [AppSettings Service] Saving Dashboard config to LocalStorage @ http://localhost:3000/@mxtommy/kip/chunk-2TP7C66X.js:4
|
|
21
|
+
[ 248ms] [LOG] [Delta Service] WebSocket connected without Authorization Token @ http://localhost:3000/@mxtommy/kip/chunk-IXUKD73N.js:0
|
|
22
|
+
[ 248ms] [LOG] [ConnectionStateMachine] WebSocket connected @ http://localhost:3000/@mxtommy/kip/chunk-2TP7C66X.js:0
|
|
23
|
+
[ 249ms] [LOG] [Connection Service] Server Name: signalk-server, Version: 2.23.0-beta.1, Roles: ["master","main"] @ http://localhost:3000/@mxtommy/kip/chunk-2TP7C66X.js:0
|
|
24
|
+
[ 370ms] [WARNING] [Request Service] Status Code: 403 - DENIED: Authorization with R/W or Admin permission level is required to send commands. Configure Sign In credential. @ http://localhost:3000/@mxtommy/kip/chunk-W6MCE3GH.js:0
|
|
25
|
+
[ 370ms] [WARNING] [Request Service] Status Code: 403 - DENIED: Authorization with R/W or Admin permission level is required to send commands. Configure Sign In credential. @ http://localhost:3000/@mxtommy/kip/chunk-W6MCE3GH.js:0
|
|
26
|
+
[ 370ms] [WARNING] [Request Service] Status Code: 403 - DENIED: Authorization with R/W or Admin permission level is required to send commands. Configure Sign In credential. @ http://localhost:3000/@mxtommy/kip/chunk-W6MCE3GH.js:0
|
|
27
|
+
[ 380ms] [WARNING] An iframe which has both allow-scripts and allow-same-origin for its sandbox attribute can escape its sandboxing. @ http://localhost:3000/@mxtommy/kip/chunk-LEY6MANN.js:3
|
|
28
|
+
[ 476ms] [WARNING] An iframe which has both allow-scripts and allow-same-origin for its sandbox attribute can escape its sandboxing. @ http://localhost:3000/@signalk/freeboard-sk/:0
|
|
29
|
+
[ 934ms] [INFO] Internet connection detected. @ http://localhost:3000/@signalk/freeboard-sk/main-YHMZXR5G.js:249
|
|
30
|
+
[ 940ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:3000/plugins/freeboard-sk:0
|
|
31
|
+
[ 1000ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:3000/plugins/kip:0
|
|
32
|
+
[ 1000ms] [LOG] [KipSeriesApiClientService] POST http://localhost:3000/plugins/kip/series/reconcile (0 series) @ http://localhost:3000/@mxtommy/kip/chunk-6ZR3M3IQ.js:2
|
|
33
|
+
[ 1007ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:3000/plugins/kip/series/reconcile:0
|
|
34
|
+
[ 1007ms] [ERROR] [KipSeriesApiClientService] Series reconcile request failed: Ar @ http://localhost:3000/@mxtommy/kip/chunk-6ZR3M3IQ.js:2
|
|
35
|
+
[ 1073ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:3000/signalk/v1/api/vessels/self/navigation/anchor:0
|
|
36
|
+
[ 87530ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:3000/plugins/freeboard-sk:0
|
|
37
|
+
[ 87531ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:3000/plugins/anchoralarm:0
|
|
38
|
+
[ 87532ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:3000/plugins/tracks:0
|
|
39
|
+
[ 87532ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:3000/plugins/signalk-polar-performance-plugin:0
|
|
40
|
+
[ 87532ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:3000/plugins/resources-provider:0
|
|
41
|
+
[ 87536ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:3000/plugins/signalk-racer:0
|
|
42
|
+
[ 87572ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:3000/plugins/course-provider:0
|
|
43
|
+
[ 87573ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:3000/plugins/autopilot:0
|
|
44
|
+
[ 87573ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:3000/plugins/pypilot-autopilot-provider:0
|
|
45
|
+
[ 112153ms] [ERROR] ERROR _: NG0951
|
|
46
|
+
at Object.computation (http://localhost:3000/@mxtommy/kip/chunk-LEY6MANN.js:4:94168)
|
|
47
|
+
at Object.producerRecomputeValue (http://localhost:3000/@mxtommy/kip/chunk-LEY6MANN.js:3:33213)
|
|
48
|
+
at Qn (http://localhost:3000/@mxtommy/kip/chunk-LEY6MANN.js:3:30918)
|
|
49
|
+
at n.r [as iframe] (http://localhost:3000/@mxtommy/kip/chunk-LEY6MANN.js:3:32825)
|
|
50
|
+
at n.ngAfterViewInit (http://localhost:3000/@mxtommy/kip/chunk-5SMHTIVS.js:44:361583)
|
|
51
|
+
at ng (http://localhost:3000/@mxtommy/kip/chunk-LEY6MANN.js:4:27312)
|
|
52
|
+
at rI (http://localhost:3000/@mxtommy/kip/chunk-LEY6MANN.js:4:27474)
|
|
53
|
+
at Gg (http://localhost:3000/@mxtommy/kip/chunk-LEY6MANN.js:4:27201)
|
|
54
|
+
at wa (http://localhost:3000/@mxtommy/kip/chunk-LEY6MANN.js:4:26929)
|
|
55
|
+
at bS (http://localhost:3000/@mxtommy/kip/chunk-LEY6MANN.js:4:67813) @ http://localhost:3000/@mxtommy/kip/chunk-LEY6MANN.js:3
|
|
56
|
+
[ 263184ms] [LOG] [AppSettings Service] Saving Dashboard config to LocalStorage @ http://localhost:3000/@mxtommy/kip/chunk-2TP7C66X.js:4
|
|
57
|
+
[ 263185ms] [LOG] [AppSettings Service] Saving Application config to LocalStorage @ http://localhost:3000/@mxtommy/kip/chunk-2TP7C66X.js:4
|
|
58
|
+
[ 399636ms] [LOG] [AppSettings Service] Saving Dashboard config to LocalStorage @ http://localhost:3000/@mxtommy/kip/chunk-2TP7C66X.js:4
|
|
59
|
+
[ 399636ms] [LOG] [AppSettings Service] Saving Application config to LocalStorage @ http://localhost:3000/@mxtommy/kip/chunk-2TP7C66X.js:4
|
|
60
|
+
[ 4767580ms] [LOG] [Delta Service] App suspended @ http://localhost:3000/@mxtommy/kip/chunk-IXUKD73N.js:0
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
[ 2353ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:3000/skServer/plugins:0
|
|
2
|
+
[ 2353ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:3000/skServer/appstore/available:0
|
|
3
|
+
[ 2353ms] [ERROR] Failed to load resource: the server responded with a status of 401 (Unauthorized) @ http://localhost:3000/skServer/security/access/requests:0
|
|
4
|
+
[ 2427ms] [LOG] connected @ http://localhost:3000/admin/assets/bootstrap-BbNbkfZh.js:69
|
|
5
|
+
[ 3712ms] [ERROR] Failed to load resource: the server responded with a status of 404 (Not Found) @ http://localhost:3000/signalk-usage/assets/icons/signalk-usage-icon_72x72.png:0
|
package/README.md
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# signalk-tides
|
|
2
2
|
|
|
3
|
-
A SignalK plugin that provides tidal predictions for the vessel's position
|
|
3
|
+
A SignalK plugin that provides offline tidal predictions for the vessel's position, powered by [Neaps](https://github.com/neaps/neaps).
|
|
4
|
+
|
|
5
|
+
Since 2.0, predictions are computed locally from harmonic constituents — no network access or API keys required.
|
|
4
6
|
|
|
5
7
|
## Installation
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
Install `signalk-tides` from the SignalK Appstore or manually by running `npm install signalk-tides` in the SignalK server directory (`~/.signalk`).
|
|
8
10
|
|
|
9
|
-
2. Optionally go to the plugin settings in "Server => Plugin Config => Tides" and configure which source to use.
|
|
10
11
|
|
|
11
12
|
## Usage
|
|
12
13
|
|
|
@@ -20,205 +21,44 @@ It publishes the following [tide data](https://signalk.org/specification/1.7.0/d
|
|
|
20
21
|
* `environment.tide.timeLow`
|
|
21
22
|
* `environment.tide.heightNow`
|
|
22
23
|
* `environment.tide.stationName`
|
|
24
|
+
* `environment.tide.state` — tide trend, `rising` or `falling`
|
|
25
|
+
* `environment.tide.timeToNextExtreme` — seconds until the next high or low water
|
|
23
26
|
|
|
24
|
-
### Tides
|
|
27
|
+
### Tides API
|
|
25
28
|
|
|
26
|
-
|
|
29
|
+
The plugin mounts the [Neaps API](https://github.com/neaps/neaps) at `/signalk/v2/api/tides`, which serves station search, extremes, and timeline predictions. The synthetic station `vessel/current` resolves to the nearest station to the vessel:
|
|
27
30
|
|
|
28
31
|
```
|
|
29
|
-
$ curl http://localhost:3000/signalk/v2/api/
|
|
32
|
+
$ curl http://localhost:3000/signalk/v2/api/tides/stations/vessel/current/extremes
|
|
30
33
|
```
|
|
31
34
|
|
|
32
|
-
|
|
35
|
+
### Tides resource
|
|
33
36
|
|
|
34
|
-
|
|
37
|
+
It also registers a `tides` resource, which returns the next 7 days of tide extremes for the vessel's position.
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
$ curl http://localhost:3000/signalk/v2/api/resources/tides
|
|
41
|
+
```
|
|
35
42
|
|
|
36
43
|
##### Response
|
|
37
44
|
|
|
38
45
|
```json
|
|
39
46
|
{
|
|
40
|
-
"
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
"time" : "2025-03-29T13:18:00.000Z",
|
|
53
|
-
"type" : "Low",
|
|
54
|
-
"value" : 0.044
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
"time" : "2025-03-29T19:45:00.000Z",
|
|
58
|
-
"type" : "High",
|
|
59
|
-
"value" : 1.815
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
"time" : "2025-03-30T01:24:00.000Z",
|
|
63
|
-
"type" : "Low",
|
|
64
|
-
"value" : 0.164
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
"time" : "2025-03-30T07:52:00.000Z",
|
|
68
|
-
"type" : "High",
|
|
69
|
-
"value" : 2.024
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
"time" : "2025-03-30T14:05:00.000Z",
|
|
73
|
-
"type" : "Low",
|
|
74
|
-
"value" : -0.131
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
"time" : "2025-03-30T20:43:00.000Z",
|
|
78
|
-
"type" : "High",
|
|
79
|
-
"value" : 1.733
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
"time" : "2025-03-31T02:05:00.000Z",
|
|
83
|
-
"type" : "Low",
|
|
84
|
-
"value" : 0.334
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
"time" : "2025-03-31T08:27:00.000Z",
|
|
88
|
-
"type" : "High",
|
|
89
|
-
"value" : 2.084
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
"time" : "2025-03-31T14:53:00.000Z",
|
|
93
|
-
"type" : "Low",
|
|
94
|
-
"value" : -0.247
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
"time" : "2025-03-31T21:44:00.000Z",
|
|
98
|
-
"type" : "High",
|
|
99
|
-
"value" : 1.632
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
"time" : "2025-04-01T02:48:00.000Z",
|
|
103
|
-
"type" : "Low",
|
|
104
|
-
"value" : 0.517
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
"time" : "2025-04-01T09:06:00.000Z",
|
|
108
|
-
"type" : "High",
|
|
109
|
-
"value" : 2.094
|
|
110
|
-
},
|
|
111
|
-
{
|
|
112
|
-
"time" : "2025-04-01T15:46:00.000Z",
|
|
113
|
-
"type" : "Low",
|
|
114
|
-
"value" : -0.29
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
"time" : "2025-04-01T22:51:00.000Z",
|
|
118
|
-
"type" : "High",
|
|
119
|
-
"value" : 1.529
|
|
120
|
-
},
|
|
121
|
-
{
|
|
122
|
-
"time" : "2025-04-02T03:37:00.000Z",
|
|
123
|
-
"type" : "Low",
|
|
124
|
-
"value" : 0.695
|
|
125
|
-
},
|
|
126
|
-
{
|
|
127
|
-
"time" : "2025-04-02T09:49:00.000Z",
|
|
128
|
-
"type" : "High",
|
|
129
|
-
"value" : 2.05
|
|
130
|
-
},
|
|
131
|
-
{
|
|
132
|
-
"time" : "2025-04-02T16:43:00.000Z",
|
|
133
|
-
"type" : "Low",
|
|
134
|
-
"value" : -0.263
|
|
135
|
-
},
|
|
136
|
-
{
|
|
137
|
-
"time" : "2025-04-03T00:04:00.000Z",
|
|
138
|
-
"type" : "High",
|
|
139
|
-
"value" : 1.448
|
|
140
|
-
},
|
|
141
|
-
{
|
|
142
|
-
"time" : "2025-04-03T04:35:00.000Z",
|
|
143
|
-
"type" : "Low",
|
|
144
|
-
"value" : 0.847
|
|
145
|
-
},
|
|
146
|
-
{
|
|
147
|
-
"time" : "2025-04-03T10:39:00.000Z",
|
|
148
|
-
"type" : "High",
|
|
149
|
-
"value" : 1.957
|
|
150
|
-
},
|
|
151
|
-
{
|
|
152
|
-
"time" : "2025-04-03T17:50:00.000Z",
|
|
153
|
-
"type" : "Low",
|
|
154
|
-
"value" : -0.189
|
|
155
|
-
},
|
|
156
|
-
{
|
|
157
|
-
"time" : "2025-04-04T01:24:00.000Z",
|
|
158
|
-
"type" : "High",
|
|
159
|
-
"value" : 1.421
|
|
160
|
-
},
|
|
161
|
-
{
|
|
162
|
-
"time" : "2025-04-04T05:49:00.000Z",
|
|
163
|
-
"type" : "Low",
|
|
164
|
-
"value" : 0.946
|
|
165
|
-
},
|
|
166
|
-
{
|
|
167
|
-
"time" : "2025-04-04T11:40:00.000Z",
|
|
168
|
-
"type" : "High",
|
|
169
|
-
"value" : 1.837
|
|
170
|
-
},
|
|
171
|
-
{
|
|
172
|
-
"time" : "2025-04-04T19:07:00.000Z",
|
|
173
|
-
"type" : "Low",
|
|
174
|
-
"value" : -0.11
|
|
175
|
-
},
|
|
176
|
-
{
|
|
177
|
-
"time" : "2025-04-05T02:40:00.000Z",
|
|
178
|
-
"type" : "High",
|
|
179
|
-
"value" : 1.455
|
|
180
|
-
},
|
|
181
|
-
{
|
|
182
|
-
"time" : "2025-04-05T07:19:00.000Z",
|
|
183
|
-
"type" : "Low",
|
|
184
|
-
"value" : 0.958
|
|
185
|
-
},
|
|
186
|
-
{
|
|
187
|
-
"time" : "2025-04-05T12:53:00.000Z",
|
|
188
|
-
"type" : "High",
|
|
189
|
-
"value" : 1.728
|
|
190
|
-
},
|
|
191
|
-
{
|
|
192
|
-
"time" : "2025-04-05T20:25:00.000Z",
|
|
193
|
-
"type" : "Low",
|
|
194
|
-
"value" : -0.061
|
|
195
|
-
}
|
|
196
|
-
],
|
|
197
|
-
"station" : {
|
|
198
|
-
"name" : "Rincon Point, Pier 22 1/2",
|
|
199
|
-
"position" : {
|
|
200
|
-
"latitude" : 37.79,
|
|
201
|
-
"longitude" : -122.387
|
|
202
|
-
}
|
|
203
|
-
}
|
|
47
|
+
"datum": "MLLW",
|
|
48
|
+
"units": "meters",
|
|
49
|
+
"station": {
|
|
50
|
+
"id": "noaa/9414290",
|
|
51
|
+
"name": "San Francisco",
|
|
52
|
+
"latitude": 37.806,
|
|
53
|
+
"longitude": -122.465
|
|
54
|
+
},
|
|
55
|
+
"extremes": [
|
|
56
|
+
{ "time": "2025-03-29T00:45:00.000Z", "level": 0.025, "high": false, "low": true, "label": "Low" },
|
|
57
|
+
{ "time": "2025-03-29T07:20:00.000Z", "level": 1.928, "high": true, "low": false, "label": "High" }
|
|
58
|
+
]
|
|
204
59
|
}
|
|
205
60
|
```
|
|
206
61
|
|
|
207
|
-
## Sources
|
|
208
|
-
|
|
209
|
-
- [Neaps](https://github.com/neaps/neaps)
|
|
210
|
-
- Offline, open source, runs locally
|
|
211
|
-
- Coverage: Regional — United States and territories (currently)
|
|
212
|
-
- [NOAA](https://tidesandcurrents.noaa.gov/web_services_info.html)
|
|
213
|
-
- Online (NOAA web services)
|
|
214
|
-
- Regional — United States and territories
|
|
215
|
-
- [WorldTides API](https://www.worldtides.info/)
|
|
216
|
-
- Online (requires API key, subject to API quotas)
|
|
217
|
-
- Coverage: Global - station and model coverage varies by location
|
|
218
|
-
- [StormGlass.io](https://stormglass.io/)
|
|
219
|
-
- Online (requires API key)
|
|
220
|
-
- Coverage: Global - aggregated marine data; tide availability varies
|
|
221
|
-
|
|
222
62
|
## License
|
|
223
63
|
|
|
224
64
|
This plugin is a fork of the [signalk-tides-api](https://github.com/joabakk/signalk-tides-api) plugin (which is no longer working) and is licensed under the [Apache License 2.0](LICENSE). Kudos to @joabakk and @sbender9 for the original work.
|
package/dist/calculations.js
CHANGED
|
@@ -1,24 +1,37 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Trend of the tide at `time`: "rising" if the next extreme is a High,
|
|
3
|
+
* "falling" if it is a Low.
|
|
4
|
+
*
|
|
5
|
+
* Boundary: at the instant of an extreme the extreme itself satisfies
|
|
6
|
+
* `extreme.time >= time`, so it is still "next", and the state reads as that
|
|
7
|
+
* extreme's own type — e.g. "falling" with timeToNextExtreme 0 at the instant
|
|
8
|
+
* of low water — flipping on the following tick. Simplest consistent rule at
|
|
9
|
+
* one-minute resolution.
|
|
10
|
+
*
|
|
11
|
+
* Returns null when the forecast has no upcoming extreme (stale data).
|
|
12
|
+
*/
|
|
13
|
+
export function tideStateAt(extremes, time) {
|
|
14
|
+
const next = nextExtremeAt(extremes, time);
|
|
8
15
|
if (!next)
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
(new Date(next.time).getTime() - new Date(prev.time).getTime());
|
|
12
|
-
const value = interpolate(prev.value, next.value, easeSine(progress));
|
|
13
|
-
return parseFloat(value.toFixed(3));
|
|
16
|
+
return null;
|
|
17
|
+
return next.high ? "rising" : "falling";
|
|
14
18
|
}
|
|
15
|
-
/**
|
|
16
|
-
function
|
|
17
|
-
return
|
|
19
|
+
/** First extreme at or after `time`, or undefined. Tolerates unsorted input. */
|
|
20
|
+
function nextExtremeAt(extremes, time) {
|
|
21
|
+
return extremes
|
|
22
|
+
.slice()
|
|
23
|
+
.sort((a, b) => a.time.getTime() - b.time.getTime())
|
|
24
|
+
.find((extreme) => extreme.time >= time);
|
|
18
25
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Whole seconds (rounded up) until the next tide extreme (high or low water)
|
|
28
|
+
* at `time`, or null when the forecast has no upcoming extreme. Ceiling keeps
|
|
29
|
+
* the countdown > 0 until the extreme is actually reached; see tideStateAt
|
|
30
|
+
* for the exactly-at-extreme boundary behaviour (this returns 0 for that tick).
|
|
31
|
+
*/
|
|
32
|
+
export function timeToNextExtreme(extremes, time) {
|
|
33
|
+
const next = nextExtremeAt(extremes, time);
|
|
34
|
+
if (!next)
|
|
35
|
+
return null;
|
|
36
|
+
return Math.ceil((next.time.getTime() - time.getTime()) / 1000);
|
|
24
37
|
}
|