@meri-imperiumi/signalk-meshtastic 1.1.1 → 1.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/README.md +7 -0
- package/package.json +1 -1
- package/plugin/index.js +39 -16
package/README.md
CHANGED
|
@@ -91,6 +91,13 @@ Metrics used:
|
|
|
91
91
|
|
|
92
92
|
## Changes
|
|
93
93
|
|
|
94
|
+
* 1.2.0 (2025-09-28)
|
|
95
|
+
- Safety for nodes in DB that don't have a "last seen" timestamp
|
|
96
|
+
- Made connection status notifications clearer
|
|
97
|
+
- Attempt at support for Node.js older than 22.x
|
|
98
|
+
* 1.1.2 (2025-09-25)
|
|
99
|
+
- Added support for the new roles from Meshtastic 2.7 (`ROUTER_LATE` and `CLIENT_BASE`)
|
|
100
|
+
- Fixed issue with sending a bell with alerts that have sound enabled
|
|
94
101
|
* 1.1.1 (2025-09-18)
|
|
95
102
|
- Fixed empty response text message to digital switching actions
|
|
96
103
|
- Added support for the proposed Signal K MOB position specification
|
package/package.json
CHANGED
package/plugin/index.js
CHANGED
|
@@ -5,6 +5,13 @@ const Telemetry = require('./telemetry');
|
|
|
5
5
|
const commands = require('./commands/index');
|
|
6
6
|
const { vesselIcon } = require('./waypoint');
|
|
7
7
|
|
|
8
|
+
if (!global.crypto) {
|
|
9
|
+
// Older Node.js versions (like the one bundled in Venus OS
|
|
10
|
+
// don't have crypto module available
|
|
11
|
+
// eslint-disable-next-line global-require
|
|
12
|
+
global.crypto = require('node:crypto');
|
|
13
|
+
}
|
|
14
|
+
|
|
8
15
|
// The ES modules we'll need to import
|
|
9
16
|
let MeshDevice;
|
|
10
17
|
let TransportHTTP;
|
|
@@ -146,6 +153,14 @@ function nodeToSignalK(app, node, nodeInfo, settings) {
|
|
|
146
153
|
role = 'tak_tracker';
|
|
147
154
|
break;
|
|
148
155
|
}
|
|
156
|
+
case 11: {
|
|
157
|
+
role = 'router_late';
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
case 12: {
|
|
161
|
+
role = 'client_base';
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
149
164
|
default: {
|
|
150
165
|
break;
|
|
151
166
|
}
|
|
@@ -304,6 +319,10 @@ module.exports = (app) => {
|
|
|
304
319
|
// Ignore own node
|
|
305
320
|
return false;
|
|
306
321
|
}
|
|
322
|
+
if (!nodes[nodeId].seen) {
|
|
323
|
+
// Somehow never seen
|
|
324
|
+
return false;
|
|
325
|
+
}
|
|
307
326
|
// Online treshold, should be same as NUM_ONLINE_SECS in Meshtastic fw
|
|
308
327
|
const onlineSecs = 60 * 60 * 2;
|
|
309
328
|
if (nodes[nodeId].seen.getTime() > now.getTime() - (onlineSecs * 1000)) {
|
|
@@ -454,14 +473,14 @@ module.exports = (app) => {
|
|
|
454
473
|
{
|
|
455
474
|
state: 'warn',
|
|
456
475
|
lower: 0,
|
|
457
|
-
upper:
|
|
458
|
-
message: 'Not connected to device',
|
|
476
|
+
upper: 5,
|
|
477
|
+
message: 'Not connected to Meshtastic device',
|
|
459
478
|
},
|
|
460
479
|
{
|
|
461
480
|
state: 'nominal',
|
|
462
481
|
lower: 7,
|
|
463
482
|
upper: 8,
|
|
464
|
-
message: '
|
|
483
|
+
message: 'Meshtastic connected and configured',
|
|
465
484
|
},
|
|
466
485
|
],
|
|
467
486
|
},
|
|
@@ -488,7 +507,9 @@ module.exports = (app) => {
|
|
|
488
507
|
Object.keys(nodeDbData)
|
|
489
508
|
.forEach((nodeNum) => {
|
|
490
509
|
nodes[nodeNum] = nodeDbData[nodeNum];
|
|
491
|
-
|
|
510
|
+
if (nodeDbData[nodeNum].seen) {
|
|
511
|
+
nodes[nodeNum].seen = new Date(nodeDbData[nodeNum].seen);
|
|
512
|
+
}
|
|
492
513
|
});
|
|
493
514
|
app.setPluginStatus(`Connecting to Meshtastic node ${settings.device.address}`);
|
|
494
515
|
sendMeta();
|
|
@@ -823,7 +844,7 @@ module.exports = (app) => {
|
|
|
823
844
|
return;
|
|
824
845
|
}
|
|
825
846
|
let bell = '';
|
|
826
|
-
if (v.value.method && v.value.method.indexOf('sound')) {
|
|
847
|
+
if (v.value.method && v.value.method.indexOf('sound') !== -1) {
|
|
827
848
|
// Trigger audible bell on receiving Meshtastic devices
|
|
828
849
|
bell = '\u0007 ';
|
|
829
850
|
}
|
|
@@ -840,30 +861,32 @@ module.exports = (app) => {
|
|
|
840
861
|
if (v.path.indexOf('notifications.mob.') === 0) {
|
|
841
862
|
// This is a notification about a MOB beacon, create waypoint
|
|
842
863
|
let mobPosition;
|
|
843
|
-
let mmsi = 9712234567;
|
|
844
864
|
let mobVessel = {
|
|
845
865
|
name: 'MOB beacon',
|
|
846
|
-
mmsi,
|
|
866
|
+
mmsi: '9712234567',
|
|
847
867
|
};
|
|
848
|
-
if (v.value.data && v.value.data.
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
868
|
+
if (v.value.data && v.value.data.mmsi) {
|
|
869
|
+
mobVessel.mmsi = v.value.data.mmsi;
|
|
870
|
+
}
|
|
871
|
+
if (v.value.position) {
|
|
872
|
+
// signalk-mob-notifier and freeboard-sk include position in the notification
|
|
873
|
+
mobPosition = v.value.position;
|
|
854
874
|
} else {
|
|
855
875
|
// See if the MOB can be found from Signal K tree
|
|
856
|
-
mmsi = v.path.split('.').at(-1);
|
|
876
|
+
const mmsi = v.path.split('.').at(-1);
|
|
857
877
|
mobVessel = app.signalk.root.vessels[`vessels.urn:mrn:imo:mmsi:${mmsi}`];
|
|
858
878
|
if (mobVessel && mobVessel.navigation.position) {
|
|
859
879
|
mobPosition = mobVessel.navigation.position;
|
|
880
|
+
if (mobPosition.value) {
|
|
881
|
+
mobPosition = mobPosition.value;
|
|
882
|
+
}
|
|
860
883
|
}
|
|
861
884
|
}
|
|
862
|
-
if (!mobPosition) {
|
|
885
|
+
if (!mobPosition || !mobPosition.latitude) {
|
|
863
886
|
return;
|
|
864
887
|
}
|
|
865
888
|
const setWaypointMessage = create(Protobuf.Mesh.WaypointSchema, {
|
|
866
|
-
id: mmsi,
|
|
889
|
+
id: mobVessel.mmsi,
|
|
867
890
|
latitudeI: Math.floor(mobPosition.latitude / 1e-7),
|
|
868
891
|
longitudeI: Math.floor(mobPosition.longitude / 1e-7),
|
|
869
892
|
expire: Math.floor((new Date().getTime() / 1000) + (1 * 60 * 60)),
|