ax25-ui-packet
v0.0.1
Published
Parse and build AX.25 Unnumbered Information (UI) frames with FCS, station addresses, and APRS-style path helpers.
Maintainers
Readme
ax25-ui-packet
Parse and build AX.25 Unnumbered Information (UI) frames in Node.js: addresses (callsign + SSID), PID, payload, and Frame Check Sequence (FCS). Useful for APRS and other connectionless AX.25 over packet radio.
This package does not perform HDLC bit stuffing or full link-layer framing; it works on complete frame buffers (optionally wrapped in 0x7e flags).
It's designed to be connected to a software TNC, probably direwolf, using the kiss-tnc NPM package. See the examples below for how this can work.
Install
From the npm registry (package name ax25-ui-packet):
npm install ax25-ui-packetRequirements:
- Node.js 18+
- ESM only — use
importin your project ("type": "module"inpackage.json, or.mjsfiles).
TypeScript users get declarations from the published dist/*.d.ts files; no separate @types package is needed.
Public API
Everything is exported from the package root (ax25-ui-packet).
Default export
| Export | Description |
|--------|-------------|
| AX25UIFrame (default) | Same class as the named export below. |
Named exports (values)
| Name | Description |
|------|-------------|
| AX25UIFrame | Parse, build, and inspect UI frames (parse, wrapAPRS, build, crcCalc, etc.). |
| Station | AX.25 station address: callsign, SSID, and 7-byte encoding. |
| Layer3Protocol | Constants for the AX.25 PID (layer 3 protocol) field. |
| UIFrameWarningCode | Warning codes for non-fatal frame issues (LONG_PAYLOAD, FCS_MISMATCH, CONTROL_B_MISMATCH). |
Named exports (types only)
| Name | Description |
|------|-------------|
| StationQ | Object shape { callsign: string; ssid?: number } for address props. |
| SSID | SSID literal union 0 … 15. |
| fullyQualifiedStationValue | Template type for "CALLSIGN-SSID" strings. |
| Layer3ProtocolType | Numeric PID union from Layer3Protocol. |
| Layer3ProtocolName | Key type of the Layer3Protocol object. |
| UIFrameWarning | Shape of entries in toJSON().warnings. |
| UIFrameWarningCodeType | Union of warning code string literals. |
Import types with import type when you only need them for annotations:
import type { StationQ, UIFrameWarning } from 'ax25-ui-packet';Usage
import AX25UIFrame, { Station, Layer3Protocol } from 'ax25-ui-packet';
const frame = new AX25UIFrame({
destination: { callsign: 'APRS' },
source: { callsign: 'N0CALL', ssid: 1 },
payload: ':N0CALL :Hello',
layer3Protocol: Layer3Protocol.NO_LAYER_3_PROTOCOL,
});
const bytes = frame.build(true); // includes 0x7e flags
const roundTrip = AX25UIFrame.parse(bytes);You can import the class as import { AX25UIFrame } from 'ax25-ui-packet' instead of the default; both are the same constructor.
You can connect to direwolf using this package in combination with kiss-tnc:
import net from '@node:net';
import { KISSSender, KISSReceiver } from 'kiss-tnc';
import { AX25UIFrame } from 'ax25-ui-packet';
// Create a TCP connection to direwolf running on your computer
const direwolfSocket = net.createConnection(8001);
// Connect to the TCP connection using kiss-tnc
const sender = new KISSSender();
const receiver = new KISSReceiver({ emitObject: true, emitCommandByte: true });
sender.pipe(direwolfSocket);
direwolfSocket.pipe(receiver);
// Listen for packets from direwolf and log them to console when we receive them
receiver.on('data', ({ data }) => {
console.log(AX25UIFrame.parse(data));
});
// Send an AX.25 packet over the air using direwolf
const myFrame = new AX25UIFrame({
destination: { callsign: 'APDW18' },
source: { callsign: 'MYCALL', ssid: 1 },
payload: 'This is an AX.25 packet sent using JavaScript!',
});
sender.write(myFrame.build());
// Send an APRS message packet over the air using direwolf
const myAPRSMessage = `MYCALL>APDW18,WIDE1-1,WIDE2-2::WXBOT :90210{541`;
const myAprsFrame = AX25UIFrame.wrapAPRS(myAPRSMessage);
sender.write(myAprsFrame.build());Main methods (see JSDoc in source for full detail)
AX25UIFrame.parse(buf)— parse a raw UI frameBufferAX25UIFrame.wrapAPRS(text)— build from an APRS-styleSOURCE>DEST,PATH:…lineframe.build(withFlags?)— serialize toBufferStation— construct from"CALL"or"CALL-SSID"; useax25Encoded()for the on-wire 7-byte field
License
MIT
