UNPKG

zigbee-herdsman

Version:

An open source ZigBee gateway solution with node.js.

336 lines (273 loc) 9.28 kB
import type {Eui64} from "../zspec/tstypes"; import {Utils as ZSpecUtils} from "../zspec"; export class Buffalo { protected position: number; protected buffer: Buffer; public constructor(buffer: Buffer, position = 0) { this.position = position; this.buffer = buffer; } public getPosition(): number { return this.position; } public getBuffer(): Buffer { return this.buffer; } public getWritten(): Buffer { return this.buffer.subarray(0, this.position); } public isMore(): boolean { return this.position < this.buffer.length; } public writeUInt8(value: number): void { this.buffer.writeUInt8(value, this.position); this.position++; } public readUInt8(): number { const value = this.buffer.readUInt8(this.position); this.position++; return value; } public writeUInt16(value: number): void { this.buffer.writeUInt16LE(value, this.position); this.position += 2; } public readUInt16(): number { const value = this.buffer.readUInt16LE(this.position); this.position += 2; return value; } public writeUInt24(value: number): void { this.buffer.writeUIntLE(value, this.position, 3); this.position += 3; } public readUInt24(): number { const value = this.buffer.readUIntLE(this.position, 3); this.position += 3; return value; } public writeUInt32(value: number): void { this.buffer.writeUInt32LE(value, this.position); this.position += 4; } public readUInt32(): number { const value = this.buffer.readUInt32LE(this.position); this.position += 4; return value; } public writeUInt40(value: number): void { this.buffer.writeUIntLE(value, this.position, 5); this.position += 5; } public readUInt40(): number { const value = this.buffer.readUIntLE(this.position, 5); this.position += 5; return value; } public writeUInt48(value: number): void { this.buffer.writeUIntLE(value, this.position, 6); this.position += 6; } public readUInt48(): number { const value = this.buffer.readUIntLE(this.position, 6); this.position += 6; return value; } public writeUInt56(value: bigint): void { this.buffer.writeUIntLE(Number(value & 0xffffffffffffn), this.position, 6); this.buffer.writeUInt8(Number(value >> 48n), this.position + 6); this.position += 7; } public readUInt56(): bigint { const low = this.buffer.readUIntLE(this.position, 6); const high = this.buffer.readUInt8(this.position + 6); this.position += 7; return (BigInt(high) << 48n) | BigInt(low); } public writeUInt64(value: bigint): void { this.buffer.writeBigUInt64LE(value, this.position); this.position += 8; } public readUInt64(): bigint { const value = this.buffer.readBigUInt64LE(this.position); this.position += 8; return value; } public writeInt8(value: number): void { this.buffer.writeInt8(value, this.position); this.position++; } public readInt8(): number { const value = this.buffer.readInt8(this.position); this.position++; return value; } public writeInt16(value: number): void { this.buffer.writeInt16LE(value, this.position); this.position += 2; } public readInt16(): number { const value = this.buffer.readInt16LE(this.position); this.position += 2; return value; } public writeInt24(value: number): void { this.buffer.writeIntLE(value, this.position, 3); this.position += 3; } public readInt24(): number { const value = this.buffer.readIntLE(this.position, 3); this.position += 3; return value; } public writeInt32(value: number): void { this.buffer.writeInt32LE(value, this.position); this.position += 4; } public readInt32(): number { const value = this.buffer.readInt32LE(this.position); this.position += 4; return value; } public writeInt40(value: number): void { this.buffer.writeIntLE(value, this.position, 5); this.position += 5; } public readInt40(): number { const value = this.buffer.readIntLE(this.position, 5); this.position += 5; return value; } public writeInt48(value: number): void { this.buffer.writeIntLE(value, this.position, 6); this.position += 6; } public readInt48(): number { const value = this.buffer.readIntLE(this.position, 6); this.position += 6; return value; } public writeInt56(value: bigint): void { const unsignedValue = value < 0n ? (1n << 56n) + value : value; this.buffer.writeUIntLE(Number(unsignedValue & 0xffffffffffffn), this.position, 6); this.buffer.writeUInt8(Number(unsignedValue >> 48n), this.position + 6); this.position += 7; } public readInt56(): bigint { const low = BigInt(this.buffer.readUIntLE(this.position, 6)); const high = BigInt(this.buffer.readUInt8(this.position + 6)); let result = (high << 48n) | low; if (high & 0x80n) { result -= 1n << 56n; } this.position += 7; return result; } public writeInt64(value: bigint): void { this.buffer.writeBigInt64LE(value, this.position); this.position += 8; } public readInt64(): bigint { const value = this.buffer.readBigInt64LE(this.position); this.position += 8; return value; } public writeFloatLE(value: number): void { this.buffer.writeFloatLE(value, this.position); this.position += 4; } public readFloatLE(): number { const value = this.buffer.readFloatLE(this.position); this.position += 4; return value; } public writeDoubleLE(value: number): void { this.buffer.writeDoubleLE(value, this.position); this.position += 8; } public readDoubleLE(): number { const value = this.buffer.readDoubleLE(this.position); this.position += 8; return value; } public writeIeeeAddr(value: string /*TODO: EUI64*/): void { this.writeUInt32(Number.parseInt(value.slice(10), 16)); this.writeUInt32(Number.parseInt(value.slice(2, 10), 16)); } public readIeeeAddr(): Eui64 { return ZSpecUtils.eui64LEBufferToHex(this.readBuffer(8)); } public writeBuffer(values: Buffer | number[], length: number): void { if (values.length !== length) { throw new Error(`Length of values: '${values}' is not consitent with expected length '${length}'`); } if (!(values instanceof Buffer)) { values = Buffer.from(values); } this.position += values.copy(this.buffer, this.position); } public readBuffer(length: number): Buffer { const value = this.buffer.subarray(this.position, this.position + length); this.position += length; return value; } public writeListUInt8(values: number[]): void { for (const value of values) { this.writeUInt8(value); } } public readListUInt8(length: number): number[] { const value: number[] = []; for (let i = 0; i < length; i++) { value.push(this.readUInt8()); } return value; } public writeListUInt16(values: number[]): void { for (const value of values) { this.writeUInt16(value); } } public readListUInt16(length: number): number[] { const value: number[] = []; for (let i = 0; i < length; i++) { value.push(this.readUInt16()); } return value; } public writeListUInt24(values: number[]): void { for (const value of values) { this.writeUInt24(value); } } public readListUInt24(length: number): number[] { const value: number[] = []; for (let i = 0; i < length; i++) { value.push(this.readUInt24()); } return value; } public writeListUInt32(values: number[]): void { for (const value of values) { this.writeUInt32(value); } } public readListUInt32(length: number): number[] { const value: number[] = []; for (let i = 0; i < length; i++) { value.push(this.readUInt32()); } return value; } public writeUtf8String(value: string): void { // value==='' is supported and is identified as "empty string" this.position += this.buffer.write(value, this.position, "utf8"); } public readUtf8String(length: number): string { // length===0 is supported and is identified as "empty string" const value = this.buffer.toString("utf8", this.position, this.position + length); this.position += length; return value; } } export default Buffalo;