UNPKG

zigbee-herdsman

Version:

An open source ZigBee gateway solution with node.js.

82 lines (64 loc) 2.24 kB
/* v8 ignore start */ import * as stream from "node:stream"; import {logger} from "../../../utils/logger"; import * as consts from "./consts"; import Frame from "./frame"; const NS = "zh:ezsp:uart"; export class Parser extends stream.Transform { private tail: Buffer[]; public constructor() { super(); this.tail = []; } public override _transform(chunk: Buffer, _: string, cb: () => void): void { if (chunk.indexOf(consts.CANCEL) >= 0) { this.reset(); chunk = chunk.subarray(chunk.lastIndexOf(consts.CANCEL) + 1); } if (chunk.indexOf(consts.SUBSTITUTE) >= 0) { this.reset(); chunk = chunk.subarray(chunk.indexOf(consts.FLAG) + 1); } logger.debug(`<-- [${chunk.toString("hex")}]`, NS); let delimiterPlace = chunk.indexOf(consts.FLAG); while (delimiterPlace >= 0) { const buffer = chunk.subarray(0, delimiterPlace + 1); const frameBuffer = Buffer.from([...this.unstuff(Buffer.concat([...this.tail, buffer]))]); this.reset(); try { const frame = Frame.fromBuffer(frameBuffer); if (frame) { this.emit("parsed", frame); } } catch (error) { logger.debug(`<-- error ${error}`, NS); } chunk = chunk.subarray(delimiterPlace + 1); delimiterPlace = chunk.indexOf(consts.FLAG); } this.tail.push(chunk); cb(); } private *unstuff(buffer: Buffer): Generator<number> { /* Unstuff (unescape) a buffer after receipt */ let escaped = false; for (const byte of buffer) { if (escaped) { yield byte ^ consts.STUFF; escaped = false; } else { if (byte === consts.ESCAPE) { escaped = true; } else if (byte === consts.XOFF || byte === consts.XON) { // skip } else { yield byte; } } } } public reset(): void { // clear tail this.tail.length = 0; } }