zigbee-herdsman
Version:
An open source ZigBee gateway solution with node.js.
102 lines (85 loc) • 2.57 kB
text/typescript
/* v8 ignore start */
import {RANDOMIZE_SEQ, RANDOMIZE_START} from "./consts";
import crc16ccitt from "./utils/crc16ccitt";
export enum FrameType {
UNKNOWN = 0,
ERROR = 1,
DATA = 2,
ACK = 3,
NAK = 4,
RST = 5,
RSTACK = 6,
}
/**
* Basic class to handle uart-level frames
* https://www.silabs.com/documents/public/user-guides/ug101-uart-gateway-protocol-reference.pdf
*/
export class Frame {
/**
* Type of the Frame as determined by its control byte.
*/
public readonly type: FrameType;
public readonly buffer: Buffer;
public constructor(buffer: Buffer) {
this.buffer = buffer;
const ctrlByte = this.buffer[0];
if ((ctrlByte & 0x80) === 0) {
this.type = FrameType.DATA;
} else if ((ctrlByte & 0xe0) === 0x80) {
this.type = FrameType.ACK;
} else if ((ctrlByte & 0xe0) === 0xa0) {
this.type = FrameType.NAK;
} else if (ctrlByte === 0xc0) {
this.type = FrameType.RST;
} else if (ctrlByte === 0xc1) {
this.type = FrameType.RSTACK;
} else if (ctrlByte === 0xc2) {
this.type = FrameType.ERROR;
} else {
this.type = FrameType.UNKNOWN;
}
}
get control(): number {
return this.buffer[0];
}
public static fromBuffer(buffer: Buffer): Frame {
return new Frame(buffer);
}
/**
* XOR s with a pseudo-random sequence for transmission.
* Used only in data frames.
*/
public static makeRandomizedBuffer(buffer: Buffer): Buffer {
let rand = RANDOMIZE_START;
const out = Buffer.alloc(buffer.length);
let outIdx = 0;
for (const c of buffer) {
out.writeUInt8(c ^ rand, outIdx++);
if (rand % 2) {
rand = (rand >> 1) ^ RANDOMIZE_SEQ;
} else {
rand = rand >> 1;
}
}
return out;
}
/**
* Throws on CRC error.
*/
public checkCRC(): void {
const crc = crc16ccitt(this.buffer.subarray(0, -3), 65535);
const crcArr = Buffer.from([crc >> 8, crc % 256]);
const subArr = this.buffer.subarray(-3, -1);
if (!subArr.equals(crcArr)) {
throw new Error(`<-- CRC error: ${this.toString()}|${subArr.toString("hex")}|${crcArr.toString("hex")}`);
}
}
/**
*
* @returns Buffer to hex string
*/
public toString(): string {
return this.buffer.toString("hex");
}
}
export default Frame;