zigbee-herdsman-converters
Version:
Collection of device converters to be used with zigbee-herdsman
7,094 lines • 285 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 exposes = __importStar(require("../lib/exposes"));
const m = __importStar(require("../lib/modernExtend"));
const namron = __importStar(require("../lib/namron"));
const reporting = __importStar(require("../lib/reporting"));
const utils = __importStar(require("../lib/utils"));
//import {logger} from "../lib/logger";
const e = exposes.presets;
const ea = exposes.access;
//const NS = "zhc:slacky_diy";
const ppmReporting = { min: 10, max: 300, change: 0.000001 };
const batteryReporting = { min: 3600, max: 21600, change: 0 };
const temperatureReporting = { min: 10, max: 3600, change: 10 };
const humidityReporting = { min: 10, max: 3600, change: 10 };
const model_r01 = "THERM_SLACKY_DIY_R01";
//const model_r02 = "THERM_SLACKY_DIY_R02";
const model_r03 = "THERM_SLACKY_DIY_R03";
const model_r04 = "THERM_SLACKY_DIY_R04";
//const model_r05 = "THERM_SLACKY_DIY_R05";
const model_r06 = "THERM_SLACKY_DIY_R06";
const model_r07 = "THERM_SLACKY_DIY_R07";
const model_r08 = "THERM_SLACKY_DIY_R08";
const model_r09 = "THERM_SLACKY_DIY_R09";
//const model_r0a = "THERM_SLACKY_DIY_R0A";
const model_r0b = "THERM_SLACKY_DIY_R0B";
const modelR0c = "THERM_SLACKY_DIY_R0C";
const model_r0d = "THERM_SLACKY_DIY_R0D";
const attrThermSensorUser = 0xf000;
const attrThermFrostProtect = 0xf001;
const attrThermHeatProtect = 0xf002;
const attrThermEcoMode = 0xf003;
const attrThermEcoModeHeatTemperature = 0xf004;
const attrThermFrostProtectOnOff = 0xf005;
const attrThermSettingsReset = 0xf006;
const attrThermScheduleMode = 0xf007;
const attrThermSound = 0xf008;
const attrThermLevel = 0xf009;
const attrThermInversion = 0xf00a;
const attrThermEcoModeCoolTemperature = 0xf00b;
const attrThermExtTemperatureCalibration = 0xf00c;
const attrThermModeKeyLock = 0xf00d;
const attrThermManufName = 0xf00e;
const attrThermScreenOffTime = 0xf00f;
const attrThermLedIndicator = 0xf010;
const attrFanCtrlControl = 0xf000;
const switchSensorUsed = ["Inner (IN)", "All (AL)", "Outer (OU)"];
const attrElCityMeterModelPreset = 0xf000;
const attrElCityMeterAddressPreset = 0xf001;
const attrElCityMeterMeasurementPreset = 0xf002;
const attrElCityMeterDateRelease = 0xf003;
const attrElCityMeterModelName = 0xf004;
const attrElCityMeterPasswordPreset = 0xf005;
const attrSensorReadPeriod = 0xf000;
const attrTemperatureOffset = 0xf001;
const attrTemperatureOnOff = 0xf002;
const attrTemperatureLow = 0xf003;
const attrTemperatureHigh = 0xf004;
const attrHumidityOffset = 0xf005;
const attrHumidityOnOff = 0xf006;
const attrHumidityLow = 0xf007;
const attrHumidityHigh = 0xf008;
const attrRepeatCommand = 0xf009;
const attrCo2Calibration = 0xf008;
const attrFeaturesSensors = 0xf009;
const attrDisplayRotate = 0xf00a;
const attrDisplayInversion = 0xf00b;
const switchFeatures = ["nothing", "co2_forced_calibration", "co2_factory_reset", "bind_reset", ""];
const attrPlugKeyLock = 0xf000;
const attrPlugLedCtrl = 0xf001;
const attrPlugSwitchCurrentMax = 0xf002;
const attrPlugSwitchPowerMax = 0xf003;
const attrPlugSwitchTimeReload = 0xf004;
const attrPlugSwitchProtectCtrl = 0xf005;
const attrPlugSwitchAutoRestart = 0xf006;
const attrSocketAdjustCurrent = 0xf007;
const attrSocketAdjustVoltage = 0xf008;
const attrSocketAdjustPower = 0xf009;
const attrSwitchType = 0xf000;
const attrSwitchDecoupled = 0xf001;
const attrDeviceModelNumber = 0xf002;
const attrDoorDelayOn = 0xf003;
const attrDoorDelayOff = 0xf004;
const attrDoorOnCmdOff = 0xf005;
const attrDoorOffCmdOff = 0xf006;
const attrSceneId = 0xf000;
const attrGroupId = 0xf001;
const fzLocal = {
thermostat_custom_fw: {
cluster: "hvacThermostat",
type: ["attributeReport", "readResponse"],
convert: (model, msg, publish, options, meta) => {
const result = {};
if (msg.data[attrThermSensorUser] !== undefined) {
const lookup2 = { 0: "Inner (IN)", 1: "Outer (OU)" };
const lookup3 = { 0: "Inner (IN)", 1: "All (AL)", 2: "Outer (OU)" };
if (model.model === model_r0b) {
result.sensor = utils.getFromLookup(msg.data[attrThermSensorUser], lookup2);
}
else {
result.sensor = utils.getFromLookup(msg.data[attrThermSensorUser], lookup3);
}
}
if (msg.data.minSetpointDeadBand !== undefined) {
//logger.info(`Model: ${model.model}`, NS);
let data;
if (model.model === model_r06 || model.model === model_r09 || model.model === model_r0b || model.model === model_r0d) {
data = msg.data.minSetpointDeadBand / 10;
result.hysteresis_temperature = data;
}
else {
data = msg.data.minSetpointDeadBand;
result.deadzone_temperature = data;
}
//logger.info(`DeadBand: ${data}`, NS);
}
if (msg.data[attrThermFrostProtect] !== undefined) {
const data = Number.parseInt(msg.data[attrThermFrostProtect], 10) / 100;
result.frost_protect = data;
}
if (msg.data[attrThermHeatProtect] !== undefined) {
const data = Number.parseInt(msg.data[attrThermHeatProtect], 10) / 100;
result.heat_protect = data;
}
if (msg.data[attrThermEcoMode] !== undefined) {
result.eco_mode = msg.data[attrThermEcoMode] === 1 ? "On" : "Off";
}
if (msg.data[attrThermEcoModeCoolTemperature] !== undefined) {
const data = Number.parseInt(msg.data[attrThermEcoModeCoolTemperature], 10) / 100;
result.eco_mode_cool_temperature = data;
}
if (msg.data[attrThermEcoModeHeatTemperature] !== undefined) {
const data = Number.parseInt(msg.data[attrThermEcoModeHeatTemperature], 10) / 100;
result.eco_mode_heat_temperature = data;
}
if (msg.data[attrThermFrostProtectOnOff] !== undefined) {
result.frost_protect_on_off = msg.data[attrThermFrostProtectOnOff] === 1 ? "On" : "Off";
}
if (msg.data[attrThermLevel] !== undefined) {
if (model.model === model_r0b) {
const lookup_sleep = { 0: "Off", 1: "Dim", 2: "On" };
result.screen_sleep_mode = utils.getFromLookup(msg.data[attrThermLevel], lookup_sleep);
}
else {
const lookup = { 0: "Off", 1: "Low", 2: "Medium", 3: "High" };
result.brightness_level = utils.getFromLookup(msg.data[attrThermLevel], lookup);
}
}
if (msg.data[attrThermScreenOffTime] !== undefined) {
if (model.model === model_r0d) {
const lookup_time = { 0: "10s", 1: "20s", 2: "30s", 3: "40s", 4: "50s", 5: "60s" };
result.screen_sleep_time = utils.getFromLookup(msg.data[attrThermScreenOffTime], lookup_time);
}
}
if (msg.data[attrThermLedIndicator] !== undefined) {
result.led_indicator = msg.data[attrThermLedIndicator] === 1 ? "On" : "Off";
}
if (msg.data[attrThermSound] !== undefined) {
result.sound = msg.data[attrThermSound] === 1 ? "On" : "Off";
}
if (msg.data[attrThermInversion] !== undefined) {
result.relay_type = msg.data[attrThermInversion] === 1 ? "NO" : "NC";
}
if (msg.data[attrThermModeKeyLock] !== undefined) {
result.mode_child_lock = msg.data[attrThermModeKeyLock] === 1 ? "all" : "partial";
}
if (msg.data[attrThermScheduleMode] !== undefined) {
const lookup = { 0: "Off", 1: "5+2", 2: "6+1", 3: "7" };
result.schedule_mode = utils.getFromLookup(msg.data[attrThermScheduleMode], lookup);
}
if (msg.data[attrThermExtTemperatureCalibration] !== undefined) {
const data = Number.parseInt(msg.data[attrThermExtTemperatureCalibration], 10) / 10;
result.external_temperature_calibration = data;
}
return result;
},
},
thermostat_schedule: {
cluster: "hvacThermostat",
type: ["commandSetWeeklySchedule", "commandGetWeeklyScheduleRsp"],
convert: (model, msg, publish, options, meta) => {
const { data } = msg;
const daysOfWeekNums = [...Array.from(Array(7).keys()).filter((x) => (2 ** x) & data.dayofweek)];
// biome-ignore lint/suspicious/noExplicitAny: ignored using `--suppress`
const schedule = `${data.transitions.map((t) => `${String(Math.floor(t.transitionTime / 60)).padStart(2, "0")}:${String(t.transitionTime % 60).padStart(2, "0")}/${t.heatSetpoint / 100.0}°C`).join(" ")}`;
const daysOfWeek = ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"];
return Object.fromEntries(daysOfWeekNums.map((d) => [`schedule_${daysOfWeek[d]}`, schedule]));
},
},
fancontrol_control: {
cluster: "hvacFanCtrl",
type: ["attributeReport", "readResponse"],
convert: (model, msg, publish, options, meta) => {
const result = {};
if (msg.data[attrFanCtrlControl] !== undefined) {
result.fan_control = msg.data[attrFanCtrlControl] === 1 ? "On" : "Off";
}
return result;
},
},
display_brightness: {
cluster: "genLevelCtrl",
type: ["attributeReport", "readResponse"],
convert: (model, msg, publish, options, meta) => {
const result = {};
if (msg.data.currentLevel !== undefined) {
const property = `brightness_${utils.getEndpointName(msg, model, meta)}`;
//logger.info('property: ' + property);
return { [property]: msg.data.currentLevel };
}
return result;
},
},
thermostat_humidity_offset: {
cluster: "msRelativeHumidity",
type: ["attributeReport", "readResponse"],
convert: (model, msg, publish, options, meta) => {
const result = {};
if (msg.data[attrHumidityOffset] !== undefined) {
const data = Number.parseInt(msg.data[attrHumidityOffset], 10) / 100;
result.humidity_offset = data;
}
return result;
},
},
};
const tzLocal = {
display_brightness: {
key: ["brightness", "brightness_day", "brightness_night"],
options: [exposes.options.transition()],
convertSet: async (entity, key, value, meta) => {
await entity.command("genLevelCtrl", "moveToLevel", { level: value, transtime: 0, optionsMask: 0, optionsOverride: 0 }, utils.getOptions(meta.mapped, entity));
return { state: { brightness: value } };
},
convertGet: async (entity, key, meta) => {
await entity.read("genLevelCtrl", ["currentLevel"]);
},
},
thermostat_humidity_offset: {
key: ["humidity_offset"],
convertSet: async (entity, key, value, meta) => {
utils.assertNumber(value);
const humidity_offset = Number(Math.round(value)) * 100;
await entity.write("msRelativeHumidity", { [attrHumidityOffset]: { value: humidity_offset, type: 0x29 } });
return { readAfterWriteTime: 250, state: { humidity_offset: value } };
},
convertGet: async (entity, key, meta) => {
await entity.read("msRelativeHumidity", [attrHumidityOffset]);
},
},
thermostat_sensor_used: {
key: ["sensor"],
convertSet: async (entity, key, value, meta) => {
//const endpoint = meta.device.getEndpoint(1);
const lookup2 = { "Inner (IN)": 0, "Outer (OU)": 1 };
const lookup3 = { "Inner (IN)": 0, "All (AL)": 1, "Outer (OU)": 2 };
if (meta.mapped.model === model_r0b) {
await entity.write("hvacThermostat", { [attrThermSensorUser]: { value: utils.getFromLookup(value, lookup2), type: 0x30 } });
}
else {
await entity.write("hvacThermostat", { [attrThermSensorUser]: { value: utils.getFromLookup(value, lookup3), type: 0x30 } });
}
return { readAfterWriteTime: 250, state: { sensor: value } };
},
convertGet: async (entity, key, meta) => {
await entity.read("hvacThermostat", [attrThermSensorUser]);
},
},
thermostat_deadzone: {
key: ["deadzone_temperature"],
convertSet: async (entity, key, value, meta) => {
utils.assertNumber(value);
const minSetpointDeadBand = Number(Math.round(value));
await entity.write("hvacThermostat", { minSetpointDeadBand });
return { readAfterWriteTime: 250, state: { minSetpointDeadBand: value } };
},
convertGet: async (entity, key, meta) => {
await entity.read("hvacThermostat", ["minSetpointDeadBand"]);
},
},
thermostat_deadzone_10: {
key: ["hysteresis_temperature"],
convertSet: async (entity, key, value, meta) => {
utils.assertNumber(value);
const minSetpointDeadBand = Number(value) * 10;
await entity.write("hvacThermostat", { minSetpointDeadBand });
return { readAfterWriteTime: 250, state: { hysteresis_temperature: value } };
},
convertGet: async (entity, key, meta) => {
await entity.read("hvacThermostat", ["minSetpointDeadBand"]);
},
},
thermostat_frost_protect: {
key: ["frost_protect"],
convertSet: async (entity, key, value, meta) => {
utils.assertNumber(value);
//if (!utils.isInRange(0, 10, Number(value))) throw new Error(`Invalid value: ${value} (expected ${0} to ${10})`);
const frost_protect = Number(Math.round(value)) * 100;
await entity.write("hvacThermostat", { [attrThermFrostProtect]: { value: frost_protect, type: 0x29 } });
return { readAfterWriteTime: 250, state: { frost_protect: value } };
},
convertGet: async (entity, key, meta) => {
await entity.read("hvacThermostat", [attrThermFrostProtect]);
},
},
thermostat_heat_protect: {
key: ["heat_protect"],
convertSet: async (entity, key, value, meta) => {
utils.assertNumber(value);
//if (!utils.isInRange(25, 70, Number(value))) throw new Error(`Invalid value: ${value} (expected ${25} to ${70})`);
const heat_protect = Number(Math.round(value)) * 100;
await entity.write("hvacThermostat", { [attrThermHeatProtect]: { value: heat_protect, type: 0x29 } });
return { readAfterWriteTime: 250, state: { heat_protect: value } };
},
convertGet: async (entity, key, meta) => {
await entity.read("hvacThermostat", [attrThermHeatProtect]);
},
},
thermostat_setpoint_raise_lower: {
key: ["setpoint_raise_lower"],
convertSet: async (entity, key, value, meta) => {
utils.assertNumber(value);
//if (!utils.isInRange(-5, 5, Number(value))) throw new Error(`Invalid value: ${value} (expected ${-5} to ${5})`);
const setpoint_raise_lower = Number(Math.fround(value)) * 10; //Step 0.1°C. 5°C - 50, 1°C - 10 etc.
await entity.command("hvacThermostat", "setpointRaiseLower", { mode: 0, amount: setpoint_raise_lower });
return { readAfterWriteTime: 250, state: { setpoint_raise_lower: value } };
},
},
fancontrol_control: {
key: ["fan_control"],
convertSet: async (entity, key, value, meta) => {
const fan_control = Number(value === "On");
await entity.write("hvacFanCtrl", { [attrFanCtrlControl]: { value: fan_control, type: 0x10 } });
return { readAfterWriteTime: 250, state: { fan_control: value } };
},
convertGet: async (entity, key, meta) => {
await entity.read("hvacFanCtrl", [attrFanCtrlControl]);
},
},
thermostat_eco_mode: {
key: ["eco_mode"],
convertSet: async (entity, key, value, meta) => {
const eco_mode = Number(value === "On");
await entity.write("hvacThermostat", { [attrThermEcoMode]: { value: eco_mode, type: 0x30 } });
return { readAfterWriteTime: 250, state: { eco_mode: value } };
},
convertGet: async (entity, key, meta) => {
await entity.read("hvacThermostat", [attrThermEcoMode]);
},
},
thermostat_eco_mode_cool_temperature: {
key: ["eco_mode_cool_temperature"],
convertSet: async (entity, key, value, meta) => {
utils.assertNumber(value);
//if (!utils.isInRange(5, 45, Number(value))) throw new Error(`Invalid value: ${value} (expected ${5} to ${45})`);
const eco_mode_cool_temperature = Number(Math.round(value)) * 100;
await entity.write("hvacThermostat", { [attrThermEcoModeCoolTemperature]: { value: eco_mode_cool_temperature, type: 0x29 } });
return { readAfterWriteTime: 250, state: { eco_mode_cool_temperature: value } };
},
convertGet: async (entity, key, meta) => {
await entity.read("hvacThermostat", [attrThermEcoModeCoolTemperature]);
},
},
thermostat_eco_mode_heat_temperature: {
key: ["eco_mode_heat_temperature"],
convertSet: async (entity, key, value, meta) => {
utils.assertNumber(value);
//if (!utils.isInRange(5, 45, Number(value))) throw new Error(`Invalid value: ${value} (expected ${5} to ${45})`);
const eco_mode_heat_temperature = Number(Math.round(value)) * 100;
await entity.write("hvacThermostat", { [attrThermEcoModeHeatTemperature]: { value: eco_mode_heat_temperature, type: 0x29 } });
return { readAfterWriteTime: 250, state: { eco_mode_heat_temperature: value } };
},
convertGet: async (entity, key, meta) => {
await entity.read("hvacThermostat", [attrThermEcoModeHeatTemperature]);
},
},
thermostat_frost_protect_onoff: {
key: ["frost_protect_on_off"],
convertSet: async (entity, key, value, meta) => {
const frost_protect_on_off = Number(value === "On");
await entity.write("hvacThermostat", { [attrThermFrostProtectOnOff]: { value: frost_protect_on_off, type: 0x10 } });
return { readAfterWriteTime: 250, state: { frost_protect_on_off: value } };
},
convertGet: async (entity, key, meta) => {
await entity.read("hvacThermostat", [attrThermFrostProtectOnOff]);
},
},
thermostat_sound: {
key: ["sound"],
convertSet: async (entity, key, value, meta) => {
const sound = Number(value === "On");
await entity.write("hvacThermostat", { [attrThermSound]: { value: sound, type: 0x10 } });
return { readAfterWriteTime: 250, state: { sound: value } };
},
convertGet: async (entity, key, meta) => {
await entity.read("hvacThermostat", [attrThermSound]);
},
},
thermostat_brightness_level: {
key: ["brightness_level"],
convertSet: async (entity, key, value, meta) => {
//utils.assertNumber(value);
const lookup = { Off: 0, Low: 1, Medium: 2, High: 3 };
await entity.write("hvacThermostat", { [attrThermLevel]: { value: utils.getFromLookup(value, lookup), type: 0x30 } });
return { state: { brightness_level: value } };
},
convertGet: async (entity, key, meta) => {
await entity.read("hvacThermostat", [attrThermLevel]);
},
},
thermostat_screen_sleep_mode: {
key: ["screen_sleep_mode"],
convertSet: async (entity, key, value, meta) => {
//utils.assertNumber(value);
const lookup = { Off: 0, Dim: 1, On: 2 };
await entity.write("hvacThermostat", { [attrThermLevel]: { value: utils.getFromLookup(value, lookup), type: 0x30 } });
return { state: { screen_sleep_mode: value } };
},
convertGet: async (entity, key, meta) => {
await entity.read("hvacThermostat", [attrThermLevel]);
},
},
thermostat_screen_sleep_time: {
key: ["screen_sleep_time"],
convertSet: async (entity, key, value, meta) => {
//utils.assertNumber(value);
const lookup = { "10s": 0, "20s": 1, "30s": 2, "40s": 3, "50s": 4, "60s": 5 };
await entity.write("hvacThermostat", { [attrThermScreenOffTime]: { value: utils.getFromLookup(value, lookup), type: 0x30 } });
return { state: { screen_sleep_time: value } };
},
convertGet: async (entity, key, meta) => {
await entity.read("hvacThermostat", [attrThermScreenOffTime]);
},
},
thermostat_led_indicator: {
key: ["led_indicator"],
convertSet: async (entity, key, value, meta) => {
const led_indicator = Number(value === "On");
await entity.write("hvacThermostat", { [attrThermLedIndicator]: { value: led_indicator, type: 0x10 } });
return { readAfterWriteTime: 250, state: { led_indicator: value } };
},
convertGet: async (entity, key, meta) => {
await entity.read("hvacThermostat", [attrThermLedIndicator]);
},
},
thermostat_inversion: {
key: ["relay_type"],
convertSet: async (entity, key, value, meta) => {
const relay_type = Number(value === "NO");
await entity.write("hvacThermostat", { [attrThermInversion]: { value: relay_type, type: 0x10 } });
return { readAfterWriteTime: 250, state: { relay_type: value } };
},
convertGet: async (entity, key, meta) => {
await entity.read("hvacThermostat", [attrThermInversion]);
},
},
thermostat_mode_child_lock: {
key: ["mode_child_lock"],
convertSet: async (entity, key, value, meta) => {
const mode_child_lock = Number(value === "all");
await entity.write("hvacThermostat", { [attrThermModeKeyLock]: { value: mode_child_lock, type: 0x10 } });
return { readAfterWriteTime: 250, state: { mode_child_lock: value } };
},
convertGet: async (entity, key, meta) => {
await entity.read("hvacThermostat", [attrThermModeKeyLock]);
},
},
thermostat_schedule_mode: {
key: ["schedule_mode"],
convertSet: async (entity, key, value, meta) => {
//utils.assertNumber(value);
const lookup = { off: 0, "5+2": 1, "6+1": 2, "7": 3 };
await entity.write("hvacThermostat", { [attrThermScheduleMode]: { value: utils.getFromLookup(value, lookup), type: 0x30 } });
return { state: { schedule_mode: value } };
},
convertGet: async (entity, key, meta) => {
await entity.read("hvacThermostat", [attrThermScheduleMode]);
},
},
thermostat_settings_reset: {
key: ["settings_reset"],
convertSet: async (entity, key, value, meta) => {
const settings_reset = Number(value === "Default");
await entity.write("hvacThermostat", { [attrThermSettingsReset]: { value: settings_reset, type: 0x10 } });
return { readAfterWriteTime: 250, state: { settings_reset: value } };
},
},
thermostat_ext_temperature_calibration: {
key: ["external_temperature_calibration"],
convertSet: async (entity, key, value, meta) => {
utils.assertNumber(value);
//if (!utils.isInRange(-9, 9, Number(value))) throw new Error(`Invalid value: ${value} (expected ${-9} to ${9})`);
const external_temperature_calibration = Number(Math.round(value)) * 10;
await entity.write("hvacThermostat", { [attrThermExtTemperatureCalibration]: { value: external_temperature_calibration, type: 0x28 } });
return { readAfterWriteTime: 250, state: { external_temperature_calibration: value } };
},
convertGet: async (entity, key, meta) => {
await entity.read("hvacThermostat", [attrThermExtTemperatureCalibration]);
},
},
thermostat_manuf_name: {
key: ["manuf_name"],
convertSet: async (entity, key, value, meta) => {
const lookup = { R00: 0, R01: 1, R02: 2, R03: 3, R04: 4, R05: 5, R06: 6, R07: 7, R08: 8, R09: 9, R0A: 10, R0B: 11, R0C: 12, R0D: 13 };
await entity.write("hvacThermostat", { [attrThermManufName]: { value: utils.getFromLookup(value, lookup), type: 0x30 } });
return { state: { manuf_name: value } };
},
convertGet: async (entity, key, meta) => {
await entity.read("hvacThermostat", [attrThermManufName]);
},
},
device_model_number: {
key: ["door_device_number", "switch_device_number"],
convertSet: async (entity, key, value, meta) => {
const lookup = { model_0: 0, model_1: 1, model_2: 2, model_3: 3, model_4: 4, model_5: 5 };
await entity.write("genOnOffSwitchCfg", { [attrDeviceModelNumber]: { value: utils.getFromLookup(value, lookup), type: 0x30 } });
return { state: { [key]: value } };
},
convertGet: async (entity, key, meta) => {
await entity.read("genOnOffSwitchCfg", [attrDeviceModelNumber]);
},
},
};
const localFromZigbeeThermostat = [
fz.humidity,
fz.thermostat,
fz.fan,
namron.fromZigbee.namron_hvac_user_interface,
fz.thermostat_weekly_schedule,
fzLocal.thermostat_custom_fw,
fzLocal.thermostat_schedule,
fzLocal.display_brightness,
fzLocal.fancontrol_control,
fzLocal.thermostat_humidity_offset,
];
const localToZigbeeThermostat = [
tz.thermostat_local_temperature,
tz.thermostat_outdoor_temperature,
tz.thermostat_system_mode,
tz.thermostat_occupied_heating_setpoint,
tz.thermostat_running_state,
tz.thermostat_local_temperature_calibration,
tz.thermostat_min_heat_setpoint_limit,
tz.thermostat_max_heat_setpoint_limit,
tz.thermostat_programming_operation_mode,
namron.toZigbee.namron_thermostat_child_lock,
tz.thermostat_weekly_schedule,
tz.fan_mode,
tzLocal.display_brightness,
tzLocal.thermostat_sensor_used,
tzLocal.thermostat_deadzone,
tzLocal.thermostat_deadzone_10,
tzLocal.thermostat_setpoint_raise_lower,
tzLocal.thermostat_frost_protect,
tzLocal.thermostat_heat_protect,
tzLocal.thermostat_eco_mode,
tzLocal.thermostat_eco_mode_cool_temperature,
tzLocal.thermostat_eco_mode_heat_temperature,
tzLocal.thermostat_frost_protect_onoff,
tzLocal.thermostat_brightness_level,
tzLocal.thermostat_screen_sleep_mode,
tzLocal.thermostat_screen_sleep_time,
tzLocal.thermostat_led_indicator,
tzLocal.thermostat_sound,
tzLocal.thermostat_inversion,
tzLocal.thermostat_schedule_mode,
tzLocal.thermostat_settings_reset,
tzLocal.thermostat_ext_temperature_calibration,
tzLocal.thermostat_mode_child_lock,
tzLocal.thermostat_manuf_name,
tzLocal.fancontrol_control,
tzLocal.thermostat_humidity_offset,
];
function localActionExtend(args = {}) {
const { localAction = ["hold", "single", "double", "triple", "quadruple", "quintuple", "release"], bind = true, reporting = true, reportingConfig = { min: 10, max: 0, change: 1 }, endpointNames = undefined, } = args;
let actions = localAction;
if (endpointNames) {
actions = localAction.flatMap((c) => endpointNames.map((e) => `${c}_${e}`));
}
const exposes = [e.enum("action", ea.STATE, actions)];
const actionPayloadLookup = {
0: "hold",
1: "single",
2: "double",
3: "triple",
4: "quadruple",
5: "quintuple",
255: "release",
};
const fromZigbee = [
{
cluster: "genMultistateInput",
type: ["attributeReport", "readResponse"],
convert: (model, msg, publish, options, meta) => {
if (utils.hasAlreadyProcessedMessage(msg, model))
return;
const value = msg.data.presentValue;
//logger.logger.info('msg.data: ' + data[attribute]);
if (value === 300)
return { action: "N/A" };
const payload = { action: utils.postfixWithEndpointName(actionPayloadLookup[value], msg, model, meta) };
return payload;
},
},
];
const result = { exposes, fromZigbee, isModernExtend: true };
if (reporting)
result.configure = [
m.setupConfigureForBinding("genMultistateInput", "input", endpointNames),
m.setupConfigureForReporting("genMultistateInput", "presentValue", { config: reportingConfig, access: ea.GET, endpointNames }),
];
else if (bind)
result.configure = [m.setupConfigureForBinding("genMultistateInput", "input", endpointNames)];
return result;
}
async function configureCommon(device, coordinatorEndpoint, definition) {
//logger.info(definition.model, NS);
const endpoint1 = device.getEndpoint(1);
const endpoint2 = device.getEndpoint(2);
await endpoint1.read("hvacUserInterfaceCfg", ["keypadLockout"]);
await endpoint1.read("genLevelCtrl", ["currentLevel"]);
await endpoint2.read("genLevelCtrl", ["currentLevel"]);
await endpoint1.read("hvacThermostat", ["localTemp"]);
await endpoint1.read("hvacThermostat", ["outdoorTemp"]);
await endpoint1.read("hvacThermostat", ["absMinHeatSetpointLimit"]);
await endpoint1.read("hvacThermostat", ["absMaxHeatSetpointLimit"]);
await endpoint1.read("hvacThermostat", ["minHeatSetpointLimit"]);
await endpoint1.read("hvacThermostat", ["maxHeatSetpointLimit"]);
await endpoint1.read("hvacThermostat", ["localTemperatureCalibration"]);
await endpoint1.read("hvacThermostat", ["occupiedHeatingSetpoint"]);
await endpoint1.read("hvacThermostat", ["programingOperMode"]);
await endpoint1.read("hvacThermostat", ["systemMode"]);
await endpoint1.read("hvacThermostat", ["runningState"]);
await endpoint1.read("hvacThermostat", ["minSetpointDeadBand"]);
await endpoint1.read("hvacThermostat", [attrThermSensorUser]);
await endpoint1.read("hvacThermostat", [attrThermFrostProtect]);
await endpoint1.read("hvacThermostat", [attrThermHeatProtect]);
await endpoint1.read("hvacThermostat", [attrThermEcoMode]);
await endpoint1.read("hvacThermostat", [attrThermEcoModeCoolTemperature]);
await endpoint1.read("hvacThermostat", [attrThermEcoModeHeatTemperature]);
await endpoint1.read("hvacThermostat", [attrThermFrostProtectOnOff]);
await endpoint1.read("hvacThermostat", [attrThermScheduleMode]);
await endpoint1.read("hvacThermostat", [attrThermSound]);
await endpoint1.read("hvacThermostat", [attrThermLevel]);
await endpoint1.read("hvacThermostat", [attrThermInversion]);
await endpoint1.read("hvacThermostat", [attrThermExtTemperatureCalibration]);
if (definition.model === model_r09) {
await endpoint1.read("hvacThermostat", [attrThermModeKeyLock]);
}
await endpoint1.read("hvacFanCtrl", ["fanMode"]);
await endpoint1.read("hvacFanCtrl", [attrFanCtrlControl]);
await reporting.bind(endpoint1, coordinatorEndpoint, ["hvacThermostat", "hvacUserInterfaceCfg", "hvacFanCtrl"]);
if (definition.model === modelR0c) {
await reporting.bind(endpoint1, coordinatorEndpoint, ["msRelativeHumidity"]);
await endpoint1.read("msRelativeHumidity", ["measuredValue"]);
await endpoint1.read("msRelativeHumidity", [attrHumidityOffset]);
const payload_humidity = [
{ attribute: { ID: 0x0000, type: 0x21 }, minimumReportInterval: 10, maximumReportInterval: 3600, reportableChange: 10 },
];
await endpoint1.configureReporting("msRelativeHumidity", payload_humidity);
const payload_humidity_offset = [
{ attribute: { ID: attrHumidityOffset, type: 0x29 }, minimumReportInterval: 0, maximumReportInterval: 3600, reportableChange: 0 },
];
await endpoint1.configureReporting("msRelativeHumidity", payload_humidity_offset);
}
if (definition.model === model_r03 || definition.model === model_r04 || definition.model === model_r09 || definition.model === modelR0c) {
await reporting.bind(endpoint1, coordinatorEndpoint, ["genLevelCtrl"]);
const payloadCurrentLevel = [
{ attribute: { ID: 0x0000, type: 0x20 }, minimumReportInterval: 0, maximumReportInterval: 3600, reportableChange: 0 },
];
await endpoint1.configureReporting("genLevelCtrl", payloadCurrentLevel);
if (definition.model === model_r03 || definition.model === model_r09) {
await reporting.bind(endpoint2, coordinatorEndpoint, ["genLevelCtrl"]);
await endpoint2.configureReporting("genLevelCtrl", payloadCurrentLevel);
}
}
await reporting.thermostatTemperature(endpoint1, { min: 0, max: 3600, change: 0 });
await reporting.thermostatOccupiedHeatingSetpoint(endpoint1, { min: 0, max: 3600, change: 0 });
await reporting.thermostatRunningState(endpoint1, { min: 0, max: 3600, change: 0 });
await reporting.thermostatSystemMode(endpoint1, { min: 0, max: 3600, change: 0 });
await reporting.thermostatTemperatureCalibration(endpoint1, { min: 0, max: 3600, change: 0 });
await reporting.thermostatKeypadLockMode(endpoint1, { min: 0, max: 3600, change: 0 });
const payload_oper_mode = [
{ attribute: "programingOperMode", minimumReportInterval: 0, maximumReportInterval: 3600, reportableChange: 0 },
];
await endpoint1.configureReporting("hvacThermostat", payload_oper_mode);
const payload_sensor_used = [
{ attribute: { ID: attrThermSensorUser, type: 0x30 }, minimumReportInterval: 0, maximumReportInterval: 3600, reportableChange: 0 },
];
await endpoint1.configureReporting("hvacThermostat", payload_sensor_used);
const payload_deadzone = [{ attribute: { ID: 0x0019, type: 0x28 }, minimumReportInterval: 0, maximumReportInterval: 3600, reportableChange: 0 }];
await endpoint1.configureReporting("hvacThermostat", payload_deadzone);
const payload_min = [{ attribute: { ID: 0x0015, type: 0x29 }, minimumReportInterval: 0, maximumReportInterval: 3600, reportableChange: 0 }];
await endpoint1.configureReporting("hvacThermostat", payload_min);
const payload_max = [{ attribute: { ID: 0x0016, type: 0x29 }, minimumReportInterval: 0, maximumReportInterval: 3600, reportableChange: 0 }];
await endpoint1.configureReporting("hvacThermostat", payload_max);
if (definition.model !== model_r01 && definition.model !== model_r06 && definition.model !== model_r0b) {
const payload_outdoor = [{ attribute: { ID: 0x0001, type: 0x29 }, minimumReportInterval: 0, maximumReportInterval: 3600, reportableChange: 0 }];
await endpoint1.configureReporting("hvacThermostat", payload_outdoor);
}
const payload_frost_protect = [
{
attribute: { ID: attrThermFrostProtect, type: 0x29 },
minimumReportInterval: 0,
maximumReportInterval: 3600,
reportableChange: 0,
},
];
await endpoint1.configureReporting("hvacThermostat", payload_frost_protect);
const payload_heat_protect = [
{ attribute: { ID: attrThermHeatProtect, type: 0x29 }, minimumReportInterval: 0, maximumReportInterval: 3600, reportableChange: 0 },
];
await endpoint1.configureReporting("hvacThermostat", payload_heat_protect);
if (definition.model === model_r03 || definition.model === model_r04 || definition.model === model_r07 || definition.model === modelR0c) {
const payload_eco_mode = [
{ attribute: { ID: attrThermEcoMode, type: 0x30 }, minimumReportInterval: 0, maximumReportInterval: 3600, reportableChange: 0 },
];
await endpoint1.configureReporting("hvacThermostat", payload_eco_mode);
const payload_eco_mode_heat_temp = [
{
attribute: { ID: attrThermEcoModeHeatTemperature, type: 0x29 },
minimumReportInterval: 0,
maximumReportInterval: 3600,
reportableChange: 0,
},
];
await endpoint1.configureReporting("hvacThermostat", payload_eco_mode_heat_temp);
if (definition.model === model_r07) {
const payload_eco_mode_cool_temp = [
{
attribute: { ID: attrThermEcoModeCoolTemperature, type: 0x29 },
minimumReportInterval: 0,
maximumReportInterval: 3600,
reportableChange: 0,
},
];
await endpoint1.configureReporting("hvacThermostat", payload_eco_mode_cool_temp);
const payload_fan_control = [
{ attribute: { ID: attrFanCtrlControl, type: 0x10 }, minimumReportInterval: 0, maximumReportInterval: 3600, reportableChange: 0 },
];
await endpoint1.configureReporting("hvacFanCtrl", payload_fan_control);
await reporting.fanMode(endpoint1, { min: 0, max: 3600, change: 0 });
}
}
if (definition.model === model_r06) {
const payload_frost_protect_onoff = [
{ attribute: { ID: attrThermFrostProtectOnOff, type: 0x10 }, minimumReportInterval: 0, maximumReportInterval: 3600, reportableChange: 0 },
];
await endpoint1.configureReporting("hvacThermostat", payload_frost_protect_onoff);
const payload_sound = [
{ attribute: { ID: attrThermSound, type: 0x10 }, minimumReportInterval: 0, maximumReportInterval: 3600, reportableChange: 0 },
];
await endpoint1.configureReporting("hvacThermostat", payload_sound);
const payload_inversion = [
{ attribute: { ID: attrThermInversion, type: 0x10 }, minimumReportInterval: 0, maximumReportInterval: 3600, reportableChange: 0 },
];
await endpoint1.configureReporting("hvacThermostat", payload_inversion);
const payload_level = [
{ attribute: { ID: attrThermLevel, type: 0x30 }, minimumReportInterval: 0, maximumReportInterval: 3600, reportableChange: 0 },
];
await endpoint1.configureReporting("hvacThermostat", payload_level);
const payload_schedule_mode = [
{ attribute: { ID: attrThermScheduleMode, type: 0x30 }, minimumReportInterval: 0, maximumReportInterval: 3600, reportableChange: 0 },
];
await endpoint1.configureReporting("hvacThermostat", payload_schedule_mode);
}
if (definition.model === model_r09) {
const payload_inversion = [
{ attribute: { ID: attrThermInversion, type: 0x10 }, minimumReportInterval: 0, maximumReportInterval: 3600, reportableChange: 0 },
];
await endpoint1.configureReporting("hvacThermostat", payload_inversion);
}
if (definition.model === model_r08 || definition.model === model_r09) {
const payload_eco_mode = [
{ attribute: { ID: attrThermEcoMode, type: 0x30 }, minimumReportInterval: 0, maximumReportInterval: 3600, reportableChange: 0 },
];
await endpoint1.configureReporting("hvacThermostat", payload_eco_mode);
const payload_ext_temp_calibration = [
{
attribute: { ID: attrThermExtTemperatureCalibration, type: 0x28 },
minimumReportInterval: 0,
maximumReportInterval: 3600,
reportableChange: 0,
},
];
await endpoint1.configureReporting("hvacThermostat", payload_ext_temp_calibration);
}
}
const energyResetExtend = {
energyReset: () => {
const exposes = [e.enum("energy_reset", ea.SET, ["reset"]).withDescription("Reset of accumulated energy")];
const toZigbee = [
{
key: ["energy_reset"],
convertSet: async (entity, key, value, meta) => {
await entity.command("seMetering", 0x80, {}, utils.getOptions(meta.mapped, entity));
},
},
];
// const fromZigbee = [];
return {
exposes,
fromZigbee: [],
toZigbee,
isModernExtend: true,
};
},
};
function electricityDeviceModel(args) {
const { name, lookup, cluster, attribute, zigbeeCommandOptions } = args;
const attributeKey = utils.isString(attribute) ? attribute : attribute.ID;
const access = ea[args.access ?? "ALL"];
const mExtend = m.enumLookup(args);
const toZigbee = [
{
key: [name],
convertSet: access & ea.SET
? async (entity, key, value, meta) => {
const payloadValue = utils.getFromLookup(value, lookup);
const payload = utils.isString(attribute)
? { [attribute]: payloadValue }
: { [attribute.ID]: { value: payloadValue, type: attribute.type } };
const ep = utils.determineEndpoint(entity, meta, cluster);
await ep.write(cluster, payload, zigbeeCommandOptions);
await ep.read("seMetering", ["divisor", "multiplier"]);
await ep.read("haElectricalMeasurement", ["acPowerDivisor", "acPowerMultiplier"]);
await ep.read("haElectricalMeasurement", ["acCurrentDivisor", "acCurrentMultiplier"]);
await ep.read("haElectricalMeasurement", ["acVoltageDivisor", "acVoltageMultiplier"]);
return { state: { [key]: value } };
}
: undefined,
convertGet: access & ea.GET
? async (entity, key, meta) => {
await utils
.determineEndpoint(entity, meta, cluster)
.read(cluster, [attributeKey], zigbeeCommandOptions);
}
: undefined,
},
];
return { ...mExtend, toZigbee, isModernExtend: true };
}
const electricityMeterExtend = {
elMeter: () => {
const exposes = [
e.numeric("energy_tier_1", ea.STATE_GET).withUnit("kWh").withDescription("Energy consumed at Tier 1"),
e.numeric("energy_tier_2", ea.STATE_GET).withUnit("kWh").withDescription("Energy consumed at Tier 2"),
e.numeric("energy_tier_3", ea.STATE_GET).withUnit("kWh").withDescription("Energy consumed at Tier 3"),
e.numeric("energy_tier_4", ea.STATE_GET).withUnit("kWh").withDescription("Energy consumed at Tier 4"),
e.text("model_name", ea.STATE_GET).withDescription("Meter Model Name"),
e.text("serial_number", ea.STATE_GET).withDescription("Meter Serial Number"),
e.text("date_release", ea.STATE_GET).withDescription("Meter Date Release"),
e.numeric("battery_life", ea.STATE_GET).withUnit("%").withDescription("Battery Life"),
e.binary("tamper", ea.STATE, true, false).withDescription("Tamper"),
e.binary("battery_low", ea.STATE, true, false).withDescription("Battery Low"),
e.numeric("device_address_preset", ea.STATE_SET).withDescription("Device Address").withValueMin(1).withValueMax(9999999),
e.text("device_password_preset", ea.STATE_SET).withDescription("Meter Password"),
e.numeric("device_measurement_preset", ea.ALL).withDescription("Measurement Period").withValueMin(1).withValueMax(255),
];
const toZigbee = [
tz.currenttier1summdelivered,
tz.currenttier2summdelivered,
tz.currenttier3summdelivered,
tz.currenttier4summdelivered,
{
key: ["model_name"],
convertGet: async (entity, key, meta) => {
await entity.read("seMetering", ["deviceName"]);
},
convertSet: async (entity, key, value, meta) => {
return await null;
},
},
{
key: ["serial_number"],
convertGet: async (entity, key, meta) => {
await entity.read("seMetering", ["meterSerialNumber"]);
},
convertSet: async (entity, key, value, meta) => {
return await null;
},
},
{
key: ["date_release"],
convertGet: async (entity, key, meta) => {
await entity.read("seMetering", ["dateRelease"]);
},
convertSet: async (entity, key, value, meta) => {
return await null;
},
},
{
key: ["battery_life"],
convertGet: async (entity, key, meta) => {
await entity.read("seMetering", ["remainingBattLife"]);
},
convertSet: async (entity, key, value, meta) => {
return await null;
},
},
{
key: ["device_address_preset"],
convertSet: async (entity, key, value, meta) => {
const device_address_preset = value;
await entity.write("seMetering", { deviceAddress: device_address_preset });
return { readAfterWriteTime: 250, state: { device_address_preset: value } };
},
},
{
key: ["device_password_preset"],
convertSet: async (entity, key, value, meta) => {
const device_password_preset = value.toString();
await entity.write("seMetering", { devicePassword: device_password_preset });
return { readAfterWriteTime: 250, state: { device_password_preset: value } };
},
},
{
key: ["device_measurement_preset"],
convertSet: async (entity, key, value, meta) => {
const device_measurement_preset = value;
await entity.write("seMetering", { readPeriod: device_measurement_preset });
return { readAfterWriteTime: 250, state: { device_measurement_preset: value } };
},
convertGet: async (entity, key, meta) => {
await entity.read("seMetering", ["readPeriod"]);
},
},
];
const fromZigbee = [
fz.metering,
{
cluster: "seMetering",
type: ["attributeReport", "readResponse"],
convert: (model, msg, publish, options, meta) => {
const result = {};
if (msg.data.deviceName !== undefined) {
const data = msg.data.deviceName;
result.model_name = data.toString();
}
return result;
},
},
{
cluster: "seMetering",
type: ["attributeReport", "readResponse"],
convert: (model, msg, publish, options, meta) => {
const result = {};
if (msg.data.meterSerialNumber !== undefined) {
const data = msg.data.meterSerialNumber;
result.serial_number = data.toString();
}
return result;
},
},
{
cluster: "seMetering",
type: ["attributeReport", "readResponse"],
convert: (model, msg, publish, options, meta) => {
const result = {};
if (msg.data.dateRelease !== undefined) {
const data = msg.data.dateRelease;
result.date_release = data.toString();
}
return result;
},
},
{
cluster: "seMetering",
type: ["attributeReport", "readResponse"],
convert: (model, msg, publish, options, meta) => {
const result = {};
if (msg.data.status !== undefined) {
const data = msg.data.status;
return {
battery_low: (data & (1 << 1)) > 0,
tamper: (data & (1 << 2)) > 0,
};
}
return result;
},
},
{
cluster: "seMetering",
type: ["attributeReport", "readResponse"],
convert: (model, msg, publish, options, meta) => {
const result = {};
if (msg.data.remainingBattLife !== undefined) {
const data = msg.data.remainingBattLife;
result.battery_life = data;
}
return result;
},
},
{
cluster: "seMetering",
type: ["readResponse"],
convert: (model, msg, publish, options, meta) => {
const result = {};
if (msg.data.readPeriod !== undefined) {
result.device_measurement_preset = msg.data.readPeriod; //data;
}
return result;
},
},
];
const configure = [
async (device, coordinatorEndpoint, definition) => {
const endpoint1 = device.getEndpoint(1);
await endpoint1.read("seMetering", ["currentTier1SummDelivered"]);
await endpoint1.read("seMetering", ["currentTier2SummDelivered"]);
await endpoint1.read("seMetering", ["currentTier3SummDelivered"]);
await endpoint1.read("seMetering", ["currentTier4SummDelivered"]);
await endpoint1.read("seMetering", ["meterSerialNumber"]);
await endpoint1.read("seMetering", ["deviceName"]);
await endpoint1.read("seMetering", ["readPeriod"]);
await endpoint1.read("seMetering", ["deviceModel"]);
await endpoint1.read("seMetering", ["dateRelease"]);
await endpoint1.read("seMetering", ["remainingBattLife", "status"]);
await reporting.bind(endpoint1, coordinatorEndpoint, ["seMetering"]);
await endpoint1.configureReporting("seMetering", [
{
attribute: "currentTier1SummDelivered",
minimumReportInterval: 0,
maximumReportInterval: 3600,
reportableChange: 0,
},
]);
await endpoint1.configureReporting("seMetering", [
{
attribute: "currentTier2SummDelivered",
minimumReportInterval: 0,
maximumReportInterval: 3600,
reportableChange: 0,
},
]);
await endpoint1.configureReporting("seMetering", [
{
attribute: "currentTier3SummDelivered",
minimumReportInterval: 0,
maximumReportInterval: 3600,
reportableChange: 0,
},
]);
await endpoint1.configureReporting("seMetering", [
{
attribute: "currentTier4SummDelivered",
minimumReportInterval: 0,
maximumReportInterval: 3600,
reportableChange: 0,
},
]);
await endpoint1.configureReporting("seMetering", [
{
attribute: "currentSummDelivered",
minimumReportInterval: 0,
maximumReportInterval: 3600,
reportableChange: 0,
},
]);
await endpoint1.configureReporting("seMetering", [
{
attribute: "status",
minimumReportInterval: 0,
maximumReportInterval: 3600,
reportableChange: 0,
},
]);
await endpoint1.configureReporting("seMetering", [
{
attribute: "remainingBattLife",
minimumReportInterval: 0,
maximumReportInterval: 3600,
reportableChange: 0,
},
]);
await endpoint1.configureReporting("seMetering", [
{
attribute: "meterSerialNumber",
minimumReportInterval: 0,
maximumReportInterval: 3600,
reportableChange: 0,
},
]);
await endpoint1.configureReporting("seMetering", [
{
attribute: "dateRelease",
minimumReportInterval: 0,
maximumReportInterval: 3600,
reportableChange: 0,
},
]);
await endpoint1.configureReporting("seMetering", [
{
attribute: "deviceName",
minimumReportInterval: 0,
maximumReportInterval: 3600,
reportableChange: 0,
},
]);
},
];
return {
exposes,
fromZigbee,
toZigbee,
configure,
isModernExtend: true,
};
},
};
function waterPreset() {
const exposes = [
e
.composite("preset", "preset", ea.SET)
.withFeature(e
.numeric("hot_water_preset", ea.SET)
.withValueMin(0)
.withValueMax(99999999)
.withValueStep(1)
.withUnit("L")
.withDescription("Preset hot water"))
.withFeature(e
.numeric("cold_water_preset", ea.SET)
.withValueMin(0)
.withValueMax(99999999)
.withValueStep(1)
.withUnit("L")
.withDescription("Preset cold water"))
.withFeature(e
.numeric("step_water_preset", ea.SET)
.withValueMin(1)
.withValueMax(100)
.withValueStep(1)
.withUnit("L")
.withDescription("Preset step water")),
];
const toZigbee = [
{
key: ["preset"],
convertSet: async (entity, key, value, meta) => {
const endpoint = meta.device.getEndpoint(3);
const values = {
// biome-ignore lint/suspicious/noExplicitAny: ignored using `--suppress`
hot_water: value.hot_water_preset,
// biome-ignore lint/suspicious/noExplicitAny: ignored using `--suppress`
cold_water: value.cold_water_preset,
// biome-ignore lint/suspicious/noExplicitAny: ignored using `--suppress`
step_water: value.step_water_preset,
};
if (values.hot_water != null && values.hot_water >= 0) {
const hot_water_preset = Number.parseInt(values.hot_water, 10);
await endpoint.write("seMetering", { 61440: { value: hot_water_preset, type: 0x23 } });
}
if (values.cold_water != null && values.cold_water >= 0) {
const cold_water_preset = Number.parseInt(values.cold_water, 10);
await endpoint.write("seMetering", { 61441: { value: cold_water_preset, type: 0x23 } });
}
if (values.step_water != null && values.step_water >= 0) {
const step_water_preset = Number.parseInt(values.step_water, 10);
await endpoint.write("seMetering", { 61442: { value: step_water_preset, type: 0x21 } });
}
},
},
];
return { toZigbee, exposes, isModernExtend: true };
}
const air_extend = {
led_brightness: () => {
const exposes = [e.numeric("brightness", ea.ALL).withValueMin(0).withValueMax(255).withDescription("LED brightness")];
const toZigbee = [
{
key: ["brightness"],
convertSet: async (entity, key, value, meta) => {
await entity.command("genLevelCtrl", "moveToLevel", { level: value, transtime: 0, optionsMask: 0, optionsOverride: 0 }, utils.getOptions(meta.mapped, entity));
return { state: { brightness: value } };
},
convertGet: async (entity, key, meta) => {
await entity.read("genLevelCtrl", ["currentLevel"]);
},
},
];
const fromZigbee = [
{
cluster: "genLevelCtrl",
type: ["attributeReport", "readResponse"],
convert: (model, msg, publish, options, meta) => {
const result = {};
if (Object.hasOwn(msg.data, "currentLevel")) {
const data = msg.data.currentLevel;
result.brightness = data;
}
return result;
},
},
];
return {
exposes,
fromZigbee,
toZigbee,
isModernExtend: true,
};
},
features_sensors: () => {
const exposes = [
e.composite("features_sensors", "features_sensors", ea.SET).withFeature(e.enum("features", ea.STATE_SET, switchFeatures)),
];
const toZigbee = [
{
key: ["features_sensors"],
convertSet: async (entity, key, rawValue, meta) => {
const endpoint = meta.device.getEndpoint(1);
// biome-ignore lint/suspicious/noExplicitAny: ignored using `--suppress`
const value = rawValue.features;
if (value != null) {
const lookup = {
nothing: 0,
co2_forced_calibration: 1,
co2_factory_reset: 2,
bind_reset: 3,
};
const value_lookup = utils.getFromLookup(value, lookup);
//logger.logger.info("value_lookup: " + value_lookup);
if (value_lookup >= 1 && value_lookup <= 3) {
await endpoint.write("hvacUserInterfaceCfg", { [attrFeaturesSensors]: { value: value_lookup, type: 0x30 } });
return {
state: { [key]: value },
};
}
}
},
convertGet: async (entity, key, meta) => {
await entity.read("hvacUserInterfaceCfg", [attrFeaturesSensors]);
},
},
];
return {
exposes,
fromZigbee: [],
toZigbee,
isModernExtend: true,
};
},
};
exports.definitions = [
{
zigbeeModel: ["Tuya_CO2Sensor_r01"],
model: "SLACKY_DIY_CO2_SENSOR_R01",
vendor: "Slacky-DIY",
description: "Tuya CO2 sensor with custom Firmware",
extend: [m.co2({ reporting: ppmReporting })],
ota: true,
},
{
zigbeeModel: ["Tuya_CO2Sensor_r02"],
model: "SLACKY_DIY_CO2_SENSOR_R02",
vendor: "Slacky-DIY",
description: "Tuya CO2 sensor with custom Firmware",
extend: [
m.co2({ reporting: ppmReporting }),
m.numeric({
name: "formaldehyde",
access: "STATE_GET",
cluster: "msFormaldehyde",
attribute: "measuredValue",
reporting: ppmReporting,
unit: "ppm",
scale: 0.000001,
precision: 2,
description: "Measured Formaldehyde value",
}),
m.numeric({
name: "voc",
access: "STATE_GET",
cluster: "genAnalogInput",
attribute: "presentValue",
reporting: ppmReporting,
unit: "ppm",
scale: 0.000001,
precision: 2,
description: "Measured VOC value",
}),
m.temperature(),
m.humidity(),
],
ota: true,
},
{
zigbeeModel: ["Watermeter_TLSR8258"],
model: "Watermeter_TLSR8258",
vendor: "Slacky-DIY",
description: "Water Meter",
configure: async (device, coordinatorEndpoint, logger) => {
const thirdEndpoint = device.getEndpoint(3);
await thirdEndpoint.read("seMetering", [0xf000, 0xf001, 0xf002]);
},
extend: [
m.deviceEndpoints({
endpoints: {
"1": 1,
"2": 2,
"3": 3,
"4": 4,
"5": 5,
},
}),
m.iasZoneAlarm({ zoneType: "water_leak", zoneAttributes: ["alarm_1"] }),
m.battery({
voltage: true,
voltageReporting: true,
percentageReportingConfig: batteryReporting,
voltageReportingConfig: batteryReporting,
}),
m.enumLookup({
name: "switch_actions",
endpointName: "4",
lookup: { on_off: 0, off_on: 1, toggle: 2 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch 1",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "5",
lookup: { on_off: 0, off_on: 1, toggle: 2 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch 2",
}),
m.numeric({
name: "volume",
endpointNames: ["1"],
access: "STATE_GET",
cluster: "seMetering",
attribute: "currentSummDelivered",
reporting: { min: 0, max: 300, change: 0 },
unit: "L",
description: "Hot water",
}),
m.numeric({
name: "volume",
endpointNames: ["2"],
access: "STATE_GET",
cluster: "seMetering",
attribute: "currentSummDelivered",
reporting: { min: 0, max: 300, change: 0 },
unit: "L",
description: "Cold water",
}),
waterPreset(),
],
ota: true,
meta: { multiEndpoint: true },
},
{
zigbeeModel: ["Smoke_Sensor_TLSR8258"],
model: "Smoke Sensor TLSR8258",
vendor: "Slacky-DIY",
description: "Smoke Sensor on Rubezh IP 212-50M2 base",
extend: [
m.iasZoneAlarm({ zoneType: "smoke", zoneAttributes: ["alarm_1", "tamper", "battery_low"] }),
m.battery({
voltage: true,
voltageReporting: true,
percentageReportingConfig: batteryReporting,
voltageReportingConfig: batteryReporting,
}),
m.commandsOnOff(),
m.enumLookup({
access: "STATE",
name: "switch_type",
lookup: { toggle: 0 },
cluster: "genOnOffSwitchCfg",
attribute: "switchType",
description: "Type switch",
}),
m.enumLookup({
name: "switch_actions",
lookup: { on_off: 0, off_on: 1, toggle: 2 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
],
ota: true,
},
{
zigbeeModel: ["ElectricityMeter_DIY"],
model: "Electricity Meter TLSR8258",
vendor: "Slacky-DIY",
description: "Electricity Meter via optical port",
extend: [
m.deviceAddCustomCluster("seMetering", {
name: "seMetering",
ID: 0x0702,
attributes: {
deviceModel: {
name: "deviceModel",
ID: attrElCityMeterModelPreset,
type: 0x30,
write: true,
max: 0xff,
},
deviceAddress: {
name: "deviceAddress",
ID: attrElCityMeterAddressPreset,
type: 0x23,
write: true,
max: 0xffffffff,
},
readPeriod: {
name: "readPeriod",
ID: attrElCityMeterMeasurementPreset,
type: 0x20,
write: true,
max: 0xff,
},
dateRelease: {
name: "dateRelease",
ID: attrElCityMeterDateRelease,
type: 0x41,
},
deviceName: {
name: "deviceName",
ID: attrElCityMeterModelName,
type: 0x41,
},
devicePassword: {
name: "devicePassword",
ID: attrElCityMeterPasswordPreset,
write: true,
type: 0x41,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceTemperature(),
m.electricityMeter(),
electricityMeterExtend.elMeter(),
electricityDeviceModel({
name: "device_model_preset",
access: "STATE_SET",
lookup: {
no_device: 0,
"KASKAD-1-MT (MIRTEK)": 1,
"KASKAD-11-C1": 2,
"MERCURY-206": 3,
"ENERGOMERA-CE102M": 4,
"ENERGOMERA-CE208BY": 5,
"NEVA-MT124": 6,
"NARTIS-100": 7,
"NARTIS-I100": 8,
},
cluster: "seMetering",
attribute: "deviceModel",
description: "Device Model",
}),
],
ota: true,
},
{
zigbeeModel: ["ElectricityMeterABC_DIY"],
model: "ElectricityMeter-ABC-DIY",
vendor: "Slacky-DIY",
description: "Three phase Electricity Meter via optical port",
extend: [
m.deviceAddCustomCluster("seMetering", {
name: "seMetering",
ID: 0x0702,
attributes: {
deviceModel: {
name: "deviceModel",
ID: attrElCityMeterModelPreset,
type: 0x30,
write: true,
max: 0xff,
},
deviceAddress: {
name: "deviceAddress",
ID: attrElCityMeterAddressPreset,
type: 0x23,
write: true,
max: 0xffffffff,
},
readPeriod: {
name: "readPeriod",
ID: attrElCityMeterMeasurementPreset,
type: 0x20,
write: true,
max: 0xff,
},
dateRelease: {
name: "dateRelease",
ID: attrElCityMeterDateRelease,
type: 0x41,
},
deviceName: {
name: "deviceName",
ID: attrElCityMeterModelName,
type: 0x41,
},
devicePassword: {
name: "devicePassword",
ID: attrElCityMeterPasswordPreset,
write: true,
type: 0x41,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceTemperature(),
m.electricityMeter({ threePhase: true }),
electricityMeterExtend.elMeter(),
electricityDeviceModel({
name: "device_model_preset",
access: "STATE_SET",
lookup: {
no_device: 0,
"NARTIS-I300": 1,
},
cluster: "seMetering",
attribute: "deviceModel",
description: "Device Model",
}),
],
ota: true,
},
{
zigbeeModel: ["Tuya_Thermostat_r01"],
model: "THERM_SLACKY_DIY_R01",
vendor: "Slacky-DIY",
description: "Tuya Thermostat for Floor Heating with custom Firmware",
endpoint: (device) => {
return { day: 1, night: 2 };
},
fromZigbee: localFromZigbeeThermostat,
toZigbee: localToZigbeeThermostat,
configure: configureCommon,
extend: [
m.deviceAddCustomCluster("hvacThermostat", {
name: "hvacThermostat",
ID: 0x0201,
attributes: {
localTemperatureCalibration: {
name: "localTemperatureCalibration",
ID: 0x0010,
type: 0x28,
write: true,
max: 0xff,
},
minSetpointDeadBand: {
name: "minSetpointDeadBand",
ID: 0x0019,
type: 0x28,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
],
exposes: [
e.binary("child_lock", ea.ALL, "LOCK", "UNLOCK").withDescription("Enables/disables physical input on the device"),
e.programming_operation_mode(["setpoint", "schedule"]).withDescription("Setpoint or Schedule mode"),
e.enum("sensor", ea.ALL, switchSensorUsed).withDescription("Select temperature sensor to use"),
e
.numeric("deadzone_temperature", ea.ALL)
.withDescription("The delta between local_temperature and current_heating_setpoint to trigger activity")
.withUnit("°C")
.withValueMin(1)
.withValueMax(5)
.withValueStep(1),
e
.numeric("max_heat_setpoint_limit", ea.ALL)
.withDescription("Maximum Heating set point limit")
.withUnit("°C")
.withValueMin(15)
.withValueMax(45)
.withValueStep(1),
e
.climate()
.withLocalTemperature()
.withSetpoint("occupied_heating_setpoint", 5, 45, 1)
.withLocalTemperatureCalibration(-9, 9, 1)
.withSystemMode(["off", "heat"])
.withRunningState(["idle", "heat"], ea.STATE)
.withWeeklySchedule(["heat"], ea.ALL),
e.text("schedule_monday", ea.STATE).withDescription("Schedule for the working week"),
e.text("schedule_saturday", ea.STATE).withDescription("Saturday's schedule"),
e.text("schedule_sunday", ea.STATE).withDescription("Sunday's schedule"),
],
meta: {},
ota: true,
},
{
zigbeeModel: ["Tuya_Thermostat_r02"],
model: "THERM_SLACKY_DIY_R02",
vendor: "Slacky-DIY",
description: "Tuya Thermostat for Floor Heating with custom Firmware",
endpoint: (device) => {
return { day: 1, night: 2 };
},
fromZigbee: localFromZigbeeThermostat,
toZigbee: localToZigbeeThermostat,
configure: configureCommon,
extend: [
m.deviceAddCustomCluster("hvacThermostat", {
name: "hvacThermostat",
ID: 0x0201,
attributes: {
localTemperatureCalibration: {
name: "localTemperatureCalibration",
ID: 0x0010,
type: 0x28,
write: true,
max: 0xff,
},
minSetpointDeadBand: {
name: "minSetpointDeadBand",
ID: 0x0019,
type: 0x28,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
],
exposes: [
e.binary("child_lock", ea.ALL, "LOCK", "UNLOCK").withDescription("Enables/disables physical input on the device"),
e.programming_operation_mode(["setpoint", "schedule"]).withDescription("Setpoint or Schedule mode"),
e.enum("sensor", ea.ALL, switchSensorUsed).withDescription("Select temperature sensor to use"),
e
.numeric("deadzone_temperature", ea.ALL)
.withDescription("The delta between local_temperature and current_heating_setpoint to trigger activity")
.withUnit("°C")
.withValueMin(1)
.withValueMax(5)
.withValueStep(1),
e
.numeric("min_heat_setpoint_limit", ea.ALL)
.withUnit("°C")
.withDescription("Minimum Heating set point limit")
.withValueMin(5)
.withValueMax(15)
.withValueStep(1),
e
.numeric("max_heat_setpoint_limit", ea.ALL)
.withDescription("Maximum Heating set point limit")
.withUnit("°C")
.withValueMin(15)
.withValueMax(45)
.withValueStep(1),
e
.numeric("frost_protect", ea.ALL)
.withUnit("°C")
.withDescription("Protection against minimum freezing temperature")
.withValueMin(0)
.withValueMax(10)
.withValueStep(1),
e
.numeric("heat_protect", ea.ALL)
.withUnit("°C")
.withDescription("Protection against maximum heating temperature")
.withValueMin(25)
.withValueMax(70)
.withValueStep(1),
e.numeric("outdoor_temperature", ea.STATE_GET).withUnit("°C").withDescription("Current temperature measured from the floor outer sensor"),
e
.climate()
.withLocalTemperature()
.withSetpoint("occupied_heating_setpoint", 5, 45, 0.5)
.withLocalTemperatureCalibration(-9, 9, 1)
.withSystemMode(["off", "heat"])
.withRunningState(["idle", "heat"], ea.STATE)
.withWeeklySchedule(["heat"], ea.ALL),
e.text("schedule_monday", ea.STATE).withDescription("Monday's schedule"),
e.text("schedule_tuesday", ea.STATE).withDescription("Tuesday's schedule"),
e.text("schedule_wednesday", ea.STATE).withDescription("Wednesday's schedule"),
e.text("schedule_thursday", ea.STATE).withDescription("Thursday's schedule"),
e.text("schedule_friday", ea.STATE).withDescription("Friday's schedule"),
e.text("schedule_saturday", ea.STATE).withDescription("Saturday's schedule"),
e.text("schedule_sunday", ea.STATE).withDescription("Sunday's schedule"),
],
meta: {},
ota: true,
},
{
zigbeeModel: ["Tuya_Thermostat_r03"],
model: "THERM_SLACKY_DIY_R03",
vendor: "Slacky-DIY",
description: "Tuya Thermostat for Floor Heating with custom Firmware",
endpoint: (device) => {
return { day: 1, night: 2 };
},
fromZigbee: localFromZigbeeThermostat,
toZigbee: localToZigbeeThermostat,
configure: configureCommon,
extend: [
m.deviceAddCustomCluster("hvacThermostat", {
name: "hvacThermostat",
ID: 0x0201,
attributes: {
localTemperatureCalibration: {
name: "localTemperatureCalibration",
ID: 0x0010,
type: 0x28,
write: true,
max: 0xff,
},
minSetpointDeadBand: {
name: "minSetpointDeadBand",
ID: 0x0019,
type: 0x28,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
],
exposes: [
e.binary("child_lock", ea.ALL, "LOCK", "UNLOCK").withDescription("Enables/disables physical input on the device"),
e.programming_operation_mode(["setpoint", "schedule"]).withDescription("Setpoint or Schedule mode"),
e.enum("sensor", ea.ALL, switchSensorUsed).withDescription("Select temperature sensor to use"),
e
.numeric("deadzone_temperature", ea.ALL)
.withDescription("The delta between local_temperature and current_heating_setpoint to trigger activity")
.withUnit("°C")
.withValueMin(1)
.withValueMax(5)
.withValueStep(1),
e
.numeric("min_heat_setpoint_limit", ea.ALL)
.withUnit("°C")
.withDescription("Minimum Heating set point limit")
.withValueMin(5)
.withValueMax(15)
.withValueStep(1),
e
.numeric("max_heat_setpoint_limit", ea.ALL)
.withDescription("Maximum Heating set point limit")
.withUnit("°C")
.withValueMin(15)
.withValueMax(45)
.withValueStep(1),
e
.numeric("frost_protect", ea.ALL)
.withUnit("°C")
.withDescription("Protection against minimum freezing temperature")
.withValueMin(0)
.withValueMax(10)
.withValueStep(1),
e
.numeric("heat_protect", ea.ALL)
.withUnit("°C")
.withDescription("Protection against maximum heating temperature")
.withValueMin(25)
.withValueMax(70)
.withValueStep(1),
e.numeric("brightness", ea.ALL).withValueMin(0).withValueMax(8).withDescription("Screen brightness 06:00 - 22:00").withEndpoint("day"),
e.numeric("brightness", ea.ALL).withValueMin(0).withValueMax(8).withDescription("Screen brightness 22:00 - 06:00").withEndpoint("night"),
e.binary("eco_mode", ea.ALL, "On", "Off").withDescription("On/Off Eco Mode"),
e
.numeric("eco_mode_heat_temperature", ea.ALL)
.withUnit("°C")
.withDescription("Set heat temperature in eco mode")
.withValueMin(5)
.withValueMax(45)
.withValueStep(1),
e.numeric("outdoor_temperature", ea.STATE_GET).withUnit("°C").withDescription("Current temperature measured from the floor outer sensor"),
e
.climate()
.withLocalTemperature()
.withSetpoint("occupied_heating_setpoint", 5, 45, 0.5)
.withLocalTemperatureCalibration(-9, 9, 1)
.withSystemMode(["off", "heat"])
.withRunningState(["idle", "heat"], ea.STATE)
.withWeeklySchedule(["heat"], ea.ALL),
e.text("schedule_monday", ea.STATE).withDescription("Monday's schedule"),
e.text("schedule_tuesday", ea.STATE).withDescription("Tuesday's schedule"),
e.text("schedule_wednesday", ea.STATE).withDescription("Wednesday's schedule"),
e.text("schedule_thursday", ea.STATE).withDescription("Thursday's schedule"),
e.text("schedule_friday", ea.STATE).withDescription("Friday's schedule"),
e.text("schedule_saturday", ea.STATE).withDescription("Saturday's schedule"),
e.text("schedule_sunday", ea.STATE).withDescription("Sunday's schedule"),
],
meta: {},
ota: true,
},
{
zigbeeModel: ["Tuya_Thermostat_r04"],
model: "THERM_SLACKY_DIY_R04",
vendor: "Slacky-DIY",
description: "Tuya Thermostat for Floor Heating with custom Firmware",
endpoint: (device) => {
return { day: 1, night: 2 };
},
fromZigbee: localFromZigbeeThermostat,
toZigbee: localToZigbeeThermostat,
configure: configureCommon,
extend: [
m.deviceAddCustomCluster("hvacThermostat", {
name: "hvacThermostat",
ID: 0x0201,
attributes: {
localTemperatureCalibration: {
name: "localTemperatureCalibration",
ID: 0x0010,
type: 0x28,
write: true,
max: 0xff,
},
minSetpointDeadBand: {
name: "minSetpointDeadBand",
ID: 0x0019,
type: 0x28,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
],
exposes: [
e.binary("child_lock", ea.ALL, "LOCK", "UNLOCK").withDescription("Enables/disables physical input on the device"),
e.programming_operation_mode(["setpoint", "schedule"]).withDescription("Setpoint or Schedule mode"),
e.enum("sensor", ea.ALL, switchSensorUsed).withDescription("Select temperature sensor to use"),
e
.numeric("deadzone_temperature", ea.ALL)
.withDescription("The delta between local_temperature and current_heating_setpoint to trigger activity")
.withUnit("°C")
.withValueMin(1)
.withValueMax(5)
.withValueStep(1),
e
.numeric("min_heat_setpoint_limit", ea.ALL)
.withUnit("°C")
.withDescription("Minimum Heating set point limit")
.withValueMin(5)
.withValueMax(15)
.withValueStep(1),
e
.numeric("max_heat_setpoint_limit", ea.ALL)
.withDescription("Maximum Heating set point limit")
.withUnit("°C")
.withValueMin(15)
.withValueMax(45)
.withValueStep(1),
e
.numeric("frost_protect", ea.ALL)
.withUnit("°C")
.withDescription("Protection against minimum freezing temperature")
.withValueMin(0)
.withValueMax(10)
.withValueStep(1),
e
.numeric("heat_protect", ea.ALL)
.withUnit("°C")
.withDescription("Protection against maximum heating temperature")
.withValueMin(25)
.withValueMax(70)
.withValueStep(1),
e.numeric("brightness", ea.ALL).withValueMin(0).withValueMax(9).withDescription("Screen brightness").withEndpoint("day"),
e.binary("eco_mode", ea.ALL, "On", "Off").withDescription("On/Off Eco Mode"),
e
.numeric("eco_mode_heat_temperature", ea.ALL)
.withUnit("°C")
.withDescription("Set heat temperature in eco mode")
.withValueMin(5)
.withValueMax(45)
.withValueStep(1),
e.numeric("outdoor_temperature", ea.STATE_GET).withUnit("°C").withDescription("Current temperature measured from the floor outer sensor"),
e
.climate()
.withLocalTemperature()
.withSetpoint("occupied_heating_setpoint", 5, 45, 0.5)
.withLocalTemperatureCalibration(-9, 9, 1)
.withSystemMode(["off", "heat"])
.withRunningState(["idle", "heat"], ea.STATE)
.withWeeklySchedule(["heat"], ea.ALL),
e.text("schedule_monday", ea.STATE).withDescription("Monday's schedule"),
e.text("schedule_tuesday", ea.STATE).withDescription("Tuesday's schedule"),
e.text("schedule_wednesday", ea.STATE).withDescription("Wednesday's schedule"),
e.text("schedule_thursday", ea.STATE).withDescription("Thursday's schedule"),
e.text("schedule_friday", ea.STATE).withDescription("Friday's schedule"),
e.text("schedule_saturday", ea.STATE).withDescription("Saturday's schedule"),
e.text("schedule_sunday", ea.STATE).withDescription("Sunday's schedule"),
],
meta: {},
ota: true,
},
{
zigbeeModel: ["Tuya_Thermostat_r05"],
model: "THERM_SLACKY_DIY_R05",
vendor: "Slacky-DIY",
description: "Tuya Thermostat for Floor Heating with custom Firmware",
endpoint: (device) => {
return { day: 1, night: 2 };
},
fromZigbee: localFromZigbeeThermostat,
toZigbee: localToZigbeeThermostat,
configure: configureCommon,
extend: [
m.deviceAddCustomCluster("hvacThermostat", {
name: "hvacThermostat",
ID: 0x0201,
attributes: {
localTemperatureCalibration: {
name: "localTemperatureCalibration",
ID: 0x0010,
type: 0x28,
write: true,
max: 0xff,
},
minSetpointDeadBand: {
name: "minSetpointDeadBand",
ID: 0x0019,
type: 0x28,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
],
exposes: [
e.binary("child_lock", ea.ALL, "LOCK", "UNLOCK").withDescription("Enables/disables physical input on the device"),
e.programming_operation_mode(["setpoint", "schedule"]).withDescription("Setpoint or Schedule mode"),
e.enum("sensor", ea.ALL, switchSensorUsed).withDescription("Select temperature sensor to use"),
e
.numeric("deadzone_temperature", ea.ALL)
.withDescription("The delta between local_temperature and current_heating_setpoint to trigger activity")
.withUnit("°C")
.withValueMin(1)
.withValueMax(5)
.withValueStep(1),
e
.numeric("min_heat_setpoint_limit", ea.ALL)
.withUnit("°C")
.withDescription("Minimum Heating set point limit")
.withValueMin(5)
.withValueMax(15)
.withValueStep(1),
e
.numeric("max_heat_setpoint_limit", ea.ALL)
.withDescription("Maximum Heating set point limit")
.withUnit("°C")
.withValueMin(15)
.withValueMax(45)
.withValueStep(1),
e
.numeric("heat_protect", ea.ALL)
.withUnit("°C")
.withDescription("Protection against maximum heating temperature")
.withValueMin(25)
.withValueMax(70)
.withValueStep(1),
e.numeric("outdoor_temperature", ea.STATE_GET).withUnit("°C").withDescription("Current temperature measured from the floor outer sensor"),
e
.climate()
.withLocalTemperature()
.withSetpoint("occupied_heating_setpoint", 5, 45, 0.5)
.withLocalTemperatureCalibration(-9, 9, 1)
.withSystemMode(["off", "heat"])
.withRunningState(["idle", "heat"], ea.STATE)
.withWeeklySchedule(["heat"], ea.ALL),
e.text("schedule_monday", ea.STATE).withDescription("Monday's schedule"),
e.text("schedule_tuesday", ea.STATE).withDescription("Tuesday's schedule"),
e.text("schedule_wednesday", ea.STATE).withDescription("Wednesday's schedule"),
e.text("schedule_thursday", ea.STATE).withDescription("Thursday's schedule"),
e.text("schedule_friday", ea.STATE).withDescription("Friday's schedule"),
e.text("schedule_saturday", ea.STATE).withDescription("Saturday's schedule"),
e.text("schedule_sunday", ea.STATE).withDescription("Sunday's schedule"),
],
meta: {},
ota: true,
},
{
zigbeeModel: ["Tuya_Thermostat_r06"],
model: "THERM_SLACKY_DIY_R06",
vendor: "Slacky-DIY",
description: "Tuya Thermostat for Floor Heating with custom Firmware",
endpoint: (device) => {
return { day: 1, night: 2 };
},
fromZigbee: localFromZigbeeThermostat,
toZigbee: localToZigbeeThermostat,
configure: configureCommon,
extend: [
m.deviceAddCustomCluster("hvacThermostat", {
name: "hvacThermostat",
ID: 0x0201,
attributes: {
localTemperatureCalibration: {
name: "localTemperatureCalibration",
ID: 0x0010,
type: 0x28,
write: true,
max: 0xff,
},
minSetpointDeadBand: {
name: "minSetpointDeadBand",
ID: 0x0019,
type: 0x28,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
],
exposes: [
e.binary("child_lock", ea.ALL, "LOCK", "UNLOCK").withDescription("Enables/disables physical input on the device"),
e.binary("sound", ea.ALL, "On", "Off").withDescription("Sound On/Off"),
e.binary("relay_type", ea.ALL, "NC", "NO").withDescription("Relay type NC/NO"),
e.enum("brightness_level", ea.ALL, ["Off", "Low", "Medium", "High"]).withDescription("Screen brightness"),
e.programming_operation_mode(["setpoint", "schedule"]).withDescription("Setpoint or Schedule mode"),
e.enum("sensor", ea.ALL, switchSensorUsed).withDescription("Select temperature sensor to use"),
e
.numeric("hysteresis_temperature", ea.ALL)
.withDescription("The delta between local_temperature and current_heating_setpoint to trigger activity")
.withUnit("°C")
.withValueMin(0.5)
.withValueMax(10)
.withValueStep(0.5),
e
.numeric("max_heat_setpoint_limit", ea.ALL)
.withDescription("Maximum Heating set point limit")
.withUnit("°C")
.withValueMin(15)
.withValueMax(95)
.withValueStep(1),
e.binary("frost_protect_on_off", ea.ALL, "On", "Off").withDescription("Frost protection"),
e
.numeric("heat_protect", ea.ALL)
.withUnit("°C")
.withDescription("Protection against maximum heating temperature")
.withValueMin(35)
.withValueMax(60)
.withValueStep(1),
e
.climate()
.withLocalTemperature()
.withSetpoint("occupied_heating_setpoint", 5, 45, 0.5)
.withLocalTemperatureCalibration(-9.9, 9.9, 0.1)
.withSystemMode(["off", "heat"])
.withRunningState(["idle", "heat"], ea.STATE)
.withWeeklySchedule(["heat"], ea.ALL),
e.text("schedule_monday", ea.STATE).withDescription("Schedule for the working week"),
e.text("schedule_sunday", ea.STATE).withDescription("Weekend schedule"),
e.enum("schedule_mode", ea.ALL, ["Off", "5+2", "6+1", "7"]).withDescription("Schedule mode"),
e.enum("settings_reset", ea.SET, ["Default"]).withDescription("Default settings"),
],
meta: {},
ota: true,
},
{
zigbeeModel: ["Tuya_Thermostat_r07"],
model: "THERM_SLACKY_DIY_R07",
vendor: "Slacky-DIY",
description: "Tuya Thermostat for Floor Heating with custom Firmware",
endpoint: (device) => {
return { day: 1, night: 2 };
},
fromZigbee: localFromZigbeeThermostat,
toZigbee: localToZigbeeThermostat,
configure: configureCommon,
extend: [
m.deviceAddCustomCluster("hvacThermostat", {
name: "hvacThermostat",
ID: 0x0201,
attributes: {
localTemperatureCalibration: {
name: "localTemperatureCalibration",
ID: 0x0010,
type: 0x28,
write: true,
max: 0xff,
},
minSetpointDeadBand: {
name: "minSetpointDeadBand",
ID: 0x0019,
type: 0x28,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
],
exposes: [
e.binary("child_lock", ea.ALL, "LOCK", "UNLOCK").withDescription("Enables/disables physical input on the device"),
e.programming_operation_mode(["setpoint", "schedule"]).withDescription("Setpoint or Schedule mode"),
e
.numeric("deadzone_temperature", ea.ALL)
.withDescription("The delta between local_temperature and current_heating_setpoint to trigger activity")
.withUnit("°C")
.withValueMin(1)
.withValueMax(5)
.withValueStep(1),
e
.numeric("min_heat_setpoint_limit", ea.ALL)
.withUnit("°C")
.withDescription("Minimum Heating set point limit")
.withValueMin(5)
.withValueMax(15)
.withValueStep(1),
e
.numeric("max_heat_setpoint_limit", ea.ALL)
.withDescription("Maximum Heating set point limit")
.withUnit("°C")
.withValueMin(15)
.withValueMax(45)
.withValueStep(1),
e.binary("eco_mode", ea.ALL, "On", "Off").withDescription("On/Off Eco Mode"),
e
.numeric("eco_mode_cool_temperature", ea.ALL)
.withUnit("°C")
.withDescription("Set cool temperature in eco mode")
.withValueMin(10)
.withValueMax(30)
.withValueStep(1),
e
.numeric("eco_mode_heat_temperature", ea.ALL)
.withUnit("°C")
.withDescription("Set heat temperature in eco mode")
.withValueMin(10)
.withValueMax(30)
.withValueStep(1),
e.binary("fan_control", ea.ALL, "On", "Off").withDescription("On/Off Fan Control"),
e
.climate()
.withLocalTemperature()
.withSetpoint("occupied_heating_setpoint", 5, 45, 0.5)
.withLocalTemperatureCalibration(-9, 9, 1)
.withSystemMode(["off", "heat", "cool", "fan_only"])
.withRunningState(["idle", "heat", "cool", "fan_only"], ea.STATE)
.withFanMode(["low", "medium", "high", "auto"])
.withWeeklySchedule(["cool"], ea.ALL),
e.text("schedule_monday", ea.STATE).withDescription("Monday's schedule"),
e.text("schedule_tuesday", ea.STATE).withDescription("Tuesday's schedule"),
e.text("schedule_wednesday", ea.STATE).withDescription("Wednesday's schedule"),
e.text("schedule_thursday", ea.STATE).withDescription("Thursday's schedule"),
e.text("schedule_friday", ea.STATE).withDescription("Friday's schedule"),
e.text("schedule_saturday", ea.STATE).withDescription("Saturday's schedule"),
e.text("schedule_sunday", ea.STATE).withDescription("Sunday's schedule"),
],
meta: {},
ota: true,
},
{
zigbeeModel: ["Tuya_Thermostat_r08"],
model: "THERM_SLACKY_DIY_R08",
vendor: "Slacky-DIY",
description: "Tuya Thermostat for Floor Heating with custom Firmware",
endpoint: (device) => {
return { day: 1, night: 2 };
},
fromZigbee: localFromZigbeeThermostat,
toZigbee: localToZigbeeThermostat,
configure: configureCommon,
extend: [
m.deviceAddCustomCluster("hvacThermostat", {
name: "hvacThermostat",
ID: 0x0201,
attributes: {
localTemperatureCalibration: {
name: "localTemperatureCalibration",
ID: 0x0010,
type: 0x28,
write: true,
max: 0xff,
},
minSetpointDeadBand: {
name: "minSetpointDeadBand",
ID: 0x0019,
type: 0x28,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
],
exposes: [
e.binary("child_lock", ea.ALL, "LOCK", "UNLOCK").withDescription("Enables/disables physical input on the device"),
e.programming_operation_mode(["setpoint", "schedule"]).withDescription("Setpoint or Schedule mode"),
e
.numeric("min_heat_setpoint_limit", ea.ALL)
.withUnit("°C")
.withDescription("Minimum Heating set point limit")
.withValueMin(5)
.withValueMax(15)
.withValueStep(1),
e
.numeric("max_heat_setpoint_limit", ea.ALL)
.withDescription("Maximum Heating set point limit")
.withUnit("°C")
.withValueMin(15)
.withValueMax(45)
.withValueStep(1),
e.binary("eco_mode", ea.ALL, "On", "Off").withDescription("On/Off Sleep Mode"),
e
.numeric("external_temperature_calibration", ea.ALL)
.withDescription("External temperature calibration")
.withUnit("°C")
.withValueMin(-9)
.withValueMax(9)
.withValueStep(1),
e
.climate()
.withLocalTemperature()
.withSetpoint("occupied_heating_setpoint", 5, 45, 0.5)
.withLocalTemperatureCalibration(-9, 9, 1)
.withSystemMode(["off", "heat"])
.withRunningState(["idle", "heat"], ea.STATE)
.withWeeklySchedule(["heat"], ea.ALL),
e.text("schedule_monday", ea.STATE).withDescription("Schedule for the working week"),
e.text("schedule_saturday", ea.STATE).withDescription("Saturday's schedule"),
e.text("schedule_sunday", ea.STATE).withDescription("Sunday's schedule"),
],
meta: {},
ota: true,
},
{
zigbeeModel: ["Tuya_Thermostat_r09"],
model: "THERM_SLACKY_DIY_R09",
vendor: "Slacky-DIY",
description: "Tuya Thermostat for Floor Heating with custom Firmware",
endpoint: (device) => {
return { day: 1, night: 2 };
},
fromZigbee: localFromZigbeeThermostat,
toZigbee: localToZigbeeThermostat,
configure: configureCommon,
extend: [
m.deviceAddCustomCluster("hvacThermostat", {
name: "hvacThermostat",
ID: 0x0201,
attributes: {
localTemperatureCalibration: {
name: "localTemperatureCalibration",
ID: 0x0010,
type: 0x28,
write: true,
max: 0xff,
},
minSetpointDeadBand: {
name: "minSetpointDeadBand",
ID: 0x0019,
type: 0x28,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
],
exposes: [
e.binary("child_lock", ea.ALL, "LOCK", "UNLOCK").withDescription("Enables/disables physical input on the device"),
e.binary("mode_child_lock", ea.ALL, "partial", "all").withDescription("Child lock mode - all/partial"),
e.binary("relay_type", ea.ALL, "NC", "NO").withDescription("Relay type NC/NO"),
e.programming_operation_mode(["setpoint", "schedule"]).withDescription("Setpoint or Schedule mode"),
e.enum("sensor", ea.ALL, switchSensorUsed).withDescription("Select temperature sensor to use"),
e
.numeric("hysteresis_temperature", ea.ALL)
.withDescription("The delta between local_temperature and current_heating_setpoint to trigger activity")
.withUnit("°C")
.withValueMin(1)
.withValueMax(5)
.withValueStep(0.5),
e
.numeric("min_heat_setpoint_limit", ea.ALL)
.withUnit("°C")
.withDescription("Minimum Heating set point limit")
.withValueMin(5)
.withValueMax(15)
.withValueStep(1),
e
.numeric("max_heat_setpoint_limit", ea.ALL)
.withDescription("Maximum Heating set point limit")
.withUnit("°C")
.withValueMin(15)
.withValueMax(45)
.withValueStep(1),
e
.numeric("frost_protect", ea.ALL)
.withUnit("°C")
.withDescription("Protection against minimum freezing temperature")
.withValueMin(0)
.withValueMax(10)
.withValueStep(1),
e
.numeric("heat_protect", ea.ALL)
.withUnit("°C")
.withDescription("Protection against maximum heating temperature")
.withValueMin(25)
.withValueMax(70)
.withValueStep(1),
e.numeric("brightness", ea.ALL).withValueMin(0).withValueMax(8).withDescription("Screen brightness 06:00 - 22:00").withEndpoint("day"),
e.numeric("brightness", ea.ALL).withValueMin(0).withValueMax(8).withDescription("Screen brightness 22:00 - 06:00").withEndpoint("night"),
e.binary("eco_mode", ea.ALL, "On", "Off").withDescription("On/Off Sleep Mode"),
e
.numeric("eco_mode_heat_temperature", ea.ALL)
.withUnit("°C")
.withDescription("Set heat temperature in eco mode")
.withValueMin(5)
.withValueMax(45)
.withValueStep(1),
e
.numeric("external_temperature_calibration", ea.ALL)
.withDescription("External temperature calibration")
.withUnit("°C")
.withValueMin(-9)
.withValueMax(9)
.withValueStep(1),
e.numeric("outdoor_temperature", ea.STATE_GET).withUnit("°C").withDescription("Current temperature measured from the floor outer sensor"),
e
.climate()
.withLocalTemperature()
.withSetpoint("occupied_heating_setpoint", 5, 45, 0.5)
.withLocalTemperatureCalibration(-9, 9, 1)
.withSystemMode(["off", "heat"])
.withRunningState(["idle", "heat"], ea.STATE)
.withWeeklySchedule(["heat"], ea.ALL),
e.text("schedule_monday", ea.STATE).withDescription("Monday's schedule"),
e.text("schedule_tuesday", ea.STATE).withDescription("Tuesday's schedule"),
e.text("schedule_wednesday", ea.STATE).withDescription("Wednesday's schedule"),
e.text("schedule_thursday", ea.STATE).withDescription("Thursday's schedule"),
e.text("schedule_friday", ea.STATE).withDescription("Friday's schedule"),
e.text("schedule_saturday", ea.STATE).withDescription("Saturday's schedule"),
e.text("schedule_sunday", ea.STATE).withDescription("Sunday's schedule"),
e.enum("settings_reset", ea.SET, ["Default"]).withDescription("Default settings"),
],
meta: {},
ota: true,
},
{
zigbeeModel: ["Tuya_Thermostat_r0A"],
model: "THERM_SLACKY_DIY_R0A",
vendor: "Slacky-DIY",
description: "Tuya Thermostat for Floor Heating with custom Firmware",
endpoint: (device) => {
return { day: 1, night: 2 };
},
fromZigbee: localFromZigbeeThermostat,
toZigbee: localToZigbeeThermostat,
configure: configureCommon,
extend: [
m.deviceAddCustomCluster("hvacThermostat", {
name: "hvacThermostat",
ID: 0x0201,
attributes: {
localTemperatureCalibration: {
name: "localTemperatureCalibration",
ID: 0x0010,
type: 0x28,
write: true,
max: 0xff,
},
minSetpointDeadBand: {
name: "minSetpointDeadBand",
ID: 0x0019,
type: 0x28,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
],
exposes: [
e.binary("child_lock", ea.ALL, "LOCK", "UNLOCK").withDescription("Enables/disables physical input on the device"),
e.programming_operation_mode(["setpoint", "schedule"]).withDescription("Setpoint or Schedule mode"),
e.enum("sensor", ea.ALL, switchSensorUsed).withDescription("Select temperature sensor to use"),
e
.numeric("deadzone_temperature", ea.ALL)
.withDescription("The delta between local_temperature and current_heating_setpoint to trigger activity")
.withUnit("°C")
.withValueMin(1)
.withValueMax(5)
.withValueStep(1),
e
.numeric("min_heat_setpoint_limit", ea.ALL)
.withUnit("°C")
.withDescription("Minimum Heating set point limit")
.withValueMin(0)
.withValueMax(20)
.withValueStep(1),
e
.numeric("max_heat_setpoint_limit", ea.ALL)
.withDescription("Maximum Heating set point limit")
.withUnit("°C")
.withValueMin(20)
.withValueMax(50)
.withValueStep(1),
e
.numeric("heat_protect", ea.ALL)
.withUnit("°C")
.withDescription("Protection against maximum heating temperature")
.withValueMin(25)
.withValueMax(70)
.withValueStep(1),
e.binary("eco_mode", ea.ALL, "On", "Off").withDescription("On/Off Eco Mode"),
e
.climate()
.withLocalTemperature()
.withSetpoint("occupied_heating_setpoint", 1, 50, 1)
.withLocalTemperatureCalibration(-9, 9, 1)
.withSystemMode(["off", "heat"])
.withRunningState(["idle", "heat"], ea.STATE)
.withWeeklySchedule(["heat"], ea.ALL),
e.text("schedule_monday", ea.STATE).withDescription("Schedule for the working week"),
e.text("schedule_saturday", ea.STATE).withDescription("Saturday's schedule"),
e.text("schedule_sunday", ea.STATE).withDescription("Sunday's schedule"),
],
meta: {},
ota: true,
},
{
zigbeeModel: ["Tuya_Thermostat_r0B"],
model: "THERM_SLACKY_DIY_R0B",
vendor: "Slacky-DIY",
description: "Tuya Thermostat for Floor Heating with custom Firmware",
endpoint: (device) => {
return { day: 1, night: 2 };
},
fromZigbee: localFromZigbeeThermostat,
toZigbee: localToZigbeeThermostat,
configure: configureCommon,
extend: [
m.deviceAddCustomCluster("hvacThermostat", {
name: "hvacThermostat",
ID: 0x0201,
attributes: {
localTemperatureCalibration: {
name: "localTemperatureCalibration",
ID: 0x0010,
type: 0x28,
write: true,
max: 0xff,
},
minSetpointDeadBand: {
name: "minSetpointDeadBand",
ID: 0x0019,
type: 0x28,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
],
exposes: [
e.binary("child_lock", ea.ALL, "LOCK", "UNLOCK").withDescription("Enables/disables physical input on the device"),
e.programming_operation_mode(["setpoint", "schedule"]).withDescription("Setpoint or Schedule mode"),
e.enum("sensor", ea.ALL, ["Inner (IN)", "Outer (OU)"]).withDescription("Select temperature sensor to use"),
e.enum("screen_sleep_mode", ea.ALL, ["Off", "Dim", "On"]).withDescription("Screen sleep mode of brightness"),
e
.numeric("hysteresis_temperature", ea.ALL)
.withDescription("The delta between local_temperature and current_heating_setpoint to trigger activity")
.withUnit("°C")
.withValueMin(0.5)
.withValueMax(5)
.withValueStep(0.5),
e
.numeric("min_heat_setpoint_limit", ea.ALL)
.withUnit("°C")
.withDescription("Minimum Heating set point limit")
.withValueMin(1)
.withValueMax(5)
.withValueStep(0.5),
e
.numeric("max_heat_setpoint_limit", ea.ALL)
.withDescription("Maximum Heating set point limit")
.withUnit("°C")
.withValueMin(35)
.withValueMax(50)
.withValueStep(0.5),
e
.climate()
.withLocalTemperature()
.withSetpoint("occupied_heating_setpoint", 1, 50, 0.5)
.withLocalTemperatureCalibration(-9, 9, 1)
.withSystemMode(["off", "heat"])
.withRunningState(["idle", "heat"], ea.STATE)
.withWeeklySchedule(["heat"], ea.ALL),
e.text("schedule_monday", ea.STATE).withDescription("Schedule for the working week"),
e.text("schedule_saturday", ea.STATE).withDescription("Saturday's schedule"),
e.text("schedule_sunday", ea.STATE).withDescription("Sunday's schedule"),
],
meta: {},
ota: true,
},
{
zigbeeModel: ["Tuya_Thermostat_r0C"],
model: "THERM_SLACKY_DIY_R0C",
vendor: "Slacky-DIY",
description: "Tuya Thermostat for Floor Heating with custom Firmware",
endpoint: (device) => {
return { day: 1, night: 2 };
},
fromZigbee: localFromZigbeeThermostat,
toZigbee: localToZigbeeThermostat,
configure: configureCommon,
extend: [
m.deviceAddCustomCluster("hvacThermostat", {
name: "hvacThermostat",
ID: 0x0201,
attributes: {
localTemperatureCalibration: {
name: "localTemperatureCalibration",
ID: 0x0010,
type: 0x28,
write: true,
max: 0xff,
},
minSetpointDeadBand: {
name: "minSetpointDeadBand",
ID: 0x0019,
type: 0x28,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
],
exposes: [
e.binary("child_lock", ea.ALL, "LOCK", "UNLOCK").withDescription("Enables/disables physical input on the device"),
e.programming_operation_mode(["setpoint", "schedule"]).withDescription("Setpoint or Schedule mode"),
e.enum("sensor", ea.ALL, switchSensorUsed).withDescription("Select temperature sensor to use"),
e
.numeric("deadzone_temperature", ea.ALL)
.withDescription("The delta between local_temperature and current_heating_setpoint to trigger activity")
.withUnit("°C")
.withValueMin(1)
.withValueMax(5)
.withValueStep(1),
e
.numeric("min_heat_setpoint_limit", ea.ALL)
.withUnit("°C")
.withDescription("Minimum Heating set point limit")
.withValueMin(5)
.withValueMax(15)
.withValueStep(1),
e
.numeric("max_heat_setpoint_limit", ea.ALL)
.withDescription("Maximum Heating set point limit")
.withUnit("°C")
.withValueMin(15)
.withValueMax(45)
.withValueStep(1),
e
.numeric("frost_protect", ea.ALL)
.withUnit("°C")
.withDescription("Protection against minimum freezing temperature")
.withValueMin(0)
.withValueMax(10)
.withValueStep(1),
e
.numeric("heat_protect", ea.ALL)
.withUnit("°C")
.withDescription("Protection against maximum heating temperature")
.withValueMin(25)
.withValueMax(70)
.withValueStep(1),
e.numeric("brightness", ea.ALL).withValueMin(0).withValueMax(9).withDescription("Screen brightness").withEndpoint("day"),
e.binary("eco_mode", ea.ALL, "On", "Off").withDescription("On/Off Eco Mode"),
e
.numeric("eco_mode_heat_temperature", ea.ALL)
.withUnit("°C")
.withDescription("Set heat temperature in eco mode")
.withValueMin(5)
.withValueMax(45)
.withValueStep(1),
e.humidity(),
e
.numeric("humidity_offset", ea.ALL)
.withUnit("%")
.withDescription("Offset to add/subtract to the inside humidity")
.withValueMin(-95)
.withValueMax(95)
.withValueStep(1),
e.numeric("outdoor_temperature", ea.STATE_GET).withUnit("°C").withDescription("Current temperature measured from the floor outer sensor"),
e
.climate()
.withLocalTemperature()
.withSetpoint("occupied_heating_setpoint", 5, 45, 0.5)
.withLocalTemperatureCalibration(-9, 9, 1)
.withSystemMode(["off", "heat"])
.withRunningState(["idle", "heat"], ea.STATE)
.withWeeklySchedule(["heat"], ea.ALL),
e.text("schedule_monday", ea.STATE).withDescription("Monday's schedule"),
e.text("schedule_tuesday", ea.STATE).withDescription("Tuesday's schedule"),
e.text("schedule_wednesday", ea.STATE).withDescription("Wednesday's schedule"),
e.text("schedule_thursday", ea.STATE).withDescription("Thursday's schedule"),
e.text("schedule_friday", ea.STATE).withDescription("Friday's schedule"),
e.text("schedule_saturday", ea.STATE).withDescription("Saturday's schedule"),
e.text("schedule_sunday", ea.STATE).withDescription("Sunday's schedule"),
],
meta: {},
ota: true,
},
{
zigbeeModel: ["Tuya_Thermostat_r0D"],
model: "THERM_SLACKY_DIY_R0D",
vendor: "Slacky-DIY",
description: "Tuya Thermostat for Floor Heating with custom Firmware",
endpoint: (device) => {
return { day: 1, night: 2 };
},
fromZigbee: localFromZigbeeThermostat,
toZigbee: localToZigbeeThermostat,
configure: configureCommon,
extend: [
m.deviceAddCustomCluster("hvacThermostat", {
name: "hvacThermostat",
ID: 0x0201,
attributes: {
localTemperatureCalibration: {
name: "localTemperatureCalibration",
ID: 0x0010,
type: 0x28,
write: true,
max: 0xff,
},
minSetpointDeadBand: {
name: "minSetpointDeadBand",
ID: 0x0019,
type: 0x28,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
],
exposes: [
e.binary("child_lock", ea.ALL, "LOCK", "UNLOCK").withDescription("Enables/disables physical input on the device"),
e.enum("brightness_level", ea.ALL, ["Off", "Low", "Medium", "High"]).withDescription("Screen idle brightness"),
e.enum("screen_sleep_time", ea.ALL, ["10s", "20s", "30s", "40s", "50s", "60s"]).withDescription("Screen sleep timeout"),
e.binary("led_indicator", ea.ALL, "On", "Off").withDescription("Enables/disables light ring indicator"),
e.programming_operation_mode(["setpoint", "schedule", "schedule_with_preheat", "eco"]).withDescription("Setpoint or Schedule mode"),
e
.numeric("hysteresis_temperature", ea.ALL)
.withDescription("The delta between local_temperature and current_heating_setpoint to trigger activity")
.withUnit("°C")
.withValueMin(0.5)
.withValueMax(5)
.withValueStep(0.5),
e
.numeric("min_heat_setpoint_limit", ea.ALL)
.withUnit("°C")
.withDescription("Minimum Heating set point limit")
.withValueMin(5)
.withValueMax(15)
.withValueStep(1),
e
.numeric("max_heat_setpoint_limit", ea.ALL)
.withDescription("Maximum Heating set point limit")
.withUnit("°C")
.withValueMin(35)
.withValueMax(45)
.withValueStep(1),
e
.numeric("frost_protect", ea.ALL)
.withUnit("°C")
.withDescription("Protection against minimum freezing temperature")
.withValueMin(0)
.withValueMax(10)
.withValueStep(1),
e
.numeric("heat_protect", ea.ALL)
.withUnit("°C")
.withDescription("Protection against maximum heating temperature")
.withValueMin(10)
.withValueMax(70)
.withValueStep(1),
e
.numeric("eco_mode_cool_temperature", ea.ALL)
.withUnit("°C")
.withDescription("Set cool temperature in eco mode")
.withValueMin(10)
.withValueMax(30)
.withValueStep(1),
e.enum("sensor", ea.ALL, switchSensorUsed).withDescription("Select temperature sensor to use"),
e.numeric("outdoor_temperature", ea.STATE_GET).withUnit("°C").withDescription("Current temperature measured from the floor outer sensor"),
e
.climate()
.withLocalTemperature()
.withSetpoint("occupied_heating_setpoint", 5, 45, 1)
.withLocalTemperatureCalibration(-10, 10, 1)
.withSystemMode(["off", "heat"])
.withRunningState(["idle", "heat"], ea.STATE)
.withWeeklySchedule(["heat"], ea.ALL),
e.text("schedule_monday", ea.STATE).withDescription("Monday's schedule"),
e.text("schedule_tuesday", ea.STATE).withDescription("Tuesday's schedule"),
e.text("schedule_wednesday", ea.STATE).withDescription("Wednesday's schedule"),
e.text("schedule_thursday", ea.STATE).withDescription("Thursday's schedule"),
e.text("schedule_friday", ea.STATE).withDescription("Friday's schedule"),
e.text("schedule_saturday", ea.STATE).withDescription("Saturday's schedule"),
e.text("schedule_sunday", ea.STATE).withDescription("Sunday's schedule"),
e.enum("settings_reset", ea.SET, ["Default"]).withDescription("Default settings"),
],
meta: {},
ota: true,
},
{
zigbeeModel: [
"TS0201-z-SlD",
"TS0201-z15-SlD",
"TS0201-z21-SlD",
"TS0201-z22-SlD",
"TS0201-z23-SlD",
"TS0201-z24-SlD",
"TS0201-z28-SlD",
"TS0201-z29-SlD",
],
model: "TS0201-z-SlD",
vendor: "Slacky-DIY",
description: "Tuya temperature and humidity sensor with custom Firmware",
extend: [
m.deviceEndpoints({
endpoints: {
"1": 1,
"2": 2,
},
}),
m.battery({
voltage: true,
voltageReporting: true,
percentageReportingConfig: batteryReporting,
voltageReportingConfig: batteryReporting,
}),
m.temperature({ reporting: temperatureReporting }),
m.humidity({ reporting: humidityReporting }),
m.numeric({
name: "temperature_offset",
cluster: "msTemperatureMeasurement",
attribute: { ID: attrTemperatureOffset, type: 0x29 },
unit: "°C",
valueMin: -5,
valueMax: 5,
valueStep: 0.1,
scale: 100,
description: "Offset to add/subtract to the inside temperature",
}),
m.numeric({
name: "humidity_offset",
cluster: "msRelativeHumidity",
attribute: { ID: attrHumidityOffset, type: 0x29 },
unit: "%",
valueMin: -10,
valueMax: 10,
valueStep: 1,
scale: 100,
description: "Offset to add/subtract to the inside humidity",
}),
m.numeric({
name: "read_interval",
cluster: "msTemperatureMeasurement",
attribute: { ID: attrSensorReadPeriod, type: 0x21 },
unit: "Sec",
valueMin: 5,
valueMax: 600,
valueStep: 1,
description: "Sensors reading period",
}),
m.binary({
name: "enabling_repeat_command",
cluster: "msTemperatureMeasurement",
attribute: { ID: attrRepeatCommand, type: 0x10 },
description: "Enables/disables repeat command",
valueOn: ["ON", 0x01],
valueOff: ["OFF", 0x00],
}),
m.binary({
name: "enabling_temperature_control",
cluster: "msTemperatureMeasurement",
attribute: { ID: attrTemperatureOnOff, type: 0x10 },
description: "Enables/disables Tempearure control",
valueOn: ["ON", 0x01],
valueOff: ["OFF", 0x00],
}),
m.numeric({
name: "low_temperature",
cluster: "msTemperatureMeasurement",
attribute: { ID: attrTemperatureLow, type: 0x29 },
unit: "°C",
valueMin: -40,
valueMax: 125,
valueStep: 0.1,
scale: 100,
description: "Temperature low turn-off limit",
}),
m.numeric({
name: "high_temperature",
cluster: "msTemperatureMeasurement",
attribute: { ID: attrTemperatureHigh, type: 0x29 },
unit: "°C",
valueMin: -40,
valueMax: 125,
valueStep: 0.1,
scale: 100,
description: "Temperature high turn-on limit",
}),
m.enumLookup({
name: "temperature_actions",
endpointName: "1",
lookup: { heat: 0, cool: 1 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Heat or cool",
}),
m.binary({
name: "enabling_humidity_control",
cluster: "msRelativeHumidity",
attribute: { ID: attrHumidityOnOff, type: 0x10 },
description: "Enables/disables Humidity control",
valueOn: ["ON", 0x01],
valueOff: ["OFF", 0x00],
}),
m.numeric({
name: "low_humidity",
cluster: "msRelativeHumidity",
attribute: { ID: attrHumidityLow, type: 0x29 },
unit: "%",
valueMin: 1,
valueMax: 100,
valueStep: 1,
scale: 100,
description: "Humidity low turn-off limit",
}),
m.numeric({
name: "high_humidity",
cluster: "msRelativeHumidity",
attribute: { ID: attrHumidityHigh, type: 0x29 },
unit: "%",
valueMin: 1,
valueMax: 100,
valueStep: 1,
scale: 100,
description: "Humidity high turn-on limit",
}),
m.enumLookup({
name: "humidity_actions",
endpointName: "2",
lookup: { wet: 0, dry: 1 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Wet or dry",
}),
],
ota: true,
},
{
zigbeeModel: ["TS0201-z2C-SlD"],
model: "TS0201-LCD-SlD",
vendor: "Slacky-DIY",
description: "Tuya temperature and humidity sensor with LCD display and custom firmware",
extend: [
m.deviceEndpoints({
endpoints: {
"1": 1,
"2": 2,
},
}),
m.battery({
voltage: true,
voltageReporting: true,
percentageReportingConfig: batteryReporting,
voltageReportingConfig: batteryReporting,
}),
m.temperature({ reporting: temperatureReporting }),
m.humidity({ reporting: humidityReporting }),
m.numeric({
name: "temperature_offset",
cluster: "msTemperatureMeasurement",
attribute: { ID: attrTemperatureOffset, type: 0x29 },
unit: "°C",
valueMin: -5,
valueMax: 5,
valueStep: 0.1,
scale: 100,
description: "Offset to add/subtract to the inside temperature",
}),
m.numeric({
name: "humidity_offset",
cluster: "msRelativeHumidity",
attribute: { ID: attrHumidityOffset, type: 0x29 },
unit: "%",
valueMin: -10,
valueMax: 10,
valueStep: 1,
scale: 100,
description: "Offset to add/subtract to the inside humidity",
}),
m.numeric({
name: "read_interval",
cluster: "msTemperatureMeasurement",
attribute: { ID: attrSensorReadPeriod, type: 0x21 },
unit: "Sec",
valueMin: 5,
valueMax: 600,
valueStep: 1,
description: "Sensors reading period",
}),
m.binary({
name: "enabling_repeat_command",
cluster: "msTemperatureMeasurement",
attribute: { ID: attrRepeatCommand, type: 0x10 },
description: "Enables/disables repeat command",
valueOn: ["ON", 0x01],
valueOff: ["OFF", 0x00],
}),
m.binary({
name: "enabling_temperature_control",
cluster: "msTemperatureMeasurement",
attribute: { ID: attrTemperatureOnOff, type: 0x10 },
description: "Enables/disables Tempearure control",
valueOn: ["ON", 0x01],
valueOff: ["OFF", 0x00],
}),
m.numeric({
name: "low_temperature",
cluster: "msTemperatureMeasurement",
attribute: { ID: attrTemperatureLow, type: 0x29 },
unit: "°C",
valueMin: -40,
valueMax: 125,
valueStep: 0.1,
scale: 100,
description: "Temperature low turn-off limit",
}),
m.numeric({
name: "high_temperature",
cluster: "msTemperatureMeasurement",
attribute: { ID: attrTemperatureHigh, type: 0x29 },
unit: "°C",
valueMin: -40,
valueMax: 125,
valueStep: 0.1,
scale: 100,
description: "Temperature high turn-on limit",
}),
m.enumLookup({
name: "temperature_actions",
endpointName: "1",
lookup: { heat: 0, cool: 1 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Heat or cool",
}),
m.binary({
name: "enabling_humidity_control",
cluster: "msRelativeHumidity",
attribute: { ID: attrHumidityOnOff, type: 0x10 },
description: "Enables/disables Humidity control",
valueOn: ["ON", 0x01],
valueOff: ["OFF", 0x00],
}),
m.numeric({
name: "low_humidity",
cluster: "msRelativeHumidity",
attribute: { ID: attrHumidityLow, type: 0x29 },
unit: "%",
valueMin: 1,
valueMax: 100,
valueStep: 1,
scale: 100,
description: "Humidity low turn-off limit",
}),
m.numeric({
name: "high_humidity",
cluster: "msRelativeHumidity",
attribute: { ID: attrHumidityHigh, type: 0x29 },
unit: "%",
valueMin: 1,
valueMax: 100,
valueStep: 1,
scale: 100,
description: "Humidity high turn-on limit",
}),
m.enumLookup({
name: "humidity_actions",
endpointName: "2",
lookup: { wet: 0, dry: 1 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Wet or dry",
}),
],
ota: true,
},
{
zigbeeModel: ["ZG-222ZA-z-SlD", "ZG-222Z-z-SlD", "SNZB-05-z-SlD"],
model: "ZG-222ZA-z-SlD",
vendor: "Slacky-DIY",
description: "Tuya water leak sensor with custom firmware",
extend: [
m.battery({
voltage: true,
voltageReporting: true,
percentageReportingConfig: batteryReporting,
voltageReportingConfig: batteryReporting,
}),
m.iasZoneAlarm({ zoneType: "water_leak", zoneAttributes: ["alarm_1", "battery_low"] }),
m.commandsOnOff(),
m.enumLookup({
name: "switch_actions",
lookup: { off: 0, on: 1 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
],
meta: {},
ota: true,
},
{
zigbeeModel: ["AirQ_Monitor_S01"],
model: "AirQ_Monitor_S01",
vendor: "Slacky-DIY",
description: "Air quality monitor",
configure: async (device, coordinatorEndpoint, logger) => {
const endpoint = device.getEndpoint(1);
await endpoint.read("genLevelCtrl", ["currentLevel"]);
},
extend: [
m.co2({ reporting: { min: 10, max: 3600, change: 0.00001 } }),
m.numeric({
name: "voc_index",
access: "STATE_GET",
cluster: "genAnalogInput",
attribute: "presentValue",
reporting: { min: 10, max: 3600, change: 30 },
unit: "VOC Index points",
description: "VOC index",
}),
m.temperature(),
m.humidity(),
m.pressure(),
m.illuminance(),
m.enumLookup({
name: "display_rotate",
lookup: { horizontal: 0, vertical: 1 },
cluster: "hvacUserInterfaceCfg",
attribute: { ID: attrDisplayRotate, type: 0x30 },
reporting: { min: 0, max: 65000, change: 0 },
description: "Display orientation (horizontal/vertical)",
}),
m.enumLookup({
name: "display_inversion",
lookup: { black_on_white: 0, white_on_black: 1 },
cluster: "hvacUserInterfaceCfg",
attribute: { ID: attrDisplayInversion, type: 0x30 },
reporting: { min: 0, max: 65000, change: 0 },
description: "Display inversion (black on white/white on black)",
}),
m.enumLookup({
name: "temperature_display_mode",
lookup: { celsius: 0, fahrenheit: 1 },
cluster: "hvacUserInterfaceCfg",
attribute: "tempDisplayMode",
reporting: { min: 0, max: 65000, change: 0 },
description: "The units of the temperature displayed on the device screen",
}),
m.numeric({
name: "temperature_offset",
cluster: "msTemperatureMeasurement",
attribute: { ID: 0xf000, type: 0x29 },
unit: "°C",
valueMin: -5,
valueMax: 5,
valueStep: 0.1,
scale: 100,
description: "Offset to add/subtract to the inside temperature",
}),
m.numeric({
name: "read_interval",
cluster: "msTemperatureMeasurement",
attribute: { ID: 0xf001, type: 0x21 },
unit: "Sec",
valueMin: 5,
valueMax: 600,
valueStep: 1,
description: "Sensors reading period",
}),
m.binary({
name: "enabling_co2_control",
cluster: "msCO2",
attribute: { ID: 0xf002, type: 0x10 },
description: "Enables/disables CO2 control",
valueOn: ["ON", 0x01],
valueOff: ["OFF", 0x00],
}),
m.numeric({
name: "low_co2",
cluster: "msCO2",
attribute: { ID: 0xf003, type: 0x21 },
unit: "ppm",
valueMin: 400,
valueMax: 2000,
valueStep: 1,
description: "CO2 low turn-off limit",
}),
m.numeric({
name: "high_co2",
cluster: "msCO2",
attribute: { ID: 0xf004, type: 0x21 },
unit: "ppm",
valueMin: 400,
valueMax: 2000,
valueStep: 1,
description: "CO2 high turn-on limit",
}),
m.binary({
name: "enabling_voc_control",
cluster: "genAnalogInput",
attribute: { ID: 0xf005, type: 0x10 },
description: "Enables/disables VOC control",
valueOn: ["ON", 0x01],
valueOff: ["OFF", 0x00],
}),
m.numeric({
name: "low_voc",
cluster: "genAnalogInput",
attribute: { ID: 0xf006, type: 0x21 },
unit: "VOC index points",
valueMin: 1,
valueMax: 500,
valueStep: 1,
description: "VOC low turn-off limit",
}),
m.numeric({
name: "high_voc",
cluster: "genAnalogInput",
attribute: { ID: 0xf007, type: 0x21 },
unit: "VOC index points",
valueMin: 1,
valueMax: 500,
valueStep: 1,
description: "VOC high turn-on limit",
}),
m.enumLookup({
name: "switch_actions",
lookup: { off: 0, on: 1 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
air_extend.led_brightness(),
m.binary({
name: "enabling_sound",
cluster: "hvacUserInterfaceCfg",
attribute: { ID: 0xf00c, type: 0x10 },
description: "Enables/disables sound",
valueOn: ["ON", 0x01],
valueOff: ["OFF", 0x00],
}),
m.numeric({
name: "frc_co2_correction",
access: "STATE_GET",
cluster: "msCO2",
attribute: { ID: attrCo2Calibration, type: 0x29 },
reporting: { min: 0, max: 3600, change: 0 },
unit: "ppm",
description: "FRC CO2 correction",
}),
air_extend.features_sensors(),
m.numeric({
name: "life_time",
access: "STATE_GET",
cluster: "genTime",
attribute: "time",
reporting: { min: 60, max: 3600, change: 0 },
unit: "h",
description: "Life time of device",
}),
],
meta: {},
ota: true,
},
{
zigbeeModel: ["QS-Zigbee-SEC01-Mod"],
model: "QS-Zigbee-SEC01-Mod",
vendor: "Svetomaniya",
description: "Smart light switch module 1 gang",
extend: [
m.deviceAddCustomCluster("genOnOffSwitchCfg", {
name: "genOnOffSwitchCfg",
ID: 0x0007,
attributes: {
customSwitchType: {
name: "customSwitchType",
ID: attrSwitchType,
type: 0x30,
write: true,
max: 0xff,
},
customRelayControl: {
name: "customRelayControl",
ID: attrSwitchDecoupled,
type: 0x30,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceAddCustomCluster("genLevelCtrl", {
name: "genLevelCtrl",
ID: 0x0008,
attributes: {
minLevel: {
name: "minLevel",
ID: 0x0002,
type: 0x20,
write: true,
max: 0xff,
},
maxLevel: {
name: "maxLevel",
ID: 0x0003,
type: 0x20,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceAddCustomCluster("genScenes", {
name: "genScenes",
ID: 0x0005,
attributes: {
customSceneId: {
name: "customSceneId",
ID: attrSceneId,
type: 0x20,
write: true,
max: 0xff,
},
customGroupId: {
name: "customGroupId",
ID: attrGroupId,
type: 0x21,
write: true,
max: 0xffff,
},
},
commands: {},
commandsResponse: {},
}),
m.onOff({ powerOnBehavior: true }),
m.commandsOnOff(),
localActionExtend({ reporting: false }),
m.commandsLevelCtrl(),
m.commandsColorCtrl(),
m.enumLookup({
name: "switch_actions",
lookup: { off: 0, on: 1 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_type",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
light_control: 3,
scene: 6,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "operation_mode",
lookup: { control_relay: 0, decoupled: 1 },
cluster: "genOnOffSwitchCfg",
attribute: "customRelayControl",
reporting: { min: 0, max: 65000, change: 0 },
description: "Relay decoupled",
}),
m.commandsScenes(),
m.numeric({
name: "scene_id",
access: "ALL",
cluster: "genScenes",
attribute: "customSceneId",
valueMin: 0,
valueMax: 255,
description: "Scene ID",
}),
m.numeric({
name: "group_id",
access: "ALL",
cluster: "genScenes",
attribute: "customGroupId",
valueMin: 0,
valueMax: 65527,
description: "Group ID for scenes",
}),
m.numeric({
name: "min_level",
access: "ALL",
cluster: "genLevelCtrl",
attribute: "minLevel",
valueMin: 1,
valueMax: 255,
description: "Minimum level when decreasing",
}),
m.numeric({
name: "max_level",
access: "ALL",
cluster: "genLevelCtrl",
attribute: "maxLevel",
valueMin: 1,
valueMax: 255,
description: "Maximum level when increasing",
}),
],
meta: {},
ota: true,
},
{
zigbeeModel: ["QS-Zigbee-SEC02-Mod"],
model: "QS-Zigbee-SEC02-Mod",
vendor: "Svetomaniya",
description: "Smart light switch module 2 gang",
extend: [
m.deviceAddCustomCluster("genOnOffSwitchCfg", {
name: "genOnOffSwitchCfg",
ID: 0x0007,
attributes: {
customSwitchType: {
name: "customSwitchType",
ID: attrSwitchType,
type: 0x30,
write: true,
max: 0xff,
},
customRelayControl: {
name: "customRelayControl",
ID: attrSwitchDecoupled,
type: 0x30,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceAddCustomCluster("genLevelCtrl", {
name: "genLevelCtrl",
ID: 0x0008,
attributes: {
minLevel: {
name: "minLevel",
ID: 0x0002,
type: 0x20,
write: true,
max: 0xff,
},
maxLevel: {
name: "maxLevel",
ID: 0x0003,
type: 0x20,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceAddCustomCluster("genScenes", {
name: "genScenes",
ID: 0x0005,
attributes: {
customSceneId: {
name: "customSceneId",
ID: attrSceneId,
type: 0x20,
write: true,
max: 0xff,
},
customGroupId: {
name: "customGroupId",
ID: attrGroupId,
type: 0x21,
write: true,
max: 0xffff,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceEndpoints({ endpoints: { "1": 1, "2": 2 } }),
m.onOff({ powerOnBehavior: true, endpointNames: ["1", "2"] }),
m.commandsOnOff({ endpointNames: ["1", "2"] }),
localActionExtend({
endpointNames: ["1", "2"],
reporting: false,
}),
m.commandsLevelCtrl({ endpointNames: ["1", "2"] }),
m.commandsColorCtrl({
endpointNames: ["1", "2"],
}),
m.enumLookup({
name: "switch_actions",
endpointName: "1",
lookup: { off: 0, on: 1 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "2",
lookup: { off: 0, on: 1 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_type",
endpointName: "1",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
light_control: 3,
light_control_up: 4,
light_control_down: 5,
scene: 6,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "2",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
light_control: 3,
light_control_up: 4,
light_control_down: 5,
scene: 6,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "operation_mode",
endpointName: "1",
lookup: { control_relay: 0, decoupled: 1 },
cluster: "genOnOffSwitchCfg",
attribute: "customRelayControl",
reporting: { min: 0, max: 65000, change: 0 },
description: "Relay decoupled",
}),
m.enumLookup({
name: "operation_mode",
endpointName: "2",
lookup: { control_relay: 0, decoupled: 1 },
cluster: "genOnOffSwitchCfg",
attribute: "customRelayControl",
reporting: { min: 0, max: 65000, change: 0 },
description: "Relay decoupled",
}),
m.commandsScenes({ endpointNames: ["1", "2"] }),
m.numeric({
name: "scene_id",
endpointNames: ["1", "2"],
access: "ALL",
cluster: "genScenes",
attribute: "customSceneId",
valueMin: 0,
valueMax: 255,
description: "Scene ID",
}),
m.numeric({
name: "group_id",
endpointNames: ["1", "2"],
access: "ALL",
cluster: "genScenes",
attribute: "customGroupId",
valueMin: 0,
valueMax: 65527,
description: "Group ID for scenes",
}),
m.numeric({
name: "min_level",
endpointNames: ["1", "2"],
access: "ALL",
cluster: "genLevelCtrl",
attribute: "minLevel",
valueMin: 1,
valueMax: 255,
description: "Minimum level when decreasing",
}),
m.numeric({
name: "max_level",
endpointNames: ["1", "2"],
access: "ALL",
cluster: "genLevelCtrl",
attribute: "maxLevel",
valueMin: 1,
valueMax: 255,
description: "Maximum level when increasing",
}),
],
meta: {},
ota: true,
},
{
zigbeeModel: ["TS011F-SlD"],
model: "TS011F_plug-SlD",
vendor: "Slacky-DIY",
description: "Plug with power monitoring",
extend: [
m.onOff({ powerOnBehavior: true }),
m.binary({
name: "key_lock",
valueOn: ["LOCK", 1],
valueOff: ["UNLOCK", 0],
cluster: "genOnOff",
attribute: { ID: attrPlugKeyLock, type: 0x10 },
description: "Key lock enable/disable",
}),
m.enumLookup({
name: "led_control",
lookup: { off: 0, on: 1, "on/off": 2 },
cluster: "genOnOff",
attribute: { ID: attrPlugLedCtrl, type: 0x30 },
description: "Led control",
}),
m.electricityMeter({
current: { divisor: 100 },
voltage: { divisor: 100 },
power: { divisor: 1 },
energy: { divisor: 100 },
acFrequency: { divisor: 100 },
}),
m.deviceAddCustomCluster("seMetering", {
name: "seMetering",
ID: 0x0702,
attributes: {},
commands: {
resetEnergyMeters: {
name: "resetEnergyMeters",
ID: 0x80,
parameters: [],
},
},
commandsResponse: {},
}),
energyResetExtend.energyReset(),
m.binary({
name: "protect_control",
valueOn: ["ON", 1],
valueOff: ["OFF", 0],
cluster: "haElectricalMeasurement",
attribute: { ID: attrPlugSwitchProtectCtrl, type: 0x10 },
description: "Protection control enable/disable",
}),
m.binary({
name: "automatic_restart",
valueOn: ["ON", 1],
valueOff: ["OFF", 0],
cluster: "haElectricalMeasurement",
attribute: { ID: attrPlugSwitchAutoRestart, type: 0x10 },
description: "Automatic restart enable/disable for voltage only",
}),
m.numeric({
name: "voltage_min",
unit: "V",
cluster: "haElectricalMeasurement",
attribute: "rmsExtremeUnderVoltage",
description: "Minimum voltage value",
valueMin: 0,
valueMax: 300,
scale: 100,
}),
m.numeric({
name: "voltage_max",
unit: "V",
cluster: "haElectricalMeasurement",
attribute: "rmsExtremeOverVoltage",
description: "Maximum voltage value",
valueMin: 0,
valueMax: 300,
scale: 100,
}),
m.numeric({
name: "current_max",
unit: "A",
cluster: "haElectricalMeasurement",
attribute: { ID: attrPlugSwitchCurrentMax, type: 0x21 },
description: "Maximum current value",
scale: 100,
valueMin: 0,
valueMax: 16,
valueStep: 0.1,
}),
m.numeric({
name: "power_max",
unit: "W",
cluster: "haElectricalMeasurement",
attribute: { ID: attrPlugSwitchPowerMax, type: 0x29 },
description: "Maximum power value",
valueMin: 0,
valueMax: 3600,
}),
m.numeric({
name: "time_reload",
unit: "sec",
cluster: "haElectricalMeasurement",
attribute: { ID: attrPlugSwitchTimeReload, type: 0x21 },
description: "Reload time",
valueMin: 5,
valueMax: 60,
}),
],
meta: {},
ota: true,
},
{
zigbeeModel: ["TS0001_power-SlD"],
model: "TS0001_power-SlD",
vendor: "Slacky-DIY",
description: "Switch with power monitoring",
extend: [
m.onOff({ powerOnBehavior: true }),
m.commandsOnOff(),
localActionExtend(),
m.enumLookup({
name: "switch_actions",
lookup: { off: 0, on: 1 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_type",
lookup: { toggle: 0, momentary: 1, multifunction: 2 },
cluster: "genOnOffSwitchCfg",
attribute: { ID: 0xf000, type: 0x30 },
description: "Switch 1 type",
}),
m.enumLookup({
name: "operation_mode",
lookup: { control_relay: 0, decoupled: 1 },
cluster: "genOnOffSwitchCfg",
attribute: { ID: 0xf001, type: 0x30 },
reporting: { min: 0, max: 65000, change: 0 },
description: "Relay decoupled",
}),
m.electricityMeter({
current: { divisor: 100 },
voltage: { divisor: 100 },
power: { divisor: 1 },
energy: { divisor: 100 },
acFrequency: { divisor: 100 },
}),
m.deviceAddCustomCluster("seMetering", {
name: "seMetering",
ID: 0x0702,
attributes: {},
commands: {
resetEnergyMeters: {
name: "resetEnergyMeters",
ID: 0x80,
parameters: [],
},
},
commandsResponse: {},
}),
energyResetExtend.energyReset(),
m.binary({
name: "protect_control",
valueOn: ["ON", 1],
valueOff: ["OFF", 0],
cluster: "haElectricalMeasurement",
attribute: { ID: attrPlugSwitchProtectCtrl, type: 0x10 },
description: "Protection control enable/disable",
}),
m.binary({
name: "automatic_restart",
valueOn: ["ON", 1],
valueOff: ["OFF", 0],
cluster: "haElectricalMeasurement",
attribute: { ID: attrPlugSwitchAutoRestart, type: 0x10 },
description: "Automatic restart enable/disable for voltage only",
}),
m.numeric({
name: "voltage_min",
unit: "V",
cluster: "haElectricalMeasurement",
attribute: "rmsExtremeUnderVoltage",
description: "Minimum voltage value",
valueMin: 0,
valueMax: 300,
scale: 100,
}),
m.numeric({
name: "voltage_max",
unit: "V",
cluster: "haElectricalMeasurement",
attribute: "rmsExtremeOverVoltage",
description: "Maximum voltage value",
valueMin: 0,
valueMax: 300,
scale: 100,
}),
m.numeric({
name: "current_max",
unit: "A",
cluster: "haElectricalMeasurement",
attribute: { ID: attrPlugSwitchCurrentMax, type: 0x21 },
description: "Maximum current value",
scale: 100,
valueMin: 0,
valueMax: 16,
valueStep: 0.1,
}),
m.numeric({
name: "power_max",
unit: "W",
cluster: "haElectricalMeasurement",
attribute: { ID: attrPlugSwitchPowerMax, type: 0x29 },
description: "Maximum power value",
valueMin: 0,
valueMax: 3600,
}),
m.numeric({
name: "time_reload",
unit: "sec",
cluster: "haElectricalMeasurement",
attribute: { ID: attrPlugSwitchTimeReload, type: 0x21 },
description: "Reload time",
valueMin: 5,
valueMax: 60,
}),
],
meta: {},
ota: true,
},
{
zigbeeModel: ["TSM1-0025-SlD", "TSM1-SlD"],
model: "TSM1-SlD",
vendor: "Slacky-DIY",
description: "Tuya switch module 1 gang with custom firmware",
extend: [
m.deviceAddCustomCluster("genOnOffSwitchCfg", {
name: "genOnOffSwitchCfg",
ID: 0x0007,
attributes: {
customSwitchType: {
name: "customSwitchType",
ID: attrSwitchType,
type: 0x30,
write: true,
max: 0xff,
},
customRelayControl: {
name: "customRelayControl",
ID: attrSwitchDecoupled,
type: 0x30,
write: true,
max: 0xff,
},
customDeviceModelNumber: {
name: "customDeviceModelNumber",
ID: attrDeviceModelNumber,
type: 0x30,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceAddCustomCluster("genLevelCtrl", {
name: "genLevelCtrl",
ID: 0x0008,
attributes: {
minLevel: {
name: "minLevel",
ID: 0x0002,
type: 0x20,
write: true,
max: 0xff,
},
maxLevel: {
name: "maxLevel",
ID: 0x0003,
type: 0x20,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
m.text({
name: "model_number",
cluster: "genBasic",
attribute: "productLabel",
access: "STATE_GET",
description: "Switch model number",
}),
m.onOff({ powerOnBehavior: true }),
m.commandsOnOff(),
localActionExtend({ reporting: false }),
m.commandsLevelCtrl(),
m.enumLookup({
name: "switch_actions",
lookup: { off: 0, on: 1 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_type",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "operation_mode",
lookup: { control_relay: 0, decoupled: 1 },
cluster: "genOnOffSwitchCfg",
attribute: "customRelayControl",
reporting: { min: 0, max: 65000, change: 0 },
description: "Relay decoupled",
}),
m.numeric({
name: "min_level",
access: "ALL",
cluster: "genLevelCtrl",
attribute: "minLevel",
valueMin: 1,
valueMax: 255,
description: "Minimum level when decreasing",
}),
m.numeric({
name: "max_level",
access: "ALL",
cluster: "genLevelCtrl",
attribute: "maxLevel",
valueMin: 1,
valueMax: 255,
description: "Maximum level when increasing",
}),
],
meta: {},
ota: true,
},
{
zigbeeModel: ["TS0203-z20-SlD"],
model: "TS0203-z-Sld",
vendor: "Slacky-DIY",
description: "Tuya door/window sensor with custom firmware",
toZigbee: [tzLocal.device_model_number],
extend: [
m.deviceAddCustomCluster("genOnOffSwitchCfg", {
name: "genOnOffSwitchCfg",
ID: 0x0007,
attributes: {
customDelayOn: {
name: "customDelayOn",
ID: attrDoorDelayOn,
type: 0x20,
write: true,
max: 0xff,
},
customDelayOff: {
name: "customDelayOff",
ID: attrDoorDelayOff,
type: 0x20,
write: true,
max: 0xff,
},
customDeviceModelNumber: {
name: "customDeviceModelNumber",
ID: attrDeviceModelNumber,
type: 0x30,
write: true,
max: 0xff,
},
customOnCmdOff: {
name: "customOnCmdOff",
ID: attrDoorOnCmdOff,
type: 0x10,
write: true,
max: 0x01,
},
customOffCmdOff: {
name: "customOffCmdOff",
ID: attrDoorOffCmdOff,
type: 0x10,
write: true,
max: 0x01,
},
},
commands: {},
commandsResponse: {},
}),
m.text({
name: "model_number",
cluster: "genBasic",
attribute: "productLabel",
access: "STATE_GET",
description: "Door sensor model number",
}),
m.iasZoneAlarm({ zoneType: "contact", zoneAttributes: ["alarm_1"] }),
m.battery({
voltage: true,
voltageReporting: true,
percentageReportingConfig: { min: 3600, max: 0, change: 0 },
voltageReportingConfig: { min: 3600, max: 0, change: 0 },
}),
m.enumLookup({
name: "switch_actions",
lookup: { off: 0, on: 1, toggle: 2 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.numeric({
name: "delay_on",
unit: "sec",
cluster: "genOnOffSwitchCfg",
attribute: "customDelayOn",
description: "Delay On",
valueMin: 0,
valueMax: 120,
}),
m.numeric({
name: "delay_off",
unit: "sec",
cluster: "genOnOffSwitchCfg",
attribute: "customDelayOff",
description: "Delay Off",
valueMin: 0,
valueMax: 120,
}),
m.binary({
name: "on_command_off",
valueOn: ["ON", 0x01],
valueOff: ["OFF", 0x00],
cluster: "genOnOffSwitchCfg",
attribute: "customOnCmdOff",
description: "Disable command 'On'",
}),
m.binary({
name: "off_command_off",
valueOn: ["ON", 0x01],
valueOff: ["OFF", 0x00],
cluster: "genOnOffSwitchCfg",
attribute: "customOffCmdOff",
description: "Disable command 'Off'",
}),
],
meta: {},
ota: true,
},
{
fingerprint: [
{ modelID: "TS0041-M001-SlD", manufacturerName: "Slacky-DIY" },
{ modelID: "TS0041-M002-SlD", manufacturerName: "Slacky-DIY" },
{ modelID: "TS0041-M005-SlD", manufacturerName: "Slacky-DIY" },
],
model: "TS0041-M001-SlD",
vendor: "Slacky-DIY",
description: "Tuya wireless switch with 1 buttons with custom firmware",
whiteLabel: [
{ model: "TS0041-M002-SlD", fingerprint: [{ modelID: "TS0041-M002-SlD" }] },
{ model: "TS0041-M005-SlD", fingerprint: [{ modelID: "TS0041-M005-SlD" }] },
],
extend: [
m.deviceAddCustomCluster("genOnOffSwitchCfg", {
name: "genOnOffSwitchCfg",
ID: 0x0007,
attributes: {
customSwitchType: {
name: "customSwitchType",
ID: attrSwitchType,
type: 0x30,
write: true,
max: 0xff,
},
customDeviceModelNumber: {
name: "customDeviceModelNumber",
ID: attrDeviceModelNumber,
type: 0x30,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceAddCustomCluster("genLevelCtrl", {
name: "genLevelCtrl",
ID: 0x0008,
attributes: {
minLevel: {
name: "minLevel",
ID: 0x0002,
type: 0x20,
write: true,
max: 0xff,
},
maxLevel: {
name: "maxLevel",
ID: 0x0003,
type: 0x20,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceAddCustomCluster("genScenes", {
name: "genScenes",
ID: 0x0005,
attributes: {
customSceneId: {
name: "customSceneId",
ID: attrSceneId,
type: 0x20,
write: true,
max: 0xff,
},
customGroupId: {
name: "customGroupId",
ID: attrGroupId,
type: 0x21,
write: true,
max: 0xffff,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceEndpoints({ endpoints: { "1": 1 } }),
m.battery({
percentageReportingConfig: { min: 3600, max: 14400, change: 0 },
}),
m.commandsOnOff({ endpointNames: ["1"] }),
localActionExtend({
endpointNames: ["1"],
reporting: false,
}),
m.commandsLevelCtrl({ endpointNames: ["1"] }),
m.commandsColorCtrl({ endpointNames: ["1"] }),
m.enumLookup({
name: "switch_actions",
endpointName: "1",
lookup: { off: 0, on: 1, toggle: 2 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_type",
endpointName: "1",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
move_to_color_temperature: 6,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.commandsScenes({ endpointNames: ["1"] }),
m.numeric({
name: "scene_id",
access: "ALL",
endpointNames: ["1"],
cluster: "genScenes",
attribute: "customSceneId",
reporting: false,
valueMin: 0,
valueMax: 255,
description: "Scene ID",
}),
m.numeric({
name: "group_id",
access: "ALL",
endpointNames: ["1"],
cluster: "genScenes",
attribute: "customGroupId",
reporting: false,
valueMin: 0,
valueMax: 65527,
description: "Group ID for scenes",
}),
m.numeric({
name: "min_level",
endpointNames: ["1"],
access: "ALL",
cluster: "genLevelCtrl",
attribute: "minLevel",
valueMin: 1,
valueMax: 255,
description: "Minimum level when decreasing",
}),
m.numeric({
name: "max_level",
endpointNames: ["1"],
access: "ALL",
cluster: "genLevelCtrl",
attribute: "maxLevel",
valueMin: 1,
valueMax: 255,
description: "Maximum level when increasing",
}),
],
meta: {},
ota: true,
},
{
fingerprint: [
{ modelID: "TS0042-z-SlD", manufacturerName: "Slacky-DIY" },
{ modelID: "TS0042-M003-SlD", manufacturerName: "Slacky-DIY" },
{ modelID: "TS0042-M006-SlD", manufacturerName: "Slacky-DIY" },
],
model: "TS0042-z-SlD",
vendor: "Slacky-DIY",
description: "Tuya wireless switch with 2 buttons with custom firmware",
whiteLabel: [
{ model: "TS0042-M003-SlD", fingerprint: [{ modelID: "TS0042-M003-SlD" }] },
{ model: "TS0042-M006-SlD", fingerprint: [{ modelID: "TS0042-M006-SlD" }] },
],
extend: [
m.deviceAddCustomCluster("genOnOffSwitchCfg", {
name: "genOnOffSwitchCfg",
ID: 0x0007,
attributes: {
customSwitchType: {
name: "customSwitchType",
ID: attrSwitchType,
type: 0x30,
write: true,
max: 0xff,
},
customDeviceModelNumber: {
name: "customDeviceModelNumber",
ID: attrDeviceModelNumber,
type: 0x30,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceAddCustomCluster("genLevelCtrl", {
name: "genLevelCtrl",
ID: 0x0008,
attributes: {
minLevel: {
name: "minLevel",
ID: 0x0002,
type: 0x20,
write: true,
max: 0xff,
},
maxLevel: {
name: "maxLevel",
ID: 0x0003,
type: 0x20,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceAddCustomCluster("genScenes", {
name: "genScenes",
ID: 0x0005,
attributes: {
customSceneId: {
name: "customSceneId",
ID: attrSceneId,
type: 0x20,
write: true,
max: 0xff,
},
customGroupId: {
name: "customGroupId",
ID: attrGroupId,
type: 0x21,
write: true,
max: 0xffff,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceEndpoints({ endpoints: { "1": 1, "2": 2 } }),
m.battery({
percentageReportingConfig: { min: 3600, max: 14400, change: 0 },
}),
m.commandsOnOff({ endpointNames: ["1", "2"] }),
localActionExtend({
endpointNames: ["1", "2"],
reporting: false,
}),
m.commandsLevelCtrl({ endpointNames: ["1", "2"] }),
m.commandsColorCtrl({ endpointNames: ["1", "2"] }),
m.enumLookup({
name: "switch_actions",
endpointName: "1",
lookup: { off: 0, on: 1, toggle: 2 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "2",
lookup: { off: 0, on: 1, toggle: 2 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_type",
endpointName: "1",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "2",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.commandsScenes({ endpointNames: ["1", "2"] }),
m.numeric({
name: "scene_id",
endpointNames: ["1", "2"],
access: "ALL",
cluster: "genScenes",
attribute: "customSceneId",
valueMin: 0,
valueMax: 255,
description: "Scene ID",
}),
m.numeric({
name: "group_id",
endpointNames: ["1", "2"],
access: "ALL",
cluster: "genScenes",
attribute: "customGroupId",
valueMin: 0,
valueMax: 65527,
description: "Group ID for scenes",
}),
m.numeric({
name: "min_level",
endpointNames: ["1", "2"],
access: "ALL",
cluster: "genLevelCtrl",
attribute: "minLevel",
valueMin: 1,
valueMax: 255,
description: "Minimum level when decreasing",
}),
m.numeric({
name: "max_level",
endpointNames: ["1", "2"],
access: "ALL",
cluster: "genLevelCtrl",
attribute: "maxLevel",
valueMin: 1,
valueMax: 255,
description: "Maximum level when increasing",
}),
],
meta: {},
ota: true,
},
{
fingerprint: [
{ modelID: "TS0043-z-SlD", manufacturerName: "Slacky-DIY" },
{ modelID: "TS0043-M007-SlD", manufacturerName: "Slacky-DIY" },
],
model: "TS0043-z-SlD",
vendor: "Slacky-DIY",
description: "Tuya wireless switch with 3 buttons with custom firmware",
whiteLabel: [{ model: "TS0043-M007-SlD", fingerprint: [{ modelID: "TS0043-M007-SlD" }] }],
extend: [
m.deviceAddCustomCluster("genOnOffSwitchCfg", {
name: "genOnOffSwitchCfg",
ID: 0x0007,
attributes: {
customSwitchType: {
name: "customSwitchType",
ID: attrSwitchType,
type: 0x30,
write: true,
max: 0xff,
},
customDeviceModelNumber: {
name: "customDeviceModelNumber",
ID: attrDeviceModelNumber,
type: 0x30,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceAddCustomCluster("genLevelCtrl", {
name: "genLevelCtrl",
ID: 0x0008,
attributes: {
minLevel: {
name: "minLevel",
ID: 0x0002,
type: 0x20,
write: true,
max: 0xff,
},
maxLevel: {
name: "maxLevel",
ID: 0x0003,
type: 0x20,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceAddCustomCluster("genScenes", {
name: "genScenes",
ID: 0x0005,
attributes: {
customSceneId: {
name: "customSceneId",
ID: attrSceneId,
type: 0x20,
write: true,
max: 0xff,
},
customGroupId: {
name: "customGroupId",
ID: attrGroupId,
type: 0x21,
write: true,
max: 0xffff,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceEndpoints({ endpoints: { "1": 1, "2": 2, "3": 3 } }),
m.battery({
percentageReportingConfig: { min: 3600, max: 14400, change: 0 },
}),
m.commandsOnOff({ endpointNames: ["1", "2", "3"] }),
localActionExtend({
endpointNames: ["1", "2", "3"],
reporting: false,
}),
m.commandsLevelCtrl({ endpointNames: ["1", "2", "3"] }),
m.commandsColorCtrl({ endpointNames: ["1", "2", "3"] }),
m.enumLookup({
name: "switch_actions",
endpointName: "1",
lookup: { off: 0, on: 1, toggle: 2 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "2",
lookup: { off: 0, on: 1, toggle: 2 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "3",
lookup: { off: 0, on: 1, toggle: 2 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_type",
endpointName: "1",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "2",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "3",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.commandsScenes({ endpointNames: ["1", "2", "3"] }),
m.numeric({
name: "scene_id",
endpointNames: ["1", "2", "3"],
access: "ALL",
cluster: "genScenes",
attribute: "customSceneId",
valueMin: 0,
valueMax: 255,
description: "Scene ID",
}),
m.numeric({
name: "group_id",
endpointNames: ["1", "2", "3"],
access: "ALL",
cluster: "genScenes",
attribute: "customGroupId",
valueMin: 0,
valueMax: 65527,
description: "Group ID for scenes",
}),
m.numeric({
name: "min_level",
endpointNames: ["1", "2", "3"],
access: "ALL",
cluster: "genLevelCtrl",
attribute: "minLevel",
valueMin: 1,
valueMax: 255,
description: "Minimum level when decreasing",
}),
m.numeric({
name: "max_level",
endpointNames: ["1", "2", "3"],
access: "ALL",
cluster: "genLevelCtrl",
attribute: "maxLevel",
valueMin: 1,
valueMax: 255,
description: "Maximum level when increasing",
}),
],
meta: {},
ota: true,
},
{
fingerprint: [
{ modelID: "TS0044-z-SlD", manufacturerName: "Slacky-DIY" },
{ modelID: "TS0044-M004-SlD", manufacturerName: "Slacky-DIY" },
],
model: "TS0044-z-SlD",
vendor: "Slacky-DIY",
description: "Tuya wireless switch with 4 buttons with custom firmware",
whiteLabel: [{ model: "TS0044-M004-SlD", fingerprint: [{ modelID: "TS0044-M004-SlD" }] }],
extend: [
m.deviceAddCustomCluster("genOnOffSwitchCfg", {
name: "genOnOffSwitchCfg",
ID: 0x0007,
attributes: {
customSwitchType: {
name: "customSwitchType",
ID: attrSwitchType,
type: 0x30,
write: true,
max: 0xff,
},
customDeviceModelNumber: {
name: "customDeviceModelNumber",
ID: attrDeviceModelNumber,
type: 0x30,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceAddCustomCluster("genLevelCtrl", {
name: "genLevelCtrl",
ID: 0x0008,
attributes: {
minLevel: {
name: "minLevel",
ID: 0x0002,
type: 0x20,
write: true,
max: 0xff,
},
maxLevel: {
name: "maxLevel",
ID: 0x0003,
type: 0x20,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceAddCustomCluster("genScenes", {
name: "genScenes",
ID: 0x0005,
attributes: {
customSceneId: {
name: "customSceneId",
ID: attrSceneId,
type: 0x20,
write: true,
max: 0xff,
},
customGroupId: {
name: "customGroupId",
ID: attrGroupId,
type: 0x21,
write: true,
max: 0xffff,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceEndpoints({ endpoints: { "1": 1, "2": 2, "3": 3, "4": 4 } }),
m.battery({
percentageReportingConfig: { min: 3600, max: 14400, change: 0 },
}),
m.commandsOnOff({ endpointNames: ["1", "2", "3", "4"] }),
localActionExtend({
endpointNames: ["1", "2", "3", "4"],
reporting: false,
}),
m.commandsLevelCtrl({ endpointNames: ["1", "2", "3", "4"] }),
m.commandsColorCtrl({ endpointNames: ["1", "2", "3", "4"] }),
m.enumLookup({
name: "switch_actions",
endpointName: "1",
lookup: { off: 0, on: 1, toggle: 2 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "2",
lookup: { off: 0, on: 1, toggle: 2 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "3",
lookup: { off: 0, on: 1, toggle: 2 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "4",
lookup: { off: 0, on: 1, toggle: 2 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_type",
endpointName: "1",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "2",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "3",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "4",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.commandsScenes({ endpointNames: ["1", "2", "3", "4"] }),
m.numeric({
name: "scene_id",
endpointNames: ["1", "2", "3", "4"],
access: "ALL",
cluster: "genScenes",
attribute: "customSceneId",
valueMin: 0,
valueMax: 255,
description: "Scene ID",
}),
m.numeric({
name: "group_id",
endpointNames: ["1", "2", "3", "4"],
access: "ALL",
cluster: "genScenes",
attribute: "customGroupId",
valueMin: 0,
valueMax: 65527,
description: "Group ID for scenes",
}),
m.numeric({
name: "min_level",
endpointNames: ["1", "2", "3", "4"],
access: "ALL",
cluster: "genLevelCtrl",
attribute: "minLevel",
valueMin: 1,
valueMax: 255,
description: "Minimum level when decreasing",
}),
m.numeric({
name: "max_level",
endpointNames: ["1", "2", "3", "4"],
access: "ALL",
cluster: "genLevelCtrl",
attribute: "maxLevel",
valueMin: 1,
valueMax: 255,
description: "Maximum level when increasing",
}),
],
meta: {},
ota: true,
},
{
zigbeeModel: ["TS0046-z-SlD"],
model: "TS0046-z-SlD",
vendor: "Slacky-DIY",
description: "Tuya wireless switch with 6 buttons with custom firmware",
extend: [
m.deviceAddCustomCluster("genOnOffSwitchCfg", {
name: "genOnOffSwitchCfg",
ID: 0x0007,
attributes: {
customSwitchType: {
name: "customSwitchType",
ID: attrSwitchType,
type: 0x30,
write: true,
max: 0xff,
},
customDeviceModelNumber: {
name: "customDeviceModelNumber",
ID: attrDeviceModelNumber,
type: 0x30,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceAddCustomCluster("genLevelCtrl", {
name: "genLevelCtrl",
ID: 0x0008,
attributes: {
minLevel: {
name: "minLevel",
ID: 0x0002,
type: 0x20,
write: true,
max: 0xff,
},
maxLevel: {
name: "maxLevel",
ID: 0x0003,
type: 0x20,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceAddCustomCluster("genScenes", {
name: "genScenes",
ID: 0x0005,
attributes: {
customSceneId: {
name: "customSceneId",
ID: attrSceneId,
type: 0x20,
write: true,
max: 0xff,
},
customGroupId: {
name: "customGroupId",
ID: attrGroupId,
type: 0x21,
write: true,
max: 0xffff,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceEndpoints({ endpoints: { "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6 } }),
m.battery({
percentageReportingConfig: { min: 3600, max: 14400, change: 0 },
}),
m.commandsOnOff({ endpointNames: ["1", "2", "3", "4", "5", "6"] }),
localActionExtend({
endpointNames: ["1", "2", "3", "4", "5", "6"],
reporting: false,
}),
m.commandsLevelCtrl({ endpointNames: ["1", "2", "3", "4", "5", "6"] }),
m.commandsColorCtrl({ endpointNames: ["1", "2", "3", "4", "5", "6"] }),
m.enumLookup({
name: "switch_actions",
endpointName: "1",
lookup: { off: 0, on: 1, toggle: 2 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "2",
lookup: { off: 0, on: 1, toggle: 2 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "3",
lookup: { off: 0, on: 1, toggle: 2 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "4",
lookup: { off: 0, on: 1, toggle: 2 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "5",
lookup: { off: 0, on: 1, toggle: 2 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "6",
lookup: { off: 0, on: 1, toggle: 2 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_type",
endpointName: "1",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "2",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "3",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "4",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "5",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "6",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.commandsScenes({ endpointNames: ["1", "2", "3", "4", "5", "6"] }),
m.numeric({
name: "scene_id",
endpointNames: ["1", "2", "3", "4", "5", "6"],
access: "ALL",
cluster: "genScenes",
attribute: "customSceneId",
valueMin: 0,
valueMax: 255,
description: "Scene ID",
}),
m.numeric({
name: "group_id",
endpointNames: ["1", "2", "3", "4", "5", "6"],
access: "ALL",
cluster: "genScenes",
attribute: "customGroupId",
valueMin: 0,
valueMax: 65527,
description: "Group ID for scenes",
}),
m.numeric({
name: "min_level",
endpointNames: ["1", "2", "3", "4", "5", "6"],
access: "ALL",
cluster: "genLevelCtrl",
attribute: "minLevel",
valueMin: 1,
valueMax: 255,
description: "Minimum level when decreasing",
}),
m.numeric({
name: "max_level",
endpointNames: ["1", "2", "3", "4", "5", "6"],
access: "ALL",
cluster: "genLevelCtrl",
attribute: "maxLevel",
valueMin: 1,
valueMax: 255,
description: "Maximum level when increasing",
}),
],
meta: {},
ota: true,
},
{
zigbeeModel: ["FreePad-20K-SlD"],
model: "FreePad-20K-SlD",
vendor: "Slacky-DIY",
description: "DIY 20 buttons keypad",
extend: [
m.deviceAddCustomCluster("genOnOffSwitchCfg", {
name: "genOnOffSwitchCfg",
ID: 0x0007,
attributes: {
customSwitchType: {
name: "customSwitchType",
ID: attrSwitchType,
type: 0x30,
write: true,
max: 0xff,
},
customDeviceModelNumber: {
name: "customDeviceModelNumber",
ID: attrDeviceModelNumber,
type: 0x30,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceAddCustomCluster("genLevelCtrl", {
name: "genLevelCtrl",
ID: 0x0008,
attributes: {
minLevel: {
name: "minLevel",
ID: 0x0002,
type: 0x20,
write: true,
max: 0xff,
},
maxLevel: {
name: "maxLevel",
ID: 0x0003,
type: 0x20,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceAddCustomCluster("genScenes", {
name: "genScenes",
ID: 0x0005,
attributes: {
customSceneId: {
name: "customSceneId",
ID: attrSceneId,
type: 0x20,
write: true,
max: 0xff,
},
customGroupId: {
name: "customGroupId",
ID: attrGroupId,
type: 0x21,
write: true,
max: 0xffff,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceEndpoints({
endpoints: {
"1": 1,
"2": 2,
"3": 3,
"4": 4,
"5": 5,
"6": 6,
"7": 7,
"8": 8,
"9": 9,
"10": 10,
"11": 11,
"12": 12,
"13": 13,
"14": 14,
"15": 15,
"16": 16,
"17": 17,
"18": 18,
"19": 19,
"20": 20,
},
}),
m.battery({
percentageReportingConfig: { min: 3600, max: 14400, change: 0 },
}),
m.commandsOnOff({
endpointNames: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20"],
}),
localActionExtend({
endpointNames: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20"],
reporting: false,
}),
m.commandsLevelCtrl({
endpointNames: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20"],
}),
m.commandsColorCtrl({
endpointNames: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20"],
}),
m.enumLookup({
name: "switch_actions",
endpointName: "1",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "2",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "3",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "4",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "5",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "6",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "7",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "8",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "9",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "10",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "11",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "12",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "13",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "14",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "15",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "16",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "17",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "18",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "19",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "20",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_type",
endpointName: "1",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "2",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "3",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "4",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "5",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "6",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "7",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "8",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "9",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "10",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "11",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "12",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "13",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "14",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "15",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "16",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "17",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "18",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "19",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "20",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.commandsScenes({
endpointNames: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20"],
}),
m.numeric({
name: "scene_id",
endpointNames: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20"],
access: "ALL",
cluster: "genScenes",
attribute: "customSceneId",
valueMin: 0,
valueMax: 255,
description: "Scene ID",
}),
m.numeric({
name: "group_id",
endpointNames: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20"],
access: "ALL",
cluster: "genScenes",
attribute: "customGroupId",
valueMin: 0,
valueMax: 65527,
description: "Group ID for scenes",
}),
m.numeric({
name: "min_level",
endpointNames: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20"],
access: "ALL",
cluster: "genLevelCtrl",
attribute: "minLevel",
valueMin: 1,
valueMax: 255,
description: "Minimum level when decreasing",
}),
m.numeric({
name: "max_level",
endpointNames: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20"],
access: "ALL",
cluster: "genLevelCtrl",
attribute: "maxLevel",
valueMin: 1,
valueMax: 255,
description: "Maximum level when increasing",
}),
],
meta: {},
ota: true,
},
{
zigbeeModel: ["FreePad-12K-SlD"],
model: "FreePad-12K-SlD",
vendor: "Slacky-DIY",
description: "DIY 12 buttons keypad",
extend: [
m.deviceAddCustomCluster("genOnOffSwitchCfg", {
name: "genOnOffSwitchCfg",
ID: 0x0007,
attributes: {
customSwitchType: {
name: "customSwitchType",
ID: attrSwitchType,
type: 0x30,
write: true,
max: 0xff,
},
customDeviceModelNumber: {
name: "customDeviceModelNumber",
ID: attrDeviceModelNumber,
type: 0x30,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceAddCustomCluster("genLevelCtrl", {
name: "genLevelCtrl",
ID: 0x0008,
attributes: {
minLevel: {
name: "minLevel",
ID: 0x0002,
type: 0x20,
write: true,
max: 0xff,
},
maxLevel: {
name: "maxLevel",
ID: 0x0003,
type: 0x20,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceAddCustomCluster("genScenes", {
name: "genScenes",
ID: 0x0005,
attributes: {
customSceneId: {
name: "customSceneId",
ID: attrSceneId,
type: 0x20,
write: true,
max: 0xff,
},
customGroupId: {
name: "customGroupId",
ID: attrGroupId,
type: 0x21,
write: true,
max: 0xffff,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceEndpoints({
endpoints: {
"1": 1,
"2": 2,
"3": 3,
"4": 4,
"5": 5,
"6": 6,
"7": 7,
"8": 8,
"9": 9,
"10": 10,
"11": 11,
"12": 12,
},
}),
m.battery({
percentageReportingConfig: { min: 3600, max: 14400, change: 0 },
}),
m.commandsOnOff({
endpointNames: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"],
}),
localActionExtend({
endpointNames: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"],
reporting: false,
}),
m.commandsLevelCtrl({
endpointNames: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"],
}),
m.commandsColorCtrl({
endpointNames: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"],
}),
m.enumLookup({
name: "switch_actions",
endpointName: "1",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "2",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "3",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "4",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "5",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "6",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "7",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "8",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "9",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "10",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "11",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "12",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_type",
endpointName: "1",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "2",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "3",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "4",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "5",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "6",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "7",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "8",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "9",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "10",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "11",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "12",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.commandsScenes({
endpointNames: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"],
}),
m.numeric({
name: "scene_id",
endpointNames: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"],
access: "ALL",
cluster: "genScenes",
attribute: "customSceneId",
valueMin: 0,
valueMax: 255,
description: "Scene ID",
}),
m.numeric({
name: "group_id",
endpointNames: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"],
access: "ALL",
cluster: "genScenes",
attribute: "customGroupId",
valueMin: 0,
valueMax: 65527,
description: "Group ID for scenes",
}),
m.numeric({
name: "min_level",
endpointNames: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"],
access: "ALL",
cluster: "genLevelCtrl",
attribute: "minLevel",
valueMin: 1,
valueMax: 255,
description: "Minimum level when decreasing",
}),
m.numeric({
name: "max_level",
endpointNames: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"],
access: "ALL",
cluster: "genLevelCtrl",
attribute: "maxLevel",
valueMin: 1,
valueMax: 255,
description: "Maximum level when increasing",
}),
],
meta: {},
ota: true,
},
{
zigbeeModel: ["FreePad-08K-SlD"],
model: "FreePad-08K-SlD",
vendor: "Slacky-DIY",
description: "DIY 8 buttons keypad",
extend: [
m.deviceAddCustomCluster("genOnOffSwitchCfg", {
name: "genOnOffSwitchCfg",
ID: 0x0007,
attributes: {
customSwitchType: {
name: "customSwitchType",
ID: attrSwitchType,
type: 0x30,
write: true,
max: 0xff,
},
customDeviceModelNumber: {
name: "customDeviceModelNumber",
ID: attrDeviceModelNumber,
type: 0x30,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceAddCustomCluster("genLevelCtrl", {
name: "genLevelCtrl",
ID: 0x0008,
attributes: {
minLevel: {
name: "minLevel",
ID: 0x0002,
type: 0x20,
write: true,
max: 0xff,
},
maxLevel: {
name: "maxLevel",
ID: 0x0003,
type: 0x20,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceAddCustomCluster("genScenes", {
name: "genScenes",
ID: 0x0005,
attributes: {
customSceneId: {
name: "customSceneId",
ID: attrSceneId,
type: 0x20,
write: true,
max: 0xff,
},
customGroupId: {
name: "customGroupId",
ID: attrGroupId,
type: 0x21,
write: true,
max: 0xffff,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceEndpoints({
endpoints: {
"1": 1,
"2": 2,
"3": 3,
"4": 4,
"5": 5,
"6": 6,
"7": 7,
"8": 8,
},
}),
m.battery({
percentageReportingConfig: { min: 3600, max: 14400, change: 0 },
}),
m.commandsOnOff({
endpointNames: ["1", "2", "3", "4", "5", "6", "7", "8"],
}),
localActionExtend({
endpointNames: ["1", "2", "3", "4", "5", "6", "7", "8"],
reporting: false,
}),
m.commandsLevelCtrl({
endpointNames: ["1", "2", "3", "4", "5", "6", "7", "8"],
}),
m.commandsColorCtrl({
endpointNames: ["1", "2", "3", "4", "5", "6", "7", "8"],
}),
m.enumLookup({
name: "switch_actions",
endpointName: "1",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "2",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "3",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "4",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "5",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "6",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "7",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_actions",
endpointName: "8",
lookup: {
off: 0,
on: 1,
toggle: 2,
},
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
m.enumLookup({
name: "switch_type",
endpointName: "1",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "2",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "3",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "4",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "5",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "6",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "7",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.enumLookup({
name: "switch_type",
endpointName: "8",
lookup: {
toggle: 0,
momentary: 1,
multifunction: 2,
brightness_level: 3,
brightness_level_up: 4,
brightness_level_down: 5,
move_to_color_temperature: 6,
move_to_color_temperature_up: 7,
move_to_color_temperature_down: 8,
scene: 9,
},
cluster: "genOnOffSwitchCfg",
attribute: "customSwitchType",
description: "Switch type",
}),
m.commandsScenes({
endpointNames: ["1", "2", "3", "4", "5", "6", "7", "8"],
}),
m.numeric({
name: "scene_id",
endpointNames: ["1", "2", "3", "4", "5", "6", "7", "8"],
access: "ALL",
cluster: "genScenes",
attribute: "customSceneId",
valueMin: 0,
valueMax: 255,
description: "Scene ID",
}),
m.numeric({
name: "group_id",
endpointNames: ["1", "2", "3", "4", "5", "6", "7", "8"],
access: "ALL",
cluster: "genScenes",
attribute: "customGroupId",
valueMin: 0,
valueMax: 65527,
description: "Group ID for scenes",
}),
m.numeric({
name: "min_level",
endpointNames: ["1", "2", "3", "4", "5", "6", "7", "8"],
access: "ALL",
cluster: "genLevelCtrl",
attribute: "minLevel",
valueMin: 1,
valueMax: 255,
description: "Minimum level when decreasing",
}),
m.numeric({
name: "max_level",
endpointNames: ["1", "2", "3", "4", "5", "6", "7", "8"],
access: "ALL",
cluster: "genLevelCtrl",
attribute: "maxLevel",
valueMin: 1,
valueMax: 255,
description: "Maximum level when increasing",
}),
],
meta: {},
ota: true,
},
{
zigbeeModel: ["RCS-ST16-z-SlD"],
model: "RCS-ST16-z-SlD",
vendor: "Slacky-DIY",
description: "Socket EKF with power monitoring with custom firmware",
extend: [
m.deviceAddCustomCluster("seMetering", {
name: "seMetering",
ID: 0x0702,
attributes: {},
commands: {
resetEnergyMeters: {
name: "resetEnergyMeters",
ID: 0x80,
parameters: [],
},
},
commandsResponse: {},
}),
m.deviceAddCustomCluster("haElectricalMeasurement", {
name: "haElectricalMeasurement",
ID: 0x0b04,
attributes: {
customAdjustCurrent: {
name: "customAdjustCurrent",
ID: attrSocketAdjustCurrent,
type: 0x39,
write: true,
max: 0xffffffff,
},
customAdjustVoltage: {
name: "customAdjustVoltage",
ID: attrSocketAdjustVoltage,
type: 0x39,
write: true,
max: 0xffffffff,
},
customAdjustPower: {
name: "customAdjustPower",
ID: attrSocketAdjustPower,
type: 0x39,
write: true,
max: 0xffffffff,
},
},
commands: {},
commandsResponse: {},
}),
m.onOff({ powerOnBehavior: true }),
m.binary({
name: "key_lock",
valueOn: ["LOCK", 1],
valueOff: ["UNLOCK", 0],
cluster: "genOnOff",
attribute: { ID: attrPlugKeyLock, type: 0x10 },
description: "Key lock enable/disable",
}),
m.enumLookup({
name: "led_control",
lookup: { off: 0, on: 1, "on/off": 2, "off/on": 3 },
cluster: "genOnOff",
attribute: { ID: attrPlugLedCtrl, type: 0x30 },
description: "Led control",
}),
m.electricityMeter({
current: { divisor: 100 },
voltage: { divisor: 100 },
power: { divisor: 1 },
energy: { divisor: 1000000 },
}),
energyResetExtend.energyReset(),
m.binary({
name: "protect_control",
valueOn: ["ON", 1],
valueOff: ["OFF", 0],
cluster: "haElectricalMeasurement",
attribute: { ID: attrPlugSwitchProtectCtrl, type: 0x10 },
description: "Protection control enable/disable",
}),
m.binary({
name: "automatic_restart",
valueOn: ["ON", 1],
valueOff: ["OFF", 0],
cluster: "haElectricalMeasurement",
attribute: { ID: attrPlugSwitchAutoRestart, type: 0x10 },
description: "Automatic restart enable/disable for voltage only",
}),
m.numeric({
name: "voltage_min",
unit: "V",
cluster: "haElectricalMeasurement",
attribute: "rmsExtremeUnderVoltage",
description: "Minimum voltage value",
valueMin: 0,
valueMax: 300,
scale: 100,
}),
m.numeric({
name: "voltage_max",
unit: "V",
cluster: "haElectricalMeasurement",
attribute: "rmsExtremeOverVoltage",
description: "Maximum voltage value",
valueMin: 0,
valueMax: 300,
scale: 100,
}),
m.numeric({
name: "current_max",
unit: "A",
cluster: "haElectricalMeasurement",
attribute: { ID: attrPlugSwitchCurrentMax, type: 0x21 },
description: "Maximum current value",
scale: 100,
valueMin: 0,
valueMax: 16,
valueStep: 0.1,
}),
m.numeric({
name: "power_max",
unit: "W",
cluster: "haElectricalMeasurement",
attribute: { ID: attrPlugSwitchPowerMax, type: 0x29 },
description: "Maximum power value",
valueMin: 0,
valueMax: 3600,
}),
m.numeric({
name: "time_reload",
unit: "sec",
cluster: "haElectricalMeasurement",
attribute: { ID: attrPlugSwitchTimeReload, type: 0x21 },
description: "Reload time",
valueMin: 5,
valueMax: 60,
}),
],
meta: {},
ota: true,
},
{
zigbeeModel: ["LDR-GU10-Mod"],
model: "LDR-GU10-Mod",
vendor: "Svetomaniya",
description: "Smart light Ledron LDR-GU10 with new firmware",
extend: [
m.deviceAddCustomCluster("genLevelCtrl", {
name: "genLevelCtrl",
ID: 0x0008,
attributes: {
minLevel: {
name: "minLevel",
ID: 0xf002,
type: 0x20,
write: true,
max: 0xff,
},
maxLevel: {
name: "maxLevel",
ID: 0xf003,
type: 0x20,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
m.deviceAddCustomCluster("lightingColorCtrl", {
name: "lightingColorCtrl",
ID: 0x0300,
attributes: {
startUpColorTemperature: {
name: "startUpColorTemperature",
ID: 0x4010,
type: 0x21,
write: true,
max: 0xffff,
},
},
commands: {},
commandsResponse: {},
}),
m.light({
colorTemp: { range: [153, 500] },
turnsOffAtBrightness1: true,
levelConfig: { features: ["on_transition_time", "off_transition_time", "execute_if_off", "on_level", "current_level_startup"] },
configureReporting: true,
}),
m.numeric({
name: "min_level",
cluster: "genLevelCtrl",
attribute: "minLevel",
description: "Minimum value of level",
valueMin: 1,
valueMax: 254,
}),
m.numeric({
name: "max_level",
cluster: "genLevelCtrl",
attribute: "maxLevel",
description: "Maximum value of level",
valueMin: 1,
valueMax: 254,
}),
],
meta: {},
ota: true,
},
{
zigbeeModel: ["Router-ZG-807Z-SlD"],
model: "Router-ZG-807Z-SlD",
vendor: "Slacky-DIY",
description: "Tuya router with custom firmware",
extend: [
m.deviceAddCustomCluster("SlackyDiyCustomCluster", {
name: "SlackyDiyCustomCluster",
ID: 0xff65,
manufacturerCode: 0x6565,
attributes: {
txPower: {
name: "txPower",
ID: 0x0000,
type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
write: true,
max: 0xff,
},
},
commands: {},
commandsResponse: {},
}),
m.battery({
voltage: true,
voltageReporting: true,
lowStatus: true,
percentageReportingConfig: { min: 5, max: 3600, change: 0 },
voltageReportingConfig: { min: 5, max: 3600, change: 0 },
lowStatusReportingConfig: { min: 0, max: 3600, change: 0 },
}),
m.numeric({
name: "uptime_time",
access: "STATE_GET",
cluster: "genTime",
attribute: "time",
reporting: { min: 60, max: 3600, change: 15 },
unit: "sec",
description: "Uptime of device",
}),
m.enumLookup({
name: "tx_power",
cluster: "SlackyDiyCustomCluster",
attribute: "txPower",
lookup: { "0 dBm": 0, "5 dBm": 1, "10 dBm": 2 },
reporting: false,
description: "Rf power config",
}),
m.enumLookup({
name: "switch_actions",
lookup: { on_off: 0, off_on: 1, toggle: 2 },
cluster: "genOnOffSwitchCfg",
attribute: "switchActions",
description: "Actions switch",
}),
],
ota: true,
},
];
//# sourceMappingURL=slacky_diy.js.map