zigbee-herdsman
Version:
An open source Zigbee gateway solution with node.js.
657 lines • 26 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Foundation = void 0;
const utils_1 = require("../utils");
const zclStatusError_1 = require("../zclStatusError");
const enums_1 = require("./enums");
const status_1 = require("./status");
exports.Foundation = {
/** Read Attributes */
read: {
name: "read",
ID: 0x00,
response: 0x01, // readRsp
parse(buffalo) {
const payload = [];
do {
const attrId = buffalo.readUInt16();
payload.push({ attrId });
} while (buffalo.isMore());
return payload;
},
write(buffalo, payload) {
if (!Array.isArray(payload)) {
throw new zclStatusError_1.ZclStatusError(status_1.Status.MALFORMED_COMMAND);
}
for (const entry of payload) {
buffalo.writeUInt16(entry.attrId);
}
},
},
/** Read Attributes Response */
readRsp: {
name: "readRsp",
ID: 0x01,
parse(buffalo) {
const payload = [];
do {
const attrId = buffalo.readUInt16();
const status = buffalo.readUInt8();
const rec = { attrId, status };
if (status === status_1.Status.SUCCESS) {
const dataType = buffalo.readUInt8();
rec.dataType = dataType;
// [workaround] parse char str as Xiaomi struct for attribute 0xff01 (65281)
rec.attrData = buffalo.read(attrId === 0xff01 && dataType === enums_1.DataType.CHAR_STR ? enums_1.BuffaloZclDataType.MI_STRUCT : dataType, {});
}
payload.push(rec);
} while (buffalo.isMore());
return payload;
},
write(buffalo, payload) {
if (!Array.isArray(payload)) {
throw new zclStatusError_1.ZclStatusError(status_1.Status.MALFORMED_COMMAND);
}
for (const entry of payload) {
buffalo.writeUInt16(entry.attrId);
buffalo.writeUInt8(entry.status);
if (entry.status === status_1.Status.SUCCESS) {
buffalo.writeUInt8(entry.dataType);
buffalo.write(entry.dataType, entry.attrData, {});
}
}
},
},
/** Write Attributes */
write: {
name: "write",
ID: 0x02,
response: 0x04, // writeRsp
parse(buffalo) {
const payload = [];
do {
const attrId = buffalo.readUInt16();
const dataType = buffalo.readUInt8();
const attrData = buffalo.read(dataType, {});
payload.push({ attrId, dataType, attrData });
} while (buffalo.isMore());
return payload;
},
write(buffalo, payload) {
if (!Array.isArray(payload)) {
throw new zclStatusError_1.ZclStatusError(status_1.Status.MALFORMED_COMMAND);
}
for (const entry of payload) {
buffalo.writeUInt16(entry.attrId);
buffalo.writeUInt8(entry.dataType);
buffalo.write(entry.dataType, entry.attrData, {});
}
},
},
/** Write Attributes Undivided */
writeUndiv: {
name: "writeUndiv",
ID: 0x03,
parse(buffalo) {
const payload = [];
do {
const attrId = buffalo.readUInt16();
const dataType = buffalo.readUInt8();
const attrData = buffalo.read(dataType, {});
payload.push({ attrId, dataType, attrData });
} while (buffalo.isMore());
return payload;
},
write(buffalo, payload) {
if (!Array.isArray(payload)) {
throw new zclStatusError_1.ZclStatusError(status_1.Status.MALFORMED_COMMAND);
}
for (const entry of payload) {
buffalo.writeUInt16(entry.attrId);
buffalo.writeUInt8(entry.dataType);
buffalo.write(entry.dataType, entry.attrData, {});
}
},
},
/** Write Attributes Response */
writeRsp: {
name: "writeRsp",
ID: 0x04,
/**
* Note that write attribute status records are not included for successfully written attributes, to save bandwidth.
* In the case of successful writing of all attributes, only a single write attribute status record SHALL be included in the command,
* with the status field set to SUCCESS and the attribute identifier field omitted.
*/
parse(buffalo) {
const firstStatus = buffalo.readUInt8();
if (firstStatus === status_1.Status.SUCCESS) {
return [{ status: firstStatus }];
}
const payload = [];
const attrId = buffalo.readUInt16();
payload.push({ status: firstStatus, attrId });
while (buffalo.isMore()) {
const status = buffalo.readUInt8();
const attrId = buffalo.readUInt16();
payload.push({ status, attrId });
}
return payload;
},
write(buffalo, payload) {
if (!Array.isArray(payload)) {
throw new zclStatusError_1.ZclStatusError(status_1.Status.MALFORMED_COMMAND);
}
const nonSuccessPayload = payload.filter((entry) => entry.status !== status_1.Status.SUCCESS);
if (nonSuccessPayload.length === 0) {
buffalo.writeUInt8(status_1.Status.SUCCESS);
}
else {
for (const entry of nonSuccessPayload) {
buffalo.writeUInt8(entry.status);
buffalo.writeUInt16(entry.attrId);
}
}
},
},
/** Write Attributes No Response */
writeNoRsp: {
name: "writeNoRsp",
ID: 0x05,
parse(buffalo) {
const payload = [];
do {
const attrId = buffalo.readUInt16();
const dataType = buffalo.readUInt8();
const attrData = buffalo.read(dataType, {});
payload.push({ attrId, dataType, attrData });
} while (buffalo.isMore());
return payload;
},
write(buffalo, payload) {
if (!Array.isArray(payload)) {
throw new zclStatusError_1.ZclStatusError(status_1.Status.MALFORMED_COMMAND);
}
for (const entry of payload) {
buffalo.writeUInt16(entry.attrId);
buffalo.writeUInt8(entry.dataType);
buffalo.write(entry.dataType, entry.attrData, {});
}
},
},
/** Configure Reporting */
configReport: {
name: "configReport",
ID: 0x06,
response: 0x07, // configReportRsp
parse(buffalo) {
const payload = [];
do {
const direction = buffalo.readUInt8();
const attrId = buffalo.readUInt16();
const rec = { direction, attrId };
if (direction === enums_1.Direction.CLIENT_TO_SERVER) {
const dataType = buffalo.readUInt8();
rec.dataType = dataType;
rec.minRepIntval = buffalo.readUInt16();
rec.maxRepIntval = buffalo.readUInt16();
if ((0, utils_1.isAnalogDataType)(dataType)) {
rec.repChange = buffalo.read(dataType, {});
}
}
else if (direction === enums_1.Direction.SERVER_TO_CLIENT) {
rec.timeout = buffalo.readUInt16();
}
payload.push(rec);
} while (buffalo.isMore());
return payload;
},
write(buffalo, payload) {
if (!Array.isArray(payload)) {
throw new zclStatusError_1.ZclStatusError(status_1.Status.MALFORMED_COMMAND);
}
for (const entry of payload) {
buffalo.writeUInt8(entry.direction);
buffalo.writeUInt16(entry.attrId);
if (entry.direction === enums_1.Direction.CLIENT_TO_SERVER) {
buffalo.writeUInt8(entry.dataType);
buffalo.writeUInt16(entry.minRepIntval);
buffalo.writeUInt16(entry.maxRepIntval);
if ((0, utils_1.isAnalogDataType)(entry.dataType)) {
buffalo.write(entry.dataType, entry.repChange, {});
}
}
else if (entry.direction === enums_1.Direction.SERVER_TO_CLIENT) {
buffalo.writeUInt16(entry.timeout);
}
}
},
},
/** Configure Reporting Response */
configReportRsp: {
name: "configReportRsp",
ID: 0x07,
/**
* Note that attribute status records are not included for successfully configured attributes, to save bandwidth.
* In the case of successful configuration of all attributes, only a single attribute status record SHALL be included in the command,
* with the status field set to SUCCESS and the direction and attribute identifier fields omitted.
*/
parse(buffalo) {
const firstStatus = buffalo.readUInt8();
if (firstStatus === status_1.Status.SUCCESS) {
return [{ status: firstStatus }];
}
const payload = [];
const direction = buffalo.readUInt8();
const attrId = buffalo.readUInt16();
payload.push({ status: firstStatus, direction, attrId });
while (buffalo.isMore()) {
const status = buffalo.readUInt8();
const direction = buffalo.readUInt8();
const attrId = buffalo.readUInt16();
payload.push({ status, direction, attrId });
}
return payload;
},
write(buffalo, payload) {
if (!Array.isArray(payload)) {
throw new zclStatusError_1.ZclStatusError(status_1.Status.MALFORMED_COMMAND);
}
const nonSuccessPayload = payload.filter((entry) => entry.status !== status_1.Status.SUCCESS);
if (nonSuccessPayload.length === 0) {
buffalo.writeUInt8(status_1.Status.SUCCESS);
}
else {
for (const entry of nonSuccessPayload) {
buffalo.writeUInt8(entry.status);
buffalo.writeUInt8(entry.direction);
buffalo.writeUInt16(entry.attrId);
}
}
},
},
/** Read Reporting Configuration */
readReportConfig: {
name: "readReportConfig",
ID: 0x08,
response: 0x09, // readReportConfigRsp
parse(buffalo) {
const payload = [];
do {
const direction = buffalo.readUInt8();
const attrId = buffalo.readUInt16();
payload.push({ direction, attrId });
} while (buffalo.isMore());
return payload;
},
write(buffalo, payload) {
if (!Array.isArray(payload)) {
throw new zclStatusError_1.ZclStatusError(status_1.Status.MALFORMED_COMMAND);
}
for (const entry of payload) {
buffalo.writeUInt8(entry.direction);
buffalo.writeUInt16(entry.attrId);
}
},
},
/** Read Reporting Configuration Response */
readReportConfigRsp: {
name: "readReportConfigRsp",
ID: 0x09,
parse(buffalo) {
const payload = [];
do {
const status = buffalo.readUInt8();
const direction = buffalo.readUInt8();
const attrId = buffalo.readUInt16();
const rec = { status, direction, attrId };
if (status === status_1.Status.SUCCESS) {
if (direction === enums_1.Direction.CLIENT_TO_SERVER) {
const dataType = buffalo.readUInt8();
rec.dataType = dataType;
rec.minRepIntval = buffalo.readUInt16();
rec.maxRepIntval = buffalo.readUInt16();
if ((0, utils_1.isAnalogDataType)(dataType)) {
rec.repChange = buffalo.read(dataType, {});
}
}
else if (direction === enums_1.Direction.SERVER_TO_CLIENT) {
rec.timeout = buffalo.readUInt16();
}
}
payload.push(rec);
} while (buffalo.isMore());
return payload;
},
write(buffalo, payload) {
if (!Array.isArray(payload)) {
throw new zclStatusError_1.ZclStatusError(status_1.Status.MALFORMED_COMMAND);
}
for (const entry of payload) {
buffalo.writeUInt8(entry.status);
buffalo.writeUInt8(entry.direction);
buffalo.writeUInt16(entry.attrId);
if (entry.status === status_1.Status.SUCCESS) {
if (entry.direction === enums_1.Direction.CLIENT_TO_SERVER) {
buffalo.writeUInt8(entry.dataType);
buffalo.writeUInt16(entry.minRepIntval);
buffalo.writeUInt16(entry.maxRepIntval);
if ((0, utils_1.isAnalogDataType)(entry.dataType)) {
buffalo.write(entry.dataType, entry.repChange, {});
}
}
else if (entry.direction === enums_1.Direction.SERVER_TO_CLIENT) {
buffalo.writeUInt16(entry.timeout);
}
}
}
},
},
/** Report attributes */
report: {
name: "report",
ID: 0x0a,
parse(buffalo) {
const payload = [];
do {
const attrId = buffalo.readUInt16();
const dataType = buffalo.readUInt8();
// [workaround] parse char str as Xiaomi struct for attribute 0xff01 (65281)
const attrData = buffalo.read(attrId === 0xff01 && dataType === enums_1.DataType.CHAR_STR ? enums_1.BuffaloZclDataType.MI_STRUCT : dataType, {});
payload.push({ attrId, dataType, attrData });
} while (buffalo.isMore());
return payload;
},
write(buffalo, payload) {
if (!Array.isArray(payload)) {
throw new zclStatusError_1.ZclStatusError(status_1.Status.MALFORMED_COMMAND);
}
for (const entry of payload) {
buffalo.writeUInt16(entry.attrId);
buffalo.writeUInt8(entry.dataType);
buffalo.write(entry.dataType, entry.attrData, {});
}
},
},
/** Default Response */
defaultRsp: {
name: "defaultRsp",
ID: 0x0b,
parse(buffalo) {
const cmdId = buffalo.readUInt8();
const statusCode = buffalo.readUInt8();
return { cmdId, statusCode };
},
write(buffalo, payload) {
if (Array.isArray(payload)) {
throw new zclStatusError_1.ZclStatusError(status_1.Status.MALFORMED_COMMAND);
}
buffalo.writeUInt8(payload.cmdId);
buffalo.writeUInt8(payload.statusCode);
},
},
/** Discover Attributes */
discover: {
name: "discover",
ID: 0x0c,
parse(buffalo) {
const startAttrId = buffalo.readUInt16();
const maxAttrIds = buffalo.readUInt8();
return { startAttrId, maxAttrIds };
},
write(buffalo, payload) {
if (Array.isArray(payload)) {
throw new zclStatusError_1.ZclStatusError(status_1.Status.MALFORMED_COMMAND);
}
buffalo.writeUInt16(payload.startAttrId);
buffalo.writeUInt8(payload.maxAttrIds);
},
},
/** Discover Attributes Response */
discoverRsp: {
name: "discoverRsp",
ID: 0x0d,
parse(buffalo) {
const discComplete = buffalo.readUInt8();
const attrInfos = [];
const payload = { discComplete, attrInfos };
do {
const attrId = buffalo.readUInt16();
const dataType = buffalo.readUInt8();
attrInfos.push({ attrId, dataType });
} while (buffalo.isMore());
return payload;
},
write(buffalo, payload) {
if (Array.isArray(payload)) {
throw new zclStatusError_1.ZclStatusError(status_1.Status.MALFORMED_COMMAND);
}
buffalo.writeUInt8(payload.discComplete);
for (const entry of payload.attrInfos) {
buffalo.writeUInt16(entry.attrId);
buffalo.writeUInt8(entry.dataType);
}
},
},
/** Read Attributes Structured */
readStructured: {
name: "readStructured",
ID: 0x0e,
parse(buffalo) {
const payload = [];
do {
const attrId = buffalo.readUInt16();
const selector = buffalo.readStructuredSelector();
payload.push({ attrId, selector });
} while (buffalo.isMore());
return payload;
},
write(buffalo, payload) {
if (!Array.isArray(payload)) {
throw new zclStatusError_1.ZclStatusError(status_1.Status.MALFORMED_COMMAND);
}
for (const entry of payload) {
buffalo.writeUInt16(entry.attrId);
buffalo.writeStructuredSelector(entry.selector);
}
},
},
/** Write Attributes Structured */
writeStructured: {
name: "writeStructured",
ID: 0x0f,
response: 0x10, // writeStructuredRsp
parse(buffalo) {
const payload = [];
do {
const attrId = buffalo.readUInt16();
const selector = buffalo.readStructuredSelector();
const dataType = buffalo.readUInt8();
const elementData = buffalo.read(dataType, {});
payload.push({ attrId, selector, dataType, elementData });
} while (buffalo.isMore());
return payload;
},
write(buffalo, payload) {
if (!Array.isArray(payload)) {
throw new zclStatusError_1.ZclStatusError(status_1.Status.MALFORMED_COMMAND);
}
for (const entry of payload) {
buffalo.writeUInt16(entry.attrId);
buffalo.writeStructuredSelector(entry.selector);
buffalo.writeUInt8(entry.dataType);
buffalo.write(entry.dataType, entry.elementData, {});
}
},
},
/** Write Attributes Structured response */
writeStructuredRsp: {
name: "writeStructuredRsp",
ID: 0x10,
/**
* Note that write attribute status records are not included for successfully written attributes, to save bandwidth.
* In the case of successful writing of all attributes, only a single write attribute status record SHALL be included in the command,
* with the status field set to SUCCESS and the attribute identifier and selector fields omitted.
*/
parse(buffalo) {
const firstStatus = buffalo.readUInt8();
if (firstStatus === status_1.Status.SUCCESS) {
return [{ status: firstStatus }];
}
const payload = [];
const attrId = buffalo.readUInt16();
const selector = buffalo.readStructuredSelector();
payload.push({ status: firstStatus, attrId, selector });
while (buffalo.isMore()) {
const status = buffalo.readUInt8();
const attrId = buffalo.readUInt16();
const selector = buffalo.readStructuredSelector();
payload.push({ status, attrId, selector });
}
return payload;
},
write(buffalo, payload) {
if (!Array.isArray(payload)) {
throw new zclStatusError_1.ZclStatusError(status_1.Status.MALFORMED_COMMAND);
}
const nonSuccessPayload = payload.filter((entry) => entry.status !== status_1.Status.SUCCESS);
if (nonSuccessPayload.length === 0) {
buffalo.writeUInt8(status_1.Status.SUCCESS);
}
else {
for (const entry of nonSuccessPayload) {
buffalo.writeUInt8(entry.status);
buffalo.writeUInt16(entry.attrId);
buffalo.writeStructuredSelector(entry.selector);
}
}
},
},
/** Discover Commands Received */
discoverCommands: {
name: "discoverCommands",
ID: 0x11,
parse(buffalo) {
const startCmdId = buffalo.readUInt8();
const maxCmdIds = buffalo.readUInt8();
return { startCmdId, maxCmdIds };
},
write(buffalo, payload) {
if (Array.isArray(payload)) {
throw new zclStatusError_1.ZclStatusError(status_1.Status.MALFORMED_COMMAND);
}
buffalo.writeUInt8(payload.startCmdId);
buffalo.writeUInt8(payload.maxCmdIds);
},
},
/** Discover Commands Received Response */
discoverCommandsRsp: {
name: "discoverCommandsRsp",
ID: 0x12,
parse(buffalo) {
const discComplete = buffalo.readUInt8();
const commandIds = [];
const payload = { discComplete, commandIds };
do {
const commandId = buffalo.readUInt8();
commandIds.push(commandId);
} while (buffalo.isMore());
return payload;
},
write(buffalo, payload) {
if (Array.isArray(payload)) {
throw new zclStatusError_1.ZclStatusError(status_1.Status.MALFORMED_COMMAND);
}
buffalo.writeUInt8(payload.discComplete);
for (const commandId of payload.commandIds) {
buffalo.writeUInt8(commandId);
}
},
},
/** Discover Commands Generated */
discoverCommandsGen: {
name: "discoverCommandsGen",
ID: 0x13,
parse(buffalo) {
const startCmdId = buffalo.readUInt8();
const maxCmdIds = buffalo.readUInt8();
return { startCmdId, maxCmdIds };
},
write(buffalo, payload) {
if (Array.isArray(payload)) {
throw new zclStatusError_1.ZclStatusError(status_1.Status.MALFORMED_COMMAND);
}
buffalo.writeUInt8(payload.startCmdId);
buffalo.writeUInt8(payload.maxCmdIds);
},
},
/** Discover Commands Generated Response */
discoverCommandsGenRsp: {
name: "discoverCommandsGenRsp",
ID: 0x14,
parse(buffalo) {
const discComplete = buffalo.readUInt8();
const commandIds = [];
const payload = { discComplete, commandIds };
do {
const commandId = buffalo.readUInt8();
commandIds.push(commandId);
} while (buffalo.isMore());
return payload;
},
write(buffalo, payload) {
if (Array.isArray(payload)) {
throw new zclStatusError_1.ZclStatusError(status_1.Status.MALFORMED_COMMAND);
}
buffalo.writeUInt8(payload.discComplete);
for (const commandId of payload.commandIds) {
buffalo.writeUInt8(commandId);
}
},
},
/** Discover Attributes Extended */
discoverExt: {
name: "discoverExt",
ID: 0x15,
parse(buffalo) {
const startAttrId = buffalo.readUInt16();
const maxAttrIds = buffalo.readUInt8();
return { startAttrId, maxAttrIds };
},
write(buffalo, payload) {
if (Array.isArray(payload)) {
throw new zclStatusError_1.ZclStatusError(status_1.Status.MALFORMED_COMMAND);
}
buffalo.writeUInt16(payload.startAttrId);
buffalo.writeUInt8(payload.maxAttrIds);
},
},
/** Discover Attributes Extended Response */
discoverExtRsp: {
name: "discoverExtRsp",
ID: 0x16,
parse(buffalo) {
const discComplete = buffalo.readUInt8();
const attrInfos = [];
const payload = { discComplete, attrInfos };
do {
const attrId = buffalo.readUInt16();
const dataType = buffalo.readUInt8();
const access = buffalo.readUInt8();
attrInfos.push({ attrId, dataType, access });
} while (buffalo.isMore());
return payload;
},
write(buffalo, payload) {
if (Array.isArray(payload)) {
throw new zclStatusError_1.ZclStatusError(status_1.Status.MALFORMED_COMMAND);
}
buffalo.writeUInt8(payload.discComplete);
for (const entry of payload.attrInfos) {
buffalo.writeUInt16(entry.attrId);
buffalo.writeUInt8(entry.dataType);
buffalo.writeUInt8(entry.access);
}
},
},
};
//# sourceMappingURL=foundation.js.map