@meri-imperiumi/signalk-mob-notifier 1.1.7 → 1.1.8
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/publish.yml +4 -3
- package/CHANGELOG.md +43 -19
- package/README.md +1 -1
- package/doc/appicon-256.png +0 -0
- package/package.json +5 -4
- package/plugin/index.js +1 -1
- package/test/plugin.test.js +85 -0
|
@@ -19,12 +19,13 @@ jobs:
|
|
|
19
19
|
publish-npm:
|
|
20
20
|
needs: build
|
|
21
21
|
runs-on: ubuntu-latest
|
|
22
|
+
permissions:
|
|
23
|
+
id-token: write # Required for OIDC
|
|
24
|
+
contents: read
|
|
22
25
|
steps:
|
|
23
26
|
- uses: actions/checkout@v5
|
|
24
27
|
- uses: actions/setup-node@v6
|
|
25
28
|
with:
|
|
26
|
-
node-version:
|
|
29
|
+
node-version: 24
|
|
27
30
|
registry-url: https://registry.npmjs.org/
|
|
28
31
|
- run: npm publish
|
|
29
|
-
env:
|
|
30
|
-
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,20 +1,44 @@
|
|
|
1
|
-
|
|
2
|
-
- Added application icon
|
|
3
|
-
* 1.1.6 (2026-01-20)
|
|
4
|
-
- Round distance to beacon with single decimal
|
|
5
|
-
- Use EPIRB and SART terms for shorter notifications
|
|
6
|
-
* 1.1.5 (2025-11-15)
|
|
7
|
-
- Bump release
|
|
8
|
-
* 1.1.4 (2025-11-12)
|
|
9
|
-
- Fix reading MOB vessel data structure
|
|
10
|
-
* 1.1.3 (2025-11-02)
|
|
11
|
-
- Fix detection of beacon type (MOB/SART/EPIRB)
|
|
12
|
-
* 1.1.2 (2025-11-01)
|
|
13
|
-
- Better approach at getting MOB coordinates
|
|
14
|
-
* 1.1.1 (2025-09-18)
|
|
15
|
-
- Notifications include position when available
|
|
16
|
-
* 1.1.0 (2025-09-04)
|
|
17
|
-
- Notification is not re-published if it already exists
|
|
18
|
-
* 1.0.0 (2025-08-25)
|
|
19
|
-
- Initial release
|
|
1
|
+
# Changelog
|
|
20
2
|
|
|
3
|
+
## [Unreleased]
|
|
4
|
+
|
|
5
|
+
## [1.1.8] - 2026-10-05
|
|
6
|
+
### Changed
|
|
7
|
+
- Bump the `where` dependency to `^0.4.3`, which normalizes its bearing/direction longitude delta across the antimeridian (the upstream fix). The MOB message's distance and direction were already seam-safe — the haversine and bearing trig folds the seam — so this is a stay-current bump, pinning the upstream antimeridian-hardened version
|
|
8
|
+
|
|
9
|
+
## [1.1.7] - 2026-06-16
|
|
10
|
+
### Added
|
|
11
|
+
- Added application icon
|
|
12
|
+
|
|
13
|
+
## [1.1.6] - 2026-01-20
|
|
14
|
+
### Changed
|
|
15
|
+
- Round distance to beacon with single decimal
|
|
16
|
+
- Use EPIRB and SART terms for shorter notifications
|
|
17
|
+
|
|
18
|
+
## [1.1.5] - 2025-11-15
|
|
19
|
+
### Changed
|
|
20
|
+
- Bump release
|
|
21
|
+
|
|
22
|
+
## [1.1.4] - 2025-11-12
|
|
23
|
+
### Fixed
|
|
24
|
+
- Fix reading MOB vessel data structure
|
|
25
|
+
|
|
26
|
+
## [1.1.3] - 2025-11-02
|
|
27
|
+
### Fixed
|
|
28
|
+
- Fix detection of beacon type (MOB/SART/EPIRB)
|
|
29
|
+
|
|
30
|
+
## [1.1.2] - 2025-11-01
|
|
31
|
+
### Fixed
|
|
32
|
+
- Better approach at getting MOB coordinates
|
|
33
|
+
|
|
34
|
+
## [1.1.1] - 2025-09-18
|
|
35
|
+
### Changed
|
|
36
|
+
- Notifications include position when available
|
|
37
|
+
|
|
38
|
+
## [1.1.0] - 2025-09-04
|
|
39
|
+
### Changed
|
|
40
|
+
- Notification is not re-published if it already exists
|
|
41
|
+
|
|
42
|
+
## [1.0.0] - 2025-08-25
|
|
43
|
+
### Added
|
|
44
|
+
- Initial release
|
package/README.md
CHANGED
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meri-imperiumi/signalk-mob-notifier",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.8",
|
|
4
4
|
"description": "Create Signal K notifications for discovered AIS MOB, EPIRB, and SART beacons",
|
|
5
5
|
"main": "plugin/index.js",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"
|
|
7
|
+
"pretest": "eslint .",
|
|
8
|
+
"test": "node --test"
|
|
8
9
|
},
|
|
9
10
|
"repository": {
|
|
10
11
|
"type": "git",
|
|
@@ -30,11 +31,11 @@
|
|
|
30
31
|
"eslint-plugin-import": "^2.32.0"
|
|
31
32
|
},
|
|
32
33
|
"dependencies": {
|
|
33
|
-
"where": "^0.4.
|
|
34
|
+
"where": "^0.4.3"
|
|
34
35
|
},
|
|
35
36
|
"signalk-plugin-enabled-by-default": true,
|
|
36
37
|
"signalk": {
|
|
37
|
-
"appIcon": "./doc/appicon.png",
|
|
38
|
+
"appIcon": "./doc/appicon-256.png",
|
|
38
39
|
"displayName": "AIS MOB and EPIRB notifier",
|
|
39
40
|
"screenshots": [
|
|
40
41
|
"./doc/alert.png"
|
package/plugin/index.js
CHANGED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
const { describe, it } = require('node:test');
|
|
2
|
+
const assert = require('node:assert/strict');
|
|
3
|
+
|
|
4
|
+
const pluginFactory = require('../plugin/index');
|
|
5
|
+
|
|
6
|
+
describe('plugin', () => {
|
|
7
|
+
const app = { debug: () => {}, error: () => {} };
|
|
8
|
+
const plugin = pluginFactory(app);
|
|
9
|
+
|
|
10
|
+
it('has required interface', () => {
|
|
11
|
+
assert.equal(typeof plugin.start, 'function');
|
|
12
|
+
assert.equal(typeof plugin.stop, 'function');
|
|
13
|
+
assert.ok(plugin.id);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('starts and stops without error', () => {
|
|
17
|
+
plugin.start({}, () => {});
|
|
18
|
+
plugin.stop();
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
describe('MOB message across the antimeridian', () => {
|
|
23
|
+
it('reports the short-way distance and direction across 180°', () => {
|
|
24
|
+
// Vessel just east of the antimeridian, MOB beacon just west of it:
|
|
25
|
+
// the beacon is ~22 km east (over the seam), not half a world away.
|
|
26
|
+
const messages = [];
|
|
27
|
+
const statuses = [];
|
|
28
|
+
const raised = {};
|
|
29
|
+
const app = {
|
|
30
|
+
debug: () => {},
|
|
31
|
+
error: () => {},
|
|
32
|
+
selfId: 'urn:mrn:imo:mmsi:230099999',
|
|
33
|
+
getSelfPath: (path) => {
|
|
34
|
+
if (path === 'navigation.position') {
|
|
35
|
+
return { latitude: -14, longitude: 179.9 };
|
|
36
|
+
}
|
|
37
|
+
// The plugin dedups against the live notification subtree
|
|
38
|
+
return raised[path] ? { value: raised[path] } : undefined;
|
|
39
|
+
},
|
|
40
|
+
signalk: {
|
|
41
|
+
root: {
|
|
42
|
+
vessels: {
|
|
43
|
+
'urn:mrn:imo:mmsi:972123456': {
|
|
44
|
+
navigation: {
|
|
45
|
+
position: { value: { latitude: -14, longitude: -179.9 } },
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
setPluginStatus: (s) => statuses.push(s),
|
|
52
|
+
handleMessage: (source, delta) => {
|
|
53
|
+
messages.push(delta);
|
|
54
|
+
delta.updates.forEach((u) => u.values.forEach((v) => {
|
|
55
|
+
if (v.path.startsWith('notifications.mob.') && v.value) {
|
|
56
|
+
raised[v.path] = v.value;
|
|
57
|
+
}
|
|
58
|
+
}));
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
const plugin = pluginFactory(app);
|
|
62
|
+
plugin.start({ interval: 0.01 });
|
|
63
|
+
return new Promise((resolve) => {
|
|
64
|
+
setTimeout(() => {
|
|
65
|
+
plugin.stop();
|
|
66
|
+
const notifications = messages
|
|
67
|
+
.flatMap((d) => d.updates)
|
|
68
|
+
.flatMap((u) => u.values)
|
|
69
|
+
.filter((v) => v.path.startsWith('notifications.mob.'));
|
|
70
|
+
assert.equal(notifications.length, 1, 'one MOB notification raised');
|
|
71
|
+
const { message } = notifications[0].value;
|
|
72
|
+
const meters = Number(message.match(/([\d.]+) meters/)[1]);
|
|
73
|
+
assert.ok(
|
|
74
|
+
meters > 20000 && meters < 24000,
|
|
75
|
+
`distance ${meters} m; expected ~22 km over the seam`,
|
|
76
|
+
);
|
|
77
|
+
assert.ok(
|
|
78
|
+
/to (east|southeast|northeast)/.test(message),
|
|
79
|
+
`direction in "${message}" should read across the seam as east`,
|
|
80
|
+
);
|
|
81
|
+
resolve();
|
|
82
|
+
}, 50);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
});
|