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
+9 -12
View File
@@ -13,7 +13,6 @@ import {
ApiResponse,
ApiTags,
} from '@nestjs/swagger';
import { BROADCAST_ADDR } from './codec.js';
import { MeshService } from './mesh.service.js';
export class SendTextDto {
@@ -22,7 +21,7 @@ export class SendTextDto {
@ApiProperty({
required: false,
description:
'Decimal node number, "!b", or "broadcast" (defaults to broadcast)',
'Send target. Resolution order: omitted or "" → broadcast (0xffffffff); number → used as-is (integer in 1..0xffffffff); numeric string → that node number; "!b" or "broadcast" (case-insensitive) → broadcast; anything else is looked up by name — exact long/short name, then unique substring. DMs are unicast and wantAck-tracked via GET /api/messages (pending→delivered/failed); broadcasts stay pending because firmware strips want_ack.',
example: '!b',
})
to?: string | number;
@@ -58,7 +57,7 @@ export class MeshController {
@ApiOperation({
summary: 'Send a text message over the mesh',
description:
'Queues a TEXT_MESSAGE_APP packet on the pinned test channel (index 2, "testowy" — never the primary channel). Returns the Meshtastic packet id.',
'Queues a TEXT_MESSAGE_APP packet to the resolved target (node number, node name, or broadcast). DMs are unicast and wantAck-tracked via GET /api/messages; broadcasts stay pending because firmware strips want_ack. All sends ride the pinned test channel (index 2, "testowy" — never the primary channel) regardless of DM or broadcast, since modern firmware PKI handles unicast encryption/channel anyway. Returns the Meshtastic packet id.',
})
@ApiResponse({
status: 200,
@@ -71,15 +70,13 @@ export class MeshController {
if (typeof body?.text !== 'string' || body.text.length === 0) {
throw new BadRequestException('text must be a non-empty string');
}
let to = BROADCAST_ADDR;
const t = body.to;
if (t !== undefined && t !== '!b' && t !== 'broadcast') {
const n = typeof t === 'number' ? t : Number(String(t));
if (!Number.isFinite(n))
throw new BadRequestException(
'to must be a decimal node number, "!b", or "broadcast"',
);
to = n;
let to: number;
try {
to = await this.mesh.resolveDest(body.to);
} catch (err) {
throw new BadRequestException(
err instanceof Error ? err.message : String(err),
);
}
return { id: await this.mesh.sendText(to, body.text) };
}