zigbee-herdsman
Version:
An open source ZigBee gateway solution with node.js.
57 lines (45 loc) • 1.93 kB
text/typescript
import * as stream from "node:stream";
import {logger} from "../../../utils/logger";
import {DataStart, MinMessageLength, PositionDataLength, SOF} from "./constants";
import {Frame} from "./frame";
const NS = "zh:zstack:unpi:parser";
export class Parser extends stream.Transform {
private buffer: Buffer;
public constructor() {
super();
this.buffer = Buffer.from([]);
}
public override _transform(chunk: Buffer, _: string, cb: () => void): void {
logger.debug(`<-- [${[...chunk]}]`, NS);
this.buffer = Buffer.concat([this.buffer, chunk]);
this.parseNext();
cb();
}
private parseNext(): void {
logger.debug(`--- parseNext [${[...this.buffer]}]`, NS);
if (this.buffer.length !== 0 && this.buffer.readUInt8(0) !== SOF) {
// Buffer doesn't start with SOF, skip till SOF.
const index = this.buffer.indexOf(SOF);
if (index !== -1) {
this.buffer = this.buffer.slice(index, this.buffer.length);
}
}
if (this.buffer.length >= MinMessageLength && this.buffer.readUInt8(0) === SOF) {
const dataLength = this.buffer[PositionDataLength];
const fcsPosition = DataStart + dataLength;
const frameLength = fcsPosition + 1;
if (this.buffer.length >= frameLength) {
const frameBuffer = this.buffer.slice(0, frameLength);
try {
const frame = Frame.fromBuffer(dataLength, fcsPosition, frameBuffer);
logger.debug(`--> parsed ${frame}`, NS);
this.emit("parsed", frame);
} catch (error) {
logger.debug(`--> error ${error}`, NS);
}
this.buffer = this.buffer.slice(frameLength, this.buffer.length);
this.parseNext();
}
}
}
}