Send to by node name or broadcast sentinel (GET-free resolution via node DB) (#9)
CI / build + unit (push) Successful in 33s

This commit was merged in pull request #9.
This commit is contained in:
2026-09-24 16:47:51 +02:00
parent 57ad27d66f
commit f640f6658c
7 changed files with 111 additions and 17 deletions
+29
View File
@@ -8,6 +8,7 @@ import {
import * as net from 'node:net';
import type * as Proto from '@meshtastic/protobufs';
import {
BROADCAST_ADDR,
PORT_POSITION_APP,
PORT_ROUTING_APP,
PORT_TEXT_MESSAGE_APP,
@@ -176,6 +177,34 @@ export class MeshService implements OnModuleInit, OnModuleDestroy {
return null;
}
/**
* Resolve a send target to a node number for sendText().
* undefined/"" and "!b"/"broadcast" (case-insensitive, trimmed) → BROADCAST_ADDR;
* numbers pass through as-is (must be an integer in 1..0xffffffff); numeric strings are parsed the same way;
* anything else is looked up via node() — throws `no node matching '<to>'` when nothing or more than one matches.
*/
async resolveDest(to?: number | string): Promise<number> {
if (typeof to === 'number') {
this.assertNodeNum(to);
return to;
}
const s = String(to ?? '').trim();
if (!s) return BROADCAST_ADDR; // omitted or empty → broadcast
if (s === '!b' || s.toLowerCase() === 'broadcast') return BROADCAST_ADDR;
if (/^\d+$/.test(s)) {
this.assertNodeNum(Number(s));
return Number(s);
}
const hit = await this.node(s);
if (!hit) throw new Error(`no node matching '${to}'`);
return hit.num;
}
private assertNodeNum(n: number): void {
if (!Number.isInteger(n) || n < 1 || n > BROADCAST_ADDR)
throw new Error(`invalid node number '${n}'`);
}
/**
* Message history, newest first: inbound TEXT_MESSAGE_APP packets (dir 'rx') and our sends (dir 'tx').
* tx records start 'pending' and move to 'delivered'/'failed' when the routing ACK/NACK arrives;