UNPKG

zigbee-herdsman-converters

Version:

Collection of device converters to be used with zigbee-herdsman

462 lines • 21.1 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 zigbee_herdsman_1 = require("zigbee-herdsman"); 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 reporting = __importStar(require("../lib/reporting")); const utils = __importStar(require("../lib/utils")); const e = exposes.presets; const ea = exposes.access; const switchTypeValues = ["maintained_state", "maintained_toggle", "momentary_state", "momentary_press", "momentary_release"]; const defaultOnOffStateValues = ["on", "off", "previous"]; const manufacturerOptions = { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.CUSTOM_PERENIO }; const perenioExtend = { addCustomClusterPerenio: () => m.deviceAddCustomCluster("perenioSpecific", { ID: 64635, manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.CUSTOM_PERENIO, attributes: {}, commands: {}, commandsResponse: {}, }), }; const fzPerenio = { diagnostic: { cluster: "haDiagnostic", type: ["attributeReport", "readResponse"], convert: (model, msg, publish, options, meta) => { const result = {}; if (msg.data.lastMessageLqi !== undefined) { result.last_message_lqi = msg.data.lastMessageLqi; } if (msg.data.lastMessageRssi !== undefined) { result.last_message_rssi = msg.data.lastMessageRssi; } return result; }, }, switch_type: { cluster: "genMultistateValue", type: ["attributeReport", "readResponse"], convert: (model, msg, publish, options, meta) => { const result = {}; const switchTypeLookup = { 1: "momentary_state", 16: "maintained_state", 204: "maintained_toggle", 205: "momentary_release", 220: "momentary_press", }; if (msg.data.presentValue !== undefined) { const property = utils.postfixWithEndpointName("switch_type", msg, model, meta); result[property] = switchTypeLookup[msg.data.presentValue]; } return result; }, }, smart_plug: { cluster: "perenioSpecific", type: ["attributeReport", "readResponse"], convert: (model, msg, publish, options, meta) => { const result = {}; if (msg.data[2] !== undefined) { result.rms_current = msg.data[2]; } if (msg.data[3] !== undefined) { result.rms_voltage = msg.data[3]; } if (msg.data[4] !== undefined) { result.voltage_min = msg.data[4]; } if (msg.data[5] !== undefined) { result.voltage_max = msg.data[5]; } if (msg.data[10] !== undefined) { result.active_power = msg.data[10]; } if (msg.data[11] !== undefined) { result.power_max = msg.data[11]; } if (msg.data[14] !== undefined) { result.consumed_energy = msg.data[14]; } if (msg.data[15] !== undefined) { result.consumed_energy_limit = msg.data[15]; } if (msg.data[24] !== undefined) { result.rssi = msg.data[24]; } const powerOnStateLookup = { 0: "off", 1: "on", 2: "previous", }; if (msg.data[0] !== undefined) { // @ts-expect-error ignore result.default_on_off_state = powerOnStateLookup[msg.data[0]]; } if (msg.data[1] !== undefined) { if (msg.data[1] === 0) { result.alarm_voltage_min = false; result.alarm_voltage_max = false; result.alarm_power_max = false; result.alarm_consumed_energy = false; } else { if (msg.data[1] & 1) { result.alarm_voltage_min = true; } if (msg.data[1] & 2) { result.alarm_voltage_max = true; } if (msg.data[1] & 4) { result.alarm_power_max = true; } if (msg.data[1] & 8) { result.alarm_consumed_energy = true; } } } return result; }, }, }; const tzPerenio = { switch_type: { key: ["switch_type"], convertSet: async (entity, key, value, meta) => { utils.assertString(value, key); const switchTypeLookup = { momentary_state: 0x0001, maintained_state: 0x0010, maintained_toggle: 0x00cc, momentary_release: 0x00cd, momentary_press: 0x00dc, }; await entity.write("genMultistateValue", { presentValue: switchTypeLookup[value] }, utils.getOptions(meta.mapped, entity)); return { state: { switch_type: value } }; }, convertGet: async (entity, key, meta) => { await entity.read("genMultistateValue", ["presentValue"]); }, }, default_state: { key: ["default_on_off_state"], convertSet: async (entity, key, val, meta) => { utils.assertString(val, key); const powerOnStateLookup = { off: 0, on: 1, previous: 2, }; await entity.write("perenioSpecific", { 0: { value: powerOnStateLookup[val], type: 0x20 } }, manufacturerOptions); return { state: { default_on_off_state: val } }; }, convertGet: async (entity, key, meta) => { await entity.read("perenioSpecific", [0]); }, }, alarms_reset: { key: ["alarm_voltage_min", "alarm_voltage_max", "alarm_power_max", "alarm_consumed_energy"], convertSet: async (entity, key, val, meta) => { await entity.write("perenioSpecific", { 1: { value: 0, type: 0x20 } }, manufacturerOptions); return { state: { alarm_voltage_min: false, alarm_voltage_max: false, alarm_power_max: false, alarm_consumed_energy: false } }; }, convertGet: async (entity, key, meta) => { await entity.read("perenioSpecific", [1]); }, }, alarms_limits: { key: ["voltage_min", "voltage_max", "power_max", "consumed_energy_limit"], convertSet: async (entity, key, val, meta) => { switch (key) { case "voltage_min": await entity.write("perenioSpecific", { 4: { value: val, type: 0x21 } }, manufacturerOptions); break; case "voltage_max": await entity.write("perenioSpecific", { 5: { value: val, type: 0x21 } }, manufacturerOptions); break; case "power_max": await entity.write("perenioSpecific", { 11: { value: val, type: 0x21 } }, manufacturerOptions); break; case "consumed_energy_limit": await entity.write("perenioSpecific", { 15: { value: val, type: 0x21 } }, manufacturerOptions); break; } return { state: { [key]: val } }; }, convertGet: async (entity, key, meta) => { switch (key) { case "voltage_min": await entity.read("perenioSpecific", [4]); break; case "voltage_max": await entity.read("perenioSpecific", [5]); break; case "power_max": await entity.read("perenioSpecific", [11]); break; case "consumed_energy_limit": await entity.read("perenioSpecific", [15]); break; } }, }, on_off_mod: { key: ["state", "on_time", "off_wait_time"], convertSet: async (entity, key, value, meta) => { // @ts-expect-error ignore const state = meta.message.state != null ? meta.message.state.toLowerCase() : null; utils.validateValue(state, ["toggle", "off", "on"]); const alarmVoltageMin = meta.state[`alarm_voltage_min${meta.endpoint_name ? `_${meta.endpoint_name}` : ""}`]; const alarmVoltageMax = meta.state[`alarm_voltage_max${meta.endpoint_name ? `_${meta.endpoint_name}` : ""}`]; const alarmPowerMax = meta.state[`alarm_power_max${meta.endpoint_name ? `_${meta.endpoint_name}` : ""}`]; if (alarmVoltageMin || alarmVoltageMax || alarmPowerMax) { return { state: { state: "OFF" } }; } 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 { await entity.command("genOnOff", state, {}, utils.getOptions(meta.mapped, entity)); if (state === "toggle") { const currentState = meta.state[`state${meta.endpoint_name ? `_${meta.endpoint_name}` : ""}`]; return currentState ? { state: { state: currentState === "OFF" ? "ON" : "OFF" } } : {}; } return { state: { state: state.toUpperCase() } }; } }, convertGet: async (entity, key, meta) => { await entity.read("genOnOff", ["onOff"]); }, }, }; exports.definitions = [ { zigbeeModel: ["PECLS01"], model: "PECLS01", vendor: "Perenio", description: "Flood alarm device", fromZigbee: [fz.ias_water_leak_alarm_1, fz.ignore_basic_report, fz.battery], toZigbee: [], configure: async (device, coordinatorEndpoint) => { const endpoint = device.getEndpoint(1); await reporting.bind(endpoint, coordinatorEndpoint, ["genPowerCfg"]); await reporting.batteryPercentageRemaining(endpoint); }, exposes: [e.water_leak(), e.battery_low(), e.tamper(), e.battery()], ota: true, }, { zigbeeModel: ["ZHA-DoorLockSensor"], model: "PECWS01", vendor: "Perenio", description: "Door sensor", fromZigbee: [fz.ias_contact_alarm_1, fz.battery, fz.ignore_basic_report, fz.ias_contact_alarm_1_report], toZigbee: [], exposes: [e.contact(), e.battery(), e.battery_voltage()], configure: async (device, coordinatorEndpoint) => { const endpoint = device.getEndpoint(1); await reporting.bind(endpoint, coordinatorEndpoint, ["genPowerCfg"]); await reporting.batteryPercentageRemaining(endpoint); await reporting.batteryVoltage(endpoint); }, }, { fingerprint: [{ modelID: "ZHA-PirSensor", manufacturerName: "LDS" }], model: "PECMS01", vendor: "Perenio", description: "Motion sensor", fromZigbee: [fz.battery, fz.ias_occupancy_alarm_1], toZigbee: [], exposes: [e.occupancy(), e.battery_low(), e.tamper(), e.battery()], configure: async (device, coordinatorEndpoint) => { const endpoint = device.getEndpoint(1); await reporting.bind(endpoint, coordinatorEndpoint, ["genPowerCfg"]); await reporting.batteryPercentageRemaining(endpoint); }, ota: true, }, { zigbeeModel: ["PEHWE20", "PEHWE2X"], model: "PEHWE20", vendor: "Perenio", description: "Two channel single wire mini-relay", fromZigbee: [fz.on_off, fz.power_on_behavior, fzPerenio.diagnostic, fzPerenio.switch_type], toZigbee: [tz.on_off, tz.power_on_behavior, tzPerenio.switch_type], endpoint: (device) => { return { l1: 1, l2: 2 }; }, meta: { multiEndpoint: true }, configure: async (device, coordinatorEndpoint) => { const endpoint1 = device.getEndpoint(1); const endpoint2 = device.getEndpoint(2); const endpoint10 = device.getEndpoint(10); await reporting.bind(endpoint1, coordinatorEndpoint, ["genOnOff"]); await reporting.bind(endpoint2, coordinatorEndpoint, ["genOnOff"]); await reporting.bind(endpoint10, coordinatorEndpoint, ["haDiagnostic"]); const payload = [ { attribute: "onOff", minimumReportInterval: 0, maximumReportInterval: 3600, reportableChange: 0, }, ]; const payloadDiagnostic = [ { attribute: "lastMessageLqi", minimumReportInterval: 5, maximumReportInterval: 60, reportableChange: 0, }, { attribute: "lastMessageRssi", minimumReportInterval: 5, maximumReportInterval: 60, reportableChange: 0, }, ]; await endpoint1.configureReporting("genOnOff", payload); await endpoint2.configureReporting("genOnOff", payload); await endpoint10.configureReporting("haDiagnostic", payloadDiagnostic); await endpoint1.read("genOnOff", ["onOff", "startUpOnOff"]); await endpoint2.read("genOnOff", ["onOff", "startUpOnOff"]); await endpoint1.read("genMultistateValue", ["presentValue"]); await endpoint2.read("genMultistateValue", ["presentValue"]); await endpoint10.read("haDiagnostic", ["lastMessageLqi", "lastMessageRssi"]); }, exposes: [ e.switch().withEndpoint("l1"), e.power_on_behavior().withEndpoint("l1"), e.enum("switch_type", ea.ALL, switchTypeValues).withEndpoint("l1"), e.switch().withEndpoint("l2"), e.power_on_behavior().withEndpoint("l2"), e.enum("switch_type", ea.ALL, switchTypeValues).withEndpoint("l2"), e.numeric("last_message_lqi", ea.STATE).withUnit("lqi").withDescription("LQI seen by the device").withValueMin(0).withValueMax(255), e.numeric("last_message_rssi", ea.STATE).withUnit("dB").withDescription("RSSI seen by the device").withValueMin(-128).withValueMax(127), ], }, { zigbeeModel: ["PEHPL0X"], model: "PEHPL0X", vendor: "Perenio", description: "Power link", extend: [perenioExtend.addCustomClusterPerenio()], fromZigbee: [fz.on_off, fzPerenio.smart_plug, fz.metering], toZigbee: [tzPerenio.on_off_mod, tzPerenio.default_state, tzPerenio.alarms_reset, tzPerenio.alarms_limits], configure: async (device, coordinatorEndpoint) => { const endpoint = device.getEndpoint(1); await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff", "perenioSpecific"]); const payload = [ { attribute: "onOff", minimumReportInterval: 1, maximumReportInterval: 3600, reportableChange: 0, }, ]; await endpoint.configureReporting("genOnOff", payload); await endpoint.configureReporting("perenioSpecific", [ { attribute: { ID: 0x000a, type: 0x21 }, minimumReportInterval: 5, maximumReportInterval: 60, reportableChange: 0, }, ]); await endpoint.configureReporting("perenioSpecific", [ { attribute: { ID: 0x000e, type: 0x23 }, minimumReportInterval: 5, maximumReportInterval: 60, reportableChange: 0, }, ]); await endpoint.configureReporting("perenioSpecific", [ { attribute: { ID: 0x0003, type: 0x21 }, minimumReportInterval: 5, maximumReportInterval: 5, reportableChange: 0, }, ]); await endpoint.read("perenioSpecific", [0, 1, 2, 3]); await endpoint.read("perenioSpecific", [4, 5, 11, 15]); }, exposes: [ e.switch(), e.enum("default_on_off_state", ea.ALL, defaultOnOffStateValues), e.numeric("rms_voltage", ea.STATE).withUnit("V").withDescription("RMS voltage"), e.numeric("active_power", ea.STATE).withUnit("W").withDescription("Active power"), e.numeric("consumed_energy", ea.STATE).withUnit("W*h").withDescription("Consumed energy"), e .binary("alarm_voltage_min", ea.ALL, true, false) .withDescription("Indicates if the alarm is triggered on the voltage drop below the limit, allows to reset alarms"), e .binary("alarm_voltage_max", ea.ALL, true, false) .withDescription("Indicates if the alarm is triggered on the voltage rise above the limit, allows to reset alarms"), e .binary("alarm_power_max", ea.ALL, true, false) .withDescription("Indicates if the alarm is triggered on the active power rise above the limit, allows to reset alarms"), e .binary("alarm_consumed_energy", ea.ALL, true, false) .withDescription("Indicates if the alarm is triggered when the consumption energy limit is reached, allows to reset alarms"), e.numeric("voltage_min", ea.ALL).withValueMin(0).withValueMax(253).withDescription("Minimum allowable voltage limit for alarms."), e.numeric("voltage_max", ea.ALL).withValueMin(0).withValueMax(253).withDescription("Maximum allowable voltage limit for alarms."), e.numeric("power_max", ea.ALL).withValueMin(0).withValueMax(65534).withDescription("Maximum allowable power limit for alarms."), e .numeric("consumed_energy_limit", ea.ALL) .withValueMin(0) .withValueMax(65534) .withDescription("Limit of electric energy consumption in kW*h. 0 value represents no limit"), e.numeric("rssi", ea.STATE).withUnit("dB").withDescription("RSSI seen by the device").withValueMin(-128).withValueMax(127), ], ota: true, }, ]; //# sourceMappingURL=perenio.js.map