"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.definitions = void 0;
const fz = __importStar(require("../converters/fromZigbee"));
const tz = __importStar(require("../converters/toZigbee"));
const exposes = __importStar(require("../lib/exposes"));
const m = __importStar(require("../lib/modernExtend"));
const 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 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,
    fz.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,
    tz.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, 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_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"],
        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: ["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.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 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",
            }),
        ],
        meta: {},
        ota: true,
    },
    {
        zigbeeModel: ["QS-Zigbee-SEC02-Mod"],
        model: "QS-Zigbee-SEC02-Mod",
        vendor: "Svetomaniya",
        description: "Smart light switch module 2 gang",
        extend: [
            m.deviceEndpoints({ endpoints: { "1": 1, "2": 2 } }),
            m.onOff({ powerOnBehavior: true, endpointNames: ["1", "2"] }),
            m.commandsOnOff({ endpointNames: ["1", "2"] }),
            localActionExtend({ endpointNames: ["1", "2"] }),
            m.enumLookup({
                name: "switch_actions",
                endpointName: "1",
                lookup: { off: 0, on: 1 },
                cluster: "genOnOffSwitchCfg",
                attribute: "switchActions",
                description: "Actions switch 1",
            }),
            m.enumLookup({
                name: "switch_actions",
                endpointName: "2",
                lookup: { off: 0, on: 1 },
                cluster: "genOnOffSwitchCfg",
                attribute: "switchActions",
                description: "Actions switch 2",
            }),
            m.enumLookup({
                name: "switch_type",
                endpointName: "1",
                lookup: { toggle: 0, momentary: 1, multifunction: 2 },
                cluster: "genOnOffSwitchCfg",
                attribute: { ID: 0xf000, type: 0x30 },
                description: "Switch 1 type",
            }),
            m.enumLookup({
                name: "switch_type",
                endpointName: "2",
                lookup: { toggle: 0, momentary: 1, multifunction: 2 },
                cluster: "genOnOffSwitchCfg",
                attribute: { ID: 0xf000, type: 0x30 },
                description: "Switch 2 type",
            }),
            m.enumLookup({
                name: "operation_mode",
                endpointName: "1",
                lookup: { control_relay: 0, decoupled: 1 },
                cluster: "genOnOffSwitchCfg",
                attribute: { ID: 0xf001, type: 0x30 },
                reporting: { min: 0, max: 65000, change: 0 },
                description: "Relay 1 decoupled",
            }),
            m.enumLookup({
                name: "operation_mode",
                endpointName: "2",
                lookup: { control_relay: 0, decoupled: 1 },
                cluster: "genOnOffSwitchCfg",
                attribute: { ID: 0xf001, type: 0x30 },
                reporting: { min: 0, max: 65000, change: 0 },
                description: "Relay 2 decoupled",
            }),
        ],
        meta: { multiEndpoint: true },
        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"],
        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.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: "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",
            }),
        ],
        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" },
        ],
        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" }] }],
        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("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.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,
                    scene: 5,
                },
                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",
            }),
        ],
        meta: {},
        ota: true,
    },
    {
        fingerprint: [
            { modelID: "TS0042-z-SlD", manufacturerName: "Slacky-DIY" },
            { modelID: "TS0042-M003-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" }] }],
        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("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.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_up: 3,
                    brightness_level_down: 4,
                    scene: 5,
                },
                cluster: "genOnOffSwitchCfg",
                attribute: "customSwitchType",
                description: "Switch type",
            }),
            m.enumLookup({
                name: "switch_type",
                endpointName: "2",
                lookup: {
                    toggle: 0,
                    momentary: 1,
                    multifunction: 2,
                    brightness_level_up: 3,
                    brightness_level_down: 4,
                    scene: 5,
                },
                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",
            }),
        ],
        meta: {},
        ota: true,
    },
    {
        zigbeeModel: ["TS0043-z-SlD"],
        model: "TS0043-z-SlD",
        vendor: "Slacky-DIY",
        description: "Tuya wireless switch with 3 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("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.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_up: 3,
                    brightness_level_down: 4,
                    scene: 5,
                },
                cluster: "genOnOffSwitchCfg",
                attribute: "customSwitchType",
                description: "Switch type",
            }),
            m.enumLookup({
                name: "switch_type",
                endpointName: "2",
                lookup: {
                    toggle: 0,
                    momentary: 1,
                    multifunction: 2,
                    brightness_level_up: 3,
                    brightness_level_down: 4,
                    scene: 5,
                },
                cluster: "genOnOffSwitchCfg",
                attribute: "customSwitchType",
                description: "Switch type",
            }),
            m.enumLookup({
                name: "switch_type",
                endpointName: "3",
                lookup: {
                    toggle: 0,
                    momentary: 1,
                    multifunction: 2,
                    brightness_level_up: 3,
                    brightness_level_down: 4,
                    scene: 5,
                },
                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",
            }),
        ],
        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("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.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_up: 3,
                    brightness_level_down: 4,
                    scene: 5,
                },
                cluster: "genOnOffSwitchCfg",
                attribute: "customSwitchType",
                description: "Switch type",
            }),
            m.enumLookup({
                name: "switch_type",
                endpointName: "2",
                lookup: {
                    toggle: 0,
                    momentary: 1,
                    multifunction: 2,
                    brightness_level_up: 3,
                    brightness_level_down: 4,
                    scene: 5,
                },
                cluster: "genOnOffSwitchCfg",
                attribute: "customSwitchType",
                description: "Switch type",
            }),
            m.enumLookup({
                name: "switch_type",
                endpointName: "3",
                lookup: {
                    toggle: 0,
                    momentary: 1,
                    multifunction: 2,
                    brightness_level_up: 3,
                    brightness_level_down: 4,
                    scene: 5,
                },
                cluster: "genOnOffSwitchCfg",
                attribute: "customSwitchType",
                description: "Switch type",
            }),
            m.enumLookup({
                name: "switch_type",
                endpointName: "4",
                lookup: {
                    toggle: 0,
                    momentary: 1,
                    multifunction: 2,
                    brightness_level_up: 3,
                    brightness_level_down: 4,
                    scene: 5,
                },
                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",
            }),
        ],
        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("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.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_up: 3,
                    brightness_level_down: 4,
                    scene: 5,
                },
                cluster: "genOnOffSwitchCfg",
                attribute: "customSwitchType",
                description: "Switch type",
            }),
            m.enumLookup({
                name: "switch_type",
                endpointName: "2",
                lookup: {
                    toggle: 0,
                    momentary: 1,
                    multifunction: 2,
                    brightness_level_up: 3,
                    brightness_level_down: 4,
                    scene: 5,
                },
                cluster: "genOnOffSwitchCfg",
                attribute: "customSwitchType",
                description: "Switch type",
            }),
            m.enumLookup({
                name: "switch_type",
                endpointName: "3",
                lookup: {
                    toggle: 0,
                    momentary: 1,
                    multifunction: 2,
                    brightness_level_up: 3,
                    brightness_level_down: 4,
                    scene: 5,
                },
                cluster: "genOnOffSwitchCfg",
                attribute: "customSwitchType",
                description: "Switch type",
            }),
            m.enumLookup({
                name: "switch_type",
                endpointName: "4",
                lookup: {
                    toggle: 0,
                    momentary: 1,
                    multifunction: 2,
                    brightness_level_up: 3,
                    brightness_level_down: 4,
                    scene: 5,
                },
                cluster: "genOnOffSwitchCfg",
                attribute: "customSwitchType",
                description: "Switch type",
            }),
            m.enumLookup({
                name: "switch_type",
                endpointName: "5",
                lookup: {
                    toggle: 0,
                    momentary: 1,
                    multifunction: 2,
                    brightness_level_up: 3,
                    brightness_level_down: 4,
                    scene: 5,
                },
                cluster: "genOnOffSwitchCfg",
                attribute: "customSwitchType",
                description: "Switch type",
            }),
            m.enumLookup({
                name: "switch_type",
                endpointName: "6",
                lookup: {
                    toggle: 0,
                    momentary: 1,
                    multifunction: 2,
                    brightness_level_up: 3,
                    brightness_level_down: 4,
                    scene: 5,
                },
                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",
            }),
        ],
        meta: {},
        ota: true,
    },
];
//# sourceMappingURL=slacky_diy.js.map