mesh: update node batteryLevel from live NODEINFO_APP packets

battery_level was only populated during the initial sync; NodeInfo
frames streamed as NODEINFO_APP (port 4) now refresh deviceMetrics in
the node database so /api/nodes and downstream consumers see current
values between syncs. decodeNodeInfo + PORT_NODEINFO_APP added to the
codec, one branch in the existing packet-handling path.
This commit is contained in:
2026-09-25 12:39:45 +00:00
parent 6ce0b1ae7b
commit 8ddd91d4b5
3 changed files with 100 additions and 0 deletions
+19
View File
@@ -11,6 +11,7 @@ import type { DatabaseSync } from 'node:sqlite';
import type * as Proto from '@meshtastic/protobufs';
import {
BROADCAST_ADDR,
PORT_NODEINFO_APP,
PORT_POSITION_APP,
PORT_ROUTING_APP,
PORT_TELEMETRY_APP,
@@ -18,6 +19,7 @@ import {
buildTextToRadio,
buildWantConfigToRadio,
decodeFromRadio,
decodeNodeInfo,
decodePosition,
decodeRouting,
decodeTelemetry,
@@ -676,6 +678,23 @@ export class MeshService implements OnModuleInit, OnModuleDestroy {
position: pos,
});
}
} else if (decoded && decoded.portnum === PORT_NODEINFO_APP) {
// live node-info update: NodeInfo serialized in Data.payload; deviceMetrics carries
// battery_level so /api/nodes and the battery alerts see fresh values between syncs
let ni: Proto.Mesh.NodeInfo | undefined;
try {
ni = await decodeNodeInfo(decoded.payload);
} catch {
ni = undefined; // malformed payload — skip, keep whatever we had
}
if (ni?.deviceMetrics !== undefined) {
const num = pkt.from;
this.nodeMap.set(num, {
...this.nodeMap.get(num),
num,
deviceMetrics: ni.deviceMetrics,
});
}
} else if (decoded && decoded.portnum === PORT_ROUTING_APP) {
// ACK/NACK for our want_ack sends: Routing serialized in Data.payload,
// Data.requestId = the original packet id we sent