UNPKG

zigbee-herdsman-converters

Version:

Collection of device converters to be used with zigbee-herdsman

1,190 lines 106 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 constants = __importStar(require("../lib/constants")); const exposes = __importStar(require("../lib/exposes")); const m = __importStar(require("../lib/modernExtend")); const namron = __importStar(require("../lib/namron")); const reporting = __importStar(require("../lib/reporting")); const store = __importStar(require("../lib/store")); const tuya = __importStar(require("../lib/tuya")); const utils = __importStar(require("../lib/utils")); const ea = exposes.access; const e = exposes.presets; const sunricherManufacturer = { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SHENZHEN_SUNRICHER_TECHNOLOGY_LTD }; const fzLocal = { namron_panelheater: { cluster: "hvacThermostat", type: ["attributeReport", "readResponse"], convert: (model, msg, publish, options, meta) => { const result = {}; const data = msg.data; const isPro = model.model === "4512776/4512777"; if (data.operateDisplayBrightness !== undefined) { // OperateDisplayBrightness if (isPro) { result.display_brightness = data.operateDisplayBrightness; } else { result.display_brightnesss = data.operateDisplayBrightness; } } if (data.displayAutoOff !== undefined) { // DisplayAutoOffActivation if (isPro) { result.display_auto_off = data.displayAutoOff === 1; } else { const lookup = { 0: "deactivated", 1: "activated" }; result.display_auto_off = utils.getFromLookup(data.displayAutoOff, lookup); } } if (data.powerUpStatus !== undefined) { // PowerUpStatus (non-PRO only) const lookup = { 0: "manual", 1: "last_state" }; result.power_up_status = utils.getFromLookup(data.powerUpStatus, lookup); } if (data.windowOpenCheck2 !== undefined) { // WindowOpenCheck if (isPro) { // PRO: 0=enable, 1=disable result.window_open_detection = data.windowOpenCheck2 === 0; } else { // Non-PRO: According to real life testing 0: disable, 1: enable result.window_detection = data.windowOpenCheck2 === 1; } } if (data.hysterersis !== undefined) { // Hysteresis const value = utils.precisionRound(data.hysterersis, 2) / 10; if (isPro) { result.hysteresis = value; } else { result.hysterersis = value; } } if (data.windowOpen !== undefined) { // WindowOpen, 0: Window is not opened, 1: Window is opened result.window_open = data.windowOpen === 1; } // PRO-specific attributes if (data.controlMethod !== undefined) { // System control method: 0=PID, 1=Hysteresis result.control_method = data.controlMethod === 0 ? "pid" : "hysteresis"; } if (data.adaptiveFunction !== undefined) { // Adaptive function AS: 0=Enable, 1=Disable result.adaptive_function = data.adaptiveFunction === 0; } if (data.pidKp !== undefined) { result.pid_kp = data.pidKp / 1000.0; } if (data.pidKd !== undefined) { result.pid_kd = data.pidKd / 1000.0; } if (data.pidKi !== undefined) { result.pid_ki = data.pidKi / 1000.0; } return result; }, }, namron_thermostat2: { cluster: "hvacThermostat", type: ["attributeReport", "readResponse"], options: [exposes.options.local_temperature_based_on_sensor()], convert: (model, msg, publish, options, meta) => { const runningModeStateMap = { 0: 0, 3: 2, 4: 5 }; // override mode "idle" - not a supported running mode if (msg.data.runningMode === 0x10) msg.data.runningMode = 0; // map running *mode* to *state*, as that's what used // in homeAssistant climate ui card (red background) if (msg.data.runningMode !== undefined) msg.data.runningState = runningModeStateMap[msg.data.runningMode]; return fz.thermostat.convert(model, msg, publish, options, meta); // as KeyValue; }, }, namronSimplifyRemote: { cluster: "namronPrivateE004", type: ["raw"], convert(model, msg, publish, _options, meta) { const bytes = parseNamronBytes(msg); if (bytes.length === 0) return; const btn = bytes.at(-2); const raw = bytes.at(-1); if (btn == null || raw == null) return; const kind = NAMRON_SIMPLIFY_ACTIONS[raw]; const base = `button_${simplify_col(btn)}_${simplify_sub(btn)}_`; // Firmware sometimes sends empty action after hold: synthesize release if (!kind) { const lastHold = store.getValue(meta.device, HOLD_KEY_SIMPLIFY); if (lastHold?.endsWith("_hold")) { publish({ action: lastHold.replace("_hold", "_release") }); store.putValue(meta.device, HOLD_KEY_SIMPLIFY, null); } return; } if (kind === "hold") { store.putValue(meta.device, HOLD_KEY_SIMPLIFY, `${base}hold`); publish({ action: `${base}hold` }); return; } if (kind === "release") { publish({ action: `${base}press` }); publish({ action: `${base}release` }); return; } publish({ action: `${base}press` }); }, }, }; // Namron Simplify 3-button remote (4512793 / 4512794) // ----------------------------------------------------------- const NAMRON_SIMPLIFY_ACTIONS = { 0: "press", 1: "release", 2: "hold", }; const HOLD_KEY_SIMPLIFY = "namron_simplify_lastHold"; const simplify_col = (n) => Math.floor((n - 1) / 2) + 1; const simplify_sub = (n) => (n % 2 === 1 ? "up" : "down"); // Helper to safely parse bytes from msg without any/unknown function parseNamronBytes(msg) { const m = msg; if (m.type === "raw" && m.data && typeof m.data === "object" && "data" in m.data && Array.isArray(m.data.data)) { return m.data.data; } if (Array.isArray(m.data)) { return m.data; } if (m.data && typeof m.data === "object") { const obj = m.data; const keys = Object.keys(obj) .filter((k) => !Number.isNaN(Number(k))) .sort((a, b) => Number(a) - Number(b)); return keys.map((k) => obj[k]); } return []; } // END SimplifyBryter const tzLocal = { namron_panelheater: { key: ["display_brightnesss", "display_auto_off", "power_up_status", "window_detection", "hysterersis", "window_open"], convertSet: async (entity, key, value, meta) => { if (key === "display_brightnesss") { const payload = { 4096: { value: value, type: zigbee_herdsman_1.Zcl.DataType.ENUM8 } }; await entity.write("hvacThermostat", payload, sunricherManufacturer); } else if (key === "display_auto_off") { const lookup = { deactivated: 0, activated: 1 }; const payload = { 4097: { value: utils.getFromLookup(value, lookup), type: zigbee_herdsman_1.Zcl.DataType.ENUM8 } }; await entity.write("hvacThermostat", payload, sunricherManufacturer); } else if (key === "power_up_status") { const lookup = { manual: 0, last_state: 1 }; const payload = { 4100: { value: utils.getFromLookup(value, lookup), type: zigbee_herdsman_1.Zcl.DataType.ENUM8 } }; await entity.write("hvacThermostat", payload, sunricherManufacturer); } else if (key === "window_detection") { const payload = { 4105: { value: value ? 1 : 0, type: zigbee_herdsman_1.Zcl.DataType.ENUM8 } }; await entity.write("hvacThermostat", payload, sunricherManufacturer); } else if (key === "hysterersis") { const payload = { 4106: { value: utils.toNumber(value, "hysterersis") * 10, type: zigbee_herdsman_1.Zcl.DataType.UINT8 } }; await entity.write("hvacThermostat", payload, sunricherManufacturer); } }, convertGet: async (entity, key, meta) => { switch (key) { case "display_brightnesss": await entity.read("hvacThermostat", ["operateDisplayBrightness"], sunricherManufacturer); break; case "display_auto_off": await entity.read("hvacThermostat", ["displayAutoOff"], sunricherManufacturer); break; case "power_up_status": await entity.read("hvacThermostat", ["powerUpStatus"], sunricherManufacturer); break; case "window_detection": await entity.read("hvacThermostat", ["windowOpenCheck2"], sunricherManufacturer); break; case "hysterersis": await entity.read("hvacThermostat", ["hysterersis"], sunricherManufacturer); break; case "window_open": await entity.read("hvacThermostat", ["windowOpen"], sunricherManufacturer); break; default: // Unknown key throw new Error(`Unhandled key toZigbee.namron_panelheater.convertGet ${key}`); } }, }, namron_panelheater_pro_hysteresis: { key: ["hysteresis"], convertSet: async (entity, key, value, meta) => { let num = utils.toNumber(value, "hysteresis"); if (num < 0.5) num = 0.5; if (num > 5.0) num = 5.0; const raw = Math.round(num * 10); await entity.write("hvacThermostat", { 4106: { value: raw, type: zigbee_herdsman_1.Zcl.DataType.UINT8 } }, sunricherManufacturer); return { state: { hysteresis: num } }; }, convertGet: async (entity, key, meta) => { await entity.read("hvacThermostat", ["hysterersis"], sunricherManufacturer); }, }, namron_panelheater_pro_window_open_detection: { key: ["window_open_detection"], convertSet: async (entity, key, value, meta) => { const enable = value === true || String(value).toUpperCase() === "ON"; // 0=enable, 1=disable const raw = enable ? 0 : 1; await entity.write("hvacThermostat", { 4105: { value: raw, type: zigbee_herdsman_1.Zcl.DataType.ENUM8 } }, sunricherManufacturer); return { state: { window_open_detection: enable } }; }, convertGet: async (entity, key, meta) => { await entity.read("hvacThermostat", ["windowOpenCheck2", "windowOpen"], sunricherManufacturer); }, }, namron_panelheater_pro_display_auto_off: { key: ["display_auto_off"], convertSet: async (entity, key, value, meta) => { const enable = value === true || String(value).toUpperCase() === "ON"; const raw = enable ? 1 : 0; await entity.write("hvacThermostat", { 4097: { value: raw, type: zigbee_herdsman_1.Zcl.DataType.ENUM8 } }, sunricherManufacturer); return { state: { display_auto_off: enable } }; }, convertGet: async (entity, key, meta) => { await entity.read("hvacThermostat", ["displayAutoOff"], sunricherManufacturer); }, }, namron_panelheater_pro_control_method: { key: ["control_method"], convertSet: async (entity, key, value, meta) => { const mode = String(value).toLowerCase(); let raw; if (mode === "pid" || mode === "0") raw = 0; else if (mode === "hysteresis" || mode === "1") raw = 1; else return; await entity.write("hvacThermostat", { 8201: { value: raw, type: zigbee_herdsman_1.Zcl.DataType.ENUM8 } }, sunricherManufacturer); return { state: { control_method: raw === 0 ? "pid" : "hysteresis" } }; }, convertGet: async (entity, key, meta) => { await entity.read("hvacThermostat", ["controlMethod"], sunricherManufacturer); }, }, namron_panelheater_pro_adaptive_function: { key: ["adaptive_function"], convertSet: async (entity, key, value, meta) => { const enable = value === true || String(value).toUpperCase() === "ON"; // 0=Enable, 1=Disable const raw = enable ? 0 : 1; await entity.write("hvacThermostat", { 4108: { value: raw, type: zigbee_herdsman_1.Zcl.DataType.ENUM8 } }, sunricherManufacturer); return { state: { adaptive_function: enable } }; }, convertGet: async (entity, key, meta) => { await entity.read("hvacThermostat", ["adaptiveFunction"], sunricherManufacturer); }, }, namron_panelheater_pro_pid_kp: { key: ["pid_kp"], convertSet: async (entity, key, value, meta) => { let num = utils.toNumber(value, "pid_kp"); num = Math.min(Math.max(num, 0), 1); await entity.write("hvacThermostat", { 8198: { value: Math.round(num * 1000), type: zigbee_herdsman_1.Zcl.DataType.UINT16 } }, sunricherManufacturer); return { state: { pid_kp: num } }; }, convertGet: async (entity, key, meta) => { await entity.read("hvacThermostat", ["pidKp"], sunricherManufacturer); }, }, namron_panelheater_pro_pid_ki: { key: ["pid_ki"], convertSet: async (entity, key, value, meta) => { let num = utils.toNumber(value, "pid_ki"); num = Math.min(Math.max(num, 0), 1); await entity.write("hvacThermostat", { 8200: { value: Math.round(num * 1000), type: zigbee_herdsman_1.Zcl.DataType.UINT16 } }, sunricherManufacturer); return { state: { pid_ki: num } }; }, convertGet: async (entity, key, meta) => { await entity.read("hvacThermostat", ["pidKi"], sunricherManufacturer); }, }, namron_panelheater_pro_pid_kd: { key: ["pid_kd"], convertSet: async (entity, key, value, meta) => { let num = utils.toNumber(value, "pid_kd"); num = Math.min(Math.max(num, 0), 1); await entity.write("hvacThermostat", { 8199: { value: Math.round(num * 1000), type: zigbee_herdsman_1.Zcl.DataType.UINT16 } }, sunricherManufacturer); return { state: { pid_kd: num } }; }, convertGet: async (entity, key, meta) => { await entity.read("hvacThermostat", ["pidKd"], sunricherManufacturer); }, }, namron_panelheater_pro_state: { key: ["state"], convertSet: async (entity, key, value, meta) => { const v = String(value).toUpperCase(); const isOn = v === "ON"; const systemMode = isOn ? 0x04 : 0x00; // 0x04=heat, 0x00=off await entity.write("hvacThermostat", { systemMode }, { disableDefaultResponse: true }); return { state: { state: isOn ? "ON" : "OFF" } }; }, convertGet: async (entity, key, meta) => { await entity.read("hvacThermostat", ["systemMode"]); }, }, namron_panelheater_pro_frost_mode: { key: ["frost_mode"], convertSet: async (entity, key, value, meta) => { const enable = value === true || String(value).toUpperCase() === "ON"; if (enable) { // Save current state before enabling frost mode if (meta.state) { if (meta.state._prev_system_mode === undefined && meta.state.system_mode !== undefined) { meta.state._prev_system_mode = meta.state.system_mode; } if (meta.state._prev_occupied_heating_setpoint === undefined && meta.state.occupied_heating_setpoint !== undefined) { meta.state._prev_occupied_heating_setpoint = meta.state.occupied_heating_setpoint; } } // Set to heat mode with 7°C setpoint (700 = 7.00°C) await entity.write("hvacThermostat", { systemMode: 0x04, occupiedHeatingSetpoint: 700 }, { disableDefaultResponse: true }); } else { // Restore previous state let systemMode = 0x04; // Default to heat let occupiedHeatingSetpoint = 2100; // Default to 21°C if (meta.state) { if (meta.state._prev_system_mode !== undefined) { const sm = meta.state._prev_system_mode; if (typeof sm === "number") { systemMode = sm; } else { const smStr = String(sm); if (smStr === "off") systemMode = 0x00; else if (smStr === "auto") systemMode = 0x01; else if (smStr === "heat") systemMode = 0x04; } } if (meta.state._prev_occupied_heating_setpoint !== undefined) { let sp = meta.state._prev_occupied_heating_setpoint; // Convert to centidegrees if needed if (typeof sp === "number" && sp < 100) { sp = Math.round(sp * 100); } occupiedHeatingSetpoint = sp; } delete meta.state._prev_system_mode; delete meta.state._prev_occupied_heating_setpoint; } await entity.write("hvacThermostat", { systemMode, occupiedHeatingSetpoint }, { disableDefaultResponse: true }); } return { state: { frost_mode: enable } }; }, }, }; exports.definitions = [ { zigbeeModel: ["3308431"], model: "3308431", vendor: "Namron", description: "Luna ceiling light", extend: [m.light({ colorTemp: { range: [153, 370] } })], }, { zigbeeModel: ["3802967"], model: "3802967", vendor: "Namron", description: "Led bulb 6w RGBW", extend: [m.light({ colorTemp: { range: [153, 555] }, color: true })], }, { zigbeeModel: ["4512700"], model: "4512700", vendor: "Namron", description: "Zigbee dimmer 400W", ota: true, extend: [m.light({ configureReporting: true })], }, { zigbeeModel: ["4512739"], model: "4512739", vendor: "Namron", description: "Zigbee dimmer TW 400W", ota: true, extend: [m.light({ configureReporting: true, colorTemp: { range: [160, 450] } }), m.electricityMeter()], }, { zigbeeModel: ["4512760"], model: "4512760", vendor: "Namron", description: "Zigbee dimmer 400W", ota: true, extend: [m.light({ configureReporting: true }), m.electricityMeter({ voltage: false, current: false })], }, { zigbeeModel: ["4512708"], model: "4512708", vendor: "Namron", description: "Zigbee LED dimmer", extend: [m.light({ configureReporting: true })], }, { zigbeeModel: ["4512766"], model: "4512766", vendor: "Namron", description: "Zigbee smart plug 16A", ota: true, extend: [m.onOff(), m.electricityMeter()], }, { zigbeeModel: ["4512767"], model: "4512767", vendor: "Namron", description: "Zigbee smart plug 16A", ota: true, extend: [m.onOff(), m.electricityMeter()], }, { zigbeeModel: ["4512789"], model: "4512789", vendor: "Namron", description: "Zigbee smart plug 16A IP44", extend: [m.deviceTemperature({ scale: 100 }), m.onOff(), m.electricityMeter()], }, { zigbeeModel: ["1402767"], model: "1402767", vendor: "Namron", description: "Zigbee LED dimmer", extend: [m.light({ effect: false, configureReporting: true }), m.forcePowerSource({ powerSource: "Mains (single phase)" })], meta: { disableDefaultResponse: true }, }, { zigbeeModel: ["1402768"], model: "1402768", vendor: "Namron", description: "Zigbee LED dimmer TW 250W", extend: [m.light({ effect: false, configureReporting: true, colorTemp: { range: [250, 65279] } })], }, { zigbeeModel: ["4512733"], model: "4512733", vendor: "Namron", description: "Zigbee dimmer 2-pol 400W", extend: [m.light({ configureReporting: true })], }, { zigbeeModel: ["4512704"], model: "4512704", vendor: "Namron", description: "Zigbee switch 400W", extend: [m.onOff()], ota: true, }, { zigbeeModel: ["1402755"], model: "1402755", vendor: "Namron", description: "Zigbee LED dimmer", extend: [m.light({ configureReporting: true })], }, { zigbeeModel: ["4512703"], model: "4512703", vendor: "Namron", description: "Zigbee 4 channel switch K8 (white)", fromZigbee: [fz.command_on, fz.command_off, fz.battery, fz.command_move, fz.command_stop], exposes: [ e.battery(), e.action([ "on_l1", "off_l1", "brightness_move_up_l1", "brightness_move_down_l1", "brightness_stop_l1", "on_l2", "off_l2", "brightness_move_up_l2", "brightness_move_down_l2", "brightness_stop_l2", "on_l3", "off_l3", "brightness_move_up_l3", "brightness_move_down_l3", "brightness_stop_l3", "on_l4", "off_l4", "brightness_move_up_l4", "brightness_move_down_l4", "brightness_stop_l4", ]), ], toZigbee: [], meta: { multiEndpoint: true }, endpoint: (device) => { return { l1: 1, l2: 2, l3: 3, l4: 4 }; }, ota: true, }, { zigbeeModel: ["4512721"], model: "4512721", vendor: "Namron", description: "Zigbee 4 channel switch K8 (black)", fromZigbee: [fz.command_on, fz.command_off, fz.battery, fz.command_move, fz.command_stop], toZigbee: [], meta: { multiEndpoint: true }, exposes: [ e.battery(), e.action([ "on_l1", "off_l1", "brightness_move_up_l1", "brightness_move_down_l1", "brightness_stop_l1", "on_l2", "off_l2", "brightness_move_up_l2", "brightness_move_down_l2", "brightness_stop_l2", "on_l3", "off_l3", "brightness_move_up_l3", "brightness_move_down_l3", "brightness_stop_l3", "on_l4", "off_l4", "brightness_move_up_l4", "brightness_move_down_l4", "brightness_stop_l4", ]), ], endpoint: (device) => { return { l1: 1, l2: 2, l3: 3, l4: 4 }; }, ota: true, }, { zigbeeModel: ["4512701"], model: "4512701", vendor: "Namron", description: "Zigbee 1 channel switch K2 (White)", fromZigbee: [fz.command_on, fz.command_off, fz.battery, fz.command_move, fz.command_stop], exposes: [e.battery(), e.action(["on", "off", "brightness_move_up", "brightness_move_down", "brightness_stop"])], toZigbee: [], }, { zigbeeModel: ["4512728"], model: "4512728", vendor: "Namron", description: "Zigbee 1 channel switch K2 (Black)", fromZigbee: [fz.command_on, fz.command_off, fz.battery, fz.command_move, fz.command_stop], exposes: [e.battery(), e.action(["on", "off", "brightness_move_up", "brightness_move_down", "brightness_stop"])], toZigbee: [], }, { zigbeeModel: ["1402769"], model: "1402769", vendor: "Namron", description: "Zigbee LED dimmer", extend: [m.light({ configureReporting: true }), m.forcePowerSource({ powerSource: "Mains (single phase)" })], ota: true, }, { zigbeeModel: ["4512702"], model: "4512702", vendor: "Namron", description: "Zigbee 1 channel switch K4", fromZigbee: [fz.command_on, fz.command_off, fz.battery, fz.command_move, fz.command_stop, fz.command_step], exposes: [ e.battery(), e.action(["on", "off", "brightness_move_up", "brightness_move_down", "brightness_stop", "brightness_step_up", "brightness_step_down"]), ], toZigbee: [], }, { zigbeeModel: ["4512719"], model: "4512719", vendor: "Namron", description: "Zigbee 2 channel switch K4 (white)", fromZigbee: [fz.command_on, fz.command_off, fz.battery, fz.command_move, fz.command_stop], meta: { multiEndpoint: true }, exposes: [ e.battery(), e.action([ "on_l1", "off_l1", "brightness_move_up_l1", "brightness_move_down_l1", "brightness_stop_l1", "on_l2", "off_l2", "brightness_move_up_l2", "brightness_move_down_l2", "brightness_stop_l2", ]), ], toZigbee: [], endpoint: (device) => { return { l1: 1, l2: 2 }; }, ota: true, }, { fingerprint: [{ modelID: "DIM Lighting", manufacturerName: "Namron As" }], model: "4512707", vendor: "Namron", description: "Zigbee LED-Controller", extend: [m.light()], }, { zigbeeModel: ["4512726"], model: "4512726", vendor: "Namron", description: "Zigbee 4 in 1 dimmer", fromZigbee: [fz.battery, fz.command_on, fz.command_off, fz.command_move_to_level, fz.command_move_to_color_temp, fz.command_move_to_hue], toZigbee: [], exposes: [e.battery(), e.battery_voltage(), e.action(["on", "off", "brightness_move_to_level", "color_temperature_move", "move_to_hue"])], meta: { battery: { dontDividePercentage: true } }, configure: async (device, coordinatorEndpoint) => { const endpoint = device.getEndpoint(1); const binds = ["genBasic", "genPowerCfg", "genIdentify", "haDiagnostic", "genOta"]; await reporting.bind(endpoint, coordinatorEndpoint, binds); await reporting.batteryPercentageRemaining(endpoint); await reporting.batteryVoltage(endpoint); }, ota: true, }, { zigbeeModel: ["4512729"], model: "4512729", vendor: "Namron", description: "Zigbee 2 channel switch K4 (black)", fromZigbee: [fz.command_on, fz.command_off, fz.battery, fz.command_move, fz.command_stop], meta: { multiEndpoint: true }, exposes: [ e.battery(), e.action([ "on_l1", "off_l1", "brightness_move_up_l1", "brightness_move_down_l1", "brightness_stop_l1", "on_l2", "off_l2", "brightness_move_up_l2", "brightness_move_down_l2", "brightness_stop_l2", ]), ], toZigbee: [], endpoint: (device) => { return { l1: 1, l2: 2 }; }, ota: true, }, { zigbeeModel: ["4512706"], model: "4512706", vendor: "Namron", description: "Remote control", fromZigbee: [ fz.command_on, fz.command_off, fz.command_step, fz.command_step_color_temperature, fz.command_recall, fz.command_move_to_color_temp, fz.battery, fz.command_move_to_hue, ], exposes: [ e.battery(), e.action([ "on", "off", "brightness_step_up", "brightness_step_down", "color_temperature_step_up", "color_temperature_step_down", "recall_*", "color_temperature_move", "move_to_hue_l1", "move_to_hue_l2", "move_to_hue_l3", "move_to_hue_l4", ]), ], toZigbee: [], meta: { multiEndpoint: true }, endpoint: (device) => { return { l1: 1, l2: 2, l3: 3, l4: 4 }; }, }, { zigbeeModel: ["4512705"], model: "4512705", vendor: "Namron", description: "Zigbee 4 channel remote control", fromZigbee: [fz.command_on, fz.command_off, fz.battery, fz.command_move, fz.command_stop, fz.command_recall], toZigbee: [], ota: true, exposes: [ e.battery(), e.action([ "on_l1", "off_l1", "brightness_move_up_l1", "brightness_move_down_l1", "brightness_stop_l1", "on_l2", "off_l2", "brightness_move_up_l2", "brightness_move_down_l2", "brightness_stop_l2", "on_l3", "off_l3", "brightness_move_up_l3", "brightness_move_down_l3", "brightness_stop_l3", "on_l4", "off_l4", "brightness_move_up_l4", "brightness_move_down_l4", "brightness_stop_l4", "recall_*", ]), ], meta: { multiEndpoint: true }, endpoint: (device) => { return { l1: 1, l2: 2, l3: 3, l4: 4 }; }, }, { zigbeeModel: ["3802960"], model: "3802960", vendor: "Namron", description: "LED 9W DIM E27", extend: [m.light()], }, { zigbeeModel: ["3802961"], model: "3802961", vendor: "Namron", description: "LED 9W CCT E27", extend: [m.light({ colorTemp: { range: [153, 370] } })], }, { zigbeeModel: ["3802962"], model: "3802962", vendor: "Namron", description: "LED 9W RGBW E27", extend: [m.light({ colorTemp: { range: undefined }, color: true, turnsOffAtBrightness1: true })], }, { zigbeeModel: ["3802963"], model: "3802963", vendor: "Namron", description: "LED 5,3W DIM E14", extend: [m.light()], }, { zigbeeModel: ["3802964"], model: "3802964", vendor: "Namron", description: "LED 5,3W CCT E14", extend: [m.light({ colorTemp: { range: undefined } })], }, { zigbeeModel: ["3802965"], model: "3802965", vendor: "Namron", description: "LED 4,8W DIM GU10", extend: [m.light()], }, { zigbeeModel: ["3802966"], model: "3802966", vendor: "Namron", description: "LED 4.8W CCT GU10", extend: [m.light({ colorTemp: { range: [153, 454] } })], }, { zigbeeModel: ["89665"], model: "89665", vendor: "Namron", description: "LED Strip RGB+W (5m) IP20", extend: [m.light({ colorTemp: { range: undefined }, color: true, turnsOffAtBrightness1: true })], }, { zigbeeModel: ["4512737", "4512738"], model: "4512737/4512738", vendor: "Namron", description: "Touch thermostat", fromZigbee: [ fz.thermostat, namron.fromZigbee.namron_thermostat, fz.metering, fz.electrical_measurement, namron.fromZigbee.namron_hvac_user_interface, ], toZigbee: [ tz.thermostat_occupied_heating_setpoint, tz.thermostat_unoccupied_heating_setpoint, tz.thermostat_occupancy, tz.thermostat_local_temperature_calibration, tz.thermostat_local_temperature, tz.thermostat_outdoor_temperature, tz.thermostat_system_mode, tz.thermostat_control_sequence_of_operation, tz.thermostat_running_state, namron.toZigbee.namron_thermostat_child_lock, namron.toZigbee.namron_thermostat, ], exposes: [ e.local_temperature(), e.numeric("outdoor_temperature", ea.STATE_GET).withUnit("°C").withDescription("Current temperature measured from the floor sensor"), e .climate() .withSetpoint("occupied_heating_setpoint", 0, 40, 0.1) .withLocalTemperature() .withLocalTemperatureCalibration(-3, 3, 0.1) .withSystemMode(["off", "auto", "dry", "heat"]) .withRunningState(["idle", "heat"]), e.binary("away_mode", ea.ALL, "ON", "OFF").withDescription("Enable/disable away mode"), e.binary("child_lock", ea.ALL, "LOCK", "UNLOCK").withDescription("Enables/disables physical input on the device"), e.power(), e.current(), e.voltage(), e.energy(), e.enum("lcd_brightness", ea.ALL, ["low", "mid", "high"]).withDescription("OLED brightness when operating the buttons. Default: Medium."), e.enum("button_vibration_level", ea.ALL, ["off", "low", "high"]).withDescription("Key beep volume and vibration level. Default: Low."), e .enum("floor_sensor_type", ea.ALL, ["10k", "15k", "50k", "100k", "12k"]) .withDescription("Type of the external floor sensor. Default: NTC 10K/25."), e.enum("sensor", ea.ALL, ["air", "floor", "both"]).withDescription("The sensor used for heat control. Default: Room Sensor."), e.enum("powerup_status", ea.ALL, ["default", "last_status"]).withDescription("The mode after a power reset. Default: Previous Mode."), e .numeric("floor_sensor_calibration", ea.ALL) .withUnit("°C") .withValueMin(-3) .withValueMax(3) .withValueStep(0.1) .withDescription("The tempearatue calibration for the external floor sensor, between -3 and 3 in 0.1°C. Default: 0."), e .numeric("dry_time", ea.ALL) .withUnit("min") .withValueMin(5) .withValueMax(100) .withDescription("The duration of Dry Mode, between 5 and 100 minutes. Default: 5."), e.enum("mode_after_dry", ea.ALL, ["off", "manual", "auto", "away"]).withDescription("The mode after Dry Mode. Default: Auto."), e.enum("temperature_display", ea.ALL, ["room", "floor"]).withDescription("The temperature on the display. Default: Room Temperature."), e .numeric("window_open_check", ea.ALL) .withUnit("°C") .withValueMin(0) .withValueMax(4) .withValueStep(0.5) .withDescription("The threshold to detect window open, between 1.5 and 4 in 0.5 °C. Default: 0 (disabled)."), e .numeric("hysterersis", ea.ALL) .withUnit("°C") .withValueMin(0.5) .withValueMax(5) .withValueStep(0.1) .withDescription("Hysteresis setting, between 0.5 and 5 in 0.1 °C. Default: 0.5."), e.enum("display_auto_off_enabled", ea.ALL, ["enabled", "disabled"]), e .numeric("alarm_airtemp_overvalue", ea.ALL) .withUnit("°C") .withValueMin(0) .withValueMax(35) .withDescription("Floor temperature over heating threshold, range is 0-35, unit is 1ºC, " + "0 means this function is disabled, default value is 27."), ], // Device does not asks for the time with binding, therefore we write the time every 24 hours extend: [m.writeTimeDaily({ endpointId: 1 }), namron.namronExtend.addNamronHvacThermostat2Cluster()], configure: async (device, coordinatorEndpoint) => { const endpoint = device.getEndpoint(1); const binds = [ "genBasic", "genIdentify", "hvacThermostat", "seMetering", "haElectricalMeasurement", "genAlarms", "msOccupancySensing", "genTime", "hvacUserInterfaceCfg", ]; await reporting.bind(endpoint, coordinatorEndpoint, binds); // standard ZCL attributes await reporting.thermostatTemperature(endpoint, { min: 0, change: 50 }); await reporting.thermostatOccupiedHeatingSetpoint(endpoint); await reporting.thermostatUnoccupiedHeatingSetpoint(endpoint); await reporting.thermostatKeypadLockMode(endpoint); // Metering await endpoint.read("haElectricalMeasurement", ["acVoltageMultiplier", "acVoltageDivisor", "acCurrentMultiplier"]); await endpoint.read("haElectricalMeasurement", ["acCurrentDivisor"]); await reporting.rmsVoltage(endpoint, { min: 10, change: 20 }); // Voltage - Min change of 2v await reporting.rmsCurrent(endpoint, { min: 10, change: 10 }); // A - z2m displays only the first decimals, so change of 10 (0,01) await reporting.activePower(endpoint, { min: 10, change: 15 }); // W - Min change of 1,5W await reporting.currentSummDelivered(endpoint, { min: 300 }); // Report KWH every 5min await reporting.readMeteringMultiplierDivisor(endpoint); // OperateDisplayLcdBrightnesss await endpoint.configureReporting("hvacThermostat", [ { attribute: "lcdBrightness", minimumReportInterval: 0, maximumReportInterval: constants.repInterval.HOUR, reportableChange: null, }, ], sunricherManufacturer); // ButtonVibrationLevel await endpoint.configureReporting("hvacThermostat", [ { attribute: "buttonVibrationLevel", minimumReportInterval: 0, maximumReportInterval: constants.repInterval.HOUR, reportableChange: null, }, ], sunricherManufacturer); // FloorSensorType await endpoint.configureReporting("hvacThermostat", [ { attribute: "floorSensorType", minimumReportInterval: 0, maximumReportInterval: constants.repInterval.HOUR, reportableChange: null, }, ], sunricherManufacturer); // ControlType await endpoint.configureReporting("hvacThermostat", [ { attribute: "controlType", minimumReportInterval: 0, maximumReportInterval: constants.repInterval.HOUR, reportableChange: null, }, ], sunricherManufacturer); // PowerUpStatus await endpoint.configureReporting("hvacThermostat", [ { attribute: "powerUpStatus", minimumReportInterval: 0, maximumReportInterval: constants.repInterval.HOUR, reportableChange: null, }, ], sunricherManufacturer); // FloorSensorCalibration await endpoint.configureReporting("hvacThermostat", [ { attribute: "floorSensorCalibration", minimumReportInterval: 0, maximumReportInterval: constants.repInterval.HOUR, reportableChange: 0, }, ], sunricherManufacturer); // DryTime await endpoint.configureReporting("hvacThermostat", [ { attribute: "dryTime", minimumReportInterval: 0, maximumReportInterval: constants.repInterval.HOUR, reportableChange: 0, }, ], sunricherManufacturer); // ModeAfterDry await endpoint.configureReporting("hvacThermostat", [ { attribute: "modeAfterDry", minimumReportInterval: 0, maximumReportInterval: constants.repInterval.HOUR, reportableChange: null, }, ], sunricherManufacturer); // TemperatureDisplay await endpoint.configureReporting("hvacThermostat", [ { attribute: "temperatureDisplay", minimumReportInterval: 0, maximumReportInterval: constants.repInterval.HOUR, reportableChange: null, }, ], sunricherManufacturer); // WindowOpenCheck await endpoint.configureReporting("hvacThermostat", [ { attribute: "windowOpenCheck2", minimumReportInterval: 0, maximumReportInterval: constants.repInterval.HOUR, reportableChange: 0, }, ], sunricherManufacturer); // Hysterersis await endpoint.configureReporting("hvacThermostat", [ { attribute: "hysterersis", minimumReportInterval: 0, maximumReportInterval: constants.repInterval.HOUR, reportableChange: 0, }, ], sunricherManufacturer); // DisplayAutoOffEnable await endpoint.configureReporting("hvacThermostat", [ { attribute: "displayAutoOffEnable", minimumReportInterval: 0, maximumReportInterval: constants.repInterval.HOUR, reportableChange: null, }, ], sunricherManufacturer); // AlarmAirTempOverValue await endpoint.configureReporting("hvacThermostat", [ { attribute: "alarmAirTempOverValue", minimumReportInterval: 0, maximumReportInterval: constants.repInterval.HOUR, reportableChange: 0, }, ], sunricherManufacturer); // Away Mode Set await endpoint.configureReporting("hvacThermostat", [ { attribute: "awayModeSet", minimumReportInterval: 0, maximumReportInterval: constants.repInterval.HOUR, reportableChange: null, }, ], sunricherManufacturer); // Trigger initial read await endpoint.read("hvacThermostat", ["systemMode", "runningState", "occupiedHeatingSetpoint"]); await endpoint.read("hvacThermostat", ["lcdBrightness", "buttonVibrationLevel", "floorSensorType", "controlType"], sunricherManufacturer); await endpoint.read("hvacThermostat", ["powerUpStatus", "floorSensorCalibration", "dryTime", "modeAfterDry"], sunricherManufacturer); await endpoint.read("hvacThermostat", ["temperatureDisplay", "windowOpenCheck2", "hysterersis", "displayAutoOffEnable"], sunricherManufacturer); await endpoint.read("hvacThermostat", ["alarmAirTempOverValue", "awayModeSet"], sunricherManufacturer); }, ota: true, }, { zigbeeModel: ["4512735"], model: "4512735", vendor: "Namron", description: "Multiprise with 4 AC outlets and 2 USB super charging ports (16A)", fromZigbee: [fz.on_off], toZigbee: [tz.on_off], exposes: [ e.switch().withEndpoint("l1"), e.switch().withEndpoint("l2"), e.switch().withEndpoint("l3"), e.switch().withEndpoint("l4"), e.switch().withEndpoint("l5"), ], endpoint: (device) => { return { l1: 1, l2: 2, l3: 3, l4: 4, l5: 5 }; }, meta: { multiEndpoint: true }, configure: async (device, coordinatorEndpoint) => { for (const ID of [1, 2, 3, 4, 5]) { const endpoint = device.getEndpoint(ID); await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff"]); } device.powerSource = "Mains (single phase)"; device.save(); }, }, { zigbeeModel: ["5401392", "5401396", "5401393", "5401397", "5401394", "5401398", "5401395", "5401399"], model: "540139X", vendor: "Namron", description: "Panel heater 400/600/800/1000 W", extend: [namron.namronExtend.addNamronHvacThermostatCluster()], ota: true, fromZigbee: [fz.thermostat, fz.metering, fz.electrical_measurement, fzLocal.namron_panelheater, namron.fromZigbee.namron_hvac_user_interface], toZigbee: [ tz.thermostat_occupied_heating_setpoint, tz.thermostat_local_temperature_calibration, tz.thermostat_system_mode, tz.thermostat_running_state, tz.thermostat_local_temperature, tzLocal.namron_panelheater, namron.toZigbee.namron_thermostat_child_lock, ], exposes: [ e.power(), e.current(), e.voltage(), e.energy(), e .climate() .withSetpoint("occupied_heating_setpoint", 5, 35, 0.5) .withLocalTemperature() // Unit also supports Auto, but i haven't added support the scheduler yet // so the function is not listed for now, as this doesn´t allow you the set the temperature .withSystemMode(["off", "heat"]) .withLocalTemperatureCalibration(-3, 3, 0.1) .withRunningState(["idle", "heat"]), // Namron proprietary stuff e.binary("child_lock", ea.ALL, "LOCK", "UNLOCK").withDescription("Enables/disables physical input on the device"), e .numeric("hysterersis", ea.ALL) .withUnit("°C") .withValueMin(0.5) .withValueMax(2) .withValueS