mesh-bot
Minimal NestJS bot for Meshtastic. Long-running service that TCP-connects to a
Meshtastic serial bridge (raw socat pipe) at 192.168.1.4:4403, sends
want_config_id on connect so the firmware streams its initial sync data,
parses inbound protobuf frames, logs received text messages, and exposes HTTP
endpoints to send text.
Local run
npm i
npm run start:dev
Docker
docker compose up -d --build
Exposed via Traefik only (no published ports) at http://bot.dev.kkhost.pl.
Endpoints
All API endpoints live under the /api prefix:
GET /api/status—{ connected, myNodeNum, host, port }POST /api/send— body{ "text": "...", "to"?: <node number | "!b" | "broadcast"> }, returns{ id }GET /api/channels— the device's Meshtastic channels as{ index, name, uplinkEnabled, downlinkEnabled }[](psk/keys are redacted; empty until the initial sync completes)
Interactive API docs (Scalar) are served at /, with the OpenAPI JSON at
/docs-json.
curl http://localhost:3000/api/status
curl -X POST http://localhost:3000/api/send -H 'content-type: application/json' -d '{"text":"hi"}'
curl -X POST http://localhost:3000/api/send -H 'content-type: application/json' -d '{"to":123456789,"text":"hello"}'
curl http://localhost:3000/api/channels
to omitted, "!b", or "broadcast" sends to the broadcast address 0xffffffff.
All sends always target channel index 2 (testowy) — never the primary
channel. Override with MESH_SEND_CHANNEL.
Env vars
MESH_HOST(default192.168.1.4) — bridge hostMESH_PORT(default4403) — bridge portMESH_RECONNECT_MS(default5000) — reconnect interval in msMESH_SEND_CHANNEL(default2) — channel index all sends target (testowy; never the primary channel)PORT(default3000) — HTTP listen port
Note: the serial bridge accepts only ONE client at a time — if another app is connected to the radio, this bot will not get a connection.