zigbee-herdsman
Version:
An open source ZigBee gateway solution with node.js.
934 lines • 36.1 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.BuffaloZcl = void 0;
const buffalo_1 = require("../../buffalo");
const logger_1 = require("../../utils/logger");
const utils_1 = require("../../utils/utils");
const enums_1 = require("./definition/enums");
const Utils = __importStar(require("./utils"));
const NS = "zh:zcl:buffalo";
const SEC_KEY_LENGTH = 16;
const EXTENSION_FIELD_SETS_DATA_TYPE = {
6: [enums_1.DataType.UINT8],
8: [enums_1.DataType.UINT8],
258: [enums_1.DataType.UINT8, enums_1.DataType.UINT8],
768: [enums_1.DataType.UINT16, enums_1.DataType.UINT16, enums_1.DataType.UINT16, enums_1.DataType.UINT8, enums_1.DataType.UINT8, enums_1.DataType.UINT8, enums_1.DataType.UINT16, enums_1.DataType.UINT16],
};
class BuffaloZcl extends buffalo_1.Buffalo {
writeOctetStr(value) {
// TODO: this does not allow "non-value" 0xFF
this.writeUInt8(value.length);
this.writeBuffer(value, value.length);
}
readOctetStr() {
const length = this.readUInt8();
return length < 0xff ? this.readBuffer(length) : Buffer.from([]); // non-value
}
writeCharStr(value) {
// TODO: this does not allow "non-value" 0xFF
if (typeof value === "string") {
this.writeUInt8(Buffer.byteLength(value, "utf8"));
this.writeUtf8String(value);
}
else {
// XXX: value.length not written?
this.writeBuffer(value, value.length);
}
}
readCharStr() {
const length = this.readUInt8();
return length < 0xff ? this.readUtf8String(length) : "";
}
writeLongOctetStr(value) {
// TODO: this does not allow "non-value" 0xFF
this.writeUInt16(value.length);
this.writeBuffer(value, value.length);
}
readLongOctetStr() {
const length = this.readUInt16();
return length < 0xffff ? this.readBuffer(length) : Buffer.from([]); // non-value
}
writeLongCharStr(value) {
// TODO: this does not allow "non-value" 0xFF
this.writeUInt16(Buffer.byteLength(value, "utf8"));
this.writeUtf8String(value);
}
readLongCharStr() {
const length = this.readUInt16();
return length < 0xffff ? this.readUtf8String(length) : ""; // non-value
}
writeArray(value) {
const elTypeNumeric = typeof value.elementType === "number" ? value.elementType : enums_1.DataType[value.elementType];
this.writeUInt8(elTypeNumeric);
// TODO: this does not allow writing "non-value" 0xFFFF
this.writeUInt16(value.elements.length);
for (const element of value.elements) {
this.write(elTypeNumeric, element, {});
}
}
readArray() {
const values = [];
const elementType = this.readUInt8();
const numberOfElements = this.readUInt16();
if (numberOfElements < 0xffff) {
for (let i = 0; i < numberOfElements; i++) {
const value = this.read(elementType, {});
values.push(value);
}
}
return values;
}
writeStruct(value) {
// XXX: from ZCL spec: "The zeroth element may not be written to."
// how does this translates to writing here?
// TODO: this does not allow writing "non-value" 0xFFFF
this.writeUInt16(value.length);
for (const v of value) {
this.writeUInt8(v.elmType);
this.write(v.elmType, v.elmVal, {});
}
}
readStruct() {
const values = [];
const numberOfElements = this.readUInt16();
if (numberOfElements < 0xffff) {
for (let i = 0; i < numberOfElements; i++) {
const elementType = this.readUInt8();
const value = this.read(elementType, {});
values.push({ elmType: elementType, elmVal: value });
}
}
return values;
}
writeToD(value) {
this.writeUInt8(value.hours ?? 0xff);
this.writeUInt8(value.minutes ?? 0xff);
this.writeUInt8(value.seconds ?? 0xff);
this.writeUInt8(value.hundredths ?? 0xff);
}
readToD() {
const hours = this.readUInt8();
const minutes = this.readUInt8();
const seconds = this.readUInt8();
const hundredths = this.readUInt8();
return {
hours: hours < 0xff ? hours : undefined,
minutes: minutes < 0xff ? minutes : undefined,
seconds: seconds < 0xff ? seconds : undefined,
hundredths: hundredths < 0xff ? hundredths : undefined,
};
}
writeDate(value) {
this.writeUInt8(value.year !== undefined ? value.year - 1900 : 0xff);
this.writeUInt8(value.month ?? 0xff);
this.writeUInt8(value.dayOfMonth ?? 0xff);
this.writeUInt8(value.dayOfWeek ?? 0xff);
}
readDate() {
const year = this.readUInt8();
const month = this.readUInt8();
const dayOfMonth = this.readUInt8();
const dayOfWeek = this.readUInt8();
return {
year: year < 0xff ? year + 1900 : undefined,
month: month < 0xff ? month : undefined,
dayOfMonth: dayOfMonth < 0xff ? dayOfMonth : undefined,
dayOfWeek: dayOfWeek < 0xff ? dayOfWeek : undefined,
};
}
//--- BuffaloZclDataType
writeListZoneInfo(values) {
for (const value of values) {
this.writeUInt8(value.zoneID);
this.writeUInt16(value.zoneStatus);
}
}
readListZoneInfo(length) {
const value = [];
for (let i = 0; i < length; i++) {
value.push({
zoneID: this.readUInt8(),
zoneStatus: this.readUInt16(),
});
}
return value;
}
writeExtensionFieldSets(values) {
for (const value of values) {
this.writeUInt16(value.clstId);
this.writeUInt8(value.len);
let index = 0;
for (const entry of value.extField) {
this.write(EXTENSION_FIELD_SETS_DATA_TYPE[value.clstId][index], entry, {});
index++;
}
}
}
readExtensionFieldSets() {
const value = [];
// XXX: doesn't work if buffer has more unrelated fields after this one
while (this.isMore()) {
const clstId = this.readUInt16();
const len = this.readUInt8();
const end = this.getPosition() + len;
let index = 0;
const extField = [];
while (this.getPosition() < end) {
extField.push(this.read(EXTENSION_FIELD_SETS_DATA_TYPE[clstId][index], {}));
index++;
}
value.push({ extField, clstId, len });
}
return value;
}
writeListThermoTransitions(value) {
for (const entry of value) {
this.writeUInt16(entry.transitionTime);
if (entry.heatSetpoint != null) {
this.writeUInt16(entry.heatSetpoint);
}
if (entry.coolSetpoint != null) {
this.writeUInt16(entry.coolSetpoint);
}
}
}
readListThermoTransitions(options) {
if (options.payload == null || options.payload.mode == null || options.payload.numoftrans == null) {
throw new Error("Cannot read LIST_THERMO_TRANSITIONS without required payload options specified");
}
const heat = options.payload.mode & 1;
const cool = options.payload.mode & 2;
const result = [];
for (let i = 0; i < options.payload.numoftrans; i++) {
const entry = {
transitionTime: this.readUInt16(),
};
if (heat) {
entry.heatSetpoint = this.readUInt16();
}
if (cool) {
entry.coolSetpoint = this.readUInt16();
}
result.push(entry);
}
return result;
}
writeGpdFrame(value) {
if (value.commandID === 0xf0) {
// Commissioning Reply
const v = value;
const panIDPresent = Boolean(v.options & 0x1);
const gpdSecurityKeyPresent = Boolean(v.options & 0x2);
const gpdKeyEncryption = Boolean((v.options >> 2) & 0x1);
const securityLevel = (v.options >> 3) & 0x3;
const hasGPDKeyMIC = gpdKeyEncryption && gpdSecurityKeyPresent;
const hasFrameCounter = gpdSecurityKeyPresent && gpdKeyEncryption && (securityLevel === 0b10 || securityLevel === 0b11);
this.writeUInt8(1 + (panIDPresent ? 2 : 0) + (gpdSecurityKeyPresent ? 16 : 0) + (hasGPDKeyMIC ? 4 : 0) + (hasFrameCounter ? 4 : 0)); // Length
this.writeUInt8(v.options);
if (panIDPresent) {
// biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
this.writeUInt16(v.panID);
}
if (gpdSecurityKeyPresent) {
// biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
this.writeBuffer(v.securityKey, 16);
}
if (hasGPDKeyMIC) {
// biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
this.writeUInt32(v.keyMic);
}
if (hasFrameCounter) {
// biome-ignore lint/style/noNonNullAssertion: ignored using `--suppress`
this.writeUInt32(v.frameCounter);
}
}
else if (value.commandID === 0xf3) {
// Channel configuration
const v = value;
this.writeUInt8(1);
this.writeUInt8((v.operationalChannel & 0xf) | ((v.basic ? 1 : 0) << 4));
}
else if (value.commandID === 0xf4 || value.commandID === 0xf5 || (value.commandID >= 0xf7 && value.commandID <= 0xff)) {
// Other commands sent to GPD
const v = value;
this.writeUInt8(v.buffer.length);
this.writeBuffer(v.buffer, v.buffer.length);
}
// 0xf1: Write Attributes
// 0xf2: Read Attributes
// 0xf6: ZCL Tunneling
}
readGpdFrame(options) {
// ensure offset by options.payload.payloadSize (if any) at end of parsing to not cause issues with spec changes (until supported)
const startPosition = this.position;
if (options.payload?.commandID === 0xe0) {
// Commisioning
const frame = {
deviceID: this.readUInt8(),
options: this.readUInt8(),
extendedOptions: 0,
securityKey: Buffer.alloc(16),
keyMic: 0,
outgoingCounter: 0,
applicationInfo: 0,
manufacturerID: 0,
modelID: 0,
numGpdCommands: 0,
gpdCommandIdList: Buffer.alloc(0),
numServerClusters: 0,
numClientClusters: 0,
gpdServerClusters: Buffer.alloc(0),
gpdClientClusters: Buffer.alloc(0),
genericSwitchConfig: 0,
currentContactStatus: 0,
};
if (frame.options & 0x80) {
frame.extendedOptions = this.readUInt8();
}
if (frame.extendedOptions & 0x20) {
frame.securityKey = this.readBuffer(16);
}
if (frame.extendedOptions & 0x40) {
frame.keyMic = this.readUInt32();
}
if (frame.extendedOptions & 0x80) {
frame.outgoingCounter = this.readUInt32();
}
if (frame.options & 0x04) {
frame.applicationInfo = this.readUInt8();
}
if (frame.applicationInfo & 0x01) {
frame.manufacturerID = this.readUInt16();
}
if (frame.applicationInfo & 0x02) {
frame.modelID = this.readUInt16();
}
if (frame.applicationInfo & 0x04) {
frame.numGpdCommands = this.readUInt8();
frame.gpdCommandIdList = this.readBuffer(frame.numGpdCommands);
}
if (frame.applicationInfo & 0x08) {
const len = this.readUInt8();
frame.numServerClusters = len & 0xf;
frame.numClientClusters = (len >> 4) & 0xf;
frame.gpdServerClusters = this.readBuffer(2 * frame.numServerClusters);
frame.gpdClientClusters = this.readBuffer(2 * frame.numClientClusters);
}
if (frame.applicationInfo & 0x10) {
const len = this.readUInt8();
if (len >= 1) {
frame.genericSwitchConfig = this.readUInt8();
}
if (len >= 2) {
frame.currentContactStatus = this.readUInt8();
}
}
if (options.payload.payloadSize) {
this.position = startPosition + options.payload.payloadSize;
}
return frame;
}
if (options.payload?.commandID === 0xe3) {
// Channel Request
const channelOpts = this.readUInt8();
/* v8 ignore start */
if (options.payload?.payloadSize) {
this.position = startPosition + options.payload.payloadSize;
}
/* v8 ignore stop */
return {
nextChannel: channelOpts & 0xf,
nextNextChannel: channelOpts >> 4,
};
}
if (options.payload?.commandID === 0xa1) {
// Manufacturer-specific Attribute Reporting
if (options.payload.payloadSize === undefined) {
throw new Error("Cannot read GPD_FRAME with commandID=0xA1 without payloadSize options specified");
}
const start = this.position;
const frame = {
manufacturerCode: this.readUInt16(),
clusterID: this.readUInt16(),
attributes: {},
};
const cluster = Utils.getCluster(frame.clusterID, frame.manufacturerCode, {});
while (this.position - start < options.payload.payloadSize) {
const attributeID = this.readUInt16();
const type = this.readUInt8();
let attribute = attributeID;
try {
attribute = cluster.getAttribute(attributeID).name;
}
catch {
// this is spammy because of the many manufacturer-specific attributes not currently used
logger_1.logger.debug(`Unknown attribute ${attributeID} in cluster ${cluster.name}`, NS);
}
frame.attributes[attribute] = this.read(type, options);
}
this.position = startPosition + options.payload.payloadSize;
return frame;
}
if (options.payload?.payloadSize && this.isMore()) {
// might contain `gppNwkAddr`, `gppGpdLink` & `mic` from ZCL cluster, so limit by `payloadSize`
return { raw: this.readBuffer(options.payload.payloadSize) };
}
if (options.payload?.payloadSize) {
this.position = startPosition + options.payload.payloadSize;
}
return {};
}
writeStructuredSelector(value) {
if (value != null) {
const indexes = value.indexes || [];
const indicatorType = value.indicatorType || enums_1.StructuredIndicatorType.Whole;
const indicator = indexes.length + indicatorType;
this.writeUInt8(indicator);
for (const index of indexes) {
this.writeUInt16(index);
}
}
}
readStructuredSelector() {
/** [0-15] range */
const indicator = this.readUInt8();
if (indicator === 0) {
// no indexes, whole attribute value is to be read
return { indicatorType: enums_1.StructuredIndicatorType.Whole };
}
if (indicator < enums_1.StructuredIndicatorType.WriteAdd) {
const indexes = [];
for (let i = 0; i < indicator; i++) {
const index = this.readUInt16();
indexes.push(index);
}
return { indexes };
}
throw new Error("Read structured selector was outside [0-15] range.");
}
writeListTuyaDataPointValues(dpValues) {
for (const dpValue of dpValues) {
this.writeUInt8(dpValue.dp);
this.writeUInt8(dpValue.datatype);
const dataLen = dpValue.data.length;
// UInt16BE
this.writeUInt8((dataLen >> 8) & 0xff);
this.writeUInt8(dataLen & 0xff);
this.writeBuffer(dpValue.data, dataLen);
}
}
readListTuyaDataPointValues() {
const value = [];
// XXX: doesn't work if buffer has more unrelated fields after this one
while (this.isMore()) {
try {
const dp = this.readUInt8();
const datatype = this.readUInt8();
const len_hi = this.readUInt8();
const len_lo = this.readUInt8();
const data = this.readBuffer(len_lo + (len_hi << 8));
value.push({ dp, datatype, data });
}
catch {
break;
}
}
return value;
}
writeListMiboxerZones(values) {
this.writeUInt8(values.length);
for (const value of values) {
this.writeUInt16(value.groupId);
this.writeUInt8(value.zoneNum);
}
}
readListMiboxerZones() {
const value = [];
const len = this.readUInt8();
for (let i = 0; i < len; i++) {
const groupId = this.readUInt16();
const zoneNum = this.readUInt8();
value.push({ groupId, zoneNum });
}
return value;
}
writeBigEndianUInt24(value) {
this.buffer.writeUIntBE(value, this.position, 3);
this.position += 3;
}
readBigEndianUInt24() {
const value = this.buffer.readUIntBE(this.position, 3);
this.position += 3;
return value;
}
// NOTE: writeMiStruct is not supported.
readMiStruct() {
const length = this.readUInt8();
const value = {};
if (length === 0xff) {
return value;
}
for (let i = 0; i < length; i++) {
const index = this.readUInt8();
const dataType = this.readUInt8();
value[index] = this.read(dataType, {});
const remaining = this.buffer.length - this.position;
if (remaining <= 1) {
if (remaining === 1) {
// Some Xiaomi structs have a trailing byte, skip it.
this.position += 1;
}
break;
}
}
return value;
}
// biome-ignore lint/suspicious/noExplicitAny: API
write(type, value, options) {
switch (type) {
case enums_1.DataType.NO_DATA:
case enums_1.DataType.UNKNOWN: {
return; // nothing to write
}
case enums_1.DataType.DATA8:
case enums_1.DataType.BOOLEAN:
case enums_1.DataType.BITMAP8:
case enums_1.DataType.UINT8:
case enums_1.DataType.ENUM8: {
this.writeUInt8(value);
break;
}
case enums_1.DataType.DATA16:
case enums_1.DataType.BITMAP16:
case enums_1.DataType.UINT16:
case enums_1.DataType.ENUM16:
case enums_1.DataType.CLUSTER_ID:
case enums_1.DataType.ATTR_ID: {
this.writeUInt16(value);
break;
}
case enums_1.DataType.DATA24:
case enums_1.DataType.BITMAP24:
case enums_1.DataType.UINT24: {
this.writeUInt24(value);
break;
}
case enums_1.DataType.DATA32:
case enums_1.DataType.BITMAP32:
case enums_1.DataType.UINT32:
case enums_1.DataType.UTC:
case enums_1.DataType.BAC_OID: {
this.writeUInt32(value);
break;
}
case enums_1.DataType.DATA40:
case enums_1.DataType.BITMAP40:
case enums_1.DataType.UINT40: {
this.writeUInt40(value);
break;
}
case enums_1.DataType.DATA48:
case enums_1.DataType.BITMAP48:
case enums_1.DataType.UINT48: {
this.writeUInt48(value);
break;
}
case enums_1.DataType.DATA56:
case enums_1.DataType.BITMAP56:
case enums_1.DataType.UINT56: {
this.writeUInt56(value);
break;
}
case enums_1.DataType.DATA64:
case enums_1.DataType.BITMAP64:
case enums_1.DataType.UINT64: {
this.writeUInt64(value);
break;
}
case enums_1.DataType.INT8: {
this.writeInt8(value);
break;
}
case enums_1.DataType.INT16: {
this.writeInt16(value);
break;
}
case enums_1.DataType.INT24: {
this.writeInt24(value);
break;
}
case enums_1.DataType.INT32: {
this.writeInt32(value);
break;
}
case enums_1.DataType.INT40: {
this.writeInt40(value);
break;
}
case enums_1.DataType.INT48: {
this.writeInt48(value);
break;
}
case enums_1.DataType.INT56: {
this.writeInt56(value);
break;
}
case enums_1.DataType.INT64: {
this.writeInt64(value);
break;
}
// case DataType.SEMI_PREC: {
// // https://tc39.es/proposal-float16array/
// // not currently used
// this.writeSemiFloatLE(value);
// break;
// }
case enums_1.DataType.SINGLE_PREC: {
this.writeFloatLE(value);
break;
}
case enums_1.DataType.DOUBLE_PREC: {
this.writeDoubleLE(value);
break;
}
case enums_1.DataType.OCTET_STR: {
this.writeOctetStr(value);
break;
}
case enums_1.DataType.CHAR_STR: {
this.writeCharStr(value);
break;
}
case enums_1.DataType.LONG_OCTET_STR: {
this.writeLongOctetStr(value);
break;
}
case enums_1.DataType.LONG_CHAR_STR: {
this.writeLongCharStr(value);
break;
}
case enums_1.DataType.ARRAY:
case enums_1.DataType.SET:
case enums_1.DataType.BAG: {
this.writeArray(value);
break;
}
case enums_1.DataType.STRUCT: {
this.writeStruct(value);
break;
}
case enums_1.DataType.TOD: {
this.writeToD(value);
break;
}
case enums_1.DataType.DATE: {
this.writeDate(value);
break;
}
case enums_1.DataType.IEEE_ADDR: {
this.writeIeeeAddr(value);
break;
}
case enums_1.DataType.SEC_KEY: {
this.writeBuffer(value, SEC_KEY_LENGTH);
break;
}
case enums_1.BuffaloZclDataType.USE_DATA_TYPE: {
if (options.dataType == null) {
if (Buffer.isBuffer(value) || (0, utils_1.isNumberArray)(value)) {
this.writeBuffer(value, value.length);
break;
}
throw new Error("Cannot write USE_DATA_TYPE without dataType option specified");
}
this.write(options.dataType, value, options);
break;
}
case enums_1.BuffaloZclDataType.LIST_UINT8: {
this.writeListUInt8(value);
break;
}
case enums_1.BuffaloZclDataType.LIST_UINT16: {
this.writeListUInt16(value);
break;
}
case enums_1.BuffaloZclDataType.LIST_UINT24: {
this.writeListUInt24(value);
break;
}
case enums_1.BuffaloZclDataType.LIST_UINT32: {
this.writeListUInt32(value);
break;
}
case enums_1.BuffaloZclDataType.LIST_ZONEINFO: {
this.writeListZoneInfo(value);
break;
}
case enums_1.BuffaloZclDataType.EXTENSION_FIELD_SETS: {
this.writeExtensionFieldSets(value);
break;
}
case enums_1.BuffaloZclDataType.LIST_THERMO_TRANSITIONS: {
this.writeListThermoTransitions(value);
break;
}
case enums_1.BuffaloZclDataType.BUFFER: {
// XXX: inconsistent with read that allows partial with options.length, here always "whole"
this.writeBuffer(value, value.length);
break;
}
case enums_1.BuffaloZclDataType.GPD_FRAME: {
this.writeGpdFrame(value);
break;
}
case enums_1.BuffaloZclDataType.STRUCTURED_SELECTOR: {
this.writeStructuredSelector(value);
break;
}
case enums_1.BuffaloZclDataType.LIST_TUYA_DATAPOINT_VALUES: {
this.writeListTuyaDataPointValues(value);
break;
}
case enums_1.BuffaloZclDataType.LIST_MIBOXER_ZONES: {
this.writeListMiboxerZones(value);
break;
}
case enums_1.BuffaloZclDataType.BIG_ENDIAN_UINT24: {
this.writeBigEndianUInt24(value);
break;
}
default: {
// In case the type is undefined, write it as a buffer to easily allow for custom types
// e.g. for https://github.com/Koenkk/zigbee-herdsman/issues/127
if (Buffer.isBuffer(value) || (0, utils_1.isNumberArray)(value)) {
this.writeBuffer(value, value.length);
break;
}
throw new Error(`Write for '${type}' not available`);
}
}
}
// biome-ignore lint/suspicious/noExplicitAny: API
read(type, options) {
switch (type) {
case enums_1.DataType.NO_DATA:
case enums_1.DataType.UNKNOWN: {
return; // nothing to write
}
case enums_1.DataType.DATA8:
case enums_1.DataType.BOOLEAN:
case enums_1.DataType.BITMAP8:
case enums_1.DataType.UINT8:
case enums_1.DataType.ENUM8: {
return this.readUInt8();
}
case enums_1.DataType.DATA16:
case enums_1.DataType.BITMAP16:
case enums_1.DataType.UINT16:
case enums_1.DataType.ENUM16:
case enums_1.DataType.CLUSTER_ID:
case enums_1.DataType.ATTR_ID: {
return this.readUInt16();
}
case enums_1.DataType.DATA24:
case enums_1.DataType.BITMAP24:
case enums_1.DataType.UINT24: {
return this.readUInt24();
}
case enums_1.DataType.DATA32:
case enums_1.DataType.BITMAP32:
case enums_1.DataType.UINT32:
case enums_1.DataType.UTC:
case enums_1.DataType.BAC_OID: {
return this.readUInt32();
}
case enums_1.DataType.DATA40:
case enums_1.DataType.BITMAP40:
case enums_1.DataType.UINT40: {
return this.readUInt40();
}
case enums_1.DataType.DATA48:
case enums_1.DataType.BITMAP48:
case enums_1.DataType.UINT48: {
return this.readUInt48();
}
case enums_1.DataType.DATA56:
case enums_1.DataType.BITMAP56:
case enums_1.DataType.UINT56: {
return this.readUInt56();
}
case enums_1.DataType.DATA64:
case enums_1.DataType.BITMAP64:
case enums_1.DataType.UINT64: {
return this.readUInt64();
}
case enums_1.DataType.INT8: {
return this.readInt8();
}
case enums_1.DataType.INT16: {
return this.readInt16();
}
case enums_1.DataType.INT24: {
return this.readInt24();
}
case enums_1.DataType.INT32: {
return this.readInt32();
}
case enums_1.DataType.INT40: {
return this.readInt40();
}
case enums_1.DataType.INT48: {
return this.readInt48();
}
case enums_1.DataType.INT56: {
return this.readInt56();
}
case enums_1.DataType.INT64: {
return this.readInt64();
}
// case DataType.SEMI_PREC: {
// // https://tc39.es/proposal-float16array/
// // not currently used
// return this.readSemiFloatLE();
// }
case enums_1.DataType.SINGLE_PREC: {
return this.readFloatLE();
}
case enums_1.DataType.DOUBLE_PREC: {
return this.readDoubleLE();
}
case enums_1.DataType.OCTET_STR: {
return this.readOctetStr();
}
case enums_1.DataType.CHAR_STR: {
return this.readCharStr();
}
case enums_1.DataType.LONG_OCTET_STR: {
return this.readLongOctetStr();
}
case enums_1.DataType.LONG_CHAR_STR: {
return this.readLongCharStr();
}
case enums_1.DataType.ARRAY:
case enums_1.DataType.SET:
case enums_1.DataType.BAG: {
return this.readArray();
}
case enums_1.DataType.STRUCT: {
return this.readStruct();
}
case enums_1.DataType.TOD: {
return this.readToD();
}
case enums_1.DataType.DATE: {
return this.readDate();
}
case enums_1.DataType.IEEE_ADDR: {
return this.readIeeeAddr();
}
case enums_1.DataType.SEC_KEY: {
return this.readBuffer(SEC_KEY_LENGTH);
}
case enums_1.BuffaloZclDataType.USE_DATA_TYPE: {
if (options.dataType == null) {
return this.readBuffer(options.length ?? this.buffer.length);
}
return this.read(options.dataType, options);
}
case enums_1.BuffaloZclDataType.LIST_UINT8: {
if (options.length == null) {
throw new Error("Cannot read LIST_UINT8 without length option specified");
}
return this.readListUInt8(options.length);
}
case enums_1.BuffaloZclDataType.LIST_UINT16: {
if (options.length == null) {
throw new Error("Cannot read LIST_UINT16 without length option specified");
}
return this.readListUInt16(options.length);
}
case enums_1.BuffaloZclDataType.LIST_UINT24: {
if (options.length == null) {
throw new Error("Cannot read LIST_UINT24 without length option specified");
}
return this.readListUInt24(options.length);
}
case enums_1.BuffaloZclDataType.LIST_UINT32: {
if (options.length == null) {
throw new Error("Cannot read LIST_UINT32 without length option specified");
}
return this.readListUInt32(options.length);
}
case enums_1.BuffaloZclDataType.LIST_ZONEINFO: {
if (options.length == null) {
throw new Error("Cannot read LIST_ZONEINFO without length option specified");
}
return this.readListZoneInfo(options.length);
}
case enums_1.BuffaloZclDataType.EXTENSION_FIELD_SETS: {
return this.readExtensionFieldSets();
}
case enums_1.BuffaloZclDataType.LIST_THERMO_TRANSITIONS: {
return this.readListThermoTransitions(options);
}
case enums_1.BuffaloZclDataType.BUFFER: {
// if length option not specified, read the whole buffer
return this.readBuffer(options.length ?? this.buffer.length);
}
case enums_1.BuffaloZclDataType.GPD_FRAME: {
return this.readGpdFrame(options);
}
case enums_1.BuffaloZclDataType.STRUCTURED_SELECTOR: {
return this.readStructuredSelector();
}
case enums_1.BuffaloZclDataType.LIST_TUYA_DATAPOINT_VALUES: {
return this.readListTuyaDataPointValues();
}
case enums_1.BuffaloZclDataType.LIST_MIBOXER_ZONES: {
return this.readListMiboxerZones();
}
case enums_1.BuffaloZclDataType.BIG_ENDIAN_UINT24: {
return this.readBigEndianUInt24();
}
case enums_1.BuffaloZclDataType.MI_STRUCT: {
return this.readMiStruct();
}
}
throw new Error(`Read for '${type}' not available`);
}
}
exports.BuffaloZcl = BuffaloZcl;
//# sourceMappingURL=buffaloZcl.js.map