@squawk
    Preparing search index...

    Module @squawk/beast

    squawk logo  @squawk/beast

    MIT License npm TypeScript

    Parses the Beast binary format - the framing dump1090-fa, readsb, and other decoders use to carry raw Mode-S/Mode-A/C messages, originally built for the Mode-S Beast USB dongle. Decoding of the messages themselves is delegated to @squawk/mode-s; this package's own job is the wire framing - the 0x1a escape/unescape byte-stuffing and the three Beast message types (Mode A/C, short Mode-S, long Mode-S).

    The core @squawk/beast export is a pure frame parser with no I/O - it takes a byte buffer (from a live socket, a replayed capture file, or anywhere else) and returns decoded frames. An opt-in @squawk/beast/stream subpath adds a ready-made Node TCP client for consumers who want to point it at a live Beast feed without writing their own socket handling.

    Part of the @squawk aviation library suite. See all packages on npm.

    npm install @squawk/beast
    

    deframeBeastBytes is pure and stateless - call it repeatedly as bytes arrive, feeding back its remainder (a frame that hasn't fully arrived yet) as the start of the next chunk:

    import { deframeBeastBytes } from '@squawk/beast';

    let pending = new Uint8Array(0);

    function onChunk(chunk: Uint8Array): void {
    const combined = new Uint8Array(pending.length + chunk.length);
    combined.set(pending);
    combined.set(chunk, pending.length);

    const result = deframeBeastBytes(combined);
    pending = result.remainder;

    for (const frame of result.frames) {
    console.log(frame.type, frame.decoded); // decoded via @squawk/mode-s
    }
    for (const error of result.errors) {
    console.warn(error.reason, error.bytes); // malformed framing, or a message that failed to decode
    }
    }
    import { createBeastStream } from '@squawk/beast/stream';

    const stream = createBeastStream({ host: '192.168.1.50' }); // port defaults to 30005

    stream.addEventListener('beast:message', (event) => {
    console.log((event as CustomEvent).detail.frame);
    });
    stream.addEventListener('beast:frameError', (event) => {
    console.warn((event as CustomEvent).detail.error);
    });
    stream.addEventListener('beast:connect', (event) => {
    console.log('connected', (event as CustomEvent).detail);
    });
    stream.addEventListener('beast:disconnect', (event) => {
    console.log('disconnected, reconnecting', (event as CustomEvent).detail);
    });

    stream.start();
    // later: stream.stop();

    createBeastStream reconnects automatically (after reconnectDelayMs, default 5000ms) if the connection closes or errors, until stop() is called.

    Import deframeBeastBytes from the /browser subpath - it's a pure parser with no Node dependency, so it aliases the main entry. createBeastStream depends on Node's net module (raw TCP sockets have no browser API) and is only available from /stream.

    import { deframeBeastBytes } from '@squawk/beast/browser';
    
    • deframeBeastBytes(buffer) - parses as many complete frames as are present in buffer, returning { frames, errors, remainder }.
    • createBeastStream({ host, port?, reconnectDelayMs? }) (from /stream, Node-only) - creates a live client, returning a BeastStream (an EventTarget) with start() / stop().
    • Events (via addEventListener, read off CustomEvent.detail): beast:message ({ frame: BeastFrame }, dispatched for every deframed frame whether or not it decoded), beast:frameError ({ error: BeastFrameError }), beast:connect ({ host, port }), beast:disconnect ({ host, port, reconnectDelayMs }).

    A BeastFrame's decoded field is a @squawk/mode-s DecodedModeSMessage for Mode-S frames, a ModeAcReply for Mode A/C frames, or undefined if the message didn't decode (an unsupported downlink format/type code, or a failed CRC) - rawMessage is always populated regardless, so a consumer that wants the bytes anyway still has them.

    browser
    stream