UNPKG

zigbee-herdsman-converters

Version:

Collection of device converters to be used with zigbee-herdsman

523 lines • 22.9 kB
"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.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