"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.definitions = void 0;
const zigbee_herdsman_1 = require("zigbee-herdsman");
const zspec_1 = require("zigbee-herdsman/dist/zspec");
const fz = __importStar(require("../converters/fromZigbee"));
const tz = __importStar(require("../converters/toZigbee"));
const constants = __importStar(require("../lib/constants"));
const exposes = __importStar(require("../lib/exposes"));
const logger_1 = require("../lib/logger");
const m = __importStar(require("../lib/modernExtend"));
const reporting = __importStar(require("../lib/reporting"));
const globalStore = __importStar(require("../lib/store"));
const utils = __importStar(require("../lib/utils"));
const utils_1 = require("../lib/utils");
const e = exposes.presets;
const ea = exposes.access;
const NS = "zhc:schneider_electric";
function indicatorMode(endpoint) {
    let description = "Set Indicator Mode.";
    if (endpoint) {
        description = `Set Indicator Mode for ${endpoint} switch.`;
    }
    return m.enumLookup({
        name: "indicator_mode",
        lookup: {
            reverse_with_load: 2,
            consistent_with_load: 0,
            always_off: 3,
            always_on: 1,
            flash_on_click: 4,
        },
        cluster: "manuSpecificSchneiderLightSwitchConfiguration",
        attribute: "ledIndication",
        description: description,
        endpointName: endpoint,
    });
}
function socketIndicatorMode() {
    return m.enumLookup({
        name: "indicator_mode",
        lookup: {
            reverse_with_load: 0,
            consistent_with_load: 1,
            always_off: 2,
            always_on: 3,
        },
        cluster: "manuSpecificSchneiderFanSwitchConfiguration",
        attribute: "ledIndication",
        description: "Set indicator mode",
    });
}
function evlinkIndicatorMode() {
    return m.enumLookup({
        name: "indicator_mode",
        lookup: {
            default: 1,
            temporary: 5,
        },
        cluster: "manuSpecificSchneiderFanSwitchConfiguration",
        attribute: "ledIndication",
        description: "Set indicator mode",
    });
}
function fanIndicatorMode() {
    const description = "Set Indicator Mode.";
    return m.enumLookup({
        name: "indicator_mode",
        lookup: {
            always_on: 3,
            on_with_timeout_but_as_locator: 4,
            on_with_timeout: 5,
        },
        cluster: "manuSpecificSchneiderFanSwitchConfiguration",
        attribute: "ledIndication",
        description: description,
    });
}
function fanIndicatorOrientation() {
    const description = "Set Indicator Orientation.";
    return m.enumLookup({
        name: "indicator_orientation",
        lookup: {
            horizontal_left: 2,
            horizontal_right: 0,
            vertical_top: 3,
            vertical_bottom: 1,
        },
        cluster: "manuSpecificSchneiderFanSwitchConfiguration",
        attribute: "ledOrientation",
        description: description,
    });
}
function switchActions(endpoint) {
    let description = "Set Switch Action.";
    if (endpoint) {
        description = `Set Switch Action for ${endpoint} Button.`;
    }
    return m.enumLookup({
        name: "switch_actions",
        lookup: {
            light: 0,
            light_opposite: 254,
            dimmer: 1,
            dimmer_opposite: 253,
            standard_shutter: 2,
            standard_shutter_opposite: 252,
            schneider_shutter: 3,
            schneider_shutter_opposite: 251,
            scene: 4,
            toggle_light: 5,
            toggle_dimmer: 6,
            alternate_light: 7,
            alternate_dimmer: 8,
            not_used: 127,
        },
        cluster: "manuSpecificSchneiderLightSwitchConfiguration",
        attribute: "switchActions",
        description: description,
        endpointName: endpoint,
    });
}
const schneiderElectricExtend = {
    addVisaConfigurationCluster: (enumDataType) => m.deviceAddCustomCluster("visaConfiguration", {
        name: "visaConfiguration",
        ID: 0xfc04,
        manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
        attributes: {
            indicatorLuminanceLevel: { name: "indicatorLuminanceLevel", ID: 0x0000, type: enumDataType, write: true },
            indicatorColor: { name: "indicatorColor", ID: 0x0001, type: enumDataType, write: true },
            indicatorMode: { name: "indicatorMode", ID: 0x0002, type: enumDataType, write: true },
            motorTypeChannel1: { name: "motorTypeChannel1", ID: 0x0003, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            motorTypeChannel2: { name: "motorTypeChannel2", ID: 0x0004, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            curtainStatusChannel1: { name: "curtainStatusChannel1", ID: 0x0005, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            curtainStatusChannel2: { name: "curtainStatusChannel2", ID: 0x0006, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            key1EventNotification: { name: "key1EventNotification", ID: 0x0020, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            key2EventNotification: { name: "key2EventNotification", ID: 0x0021, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            key3EventNotification: { name: "key3EventNotification", ID: 0x0022, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            key4EventNotification: { name: "key4EventNotification", ID: 0x0023, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
        },
        commands: {},
        commandsResponse: {},
    }),
    visaConfigIndicatorLuminanceLevel: () => {
        return m.enumLookup({
            name: "indicator_luminance_level",
            lookup: {
                "100": 0,
                "80": 1,
                "60": 2,
                "40": 3,
                "20": 4,
                "0": 5,
            },
            cluster: "visaConfiguration",
            attribute: "indicatorLuminanceLevel",
            description: "Set indicator luminance Level",
        });
    },
    visaConfigIndicatorColor: () => {
        return m.enumLookup({
            name: "indicator_color",
            lookup: {
                white: 0,
                blue: 1,
            },
            cluster: "visaConfiguration",
            attribute: "indicatorColor",
            description: "Set indicator color",
        });
    },
    visaIndicatorMode: ([reverseWithLoad, consistentWithLoad, alwaysOff, alwaysOn]) => {
        return m.enumLookup({
            name: "indicator_mode",
            lookup: {
                reverse_with_load: reverseWithLoad,
                consistent_with_load: consistentWithLoad,
                always_off: alwaysOff,
                always_on: alwaysOn,
            },
            cluster: "visaConfiguration",
            attribute: "indicatorMode",
            description: "Set indicator mode for switch",
        });
    },
    visaConfigMotorType: (channel) => {
        // TODO: was defaulting `motorTypeChannel` which is not part of the custom cluster
        const attribute = `motorTypeChannel${channel}`;
        const description = `Set motor type for channel ${channel || ""}`;
        return m.enumLookup({
            name: `motor_type${channel ? `_${channel}` : ""}`,
            lookup: {
                ac_motor: 0,
                pulse_motor: 1,
            },
            cluster: "visaConfiguration",
            attribute: attribute,
            description: description,
        });
    },
    visaConfigCurtainStatus: (channel) => {
        // TODO: was defaulting `motorTypeChannel` which is not part of the custom cluster
        const attribute = `curtainStatusChannel${channel}`;
        const description = `Set curtain status for channel ${channel}`;
        return m.enumLookup({
            access: "STATE",
            name: `curtain_status${channel ? `_${channel}` : ""}`,
            lookup: {
                stop: 0,
                opening: 1,
                closing: 2,
            },
            cluster: "visaConfiguration",
            attribute: attribute,
            description: description,
        });
    },
    visaWiserCurtain: (endpointNames) => {
        return {
            isModernExtend: true,
            fromZigbee: [
                {
                    cluster: "genLevelCtrl",
                    type: ["attributeReport", "readResponse"],
                    convert: (model, msg, publish, options, meta) => {
                        const onOffTransitionTime = Number(msg.data.onOffTransitionTime) / 10;
                        const currentLevel = utils.mapNumberRange(Number(msg.data.currentLevel), 0, 255, 0, 100);
                        const transition = (0, utils_1.postfixWithEndpointName)("transition", msg, model, meta);
                        const position = (0, utils_1.postfixWithEndpointName)("position", msg, model, meta);
                        return {
                            [transition]: onOffTransitionTime,
                            [position]: currentLevel,
                        };
                    },
                },
            ],
            toZigbee: [
                {
                    key: ["transition", "position"],
                    convertGet: async (entity, key, meta) => {
                        await entity.read("genLevelCtrl", ["onOffTransitionTime", "currentLevel"]);
                    },
                    convertSet: async (entity, key, value, meta) => {
                        if (key === "transition") {
                            await entity.write("genLevelCtrl", { onOffTransitionTime: +value * 10 }, utils.getOptions(meta.mapped, entity));
                        }
                        else if (key === "position") {
                            await entity.command("genLevelCtrl", "moveToLevelWithOnOff", { level: utils.mapNumberRange(Number(value), 0, 100, 0, 255), transtime: 0, optionsMask: 0, optionsOverride: 0 }, utils.getOptions(meta.mapped, entity));
                        }
                    },
                },
                {
                    key: ["state"],
                    convertSet: async (entity, key, value, meta) => {
                        if (value === "OPEN") {
                            await entity.command("genOnOff", "on", {}, utils.getOptions(meta.mapped, entity));
                        }
                        else if (value === "CLOSE") {
                            await entity.command("genOnOff", "off", {}, utils.getOptions(meta.mapped, entity));
                        }
                        else if (value === "STOP") {
                            await entity.command("genLevelCtrl", "stop", { optionsMask: 0, optionsOverride: 0 }, utils.getOptions(meta.mapped, entity));
                        }
                    },
                },
            ],
            exposes: [
                ...endpointNames.map((endpointName) => e.cover_position().withDescription("State of the curtain").withEndpoint(endpointName)),
                ...endpointNames.map((endpointName) => e
                    .numeric("transition", ea.ALL)
                    .withValueMin(0)
                    .withValueMax(300)
                    .withUnit("s")
                    .withDescription("Transition time in seconds")
                    .withEndpoint(endpointName)),
            ],
        };
    },
    visaKeyEventNotification: (key) => {
        return {
            isModernExtend: true,
            fromZigbee: [
                {
                    cluster: "visaConfiguration",
                    type: ["attributeReport"],
                    convert: (model, msg, publish, options, meta) => {
                        for (const key of ["1", "2", "3", "4"]) {
                            const zigbeeKey = `key${key}EventNotification`;
                            if (Object.hasOwn(msg.data, zigbeeKey)) {
                                return { action: `scene_${key}` };
                            }
                        }
                    },
                },
            ],
        };
    },
    dimmingMode: () => {
        const extend = m.enumLookup({
            name: "dimmer_mode",
            lookup: {
                Auto: 0,
                "RL-LED": 3,
            },
            cluster: "lightingBallastCfg",
            attribute: "wiserControlMode",
            description: "Auto detects the correct mode for the ballast. RL-LED may have improved dimming quality for LEDs.",
            entityCategory: "config",
            zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC },
        });
        extend.configure.push(m.setupConfigureForReading("lightingBallastCfg", ["wiserControlMode"], undefined, {
            manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
        }));
        return extend;
    },
    addOccupancyConfigurationCluster: () => m.deviceAddCustomCluster("occupancyConfiguration", {
        name: "occupancyConfiguration",
        ID: 0xff19,
        manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
        attributes: {
            ambienceLightThreshold: { name: "ambienceLightThreshold", ID: 0x0000, type: zigbee_herdsman_1.Zcl.DataType.UINT16, write: true, max: 0xffff },
            occupancyActions: { name: "occupancyActions", ID: 0x0001, type: zigbee_herdsman_1.Zcl.DataType.ENUM8, write: true, max: 0xff },
            unoccupiedLevelDflt: { name: "unoccupiedLevelDflt", ID: 0x0002, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            unoccupiedLevel: { name: "unoccupiedLevel", ID: 0x0003, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
        },
        commands: {},
        commandsResponse: {},
    }),
    occupancyConfiguration: () => {
        const extend = m.enumLookup({
            name: "occupancy_sensitivity",
            lookup: {
                Low: 50,
                Medium: 75,
                High: 100,
            },
            cluster: "msOccupancySensing",
            attribute: { ID: 0xe003, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
            zigbeeCommandOptions: {
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
            },
            description: "Sensitivity of the occupancy sensor",
            entityCategory: "config",
        });
        const luxScale = (value, type) => {
            if (type === "from") {
                return Math.round(10 ** ((value - 1) / 10000));
            }
            return Math.round(10000 * Math.log10(value) + 1);
        };
        const luxThresholdExtend = m.numeric({
            name: "ambience_light_threshold",
            cluster: "occupancyConfiguration",
            attribute: "ambienceLightThreshold",
            reporting: { min: "10_SECONDS", max: "1_HOUR", change: 5 },
            description: "Threshold above which occupancy will not trigger the light switch.",
            unit: "lx",
            scale: luxScale,
            entityCategory: "config",
            valueMin: 1,
            valueMax: 2000,
        });
        extend.fromZigbee.push(...luxThresholdExtend.fromZigbee);
        extend.toZigbee.push(...luxThresholdExtend.toZigbee);
        extend.exposes.push(...luxThresholdExtend.exposes);
        extend.configure.push(m.setupConfigureForReading("occupancyConfiguration", ["ambienceLightThreshold"]));
        return extend;
    },
    runningStateFromPower: () => {
        return {
            isModernExtend: true,
            fromZigbee: [
                {
                    cluster: "seMetering",
                    type: ["attributeReport", "readResponse"],
                    convert: (model, msg, publish, options, meta) => {
                        if ("instantaneousDemand" in msg.data) {
                            const w = Math.max(0, Number(msg.data.instantaneousDemand));
                            return { running_state: w > 0 ? "heat" : "idle" };
                        }
                    },
                },
            ],
        };
    },
    addHeatingCoolingOutputClusterServer: () => m.deviceAddCustomCluster("heatingCoolingOutputClusterServer", {
        name: "heatingCoolingOutputClusterServer",
        ID: 0xff23,
        manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
        attributes: {
            measuredTemperature: { name: "measuredTemperature", ID: 0x0000, type: zigbee_herdsman_1.Zcl.DataType.INT16, max: 0x7fff },
            absMinHeatTemperatureLimit: { name: "absMinHeatTemperatureLimit", ID: 0x0003, type: zigbee_herdsman_1.Zcl.DataType.INT16, max: 0x7fff },
            absMaxHeatTemperatureLimit: { name: "absMaxHeatTemperatureLimit", ID: 0x0004, type: zigbee_herdsman_1.Zcl.DataType.INT16, max: 0x7fff },
            absMinCoolTemperatureLimit: { name: "absMinCoolTemperatureLimit", ID: 0x0005, type: zigbee_herdsman_1.Zcl.DataType.INT16, max: 0x7fff },
            absMaxCoolTemperatureLimit: { name: "absMaxCoolTemperatureLimit", ID: 0x0006, type: zigbee_herdsman_1.Zcl.DataType.INT16, max: 0x7fff },
            minHeatTemperatureLimit: { name: "minHeatTemperatureLimit", ID: 0x0015, type: zigbee_herdsman_1.Zcl.DataType.INT16, write: true, max: 0x7fff },
            maxHeatTemperatureLimit: { name: "maxHeatTemperatureLimit", ID: 0x0016, type: zigbee_herdsman_1.Zcl.DataType.INT16, write: true, max: 0x7fff },
            minCoolTemperatureLimit: { name: "minCoolTemperatureLimit", ID: 0x0017, type: zigbee_herdsman_1.Zcl.DataType.INT16, write: true, max: 0x7fff },
            maxCoolTemperatureLimit: { name: "maxCoolTemperatureLimit", ID: 0x0018, type: zigbee_herdsman_1.Zcl.DataType.INT16, write: true, max: 0x7fff },
            heatTemperatureHighLimit: { name: "heatTemperatureHighLimit", ID: 0x0020, type: zigbee_herdsman_1.Zcl.DataType.INT16, write: true, max: 0x7fff },
            heatTemperatureLowLimit: { name: "heatTemperatureLowLimit", ID: 0x0021, type: zigbee_herdsman_1.Zcl.DataType.INT16, write: true, max: 0x7fff },
            coolTemperatureHighLimit: { name: "coolTemperatureHighLimit", ID: 0x0022, type: zigbee_herdsman_1.Zcl.DataType.INT16, write: true, max: 0x7fff },
            coolTemperatureLowLimit: { name: "coolTemperatureLowLimit", ID: 0x0023, type: zigbee_herdsman_1.Zcl.DataType.INT16, write: true, max: 0x7fff },
            coolingOutputMode: { name: "coolingOutputMode", ID: 0x0030, type: zigbee_herdsman_1.Zcl.DataType.ENUM8, write: true },
            heatingOutputMode: { name: "heatingOutputMode", ID: 0x0031, type: zigbee_herdsman_1.Zcl.DataType.ENUM8, write: true },
            maximumIdleTime: { name: "maximumIdleTime", ID: 0x0041, type: zigbee_herdsman_1.Zcl.DataType.UINT16, write: true, max: 8784 },
            antiIdleExerciseTime: { name: "antiIdleExerciseTime", ID: 0x0042, type: zigbee_herdsman_1.Zcl.DataType.UINT16, write: true, max: 3600 },
            preferredExerciseTime: { name: "preferredExerciseTime", ID: 0x0043, type: zigbee_herdsman_1.Zcl.DataType.UINT16, write: true, max: 1439 },
            minOffTime: { name: "minOffTime", ID: 0x0044, type: zigbee_herdsman_1.Zcl.DataType.UINT16, write: true },
            minOnTime: { name: "minOnTime", ID: 0x0045, type: zigbee_herdsman_1.Zcl.DataType.UINT16, write: true },
            maxOverallDutyCycle: { name: "maxOverallDutyCycle", ID: 0xe207, type: zigbee_herdsman_1.Zcl.DataType.UINT16, write: true, min: 900, max: 3600 },
            overallDutyCyclePeriod: { name: "overallDutyCyclePeriod", ID: 0xe208, type: zigbee_herdsman_1.Zcl.DataType.UINT16, write: true, max: 1440 },
            clusterRevision: { name: "clusterRevision", ID: 0xfffd, type: zigbee_herdsman_1.Zcl.DataType.UINT16, max: 0xfffe },
        },
        commands: {},
        commandsResponse: {},
    }),
    heatingOutputMode: (args) => m.enumLookup({
        name: "heating_output_mode",
        cluster: "heatingCoolingOutputClusterServer",
        attribute: "heatingOutputMode",
        description: "On devices with alternate heating output types, this selects which should be used to control the heating unit. This attribute is (mistakenly) also called pilot_mode on some devices.",
        entityCategory: "config",
        access: "ALL",
        lookup: {
            Disabled: 0,
            Relay: 1,
            OpenTherm: 2,
            "Fil Pilote": 3,
            "Relay NC": 4,
        },
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC },
        ...args,
    }),
    pilotMode: (args) => m.enumLookup({
        name: "schneider_pilot_mode",
        cluster: "heatingCoolingOutputClusterServer",
        attribute: "heatingOutputMode",
        description: "Controls piloting mode (from 'old description'). According to SE the attribute is called 'Heating output mode', and the corresponding custom cluster is heatingCoolingOutputClusterServer.",
        entityCategory: "config",
        access: "ALL",
        lookup: {
            contactor: 1,
            pilot: 3,
        },
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC },
        ...args,
    }),
    addHvacUserInterfaceCfgCustomAttributes: () => m.deviceAddCustomCluster("hvacUserInterfaceCfg", {
        name: "hvacUserInterfaceCfg",
        ID: zigbee_herdsman_1.Zcl.Clusters.hvacUserInterfaceCfg.ID,
        attributes: {
            displayBrightnessActive: {
                name: "displayBrightnessActive",
                ID: 0xe000,
                type: zigbee_herdsman_1.Zcl.DataType.UINT8,
                write: true,
                min: 0,
                max: 100,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
            },
            displayBrightnessInactive: {
                name: "displayBrightnessInactive",
                ID: 0xe001,
                type: zigbee_herdsman_1.Zcl.DataType.UINT8,
                write: true,
                min: 0,
                max: 100,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
            },
            displayActiveTimeout: {
                name: "displayActiveTimeout",
                ID: 0xe002,
                type: zigbee_herdsman_1.Zcl.DataType.UINT16,
                write: true,
                min: 5,
                max: 600,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
            },
        },
        commands: {},
        commandsResponse: {},
    }),
    displayBrightnessActive: (args) => m.numeric({
        name: "display_brightness_active",
        cluster: "hvacUserInterfaceCfg",
        attribute: "displayBrightnessActive",
        description: "Sets brightness of the temperature display during active state",
        entityCategory: "config",
        unit: "%",
        valueMin: 0,
        valueMax: 100,
        valueStep: 1,
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC },
        ...args,
    }),
    displayBrightnessInactive: (args) => m.numeric({
        name: "display_brightness_inactive",
        cluster: "hvacUserInterfaceCfg",
        attribute: "displayBrightnessInactive",
        description: "Sets brightness of the temperature display during inactive state",
        entityCategory: "config",
        unit: "%",
        valueMin: 0,
        valueMax: 100,
        valueStep: 1,
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC },
        ...args,
    }),
    displayActiveTimeout: (args) => m.numeric({
        name: "display_active_timeout",
        cluster: "hvacUserInterfaceCfg",
        attribute: "displayActiveTimeout",
        description: "Sets timeout of the temperature display active state",
        entityCategory: "config",
        unit: "seconds",
        valueMin: 5,
        valueMax: 600,
        valueStep: 5,
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC },
        ...args,
    }),
    customTemperatureMeasurementCluster: () => m.deviceAddCustomCluster("msTemperatureMeasurement", {
        name: "msTemperatureMeasurement",
        ID: zigbee_herdsman_1.Zcl.Clusters.msTemperatureMeasurement.ID,
        attributes: {
            sensorCorrection: {
                name: "sensorCorrection",
                ID: 0xe020,
                type: zigbee_herdsman_1.Zcl.DataType.INT16,
                write: true,
                min: -900,
                max: 900,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
            },
            temperatureSensorType: {
                name: "temperatureSensorType",
                ID: 0xe021,
                type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
                write: true,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
            },
        },
        commands: {},
        commandsResponse: {},
    }),
    sensorCorrection: (args) => m.numeric({
        name: "temperature_sensor_correction",
        cluster: "msTemperatureMeasurement",
        attribute: "sensorCorrection",
        description: "This is a user correction, possibly negative, to be added to the temperature measured by the sensor.",
        unit: "°C",
        scale: 100,
        valueMin: -9,
        valueMax: 9,
        valueStep: 0.01,
        access: "ALL",
        entityCategory: "config",
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC },
        ...args,
    }),
    temperatureSensorType: (args) => m.enumLookup({
        name: "temperature_sensor_type",
        cluster: "msTemperatureMeasurement",
        attribute: "temperatureSensorType",
        description: "This is used to specify the type of temperature sensor connected to this input",
        entityCategory: "config",
        access: "ALL",
        lookup: {
            "2kΩ sensor from HRT/Alre": 1,
            "10kΩ sensor from B+J": 2,
            "12kΩ sensor from OJ": 3,
            "15kΩ sensor from DEVI": 4,
            "33kΩ sensor from EBERLE": 5,
            "47kΩ sensor from CTM": 6,
            "No sensor": 0xff,
        },
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC },
        ...args,
    }),
    customMeteringCluster: () => m.deviceAddCustomCluster("seMetering", {
        name: "seMetering",
        ID: zigbee_herdsman_1.Zcl.Clusters.seMetering.ID,
        attributes: {
            fixedLoadDemand: {
                name: "fixedLoadDemand",
                ID: 0x4510,
                type: zigbee_herdsman_1.Zcl.DataType.UINT24,
                write: true,
                max: 0x7fffff,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
            },
        },
        commands: {},
        commandsResponse: {},
    }),
    fixedLoadDemand: (args) => {
        const zigbeeCommandOptions = { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC };
        const extend = m.numeric({
            name: "fixed_load_demand",
            cluster: "seMetering",
            attribute: "fixedLoadDemand",
            description: "Load in W when heating is on (between 1-3600 W). The thermostat reports this value as power (instantaneousDemand) when heating is on. The load has to be defined if the device should report running state ('heat' or 'idle').",
            entityCategory: "config",
            unit: "W",
            valueMin: 0,
            valueMax: 3600,
            valueStep: 1,
            zigbeeCommandOptions,
            ...args,
        });
        extend.configure.push(async (device) => {
            const endpoint = (0, utils_1.getEndpointsWithCluster)(device, "seMetering", "input")[0];
            const { fixedLoadDemand } = await endpoint.read("seMetering", ["fixedLoadDemand"], zigbeeCommandOptions);
            if (fixedLoadDemand === 0) {
                await endpoint.write("seMetering", { fixedLoadDemand: 1 }, zigbeeCommandOptions);
            }
        });
        return extend;
    },
    customThermostatCluster: () => m.deviceAddCustomCluster("hvacThermostat", {
        name: "hvacThermostat",
        ID: zigbee_herdsman_1.Zcl.Clusters.hvacThermostat.ID,
        attributes: {
            schneiderWiserSpecific: {
                name: "schneiderWiserSpecific",
                ID: 0xe110,
                type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
                write: true,
                max: 0xff,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
            },
            controlStatus: {
                name: "controlStatus",
                ID: 0xe211,
                type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
            },
            localTemperatureSourceSelect: {
                name: "localTemperatureSourceSelect",
                ID: 0xe212,
                type: zigbee_herdsman_1.Zcl.DataType.UINT8,
                write: true,
                max: 0xfe,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
            },
            controlType: {
                name: "controlType",
                ID: 0xe213,
                type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
                write: true,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
            },
            thermostatApplication: {
                name: "thermostatApplication",
                ID: 0xe216,
                type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
                write: true,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
            },
            heatingFuel: {
                name: "heatingFuel",
                ID: 0xe217,
                type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
                write: true,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
            },
            heatTransferMedium: {
                name: "heatTransferMedium",
                ID: 0xe218,
                type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
                write: true,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
            },
            heatingEmitter: {
                name: "heatingEmitter",
                ID: 0xe21a,
                type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
                write: true,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
            },
            wiserSmartZoneMode: {
                name: "wiserSmartZoneMode",
                ID: 0xe010,
                type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
                write: true,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
            },
            wiserSmartHactConfig: {
                name: "wiserSmartHactConfig",
                ID: 0xe011,
                type: zigbee_herdsman_1.Zcl.DataType.BITMAP8,
                write: true,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
            },
            wiserSmartCurrentFilPiloteMode: {
                name: "wiserSmartCurrentFilPiloteMode",
                ID: 0xe020,
                type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
                write: true,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
            },
            wiserSmartValvePosition: {
                name: "wiserSmartValvePosition",
                ID: 0xe030,
                type: zigbee_herdsman_1.Zcl.DataType.UINT8,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
            },
            wiserSmartValveCalibrationStatus: {
                name: "wiserSmartValveCalibrationStatus",
                ID: 0xe031,
                type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
            },
        },
        commands: {
            schneiderWiserThermostatBoost: {
                name: "schneiderWiserThermostatBoost",
                ID: 0x80,
                parameters: [
                    { name: "command", type: zigbee_herdsman_1.Zcl.DataType.ENUM8, max: 0xff },
                    { name: "enable", type: zigbee_herdsman_1.Zcl.DataType.ENUM8, max: 0xff },
                    { name: "temperature", type: zigbee_herdsman_1.Zcl.DataType.UINT16, max: 0xffff },
                    { name: "duration", type: zigbee_herdsman_1.Zcl.DataType.UINT16, max: 0xffff },
                ],
            },
            wiserSmartSetSetpoint: {
                name: "wiserSmartSetSetpoint",
                ID: 0xe0,
                parameters: [
                    { name: "operatingmode", type: zigbee_herdsman_1.Zcl.DataType.UINT8, max: 0xff },
                    { name: "zonemode", type: zigbee_herdsman_1.Zcl.DataType.UINT8, max: 0xff },
                    { name: "setpoint", type: zigbee_herdsman_1.Zcl.DataType.INT16, min: -32768, max: 32767 },
                    { name: "reserved", type: zigbee_herdsman_1.Zcl.DataType.UINT8, max: 0xff },
                ],
            },
            wiserSmartSetFipMode: {
                name: "wiserSmartSetFipMode",
                ID: 0xe1,
                parameters: [
                    { name: "zonemode", type: zigbee_herdsman_1.Zcl.DataType.UINT8, max: 0xff },
                    { name: "fipmode", type: zigbee_herdsman_1.Zcl.DataType.ENUM8, max: 0xff },
                    { name: "reserved", type: zigbee_herdsman_1.Zcl.DataType.UINT8, max: 0xff },
                ],
            },
            wiserSmartCalibrateValve: { name: "wiserSmartCalibrateValve", ID: 0xe2, parameters: [] },
        },
        commandsResponse: {},
    }),
    controlStatus: (args) => m.enumLookup({
        name: "control_status",
        cluster: "hvacThermostat",
        attribute: "controlStatus",
        description: "This indicates the status of the thermostat and allows reporting of abnormal and fault conditions.",
        entityCategory: "diagnostic",
        access: "STATE",
        lookup: {
            "Normal Operation": 0x00,
            "No Temperature": 0x20,
            "Remote Demand Override": 0x40,
            "Window Open": 0x41,
            "Local Force On": 0x61,
            Maintenance: 0x82,
            "Output Temporal Limit": 0x83,
            "Sensor Fault": 0x84,
        },
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC },
        ...args,
    }),
    localTemperatureSourceSelect: () => m.enumLookup({
        name: "local_temperature_source_select",
        cluster: "hvacThermostat",
        attribute: "localTemperatureSourceSelect",
        description: "On devices with more than one temperature input, this selects which should be used for LocalTemperature.",
        entityCategory: "config",
        lookup: { Ambient: 2, External: 3 },
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC },
    }),
    controlType: () => m.enumLookup({
        name: "control_type",
        cluster: "hvacThermostat",
        attribute: "controlType",
        description: "'On/Off', 'PI' and 'None' supported. This specifies the type of control algorithm to be used to regulate temperature.",
        entityCategory: "config",
        lookup: { "On/Off": 0, PI: 1, None: 0xff },
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC },
    }),
    thermostatApplication: () => m.enumLookup({
        name: "thermostat_application",
        cluster: "hvacThermostat",
        attribute: "thermostatApplication",
        description: "This is used to specify what the Thermostat is regulating. 'Occupied Space' - heating where the room temperature is used as the control value, 'Floor' - Floor warming applications where the temperature of the floor itself is regulated.",
        entityCategory: "config",
        lookup: { "Occupied Space": 0, Floor: 1, "Not known": 0xff },
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC },
    }),
    heatingFuel: () => m.enumLookup({
        name: "heating_fuel",
        cluster: "hvacThermostat",
        attribute: "heatingFuel",
        description: "Type of fuel used for heating.",
        entityCategory: "config",
        lookup: {
            electricity: 0x00,
            gas: 0x01,
            oil: 0x02,
            solid_fuel: 0x03,
            solar: 0x04,
            community_heating: 0x05,
            heat_pump: 0x06,
            not_specified: 0xff,
        },
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC },
    }),
    heatTransferMedium: () => m.enumLookup({
        name: "heat_transfer_medium",
        cluster: "hvacThermostat",
        attribute: "heatTransferMedium",
        description: "Medium used to transfer heat.",
        entityCategory: "config",
        lookup: { nothing: 0x00, hydronic: 0x01, air: 0x02 },
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC },
    }),
    heatingEmitter: () => m.enumLookup({
        name: "heating_emitter",
        cluster: "hvacThermostat",
        attribute: "heatingEmitter",
        description: "This is used to specify the heat emitter.",
        entityCategory: "config",
        lookup: { None: 0, Radiator: 1, "Fan Assisted Radiator": 2, "Radiant Panel": 3, Floor: 4, "Not specified": 0xff },
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC },
    }),
    addWiserDeviceInfoCluster: () => m.deviceAddCustomCluster("wiserDeviceInfo", {
        name: "wiserDeviceInfo",
        ID: 0xfe03,
        attributes: {
            deviceInfo: { name: "deviceInfo", ID: 0x0020, type: zigbee_herdsman_1.Zcl.DataType.CHAR_STR, write: true },
        },
        commands: {},
        commandsResponse: {},
    }),
    addSchneiderLightSwitchConfigurationCluster: () => m.deviceAddCustomCluster("manuSpecificSchneiderLightSwitchConfiguration", {
        name: "manuSpecificSchneiderLightSwitchConfiguration",
        ID: 0xff17,
        manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
        attributes: {
            ledIndication: { name: "ledIndication", ID: 0x0000, type: zigbee_herdsman_1.Zcl.DataType.ENUM8, write: true, max: 0xff },
            upSceneID: { name: "upSceneID", ID: 0x0010, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            upGroupID: { name: "upGroupID", ID: 0x0011, type: zigbee_herdsman_1.Zcl.DataType.UINT16, write: true, max: 0xffff },
            downSceneID: { name: "downSceneID", ID: 0x0020, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            downGroupID: { name: "downGroupID", ID: 0x0021, type: zigbee_herdsman_1.Zcl.DataType.UINT16, write: true, max: 0xffff },
            switchActions: { name: "switchActions", ID: 0x0001, type: zigbee_herdsman_1.Zcl.DataType.ENUM8, write: true, max: 0xff },
        },
        commands: {},
        commandsResponse: {},
    }),
    addSchneiderFanSwitchConfigurationCluster: () => m.deviceAddCustomCluster("manuSpecificSchneiderFanSwitchConfiguration", {
        name: "manuSpecificSchneiderFanSwitchConfiguration",
        ID: 0xfc04,
        manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
        attributes: {
            ledIndication: { name: "ledIndication", ID: 0x0002, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            ledOrientation: { name: "ledOrientation", ID: 0x0060, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
        },
        commands: {},
        commandsResponse: {},
    }),
    addSchneiderLightingBallastCfgCluster: () => m.deviceAddCustomCluster("lightingBallastCfg", {
        name: "lightingBallastCfg",
        ID: zigbee_herdsman_1.Zcl.Clusters.lightingBallastCfg.ID,
        attributes: {
            wiserControlMode: {
                name: "wiserControlMode",
                ID: 0xe000,
                type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
                write: true,
                max: 0xff,
            },
        },
        commands: {},
        commandsResponse: {},
    }),
    addSchneiderClosuresWindowCoveringCluster: () => m.deviceAddCustomCluster("closuresWindowCovering", {
        name: "closuresWindowCovering",
        ID: zigbee_herdsman_1.Zcl.Clusters.closuresWindowCovering.ID,
        attributes: {
            liftDriveUpTime: {
                name: "liftDriveUpTime",
                ID: 0xe014,
                type: zigbee_herdsman_1.Zcl.DataType.UINT16,
                write: true,
                min: 0,
                max: 3000,
                default: 1200,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
            },
            liftDriveDownTime: {
                name: "liftDriveDownTime",
                ID: 0xe015,
                type: zigbee_herdsman_1.Zcl.DataType.UINT16,
                write: true,
                min: 0,
                max: 3000,
                default: 1200,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
            },
            tiltOpenCloseAndStepTime: {
                name: "tiltOpenCloseAndStepTime",
                ID: 0xe016,
                type: zigbee_herdsman_1.Zcl.DataType.UINT16,
                write: true,
                min: 0,
                max: 3000,
                default: 100,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
            },
        },
        commands: {},
        commandsResponse: {},
    }),
};
// #region CCTFR6400 hub-less boost handling
//
// The CCTFR6400 keeps no boost state of its own: ~8 seconds after the last
// center-button press it sends a single schneiderWiserThermostatBoost command
// and forgets about the boost. It even drops an unhonoured boost locally when
// the setpoint it reads back does not reflect the boost temperature. The full
// boost lifecycle is therefore the controller's job: save the pre-boost
// setpoint, apply the boost temperature and restore the saved setpoint when
// the boost duration ends or when the boost is cancelled on the device
// (option `boost_auto_honor`, enabled by default).
//
// Precedence rules (the last written setpoint always wins):
// - an external occupied_heating_setpoint write cancels a pending restore,
// - a +/- press after the boost commit is a normal setpoint change for the
//   user and also cancels the pending restore,
// - only an undisturbed expiry or a boost cancel on the device restores the
//   saved pre-boost setpoint.
const cctfr6400BoostTimerStoreKey = "cctfr6400_boost_timer";
const cctfr6400PublishStoreKey = "cctfr6400_publish";
const cctfr6400PendingPublishStoreKey = "cctfr6400_pending_publish";
const cctfr6400BoostBaseMetaKey = "cctfr6400BoostSavedSetpoint";
const cctfr6400BoostEndMetaKey = "cctfr6400BoostEndTime";
const cctfr6400Options = {
    boostAutoHonor: () => e
        .binary("boost_auto_honor", ea.SET, true, false)
        .withLabel("Auto honor boost")
        .withDescription("Handle a boost started from the device's center button by temporarily applying the boost temperature as the setpoint and " +
        "restoring the previous setpoint when the boost duration ends or the boost is cancelled on the device (default true). " +
        "Disable this when an external automation implements its own boost policy based on the boost_set/boost_cancel actions."),
};
function cctfr6400BoostAutoHonorEnabled(options) {
    return options?.boost_auto_honor !== false;
}
// Remember the publish callback so that a boost restore that happens outside
// of a message context (timer expiry after a restart, or an end time that
// passed while the controller was down) can still update the exposed state.
// If no callback has been captured yet the restore payload is parked and
// published with the next incoming message of this device (it wakes and
// reports roughly every minute).
function cctfr6400RememberPublish(device, publish) {
    globalStore.putValue(device.ieeeAddr, cctfr6400PublishStoreKey, publish);
    const pending = globalStore.getValue(device.ieeeAddr, cctfr6400PendingPublishStoreKey);
    if (pending !== undefined) {
        globalStore.clearValue(device.ieeeAddr, cctfr6400PendingPublishStoreKey);
        publish(pending);
    }
}
function cctfr6400PublishOrDefer(device, payload) {
    const publish = globalStore.getValue(device.ieeeAddr, cctfr6400PublishStoreKey);
    if (publish) {
        publish(payload);
    }
    else {
        globalStore.putValue(device.ieeeAddr, cctfr6400PendingPublishStoreKey, payload);
    }
}
// Forget a pending boost without touching the setpoint (external setpoint
// write, +/- press after the commit, or auto honor disabled).
function cctfr6400BoostWipe(device) {
    clearTimeout(globalStore.getValue(device.ieeeAddr, cctfr6400BoostTimerStoreKey));
    globalStore.clearValue(device.ieeeAddr, cctfr6400BoostTimerStoreKey);
    if (device.meta[cctfr6400BoostBaseMetaKey] !== undefined || device.meta[cctfr6400BoostEndMetaKey] !== undefined) {
        delete device.meta[cctfr6400BoostBaseMetaKey];
        delete device.meta[cctfr6400BoostEndMetaKey];
        device.save();
    }
}
// Restore the saved pre-boost setpoint (undisturbed expiry or device cancel).
// Returns the state payload of the restore, or undefined when no boost was
// pending.
function cctfr6400BoostRestore(device) {
    const base = device.meta[cctfr6400BoostBaseMetaKey];
    cctfr6400BoostWipe(device);
    if (base === undefined) {
        return undefined;
    }
    device.getEndpoint(1).saveClusterAttributeKeyValue("hvacThermostat", { occupiedHeatingSetpoint: base });
    return { occupied_heating_setpoint: base / 100 };
}
function cctfr6400BoostStartTimer(device, timeoutMs) {
    clearTimeout(globalStore.getValue(device.ieeeAddr, cctfr6400BoostTimerStoreKey));
    const timer = setTimeout(() => {
        globalStore.clearValue(device.ieeeAddr, cctfr6400BoostTimerStoreKey);
        const payload = cctfr6400BoostRestore(device);
        if (payload) {
            cctfr6400PublishOrDefer(device, payload);
        }
    }, Math.max(timeoutMs, 0)).unref();
    globalStore.putValue(device.ieeeAddr, cctfr6400BoostTimerStoreKey, timer);
}
// Honor a boost commit: save the pre-boost setpoint (a new commit during a
// running boost keeps the originally saved setpoint and restarts the timer),
// apply the boost temperature and arm the restore timer. The bookkeeping is
// persisted in device.meta so a restart resumes the boost (see onEvent).
function cctfr6400BoostArm(device, durationMinutes, temperature) {
    const endpoint = device.getEndpoint(1);
    if (device.meta[cctfr6400BoostBaseMetaKey] === undefined) {
        const current = Number(endpoint.getClusterAttributeValue("hvacThermostat", "occupiedHeatingSetpoint"));
        if (Number.isFinite(current)) {
            device.meta[cctfr6400BoostBaseMetaKey] = current;
        }
    }
    if (device.meta[cctfr6400BoostBaseMetaKey] !== undefined) {
        device.meta[cctfr6400BoostEndMetaKey] = Date.now() + durationMinutes * 60000;
        device.save();
        cctfr6400BoostStartTimer(device, durationMinutes * 60000);
    }
    endpoint.saveClusterAttributeKeyValue("hvacThermostat", { occupiedHeatingSetpoint: temperature });
}
// Resume or finish a persisted boost after a restart.
function cctfr6400BoostResume(device, options) {
    const endTime = device.meta[cctfr6400BoostEndMetaKey];
    if (endTime === undefined) {
        return;
    }
    if (!cctfr6400BoostAutoHonorEnabled(options)) {
        // Auto honor was disabled while a boost was pending: forget it without
        // touching the setpoint, an external automation is in charge now.
        cctfr6400BoostWipe(device);
        return;
    }
    if (endTime <= Date.now()) {
        const payload = cctfr6400BoostRestore(device);
        if (payload) {
            cctfr6400PublishOrDefer(device, payload);
        }
    }
    else {
        cctfr6400BoostStartTimer(device, endTime - Date.now());
    }
}
function cctfr6400HvacReadAttribute(attrId) {
    switch (attrId) {
        case 0x0012:
            return "occupiedHeatingSetpoint";
        case 0x001c:
            return "systemMode";
        case 0x001b:
            return "ctrlSeqeOfOper";
        case 0x0008:
            return "pIHeatingDemand";
        case 0xe110:
            return "schneiderWiserSpecific";
        default:
            return undefined;
    }
}
// Since zigbee-herdsman 10.0.3 device reads are no longer answered from the
// coordinator attribute cache; everything except genTime/genBasic gets
// UNSUPPORTED_ATTRIBUTE. The CCTFR6400 is a thermostat *client*: it polls the
// attributes above every ~5 seconds while its screen is awake and needs real
// answers for its display (and its local setpoint/boost UI) to work. Answer
// the reads from the endpoint attribute cache, which the cctfr6400_thermostat
// toZigbee converters and the +/- emulation keep up to date.
function cctfr6400InstallCustomReadResponse(device) {
    if (device.customReadResponse) {
        return;
    }
    device.customReadResponse = (frame, endpoint) => {
        if (!frame.isCluster("hvacThermostat")) {
            // genBasic/genTime reads are answered by zigbee-herdsman itself.
            return false;
        }
        const attributes = {};
        for (const item of frame.payload) {
            const name = cctfr6400HvacReadAttribute(item.attrId);
            const value = name === undefined ? undefined : endpoint.getClusterAttributeValue("hvacThermostat", name);
            if (typeof value !== "number") {
                // Unknown attribute or no cached value yet: let zigbee-herdsman
                // answer the whole frame with UNSUPPORTED_ATTRIBUTE instead of
                // sending a partial response.
                return false;
            }
            attributes[name] = value;
        }
        // Measured on the wire: the device targets these reads at coordinator
        // endpoint 3 and expects the response to come from that endpoint, so
        // mirror it (like the default zigbee-herdsman read response path does).
        const options = { srcEndpoint: 3 };
        if (frame.header.manufacturerCode !== undefined) {
            options.manufacturerCode = frame.header.manufacturerCode;
        }
        endpoint
            .readResponse("hvacThermostat", frame.header.transactionSequenceNumber, attributes, options)
            .catch((error) => {
            logger_1.logger.warning(`CCTFR6400 read response failed for '${device.ieeeAddr}': ${error}`, NS);
        });
        return true;
    };
}
// #endregion
const tzLocal = {
    lift_duration: {
        key: ["lift_duration"],
        convertSet: async (entity, key, value, meta) => {
            await entity.write(0x0102, { 57344: { value, type: 0x21 } }, { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC });
            return { state: { lift_duration: value } };
        },
    },
    fan_mode: {
        ...tz.fan_mode,
        convertSet: async (entity, key, value, meta) => {
            utils.assertString(value);
            if (value.toLowerCase() === "on")
                value = "low";
            return await tz.fan_mode.convertSet(entity, key, value, meta);
        },
    },
    wiser_dimmer_mode: {
        key: ["dimmer_mode"],
        convertSet: async (entity, key, value, meta) => {
            await entity.write("lightingBallastCfg", { wiserControlMode: utils.getKey(constants.wiserDimmerControlMode, value, value, Number) }, { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC });
            return { state: { dimmer_mode: value } };
        },
        convertGet: async (entity, key, meta) => {
            await entity.read("lightingBallastCfg", ["wiserControlMode"], {
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
            });
        },
    },
    wiser_fip_setting: {
        key: ["fip_setting"],
        convertSet: async (entity, key, value, meta) => {
            utils.assertString(value, key);
            const zoneLookup = { manual: 1, schedule: 2, energy_saver: 3, holiday: 6 };
            const zonemodeNum = utils.getFromLookup(meta.state.zone_mode, zoneLookup);
            const fipLookup = { comfort: 0, "comfort_-1": 1, "comfort_-2": 2, energy_saving: 3, frost_protection: 4, off: 5 };
            value = value.toLowerCase();
            utils.validateValue(value, Object.keys(fipLookup));
            const fipmodeNum = utils.getFromLookup(value, fipLookup);
            const payload = {
                zonemode: zonemodeNum,
                fipmode: fipmodeNum,
                reserved: 0xff,
            };
            await entity.command("hvacThermostat", "wiserSmartSetFipMode", payload, { srcEndpoint: 11, disableDefaultResponse: true });
            return { state: { fip_setting: value } };
        },
        convertGet: async (entity, key, meta) => {
            await entity.read("hvacThermostat", ["wiserSmartCurrentFilPiloteMode"]);
        },
    },
    wiser_hact_config: {
        key: ["hact_config"],
        convertSet: async (entity, key, value, meta) => {
            utils.assertString(value, key);
            const lookup = { unconfigured: 0x00, setpoint_switch: 0x80, setpoint_fip: 0x82, fip_fip: 0x83 };
            value = value.toLowerCase();
            const mode = utils.getFromLookup(value, lookup);
            await entity.write("hvacThermostat", { 57361: { value: mode, type: 0x18 } });
            return { state: { hact_config: value } };
        },
        convertGet: async (entity, key, meta) => {
            await entity.read("hvacThermostat", ["wiserSmartHactConfig"]);
        },
    },
    wiser_zone_mode: {
        key: ["zone_mode"],
        convertSet: async (entity, key, value, meta) => {
            const lookup = { manual: 1, schedule: 2, energy_saver: 3, holiday: 6 };
            const zonemodeNum = utils.getFromLookup(value, lookup);
            await entity.write("hvacThermostat", { 57360: { value: zonemodeNum, type: 0x30 } });
            return { state: { zone_mode: value } };
        },
        convertGet: async (entity, key, meta) => {
            await entity.read("hvacThermostat", ["wiserSmartZoneMode"]);
        },
    },
    wiser_vact_calibrate_valve: {
        key: ["calibrate_valve"],
        convertSet: async (entity, key, value, meta) => {
            await entity.command("hvacThermostat", "wiserSmartCalibrateValve", {}, { srcEndpoint: 11, disableDefaultResponse: true });
            return { state: { calibrate_valve: value } };
        },
    },
    wiser_sed_zone_mode: {
        key: ["zone_mode"],
        convertSet: (entity, key, value, meta) => {
            return { state: { zone_mode: value } };
        },
    },
    wiser_sed_occupied_heating_setpoint: {
        key: ["occupied_heating_setpoint"],
        convertSet: (entity, key, value, meta) => {
            utils.assertNumber(value, key);
            utils.assertEndpoint(entity);
            const occupiedHeatingSetpoint = Number((Math.round(Number((value * 2).toFixed(1))) / 2).toFixed(1)) * 100;
            entity.saveClusterAttributeKeyValue("hvacThermostat", { occupiedHeatingSetpoint });
            return { state: { occupied_heating_setpoint: value } };
        },
    },
    wiser_sed_thermostat_local_temperature_calibration: {
        key: ["local_temperature_calibration"],
        convertSet: async (entity, key, value, meta) => {
            utils.assertNumber(value);
            await entity.write("hvacThermostat", { localTemperatureCalibration: Math.round(value * 10) }, { srcEndpoint: 11, disableDefaultResponse: true });
            return { state: { local_temperature_calibration: value } };
        },
    },
    wiser_sed_thermostat_keypad_lockout: {
        key: ["keypad_lockout"],
        convertSet: async (entity, key, value, meta) => {
            await entity.write("hvacUserInterfaceCfg", { keypadLockout: utils.getKey(constants.keypadLockoutMode, value, value, Number) }, { srcEndpoint: 11, disableDefaultResponse: true });
            return { state: { keypad_lockout: value } };
        },
    },
    cctfr6400_thermostat_system_mode: {
        key: ["system_mode"],
        convertSet: (entity, key, value, meta) => {
            utils.assertEndpoint(entity);
            const systemMode = utils.getKey(constants.thermostatSystemModes, value, undefined, Number);
            entity.saveClusterAttributeKeyValue("hvacThermostat", { systemMode: systemMode });
            return { state: { system_mode: value } };
        },
    },
    cctfr6400_thermostat_occupied_heating_setpoint: {
        key: ["occupied_heating_setpoint"],
        convertSet: (entity, key, value, meta) => {
            utils.assertNumber(value, key);
            utils.assertEndpoint(entity);
            if (meta.device) {
                // An external setpoint write overrules a pending boost: the new
                // value applies and the pre-boost setpoint is no longer
                // restored, so a schedule can never be overwritten by a stale
                // boost restore.
                cctfr6400BoostWipe(meta.device);
            }
            const occupiedHeatingSetpoint = Number((Math.round(Number((value * 2).toFixed(1))) / 2).toFixed(1)) * 100;
            entity.saveClusterAttributeKeyValue("hvacThermostat", { occupiedHeatingSetpoint: occupiedHeatingSetpoint });
            return { state: { occupied_heating_setpoint: value } };
        },
    },
    cctfr6400_thermostat_control_sequence_of_operation: {
        key: ["control_sequence_of_operation"],
        convertSet: (entity, key, value, meta) => {
            utils.assertEndpoint(entity);
            const val = utils.getKey(constants.thermostatControlSequenceOfOperations, value, value, Number);
            entity.saveClusterAttributeKeyValue("hvacThermostat", { ctrlSeqeOfOper: val });
            return { state: { control_sequence_of_operation: value } };
        },
    },
    cctfr6400_thermostat_pi_heating_demand: {
        key: ["pi_heating_demand"],
        convertSet: (entity, key, value, meta) => {
            utils.assertEndpoint(entity);
            entity.saveClusterAttributeKeyValue("hvacThermostat", { pIHeatingDemand: value });
            return { state: { pi_heating_demand: value } };
        },
    },
    schneider_thermostat_keypad_lockout: {
        key: ["keypad_lockout"],
        convertSet: async (entity, key, value, meta) => {
            utils.assertEndpoint(entity);
            const keypadLockout = utils.getKey(constants.keypadLockoutMode, value, value, Number);
            await entity.write("hvacUserInterfaceCfg", { keypadLockout });
            entity.saveClusterAttributeKeyValue("hvacUserInterfaceCfg", { keypadLockout });
            return { state: { keypad_lockout: value } };
        },
    },
    schneider_dimmer_mode: {
        key: ["dimmer_mode"],
        convertSet: async (entity, key, value, meta) => {
            const lookup = { RC: 1, RL: 2 };
            const mode = utils.getFromLookup(value, lookup);
            await entity.write("lightingBallastCfg", { wiserControlMode: mode }, { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC });
            return { state: { dimmer_mode: value } };
        },
        convertGet: async (entity, key, meta) => {
            await entity.read("lightingBallastCfg", ["wiserControlMode"], {
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
            });
        },
    },
    cctfr6700_temperature_measured_value: {
        key: ["temperature_measured_value"],
        convertSet: async (entity, key, value, meta) => {
            utils.assertNumber(value);
            utils.assertEndpoint(entity);
            await entity.report("msTemperatureMeasurement", { measuredValue: Math.round(value * 100) });
        },
    },
};
const fzLocal = {
    schneider_ui_action: {
        cluster: "wiserDeviceInfo",
        type: "attributeReport",
        convert: (model, msg, publish, options, meta) => {
            if (utils.hasAlreadyProcessedMessage(msg, model))
                return;
            cctfr6400RememberPublish(msg.device, publish);
            const data = msg.data.deviceInfo.split(",");
            if (data[0] === "UI" && data[1]) {
                const result = { action: utils.toSnakeCase(data[1]) };
                let screenAwake = globalStore.getValue(msg.endpoint, "screenAwake");
                screenAwake = screenAwake !== undefined ? screenAwake : false;
                const keypadLockedNumber = Number(msg.endpoint.getClusterAttributeValue("hvacUserInterfaceCfg", "keypadLockout"));
                const keypadLocked = keypadLockedNumber !== undefined ? keypadLockedNumber !== 0 : false;
                // While the boost selection UI is open (center press seen,
                // clock icon shown), +/- presses adjust the device's local
                // boost target, not the setpoint. Emulating them against the
                // setpoint cache would leak boost adjustments into the
                // setpoint. The window ends at the boost commit (~8 s after
                // the last press) or at screen sleep. No time based guard is
                // needed: the device drops an uncommitted boost by itself.
                const boostSelecting = globalStore.getValue(msg.endpoint, "boostSelecting") === true;
                // Emulate UI temperature update
                if (data[1] === "ScreenWake") {
                    globalStore.putValue(msg.endpoint, "screenAwake", true);
                }
                else if (data[1] === "ScreenSleep") {
                    globalStore.putValue(msg.endpoint, "screenAwake", false);
                    globalStore.putValue(msg.endpoint, "boostSelecting", false);
                }
                else if (data[1] === "ButtonPressCenterDown") {
                    if (screenAwake && !keypadLocked) {
                        globalStore.putValue(msg.endpoint, "boostSelecting", true);
                    }
                }
                else if ((data[1] === "ButtonPressMinusDown" || data[1] === "ButtonPressPlusDown") &&
                    screenAwake &&
                    !keypadLocked &&
                    !boostSelecting) {
                    // A +/- press after the boost commit is a normal setpoint
                    // change for the user: like an external setpoint write it
                    // cancels a pending boost restore (the last written
                    // setpoint always wins).
                    cctfr6400BoostWipe(msg.device);
                    let occupiedHeatingSetpoint = Number(msg.endpoint.getClusterAttributeValue("hvacThermostat", "occupiedHeatingSetpoint"));
                    occupiedHeatingSetpoint =
                        occupiedHeatingSetpoint != null && !Number.isNaN(occupiedHeatingSetpoint) ? occupiedHeatingSetpoint : 400;
                    if (data[1] === "ButtonPressMinusDown") {
                        occupiedHeatingSetpoint -= 50;
                    }
                    else {
                        occupiedHeatingSetpoint += 50;
                    }
                    msg.endpoint.saveClusterAttributeKeyValue("hvacThermostat", { occupiedHeatingSetpoint: occupiedHeatingSetpoint });
                    result.occupied_heating_setpoint = occupiedHeatingSetpoint / 100;
                }
                return result;
            }
        },
    },
    cctfr6400_boost: {
        cluster: "hvacThermostat",
        type: ["commandSchneiderWiserThermostatBoost"],
        options: [cctfr6400Options.boostAutoHonor()],
        convert: (model, msg, publish, options, meta) => {
            if (utils.hasAlreadyProcessedMessage(msg, model))
                return;
            cctfr6400RememberPublish(msg.device, publish);
            // The commit closes the boost selection window of the +/- guard.
            globalStore.putValue(msg.endpoint, "boostSelecting", false);
            const enable = Number(msg.data.enable) === 1;
            // Cancel = enable 0, duration 0, temperature 0xFFF.
            const result = {
                action: enable ? "boost_set" : "boost_cancel",
                boost_duration: enable ? Number(msg.data.duration) : 0,
                boost_temperature: enable ? Number(msg.data.temperature) / 100 : null,
            };
            if (cctfr6400BoostAutoHonorEnabled(options)) {
                if (enable) {
                    const temperature = Number(msg.data.temperature);
                    cctfr6400BoostArm(msg.device, Number(msg.data.duration), temperature);
                    result.occupied_heating_setpoint = temperature / 100;
                }
                else {
                    const restored = cctfr6400BoostRestore(msg.device);
                    if (restored) {
                        Object.assign(result, restored);
                    }
                }
            }
            return result;
        },
    },
    cctfr6400_ignore_thermostat_read: {
        // The display poll reads answered by customReadResponse (see
        // cctfr6400InstallCustomReadResponse) also pass through the fromZigbee
        // pipeline; absorb them silently to avoid "No converter available"
        // log spam every ~5 seconds while the screen is awake.
        cluster: "hvacThermostat",
        type: ["read"],
        convert: () => { },
    },
    cctfr6400_ignore_setpoint_raise_lower: {
        // Once its reads are answered the device also sends a standard
        // setpointRaiseLower command (amount in 0.1 °C steps, e.g. -5 for
        // -0.5 °C) for every +/- press. The schneider_ui_action emulation
        // above already applies the same step to the setpoint cache, so acting
        // on this command as well would double count every press.
        cluster: "hvacThermostat",
        type: ["commandSetpointRaiseLower"],
        convert: () => { },
    },
    schneider_powertag: {
        cluster: "greenPower",
        type: ["commandNotification", "commandCommissioningNotification"],
        convert: async (model, msg, publish, options, meta) => {
            if (msg.type !== "commandNotification") {
                return;
            }
            const commandID = msg.data.commandID;
            if (utils.hasAlreadyProcessedMessage(msg, model, msg.data.frameCounter, `${msg.device.ieeeAddr}_${commandID}`)) {
                return;
            }
            if (commandID >= 0xe0)
                return; // Skip op commands
            const rxAfterTx = msg.data.options & (1 << 11);
            const ret = {};
            switch (commandID) {
                case 0xa0: {
                    // Should handle this cluster as well
                    // const cmd = msg.data.commandFrame as GpdAttributeReport;
                    break;
                }
                case 0xa1: {
                    const cmd = msg.data.commandFrame;
                    switch (cmd.clusterID) {
                        case zigbee_herdsman_1.Zcl.Clusters.haElectricalMeasurement.ID: {
                            const attr = cmd.attributes;
                            const acCurrentDivisor = attr.acCurrentDivisor;
                            const acVoltageDivisor = attr.acVoltageDivisor;
                            const acFrequencyDivisor = attr.acFrequencyDivisor;
                            const powerDivisor = attr.powerDivisor;
                            if (attr.rmsVoltage !== undefined) {
                                ret.voltage_phase_a = attr.rmsVoltage / acVoltageDivisor;
                            }
                            if (attr.rmsVoltagePhB !== undefined) {
                                ret.voltage_phase_b = attr.rmsVoltagePhB / acVoltageDivisor;
                            }
                            if (attr.rmsVoltagePhC !== undefined) {
                                ret.voltage_phase_c = attr.rmsVoltagePhC / acVoltageDivisor;
                            }
                            if (attr["19200"] !== undefined) {
                                ret.voltage_phase_ab = attr["19200"] / acVoltageDivisor;
                            }
                            if (attr["19456"] !== undefined) {
                                ret.voltage_phase_bc = attr["19456"] / acVoltageDivisor;
                            }
                            if (attr["19712"] !== undefined) {
                                ret.voltage_phase_ca = attr["19712"] / acVoltageDivisor;
                            }
                            if (attr.rmsCurrent !== undefined) {
                                ret.current_phase_a = attr.rmsCurrent / acCurrentDivisor;
                            }
                            if (attr.rmsCurrentPhB !== undefined) {
                                ret.current_phase_b = attr.rmsCurrentPhB / acCurrentDivisor;
                            }
                            if (attr.rmsCurrentPhC !== undefined) {
                                ret.current_phase_c = attr.rmsCurrentPhC / acCurrentDivisor;
                            }
                            if (attr.totalActivePower !== undefined) {
                                ret.power = (attr.totalActivePower * 1000) / powerDivisor;
                            }
                            if (attr.totalApparentPower !== undefined) {
                                ret.power_apparent = (attr.totalApparentPower * 1000) / powerDivisor;
                            }
                            if (attr.acFrequency !== undefined) {
                                ret.ac_frequency = attr.acFrequency / acFrequencyDivisor;
                            }
                            if (attr.activePower !== undefined) {
                                ret.power_phase_a = (attr.activePower * 1000) / powerDivisor;
                            }
                            if (attr.activePowerPhB !== undefined) {
                                ret.power_phase_b = (attr.activePowerPhB * 1000) / powerDivisor;
                            }
                            if (attr.activePowerPhC !== undefined) {
                                ret.power_phase_c = (attr.activePowerPhC * 1000) / powerDivisor;
                            }
                            break;
                        }
                        case zigbee_herdsman_1.Zcl.Clusters.seMetering.ID: {
                            const attr = cmd.attributes;
                            const divisor = attr.divisor;
                            if (attr.currentSummDelivered !== undefined) {
                                const val = attr.currentSummDelivered;
                                ret.energy = val / divisor;
                            }
                            if (attr["16652"] !== undefined) {
                                ret.energy_phase_a = attr["16652"] / divisor;
                            }
                            if (attr["16908"] !== undefined) {
                                ret.energy_phase_b = attr["16908"] / divisor;
                            }
                            if (attr["17164"] !== undefined) {
                                ret.energy_phase_c = attr["17164"] / divisor;
                            }
                            if (attr.powerFactor !== undefined) {
                                ret.power_factor = attr.powerFactor;
                            }
                            break;
                        }
                    }
                    break;
                }
                case 0xa3: {
                    // Should handle this cluster as well
                    // const cmd = msg.data.commandFrame as GpdManufMultiClusterAttributeReport;
                    break;
                }
            }
            if (rxAfterTx) {
                // Send Schneider specific ACK to make PowerTag happy
                // @ts-expect-error ignore
                const networkParameters = await msg.device.constructor.adapter.getNetworkParameters();
                await msg.endpoint.commandResponse("greenPower", "response", {
                    options: 0b000,
                    tempMaster: msg.data.gppNwkAddr ?? zspec_1.COORDINATOR_ADDRESS,
                    tempMasterTx: networkParameters.channel - 11,
                    srcID: msg.data.srcID,
                    gpdCmd: 0xfe,
                    gpdPayload: {
                        commandID: 0xfe,
                        buffer: Buffer.alloc(1),
                    },
                }, {
                    srcEndpoint: 242,
                    disableDefaultResponse: true,
                });
            }
            return ret;
        },
    },
    wiser_device_info: {
        cluster: "wiserDeviceInfo",
        type: "attributeReport",
        convert: (model, msg, publish, options, meta) => {
            const result = {};
            const data = msg.data.deviceInfo.split(",");
            if (data[0] === "ALG") {
                // TODO What is ALG
                const alg = data.slice(1);
                result.ALG = alg.join(",");
                result.occupied_heating_setpoint = Number.parseInt(alg[2], 10) / 10;
                result.local_temperature = Number.parseInt(alg[3], 10) / 10;
                result.pi_heating_demand = Number.parseInt(alg[9], 10);
            }
            else if (data[0] === "ADC") {
                // TODO What is ADC
                const adc = data.slice(1);
                result.ADC = adc.join(",");
                // TODO: should parseInt?
                result.occupied_heating_setpoint = Number.parseInt(adc[5], 10) / 100;
                result.local_temperature = Number.parseInt(adc[3], 10) / 10;
            }
            else if (data[0] === "UI") {
                if (data[1] === "BoostUp") {
                    result.boost = "Up";
                }
                else if (data[1] === "BoostDown") {
                    result.boost = "Down";
                }
                else {
                    result.boost = "None";
                }
            }
            else if (data[0] === "MOT") {
                // Info about the motor
                result.MOT = data[1];
            }
            return result;
        },
    },
    wiser_lighting_ballast_configuration: {
        cluster: "lightingBallastCfg",
        type: ["attributeReport", "readResponse"],
        convert: (model, msg, publish, options, meta) => {
            const result = fz.lighting_ballast_configuration.convert(model, msg, publish, options, meta);
            if (result && msg.data.wiserControlMode !== undefined) {
                result.dimmer_mode = constants.wiserDimmerControlMode[msg.data.wiserControlMode];
            }
            return result;
        },
    },
    wiser_smart_setpoint_command_client: {
        cluster: "hvacThermostat",
        type: ["commandWiserSmartSetSetpoint"],
        convert: (model, msg, publish, options, meta) => {
            const attribute = {};
            const result = {};
            // The UI client on the thermostat also updates the server, so no need to readback/send again on next sync.
            // This also ensures the next client read of setpoint is in sync with the latest commanded value.
            attribute.occupiedHeatingSetpoint = msg.data.setpoint;
            msg.endpoint.saveClusterAttributeKeyValue("hvacThermostat", attribute);
            result.occupied_heating_setpoint = msg.data.setpoint / 100.0;
            logger_1.logger.debug(`received wiser setpoint command with value: '${msg.data.setpoint}'`, NS);
            return result;
        },
    },
    wiser_smart_thermostat: {
        cluster: "hvacThermostat",
        type: ["attributeReport", "readResponse"],
        convert: async (model, msg, publish, options, meta) => {
            const result = fz.thermostat.convert(model, msg, publish, options, meta);
            if (result) {
                if (msg.data.wiserSmartZoneMode !== undefined) {
                    const lookup = { 1: "manual", 2: "schedule", 3: "energy_saver", 6: "holiday" };
                    result.zone_mode = lookup[msg.data.wiserSmartZoneMode];
                }
                if (msg.data.wiserSmartHactConfig !== undefined) {
                    const lookup = { 0: "unconfigured", 128: "setpoint_switch", 130: "setpoint_fip", 131: "fip_fip" };
                    result.hact_config = lookup[msg.data.wiserSmartHactConfig];
                }
                if (msg.data.wiserSmartCurrentFilPiloteMode !== undefined) {
                    const lookup = {
                        0: "comfort",
                        1: "comfort_-1",
                        2: "comfort_-2",
                        3: "energy_saving",
                        4: "frost_protection",
                        5: "off",
                    };
                    result.fip_setting = lookup[msg.data.wiserSmartCurrentFilPiloteMode];
                }
                if (msg.data.wiserSmartValvePosition !== undefined) {
                    result.pi_heating_demand = msg.data.wiserSmartValvePosition;
                }
                if (msg.data.wiserSmartValveCalibrationStatus !== undefined) {
                    const lookup = {
                        0: "ongoing",
                        1: "successful",
                        2: "uncalibrated",
                        3: "failed_e1",
                        4: "failed_e2",
                        5: "failed_e3",
                    };
                    result.valve_calibration_status = lookup[msg.data.wiserSmartValveCalibrationStatus];
                }
                // Radiator thermostats command changes from UI, but report value periodically for sync,
                // force an update of the value if it doesn't match the current existing value
                if (meta.device.modelID === "EH-ZB-VACT" &&
                    msg.data.occupiedHeatingSetpoint !== undefined &&
                    meta.state.occupied_heating_setpoint !== undefined) {
                    if (result.occupied_heating_setpoint !== meta.state.occupied_heating_setpoint) {
                        const lookup = { manual: 1, schedule: 2, energy_saver: 3, holiday: 6 };
                        const zonemodeNum = lookup[Number(meta.state.zone_mode)];
                        const setpoint = Number((Math.round(Number((Number(meta.state.occupied_heating_setpoint) * 2).toFixed(1))) / 2).toFixed(1)) * 100;
                        const payload = {
                            operatingmode: 0,
                            zonemode: zonemodeNum,
                            setpoint: setpoint,
                            reserved: 0xff,
                        };
                        await msg.endpoint.command("hvacThermostat", "wiserSmartSetSetpoint", payload, {
                            srcEndpoint: 11,
                            disableDefaultResponse: true,
                        });
                        logger_1.logger.debug(`syncing vact setpoint was: '${result.occupied_heating_setpoint}' now: '${meta.state.occupied_heating_setpoint}'`, NS);
                    }
                }
                else {
                    publish(result);
                }
            }
        },
    },
    wiser_smart_thermostat_client: {
        cluster: "hvacThermostat",
        type: "read",
        convert: async (model, msg, publish, options, meta) => {
            const response = {};
            if (msg.data.includes("wiserSmartZoneMode") || msg.data.includes(0xe010)) {
                // Zone Mode
                const lookup = { manual: 1, schedule: 2, energy_saver: 3, holiday: 6 };
                const zonemodeNum = meta.state.zone_mode ? lookup[meta.state.zone_mode] : 1;
                response.wiserSmartZoneMode = { value: zonemodeNum };
                await msg.endpoint.readResponse(msg.cluster, msg.meta.zclTransactionSequenceNumber, response, { srcEndpoint: 11 });
            }
        },
    },
    thermostat_running_state_from_piheat: {
        cluster: "hvacThermostat",
        type: ["attributeReport", "readResponse"],
        convert: (model, msg, publish, options, meta) => {
            const result = fz.thermostat.convert(model, msg, publish, options, meta);
            if (result && msg.data.pIHeatingDemand !== undefined) {
                result.running_state = msg.data.pIHeatingDemand >= 10 ? "heat" : "idle";
            }
            return result;
        },
    },
    schneider_temperature: {
        cluster: "msTemperatureMeasurement",
        type: ["attributeReport", "readResponse"],
        convert: (model, msg, publish, options, meta) => {
            const temperature = msg.data.measuredValue / 100.0;
            const property = (0, utils_1.postfixWithEndpointName)("local_temperature", msg, model, meta);
            return { [property]: temperature };
        },
    },
    schneider_lighting_ballast_configuration: {
        cluster: "lightingBallastCfg",
        type: ["attributeReport", "readResponse"],
        convert: (model, msg, publish, options, meta) => {
            const result = fz.lighting_ballast_configuration.convert(model, msg, publish, options, meta);
            const lookup = { 1: "RC", 2: "RL" };
            if (result && msg.data.wiserControlMode !== undefined) {
                result.dimmer_mode = lookup[msg.data.wiserControlMode];
            }
            return result;
        },
    },
    // biome-ignore lint/style/useNamingConvention: ignored using `--suppress`
    EKO09738_metering: {
        // ELKO EKO09738 and EKO09716 reports power in mW, scale to W
        cluster: "seMetering",
        type: ["attributeReport", "readResponse"],
        convert: (model, msg, publish, options, meta) => {
            const result = fz.metering.convert(model, msg, publish, options, meta);
            if (result && result.power !== undefined) {
                result.power /= 1000;
            }
            return result;
        },
    },
};
exports.definitions = [
    {
        zigbeeModel: ["W564100"],
        model: "W564100",
        vendor: "Schneider Electric",
        description: "Motion sensor",
        extend: [
            m.onOff({ powerOnBehavior: false }),
            // Illuminance doesn't require scale
            // https://github.com/Koenkk/zigbee2mqtt/issues/30580#issuecomment-3742159287
            m.illuminance({ scale: (v) => v }),
            m.temperature(),
            m.iasZoneAlarm({ zoneType: "occupancy", zoneAttributes: ["alarm_2"] }),
            m.commandsOnOff(),
            m.commandsLevelCtrl(),
        ],
    },
    {
        zigbeeModel: ["PUCK/SHUTTER/1"],
        model: "CCT5015-0001",
        vendor: "Schneider Electric",
        description: "Roller shutter module",
        fromZigbee: [fz.cover_position_tilt],
        toZigbee: [tz.cover_position_tilt, tz.cover_state, tzLocal.lift_duration],
        exposes: [
            e.cover_position(),
            e.numeric("lift_duration", ea.STATE_SET).withUnit("s").withValueMin(0).withValueMax(300).withDescription("Duration of lift"),
        ],
        meta: { coverInverted: true },
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(5);
            await reporting.bind(endpoint, coordinatorEndpoint, ["closuresWindowCovering"]);
            await reporting.currentPositionLiftPercentage(endpoint);
        },
    },
    {
        zigbeeModel: ["NHPB/SHUTTER/1"],
        model: "S520567",
        vendor: "Schneider Electric",
        description: "Wiser Odace roller shutter switch (S520567W)",
        onEvent: async (event) => {
            if (event.type !== "deviceOptionsChanged")
                return;
            const oldNoTilt = event.data.from?.no_tilt === true;
            const newNoTilt = event.data.to?.no_tilt === true;
            if (oldNoTilt === newNoTilt)
                return;
            const coverEndpoint = event.data.device.getEndpoint(5);
            await coverEndpoint.read("closuresWindowCovering", ["tiltOpenCloseAndStepTime"], { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC });
            await coverEndpoint.write("closuresWindowCovering", { tiltOpenCloseAndStepTime: newNoTilt ? 0 : 10 }, { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC });
            await coverEndpoint.read("closuresWindowCovering", ["tiltOpenCloseAndStepTime"], { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC });
            const controlEndpoint = event.data.device.getEndpoint(21);
            await controlEndpoint.read("manuSpecificSchneiderLightSwitchConfiguration", ["switchActions"], { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC });
            const switchActions = (newNoTilt ? 0 : 1) + (event.data.state.child_lock === "LOCK" ? 0 : 2);
            await controlEndpoint.write("manuSpecificSchneiderLightSwitchConfiguration", { switchActions }, { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC });
            await controlEndpoint.read("manuSpecificSchneiderLightSwitchConfiguration", ["switchActions"], { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC });
        },
        extend: [
            m.identify(),
            m.deviceEndpoints({ endpoints: { cover: 5, switch: 21 } }),
            schneiderElectricExtend.addSchneiderLightSwitchConfigurationCluster(),
            schneiderElectricExtend.addSchneiderClosuresWindowCoveringCluster(),
            m.enumLookup({
                name: "indicator_mode",
                lookup: {
                    consistent_with_load: 0,
                    always_on: 1,
                    reverse_with_load: 2,
                    always_off: 3,
                },
                cluster: "manuSpecificSchneiderLightSwitchConfiguration",
                attribute: "ledIndication",
                description: "Set Indicator Mode.",
                endpointName: "switch",
                entityCategory: "config",
            }),
            m.numeric({
                name: "lift_duration_up",
                endpointNames: ["cover"],
                cluster: "closuresWindowCovering",
                attribute: "liftDriveUpTime",
                unit: "s",
                valueMin: 0,
                valueMax: 300,
                valueStep: 0.1,
                scale: 10,
                description: "Duration in seconds for shutter upward movement (0.1s precision) (Default: 120)",
                zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC },
            }),
            m.numeric({
                name: "lift_duration_down",
                endpointNames: ["cover"],
                cluster: "closuresWindowCovering",
                attribute: "liftDriveDownTime",
                unit: "s",
                valueMin: 0,
                valueMax: 300,
                valueStep: 0.1,
                scale: 10,
                description: "Duration in seconds for shutter downward movement (0.1s precision) (Default: 120)",
                zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC },
            }),
            (() => {
                const extend = m.numeric({
                    name: "tilt_duration",
                    endpointNames: ["cover"],
                    cluster: "closuresWindowCovering",
                    attribute: "tiltOpenCloseAndStepTime",
                    unit: "s",
                    valueMin: 0,
                    valueMax: 30,
                    valueStep: 0.01,
                    scale: 100,
                    description: "Duration in seconds for shutter tilt movement (0.01s precision) (Default: 1)",
                    zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC },
                });
                const original_exposes = extend.exposes;
                extend.exposes = [
                    (device, options) => {
                        return options.no_tilt === true ? [] : original_exposes.flatMap((e) => (typeof e === "function" ? e(device, options) : e));
                    },
                ];
                return extend;
            })(),
        ],
        fromZigbee: [
            {
                ...fz.cover_position_tilt,
                convert: async (model, msg, publish, options, meta) => {
                    const result = await fz.cover_position_tilt.convert(model, msg, publish, options, meta);
                    if (!result)
                        return result;
                    delete result[(0, utils_1.postfixWithEndpointName)("state", msg, model, meta)];
                    return result;
                },
            },
            {
                cluster: "closuresWindowCovering",
                type: ["attributeReport", "readResponse"],
                convert: (model, msg) => {
                    const result = {};
                    const windowCoveringMode = msg.data.windowCoveringMode;
                    if (windowCoveringMode !== undefined) {
                        result.reversed = (windowCoveringMode & 1) !== 0;
                    }
                    return Object.keys(result).length > 0 ? result : undefined;
                },
            },
            {
                cluster: "manuSpecificSchneiderLightSwitchConfiguration",
                type: ["attributeReport", "readResponse"],
                convert: (model, msg, publish, options) => {
                    const result = {};
                    const switchActions = msg.data.switchActions;
                    if (switchActions !== undefined) {
                        result.child_lock = switchActions === 0 || switchActions === 1 ? "LOCK" : "UNLOCK";
                        result.tilt_lock = switchActions === 0 || switchActions === 2 ? "LOCK" : "UNLOCK";
                    }
                    return Object.keys(result).length > 0 ? result : undefined;
                },
            },
        ],
        toZigbee: [
            tz.cover_state,
            tz.cover_position_tilt,
            {
                key: ["reversed"],
                convertSet: async (entity, key, value, meta) => {
                    if (typeof value !== "boolean") {
                        throw new Error("reversed must be a boolean");
                    }
                    const endpoint = meta.device.getEndpoint(5);
                    const currentMode = await endpoint.read("closuresWindowCovering", [0x0017]);
                    const modeValue = currentMode.windowCoveringMode ?? 0;
                    const bit0 = 1 << 0;
                    const updatedModeValue = value ? modeValue | bit0 : modeValue & ~bit0;
                    await endpoint.write("closuresWindowCovering", { [0x0017]: { value: updatedModeValue, type: zigbee_herdsman_1.Zcl.DataType.BITMAP8 } });
                    return { state: { reversed: value } };
                },
                convertGet: async (entity, key, meta) => {
                    const endpoint = meta.device.getEndpoint(5);
                    await endpoint.read("closuresWindowCovering", [0x0017]);
                },
            },
            {
                key: ["child_lock"],
                convertSet: async (entity, key, value, meta) => {
                    const endpoint = meta.device.getEndpoint(21);
                    const switchActions = (meta.state.tilt_lock === "LOCK" ? 0 : 1) + (value === "LOCK" ? 0 : 2);
                    await endpoint.write("manuSpecificSchneiderLightSwitchConfiguration", { switchActions }, { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC });
                    return { state: { child_lock: value } };
                },
                convertGet: async (entity, key, meta) => {
                    const endpoint = meta.device.getEndpoint(21);
                    await endpoint.read("manuSpecificSchneiderLightSwitchConfiguration", ["switchActions"], { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC });
                },
            },
            {
                key: ["tilt_lock"],
                convertSet: async (entity, key, value, meta) => {
                    const endpoint = meta.device.getEndpoint(21);
                    const switchActions = (value === "LOCK" ? 0 : 1) + (meta.state.child_lock === "LOCK" ? 0 : 2);
                    await endpoint.write("manuSpecificSchneiderLightSwitchConfiguration", { switchActions }, { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC });
                    return { state: { tilt_lock: value } };
                },
                convertGet: async (entity, key, meta) => {
                    const endpoint = meta.device.getEndpoint(21);
                    await endpoint.read("manuSpecificSchneiderLightSwitchConfiguration", ["switchActions"], { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC });
                },
            },
        ],
        options: [
            e
                .binary("no_tilt", ea.SET, true, false)
                .withCategory("config")
                .withDescription("Disable tilt functionality, updating this setting will reset the values of tilt_duration and tilt_lock. (default: false)")
                .withHomeAssistant({ icon: "mdi:arrow-up-down" }),
        ],
        exposes: (device, options) => {
            const exposesList = [];
            const tilt_enabled = !(options.no_tilt === true);
            if (tilt_enabled) {
                exposesList.push(e.cover_position_tilt().withEndpoint("cover"));
            }
            else {
                exposesList.push(e.cover_position().withEndpoint("cover"));
            }
            exposesList.push(e
                .binary("reversed", ea.ALL, true, false)
                .withCategory("config")
                .withDescription("Reverse motor direction (window covering mode bit 0)")
                .withHomeAssistant({ icon: "mdi:swap-vertical" }));
            exposesList.push(e.child_lock().withAccess(ea.ALL));
            if (tilt_enabled) {
                exposesList.push(e
                    .binary("tilt_lock", ea.ALL, "LOCK", "UNLOCK")
                    .withCategory("config")
                    .withDescription("Disable or enable tilt control on the physical switch button")
                    .withHomeAssistant({ icon: "mdi:lock" }));
            }
            return exposesList;
        },
        meta: { coverInverted: true },
        configure: async (device, coordinatorEndpoint) => {
            const coverEndpoint = device.getEndpoint(5);
            await reporting.bind(coverEndpoint, coordinatorEndpoint, ["closuresWindowCovering"]);
            await reporting.currentPositionLiftPercentage(coverEndpoint);
            await reporting.currentPositionTiltPercentage(coverEndpoint);
            await coverEndpoint.read("closuresWindowCovering", ["windowCoveringMode"]);
            await coverEndpoint.read("closuresWindowCovering", ["liftDriveUpTime", "liftDriveDownTime", "tiltOpenCloseAndStepTime"], {
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC,
            });
            const controlEndpoint = device.getEndpoint(21);
            await controlEndpoint.read("manuSpecificSchneiderLightSwitchConfiguration", ["ledIndication", "switchActions"], { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SCHNEIDER_ELECTRIC });
        },
    },
    {
        zigbeeModel: ["iTRV"],
        model: "WV704R0A0902",
        vendor: "Schneider Electric",
        description: "Wiser radiator thermostat",
        extend: [schneiderElectricExtend.addWiserDeviceInfoCluster()],
        fromZigbee: [fz.ignore_haDiagnostic, fz.thermostat, fz.battery, fz.hvac_user_interface, fzLocal.wiser_device_info],
        toZigbee: [tz.thermostat_occupied_heating_setpoint, tz.thermostat_keypad_lockout],
        meta: { battery: { voltageToPercentage: { min: 2500, max: 3200 } } },
        exposes: [
            e
                .climate()
                .withSetpoint("occupied_heating_setpoint", 5, 30, 0.5)
                .withLocalTemperature(ea.STATE)
                .withRunningState(["idle", "heat"], ea.STATE)
                .withPiHeatingDemand(),
            e.battery(),
            e.battery_voltage(),
            e.keypad_lockout().withAccess(ea.ALL),
        ],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            const binds = ["genBasic", "genPowerCfg", "hvacThermostat", "haDiagnostic"];
            await reporting.bind(endpoint, coordinatorEndpoint, binds);
            await reporting.batteryVoltage(endpoint);
            await reporting.thermostatTemperature(endpoint);
            await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
            await reporting.thermostatPIHeatingDemand(endpoint);
            // bind of hvacUserInterfaceCfg fails with 'Table Full', does this have any effect?
            await endpoint.configureReporting("hvacUserInterfaceCfg", [
                {
                    attribute: "keypadLockout",
                    reportableChange: 1,
                    minimumReportInterval: constants.repInterval.MINUTE,
                    maximumReportInterval: constants.repInterval.HOUR,
                },
            ]);
        },
    },
    {
        zigbeeModel: ["U202DST600ZB"],
        model: "U202DST600ZB",
        vendor: "Schneider Electric",
        description: "EZinstall3 2 gang 2x300W dimmer module",
        extend: [m.deviceEndpoints({ endpoints: { l1: 10, l2: 11 } }), m.light({ endpointNames: ["l1", "l2"], configureReporting: true })],
    },
    {
        zigbeeModel: ["PUCK/DIMMER/1"],
        model: "CCT5010-0001",
        vendor: "Schneider Electric",
        description: "Micro module dimmer",
        ota: true,
        extend: [
            schneiderElectricExtend.addSchneiderLightingBallastCfgCluster(),
            m.light({ powerOnBehavior: false, configureReporting: true, levelConfig: {} }),
        ],
        fromZigbee: [fzLocal.wiser_lighting_ballast_configuration],
        toZigbee: [tz.ballast_config, tzLocal.wiser_dimmer_mode],
        exposes: [
            e
                .numeric("ballast_minimum_level", ea.ALL)
                .withValueMin(1)
                .withValueMax(254)
                .withDescription("Specifies the minimum light output of the ballast"),
            e
                .numeric("ballast_maximum_level", ea.ALL)
                .withValueMin(1)
                .withValueMax(254)
                .withDescription("Specifies the maximum light output of the ballast"),
            e
                .enum("dimmer_mode", ea.ALL, ["auto", "rc", "rl", "rl_led"])
                .withDescription("Sets dimming mode to autodetect or fixed RC/RL/RL_LED mode (max load is reduced in RL_LED)"),
        ],
        whiteLabel: [
            { vendor: "ELKO", model: "EKO07090" },
            { vendor: "Schneider Electric", model: "550B1012" },
        ],
    },
    {
        zigbeeModel: ["PUCK/SWITCH/1"],
        model: "CCT5011-0001/CCT5011-0002/MEG5011-0001",
        vendor: "Schneider Electric",
        description: "Micro module switch",
        ota: true,
        extend: [m.onOff({ powerOnBehavior: false })],
        whiteLabel: [{ vendor: "ELKO", model: "EKO07144" }],
    },
    {
        zigbeeModel: ["PUCK/UNIDIM/1"],
        model: "CCT5010-0003",
        vendor: "Schneider Electric",
        description: "Micro module dimmer with neutral lead",
        ota: true,
        extend: [
            schneiderElectricExtend.addSchneiderLightingBallastCfgCluster(),
            schneiderElectricExtend.addSchneiderLightSwitchConfigurationCluster(),
            m.light({ configureReporting: true, levelConfig: {}, powerOnBehavior: false }),
            m.deviceEndpoints({ endpoints: { l1: 21, l2: 22 } }),
            switchActions("l1"),
            switchActions("l2"),
        ],
        fromZigbee: [fzLocal.wiser_lighting_ballast_configuration],
        toZigbee: [tz.ballast_config, tzLocal.wiser_dimmer_mode],
        exposes: [
            e
                .numeric("ballast_minimum_level", ea.ALL)
                .withValueMin(1)
                .withValueMax(254)
                .withDescription("Specifies the minimum light output of the ballast"),
            e
                .numeric("ballast_maximum_level", ea.ALL)
                .withValueMin(1)
                .withValueMax(254)
                .withDescription("Specifies the maximum light output of the ballast"),
            e
                .enum("dimmer_mode", ea.ALL, ["auto", "rc", "rl", "rl_led"])
                .withDescription("Sets dimming mode to autodetect or fixed RC/RL/RL_LED mode (max load is reduced in RL_LED)"),
        ],
    },
    {
        zigbeeModel: ["CCTFR6730"],
        model: "CCTFR6730",
        vendor: "Schneider Electric",
        description: "Wiser power micromodule",
        whiteLabel: [{ vendor: "ELKO", model: "EKO20004" }],
        extend: [m.onOff({ powerOnBehavior: true }), m.electricityMeter({ cluster: "metering" }), m.identify()],
    },
    {
        zigbeeModel: ["NHROTARY/DIMMER/1"],
        model: "WDE002334",
        vendor: "Schneider Electric",
        description: "Rotary dimmer",
        extend: [schneiderElectricExtend.addSchneiderLightingBallastCfgCluster()],
        fromZigbee: [fz.on_off, fz.brightness, fz.level_config, fzLocal.wiser_lighting_ballast_configuration],
        toZigbee: [tz.light_onoff_brightness, tz.level_config, tz.ballast_config, tzLocal.wiser_dimmer_mode],
        exposes: [
            e.light_brightness().withLevelConfig(),
            e
                .numeric("ballast_minimum_level", ea.ALL)
                .withValueMin(1)
                .withValueMax(254)
                .withDescription("Specifies the minimum light output of the ballast"),
            e
                .numeric("ballast_maximum_level", ea.ALL)
                .withValueMin(1)
                .withValueMax(254)
                .withDescription("Specifies the maximum light output of the ballast"),
            e
                .enum("dimmer_mode", ea.ALL, ["auto", "rc", "rl", "rl_led"])
                .withDescription("Sets dimming mode to autodetect or fixed RC/RL/RL_LED mode (max load is reduced in RL_LED)"),
        ],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(3);
            await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff", "genLevelCtrl", "lightingBallastCfg"]);
            await reporting.onOff(endpoint);
            await reporting.brightness(endpoint);
        },
    },
    {
        zigbeeModel: ["NHROTARY/UNIDIM/1"],
        model: "NH3516A",
        vendor: "Schneider Electric",
        description: "Rotary dimmer",
        extend: [
            m.light({
                effect: false,
                powerOnBehavior: false,
                color: false,
                configureReporting: true,
                levelConfig: { features: ["on_level", "current_level_startup"] },
            }),
            m.lightingBallast(),
            schneiderElectricExtend.addSchneiderLightingBallastCfgCluster(),
            schneiderElectricExtend.dimmingMode(),
        ],
        whiteLabel: [
            { vendor: "ELKO", model: "EKO07278" },
            { vendor: "ELKO", model: "EKO07279" },
            { vendor: "ELKO", model: "EKO07280" },
            { vendor: "ELKO", model: "EKO07281" },
            { vendor: "ELKO", model: "EKO30198" },
            { vendor: "Schneider", model: "WDE002961" },
            { vendor: "Schneider", model: "WDE003961" },
            { vendor: "Schneider", model: "WDE004961" },
        ],
    },
    {
        zigbeeModel: ["NHPB/UNIDIM/1"],
        model: "WDE002960",
        vendor: "Schneider Electric",
        description: "Push button dimmer",
        extend: [schneiderElectricExtend.addSchneiderLightingBallastCfgCluster()],
        fromZigbee: [fz.on_off, fz.brightness, fz.level_config, fzLocal.wiser_lighting_ballast_configuration],
        toZigbee: [tz.light_onoff_brightness, tz.level_config, tz.ballast_config, tzLocal.wiser_dimmer_mode],
        exposes: [
            e.light_brightness().withLevelConfig(),
            e
                .numeric("ballast_minimum_level", ea.ALL)
                .withValueMin(1)
                .withValueMax(254)
                .withDescription("Specifies the minimum light output of the ballast"),
            e
                .numeric("ballast_maximum_level", ea.ALL)
                .withValueMin(1)
                .withValueMax(254)
                .withDescription("Specifies the maximum light output of the ballast"),
            e
                .enum("dimmer_mode", ea.ALL, ["auto", "rc", "rl", "rl_led"])
                .withDescription("Sets dimming mode to autodetect or fixed RC/RL/RL_LED mode (max load is reduced in RL_LED)"),
        ],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(3);
            await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff", "genLevelCtrl", "lightingBallastCfg"]);
            await reporting.onOff(endpoint);
            await reporting.brightness(endpoint);
        },
    },
    {
        zigbeeModel: ["CCT593011_AS"],
        model: "550B1024",
        vendor: "Schneider Electric",
        description: "Temperature & humidity sensor",
        fromZigbee: [fz.humidity, fz.temperature, fz.battery],
        toZigbee: [],
        exposes: [e.battery(), e.temperature(), e.humidity()],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            const binds = ["msTemperatureMeasurement", "genPowerCfg", "msRelativeHumidity"];
            await reporting.bind(endpoint, coordinatorEndpoint, binds);
            await reporting.batteryPercentageRemaining(endpoint);
            await reporting.temperature(endpoint);
            await reporting.humidity(endpoint);
        },
    },
    {
        zigbeeModel: ["NHPB/DIMMER/1"],
        model: "WDE002386",
        vendor: "Schneider Electric",
        description: "Push button dimmer",
        extend: [
            schneiderElectricExtend.addSchneiderLightSwitchConfigurationCluster(),
            m.light({
                effect: false,
                powerOnBehavior: true,
                configureReporting: true,
                levelConfig: { features: ["on_level", "current_level_startup"] },
            }),
            m.lightingBallast(),
            m.identify(),
            schneiderElectricExtend.addSchneiderLightingBallastCfgCluster(),
            schneiderElectricExtend.dimmingMode(),
            indicatorMode(),
        ],
        meta: { omitOptionalLevelAndColorParams: true },
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(3);
            await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff", "genLevelCtrl", "lightingBallastCfg"]);
            await reporting.onOff(endpoint);
            await reporting.brightness(endpoint);
        },
    },
    {
        zigbeeModel: ["CH/DIMMER/1"],
        model: "41EPBDWCLMZ/354PBDMBTZ",
        vendor: "Schneider Electric",
        description: "Wiser 40/300-Series Module Dimmer",
        fromZigbee: [fz.on_off, fz.brightness, fz.level_config, fz.lighting_ballast_configuration],
        toZigbee: [tz.light_onoff_brightness, tz.level_config, tz.ballast_config, tz.ignore_transition],
        exposes: [
            e.light_brightness().withLevelConfig(["on_level", "current_level_startup"]),
            e
                .numeric("ballast_minimum_level", ea.ALL)
                .withValueMin(1)
                .withValueMax(254)
                .withDescription("Specifies the minimum light output of the ballast"),
            e
                .numeric("ballast_maximum_level", ea.ALL)
                .withValueMin(1)
                .withValueMax(254)
                .withDescription("Specifies the maximum light output of the ballast"),
        ],
        ota: true,
        extend: [schneiderElectricExtend.addSchneiderLightSwitchConfigurationCluster(), indicatorMode("smart")],
        meta: { multiEndpoint: true },
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(3);
            await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff", "genLevelCtrl", "lightingBallastCfg"]);
            await reporting.onOff(endpoint);
            await reporting.brightness(endpoint);
        },
        endpoint: (device) => {
            return { smart: 21 };
        },
    },
    {
        zigbeeModel: ["CH2AX/SWITCH/1"],
        model: "41E2PBSWMZ/356PB2MBTZ",
        vendor: "Schneider Electric",
        description: "Wiser 40/300-Series module switch 2AX",
        ota: true,
        extend: [schneiderElectricExtend.addSchneiderLightSwitchConfigurationCluster(), m.onOff({ powerOnBehavior: false }), indicatorMode("smart")],
        meta: { multiEndpoint: true },
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff"]);
            await reporting.onOff(endpoint);
        },
        endpoint: (device) => {
            return { smart: 21 };
        },
    },
    {
        zigbeeModel: ["CH10AX/SWITCH/1"],
        model: "41E10PBSWMZ-VW",
        vendor: "Schneider Electric",
        description: "Wiser 40/300-Series module switch 10AX with ControlLink",
        ota: true,
        extend: [schneiderElectricExtend.addSchneiderLightSwitchConfigurationCluster(), m.onOff({ powerOnBehavior: false }), indicatorMode("smart")],
        meta: { multiEndpoint: true },
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff"]);
            await reporting.onOff(endpoint);
        },
        endpoint: (device) => {
            return { smart: 21 };
        },
    },
    {
        zigbeeModel: ["CHFAN/SWITCH/1"],
        model: "41ECSFWMZ-VW",
        vendor: "Schneider Electric",
        description: "Wiser 40/300-Series Module AC Fan Controller",
        fromZigbee: [fz.fan],
        toZigbee: [tzLocal.fan_mode],
        exposes: [e.fan().withState("fan_state").withModes(["off", "low", "medium", "high", "on"])],
        ota: true,
        extend: [schneiderElectricExtend.addSchneiderFanSwitchConfigurationCluster(), fanIndicatorMode(), fanIndicatorOrientation()],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(7);
            await reporting.bind(endpoint, coordinatorEndpoint, ["hvacFanCtrl"]);
            await reporting.fanMode(endpoint);
        },
    },
    {
        zigbeeModel: ["SMARTPLUG/1"],
        model: "CCT711119",
        vendor: "Schneider Electric",
        description: "Wiser smart plug",
        version: "0.0.1",
        extend: [
            m.onOff(),
            m.electricityMeter({
                power: { min: 5, change: 1 },
                energy: { min: "1_MINUTE", change: 1 },
                voltage: false,
                current: false,
            }),
        ],
    },
    {
        zigbeeModel: ["U201DST600ZB"],
        model: "U201DST600ZB",
        vendor: "Schneider Electric",
        description: "EZinstall3 1 gang 550W dimmer module",
        extend: [m.light({ configureReporting: true })],
    },
    {
        zigbeeModel: ["U201SRY2KWZB"],
        model: "U201SRY2KWZB",
        vendor: "Schneider Electric",
        description: "Ulti 240V 9.1 A 1 gang relay switch impress switch module, amber LED",
        extend: [m.onOff()],
    },
    {
        zigbeeModel: ["CCTFR6100"],
        model: "CCTFR6100Z3",
        vendor: "Schneider Electric",
        description: "Wiser radiator thermostat",
        extend: [schneiderElectricExtend.addWiserDeviceInfoCluster()],
        fromZigbee: [fz.ignore_haDiagnostic, fz.thermostat, fz.battery, fz.hvac_user_interface, fzLocal.wiser_device_info],
        toZigbee: [tz.thermostat_occupied_heating_setpoint, tz.thermostat_keypad_lockout],
        exposes: [
            e
                .climate()
                .withSetpoint("occupied_heating_setpoint", 7, 30, 1)
                .withLocalTemperature(ea.STATE)
                .withRunningState(["idle", "heat"], ea.STATE)
                .withPiHeatingDemand(),
        ],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            const binds = ["genBasic", "genPowerCfg", "hvacThermostat", "haDiagnostic"];
            await reporting.bind(endpoint, coordinatorEndpoint, binds);
            await reporting.batteryVoltage(endpoint);
            await reporting.thermostatTemperature(endpoint);
            await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
            await reporting.thermostatPIHeatingDemand(endpoint);
            // bind of hvacUserInterfaceCfg fails with 'Table Full', does this have any effect?
            await endpoint.configureReporting("hvacUserInterfaceCfg", [
                {
                    attribute: "keypadLockout",
                    reportableChange: 1,
                    minimumReportInterval: constants.repInterval.MINUTE,
                    maximumReportInterval: constants.repInterval.HOUR,
                },
            ]);
        },
    },
    {
        zigbeeModel: ["NHPB/SWITCH/1"],
        model: "S520530W",
        vendor: "Schneider Electric",
        description: "Odace connectable relay switch 10A",
        extend: [m.onOff({ powerOnBehavior: false }), m.commandsOnOff()],
    },
    {
        zigbeeModel: ["U202SRY2KWZB"],
        model: "U202SRY2KWZB",
        vendor: "Schneider Electric",
        description: "Ulti 240V 9.1 A 2 gangs relay switch impress switch module, amber LED",
        extend: [m.deviceEndpoints({ endpoints: { l1: 10, l2: 11 } }), m.onOff({ endpointNames: ["l1", "l2"] })],
    },
    {
        zigbeeModel: ["1GANG/SHUTTER/1"],
        model: "MEG5113-0300/MEG5165-0000",
        vendor: "Schneider Electric",
        description: "Merten MEG5165 PlusLink Shutter insert with Merten Wiser System M Push Button (1fold)",
        fromZigbee: [fz.cover_position_tilt, fz.command_cover_close, fz.command_cover_open, fz.command_cover_stop],
        toZigbee: [tz.cover_position_tilt, tz.cover_state, tzLocal.lift_duration],
        exposes: [
            e.cover_position_tilt(),
            e.numeric("lift_duration", ea.STATE_SET).withUnit("s").withValueMin(0).withValueMax(300).withDescription("Duration of lift"),
        ],
        meta: { coverInverted: true },
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1) || device.getEndpoint(5);
            await reporting.bind(endpoint, coordinatorEndpoint, ["closuresWindowCovering"]);
            await reporting.currentPositionLiftPercentage(endpoint);
        },
    },
    {
        zigbeeModel: ["1GANG/DIMMER/1", "1GANG/DALI/1"],
        model: "MEG5116-0300/MEG5171-0000",
        vendor: "Schneider Electric",
        description: "Merten MEG5171 PlusLink Dimmer insert with Merten Wiser System M Push Button (1fold)",
        fromZigbee: [fz.on_off, fz.brightness, fz.level_config, fzLocal.wiser_lighting_ballast_configuration],
        toZigbee: [tz.light_onoff_brightness, tz.level_config, tz.ballast_config, tzLocal.wiser_dimmer_mode],
        exposes: [
            e.light_brightness().withLevelConfig(),
            e
                .numeric("ballast_minimum_level", ea.ALL)
                .withValueMin(1)
                .withValueMax(254)
                .withDescription("Specifies the minimum light output of the ballast"),
            e
                .numeric("ballast_maximum_level", ea.ALL)
                .withValueMin(1)
                .withValueMax(254)
                .withDescription("Specifies the maximum light output of the ballast"),
            e
                .enum("dimmer_mode", ea.ALL, ["auto", "rc", "rl", "rl_led"])
                .withDescription("Sets dimming mode to autodetect or fixed RC/RL/RL_LED mode (max load is reduced in RL_LED)"),
        ],
        extend: [
            schneiderElectricExtend.addSchneiderLightingBallastCfgCluster(),
            schneiderElectricExtend.addSchneiderLightSwitchConfigurationCluster(),
            indicatorMode(),
            switchActions(),
        ],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(3);
            await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff", "genLevelCtrl", "lightingBallastCfg"]);
            await reporting.onOff(endpoint);
            await reporting.brightness(endpoint);
        },
    },
    {
        zigbeeModel: ["2GANG/DIMMER/1"],
        model: "MEG5126-0300/MEG5171-0000",
        vendor: "Schneider Electric",
        description: "Merten MEG5171 PlusLink Dimmer insert with Merten Wiser System M Push Button (2fold)",
        fromZigbee: [fz.on_off, fz.brightness, fz.level_config, fzLocal.wiser_lighting_ballast_configuration],
        toZigbee: [tz.light_onoff_brightness, tz.level_config, tz.ballast_config, tzLocal.wiser_dimmer_mode],
        exposes: [
            e.light_brightness().withLevelConfig(),
            e
                .numeric("ballast_minimum_level", ea.ALL)
                .withValueMin(1)
                .withValueMax(254)
                .withDescription("Specifies the minimum light output of the ballast"),
            e
                .numeric("ballast_maximum_level", ea.ALL)
                .withValueMin(1)
                .withValueMax(254)
                .withDescription("Specifies the maximum light output of the ballast"),
            e
                .enum("dimmer_mode", ea.ALL, ["auto", "rc", "rl", "rl_led"])
                .withDescription("Sets dimming mode to autodetect or fixed RC/RL/RL_LED mode (max load is reduced in RL_LED)"),
        ],
        extend: [
            schneiderElectricExtend.addSchneiderLightingBallastCfgCluster(),
            schneiderElectricExtend.addSchneiderLightSwitchConfigurationCluster(),
            indicatorMode("right"),
            indicatorMode("left"),
            switchActions("right"),
            switchActions("left"),
        ],
        meta: { multiEndpoint: true },
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(3);
            await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff", "genLevelCtrl", "lightingBallastCfg"]);
            await reporting.onOff(endpoint);
            await reporting.brightness(endpoint);
        },
        endpoint: (device) => {
            return { right: 21, left: 22 };
        },
    },
    {
        zigbeeModel: ["2GANG/DIMMER/2"],
        model: "MEG5126-0300/MEG5172-0000",
        vendor: "Schneider Electric",
        description: "Merten MEG5172 PlusLink Dimmer insert with Merten Wiser System M Push Button (2fold)",
        fromZigbee: [fzLocal.wiser_lighting_ballast_configuration],
        toZigbee: [tz.ballast_config, tzLocal.wiser_dimmer_mode],
        exposes: [
            e
                .numeric("ballast_minimum_level", ea.ALL)
                .withValueMin(1)
                .withValueMax(254)
                .withDescription("Specifies the minimum light output of the ballast"),
            e
                .numeric("ballast_maximum_level", ea.ALL)
                .withValueMin(1)
                .withValueMax(254)
                .withDescription("Specifies the maximum light output of the ballast"),
            e
                .enum("dimmer_mode", ea.ALL, ["auto", "rc", "rl", "rl_led"])
                .withDescription("Sets dimming mode to autodetect or fixed RC/RL/RL_LED mode (max load is reduced in RL_LED)"),
        ],
        extend: [
            schneiderElectricExtend.addSchneiderLightingBallastCfgCluster(),
            schneiderElectricExtend.addSchneiderLightSwitchConfigurationCluster(),
            m.deviceEndpoints({ endpoints: { left: 4, right: 3, left_btn: 22, right_btn: 21 } }),
            m.light({ endpointNames: ["left", "right"], configureReporting: true }),
            switchActions("left_btn"),
            switchActions("right_btn"),
            indicatorMode("left_btn"),
        ],
    },
    {
        zigbeeModel: ["1GANG/SWITCH/1"],
        model: "MEG5161-0000",
        vendor: "Schneider Electric",
        description: "Merten PlusLink relay insert with Merten Wiser system M push button (1fold)",
        extend: [m.onOff({ powerOnBehavior: false })],
    },
    {
        zigbeeModel: ["LK Switch"],
        model: "545D6514",
        vendor: "Schneider Electric",
        description: "LK FUGA wiser wireless double relay",
        meta: { multiEndpoint: true },
        fromZigbee: [fz.on_off, fz.command_on, fz.command_off],
        toZigbee: [tz.on_off],
        endpoint: (device) => {
            return { l1: 1, l2: 2, s1: 21, s2: 22, s3: 23, s4: 24 };
        },
        extend: [
            schneiderElectricExtend.addSchneiderLightSwitchConfigurationCluster(),
            indicatorMode("s1"),
            indicatorMode("s2"),
            indicatorMode("s3"),
            indicatorMode("s4"),
            switchActions("s1"),
            switchActions("s2"),
            switchActions("s3"),
            switchActions("s4"),
        ],
        exposes: [e.switch().withEndpoint("l1"), e.switch().withEndpoint("l2"), e.action(["on_s*", "off_s*"])],
        configure: (device, coordinatorEndpoint) => {
            device.endpoints.forEach(async (ep) => {
                if (ep.outputClusters.includes(6) || ep.ID <= 2) {
                    await reporting.bind(ep, coordinatorEndpoint, ["genOnOff"]);
                    if (ep.ID <= 2) {
                        await reporting.onOff(ep);
                    }
                }
            });
        },
    },
    {
        zigbeeModel: ["LK Dimmer"],
        model: "545D6102",
        vendor: "Schneider Electric",
        description: "LK FUGA wiser wireless dimmer",
        fromZigbee: [
            fzLocal.schneider_lighting_ballast_configuration,
            fz.command_recall,
            fz.command_on,
            fz.command_off,
            fz.command_move,
            fz.command_stop,
        ],
        toZigbee: [tz.ballast_config, tzLocal.schneider_dimmer_mode],
        endpoint: (device) => {
            return { l1: 3, s1: 21, s2: 22, s3: 23, s4: 24 };
        },
        meta: { multiEndpoint: true },
        extend: [
            m.light({ endpointNames: ["l1"], configureReporting: true, levelConfig: {} }),
            schneiderElectricExtend.addSchneiderLightSwitchConfigurationCluster(),
            schneiderElectricExtend.addSchneiderLightingBallastCfgCluster(),
            indicatorMode("s1"),
            indicatorMode("s2"),
            indicatorMode("s3"),
            indicatorMode("s4"),
            switchActions("s1"),
            switchActions("s2"),
            switchActions("s3"),
            switchActions("s4"),
        ],
        exposes: [
            e
                .numeric("ballast_minimum_level", ea.ALL)
                .withValueMin(1)
                .withValueMax(254)
                .withDescription("Specifies the minimum light output of the ballast")
                .withEndpoint("l1"),
            e
                .numeric("ballast_maximum_level", ea.ALL)
                .withValueMin(1)
                .withValueMax(254)
                .withDescription("Specifies the maximum light output of the ballast")
                .withEndpoint("l1"),
            e.enum("dimmer_mode", ea.ALL, ["RC", "RL"]).withDescription("Controls Capacitive or Inductive Dimming Mode").withEndpoint("l1"),
            e.action(["on", "off", "brightness_move_up", "brightness_move_down", "brightness_stop", "recall_*"]),
        ],
        configure: async (device, coordinatorEndpoint) => {
            // Configure the dimmer actuator endpoint
            const endpoint = device.getEndpoint(3);
            await reporting.bind(endpoint, coordinatorEndpoint, ["lightingBallastCfg"]);
            // Configure the four front switches
            device.endpoints.forEach(async (ep) => {
                if (21 <= ep.ID && ep.ID <= 22) {
                    await reporting.bind(ep, coordinatorEndpoint, ["genOnOff", "genLevelCtrl"]);
                }
                else if (23 <= ep.ID && ep.ID <= 24) {
                    await reporting.bind(ep, coordinatorEndpoint, ["genScenes"]);
                }
            });
        },
        onEvent: (event) => {
            // Record the factory default bindings for easy removal/change after deviceInterview
            if (event.type === "deviceInterview") {
                const dimmer = event.data.device.getEndpoint(3);
                event.data.device.endpoints.forEach((ep) => {
                    if (21 <= ep.ID && ep.ID <= 22) {
                        ep.addBinding("genOnOff", dimmer);
                        ep.addBinding("genLevelCtrl", dimmer);
                    }
                    if (23 <= ep.ID && ep.ID <= 24) {
                        ep.addBinding("genScenes", dimmer);
                    }
                });
            }
        },
    },
    {
        zigbeeModel: ["FLS/AIRLINK/4"],
        model: "550D6001",
        vendor: "Schneider Electric",
        description: "LK FUGA wiser wireless battery 4 button switch",
        fromZigbee: [fz.command_on, fz.command_off, fz.command_move, fz.command_stop, fz.battery],
        toZigbee: [],
        endpoint: (device) => {
            return { top: 21, bottom: 22 };
        },
        whiteLabel: [{ vendor: "ELKO", model: "EKO07117" }],
        meta: { multiEndpoint: true },
        exposes: [
            e.action([
                "on_top",
                "off_top",
                "on_bottom",
                "off_bottom",
                "brightness_move_up_top",
                "brightness_stop_top",
                "brightness_move_down_top",
                "brightness_stop_top",
                "brightness_move_up_bottom",
                "brightness_stop_bottom",
                "brightness_move_down_bottom",
                "brightness_stop_bottom",
            ]),
            e.battery(),
        ],
        configure: async (device, coordinatorEndpoint) => {
            // When in 2-gang operation mode, unit operates out of endpoints 21 and 22, otherwise just 21
            const topButtonsEndpoint = device.getEndpoint(21);
            await reporting.bind(topButtonsEndpoint, coordinatorEndpoint, ["genOnOff", "genLevelCtrl", "genPowerCfg"]);
            await reporting.batteryPercentageRemaining(topButtonsEndpoint);
            const bottomButtonsEndpoint = device.getEndpoint(22);
            await reporting.bind(bottomButtonsEndpoint, coordinatorEndpoint, ["genOnOff", "genLevelCtrl"]);
        },
    },
    {
        fingerprint: [
            { modelID: "CCTFR6700", manufacturerName: "Schneider Electric" },
            { modelID: "CCTFR6710", manufacturerName: "Schneider Electric" },
        ],
        model: "CCTFR6700",
        vendor: "Schneider Electric",
        description: "Heating thermostat",
        whiteLabel: [{ model: "CCTFR6710", fingerprint: [{ modelID: "CCTFR6710" }] }],
        fromZigbee: [fz.thermostat, fz.metering],
        toZigbee: [
            tzLocal.cctfr6700_temperature_measured_value,
            tz.thermostat_system_mode,
            tz.thermostat_running_state,
            tz.thermostat_local_temperature,
            tz.thermostat_occupied_heating_setpoint,
            tz.thermostat_control_sequence_of_operation,
        ],
        extend: [schneiderElectricExtend.addHeatingCoolingOutputClusterServer(), schneiderElectricExtend.pilotMode()],
        exposes: [
            e.power(),
            e.energy(),
            e
                .climate()
                .withSetpoint("occupied_heating_setpoint", 4, 30, 0.5)
                .withLocalTemperature()
                .withSystemMode(["off", "auto", "heat"])
                .withPiHeatingDemand(),
        ],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint1 = device.getEndpoint(1);
            const endpoint2 = device.getEndpoint(2);
            await reporting.bind(endpoint1, coordinatorEndpoint, ["hvacThermostat"]);
            await reporting.thermostatOccupiedHeatingSetpoint(endpoint1);
            await reporting.thermostatPIHeatingDemand(endpoint1);
            await reporting.bind(endpoint2, coordinatorEndpoint, ["seMetering"]);
            await reporting.instantaneousDemand(endpoint2, { min: 0, max: 60, change: 1 });
            await reporting.currentSummDelivered(endpoint2, { min: 0, max: 60, change: 1 });
        },
    },
    {
        fingerprint: [{ modelID: "Thermostat", manufacturerName: "Schneider Electric" }],
        model: "CCTFR6400",
        vendor: "Schneider Electric",
        description: "Temperature/Humidity measurement with thermostat interface",
        extend: [schneiderElectricExtend.customThermostatCluster(), schneiderElectricExtend.addWiserDeviceInfoCluster()],
        fromZigbee: [
            fz.battery,
            fzLocal.schneider_temperature,
            fz.humidity,
            fz.thermostat,
            fzLocal.schneider_ui_action,
            fzLocal.cctfr6400_boost,
            fzLocal.cctfr6400_ignore_thermostat_read,
            fzLocal.cctfr6400_ignore_setpoint_raise_lower,
            fz.ignore_haDiagnostic,
        ],
        toZigbee: [
            tzLocal.cctfr6400_thermostat_system_mode,
            tzLocal.cctfr6400_thermostat_occupied_heating_setpoint,
            tzLocal.cctfr6400_thermostat_control_sequence_of_operation,
            tzLocal.cctfr6400_thermostat_pi_heating_demand,
            tzLocal.schneider_thermostat_keypad_lockout,
        ],
        exposes: [
            e.keypad_lockout().withAccess(ea.STATE_SET),
            e.humidity(),
            e.battery(),
            e.battery_voltage(),
            e.action([
                "screen_sleep",
                "screen_wake",
                "button_press_plus_down",
                "button_press_center_down",
                "button_press_minus_down",
                "boost_set",
                "boost_cancel",
            ]),
            e
                .numeric("boost_duration", ea.STATE)
                .withUnit("min")
                .withDescription("Duration in minutes of the last boost committed on the device (0 when cancelled)"),
            e.numeric("boost_temperature", ea.STATE).withUnit("°C").withDescription("Target temperature of the last boost committed on the device"),
            e.climate().withSetpoint("occupied_heating_setpoint", 4, 30, 0.5, ea.SET).withLocalTemperature(ea.STATE).withPiHeatingDemand(ea.SET),
        ],
        meta: { battery: { dontDividePercentage: true } },
        onEvent: (event) => {
            if (event.type === "stop") {
                clearTimeout(globalStore.getValue(event.data.ieeeAddr, cctfr6400BoostTimerStoreKey));
                globalStore.clearValue(event.data.ieeeAddr, cctfr6400BoostTimerStoreKey);
                globalStore.clearValue(event.data.ieeeAddr, cctfr6400PublishStoreKey);
                globalStore.clearValue(event.data.ieeeAddr, cctfr6400PendingPublishStoreKey);
            }
            else if (event.type === "start") {
                cctfr6400InstallCustomReadResponse(event.data.device);
                cctfr6400BoostResume(event.data.device, event.data.options);
            }
            else if (event.type === "deviceOptionsChanged" && event.data.to.boost_auto_honor === false) {
                // Auto honor was turned off: forget a pending boost without
                // touching the setpoint, an external automation is in charge.
                cctfr6400BoostWipe(event.data.device);
            }
        },
        configure: async (device, coordinatorEndpoint) => {
            const endpoint1 = device.getEndpoint(1);
            await reporting.bind(endpoint1, coordinatorEndpoint, ["genPowerCfg", "hvacThermostat", "msTemperatureMeasurement", "msRelativeHumidity"]);
            await reporting.temperature(endpoint1);
            await reporting.humidity(endpoint1);
            await reporting.batteryPercentageRemaining(endpoint1);
            endpoint1.saveClusterAttributeKeyValue("genBasic", { zclVersion: 3 });
            endpoint1.saveClusterAttributeKeyValue("hvacThermostat", { schneiderWiserSpecific: 1, systemMode: 4, ctrlSeqeOfOper: 2 });
            endpoint1.saveClusterAttributeKeyValue("hvacUserInterfaceCfg", { keypadLockout: 0 });
        },
    },
    {
        zigbeeModel: ["EH-ZB-SPD-V2"],
        model: "EER40030",
        vendor: "Schneider Electric",
        description: "Zigbee smart plug with power meter",
        fromZigbee: [fz.on_off, fz.metering],
        toZigbee: [tz.on_off],
        exposes: [e.switch(), e.power(), e.energy()],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(11);
            const options = { disableDefaultResponse: true };
            await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff", "seMetering"]);
            await reporting.onOff(endpoint);
            await reporting.readMeteringMultiplierDivisor(endpoint);
            await reporting.instantaneousDemand(endpoint);
            await endpoint.write("genBasic", { 57424: { value: 1, type: 0x10 } }, options);
        },
    },
    {
        zigbeeModel: ["EH-ZB-LMACT"],
        model: "EER42000",
        vendor: "Schneider Electric",
        description: "Zigbee load actuator with power meter",
        fromZigbee: [fz.on_off, fz.metering],
        toZigbee: [tz.on_off],
        exposes: [e.switch(), e.power(), e.energy()],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(11);
            await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff", "seMetering"]);
            await reporting.onOff(endpoint);
            await reporting.readMeteringMultiplierDivisor(endpoint);
            await reporting.instantaneousDemand(endpoint);
        },
    },
    {
        zigbeeModel: ["2GANG/SWITCH/2", "2GANG/SWITCH/1"],
        model: "MEG5126-0300",
        vendor: "Schneider Electric",
        description: "Merten MEG5165 PlusLink relais insert with Merten Wiser System M push button (2fold)",
        extend: [m.deviceEndpoints({ endpoints: { l1: 1, l2: 2 } }), m.onOff({ endpointNames: ["l1", "l2"], powerOnBehavior: false })],
    },
    {
        zigbeeModel: ["EH-ZB-VACT"],
        model: "EER53000",
        vendor: "Schneider Electric",
        description: "Wiser radiator thermostat (VACT)",
        extend: [schneiderElectricExtend.customThermostatCluster()],
        fromZigbee: [
            fz.battery,
            fz.hvac_user_interface,
            fzLocal.wiser_smart_thermostat,
            fzLocal.wiser_smart_thermostat_client,
            fzLocal.wiser_smart_setpoint_command_client,
        ],
        toZigbee: [
            tzLocal.wiser_sed_thermostat_local_temperature_calibration,
            tzLocal.wiser_sed_occupied_heating_setpoint,
            tzLocal.wiser_sed_thermostat_keypad_lockout,
            tzLocal.wiser_vact_calibrate_valve,
            tzLocal.wiser_sed_zone_mode,
        ],
        exposes: [
            e.battery(),
            e.binary("keypad_lockout", ea.STATE_SET, "lock1", "unlock").withDescription("Enables/disables physical input on the device"),
            e.binary("calibrate_valve", ea.STATE_SET, "calibrate", "idle").withDescription("Calibrates valve on next wakeup"),
            e.enum("valve_calibration_status", ea.STATE, ["ongoing", "successful", "uncalibrated", "failed_e1", "failed_e2", "failed_e3"]),
            e.enum("zone_mode", ea.STATE_SET, ["manual", "schedule", "energy_saver", "holiday"]).withDescription("Icon shown on device displays"),
            e
                .climate()
                .withSetpoint("occupied_heating_setpoint", 7, 30, 0.5, ea.STATE_SET)
                .withLocalTemperature(ea.STATE)
                .withLocalTemperatureCalibration(-12.8, 12.7, 0.1, ea.STATE_SET)
                .withPiHeatingDemand(),
        ],
        meta: { battery: { voltageToPercentage: { min: 2500, max: 3000 } } },
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(11);
            // Insert default values for client requested attributes
            endpoint.saveClusterAttributeKeyValue("hvacThermostat", { minHeatSetpointLimit: 7 * 100 });
            endpoint.saveClusterAttributeKeyValue("hvacThermostat", { maxHeatSetpointLimit: 30 * 100 });
            endpoint.saveClusterAttributeKeyValue("hvacThermostat", { occupiedHeatingSetpoint: 20 * 100 });
            endpoint.saveClusterAttributeKeyValue("hvacThermostat", { systemMode: 4 });
            // VACT needs binding to endpoint 11 due to some hardcoding in the device
            const coordinatorEndpointB = coordinatorEndpoint.getDevice().getEndpoint(11);
            const binds = ["genBasic", "genPowerCfg", "hvacThermostat"];
            await reporting.bind(endpoint, coordinatorEndpointB, binds);
            await reporting.batteryVoltage(endpoint);
            await reporting.thermostatTemperature(endpoint);
            await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
            await endpoint.configureReporting("hvacUserInterfaceCfg", [
                {
                    attribute: "keypadLockout",
                    minimumReportInterval: constants.repInterval.MINUTE,
                    maximumReportInterval: constants.repInterval.HOUR,
                    reportableChange: 1,
                },
            ]);
        },
    },
    {
        zigbeeModel: ["EH-ZB-RTS"],
        model: "EER51000",
        vendor: "Schneider Electric",
        description: "Wiser thermostat (RTS)",
        extend: [schneiderElectricExtend.customThermostatCluster()],
        fromZigbee: [
            fz.battery,
            fz.hvac_user_interface,
            fzLocal.wiser_smart_thermostat_client,
            fzLocal.wiser_smart_setpoint_command_client,
            fzLocal.schneider_temperature,
        ],
        toZigbee: [tzLocal.wiser_sed_zone_mode, tzLocal.wiser_sed_occupied_heating_setpoint],
        exposes: [
            e.battery(),
            e.climate().withSetpoint("occupied_heating_setpoint", 7, 30, 0.5, ea.STATE_SET).withLocalTemperature(ea.STATE),
            e.enum("zone_mode", ea.STATE_SET, ["manual", "schedule", "energy_saver", "holiday"]).withDescription("Icon shown on device displays"),
        ],
        meta: { battery: { voltageToPercentage: { min: 3000, max: 4200 } } },
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(11);
            // Insert default values for client requested attributes
            endpoint.saveClusterAttributeKeyValue("hvacThermostat", { minHeatSetpointLimit: 7 * 100 });
            endpoint.saveClusterAttributeKeyValue("hvacThermostat", { maxHeatSetpointLimit: 30 * 100 });
            endpoint.saveClusterAttributeKeyValue("hvacThermostat", { occupiedHeatingSetpoint: 20 * 100 });
            endpoint.saveClusterAttributeKeyValue("hvacThermostat", { systemMode: 4 });
            // RTS needs binding to endpoint 11 due to some hardcoding in the device
            const coordinatorEndpointB = coordinatorEndpoint.getDevice().getEndpoint(11);
            const binds = [
                "genBasic",
                "genPowerCfg",
                "genIdentify",
                "genAlarms",
                "genOta",
                "hvacThermostat",
                "hvacUserInterfaceCfg",
                "msTemperatureMeasurement",
            ];
            await reporting.bind(endpoint, coordinatorEndpointB, binds);
            // Battery reports without config once a day, do the first read manually
            await endpoint.read("genPowerCfg", ["batteryVoltage"]);
            await endpoint.configureReporting("msTemperatureMeasurement", [
                {
                    attribute: "measuredValue",
                    minimumReportInterval: constants.repInterval.MINUTE,
                    maximumReportInterval: constants.repInterval.MINUTES_10,
                    reportableChange: 50,
                },
            ]);
        },
    },
    {
        zigbeeModel: ["EH-ZB-HACT"],
        model: "EER50000",
        vendor: "Schneider Electric",
        description: "Wiser H-Relay (HACT)",
        extend: [schneiderElectricExtend.customThermostatCluster()],
        fromZigbee: [fzLocal.wiser_smart_thermostat, fz.metering, fz.identify],
        toZigbee: [
            tz.thermostat_local_temperature,
            tz.thermostat_occupied_heating_setpoint,
            tzLocal.wiser_fip_setting,
            tzLocal.wiser_hact_config,
            tzLocal.wiser_zone_mode,
            tz.identify,
        ],
        exposes: [
            e.climate().withSetpoint("occupied_heating_setpoint", 7, 30, 0.5).withLocalTemperature(),
            e.power(),
            e.energy(),
            e.enum("identify", ea.SET, ["0", "30", "60", "600", "900"]).withDescription("Flash green tag for x seconds"),
            e.enum("zone_mode", ea.ALL, ["manual", "schedule", "energy_saver", "holiday"]),
            e
                .enum("hact_config", ea.ALL, ["unconfigured", "setpoint_switch", "setpoint_fip", "fip_fip"])
                .withDescription("Input (command) and output (control) behavior of actuator"),
            e
                .enum("fip_setting", ea.ALL, ["comfort", "comfort_-1", "comfort_-2", "energy_saving", "frost_protection", "off"])
                .withDescription("Output signal when operating in fil pilote mode (fip_fip)"),
        ],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(11);
            const binds = ["genBasic", "genPowerCfg", "hvacThermostat", "msTemperatureMeasurement", "seMetering"];
            await reporting.bind(endpoint, coordinatorEndpoint, binds);
            await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
            await reporting.readMeteringMultiplierDivisor(endpoint);
            await reporting.instantaneousDemand(endpoint);
        },
    },
    {
        zigbeeModel: ["FLS/SYSTEM-M/4"],
        model: "WDE002906/MEG5001-0300",
        vendor: "Schneider Electric",
        description: "Wiser wireless switch 1-gang or 2-gang",
        extend: [
            m.battery(),
            m.deviceEndpoints({ endpoints: { right: 21, left: 22 } }),
            schneiderElectricExtend.addSchneiderLightSwitchConfigurationCluster(),
            switchActions("right"),
            switchActions("left"),
            m.commandsOnOff({ endpointNames: ["right", "left"] }),
            m.commandsLevelCtrl({ endpointNames: ["right", "left"] }),
        ],
    },
    {
        zigbeeModel: ["SOCKET/OUTLET/2"],
        model: "EKO09738",
        vendor: "Schneider Electric",
        description: "Zigbee smart socket with power meter",
        fromZigbee: [fz.on_off, fz.electrical_measurement, fzLocal.EKO09738_metering, fz.power_on_behavior],
        toZigbee: [tz.on_off, tz.power_on_behavior],
        exposes: [
            e.switch(),
            e.power(),
            e.energy(),
            e.enum("power_on_behavior", ea.ALL, ["off", "previous", "on"]).withDescription("Controls the behaviour when the device is powered on"),
            e.current(),
            e.voltage(),
        ],
        whiteLabel: [{ vendor: "ELKO", model: "EKO09738", description: "SmartStikk" }],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(6);
            await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff", "haElectricalMeasurement", "seMetering"]);
            await reporting.onOff(endpoint);
            // Unit supports acVoltage and acCurrent, but only acCurrent divisor/multiplier can be read
            await endpoint.read("haElectricalMeasurement", ["acCurrentDivisor", "acCurrentMultiplier"]);
            await reporting.readMeteringMultiplierDivisor(endpoint);
        },
    },
    {
        zigbeeModel: ["SOCKET/OUTLET/1"],
        model: "EKO09716",
        vendor: "Schneider Electric",
        description: "Zigbee smart socket with power meter",
        fromZigbee: [fz.on_off, fz.electrical_measurement, fzLocal.EKO09738_metering, fz.power_on_behavior],
        toZigbee: [tz.on_off, tz.power_on_behavior],
        exposes: [
            e.switch(),
            e.power(),
            e.energy(),
            e.enum("power_on_behavior", ea.ALL, ["off", "previous", "on"]).withDescription("Controls the behaviour when the device is powered on"),
            e.current(),
            e.voltage(),
        ],
        extend: [schneiderElectricExtend.addSchneiderFanSwitchConfigurationCluster(), socketIndicatorMode()],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(6);
            await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff", "haElectricalMeasurement", "seMetering"]);
            await reporting.onOff(endpoint);
            // Unit supports acVoltage and acCurrent, but only acCurrent divisor/multiplier can be read
            await endpoint.read("haElectricalMeasurement", ["acCurrentDivisor", "acCurrentMultiplier"]);
            await reporting.readMeteringMultiplierDivisor(endpoint);
        },
    },
    {
        zigbeeModel: ["LK/OUTLET/1"],
        model: "545D6115",
        vendor: "Schneider Electric",
        description: "LK FUGA wiser wireless socket outlet",
        fromZigbee: [fz.on_off, fz.electrical_measurement, fzLocal.EKO09738_metering, fz.power_on_behavior],
        toZigbee: [tz.on_off, tz.power_on_behavior],
        extend: [schneiderElectricExtend.addSchneiderFanSwitchConfigurationCluster(), socketIndicatorMode()],
        exposes: [
            e.switch(),
            e.power(),
            e.energy(),
            e.current(),
            e.voltage(),
            e.enum("power_on_behavior", ea.ALL, ["off", "previous", "on"]).withDescription("Controls the behaviour when the device is powered on"),
        ],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(6);
            await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff", "haElectricalMeasurement", "seMetering"]);
            await reporting.onOff(endpoint);
            // Unit supports acVoltage and acCurrent, but only acCurrent divisor/multiplier can be read
            await endpoint.read("haElectricalMeasurement", ["acCurrentDivisor", "acCurrentMultiplier"]);
            await reporting.readMeteringMultiplierDivisor(endpoint);
            await reporting.currentSummDelivered(endpoint, { min: 60, change: 1 });
        },
    },
    {
        zigbeeModel: ["EVSCKT/OUTLET/1"],
        model: "MUR36014",
        vendor: "Schneider Electric",
        description: "Mureva EVlink Smart socket outlet",
        extend: [
            schneiderElectricExtend.addSchneiderFanSwitchConfigurationCluster(),
            m.onOff(),
            m.electricityMeter({
                // Unit supports acVoltage and acCurrent, but only acCurrent divisor/multiplier can be read
                voltage: { multiplier: 1, divisor: 1 },
                // power is provided by 'seMetering' instead of "haElectricalMeasurement"
                power: { cluster: "metering" },
            }),
            evlinkIndicatorMode(),
        ],
    },
    {
        zigbeeModel: ["NHMOTION/SWITCH/1"],
        model: "NH3526",
        vendor: "Schneider Electric",
        description: "Motion sensor with switch",
        extend: [
            m.onOff({
                powerOnBehavior: false,
                configureReporting: true,
            }),
            m.illuminance(),
            m.occupancy({
                pirConfig: ["otu_delay"],
            }),
            schneiderElectricExtend.addOccupancyConfigurationCluster(),
            schneiderElectricExtend.occupancyConfiguration(),
        ],
        whiteLabel: [
            { vendor: "ELKO", model: "EKO06988" },
            { vendor: "ELKO", model: "EKO06989" },
            { vendor: "ELKO", model: "EKO06990" },
            { vendor: "ELKO", model: "EKO06991" },
            { vendor: "LK", model: "545D6306" },
        ],
    },
    {
        zigbeeModel: ["CCT595011_AS"],
        model: "CCT595011",
        vendor: "Schneider Electric",
        description: "Wiser motion sensor",
        version: "0.0.1",
        extend: [
            m.battery(),
            m.iasZoneAlarm({ zoneType: "occupancy", zoneAttributes: ["alarm_2", "battery_low"] }),
            m.illuminance(),
            m.enumLookup({
                name: "sensitivity_level",
                description: "Sensitivity level for the occupancy sensor",
                attribute: "currentZoneSensitivityLevel",
                cluster: "ssIasZone",
                lookup: { low: 0x00, medium: 0x01, high: 0x02 },
                entityCategory: "config",
            }),
        ],
    },
    {
        zigbeeModel: ["CH/Socket/2"],
        model: "3025CSGZ",
        vendor: "Schneider Electric",
        description: "Dual connected smart socket",
        ota: true,
        extend: [m.deviceEndpoints({ endpoints: { l1: 1, l2: 2 } }), m.onOff({ endpointNames: ["l1", "l2"] })],
    },
    {
        zigbeeModel: ["CCT592011_AS"],
        model: "CCT592011",
        vendor: "Schneider Electric",
        description: "Wiser water leakage sensor",
        fromZigbee: [fz.ias_water_leak_alarm_1],
        toZigbee: [],
        exposes: [e.battery_low(), e.water_leak(), e.tamper()],
    },
    {
        fingerprint: [{ modelID: "GreenPower_254", ieeeAddr: /^0x00000000e.......$/ }],
        model: "A9MEM1570",
        vendor: "Schneider Electric",
        description: "PowerTag power sensor",
        fromZigbee: [fzLocal.schneider_powertag],
        toZigbee: [],
        exposes: [
            e.power(),
            e.power_apparent(),
            e.numeric("power_phase_a", ea.STATE).withUnit("W").withDescription("Instantaneous measured power on phase A"),
            e.numeric("power_phase_b", ea.STATE).withUnit("W").withDescription("Instantaneous measured power on phase B"),
            e.numeric("power_phase_c", ea.STATE).withUnit("W").withDescription("Instantaneous measured power on phase C"),
            e.power_factor(),
            e.energy(),
            e.numeric("energy_phase_a", ea.STATE).withUnit("kWh").withDescription("Sum of consumed energy on phase A"),
            e.numeric("energy_phase_b", ea.STATE).withUnit("kWh").withDescription("Sum of consumed energy on phase B"),
            e.numeric("energy_phase_c", ea.STATE).withUnit("kWh").withDescription("Sum of consumed energy on phase C"),
            e.ac_frequency(),
            e.numeric("voltage_phase_a", ea.STATE).withUnit("V").withDescription("Measured electrical potential value on phase A"),
            e.numeric("voltage_phase_b", ea.STATE).withUnit("V").withDescription("Measured electrical potential value on phase B"),
            e.numeric("voltage_phase_c", ea.STATE).withUnit("V").withDescription("Measured electrical potential value on phase C"),
            e.numeric("voltage_phase_ab", ea.STATE).withUnit("V").withDescription("Measured electrical potential value between phase A and B"),
            e.numeric("voltage_phase_bc", ea.STATE).withUnit("V").withDescription("Measured electrical potential value between phase B and C"),
            e.numeric("voltage_phase_ca", ea.STATE).withUnit("V").withDescription("Measured electrical potential value between phase C and A"),
            e.numeric("current_phase_a", ea.STATE).withUnit("A").withDescription("Instantaneous measured electrical current on phase A"),
            e.numeric("current_phase_b", ea.STATE).withUnit("A").withDescription("Instantaneous measured electrical current on phase B"),
            e.numeric("current_phase_c", ea.STATE).withUnit("A").withDescription("Instantaneous measured electrical current on phase C"),
        ],
    },
    {
        zigbeeModel: ["W599001", "W599501", "755WSA"],
        model: "W599001",
        vendor: "Schneider Electric",
        description: "Wiser smoke alarm",
        extend: [
            m.battery({ voltage: true, voltageReporting: true }),
            m.temperature(),
            m.iasZoneAlarm({
                zoneType: "smoke",
                zoneAttributes: ["alarm_1", "tamper", "battery_low", "test"],
                zoneStatusReporting: true,
                manufacturerZoneAttributes: [
                    {
                        bit: 1,
                        name: "heat",
                        valueOn: true,
                        valueOff: false,
                        description: "Indicates whether the device has detected high temperature",
                    },
                    {
                        bit: 11,
                        name: "hush",
                        valueOn: true,
                        valueOff: false,
                        description: "Indicates whether the device is in hush mode",
                        entityCategory: "diagnostic",
                    },
                ],
            }),
        ],
        whiteLabel: [
            { vendor: "Schneider Electric", model: "W599501", description: "Wiser smoke alarm", fingerprint: [{ modelID: "W599501" }] },
            { vendor: "Schneider Electric", model: "755WSA", description: "Clipsal Wiser smoke alarm", fingerprint: [{ modelID: "755WSA" }] },
        ],
    },
    {
        zigbeeModel: ["CCT591011_AS"],
        model: "CCT591011_AS",
        vendor: "Schneider Electric",
        description: "Wiser window/door sensor",
        fromZigbee: [fz.ias_contact_alarm_1, fz.ias_contact_alarm_1_report],
        toZigbee: [],
        exposes: [e.battery_low(), e.contact(), e.tamper()],
    },
    {
        zigbeeModel: ["EKO07259"],
        model: "EKO07259",
        vendor: "Schneider Electric",
        description: "Smart thermostat",
        extend: [
            m.thermostat({
                localTemperature: {
                    values: {
                        description: "The temperature measured by the selected sensor (see 'Local temperature source select', Ambient or External).",
                    },
                },
                setpoints: { values: { occupiedHeatingSetpoint: { min: 4, max: 40, step: 0.5 } } },
                setpointsLimit: {
                    maxHeatSetpointLimit: { min: 4, max: 40, step: 0.5 },
                    minHeatSetpointLimit: { min: 4, max: 40, step: 0.5 },
                },
                runningState: {
                    values: ["idle", "heat"],
                    toZigbee: { skip: true },
                    configure: { skip: true },
                },
                systemMode: { values: ["off", "heat"] },
                piHeatingDemand: { values: true, dontMapPIHeatingDemand: true },
                ctrlSeqeOfOper: { values: ["cooling_only", "heating_only"] },
            }),
            schneiderElectricExtend.runningStateFromPower(),
            m.electricityMeter({
                cluster: "metering",
                voltage: false,
                current: false,
                configureReporting: true,
                energy: { divisor: 1000, multiplier: 1 },
            }),
            schneiderElectricExtend.customMeteringCluster(),
            schneiderElectricExtend.fixedLoadDemand(),
            schneiderElectricExtend.addHvacUserInterfaceCfgCustomAttributes(),
            schneiderElectricExtend.displayBrightnessActive(),
            schneiderElectricExtend.displayBrightnessInactive(),
            schneiderElectricExtend.displayActiveTimeout(),
            schneiderElectricExtend.customThermostatCluster(),
            schneiderElectricExtend.localTemperatureSourceSelect(),
            schneiderElectricExtend.controlType(),
            schneiderElectricExtend.controlStatus(),
            schneiderElectricExtend.thermostatApplication(),
            schneiderElectricExtend.heatingEmitter(),
            schneiderElectricExtend.addHeatingCoolingOutputClusterServer(),
            schneiderElectricExtend.heatingOutputMode({
                description: "On devices with alternate heating output types, this selects which should be used to control the heating unit. This attribute is (mistakenly) also called pilot_mode on some devices.",
                lookup: { Disabled: 0, Relay: 1 },
            }),
            schneiderElectricExtend.customTemperatureMeasurementCluster(),
            m.deviceEndpoints({
                endpoints: { floor: 3 },
            }),
            schneiderElectricExtend.sensorCorrection({
                endpointNames: ["floor"],
            }),
            schneiderElectricExtend.temperatureSensorType({
                endpointName: "floor",
            }),
            m.enumLookup({
                name: "temperature_display_mode",
                lookup: { celsius: 0 },
                cluster: "hvacUserInterfaceCfg",
                attribute: "tempDisplayMode",
                description: "The unit of the temperature displayed on the device screen. Celsius is the only supported unit.",
                entityCategory: "config",
            }),
            m.binary({
                name: "child_lock",
                valueOn: ["LOCK", 1],
                valueOff: ["UNLOCK", 0],
                cluster: "hvacUserInterfaceCfg",
                attribute: "keypadLockout",
                description: "Enables/disables physical input on the device",
                access: "ALL",
                reporting: { min: 0, max: 3600, change: 0 },
            }),
            schneiderElectricExtend.addWiserDeviceInfoCluster(),
        ],
    },
    {
        zigbeeModel: ["WDE002497"],
        model: "WDE002497",
        vendor: "Schneider Electric",
        description: "Smart thermostat",
        extend: [
            m.thermostat({
                localTemperature: {
                    values: {
                        description: "The temperature measured by the selected sensor (see 'Local temperature source select', Ambient or External).",
                    },
                },
                setpoints: { values: { occupiedHeatingSetpoint: { min: 4, max: 40, step: 0.5 } } },
                setpointsLimit: {
                    maxHeatSetpointLimit: { min: 4, max: 40, step: 0.5 },
                    minHeatSetpointLimit: { min: 4, max: 40, step: 0.5 },
                },
                runningState: {
                    values: ["idle", "heat"],
                    toZigbee: { skip: true },
                    configure: { skip: true },
                },
                systemMode: { values: ["off", "heat"] },
                piHeatingDemand: { values: true },
                ctrlSeqeOfOper: { values: ["cooling_only", "heating_only"] },
            }),
            schneiderElectricExtend.runningStateFromPower(),
            m.electricityMeter({
                cluster: "metering",
                voltage: false,
                current: false,
                configureReporting: true,
                energy: { divisor: 1000, multiplier: 1 },
            }),
            schneiderElectricExtend.customMeteringCluster(),
            schneiderElectricExtend.fixedLoadDemand(),
            schneiderElectricExtend.addHvacUserInterfaceCfgCustomAttributes(),
            schneiderElectricExtend.displayBrightnessActive(),
            schneiderElectricExtend.displayBrightnessInactive(),
            schneiderElectricExtend.displayActiveTimeout(),
            schneiderElectricExtend.customThermostatCluster(),
            schneiderElectricExtend.localTemperatureSourceSelect(),
            schneiderElectricExtend.controlType(),
            schneiderElectricExtend.controlStatus(),
            schneiderElectricExtend.thermostatApplication(),
            schneiderElectricExtend.heatingEmitter(),
            schneiderElectricExtend.addHeatingCoolingOutputClusterServer(),
            schneiderElectricExtend.heatingOutputMode({
                description: "On devices with alternate heating output types, this selects which should be used to control the heating unit. This attribute is (mistakenly) also called pilot_mode on some devices.",
                lookup: { Disabled: 0, Relay: 1 },
            }),
            schneiderElectricExtend.customTemperatureMeasurementCluster(),
            m.deviceEndpoints({
                endpoints: { floor: 3 },
            }),
            schneiderElectricExtend.sensorCorrection({
                endpointNames: ["floor"],
            }),
            schneiderElectricExtend.temperatureSensorType({
                endpointName: "floor",
            }),
            m.enumLookup({
                name: "temperature_display_mode",
                lookup: { celsius: 0 },
                cluster: "hvacUserInterfaceCfg",
                attribute: "tempDisplayMode",
                description: "The unit of the temperature displayed on the device screen. Celsius is the only supported unit.",
                entityCategory: "config",
            }),
            m.binary({
                name: "child_lock",
                valueOn: ["LOCK", 1],
                valueOff: ["UNLOCK", 0],
                cluster: "hvacUserInterfaceCfg",
                attribute: "keypadLockout",
                description: "Enables/disables physical input on the device",
                access: "ALL",
                reporting: { min: 0, max: 3600, change: 0 },
            }),
            schneiderElectricExtend.addWiserDeviceInfoCluster(),
        ],
    },
    {
        zigbeeModel: ["WDE011680"],
        model: "WDE011680",
        vendor: "Schneider Electric",
        description: "Smart thermostat",
        fromZigbee: [fzLocal.thermostat_running_state_from_piheat, fz.metering, fzLocal.wiser_device_info, fz.hvac_user_interface, fz.temperature],
        toZigbee: [
            tz.thermostat_occupied_heating_setpoint,
            tz.thermostat_system_mode,
            tz.thermostat_running_state,
            tz.thermostat_local_temperature,
            tz.thermostat_control_sequence_of_operation,
            tzLocal.schneider_thermostat_keypad_lockout,
            tz.thermostat_temperature_display_mode,
        ],
        extend: [
            schneiderElectricExtend.addWiserDeviceInfoCluster(),
            schneiderElectricExtend.addHeatingCoolingOutputClusterServer(),
            schneiderElectricExtend.pilotMode(),
        ],
        exposes: [
            e.binary("keypad_lockout", ea.STATE_SET, "lock1", "unlock").withDescription("Enables/disables physical input on the device"),
            e
                .enum("temperature_display_mode", ea.ALL, ["celsius", "fahrenheit"])
                .withDescription("The temperature format displayed on the thermostat screen"),
            e
                .climate()
                .withSetpoint("occupied_heating_setpoint", 4, 30, 0.5)
                .withLocalTemperature()
                .withSystemMode(["off", "heat"])
                .withRunningState(["idle", "heat"])
                .withPiHeatingDemand(),
            e.temperature(),
        ],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint1 = device.getEndpoint(1);
            const endpoint2 = device.getEndpoint(2);
            await reporting.bind(endpoint1, coordinatorEndpoint, ["hvacThermostat"]);
            await reporting.thermostatPIHeatingDemand(endpoint1);
            await reporting.thermostatOccupiedHeatingSetpoint(endpoint1);
            await reporting.bind(endpoint2, coordinatorEndpoint, ["msTemperatureMeasurement"]);
            await reporting.temperature(endpoint2);
            await endpoint1.read("hvacUserInterfaceCfg", ["keypadLockout", "tempDisplayMode"]);
        },
    },
    {
        zigbeeModel: ["2GANG/ESWITCH/2"],
        model: "MEG5126-0300_MEG5152-0000",
        vendor: "Schneider Electric",
        description: "Merten MEG5152 switch insert (2fold) with Merten System M push button (2fold)",
        extend: [
            m.deviceEndpoints({ endpoints: { left: 1, right: 2, left_sw: 21, right_sw: 22 } }),
            m.identify(),
            m.onOff({ powerOnBehavior: false, endpointNames: ["left", "right"] }),
            m.commandsOnOff({ endpointNames: ["left_sw", "right_sw"] }),
        ],
    },
    {
        zigbeeModel: ["1GANG/SWITCH/2"],
        model: "MEG5116-0300_MEG5162-0000",
        vendor: "Schneider Electric",
        description: "Merten MEG5162 switch insert (2fold) with Merten System M push button (1fold)",
        extend: [
            m.deviceEndpoints({ endpoints: { left: 1, right: 2, left_sw: 21 } }),
            m.identify(),
            m.onOff({ powerOnBehavior: false, endpointNames: ["left", "right"] }),
            m.commandsOnOff({ endpointNames: ["left_sw"] }),
        ],
    },
    {
        zigbeeModel: ["1GANG/ESWITCH/1"],
        model: "MEG5116-0300_MEG5151-0000",
        vendor: "Schneider Electric",
        description: "Merten MEG5151 switch insert with Merten System M push button (1fold)",
        extend: [
            m.deviceEndpoints({ endpoints: { switch: 1, switch_sw: 21 } }),
            m.identify(),
            m.onOff({ powerOnBehavior: false }),
            m.commandsOnOff({ endpointNames: ["switch_sw"] }),
        ],
    },
    {
        zigbeeModel: ["MEG5779"],
        model: "MEG5779",
        vendor: "Schneider Electric",
        description: "Merten Connected Room Temperature Controller",
        fromZigbee: [
            {
                cluster: "hvacThermostat",
                type: ["attributeReport", "readResponse"],
                convert: (model, msg, publish, options, meta) => {
                    if (msg.data.pIHeatingDemand !== undefined) {
                        return { running_state: msg.data.pIHeatingDemand > 0 ? "heat" : "idle" };
                    }
                    if (msg.data.pICoolingDemand !== undefined) {
                        return { running_state: msg.data.pICoolingDemand > 0 ? "cool" : "idle" };
                    }
                },
            },
        ],
        extend: [
            m.thermostat({
                setpoints: {
                    values: {
                        occupiedHeatingSetpoint: { min: 4, max: 30, step: 0.5 },
                        unoccupiedHeatingSetpoint: { min: 4, max: 30, step: 0.5 },
                        occupiedCoolingSetpoint: { min: 4, max: 30, step: 0.5 },
                        unoccupiedCoolingSetpoint: { min: 4, max: 30, step: 0.5 },
                    },
                },
                setpointsLimit: {
                    maxHeatSetpointLimit: { min: 4, max: 30, step: 0.5 },
                    minHeatSetpointLimit: { min: 4, max: 30, step: 0.5 },
                    maxCoolSetpointLimit: { min: 4, max: 30, step: 0.5 },
                    minCoolSetpointLimit: { min: 4, max: 30, step: 0.5 },
                },
                systemMode: {
                    values: ["off", "heat", "cool"],
                },
                runningState: {
                    values: ["idle", "heat", "cool"],
                    configure: { reporting: false },
                },
                piHeatingDemand: {
                    values: ea.ALL,
                },
            }),
            schneiderElectricExtend.addHvacUserInterfaceCfgCustomAttributes(),
            schneiderElectricExtend.displayBrightnessActive(),
            schneiderElectricExtend.displayBrightnessInactive(),
            schneiderElectricExtend.displayActiveTimeout(),
            m.enumLookup({
                name: "temperature_display_mode",
                lookup: { celsius: 0, fahrenheit: 1 },
                cluster: "hvacUserInterfaceCfg",
                attribute: "tempDisplayMode",
                description: "The unit of the temperature displayed on the device screen.",
            }),
            m.enumLookup({
                name: "keypadLockout",
                lookup: { unlock: 0, lock1: 1 },
                cluster: "hvacUserInterfaceCfg",
                attribute: "keypadLockout",
                description: "Enables/disables physical input on the device.",
            }),
            schneiderElectricExtend.customThermostatCluster(),
            schneiderElectricExtend.thermostatApplication(),
            schneiderElectricExtend.heatingFuel(),
            schneiderElectricExtend.heatTransferMedium(),
            schneiderElectricExtend.heatingEmitter(),
        ],
    },
    {
        zigbeeModel: ["E8331DST300ZB"],
        model: "E8331DST300ZB",
        vendor: "Schneider Electric",
        description: "Wiser AvatarOn 1G dimmer switch",
        extend: [
            m.light({ effect: false, color: false, powerOnBehavior: false, configureReporting: true }),
            schneiderElectricExtend.addVisaConfigurationCluster(zigbee_herdsman_1.Zcl.DataType.UINT8),
            schneiderElectricExtend.visaConfigIndicatorLuminanceLevel(),
            schneiderElectricExtend.visaConfigIndicatorColor(),
            schneiderElectricExtend.visaIndicatorMode([0, 1, 2, 3]),
        ],
    },
    {
        zigbeeModel: ["E8332DST350ZB"],
        model: "E8332DST350ZB",
        vendor: "Schneider Electric",
        description: "Wiser AvatarOn 2G dimmer switch",
        extend: [
            m.deviceEndpoints({ endpoints: { l1: 10, l2: 11 } }),
            m.light({
                endpointNames: ["l1", "l2"],
                effect: false,
                color: false,
                powerOnBehavior: false,
                configureReporting: true,
            }),
            schneiderElectricExtend.addVisaConfigurationCluster(zigbee_herdsman_1.Zcl.DataType.ENUM8),
            schneiderElectricExtend.visaConfigIndicatorLuminanceLevel(),
            schneiderElectricExtend.visaConfigIndicatorColor(),
            schneiderElectricExtend.visaIndicatorMode([2, 0, 3, 1]),
        ],
    },
    {
        zigbeeModel: ["E8331SRY800ZB"],
        model: "E8331SRY800ZB",
        vendor: "Schneider Electric",
        description: "Wiser AvatarOn 1G onoff switch",
        extend: [
            m.deviceEndpoints({ endpoints: { l1: 10 } }),
            m.onOff({ endpointNames: ["l1"], powerOnBehavior: false }),
            schneiderElectricExtend.addVisaConfigurationCluster(zigbee_herdsman_1.Zcl.DataType.UINT8),
            schneiderElectricExtend.visaConfigIndicatorLuminanceLevel(),
            schneiderElectricExtend.visaConfigIndicatorColor(),
            schneiderElectricExtend.visaIndicatorMode([0, 1, 2, 3]),
        ],
    },
    {
        zigbeeModel: ["A3N31SR800ZB_xx_C1"],
        model: "E8331SRY800ZB_NEW",
        vendor: "Schneider Electric",
        description: "Wiser AvatarOn 1G onoff switch",
        extend: [
            m.deviceEndpoints({ endpoints: { l1: 10 } }),
            m.onOff({ endpointNames: ["l1"], powerOnBehavior: false }),
            schneiderElectricExtend.addVisaConfigurationCluster(zigbee_herdsman_1.Zcl.DataType.UINT8),
            schneiderElectricExtend.visaIndicatorMode([0, 1, 2, 3]),
        ],
    },
    {
        zigbeeModel: ["E8332SRY800ZB"],
        model: "E8332SRY800ZB",
        vendor: "Schneider Electric",
        description: "Wiser AvatarOn 2G onoff switch",
        extend: [
            m.deviceEndpoints({ endpoints: { l1: 10, l2: 11 } }),
            m.onOff({ endpointNames: ["l1", "l2"], powerOnBehavior: false }),
            schneiderElectricExtend.addVisaConfigurationCluster(zigbee_herdsman_1.Zcl.DataType.UINT8),
            schneiderElectricExtend.visaConfigIndicatorLuminanceLevel(),
            schneiderElectricExtend.visaConfigIndicatorColor(),
            schneiderElectricExtend.visaIndicatorMode([0, 1, 2, 3]),
        ],
    },
    {
        zigbeeModel: ["A3N32SR800ZB_xx_C1"],
        model: "E8332SRY800ZB_NEW",
        vendor: "Schneider Electric",
        description: "Wiser AvatarOn 2G onoff switch",
        extend: [
            m.deviceEndpoints({ endpoints: { l1: 10, l2: 11 } }),
            m.onOff({ endpointNames: ["l1", "l2"], powerOnBehavior: false }),
            schneiderElectricExtend.addVisaConfigurationCluster(zigbee_herdsman_1.Zcl.DataType.UINT8),
            schneiderElectricExtend.visaIndicatorMode([0, 1, 2, 3]),
        ],
    },
    {
        zigbeeModel: ["E8333SRY800ZB"],
        model: "E8333SRY800ZB",
        vendor: "Schneider Electric",
        description: "Wiser AvatarOn 3G onoff switch",
        extend: [
            m.deviceEndpoints({ endpoints: { l1: 10, l2: 11, l3: 12 } }),
            m.onOff({ endpointNames: ["l1", "l2", "l3"], powerOnBehavior: false }),
            schneiderElectricExtend.addVisaConfigurationCluster(zigbee_herdsman_1.Zcl.DataType.UINT8),
            schneiderElectricExtend.visaConfigIndicatorLuminanceLevel(),
            schneiderElectricExtend.visaConfigIndicatorColor(),
            schneiderElectricExtend.visaIndicatorMode([0, 1, 2, 3]),
        ],
    },
    {
        zigbeeModel: ["A3N33SR800ZB_xx_C1"],
        model: "E8333SRY800ZB_NEW",
        vendor: "Schneider Electric",
        description: "Wiser AvatarOn 3G onoff switch",
        extend: [
            m.deviceEndpoints({ endpoints: { l1: 10, l2: 11, l3: 12 } }),
            m.onOff({ endpointNames: ["l1", "l2", "l3"], powerOnBehavior: false }),
            schneiderElectricExtend.addVisaConfigurationCluster(zigbee_herdsman_1.Zcl.DataType.UINT8),
            schneiderElectricExtend.visaIndicatorMode([0, 1, 2, 3]),
        ],
    },
    {
        zigbeeModel: ["E8332SCN300ZB"],
        model: "E8332SCN300ZB",
        vendor: "Schneider Electric",
        description: "Wiser AvatarOn 2G curtain switch",
        extend: [
            m.deviceEndpoints({ endpoints: { l1: 10, l2: 11 } }),
            schneiderElectricExtend.addVisaConfigurationCluster(zigbee_herdsman_1.Zcl.DataType.UINT8),
            schneiderElectricExtend.visaConfigIndicatorLuminanceLevel(),
            schneiderElectricExtend.visaConfigIndicatorColor(),
            schneiderElectricExtend.visaIndicatorMode([0, 1, 2, 3]),
            schneiderElectricExtend.visaWiserCurtain(["l1", "l2"]),
            schneiderElectricExtend.visaConfigMotorType(1),
            schneiderElectricExtend.visaConfigMotorType(2),
            schneiderElectricExtend.visaConfigCurtainStatus(1),
            schneiderElectricExtend.visaConfigCurtainStatus(2),
        ],
    },
    {
        zigbeeModel: ["E8334RWMZB"],
        model: "E8334RWMZB",
        vendor: "Schneider Electric",
        description: "Wiser AvatarOn 4K Freelocate",
        extend: [
            schneiderElectricExtend.addVisaConfigurationCluster(zigbee_herdsman_1.Zcl.DataType.UINT8),
            schneiderElectricExtend.visaConfigIndicatorLuminanceLevel(),
            schneiderElectricExtend.visaConfigIndicatorColor(),
            schneiderElectricExtend.visaKeyEventNotification("1"),
            schneiderElectricExtend.visaKeyEventNotification("2"),
            schneiderElectricExtend.visaKeyEventNotification("3"),
            schneiderElectricExtend.visaKeyEventNotification("4"),
        ],
        exposes: [e.action(["key1", "key2", "key3", "key4"]).withDescription("Last Visa key pressed")],
    },
    {
        zigbeeModel: ["NHMOTION/DIMMER/1"],
        model: "NH3527A",
        vendor: "Schneider Electric",
        description: "Motion sensor with dimmer",
        extend: [
            m.light({
                effect: false,
                powerOnBehavior: false,
                color: false,
                configureReporting: true,
                levelConfig: { features: ["on_level", "current_level_startup"] },
            }),
            m.lightingBallast(),
            m.illuminance(),
            m.occupancy({
                pirConfig: ["otu_delay"],
            }),
            schneiderElectricExtend.addOccupancyConfigurationCluster(),
            schneiderElectricExtend.occupancyConfiguration(),
            schneiderElectricExtend.addSchneiderLightingBallastCfgCluster(),
            schneiderElectricExtend.dimmingMode(),
        ],
        whiteLabel: [
            { vendor: "ELKO", model: "EKO07250" },
            { vendor: "ELKO", model: "EKO07251" },
            { vendor: "ELKO", model: "EKO07252" },
            { vendor: "ELKO", model: "EKO07253" },
            { vendor: "ELKO", model: "EKO30199" },
            { vendor: "Exxact", model: "WDE002962" },
            { vendor: "Exxact", model: "WDE003962" },
        ],
    },
    {
        zigbeeModel: ["NHMOTION/UNIDIM/1"],
        model: "NHMOTION/UNIDIM/1",
        vendor: "Schneider Electric",
        description: "Motion sensor with dimmer",
        extend: [
            m.light({
                effect: false,
                powerOnBehavior: false,
                color: false,
                configureReporting: true,
                levelConfig: {
                    features: ["on_level", "current_level_startup"],
                },
            }),
            m.lightingBallast(),
            m.illuminance(),
            m.occupancy({
                pirConfig: ["otu_delay"],
            }),
            schneiderElectricExtend.addOccupancyConfigurationCluster(),
            schneiderElectricExtend.occupancyConfiguration(),
            schneiderElectricExtend.addSchneiderLightingBallastCfgCluster(),
            schneiderElectricExtend.dimmingMode(),
        ],
        whiteLabel: [
            { vendor: "ELKO", model: "EKO06984", description: "SmartPir with push dimmer" },
            { vendor: "ELKO", model: "EKO06985", description: "SmartPir with push dimmer" },
            { vendor: "ELKO", model: "EKO06986", description: "SmartPir with push dimmer" },
        ],
    },
    {
        zigbeeModel: ["S520619"],
        model: "S520619",
        vendor: "Schneider Electric",
        description: "Wiser Odace Smart thermostat",
        fromZigbee: [
            fzLocal.thermostat_running_state_from_piheat,
            fz.metering,
            fzLocal.wiser_device_info,
            fz.hvac_user_interface,
            fz.temperature,
            fz.occupancy,
        ],
        toZigbee: [
            tz.thermostat_occupied_heating_setpoint,
            tz.thermostat_occupied_cooling_setpoint,
            tz.thermostat_system_mode,
            tz.thermostat_local_temperature,
            tz.thermostat_control_sequence_of_operation,
            tzLocal.schneider_thermostat_keypad_lockout,
            tz.thermostat_temperature_display_mode,
            tz.thermostat_running_state,
        ],
        exposes: [
            e.binary("keypad_lockout", ea.STATE_SET, "lock1", "unlock").withDescription("Enables/disables physical input on the device"),
            e
                .enum("temperature_display_mode", ea.ALL, ["celsius", "fahrenheit"])
                .withDescription("The temperature format displayed on the thermostat screen"),
            e
                .climate()
                .withSetpoint("occupied_heating_setpoint", 4, 30, 0.5)
                .withSetpoint("occupied_cooling_setpoint", 4, 30, 0.5)
                .withLocalTemperature()
                .withSystemMode(["off", "heat", "cool"])
                .withRunningState(["idle", "heat", "cool"])
                .withPiHeatingDemand()
                .withPiCoolingDemand(),
            e.temperature(),
            e.occupancy(),
        ],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint1 = device.getEndpoint(1);
            const endpoint2 = device.getEndpoint(2);
            const endpoint4 = device.getEndpoint(4);
            await reporting.bind(endpoint1, coordinatorEndpoint, ["hvacThermostat"]);
            await reporting.thermostatPIHeatingDemand(endpoint1);
            await reporting.thermostatPICoolingDemand(endpoint1);
            await reporting.thermostatOccupiedHeatingSetpoint(endpoint1);
            await reporting.thermostatOccupiedCoolingSetpoint(endpoint1);
            await reporting.temperature(endpoint2);
            await endpoint1.read("hvacUserInterfaceCfg", ["keypadLockout", "tempDisplayMode"]);
            await reporting.bind(endpoint4, coordinatorEndpoint, ["msOccupancySensing"]);
            await utils.ignoreUnsupportedAttribute(async () => await reporting.thermostatOccupancy(endpoint4), "thermostatOccupancy");
        },
        extend: [
            schneiderElectricExtend.addWiserDeviceInfoCluster(),
            schneiderElectricExtend.addHeatingCoolingOutputClusterServer(),
            schneiderElectricExtend.pilotMode(),
            m.poll({
                key: "measurement",
                option: exposes.options.measurement_poll_interval().withDescription("Polling interval of the occupied heating/cooling setpoint"),
                defaultIntervalSeconds: 20,
                poll: async (device) => {
                    const endpoint = device.getEndpoint(1);
                    await endpoint.read("hvacThermostat", ["occupiedHeatingSetpoint", "occupiedCoolingSetpoint"]);
                },
            }),
        ],
    },
    {
        zigbeeModel: ["E8332RWMZB"],
        model: "E8332RWMZB",
        vendor: "Schneider Electric",
        description: "Wiser AvatarOn 2K Freelocate",
        extend: [
            schneiderElectricExtend.addVisaConfigurationCluster(zigbee_herdsman_1.Zcl.DataType.UINT8),
            schneiderElectricExtend.visaConfigIndicatorLuminanceLevel(),
            schneiderElectricExtend.visaConfigIndicatorColor(),
            schneiderElectricExtend.visaKeyEventNotification("1"),
            schneiderElectricExtend.visaKeyEventNotification("2"),
        ],
        exposes: [e.action(["key1", "key2"]).withDescription("Last Visa key pressed")],
    },
    {
        zigbeeModel: ["E8331SCN200ZB"],
        model: "E8331SCN200ZB",
        vendor: "Schneider Electric",
        description: "Wiser AvatarOn 1G curtain switch",
        extend: [
            m.deviceEndpoints({ endpoints: { l1: 10 } }),
            schneiderElectricExtend.addVisaConfigurationCluster(zigbee_herdsman_1.Zcl.DataType.UINT8),
            schneiderElectricExtend.visaConfigIndicatorLuminanceLevel(),
            schneiderElectricExtend.visaConfigIndicatorColor(),
            schneiderElectricExtend.visaIndicatorMode([0, 1, 2, 3]),
            schneiderElectricExtend.visaWiserCurtain(["l1"]),
            schneiderElectricExtend.visaConfigMotorType(1),
            schneiderElectricExtend.visaConfigCurtainStatus(1),
        ],
    },
    {
        fingerprint: [{ modelID: "GreenPower_254", ieeeAddr: /^0x00000000e205567e$/ }],
        model: "EKO01825",
        vendor: "ELKO",
        description: "PowerTag power sensor",
        whiteLabel: [{ vendor: "Schneider Electric", model: "A9MEM1570" }],
        fromZigbee: [fzLocal.schneider_powertag],
        toZigbee: [],
        exposes: [
            e.power(),
            e.power_apparent(),
            e.power_factor(),
            e.energy(),
            e.ac_frequency(),
            e.numeric("voltage_phase_ab", ea.STATE).withUnit("V").withDescription("Measured electrical potential value between phase L1 and L2"),
            e.numeric("voltage_phase_bc", ea.STATE).withUnit("V").withDescription("Measured electrical potential value between phase L2 and L3"),
            e.numeric("voltage_phase_ca", ea.STATE).withUnit("V").withDescription("Measured electrical potential value between phase L1 and L3"),
            e.numeric("current_phase_a", ea.STATE).withUnit("A").withDescription("Instantaneous measured electrical current on phase L1"),
            e.numeric("current_phase_b", ea.STATE).withUnit("A").withDescription("Instantaneous measured electrical current on phase L2"),
            e.numeric("current_phase_c", ea.STATE).withUnit("A").withDescription("Instantaneous measured electrical current on phase L3"),
        ],
    },
    {
        zigbeeModel: ["UFH"],
        model: "CCTFR6000",
        vendor: "Schneider Electric",
        description: "6 Channel Boiler Actuator",
        extend: [
            m.deviceEndpoints({ endpoints: { "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8 } }),
            m.onOff({ powerOnBehavior: false, endpointNames: ["1", "2", "3", "4", "5", "6", "7", "8"] }),
        ],
    },
];
//# sourceMappingURL=schneider_electric.js.map