@meri-imperiumi/signalk-mob-notifier 1.1.6 → 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/.editorconfig +5 -0
- package/.eslintrc.json +3 -0
- package/.github/workflows/publish.yml +4 -3
- package/.github/workflows/signalk-ci.yml +11 -0
- package/CHANGELOG.md +44 -0
- package/README.md +1 -17
- package/doc/alert.png +0 -0
- package/doc/appicon-256.png +0 -0
- package/doc/appicon.png +0 -0
- package/package.json +16 -3
- package/plugin/index.js +1 -1
- package/test/plugin.test.js +85 -0
package/.editorconfig
ADDED
package/.eslintrc.json
CHANGED
|
@@ -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
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Changelog
|
|
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
|
@@ -11,20 +11,4 @@ Please note that this plugin aims to aid with noticing and locating crew overboa
|
|
|
11
11
|
|
|
12
12
|
## Changes
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
- Round distance to beacon with single decimal
|
|
16
|
-
- Use EPIRB and SART terms for shorter notifications
|
|
17
|
-
* 1.1.5 (2025-11-15)
|
|
18
|
-
- Bump release
|
|
19
|
-
* 1.1.4 (2025-11-12)
|
|
20
|
-
- Fix reading MOB vessel data structure
|
|
21
|
-
* 1.1.3 (2025-11-02)
|
|
22
|
-
- Fix detection of beacon type (MOB/SART/EPIRB)
|
|
23
|
-
* 1.1.2 (2025-11-01)
|
|
24
|
-
- Better approach at getting MOB coordinates
|
|
25
|
-
* 1.1.1 (2025-09-18)
|
|
26
|
-
- Notifications include position when available
|
|
27
|
-
* 1.1.0 (2025-09-04)
|
|
28
|
-
- Notification is not re-published if it already exists
|
|
29
|
-
* 1.0.0 (2025-08-25)
|
|
30
|
-
- Initial release
|
|
14
|
+
See [Changelog](CHANGELOG.md)
|
package/doc/alert.png
ADDED
|
Binary file
|
|
Binary file
|
package/doc/appicon.png
ADDED
|
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,6 +31,18 @@
|
|
|
30
31
|
"eslint-plugin-import": "^2.32.0"
|
|
31
32
|
},
|
|
32
33
|
"dependencies": {
|
|
33
|
-
"where": "^0.4.
|
|
34
|
+
"where": "^0.4.3"
|
|
35
|
+
},
|
|
36
|
+
"signalk-plugin-enabled-by-default": true,
|
|
37
|
+
"signalk": {
|
|
38
|
+
"appIcon": "./doc/appicon-256.png",
|
|
39
|
+
"displayName": "AIS MOB and EPIRB notifier",
|
|
40
|
+
"screenshots": [
|
|
41
|
+
"./doc/alert.png"
|
|
42
|
+
],
|
|
43
|
+
"recommends": [
|
|
44
|
+
"@meri-imperiumi/signalk-meshtastic",
|
|
45
|
+
"@meri-imperiumi/signalk-audio-notifications"
|
|
46
|
+
]
|
|
34
47
|
}
|
|
35
48
|
}
|
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
|
+
});
|