@meri-imperiumi/signalk-meshtastic 1.2.0 → 1.2.2

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 CHANGED
@@ -91,10 +91,16 @@ Metrics used:
91
91
 
92
92
  ## Changes
93
93
 
94
+ * 1.2.2 (2025-10-01)
95
+ - Set "last seen" timestamp of nodes based on packet payloads, not the time they're received
96
+ - Send timestamp with telemetry
97
+ - Fixed issue with persising node-to-vessel matches from `DE <callsign>`
98
+ * 1.2.1 (2025-09-28)
99
+ - Fixed issue with Signal K servers that don't have navigation.position set
94
100
  * 1.2.0 (2025-09-28)
101
+ - Support for Node.js older than 22.x, for example as seen in Venus OS Large
95
102
  - Safety for nodes in DB that don't have a "last seen" timestamp
96
103
  - Made connection status notifications clearer
97
- - Attempt at support for Node.js older than 22.x
98
104
  * 1.1.2 (2025-09-25)
99
105
  - Added support for the new roles from Meshtastic 2.7 (`ROUTER_LATE` and `CLIENT_BASE`)
100
106
  - Fixed issue with sending a bell with alerts that have sound enabled
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meri-imperiumi/signalk-meshtastic",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "Signal K plugin for interfacing with the Meshtastic LoRa mesh network",
5
5
  "scripts": {
6
6
  "test": "eslint ."
package/plugin/index.js CHANGED
@@ -278,6 +278,7 @@ module.exports = (app) => {
278
278
  return;
279
279
  }
280
280
  const telemetryMessage = create(Protobuf.Telemetry.TelemetrySchema, {
281
+ time: Math.floor(new Date().getTime() / 1000),
281
282
  variant: {
282
283
  case: 'environmentMetrics',
283
284
  value: create(Protobuf.Telemetry.EnvironmentMetricsSchema, values),
@@ -310,6 +311,13 @@ module.exports = (app) => {
310
311
  }, 60000 * minutes);
311
312
  }
312
313
 
314
+ function writeNodeDb() {
315
+ writeFile(nodeDbFile, JSON.stringify(nodes, null, 2), 'utf-8')
316
+ .catch((e) => {
317
+ app.error(`Failed to store node DB: ${e.message}`);
318
+ });
319
+ }
320
+
313
321
  function setConnectionStatus() {
314
322
  setWatchdog();
315
323
  const now = new Date();
@@ -559,16 +567,18 @@ module.exports = (app) => {
559
567
  nodes[nodeInfo.num].mmsi = ctx.split(':').at(-1);
560
568
  }
561
569
  setConnectionStatus();
562
- writeFile(nodeDbFile, JSON.stringify(nodes, null, 2), 'utf-8')
563
- .catch((e) => {
564
- app.error(`Failed to store node DB: ${e.message}`);
565
- });
570
+ writeNodeDb();
566
571
  }),
567
572
  device.events.onMeshPacket.subscribe((packet) => {
568
573
  if (!nodes[packet.from]) {
569
574
  nodes[packet.from] = {};
570
575
  }
571
- nodes[packet.from].seen = new Date();
576
+ if (packet.rxTime) {
577
+ const packetDate = new Date(packet.rxTime * 1000);
578
+ if (packetDate > nodes[packet.from].seen) {
579
+ nodes[packet.from].seen = packetDate;
580
+ }
581
+ }
572
582
  setConnectionStatus();
573
583
  }),
574
584
  device.events.onMessagePacket.subscribe((message) => {
@@ -604,7 +614,12 @@ module.exports = (app) => {
604
614
  // Unknown node
605
615
  return;
606
616
  }
607
- nodes[packet.from].seen = new Date();
617
+ if (packet.data && packet.data.time) {
618
+ const telemetryDate = new Date(packet.data.time * 1000);
619
+ if (telemetryDate > nodes[packet.from].seen) {
620
+ nodes[packet.from].seen = telemetryDate;
621
+ }
622
+ }
608
623
  setConnectionStatus();
609
624
  const context = getNodeContext(app, nodes[packet.from], packet.from, settings);
610
625
  if (!context) {
@@ -697,7 +712,12 @@ module.exports = (app) => {
697
712
  // Unknown node
698
713
  return;
699
714
  }
700
- nodes[position.from].seen = new Date();
715
+ if (position.data && position.data.time) {
716
+ const positionDate = new Date(position.data.time * 1000);
717
+ if (positionDate > nodes[position.from].seen) {
718
+ nodes[position.from].seen = positionDate;
719
+ }
720
+ }
701
721
  setConnectionStatus();
702
722
  const context = getNodeContext(app, nodes[position.from], position.from, settings);
703
723
  if (!context) {
@@ -750,6 +770,11 @@ module.exports = (app) => {
750
770
  },
751
771
  ],
752
772
  });
773
+ if (context && context.indexOf('vessels.urn:mrn:imo:mmsi:') === 0) {
774
+ // We have an MMSI match, store it
775
+ nodes[position.from].mmsi = context.split(':').at(-1);
776
+ }
777
+ writeNodeDb();
753
778
  }),
754
779
  );
755
780
 
@@ -822,6 +847,10 @@ module.exports = (app) => {
822
847
  // Not connected to Meshtastic yet
823
848
  return;
824
849
  }
850
+ if (v.value.latitude === null) {
851
+ // No position
852
+ return;
853
+ }
825
854
  if (!settings.communications || !settings.communications.send_position) {
826
855
  return;
827
856
  }