zigbee-herdsman-converters
Version:
Collection of device converters to be used with zigbee-herdsman
523 lines • 22.9 kB
JavaScript
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.definitions = void 0;
const fz = __importStar(require("../converters/fromZigbee"));
const tz = __importStar(require("../converters/toZigbee"));
const exposes = __importStar(require("../lib/exposes"));
const m = __importStar(require("../lib/modernExtend"));
const utils = __importStar(require("../lib/utils"));
const e = exposes.presets;
const ea = exposes.access;
const buttonModesList = {
single_click: 0x01,
multi_click: 0x02,
};
const inputLinkList = {
no: 0x00,
yes: 0x01,
};
const bindCommandList = {
"on/off": 0x00,
toggle: 0x01,
change_level_up: 0x02,
change_level_down: 0x03,
change_level_up_with_off: 0x04,
change_level_down_with_off: 0x05,
recall_scene_0: 0x06,
recall_scene_1: 0x07,
recall_scene_2: 0x08,
recall_scene_3: 0x09,
recall_scene_4: 0x0a,
recall_scene_5: 0x0b,
};
const switchTypesList = {
switch: 0x00,
single_click: 0x01,
multi_click: 0x02,
reset_to_defaults: 0xff,
};
const switchActionsList = {
on: 0x00,
off: 0x01,
toggle: 0x02,
};
function getSortedList(source) {
const keysSorted = [];
for (const key in source) {
if (key != null) {
keysSorted.push([key, source[key]]);
}
}
keysSorted.sort((a, b) => {
return a[1] - b[1];
});
const result = [];
// biome-ignore lint/complexity/noForEach: ignored using `--suppress`
keysSorted.forEach((item) => {
result.push(item[0]);
});
return result;
}
function zigDcInputConfigExposes(epName, desc) {
const features = [];
features.push(e.enum("switch_type", exposes.access.ALL, getSortedList(switchTypesList)).withEndpoint(epName).withDescription(desc));
features.push(e.enum("switch_actions", exposes.access.ALL, getSortedList(switchActionsList)).withEndpoint(epName));
features.push(e.enum("bind_command", exposes.access.ALL, getSortedList(bindCommandList)).withEndpoint(epName));
return features;
}
const tzLocal = {
zigusb_button_config: {
key: ["button_mode", "link_to_output", "bind_command"],
convertGet: async (entity, key, meta) => {
await entity.read("genOnOffSwitchCfg", ["buttonMode", 0x4001, 0x4002]);
},
convertSet: async (entity, key, value, meta) => {
// biome-ignore lint/suspicious/noImplicitAnyLet: ignored using `--suppress`
let payload;
// biome-ignore lint/suspicious/noImplicitAnyLet: ignored using `--suppress`
let data;
switch (key) {
case "button_mode":
data = utils.getFromLookup(value, buttonModesList);
payload = { buttonMode: data };
break;
case "link_to_output":
data = utils.getFromLookup(value, inputLinkList);
payload = { 16385: { value: data, type: 32 /* uint8 */ } };
break;
case "bind_command":
data = utils.getFromLookup(value, bindCommandList);
payload = { 16386: { value: data, type: 32 /* uint8 */ } };
break;
}
await entity.write("genOnOffSwitchCfg", payload);
},
},
zigusb_on_off_invert: {
key: ["state", "on_time", "off_wait_time"],
convertSet: async (entity, key, value, meta) => {
const state = utils.isString(meta.message.state) ? meta.message.state.toLowerCase() : null;
utils.validateValue(state, ["toggle", "off", "on"]);
if (state === "on" && (meta.message.on_time != null || meta.message.off_wait_time != null)) {
const onTime = meta.message.on_time != null ? meta.message.on_time : 0;
const offWaitTime = meta.message.off_wait_time != null ? meta.message.off_wait_time : 0;
if (typeof onTime !== "number") {
throw Error("The on_time value must be a number!");
}
if (typeof offWaitTime !== "number") {
throw Error("The off_wait_time value must be a number!");
}
const payload = { ctrlbits: 0, ontime: Math.round(onTime * 10), offwaittime: Math.round(offWaitTime * 10) };
await entity.command("genOnOff", "onWithTimedOff", payload, utils.getOptions(meta.mapped, entity));
}
else {
if (state === "toggle") {
await entity.command("genOnOff", state, {}, utils.getOptions(meta.mapped, entity));
const currentState = meta.state[`state${meta.endpoint_name ? `_${meta.endpoint_name}` : ""}`];
return currentState ? { state: { state: currentState === "OFF" ? "OFF" : "ON" } } : {};
}
await entity.command("genOnOff", state === "off" ? "on" : "off", {}, utils.getOptions(meta.mapped, entity));
return { state: { state: state === "off" ? "OFF" : "ON" } };
}
},
convertGet: async (entity, key, meta) => {
await entity.read("genOnOff", ["onOff"]);
},
},
zigusb_restart_interval: {
key: ["restart", "interval"],
convertSet: async (entity, key, value, meta) => {
utils.assertNumber(value, key);
utils.assertEndpoint(entity);
if (key === "restart") {
await entity.command("genOnOff", "onWithTimedOff", { ctrlbits: 0, ontime: Math.round(value * 10), offwaittime: 0 });
return { state: { [key]: value } };
}
if (key === "interval") {
await entity.configureReporting("genOnOff", [
{
attribute: "onOff",
minimumReportInterval: value,
maximumReportInterval: value,
reportableChange: 0,
},
]);
return { state: { [key]: value } };
}
},
},
// biome-ignore lint/style/useNamingConvention: ignored using `--suppress`
ZigDC_interval: {
key: ["interval"],
convertSet: async (entity, key, value, meta) => {
const epId = 2;
const endpoint = meta.device.getEndpoint(epId);
const value2 = Number.parseInt(value.toString());
if (!Number.isNaN(value2) && value2 > 0) {
await endpoint.configureReporting("genOnOff", [
{
attribute: "onOff",
minimumReportInterval: value2,
maximumReportInterval: value2,
reportableChange: 0,
},
]);
}
return;
},
},
// biome-ignore lint/style/useNamingConvention: ignored using `--suppress`
ZigDC_input_config: {
key: ["switch_type", "switch_actions", "bind_command"],
convertGet: async (entity, key, meta) => {
await entity.read("genOnOffSwitchCfg", ["switchType", "switchActions", 0x4001, 0x4002]);
},
convertSet: async (entity, key, value, meta) => {
// biome-ignore lint/suspicious/noImplicitAnyLet: ignored using `--suppress`
let payload;
// biome-ignore lint/suspicious/noImplicitAnyLet: ignored using `--suppress`
let data;
switch (key) {
case "switch_type":
data = utils.getFromLookup(value, switchTypesList);
payload = { switchType: data };
break;
case "switch_actions":
data = utils.getFromLookup(value, switchActionsList);
payload = { switchActions: data };
break;
case "bind_command":
data = utils.getFromLookup(value, bindCommandList);
payload = { 16386: { value: data, type: 32 /* uint8 */ } };
break;
}
await entity.write("genOnOffSwitchCfg", payload);
},
},
};
const fzLocal = {
zigusb_button_config: {
cluster: "genOnOffSwitchCfg",
type: ["readResponse", "attributeReport"],
convert: (model, msg, publish, options, meta) => {
const channel = utils.getKey(model.endpoint(msg.device), msg.endpoint.ID);
const { buttonMode } = msg.data;
const inputLink = msg.data[0x4001];
const bindCommand = msg.data[0x4002];
return {
[`button_mode_${channel}`]: utils.getKey(buttonModesList, buttonMode),
[`link_to_output_${channel}`]: utils.getKey(inputLinkList, inputLink),
[`bind_command_${channel}`]: utils.getKey(bindCommandList, bindCommand),
};
},
},
zigusb_analog_input: {
cluster: "genAnalogInput",
type: ["attributeReport", "readResponse"],
convert: (model, msg, publish, options, meta) => {
const payload = {};
const channel = msg.endpoint.ID;
const name = `l${channel}`;
payload[name] = utils.precisionRound(msg.data.presentValue, 3);
if (channel === 5) {
payload[`uptime_${name}`] = utils.precisionRound(msg.data.presentValue, 3);
}
else if (msg.data.description !== undefined) {
const data1 = msg.data.description;
if (data1) {
const data2 = data1.split(",");
const devid = data2[1];
const unit = data2[0];
if (devid) {
payload[`device_${name}`] = devid;
}
const valRaw = msg.data.presentValue;
if (unit) {
let val = utils.precisionRound(valRaw, 1);
const nameLookup = {
C: "temperature",
V: "voltage",
A: "current",
W: "power",
};
let nameAlt = "";
if (unit === "A") {
if (valRaw < 1) {
val = utils.precisionRound(valRaw, 3);
}
else {
val = utils.precisionRound(valRaw, 2);
}
}
nameAlt = nameLookup[unit];
if (nameAlt === undefined) {
const valueIndex = Number.parseInt(unit, 10);
if (!Number.isNaN(valueIndex)) {
nameAlt = `val${unit}`;
}
}
if (nameAlt !== undefined) {
payload[`${nameAlt}_${name}`] = val;
}
}
}
}
return payload;
},
},
zigusb_on_off_invert: {
cluster: "genOnOff",
type: ["attributeReport", "readResponse"],
convert: (model, msg, publish, options, meta) => {
if (msg.data.onOff !== undefined) {
const payload = {};
const endpointName = model.endpoint !== undefined ? utils.getKey(model.endpoint(meta.device), msg.endpoint.ID) : msg.endpoint.ID;
const state = msg.data.onOff === 1 ? "OFF" : "ON";
payload[`state_${endpointName}`] = state;
return payload;
}
},
},
// biome-ignore lint/style/useNamingConvention: ignored using `--suppress`
ZigDC_ina3221: {
cluster: "genAnalogInput",
type: ["attributeReport", "readResponse"],
convert: (model, msg, publish, options, meta) => {
const payload = {};
const endpoint = msg.endpoint.ID;
if (endpoint === 3 || endpoint === 5) {
const parts = msg.data.description.split(",");
const numbers = parts[1].split("-");
const param = parts[0];
const addr = Number.parseInt(numbers[0], 10);
const ch = Number.parseInt(numbers[1], 10);
const isCurrent = param === "A";
const name = isCurrent ? "current" : "voltage";
const alt = isCurrent ? "voltage" : "current";
const baseCh = addr === 41 ? 1 : 4;
const suffix = `_ch${baseCh + ch - 1}`;
const otherKey = alt + suffix;
const otherValue = meta.state[otherKey];
const value = msg.data.presentValue * (isCurrent ? 30 : 1);
const power = value * otherValue;
payload[`power${suffix}`] = power;
payload[`${name}${suffix}`] = value;
}
return payload;
},
},
// biome-ignore lint/style/useNamingConvention: ignored using `--suppress`
ZigDC_uptime: {
cluster: "genAnalogInput",
type: ["attributeReport", "readResponse"],
convert: (model, msg, publish, options, meta) => {
const payload = {};
const channel = msg.endpoint.ID;
if (channel === 1) {
payload.uptime = msg.data.presentValue;
}
return payload;
},
},
// biome-ignore lint/style/useNamingConvention: ignored using `--suppress`
ZigDC_input_config: {
cluster: "genOnOffSwitchCfg",
type: ["readResponse", "attributeReport"],
convert: (model, msg, publish, options, meta) => {
const channel = utils.getKey(model.endpoint(msg.device), msg.endpoint.ID);
const { switchActions, switchType } = msg.data;
const bindCommand = msg.data[0x4002];
return {
[`switch_type_${channel}`]: utils.getKey(switchTypesList, switchType),
[`switch_actions_${channel}`]: utils.getKey(switchActionsList, switchActions),
[`bind_command_${channel}`]: utils.getKey(bindCommandList, bindCommand),
};
},
},
};
function zigusbBtnConfigExposes(epName) {
const features = [];
features.push(e.enum("button_mode", exposes.access.ALL, getSortedList(buttonModesList)).withEndpoint(epName));
features.push(e.enum("link_to_output", exposes.access.ALL, getSortedList(inputLinkList)).withEndpoint(epName));
features.push(e.enum("bind_command", exposes.access.ALL, getSortedList(bindCommandList)).withEndpoint(epName));
return features;
}
exports.definitions = [
{
zigbeeModel: ["ZigUSB"],
model: "ZigUSB",
vendor: "xyzroe",
description: "Zigbee USB power monitor and switch",
fromZigbee: [
fz.ignore_basic_report,
fzLocal.zigusb_on_off_invert,
fzLocal.zigusb_analog_input,
fz.temperature,
fz.ptvo_multistate_action,
fzLocal.zigusb_button_config,
],
toZigbee: [tzLocal.zigusb_restart_interval, tzLocal.zigusb_on_off_invert, tz.ptvo_switch_analog_input, tzLocal.zigusb_button_config],
exposes: [
e.switch().withEndpoint("l1"),
e
.numeric("restart", ea.SET)
.withEndpoint("l1")
.withValueMin(1)
.withValueMax(30)
.withValueStep(1)
.withDescription("OFF time")
.withUnit("seconds"),
...zigusbBtnConfigExposes("l1"),
e.action(["single", "double", "triple"]).withDescription("Single click works only with NO link to output"),
e.current().withAccess(ea.STATE).withEndpoint("l2"),
e.voltage().withAccess(ea.STATE).withEndpoint("l2"),
e.power().withAccess(ea.STATE).withEndpoint("l2"),
e
.numeric("interval", ea.SET)
.withEndpoint("l2")
.withValueMin(1)
.withValueMax(3600)
.withValueStep(1)
.withDescription("Reporting interval")
.withUnit("sec"),
e.cpu_temperature().withProperty("temperature").withEndpoint("l4"),
e.numeric("uptime", ea.STATE).withEndpoint("l5").withDescription("CC2530").withUnit("seconds"),
],
meta: { multiEndpoint: true },
endpoint: (device) => {
return { l1: 1, l2: 2, l4: 4, l5: 5 };
},
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(1);
await endpoint.read("genBasic", ["modelId", "swBuildId", "powerSource"]);
},
},
{
zigbeeModel: ["ZigDC"],
model: "ZigDC",
vendor: "xyzroe",
description: "ZigDC",
fromZigbee: [
fz.ignore_basic_report,
fz.temperature,
fz.humidity,
fz.ptvo_multistate_action,
fzLocal.ZigDC_ina3221,
fzLocal.ZigDC_uptime,
fzLocal.ZigDC_input_config,
],
toZigbee: [tzLocal.ZigDC_interval, tzLocal.ZigDC_input_config],
exposes: [
e.current().withAccess(ea.STATE).withEndpoint("ch1"),
e.voltage().withAccess(ea.STATE).withEndpoint("ch1"),
e.power().withAccess(ea.STATE).withEndpoint("ch1"),
e.current().withAccess(ea.STATE).withEndpoint("ch2"),
e.voltage().withAccess(ea.STATE).withEndpoint("ch2"),
e.power().withAccess(ea.STATE).withEndpoint("ch2"),
e.current().withAccess(ea.STATE).withEndpoint("ch3"),
e.voltage().withAccess(ea.STATE).withEndpoint("ch3"),
e.power().withAccess(ea.STATE).withEndpoint("ch3"),
e.current().withAccess(ea.STATE).withEndpoint("ch4"),
e.voltage().withAccess(ea.STATE).withEndpoint("ch4"),
e.power().withAccess(ea.STATE).withEndpoint("ch4"),
e.current().withAccess(ea.STATE).withEndpoint("ch5"),
e.voltage().withAccess(ea.STATE).withEndpoint("ch5"),
e.power().withAccess(ea.STATE).withEndpoint("ch5"),
e.current().withAccess(ea.STATE).withEndpoint("ch6"),
e.voltage().withAccess(ea.STATE).withEndpoint("ch6"),
e.power().withAccess(ea.STATE).withEndpoint("ch6"),
e.temperature().withEndpoint("l6"),
e.humidity().withEndpoint("l6"),
e.action(["single", "double", "triple", "hold", "release"]),
e.cpu_temperature().withProperty("temperature").withEndpoint("l2"),
...zigDcInputConfigExposes("l7", "IN1"),
...zigDcInputConfigExposes("l8", "IN2"),
...zigDcInputConfigExposes("l1", "BTN"),
e.numeric("uptime", ea.STATE).withDescription("Uptime").withUnit("sec"),
e.numeric("interval", ea.SET).withValueMin(5).withValueMax(600).withValueStep(1).withDescription("Reporting interval").withUnit("sec"),
],
meta: { multiEndpoint: true },
endpoint: (device) => {
return { l1: 1, l2: 2, l3: 3, l5: 5, l6: 6, l7: 7, l8: 8 };
},
configure: async (device, coordinatorEndpoint, logger) => {
const endpoint1 = device.getEndpoint(1);
await endpoint1.read("genBasic", ["modelId", "swBuildId", "powerSource"]);
const endpoint2 = device.getEndpoint(2);
await endpoint2.configureReporting("genOnOff", [
{ attribute: "onOff", minimumReportInterval: 20, maximumReportInterval: 120, reportableChange: 0.1 },
]);
},
},
{
zigbeeModel: ["ZigUSB_C6"],
model: "ZigUSB_C6",
vendor: "xyzroe",
description: "Zigbee USB switch with monitoring",
ota: true,
toZigbee: [tzLocal.zigusb_restart_interval],
exposes: [
e
.numeric("restart", ea.SET)
.withEndpoint("4")
.withValueMin(1)
.withValueMax(30)
.withValueStep(1)
.withDescription("Restart USB device - OFF time")
.withUnit("seconds"),
],
extend: [
m.deviceEndpoints({ endpoints: { 1: 1, 2: 2, 3: 3, 4: 4 } }),
m.identify(),
m.electricityMeter({
cluster: "electrical",
electricalMeasurementType: "both",
// Since this device measures lower voltage devices, lower the change value.
current: { change: 100 },
power: { change: 100 },
voltage: { change: 100 },
endpointNames: ["1"],
}),
m.temperature(),
m.onOff({ endpointNames: ["1"], description: "Controls the USB port" }),
m.onOff({ powerOnBehavior: false, endpointNames: ["2"], description: "LED indicates the Zigbee status" }),
m.onOff({ powerOnBehavior: false, endpointNames: ["3"], description: "LED indicates the USB state" }),
m.iasZoneAlarm({ zoneType: "generic", zoneAttributes: ["alarm_1"], description: "Over current alarm" }),
],
meta: { multiEndpoint: true },
},
];
//# sourceMappingURL=xyzroe.js.map
;