zigbee-herdsman-converters
Version:
Collection of device converters to be used with zigbee-herdsman
1,191 lines • 106 kB
JavaScript
"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[0x2009] !== undefined) {
// System control method: 0=PID, 1=Hysteresis
result.control_method = data[0x2009] === 0 ? "pid" : "hysteresis";
}
if (data[0x100c] !== undefined) {
// Adaptive function AS: 0=Enable, 1=Disable
result.adaptive_function = data[0x100c] === 0;
}
if (data[0x2006] !== undefined) {
result.pid_kp = data[0x2006] / 1000.0;
}
if (data[0x2007] !== undefined) {
result.pid_kd = data[0x2007] / 1000.0;
}
if (data[0x2008] !== undefined) {
result.pid_ki = data[0x2008] / 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", [0x2009], 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", [0x100c], 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", [0x2006], 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", [0x2008], 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", [0x2007], 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)
.withValueStep(0.1)
.withDescription(