5.5 KiB
5.5 KiB
Changelog
v0.3.0 — 2026-09-24 14:08
- Message history with delivery tracking, exposed as
GET /api/messages(newest first): inbound TEXT_MESSAGE_APP packets (dir:'rx', withfrom) and our sends (dir:'tx', withto+status). tx records startpendingand move todelivered/failedwhen the routing ACK/NACK arrives — ROUTING_APP packets carry a serializedmeshtastic.RoutinginData.payloadwhose oneof variant iserrorReason(Routing_Error: 0 NONE = delivered, anything else failed with a human-readableackError, e.g. NO_ROUTE/GOT_NAK/TIMEOUT, fallbackreason <n>), matched to our sends viaData.requestId. Broadcasts staypendingbecause firmware strips want_ack pre-TX (documented behavior, no timer). History is a bounded in-memory buffer of the last 100 records (newest kept) and resets on every bridge reconnect alongside channels/nodes. - Codec: new
PORT_ROUTING_APP = 5constant (verified against the installed@meshtastic/protobufsPortNum enum),decodeRouting()for ROUTING_APP payloads, anddescribeRoutingError()which maps a Routing.Error code to its name from the installed package'sMesh.Routing_Errorenum. - Swagger:
GET /api/messagesdocumented with the pending→delivered/failed lifecycle, the broadcast caveat, and an example matching the record shape; README + AGENTS.md endpoint lists updated.
v0.2.0 — 2026-09-24 13:08
- Node database collected during the initial sync (
FromRadio.nodeInfoframes, upserted by node number) and kept fresh by livePOSITION_APPpackets (the Position is serialized inData.payload; unknown senders get a stub entry). The map resets on every bridge reconnect alongside channels. - New endpoints:
GET /api/nodes— lean summaries sorted by node number as{ num, longName?, shortName?, hwModel?, batteryLevel?, lastHeard (epoch secs | null), position? { lat, lon, alt? } }[]; names/hwModel/battery appear only when the device reported them,hwModelis the enum's string name (UNSET omitted), andpositiononly when both coordinates are known.GET /api/nodes/:id— lookup by exact node number (numbers/numeric strings), then case-insensitive exact long/short name, else unique case-insensitive substring; 404 with a clear message when nothing or more than one node matches. - Codec: new
PORT_POSITION_APP = 3constant (verified against the installed@meshtastic/protobufsPortNum enum),decodePosition()for POSITION_APP payloads, andloadHwModelNames()reverse lookup of the HardwareModel enum. - Swagger docs made genuinely useful:
Meshtag on the controller (description viaDocumentBuilder.addTag— v12'sApiTagOptionshas no description field) plus@ApiOperationsummary/description and@ApiResponseexamples on all endpoints, existing and new. - Unit tests build real framed FromRadio bytes for nodeInfo/POSITION_APP: sync collection + summary shape (lat/lon = value × 1e-7, battery), stub entry from an unknown POSITION_APP sender, lookup ladder (exact num / numeric string / exact name / unique substring) with ambiguous and missing → null, and reconnect reset.
v0.1.4 — 2026-09-23 20:33
- Send a
ToRadiowithwant_config_id(random non-zero uint32 nonce) on every bridge connect, so the firmware streams its initial sync data (myInfo, channels,config_complete_id) — previously nothing was written on connect, which is why/api/channelsstayed empty andmyNodeNumstayed null in production. New codec helperbuildWantConfigToRadio; unit test captures the outbound frame on the fake bridge, asserts thewantConfigIdoneof case with a non-zero value, then feeds backmyInfo+configCompleteIdframes and checks service state.
v0.1.3 — 2026-09-23 19:58
- Sends are now pinned to the test channel
testowy(channel index 2) instead of the hardcoded primary channel (channel: 0). The target channel is configurable viaMESH_SEND_CHANNEL(default2) and parsed once at service construction;buildTextToRadiotakes the channel index as a parameter. Unit tests now decode the outbound ToRadio frame on the fake bridge and assertpacket.channel === 2on the default send path.
v0.1.2 — 2026-09-23 19:51
- Added a Gitea Actions CI pipeline (
.gitea/workflows/ci.yml), mirroring flight's runner conventions: on push/PR tomain(plus manual dispatch) one job runsnpm ci,nest build, the vitest unit suite, and a production Docker image build — with retry loops for the runner's flaky uplink. No app code changed.
v0.1.1 — 2026-09-23 19:38
- Fixed the default bridge port to
4403, the meshtastic-serial-bridge's actual TCP port (the old value pointed at a closed port). Updated theMESH_PORTdefault in code, the docker-compose environment, and docs.
v0.1.0 — 2026-09-23 18:54
- New
GET /api/channelsendpoint listing the device's Meshtastic channels as{ index, name, uplinkEnabled, downlinkEnabled }; psk/keys are redacted and never exposed over HTTP. Channels are collected fromFromRadio.channelframes streamed during initial sync (beforeconfig_complete_id) and reset on every bridge reconnect so stale data is dropped after a disconnect. - All endpoints moved under the
/apinamespace viaapp.setGlobalPrefix("api"):GET /status→GET /api/status,POST /send→POST /api/send. - Scalar API docs served at
/(OpenAPI JSON at/docs-json) using@nestjs/swagger+@scalar/nestjs-api-reference; added light swagger decorators (ApiPropertyon the send body,ApiOperationsummaries) so the docs are useful. - Reconnect interval is now configurable via
MESH_RECONNECT_MS(default 5000 ms).