Nana Plays Minesweeper

    split-frames
    TypeScript icon, indicating that this package has built-in type declarations

    2.4.2 • Public • Published

    split-frames

    Split Buffer frames from streams

    Build Status Coverage Status Dependency Status Dev dependency Status Issues Pull requests

    Installation

    $ npm install split-frames

    Doc

    Works very well with, for example, serialport for industrial protocols like Concert

    /!\ this version only split frames properly, and does not remove start & end tags or escape bits anymore.

    Methods

    • inherited from stream.Transform
    • constructor ([ options: object ]): split-frames instance

    Options

    All these options are optionnal

    type ControlBits = "none" | "end+1" | "end+2";
    type Tagnumber | Buffer | Array< number | Buffer >
    • javascript "startWith": Tag
    • javascript "startTimeout": integer (default: 200)
    • javascript "endWith": Tag
    • javascript "escapeWith": number
    • javascript "escaped": Array<number>
    • javascript "specifics": object
    • javascript "controlBits": ControlBits (default: "none")

    "startTimeout" is a timeout (in milliseconds) which end frame in "start only" mode, if no second "start" bit is encountered after the first one

    "specifics" is a [ key: string => value: Tag ] object which fire a "key" event when a "value" tag is found out of the message and not escaped ex : { "specifics": { "nak": 0x25 } } will fire an "nak" event when 0x25 bit is encountered

    Examples

    In the following exemples, "Splitter" and "Readable" classes are defined like that :

    // typescript
    import Splitter = require("split-frames");
    import { Readable } from "stream";
    // javascript
    const Splitter = require("split-frames");
    const { Readable } = require("stream");

    The "createReadStream" function is defined like that :

    function createReadStream () {
        return new Readable({
            read () { }
        });
    }

    And the "STX", "DLE" and "ETX" constants are defined like that :

    const STX = 0x02, ETX = 0x03, DLE = 0x10, ACK = 0x06, NAK = 0x15, WAK = 0x13;

    want to split frames content on a start bit ?

    const stream = createReadStream();
     
    stream.pipe(new Splitter({
        "startWith": STX
    })).on("data", (chunk) => {
        // Buffer([ STX, 0x24, 0x25, 0x26 ])
        // Buffer([ STX, 0x24, 0x25 ])
    });
     
    stream.push(Buffer.from([ 0x20, STX, 0x24, 0x25, 0x26, STX, 0x24 ]));
    stream.push(Buffer.from([ 0x25, STX ]));

    prefere an end bit ?

    const stream = createReadStream();
     
    stream.pipe(new Splitter({
        "endWith": ETX
    })).on("data", (chunk) => {
        // Buffer([ 0x24, 0x25, 0x26, ETX ])
        // Buffer([ 0x24, 0x25, ETX ])
    });
     
    stream.push(Buffer.from([ 0x24, 0x25, 0x26, ETX, 0x24, 0x25 ]));
    stream.push(Buffer.from([ ETX ]));

    want both ?

    const stream = createReadStream();
     
    stream.pipe(new Splitter({
        "startWith": STX, "endWith": ETX
    })).on("data", (chunk) => {
        // Buffer([ STX, 0x24, 0x25, 0x26, ETX ])
        // Buffer([ STX, 0x24, 0x25, ETX ])
    });
     
    stream.push(Buffer.from([ 0x20, STX, 0x24, 0x25, 0x26, ETX, 0x24, 0x25, STX ]));
    stream.push(Buffer.from([ 0x24, 0x25, ETX ]));

    what about two end bits (works with start one as well) ?

    const stream = createReadStream();
     
    stream.pipe(new Splitter({
        "startWith": STX, "endWith": Buffer.from([ DLE, ETX ])
    })).on("data", (chunk) => {
        // Buffer([ STX, 0x24, 0x25, 0x26, DLE, ETX ])
    });
     
    stream.push(Buffer.from([ 0x20, STX, 0x24, 0x25, 0x26, DLE, ETX, STX, 0x24, 0x25 ]));

    Do you need to parse escaped bits ?

    const stream = createReadStream();
     
    stream.pipe(new Splitter({
        "startWith": STX, "endWith": ETX,
        "escapeWith": DLE, "escaped": [ DLE, STX, ETX ]
    })).on("data", (chunk) => {
        // Buffer([ STX, 0x24, DLE, STX, 0x25, 0x26, DLE, DLE, 0x27, DLE, ETX, 0x28, ETX ])
    });
     
    stream.push(Buffer.from([ 0x20, STX, 0x24, DLE, STX, 0x25, 0x26 ]));
    stream.push(Buffer.from([ DLE, DLE, 0x27, DLE, ETX, 0x28, ETX, STX, 0x24, 0x25 ]));

    And what do you think about multiple start (or end !) bits possibilities ?

    For even parity in seriaport, for example

    const STX2 = 0x82;
    const stream = createReadStream();
     
    stream.pipe(new Splitter({
        "startWith": [ STX, STX2 ], "endWith": ETX,
        "escapeWith": DLE, "escaped": [ DLE, STX, ETX ]
    })).on("data", (chunk) => {
        // Buffer([ STX, 0x24, DLE, STX, 0x25, 0x26, DLE, DLE, 0x27, DLE, ETX, 0x28, ETX ])
        // Buffer([ STX2, 0x24, DLE, STX, 0x25, 0x26, DLE, DLE, 0x27, DLE, ETX, 0x28, ETX ])
    });
     
    stream.push(Buffer.from([ 0x24, STX, 0x24, DLE, STX, 0x25, ACK ]));
    stream.push(Buffer.from([ DLE, DLE, 0x27, DLE, ETX, 0x28, ETX, ACK, 0x24, 0x25 ]));
    stream.push(Buffer.from([ STX2, 0x24, DLE, STX, 0x25, ACK ]));
    stream.push(Buffer.from([ DLE, DLE, 0x27, DLE, ETX, 0x28, ETX, ACK, 0x24, 0x25 ]));

    Want to extract specific tags ?

    positive acknowledgement, negative acknowledgement, waiting for acknowledgement, whatever... only with no tags || start AND end tags || end tags (for firsts bits)

    const stream = createReadStream();
     
    stream.pipe(new Splitter({
        "startWith": STX, "endWith": ETX,
        "specifics": {
            "ack": ACK, "nak": NAK, "wak": WAK, "whatever": 0x51
        },
        "escapeWith": DLE, "escaped": [ DLE, ACK, NAK, WAK ]
    })).on("ack", () => {
        console.log("ack received"); // (only 1x) -> good, escaped, in data
    }).on("nak", () => {
        console.log("nak received"); // (only 1x) -> in data, good, escaped
    }).on("wak", () => {
        console.log("wak received"); // (only 1x) -> in data, good, escaped
    }).on("whatever", () => {
        console.log("whatever received"); // (only 1x)
    }).on("data", (chunk) => {
        // Buffer([ STX, 0x20, 0x21, 0x22, ACK, NAK, WAK, 0x23, ETX ]) (x1)
    });
     
    stream.push(Buffer.from([ 0x51, 0x24, ACK, DLE, ACK, STX, 0x20, 0x21, 0x22, ACK, NAK, WAK ]));
    stream.push(Buffer.from([ 0x23, ETX, NAK, DLE, NAK, WAK, DLE, WAK, 0x20, 0x21 ]));

    Want to use control bits ?

    used to compute LRC, MSB, LSB, etc... this example is for a structure like STX ETX LRC, where LRC compute all bits

     
    function _computeLRC (frame) {
     
        let lrc = 0x00;
     
            for (let i = 0; i < frame.length; ++i) {
                lrc ^= frame[i];
            }
     
        return lrc;
     
    }
     
    const stream = createReadStream();
     
    stream.pipe(new Splitter({
        "startWith": STX, "endWith": ETX,
        "controlBits": "end+1"
    })).on("data", (chunk) => {
     
        // Buffer([ STX, 0x20, 0x21, 0x22, 0x24, ETX, 0x07 ]) (x1)
     
        const data = chunk.slice(1, chunk.length - 2); // Buffer([ 0x20, 0x21, 0x22, 0x24 ])
        const LRC = chunk[chunk.length - 1];
     
        if (_computeLRC(data) === LRC) {
            console.log("OK");
        }
        else {
            console.error(new Error("not well-computed data :" + data.toString("hex") + "|" + Buffer.from([ LRC ]).toString("hex")));
        }
     
    });
     
    stream.push(Buffer.from([ 0x51, 0x24, STX, 0x20, 0x21, 0x22, 0x24, ETX, 0x07, 0x24 ]));

    Tests

    $ npm run-script tests

    License

    ISC

    Install

    npm i split-frames

    DownloadsWeekly Downloads

    23

    Version

    2.4.2

    License

    ISC

    Unpacked Size

    92.5 kB

    Total Files

    23

    Last publish

    Collaborators

    • psychopoulet