zigbee-herdsman-zigate
Version:
An open source ZigBee gateway solution with node.js.
69 lines (54 loc) • 2.25 kB
text/typescript
import {Type, Subsystem, DataStart, SOF, PositionCmd0, PositionCmd1} from './constants';
class Frame {
public readonly type: Type;
public readonly subsystem: Subsystem;
public readonly commandID: number;
public readonly data: Buffer;
public readonly length: number;
public readonly fcs: number;
public constructor(
type: Type, subsystem: Subsystem, commandID: number, data: Buffer,
length: number = null, fcs: number = null,
) {
this.type = type;
this.subsystem = subsystem;
this.commandID = commandID;
this.data = data;
this.length = length;
this.fcs = fcs;
}
public toBuffer(): Buffer {
const length = this.data.length;
const cmd0 = ((this.type << 5) & 0xE0) | (this.subsystem & 0x1F);
let payload = Buffer.from([SOF, length, cmd0, this.commandID]);
payload = Buffer.concat([payload, this.data]);
const fcs = Frame.calculateChecksum(payload.slice(1, payload.length));
return Buffer.concat([payload, Buffer.from([fcs])]);
}
public static fromBuffer(length: number, fcsPosition: number, buffer: Buffer): Frame {
const subsystem: Subsystem = buffer.readUInt8(PositionCmd0) & 0x1F;
const type: Type = (buffer.readUInt8(PositionCmd0) & 0xE0) >> 5;
const commandID = buffer.readUInt8(PositionCmd1);
const data = buffer.slice(DataStart, fcsPosition);
const fcs = buffer.readUInt8(fcsPosition);
// Validate the checksum to see if we fully received the message
const checksum = this.calculateChecksum(buffer.slice(1, fcsPosition));
if (checksum === fcs) {
return new Frame(type, subsystem, commandID, data, length, fcs);
} else {
throw new Error("Invalid checksum");
}
}
private static calculateChecksum(values: Buffer): number {
let checksum = 0;
for (const value of values) {
checksum ^= value;
}
return checksum;
}
public toString(): string {
return `${this.length} - ${this.type} - ${this.subsystem} - ${this.commandID} - ` +
`[${[...this.data]}] - ${this.fcs}`;
}
}
export default Frame;