UNPKG

zigbee-herdsman-converters

Version:

Collection of device converters to be used with zigbee-herdsman

6,242 lines 293 kB
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.definitions = void 0;
const zigbee_herdsman_1 = require("zigbee-herdsman");
const fz = __importStar(require("../converters/fromZigbee"));
const tz = __importStar(require("../converters/toZigbee"));
const exposes = __importStar(require("../lib/exposes"));
const logger_1 = require("../lib/logger");
const lumi = __importStar(require("../lib/lumi"));
const m = __importStar(require("../lib/modernExtend"));
const reporting = __importStar(require("../lib/reporting"));
const utils_1 = require("../lib/utils");
const e = exposes.presets;
const ea = exposes.access;
const { lumiAction, lumiOperationMode, lumiPowerOnBehavior, lumiZigbeeOTA, lumiSwitchType, lumiAirQuality, lumiVoc, lumiDisplayUnit, lumiLight, lumiOutageCountRestoreBindReporting, lumiElectricityMeter, lumiPower, lumiOverloadProtection, lumiLedIndicator, lumiButtonLock, lumiMotorSpeed, lumiCurtainSpeed, lumiCurtainManualOpenClose, lumiCurtainAdaptivePullingSpeed, lumiCurtainManualStop, lumiCurtainReverse, lumiCurtainStatus, lumiCurtainLastManualOperation, lumiCurtainPosition, lumiCurtainTraverseTime, lumiCurtainCalibrationStatus, lumiCurtainCalibrated, lumiCurtainIdentifyBeep, lumiOnOff, lumiLedDisabledNight, lumiFlipIndicatorLight, lumiPreventReset, lumiAqaraH2EuShutterSwitchAction, lumiClickMode, lumiSlider, lumiSetEventMode, lumiSwitchMode, lumiVibration, lumiReportInterval, lumiSensitivityAdjustment, lumiKnobRotation, lumiCommandMode, lumiBattery, lumiLockRelay, lumiMultiClick, lumiPreventLeave, lumiExternalSensor, w600ExternalTempSensor, w600Heartbeat, w600PresetTemperatureTable, w600Schedule, w600Thermostat, w600ValvePosition, w600WeeklySchedule, lumiBathroomHeaterT1, lumiReadPositionOnReport, } = lumi.modernExtend;
const NS = "zhc:lumi";
const { manufacturerCode } = lumi;
const aqaraH2EuShutterSwitchEndpoints = { top_wireless_button: 3, bottom_wireless_button: 4 };
const aqaraH2EuShutterSwitchEndpointNames = ["top_wireless_button", "bottom_wireless_button"];
const aqaraH2EuShutterSwitchMultiEndpointSkip = ["energy", "position", "state", "tilt"];
const aqaraH2EuShutterSwitchMultiClickAttribute = 0x0286;
async function configureAqaraH2EuShutterSwitch(device, coordinatorEndpoint) {
    for (const endpointName of aqaraH2EuShutterSwitchEndpointNames) {
        const endpoint = device.getEndpoint(aqaraH2EuShutterSwitchEndpoints[endpointName]);
        await reporting.bind(endpoint, coordinatorEndpoint, ["manuSpecificLumi", "genMultistateInput"]);
        // Disable reporting for presentValue (max=0xFFFF = "shall not issue reports", ZCL).
        // Button presses are firmware-generated unsolicited reports and keep working;
        // an active reporting entry caused the hourly stale action replays.
        // https://github.com/Koenkk/zigbee2mqtt/issues/32059
        await endpoint.configureReporting("genMultistateInput", reporting.payload("presentValue", 0, 65535, 1));
        // Initialize Aqara's per-button multi-click setting on startup.
        await endpoint.read("manuSpecificLumi", [aqaraH2EuShutterSwitchMultiClickAttribute], {
            manufacturerCode,
        });
    }
}
async function ensureLumiIasEnrollment(endpoint, coordinatorEndpoint) {
    const coordinatorIeeeAddress = coordinatorEndpoint.deviceIeeeAddress;
    const isEnrolled = (state) => state.zoneState === 1 && state.iasCieAddr?.toLowerCase() === coordinatorIeeeAddress.toLowerCase();
    if (isEnrolled(await endpoint.read("ssIasZone", ["zoneState", "iasCieAddr"], { sendPolicy: "immediate" }))) {
        return;
    }
    await endpoint.write("ssIasZone", { iasCieAddr: coordinatorIeeeAddress }, { sendPolicy: "immediate" });
    await endpoint.command("ssIasZone", "enrollRsp", { enrollrspcode: 0, zoneid: 23 }, { disableDefaultResponse: true, sendPolicy: "immediate" });
    await (0, utils_1.sleep)(500);
    const state = await endpoint.read("ssIasZone", ["zoneState", "iasCieAddr"], { sendPolicy: "immediate" });
    if (!isEnrolled(state)) {
        throw new Error(`IAS enrollment failed; expected zoneState=1 and iasCieAddr=${coordinatorIeeeAddress}, got ${JSON.stringify(state)}`);
    }
}
function fp310DetectionRange() {
    return {
        isModernExtend: true,
        exposes: [
            e
                .numeric("detection_range", ea.ALL)
                .withValueMin(0)
                .withValueMax(6)
                .withValueStep(0.25)
                .withUnit("m")
                .withDescription("Specifies the range that is being detected. Press the on-device button to wake the device up and refresh it's settings."),
        ],
        fromZigbee: [
            {
                cluster: "manuSpecificLumi",
                type: ["attributeReport", "readResponse"],
                convert: (model, msg, publish, options, meta) => {
                    if (msg.data["410"] && Buffer.isBuffer(msg.data["410"])) {
                        const buffer = msg.data["410"];
                        const mask = buffer[2] | (buffer[3] << 8) | (buffer[4] << 16);
                        let zones = 0;
                        let value = mask;
                        while (value > 0) {
                            zones++;
                            value >>= 1;
                        }
                        // 1 zone = 0.25m
                        const detection_range = zones * 0.25;
                        return { detection_range };
                    }
                },
            },
        ],
        toZigbee: [
            {
                key: ["detection_range"],
                convertSet: async (entity, key, value, meta) => {
                    (0, utils_1.assertNumber)(value);
                    const distance = Math.max(0, Math.min(6, value));
                    const zones = Math.round(distance / 0.25);
                    const mask = zones === 0 ? 0 : (1 << zones) - 1;
                    const buffer = Buffer.from([0x00, 0x03, mask & 0xff, (mask >> 8) & 0xff, (mask >> 16) & 0xff]);
                    await entity.write("manuSpecificLumi", { 410: { value: buffer, type: 0x41 } }, { manufacturerCode: manufacturerCode });
                    return {
                        state: { detection_range: value },
                    };
                },
                convertGet: async (entity, key, meta) => {
                    const endpoint = meta.device.getEndpoint(1);
                    await endpoint.read("manuSpecificLumi", [0x019a], { manufacturerCode: manufacturerCode });
                },
            },
        ],
    };
}
exports.definitions = [
    {
        zigbeeModel: ["lumi.bhf_light.acn001"],
        model: "ZNYB01LM",
        vendor: "Aqara",
        description: "Smart bathroom heater T1",
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiZigbeeOTA(),
            m.identify(),
            m.light({ effect: false, powerOnBehavior: false, colorTemp: { range: [153, 370] } }),
            m.ignoreClusterReport({ cluster: "hvacFanCtrl" }),
            lumiBathroomHeaterT1(),
        ],
    },
    {
        zigbeeModel: ["lumi.flood.acn001"],
        model: "SJCGQ13LM",
        vendor: "Aqara",
        description: "Water leak sensor E1",
        fromZigbee: [fz.ias_water_leak_alarm_1, lumi.fromZigbee.lumi_specific, fz.battery],
        toZigbee: [],
        exposes: [e.water_leak(), e.battery(), e.battery_low(), e.battery_voltage(), e.device_temperature(), e.power_outage_count(false)],
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            await endpoint.read("genPowerCfg", ["batteryVoltage"]);
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), m.quirkCheckinInterval("1_HOUR"), lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["lumi.airm.fhac01"],
        model: "KQJCMB11LM",
        vendor: "Aqara",
        description: "Air monitoring panel S1",
        fromZigbee: [fz.temperature, fz.humidity, lumi.fromZigbee.lumi_pm25, lumi.fromZigbee.lumi_co2],
        toZigbee: [],
        exposes: [e.temperature(), e.humidity(), e.pm25(), e.co2()],
        extend: [lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["lumi.magnet.acn001"],
        model: "MCCGQ14LM",
        vendor: "Aqara",
        description: "Door and window sensor E1",
        fromZigbee: [fz.ias_contact_alarm_1, lumi.fromZigbee.lumi_specific, fz.battery],
        toZigbee: [],
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        exposes: [e.contact(), e.battery(), e.battery_low(), e.battery_voltage()],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            await endpoint.read("genPowerCfg", ["batteryVoltage"]);
        },
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            m.quirkCheckinInterval("1_HOUR"),
            // OTA request: "fieldControl":0, "manufacturerCode":4447, "imageType":10635, no available for now
            // https://github.com/Koenkk/zigbee-OTA/pull/138
            // lumiZigbeeOTA(),
        ],
    },
    {
        zigbeeModel: ["lumi.magnet.ac01"],
        model: "MCCGQ13LM",
        vendor: "Aqara",
        description: "Door and window sensor P1",
        fromZigbee: [lumi.fromZigbee.lumi_contact, fz.ias_contact_alarm_1, lumi.fromZigbee.lumi_specific],
        toZigbee: [lumi.toZigbee.lumi_detection_distance],
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        exposes: [
            e.contact(),
            e.battery(),
            e.battery_voltage(),
            e.tamper(),
            e
                .enum("detection_distance", ea.ALL, ["10mm", "20mm", "30mm"])
                .withDescription('The sensor will be considered "off" within the set distance. Please press the device button before setting'),
        ],
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), m.quirkCheckinInterval("1_HOUR")],
    },
    {
        zigbeeModel: ["lumi.dimmer.rcbac1"],
        model: "ZNDDMK11LM",
        vendor: "Aqara",
        description: "Smart lightstrip driver",
        fromZigbee: [lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_specific, ...m.light({ colorTemp: { range: undefined }, color: true }).fromZigbee],
        toZigbee: [
            lumi.toZigbee.lumi_dimmer_mode,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            ...m.light({ colorTemp: { range: undefined }, color: true }).toZigbee,
        ],
        exposes: [
            e.power(),
            e.energy(),
            e.voltage(),
            e.device_temperature(),
            e.power_outage_memory(),
            // When in rgbw mode, only one of color and colortemp will be valid, and l2 will be invalid
            // Do not control l2 in rgbw mode
            e.light_brightness_colortemp_colorxy([153, 370]).removeFeature("color_temp_startup").withEndpoint("l1"),
            e.light_brightness_colortemp([153, 370]).removeFeature("color_temp_startup").withEndpoint("l2"),
            e.enum("dimmer_mode", ea.ALL, ["rgbw", "dual_ct"]).withDescription("Switch between rgbw mode or dual color temperature mode"),
        ],
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), m.deviceEndpoints({ endpoints: { l1: 1, l2: 2 } }), lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["lumi.light.aqcn02"],
        model: "ZNLDP12LM",
        vendor: "Aqara",
        description: "Light bulb",
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiLight({ colorTemp: true, powerOutageMemory: "light" }), lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["lumi.light.acn003"],
        model: "ZNXDD01LM",
        vendor: "Aqara",
        description: "Ceiling light L1-350",
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiLight({ colorTemp: true, powerOutageMemory: "switch", levelConfig: { features: ["on_level"] } }),
            lumiZigbeeOTA(),
        ],
    },
    {
        zigbeeModel: ["lumi.light.acn033"],
        model: "HCXDD13LM",
        vendor: "Aqara",
        description: "Nebula ceiling lamp H1",
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            m.light({ colorTemp: { range: [153, 370], startup: false }, effect: false, powerOnBehavior: false }),
            lumiPowerOnBehavior(),
            lumiZigbeeOTA(),
        ],
    },
    {
        zigbeeModel: ["lumi.light.cwac02", "lumi.light.acn014"],
        model: "ZNLDP13LM",
        vendor: "Aqara",
        description: "Light bulb T1",
        whiteLabel: [{ vendor: "Aqara", model: "LEDLBT1-L01" }],
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiZigbeeOTA(),
            lumiLight({ colorTemp: true, powerOutageMemory: "switch" }),
            m.forceDeviceType({ type: "Router" }),
            m.forcePowerSource({ powerSource: "Mains (single phase)" }),
        ],
    },
    {
        zigbeeModel: ["lumi.light.cwopcn01"],
        model: "XDD11LM",
        vendor: "Aqara",
        description: "Opple MX960",
        meta: { turnsOffAtBrightness1: true },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiLight({ colorTemp: true, powerOutageMemory: "switch" }), lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["lumi.light.cwopcn02"],
        model: "XDD12LM",
        vendor: "Aqara",
        description: "Opple MX650",
        meta: { turnsOffAtBrightness1: true },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA(), lumiLight({ colorTemp: true, powerOutageMemory: "switch" })],
    },
    {
        zigbeeModel: ["lumi.light.cwopcn03"],
        model: "XDD13LM",
        vendor: "Aqara",
        description: "Opple MX480",
        meta: { turnsOffAtBrightness1: true },
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiLight({ colorTemp: true, powerOutageMemory: "switch", colorTempRange: [175, 370] }),
            lumiZigbeeOTA(),
        ],
    },
    {
        zigbeeModel: ["lumi.light.cwjwcn01"],
        model: "JWSP001A",
        vendor: "Aqara",
        description: "Jiawen LED Driver & Dimmer",
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiLight({ colorTemp: true, powerOutageMemory: "switch" })],
    },
    {
        zigbeeModel: ["lumi.light.cwjwcn02"],
        model: "JWDL001A",
        vendor: "Aqara",
        description: "Embedded spot led light",
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiLight({ colorTemp: true, powerOutageMemory: "switch" })],
    },
    {
        zigbeeModel: ["lumi.sensor_switch"],
        model: "WXKG01LM",
        vendor: "Xiaomi",
        whiteLabel: [
            { vendor: "Xiaomi", model: "YTC4040GL" },
            { vendor: "Xiaomi", model: "YTC4006CN" },
            { vendor: "Xiaomi", model: "YTC4017CN" },
            { vendor: "Xiaomi", model: "ZHTZ02LM" },
        ],
        description: "Mi wireless switch",
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_action_WXKG01LM],
        exposes: [
            e.battery(),
            e.action(["single", "double", "triple", "quadruple", "hold", "release", "many"]),
            e.battery_voltage(),
            e.power_outage_count(false),
        ],
        toZigbee: [],
        extend: [m.quirkCheckinInterval("1_HOUR")],
    },
    {
        zigbeeModel: ["lumi.sensor_switch.aq2", "lumi.remote.b1acn01"],
        model: "WXKG11LM",
        vendor: "Aqara",
        description: "Wireless mini switch",
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        exposes: [
            e.battery(),
            e.battery_voltage(),
            e.action(["single", "double", "triple", "quadruple", "hold", "release"]),
            e.device_temperature(),
            e.power_outage_count(),
        ],
        fromZigbee: [lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_action, lumi.fromZigbee.lumi_basic],
        toZigbee: [],
        extend: [m.quirkCheckinInterval("1_HOUR")],
    },
    {
        zigbeeModel: ["lumi.sensor_switch.aq3", "lumi.sensor_swit"],
        model: "WXKG12LM",
        vendor: "Aqara",
        description: "Wireless mini switch (with gyroscope)",
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        exposes: [e.battery(), e.action(["single", "double", "hold", "release", "shake"]), e.battery_voltage()],
        fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_action_multistate],
        toZigbee: [],
        extend: [m.quirkCheckinInterval("1_HOUR")],
    },
    {
        zigbeeModel: ["lumi.sensor_86sw1"],
        model: "WXKG03LM_rev1",
        vendor: "Aqara",
        description: "Wireless remote switch (single rocker), 2016 model",
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        exposes: [e.battery(), e.action(["single"]), e.battery_voltage()],
        fromZigbee: [lumi.fromZigbee.lumi_action, lumi.fromZigbee.lumi_basic],
        toZigbee: [],
        extend: [m.quirkCheckinInterval("1_HOUR"), lumiPreventReset()],
    },
    {
        zigbeeModel: ["lumi.remote.b186acn01"],
        model: "WXKG03LM_rev2",
        vendor: "Aqara",
        description: "Wireless remote switch (single rocker), 2018 model",
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        exposes: [e.battery(), e.action(["single", "double", "hold"]), e.battery_voltage()],
        fromZigbee: [lumi.fromZigbee.lumi_action, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_basic],
        toZigbee: [],
        extend: [m.quirkCheckinInterval("1_HOUR"), lumiPreventReset()],
    },
    {
        zigbeeModel: ["lumi.remote.b186acn02"],
        model: "WXKG06LM",
        vendor: "Aqara",
        description: "Wireless remote switch D1 (single rocker)",
        fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_action, lumi.fromZigbee.lumi_action_multistate],
        toZigbee: [],
        exposes: [e.battery(), e.action(["single", "double", "hold"]), e.battery_voltage()],
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        extend: [m.quirkCheckinInterval("1_HOUR"), lumiPreventReset()],
        configure: async (device, coordinatorEndpoint) => {
            try {
                const endpoint = device.endpoints[1];
                await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff", "genPowerCfg"]);
            }
            catch {
                // fails for some but device works as expected: https://github.com/Koenkk/zigbee2mqtt/issues/9136
            }
        },
    },
    {
        zigbeeModel: ["lumi.light.acn132"],
        model: "LGYCDD01LM",
        vendor: "Aqara",
        whiteLabel: [{ vendor: "Aqara", model: "RLS-K01D" }],
        description: "LED Strip T1",
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            await endpoint.read("manuSpecificLumi", [0x0515], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x0516], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x0517], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x051b], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x051c], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x051d], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x051e], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x051f], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x0520], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x0523], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x0527], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x0530], { manufacturerCode: manufacturerCode });
            await endpoint.read("genLevelCtrl", [0x0012], {});
            await endpoint.read("genLevelCtrl", [0x0013], {});
        },
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiLight({
                colorTemp: true,
                color: { modes: ["xy"] },
                colorTempRange: [153, 370],
            }),
            m.forcePowerSource({ powerSource: "Mains (single phase)" }),
            m.identify(),
            lumiPowerOnBehavior({ lookup: { on: 0, previous: 1, off: 2 } }),
            lumiZigbeeOTA(),
            lumi.lumiModernExtend.lumiDimmingRangeMin(),
            lumi.lumiModernExtend.lumiDimmingRangeMax(),
            lumi.lumiModernExtend.lumiOnOffDuration(),
            lumi.lumiModernExtend.lumiOffOnDuration(),
            m.numeric({
                name: "length",
                valueMin: 1,
                valueMax: 10,
                valueStep: 0.2,
                scale: 5,
                unit: "m",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x051b, type: 0x20 },
                description: "LED strip length (5 x 20cm segments per meter)",
                entityCategory: "config",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.binary({
                name: "audio",
                valueOn: ["ON", 1],
                valueOff: ["OFF", 0],
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x051c, type: 0x20 },
                description: "Audio sync mode",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.enumLookup({
                name: "audio_sensitivity",
                lookup: { low: 0, high: 2 },
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x051e, type: 0x20 },
                description: "Audio sync sensitivity",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.enumLookup({
                name: "audio_effect",
                lookup: { random: 0, blink: 1, rainbow: 2, wave: 3 },
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x051d, type: 0x23 },
                description: "Audio effect",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            lumi.lumiModernExtend.lumiRGBEffect({ breathing: 0, rainbow1: 1, chasing: 2, flash: 3, hopping: 4, rainbow2: 5, flicker: 6, dash: 7 }),
            lumi.lumiModernExtend.lumiRGBEffectSpeed(),
            lumi.lumiModernExtend.lumiRGBEffectSegments(),
            lumi.lumiModernExtend.lumiRGBEffectColors(),
            lumi.lumiModernExtend.lumiSegmentColors(),
        ],
    },
    {
        zigbeeModel: ["lumi.sensor_86sw2", "lumi.sensor_86sw2.es1"],
        model: "WXKG02LM_rev1",
        vendor: "Aqara",
        description: "Wireless remote switch (double rocker), 2016 model",
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        exposes: [e.battery(), e.action(["single_left", "single_right", "single_both"]), e.battery_voltage(), e.power_outage_count(false)],
        fromZigbee: [lumi.fromZigbee.lumi_action, lumi.fromZigbee.lumi_basic],
        toZigbee: [],
        extend: [m.quirkCheckinInterval("1_HOUR"), lumiPreventReset()],
    },
    {
        zigbeeModel: ["lumi.remote.b286acn01"],
        model: "WXKG02LM_rev2",
        vendor: "Aqara",
        description: "Wireless remote switch (double rocker), 2018 model",
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        exposes: [
            e.battery(),
            e.action([
                "single_left",
                "single_right",
                "single_both",
                "double_left",
                "double_right",
                "double_both",
                "hold_left",
                "hold_right",
                "hold_both",
            ]),
            e.battery_voltage(),
        ],
        fromZigbee: [lumi.fromZigbee.lumi_action, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_basic],
        toZigbee: [],
        extend: [m.quirkCheckinInterval("1_HOUR"), lumiPreventReset()],
    },
    {
        zigbeeModel: ["lumi.switch.b1laus01"],
        model: "WS-USC01",
        vendor: "Aqara",
        description: "Smart wall switch (no neutral, single rocker), US",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
        toZigbee: [
            tz.on_off,
            lumi.toZigbee.lumi_switch_operation_mode_opple,
            lumi.toZigbee.lumi_flip_indicator_light,
            lumi.toZigbee.lumi_switch_mode_switch,
            lumi.toZigbee.lumi_switch_power_outage_memory,
        ],
        exposes: [
            e.switch(),
            e.action(["single", "double"]),
            e.flip_indicator_light(),
            e.power_outage_memory(),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode"),
            e
                .enum("mode_switch", ea.ALL, ["anti_flicker_mode", "quick_mode"])
                .withDescription("Anti flicker mode can be used to solve blinking issues of some lights. Quick mode makes the device respond faster."),
            e.power_outage_count(),
            e.device_temperature().withAccess(ea.STATE),
        ],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint1 = device.getEndpoint(1);
            // set "event" mode
            await endpoint1.write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
        },
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiZigbeeOTA(),
            lumiPreventReset(),
            m.forcePowerSource({ powerSource: "Mains (single phase)" }),
        ],
    },
    {
        zigbeeModel: ["lumi.switch.b2laus01"],
        model: "WS-USC02",
        vendor: "Aqara",
        description: "Smart wall switch (no neutral, double rocker), US",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
        toZigbee: [
            tz.on_off,
            lumi.toZigbee.lumi_switch_operation_mode_opple,
            lumi.toZigbee.lumi_flip_indicator_light,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            lumi.toZigbee.lumi_switch_mode_switch,
        ],
        exposes: [
            e.switch().withEndpoint("top"),
            e.switch().withEndpoint("bottom"),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for top button").withEndpoint("top"),
            e
                .enum("operation_mode", ea.ALL, ["control_relay", "decoupled"])
                .withDescription("Decoupled mode for bottom button")
                .withEndpoint("bottom"),
            e
                .enum("mode_switch", ea.ALL, ["anti_flicker_mode", "quick_mode"])
                .withDescription("Anti flicker mode can be used to solve blinking issues of some lights. Quick mode makes the device respond faster."),
            e.power_outage_count(),
            e.device_temperature().withAccess(ea.STATE),
            e.flip_indicator_light(),
            e.power_outage_memory(),
            e.action(["single_top", "single_bottom", "single_both", "double_top", "double_bottom", "double_both"]),
        ],
        meta: { multiEndpoint: true },
        endpoint: (device) => {
            return { top: 1, bottom: 2 };
        },
        configure: async (device, coordinatorEndpoint) => {
            await device
                .getEndpoint(1)
                .write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA(), lumiPreventReset()],
    },
    {
        zigbeeModel: ["lumi.switch.b1naus01"],
        model: "WS-USC03",
        vendor: "Aqara",
        description: "Smart wall switch (with neutral, single rocker), US",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
        toZigbee: [
            tz.on_off,
            lumi.toZigbee.lumi_power,
            lumi.toZigbee.lumi_switch_operation_mode_opple,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            lumi.toZigbee.lumi_flip_indicator_light,
        ],
        exposes: [
            e.switch(),
            e.action(["single", "double"]),
            e.flip_indicator_light(),
            e.power_outage_count(),
            e.device_temperature().withAccess(ea.STATE),
            e.power().withAccess(ea.STATE_GET),
            e.energy(),
            e.voltage(),
            e.power_outage_memory(),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode"),
        ],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint1 = device.getEndpoint(1);
            // set "event" mode
            await endpoint1.write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA(), lumiPreventReset()],
    },
    {
        zigbeeModel: ["lumi.switch.b2naus01"],
        model: "WS-USC04",
        vendor: "Aqara",
        description: "Smart wall switch (with neutral, double rocker), US",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
        toZigbee: [
            tz.on_off,
            lumi.toZigbee.lumi_power,
            lumi.toZigbee.lumi_switch_operation_mode_opple,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            lumi.toZigbee.lumi_flip_indicator_light,
        ],
        exposes: [
            e.switch().withEndpoint("top"),
            e.switch().withEndpoint("bottom"),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for top button").withEndpoint("top"),
            e
                .enum("operation_mode", ea.ALL, ["control_relay", "decoupled"])
                .withDescription("Decoupled mode for bottom button")
                .withEndpoint("bottom"),
            e.power_outage_count(),
            e.device_temperature().withAccess(ea.STATE),
            e.flip_indicator_light(),
            e.power().withAccess(ea.STATE_GET),
            e.energy(),
            e.voltage(),
            e.power_outage_memory(),
            e.action(["single_top", "single_bottom", "single_both", "double_top", "double_bottom", "double_both"]),
        ],
        meta: { multiEndpoint: true, multiEndpointSkip: ["power", "energy"] },
        endpoint: (device) => {
            return { top: 1, bottom: 2 };
        },
        configure: async (device, coordinatorEndpoint) => {
            await device
                .getEndpoint(1)
                .write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA(), lumiPreventReset()],
    },
    {
        zigbeeModel: ["lumi.switch.l1acn1"],
        model: "QBKG27LM",
        vendor: "Aqara",
        description: "Smart wall switch H1 (no neutral, single rocker)",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_specific, lumi.fromZigbee.lumi_action_multistate],
        toZigbee: [
            tz.on_off,
            lumi.toZigbee.lumi_switch_operation_mode_opple,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            lumi.toZigbee.lumi_led_disabled_night,
            lumi.toZigbee.lumi_flip_indicator_light,
            lumi.toZigbee.lumi_switch_mode_switch,
        ],
        exposes: [
            e.switch(),
            e.device_temperature(),
            e.power_outage_memory(),
            e.led_disabled_night(),
            e.flip_indicator_light(),
            e.action(["single", "double"]),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode"),
            e.power_outage_count(),
            e
                .enum("mode_switch", ea.ALL, ["anti_flicker_mode", "quick_mode"])
                .withDescription("Anti flicker mode can be used to solve blinking issues of some lights. Quick mode makes the device respond faster."),
        ],
        configure: async (device, coordinatorEndpoint) => {
            await device
                .getEndpoint(1)
                .write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA(), lumiPreventReset()],
    },
    {
        zigbeeModel: ["lumi.switch.l2acn1"],
        model: "QBKG28LM",
        vendor: "Aqara",
        description: "Smart wall switch H1 (no neutral, double rocker)",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
        toZigbee: [
            tz.on_off,
            lumi.toZigbee.lumi_switch_operation_mode_opple,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            lumi.toZigbee.lumi_flip_indicator_light,
            lumi.toZigbee.lumi_led_disabled_night,
            lumi.toZigbee.lumi_switch_mode_switch,
        ],
        meta: { multiEndpoint: true },
        endpoint: (device) => {
            return { left: 1, right: 2 };
        },
        exposes: [
            e.switch().withEndpoint("left"),
            e.switch().withEndpoint("right"),
            e.device_temperature(),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for left button").withEndpoint("left"),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for right button").withEndpoint("right"),
            e.action(["single_left", "double_left", "single_right", "double_right", "single_both", "double_both"]),
            e.power_outage_memory(),
            e.flip_indicator_light(),
            e.led_disabled_night(),
            e
                .enum("mode_switch", ea.ALL, ["anti_flicker_mode", "quick_mode"])
                .withDescription("Anti flicker mode can be used to solve blinking issues of some lights. Quick mode makes the device respond faster."),
        ],
        configure: async (device, coordinatorEndpoint) => {
            await device
                .getEndpoint(1)
                .write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA(), lumiPreventReset()],
    },
    {
        zigbeeModel: ["lumi.switch.l3acn1"],
        model: "QBKG29LM",
        vendor: "Aqara",
        description: "Smart wall switch H1 (no neutral, triple rocker)",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
        toZigbee: [
            tz.on_off,
            lumi.toZigbee.lumi_switch_operation_mode_opple,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            lumi.toZigbee.lumi_flip_indicator_light,
            lumi.toZigbee.lumi_led_disabled_night,
            lumi.toZigbee.lumi_switch_mode_switch,
        ],
        meta: { multiEndpoint: true },
        endpoint: (device) => ({ left: 1, center: 2, right: 3 }),
        exposes: [
            e.switch().withEndpoint("left"),
            e.switch().withEndpoint("center"),
            e.switch().withEndpoint("right"),
            e.power_outage_memory(),
            e.flip_indicator_light(),
            e.led_disabled_night(),
            e.power_outage_count(),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for left button").withEndpoint("left"),
            e
                .enum("operation_mode", ea.ALL, ["control_relay", "decoupled"])
                .withDescription("Decoupled mode for center button")
                .withEndpoint("center"),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for right button").withEndpoint("right"),
            e
                .enum("mode_switch", ea.ALL, ["anti_flicker_mode", "quick_mode"])
                .withDescription("Anti flicker mode can be used to solve blinking issues of some lights. Quick mode makes the device respond faster."),
            e.device_temperature().withAccess(ea.STATE),
            e.action([
                "single_left",
                "double_left",
                "single_center",
                "double_center",
                "single_right",
                "double_right",
                "single_left_center",
                "double_left_center",
                "single_left_right",
                "double_left_right",
                "single_center_right",
                "double_center_right",
                "single_all",
                "double_all",
            ]),
        ],
        configure: async (device, coordinatorEndpoint) => {
            await device
                .getEndpoint(1)
                .write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiPreventReset()],
    },
    {
        zigbeeModel: ["lumi.switch.n1acn1"],
        model: "QBKG30LM",
        vendor: "Aqara",
        description: "Smart wall switch H1 Pro (with neutral, single rocker)",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_specific, lumi.fromZigbee.lumi_action_multistate],
        toZigbee: [
            tz.on_off,
            lumi.toZigbee.lumi_switch_operation_mode_opple,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            lumi.toZigbee.lumi_led_disabled_night,
            lumi.toZigbee.lumi_flip_indicator_light,
        ],
        exposes: [
            e.switch(),
            e.power(),
            e.energy(),
            e.voltage(),
            e.device_temperature(),
            e.power_outage_memory(),
            e.led_disabled_night(),
            e.flip_indicator_light(),
            e.action(["single", "double"]),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode"),
            e.power_outage_count(),
        ],
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA(), lumiPreventReset()],
    },
    {
        zigbeeModel: ["lumi.switch.n2acn1"],
        model: "QBKG31LM",
        vendor: "Aqara",
        description: "Smart wall switch H1 Pro (with neutral, double rocker)",
        meta: { multiEndpoint: true, multiEndpointSkip: ["power", "energy"] },
        endpoint: (device) => {
            return { left: 1, right: 2 };
        },
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_specific, lumi.fromZigbee.lumi_action_multistate],
        toZigbee: [
            tz.on_off,
            lumi.toZigbee.lumi_switch_operation_mode_opple,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            lumi.toZigbee.lumi_led_disabled_night,
            lumi.toZigbee.lumi_flip_indicator_light,
        ],
        exposes: [
            e.switch().withEndpoint("left"),
            e.switch().withEndpoint("right"),
            e.power(),
            e.energy(),
            e.voltage(),
            e.device_temperature(),
            e.power_outage_memory(),
            e.led_disabled_night(),
            e.flip_indicator_light(),
            e.action(["single_left", "single_right", "single_both", "double_left", "double_right", "double_both"]),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for left button").withEndpoint("left"),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for right button").withEndpoint("right"),
            e.power_outage_count(),
        ],
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA(), lumiPreventReset()],
    },
    {
        zigbeeModel: ["lumi.switch.n3acn1"],
        model: "QBKG32LM",
        vendor: "Aqara",
        description: "Smart wall switch H1 Pro (with neutral, triple rocker)",
        meta: { multiEndpoint: true },
        endpoint: (device) => {
            return { left: 1, center: 2, right: 3 };
        },
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_specific, lumi.fromZigbee.lumi_action_multistate],
        toZigbee: [
            tz.on_off,
            lumi.toZigbee.lumi_switch_operation_mode_opple,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            lumi.toZigbee.lumi_led_disabled_night,
            lumi.toZigbee.lumi_flip_indicator_light,
        ],
        exposes: [
            e.switch().withEndpoint("left"),
            e.switch().withEndpoint("right"),
            e.switch().withEndpoint("center"),
            e.power(),
            e.energy(),
            e.voltage(),
            e.device_temperature(),
            e.power_outage_memory(),
            e.led_disabled_night(),
            e.flip_indicator_light(),
            e.action([
                "single_left",
                "double_left",
                "single_center",
                "double_center",
                "single_right",
                "double_right",
                "single_left_center",
                "double_left_center",
                "single_left_right",
                "double_left_right",
                "single_center_right",
                "double_center_right",
                "single_all",
                "double_all",
            ]),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for left button").withEndpoint("left"),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for right button").withEndpoint("right"),
            e
                .enum("operation_mode", ea.ALL, ["control_relay", "decoupled"])
                .withDescription("Decoupled mode for center button")
                .withEndpoint("center"),
            e.power_outage_count(),
        ],
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA(), lumiPreventReset()],
    },
    {
        zigbeeModel: ["lumi.switch.l1aeu1"],
        model: "WS-EUK01",
        vendor: "Aqara",
        description: "Smart wall switch H1 EU (no neutral, single rocker)",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
        toZigbee: [
            tz.on_off,
            lumi.toZigbee.lumi_switch_operation_mode_opple,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            lumi.toZigbee.lumi_flip_indicator_light,
            lumi.toZigbee.lumi_led_disabled_night,
            lumi.toZigbee.lumi_switch_mode_switch,
        ],
        exposes: [
            e.switch(),
            e.action(["single", "double"]),
            e.power_outage_memory(),
            e.flip_indicator_light(),
            e.led_disabled_night(),
            e.power_outage_count(),
            e.device_temperature().withAccess(ea.STATE),
            e.operation_mode_select(["control_relay", "decoupled"]).withDescription("Switches between direct relay control and action sending only"),
            e
                .mode_switch_select(["anti_flicker_mode", "quick_mode"])
                .withDescription("Features. Anti flicker mode can be used to solve blinking issues of some lights." +
                "Quick mode makes the device respond faster."),
        ],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint1 = device.getEndpoint(1);
            // set "event" mode
            await endpoint1.write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiPreventReset()],
    },
    {
        zigbeeModel: ["lumi.switch.l2aeu1"],
        model: "WS-EUK02",
        vendor: "Aqara",
        description: "Smart wall switch H1 EU (no neutral, double rocker)",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
        toZigbee: [
            tz.on_off,
            lumi.toZigbee.lumi_switch_operation_mode_opple,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            lumi.toZigbee.lumi_flip_indicator_light,
            lumi.toZigbee.lumi_led_disabled_night,
            lumi.toZigbee.lumi_switch_mode_switch,
        ],
        meta: { multiEndpoint: true },
        endpoint: (_device) => {
            return { left: 1, right: 2 };
        },
        exposes: [
            e.switch().withEndpoint("left"),
            e.switch().withEndpoint("right"),
            e.power_outage_memory(),
            e.flip_indicator_light(),
            e.led_disabled_night(),
            e.power_outage_count(),
            e.device_temperature().withAccess(ea.STATE),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for left button").withEndpoint("left"),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for right button").withEndpoint("right"),
            e
                .enum("mode_switch", ea.ALL, ["anti_flicker_mode", "quick_mode"])
                .withDescription("Anti flicker mode can be used to solve blinking issues of some lights. Quick mode makes the device respond faster."),
            e.action(["single_left", "double_left", "single_right", "double_right", "single_both", "double_both"]),
        ],
        configure: async (device, coordinatorEndpoint) => {
            await device
                .getEndpoint(1)
                .write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiPreventReset()],
    },
    {
        zigbeeModel: ["lumi.switch.n1aeu1"],
        model: "WS-EUK03",
        vendor: "Aqara",
        description: "Smart wall switch H1 EU (with neutral, single rocker)",
        fromZigbee: [fz.on_off, fz.electrical_measurement, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
        toZigbee: [
            tz.on_off,
            tz.electrical_measurement_power,
            lumi.toZigbee.lumi_switch_operation_mode_opple,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            lumi.toZigbee.lumi_flip_indicator_light,
            lumi.toZigbee.lumi_led_disabled_night,
        ],
        exposes: [
            e.switch(),
            e.action(["single", "double"]),
            e.power().withAccess(ea.STATE_GET),
            e.energy(),
            e.flip_indicator_light(),
            e.power_outage_memory(),
            e.device_temperature().withAccess(ea.STATE),
            e.led_disabled_night(),
            e.power_outage_count(),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode"),
        ],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint1 = device.getEndpoint(1);
            // set "event" mode
            await endpoint1.write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA(), lumiPreventReset()],
    },
    {
        zigbeeModel: ["lumi.switch.n2aeu1"],
        model: "WS-EUK04",
        vendor: "Aqara",
        description: "Smart wall switch H1 EU (with neutral, double rocker)",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
        toZigbee: [
            tz.on_off,
            lumi.toZigbee.lumi_power,
            lumi.toZigbee.lumi_switch_operation_mode_opple,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            lumi.toZigbee.lumi_flip_indicator_light,
            lumi.toZigbee.lumi_led_disabled_night,
        ],
        meta: { multiEndpoint: true, multiEndpointSkip: ["power", "energy"] },
        endpoint: (device) => {
            return { left: 1, right: 2 };
        },
        exposes: [
            e.switch().withEndpoint("left"),
            e.switch().withEndpoint("right"),
            e.power().withAccess(ea.STATE_GET),
            e.energy(),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for left button").withEndpoint("left"),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for right button").withEndpoint("right"),
            e.action(["single_left", "double_left", "single_right", "double_right", "single_both", "double_both"]),
            e.device_temperature().withAccess(ea.STATE),
            e.power_outage_memory(),
            e.flip_indicator_light(),
            e.led_disabled_night(),
            e.power_outage_count(),
        ],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint1 = device.getEndpoint(1);
            // set "event" mode
            await endpoint1.write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA(), lumiPreventReset()],
    },
    {
        zigbeeModel: ["lumi.ctrl_neutral1"],
        model: "QBKG04LM",
        vendor: "Aqara",
        description: "Smart wall switch (no neutral, single rocker)",
        fromZigbee: [lumi.fromZigbee.lumi_on_off, lumi.fromZigbee.lumi_action, lumi.fromZigbee.lumi_operation_mode_basic],
        exposes: [
            e.switch(),
            e.action(["release", "hold", "double", "single", "hold_release"]),
            e.enum("operation_mode", ea.STATE_SET, ["control_relay", "decoupled"]).withDescription("Decoupled mode"),
        ],
        toZigbee: [tz.on_off, { ...lumi.toZigbee.lumi_switch_operation_mode_basic, convertGet: null }],
        endpoint: (device) => {
            return { system: 1, default: 2 };
        },
        extend: [lumiZigbeeOTA(), lumiPreventReset(), m.forceDeviceType({ type: "EndDevice" })],
    },
    {
        zigbeeModel: ["lumi.ctrl_ln1.aq1", "lumi.ctrl_ln1"],
        model: "QBKG11LM",
        vendor: "Aqara",
        description: "Smart wall switch (with neutral, single rocker)",
        fromZigbee: [
            lumi.fromZigbee.lumi_action,
            lumi.fromZigbee.lumi_action_multistate,
            lumi.fromZigbee.lumi_on_off,
            lumi.fromZigbee.lumi_basic,
            lumi.fromZigbee.lumi_operation_mode_basic,
            fz.ignore_multistate_report,
            lumi.fromZigbee.lumi_power,
        ],
        exposes: [
            e.switch(),
            e.power().withAccess(ea.STATE_GET),
            e.device_temperature(),
            e.energy(),
            e.action(["single", "double", "release", "hold"]),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode"),
        ],
        toZigbee: [tz.on_off, lumi.toZigbee.lumi_switch_operation_mode_basic, lumi.toZigbee.lumi_power],
        endpoint: (device) => {
            return { system: 1 };
        },
        extend: [lumiZigbeeOTA(), lumiPreventReset(), m.forcePowerSource({ powerSource: "Mains (single phase)" })],
    },
    {
        zigbeeModel: ["lumi.ctrl_neutral2"],
        model: "QBKG03LM",
        vendor: "Aqara",
        description: "Smart wall switch (no neutral, double rocker)",
        fromZigbee: [lumi.fromZigbee.lumi_action, lumi.fromZigbee.lumi_on_off, lumi.fromZigbee.lumi_operation_mode_basic, lumi.fromZigbee.lumi_basic],
        exposes: [
            e.switch().withEndpoint("left"),
            e.switch().withEndpoint("right"),
            e.device_temperature(),
            e.action([
                "release_left",
                "release_right",
                "release_both",
                "double_left",
                "double_right",
                "single_left",
                "single_right",
                "hold_release_left",
                "hold_release_left",
            ]),
            e
                .enum("operation_mode", ea.STATE_SET, ["control_left_relay", "control_right_relay", "decoupled"])
                .withDescription("Operation mode for left button")
                .withEndpoint("left")
                .withCategory("config"),
            e
                .enum("operation_mode", ea.STATE_SET, ["control_left_relay", "control_right_relay", "decoupled"])
                .withDescription("Operation mode for right button")
                .withEndpoint("right")
                .withCategory("config"),
        ],
        toZigbee: [tz.on_off, { ...lumi.toZigbee.lumi_switch_operation_mode_basic, convertGet: null }, lumi.toZigbee.lumi_power],
        meta: { multiEndpoint: true },
        endpoint: (device) => {
            return { system: 1, left: 2, right: 3 };
        },
        extend: [lumiZigbeeOTA(), lumiPreventReset(), m.forceDeviceType({ type: "EndDevice" })],
    },
    {
        zigbeeModel: ["lumi.ctrl_ln2.aq1", "lumi.ctrl_ln2"],
        model: "QBKG12LM",
        vendor: "Aqara",
        description: "Smart wall switch (with neutral, double rocker)",
        fromZigbee: [
            lumi.fromZigbee.lumi_action,
            lumi.fromZigbee.lumi_action_multistate,
            lumi.fromZigbee.lumi_on_off,
            lumi.fromZigbee.lumi_basic,
            lumi.fromZigbee.lumi_operation_mode_basic,
            lumi.fromZigbee.lumi_power,
        ],
        exposes: [
            e.switch().withEndpoint("left"),
            e.switch().withEndpoint("right"),
            e.device_temperature(),
            e.energy(),
            e.power().withAccess(ea.STATE_GET),
            e.action([
                "single_left",
                "single_right",
                "single_both",
                "double_left",
                "double_right",
                "double_both",
                "hold_left",
                "hold_right",
                "hold_both",
                "release_left",
                "release_right",
                "release_both",
            ]),
            e
                .enum("operation_mode", ea.ALL, ["control_left_relay", "control_right_relay", "decoupled"])
                .withDescription("Operation mode for left button")
                .withEndpoint("left"),
            e
                .enum("operation_mode", ea.ALL, ["control_left_relay", "control_right_relay", "decoupled"])
                .withDescription("Operation mode for right button")
                .withEndpoint("right"),
        ],
        meta: { multiEndpoint: true, multiEndpointSkip: ["power", "energy"] },
        toZigbee: [tz.on_off, lumi.toZigbee.lumi_switch_operation_mode_basic, lumi.toZigbee.lumi_power],
        endpoint: (device) => {
            return { left: 1, right: 2, system: 1 };
        },
        extend: [lumiZigbeeOTA(), lumiPreventReset(), m.forcePowerSource({ powerSource: "Mains (single phase)" })],
    },
    {
        zigbeeModel: ["lumi.remote.b286acn02"],
        model: "WXKG07LM",
        vendor: "Aqara",
        description: "Wireless remote switch D1 (double rocker)",
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_action, lumi.fromZigbee.lumi_action_multistate],
        toZigbee: [],
        endpoint: (device) => {
            return { left: 1, right: 2, both: 3 };
        },
        exposes: [
            e.battery(),
            e.battery_voltage(),
            e.action([
                "single_left",
                "single_right",
                "single_both",
                "double_left",
                "double_right",
                "double_both",
                "hold_left",
                "hold_right",
                "hold_both",
            ]),
        ],
        extend: [m.quirkCheckinInterval("1_HOUR"), lumiPreventReset()],
    },
    {
        zigbeeModel: ["lumi.switch.b1lacn02"],
        model: "QBKG21LM",
        vendor: "Aqara",
        description: "Smart wall switch D1 (no neutral, single rocker)",
        fromZigbee: [lumi.fromZigbee.lumi_on_off, lumi.fromZigbee.lumi_action, lumi.fromZigbee.lumi_operation_mode_basic],
        exposes: [
            e.switch(),
            e.action(["release", "hold", "double", "single", "hold_release"]),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode"),
        ],
        toZigbee: [tz.on_off, lumi.toZigbee.lumi_switch_operation_mode_basic],
        endpoint: (device) => {
            return { system: 1, default: 2 };
        },
        extend: [lumiPreventReset(), m.forceDeviceType({ type: "EndDevice" }), m.forcePowerSource({ powerSource: "Mains (single phase)" })],
    },
    {
        zigbeeModel: ["lumi.switch.b2lacn02"],
        model: "QBKG22LM",
        vendor: "Aqara",
        description: "Smart wall switch D1 (no neutral, double rocker)",
        fromZigbee: [lumi.fromZigbee.lumi_on_off, lumi.fromZigbee.lumi_action, lumi.fromZigbee.lumi_operation_mode_basic],
        exposes: [
            e.switch().withEndpoint("left"),
            e.switch().withEndpoint("right"),
            e.action([
                "release_left",
                "release_right",
                "release_both",
                "double_left",
                "double_right",
                "single_left",
                "single_right",
                "hold_release_left",
                "hold_release_left",
            ]),
            e
                .enum("operation_mode", ea.ALL, ["control_left_relay", "control_right_relay", "decoupled"])
                .withDescription("Operation mode for left button")
                .withEndpoint("left"),
            e
                .enum("operation_mode", ea.ALL, ["control_left_relay", "control_right_relay", "decoupled"])
                .withDescription("Operation mode for right button")
                .withEndpoint("right"),
        ],
        toZigbee: [tz.on_off, lumi.toZigbee.lumi_switch_operation_mode_basic],
        meta: { multiEndpoint: true },
        endpoint: (device) => {
            return { system: 1, left: 2, right: 3 };
        },
        extend: [lumiPreventReset(), m.forceDeviceType({ type: "EndDevice" })],
    },
    {
        zigbeeModel: ["lumi.switch.l3acn3"],
        model: "QBKG25LM",
        vendor: "Aqara",
        description: "Smart wall switch D1 (no neutral, triple rocker)",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
        toZigbee: [
            tz.on_off,
            lumi.toZigbee.lumi_switch_operation_mode_opple,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            lumi.toZigbee.lumi_led_disabled_night,
            lumi.toZigbee.lumi_switch_mode_switch,
            lumi.toZigbee.lumi_flip_indicator_light,
        ],
        meta: { multiEndpoint: true },
        endpoint: (device) => {
            return { left: 1, center: 2, right: 3 };
        },
        exposes: [
            e.switch().withEndpoint("left"),
            e.switch().withEndpoint("center"),
            e.switch().withEndpoint("right"),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for left button").withEndpoint("left"),
            e
                .enum("operation_mode", ea.ALL, ["control_relay", "decoupled"])
                .withDescription("Decoupled mode for center button")
                .withEndpoint("center"),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for right button").withEndpoint("right"),
            e
                .enum("mode_switch", ea.ALL, ["anti_flicker_mode", "quick_mode"])
                .withDescription("Anti flicker mode can be used to solve blinking issues of some lights. Quick mode makes the device respond faster."),
            e.power_outage_memory(),
            e.led_disabled_night(),
            e.device_temperature().withAccess(ea.STATE),
            e.flip_indicator_light(),
            e.action([
                "left_single",
                "left_double",
                "center_single",
                "center_double",
                "right_single",
                "right_double",
                "single_left_center",
                "double_left_center",
                "single_left_right",
                "double_left_right",
                "single_center_right",
                "double_center_right",
                "single_all",
                "double_all",
            ]),
            e.power_outage_count(),
        ],
        configure: async (device, coordinatorEndpoint) => {
            await device
                .getEndpoint(1)
                .write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA(), lumiPreventReset()],
    },
    {
        zigbeeModel: ["lumi.switch.n3acn3"],
        model: "QBKG26LM",
        vendor: "Aqara",
        description: "Smart wall switch D1 (with neutral, triple rocker)",
        exposes: [
            e.switch().withEndpoint("left"),
            e.switch().withEndpoint("center"),
            e.switch().withEndpoint("right"),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for left button").withEndpoint("left"),
            e
                .enum("operation_mode", ea.ALL, ["control_relay", "decoupled"])
                .withDescription("Decoupled mode for center button")
                .withEndpoint("center"),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for right button").withEndpoint("right"),
            e.power().withAccess(ea.STATE),
            e.power_outage_memory(),
            e.led_disabled_night(),
            e.voltage(),
            e.energy(),
            e.device_temperature().withAccess(ea.STATE),
            e.flip_indicator_light(),
            e.action([
                "single_left",
                "double_left",
                "single_center",
                "double_center",
                "single_right",
                "double_right",
                "single_left_center",
                "double_left_center",
                "single_left_right",
                "double_left_right",
                "single_center_right",
                "double_center_right",
                "single_all",
                "double_all",
            ]),
        ],
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_specific, lumi.fromZigbee.lumi_action_multistate],
        toZigbee: [
            tz.on_off,
            lumi.toZigbee.lumi_switch_operation_mode_opple,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            lumi.toZigbee.lumi_led_disabled_night,
            lumi.toZigbee.lumi_flip_indicator_light,
        ],
        meta: { multiEndpoint: true },
        endpoint: (device) => {
            return { left: 1, center: 2, right: 3 };
        },
        configure: async (device, coordinatorEndpoint) => {
            await device
                .getEndpoint(1)
                .write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA(), lumiPreventReset()],
    },
    {
        zigbeeModel: ["lumi.switch.b1nacn02"],
        model: "QBKG23LM",
        vendor: "Aqara",
        description: "Smart wall switch D1 (with neutral, single rocker)",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_action_multistate],
        toZigbee: [tz.on_off, lumi.toZigbee.lumi_power, lumi.toZigbee.lumi_switch_operation_mode_basic],
        endpoint: (device) => {
            return { system: 1 };
        },
        exposes: [
            e.switch(),
            e.power().withAccess(ea.STATE_GET),
            e.energy(),
            e.device_temperature().withAccess(ea.STATE),
            e.voltage(),
            e.action(["single", "release"]),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode"),
        ],
        extend: [lumiZigbeeOTA(), lumiPreventReset(), m.forceDeviceType({ type: "Router" }), m.forcePowerSource({ powerSource: "Mains (single phase)" })],
    },
    {
        zigbeeModel: ["lumi.switch.b2nacn02"],
        model: "QBKG24LM",
        vendor: "Aqara",
        description: "Smart wall switch D1 (with neutral, double rocker)",
        fromZigbee: [
            fz.on_off,
            lumi.fromZigbee.lumi_power,
            lumi.fromZigbee.lumi_action_multistate,
            lumi.fromZigbee.lumi_operation_mode_basic,
            lumi.fromZigbee.lumi_specific,
            lumi.fromZigbee.lumi_basic,
        ],
        toZigbee: [tz.on_off, lumi.toZigbee.lumi_power, lumi.toZigbee.lumi_switch_operation_mode_basic],
        meta: { multiEndpoint: true, multiEndpointSkip: ["power", "energy"] },
        endpoint: (device) => {
            return { left: 1, right: 2, system: 1 };
        },
        exposes: [
            e.switch().withEndpoint("left"),
            e.switch().withEndpoint("right"),
            e.energy(),
            e.power().withAccess(ea.STATE_GET),
            e.action(["hold_left", "single_left", "double_left", "single_right", "double_right", "single_both", "double_both"]),
            e
                .enum("operation_mode", ea.ALL, ["control_left_relay", "decoupled"])
                .withDescription("Decoupled mode for left button")
                .withEndpoint("left"),
            e
                .enum("operation_mode", ea.ALL, ["control_right_relay", "decoupled"])
                .withDescription("Decoupled mode for right button")
                .withEndpoint("right"),
        ],
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA(), lumiPreventReset()],
    },
    {
        zigbeeModel: ["lumi.switch.b1lacn01"],
        model: "QBKG17LM",
        vendor: "Aqara",
        description: "Smart wall switch T1 (no neutral, single rocker)",
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiZigbeeOTA(),
            lumiOnOff({ powerOutageMemory: "binary", operationMode: true }),
            lumiLedDisabledNight(),
            lumiFlipIndicatorLight(),
            lumiAction({ actionLookup: { single: 1, double: 2 } }),
            lumiPreventReset(),
        ],
    },
    {
        zigbeeModel: ["lumi.switch.b2lacn01"],
        model: "QBKG18LM",
        vendor: "Aqara",
        description: "Smart wall switch T1 (no neutral, double rocker)",
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiZigbeeOTA(),
            m.deviceEndpoints({ endpoints: { left: 1, right: 2 } }),
            lumiOnOff({ powerOutageMemory: "binary", operationMode: true, endpointNames: ["left", "right"] }),
            lumiLedDisabledNight(),
            lumiFlipIndicatorLight(),
            lumiAction({ actionLookup: { single: 1, double: 2 }, buttonLookup: { left: 41, right: 42, both: 51 } }),
            lumiPreventReset(),
        ],
    },
    {
        zigbeeModel: ["lumi.switch.b1nacn01"],
        model: "QBKG19LM",
        vendor: "Aqara",
        description: "Smart wall switch T1 (with neutral, single rocker)",
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiZigbeeOTA(),
            lumiOnOff({ powerOutageMemory: "binary", operationMode: true }),
            lumiLedDisabledNight(),
            lumiFlipIndicatorLight(),
            lumiAction({ actionLookup: { single: 1, double: 2 } }),
            lumiElectricityMeter(),
            lumiPower(),
            lumiPreventReset(),
        ],
    },
    {
        zigbeeModel: ["lumi.switch.b2nacn01"],
        model: "QBKG20LM",
        vendor: "Aqara",
        description: "Smart wall switch T1 (with neutral, double rocker)",
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            m.forceDeviceType({ type: "Router" }),
            m.forcePowerSource({ powerSource: "Mains (single phase)" }),
            lumiZigbeeOTA(),
            m.deviceEndpoints({ endpoints: { left: 1, right: 2 } }),
            lumiOnOff({ powerOutageMemory: "binary", operationMode: true, endpointNames: ["left", "right"] }),
            lumiLedDisabledNight(),
            lumiFlipIndicatorLight(),
            lumiAction({ actionLookup: { single: 1, double: 2 }, buttonLookup: { left: 41, right: 42, both: 51 } }),
            lumiElectricityMeter(),
            lumiPower(),
            lumiPreventReset(),
        ],
    },
    {
        zigbeeModel: ["lumi.switch.b3l01"],
        model: "QBKG33LM",
        vendor: "Aqara",
        description: "Smart wall switch T1 (no neutral, triple rocker)",
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiZigbeeOTA(),
            m.deviceEndpoints({ endpoints: { left: 1, center: 2, right: 3 } }),
            lumiOnOff({ powerOutageMemory: "binary", operationMode: true, endpointNames: ["left", "center", "right"] }),
            lumiLedDisabledNight(),
            lumiFlipIndicatorLight(),
            lumiAction({
                actionLookup: { single: 1, double: 2 },
                buttonLookup: {
                    left: 41,
                    center: 42,
                    right: 43,
                    left_center: 51,
                    left_right: 52,
                    center_right: 53,
                    all: 61,
                },
            }),
            lumiPreventReset(),
        ],
    },
    {
        zigbeeModel: ["lumi.switch.b3n01"],
        model: "QBKG34LM",
        vendor: "Aqara",
        description: "Smart wall switch T1 (with neutral, triple rocker)",
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiZigbeeOTA(),
            m.deviceEndpoints({ endpoints: { left: 1, center: 2, right: 3 } }),
            lumiOnOff({ powerOutageMemory: "binary", operationMode: true, endpointNames: ["left", "center", "right"] }),
            lumiLedDisabledNight(),
            lumiFlipIndicatorLight(),
            lumiAction({
                actionLookup: { single: 1, double: 2 },
                buttonLookup: {
                    left: 41,
                    center: 42,
                    right: 43,
                    left_center: 51,
                    left_right: 52,
                    center_right: 53,
                    all: 61,
                },
            }),
            lumiElectricityMeter(),
            lumiPreventReset(),
        ],
    },
    {
        zigbeeModel: ["lumi.sens", "lumi.sensor_ht"],
        model: "WSDCGQ01LM",
        vendor: "Xiaomi",
        whiteLabel: [
            { vendor: "Xiaomi", model: "YTC4042GL" },
            { vendor: "Xiaomi", model: "YTC4007CN" },
            { vendor: "Xiaomi", model: "YTC4018CN" },
        ],
        description: "Mi temperature and humidity sensor",
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_temperature, fz.humidity],
        toZigbee: [],
        exposes: [e.battery(), e.temperature(), e.humidity(), e.battery_voltage()],
        extend: [m.quirkCheckinInterval("1_HOUR")],
    },
    {
        zigbeeModel: ["lumi.weather"],
        model: "WSDCGQ11LM",
        vendor: "Aqara",
        description: "Temperature and humidity sensor",
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_temperature, fz.humidity, fz.pressure],
        toZigbee: [],
        exposes: [e.battery(), e.temperature(), e.humidity(), e.pressure(), e.battery_voltage()],
        extend: [m.quirkCheckinInterval("1_HOUR"), m.forcePowerSource({ powerSource: "Battery" })],
    },
    {
        zigbeeModel: ["lumi.sensor_ht.agl02"],
        model: "WSDCGQ12LM",
        vendor: "Aqara",
        description: "Temperature and humidity sensor T1",
        whiteLabel: [
            { vendor: "Aqara", model: "TH-S02D" },
            { vendor: "Yandex", model: "YNDX-00523" },
        ],
        fromZigbee: [lumi.fromZigbee.lumi_specific, fz.temperature, fz.humidity, lumi.fromZigbee.lumi_pressure, fz.battery],
        toZigbee: [],
        exposes: [e.temperature(), e.humidity(), e.pressure(), e.device_temperature(), e.battery(), e.battery_voltage(), e.power_outage_count(false)],
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            const binds = ["msTemperatureMeasurement", "msRelativeHumidity", "msPressureMeasurement"];
            await reporting.bind(endpoint, coordinatorEndpoint, binds);
            await endpoint.read("genPowerCfg", ["batteryVoltage"]);
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), m.quirkCheckinInterval("1_HOUR"), lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["lumi.sensor_motion"],
        model: "RTCGQ01LM",
        vendor: "Xiaomi",
        whiteLabel: [
            { vendor: "Xiaomi", model: "YTC4041GL" },
            { vendor: "Xiaomi", model: "YTC4004CN" },
            { vendor: "Xiaomi", model: "YTC4016CN" },
            { vendor: "Xiaomi", model: "ZHTZ02LM" },
        ],
        description: "Mi motion sensor",
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        fromZigbee: [lumi.fromZigbee.lumi_basic, fz.occupancy_with_timeout],
        toZigbee: [],
        exposes: [e.battery(), e.occupancy(), e.battery_voltage(), e.power_outage_count(false)],
        extend: [m.quirkCheckinInterval("1_HOUR")],
    },
    {
        zigbeeModel: ["lumi.sensor_motion.aq2"],
        model: "RTCGQ11LM",
        vendor: "Aqara",
        description: "Motion sensor",
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        fromZigbee: [lumi.fromZigbee.lumi_basic, fz.occupancy_with_timeout, lumi.fromZigbee.lumi_illuminance],
        toZigbee: [],
        exposes: [e.battery(), e.occupancy(), e.device_temperature(), e.battery_voltage(), e.illuminance(), e.power_outage_count(false)],
        extend: [m.quirkCheckinInterval("1_HOUR")],
    },
    {
        zigbeeModel: ["lumi.motion.agl02"],
        model: "RTCGQ12LM",
        vendor: "Aqara",
        description: "Motion sensor T1",
        whiteLabel: [{ vendor: "Yandex", model: "YNDX-00522" }],
        fromZigbee: [lumi.fromZigbee.lumi_occupancy_illuminance, lumi.fromZigbee.lumi_specific, fz.battery],
        toZigbee: [lumi.toZigbee.lumi_detection_interval],
        exposes: [
            e.occupancy(),
            e.illuminance(),
            e
                .numeric("detection_interval", ea.ALL)
                .withValueMin(2)
                .withValueMax(65535)
                .withUnit("s")
                .withDescription("Time interval for detecting actions"),
            e.device_temperature(),
            e.battery(),
            e.battery_voltage(),
            e.power_outage_count(false),
        ],
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            await endpoint.read("genPowerCfg", ["batteryVoltage"]);
            await endpoint.read("manuSpecificLumi", [0x0102], { manufacturerCode: manufacturerCode });
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), m.quirkCheckinInterval("1_HOUR"), lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["lumi.motion.agl04"],
        model: "RTCGQ13LM",
        vendor: "Aqara",
        description: "High precision motion sensor",
        fromZigbee: [lumi.fromZigbee.lumi_occupancy, lumi.fromZigbee.lumi_specific, fz.battery],
        toZigbee: [lumi.toZigbee.lumi_detection_interval, lumi.toZigbee.lumi_motion_sensitivity],
        exposes: [
            e.occupancy(),
            e.enum("motion_sensitivity", ea.ALL, ["low", "medium", "high"]),
            e
                .numeric("detection_interval", ea.ALL)
                .withValueMin(2)
                .withValueMax(65535)
                .withUnit("s")
                .withDescription("Time interval for detecting actions"),
            e.device_temperature(),
            e.battery(),
            e.battery_voltage(),
            e.power_outage_count(false),
        ],
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            await endpoint.read("genPowerCfg", ["batteryVoltage"]);
            await endpoint.read("manuSpecificLumi", [0x0102], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x010c], { manufacturerCode: manufacturerCode });
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), m.quirkCheckinInterval("1_HOUR"), lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["lumi.motion.ac02"],
        model: "RTCGQ14LM",
        vendor: "Aqara",
        whiteLabel: [{ vendor: "Aqara", model: "MS-S02" }],
        description: "Motion sensor P1",
        fromZigbee: [lumi.fromZigbee.lumi_occupancy_illuminance, lumi.fromZigbee.lumi_specific, fz.battery],
        toZigbee: [lumi.toZigbee.lumi_detection_interval, lumi.toZigbee.lumi_motion_sensitivity, lumi.toZigbee.lumi_trigger_indicator],
        exposes: [
            e.occupancy(),
            e.illuminance(),
            e
                .motion_sensitivity_select(["low", "medium", "high"])
                .withDescription("Select motion sensitivity to use. Press pairing button right before changing this otherwise it will fail."),
            e
                .detection_interval()
                .withDescription("Time interval between action detection. Press pairing button right before changing this otherwise it will fail."),
            e
                .trigger_indicator()
                .withDescription("When this option is enabled then " +
                "blue LED will blink once when motion is detected. " +
                "Press pairing button right before changing this otherwise it will fail."),
            e.device_temperature(),
            e.battery(),
            e.battery_voltage(),
        ],
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            await endpoint.read("genPowerCfg", ["batteryVoltage"]);
            await endpoint.read("manuSpecificLumi", [0x0102], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x010c], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x0152], { manufacturerCode: manufacturerCode });
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), m.quirkCheckinInterval("1_HOUR"), lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["lumi.motion.acn001"],
        model: "RTCGQ15LM",
        vendor: "Aqara",
        description: "Motion sensor E1",
        fromZigbee: [lumi.fromZigbee.lumi_occupancy_illuminance, lumi.fromZigbee.lumi_specific, fz.battery],
        toZigbee: [lumi.toZigbee.lumi_detection_interval],
        exposes: [
            e.occupancy(),
            e.illuminance(),
            e
                .numeric("detection_interval", ea.ALL)
                .withValueMin(2)
                .withValueMax(65535)
                .withUnit("s")
                .withDescription("Time interval for detecting actions"),
            e.device_temperature(),
            e.battery(),
            e.battery_voltage(),
            e.power_outage_count(false),
        ],
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            await endpoint.read("genPowerCfg", ["batteryVoltage"]);
            await endpoint.read("manuSpecificLumi", [0x0102], { manufacturerCode: manufacturerCode });
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), m.quirkCheckinInterval("1_HOUR"), lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["lumi.motion.ac01"],
        model: "RTCZCGQ11LM",
        vendor: "Aqara",
        description: "Presence sensor FP1",
        fromZigbee: [lumi.fromZigbee.lumi_specific, lumi.fromZigbee.lumi_presence_region_events],
        toZigbee: [
            lumi.toZigbee.lumi_presence,
            lumi.toZigbee.lumi_monitoring_mode,
            lumi.toZigbee.lumi_approach_distance,
            lumi.toZigbee.lumi_motion_sensitivity,
            lumi.toZigbee.lumi_reset_nopresence_status,
            lumi.toZigbee.lumi_presence_region_upsert,
            lumi.toZigbee.lumi_presence_region_delete,
        ],
        exposes: [
            e.presence().withAccess(ea.STATE_GET),
            e.device_temperature(),
            e.power_outage_count(),
            e
                .enum("presence_event", ea.STATE, ["enter", "leave", "left_enter", "right_leave", "right_enter", "left_leave", "approach", "away"])
                .withDescription('Presence events: "enter", "leave", "left_enter", "right_leave", "right_enter", "left_leave", "approach", "away"'),
            e
                .enum("monitoring_mode", ea.ALL, ["undirected", "left_right"])
                .withDescription("Monitoring mode with or without considering right and left sides"),
            e.enum("approach_distance", ea.ALL, ["far", "medium", "near"]).withDescription("The distance at which the sensor detects approaching"),
            e
                .enum("motion_sensitivity", ea.ALL, ["low", "medium", "high"])
                .withDescription("Different sensitivities means different static human body recognition rate and response speed of occupied"),
            e.enum("reset_nopresence_status", ea.SET, [""]).withDescription("Reset the status of no presence"),
            e
                .enum("action", ea.STATE, ["region_*_enter", "region_*_leave", "region_*_occupied", "region_*_unoccupied"])
                .withDescription('Most recent region event. Event template is "region_<REGION_ID>_<EVENT_TYPE>", ' +
                'where <REGION_ID> is region number (1-10), <EVENT_TYPE> is one of "enter", "leave", "occupied", "unoccupied". ' +
                '"enter" / "leave" events are usually triggered first, followed by "occupied" / "unoccupied" after a couple of seconds.'),
            e
                .text("configured_regions", ea.STATE)
                .withDescription("Region definitions written through Zigbee2MQTT. " +
                "This is a Zigbee2MQTT-side cache and may not include regions configured by another gateway."),
            e
                .composite("region_upsert", "region_upsert", ea.SET)
                .withDescription("Definition of a new region to be added (or replace existing one). " +
                "Creating or modifying a region requires you to define which zones of a 7x4 detection grid " +
                "should be active for that zone. Regions can overlap, meaning that a zone can be defined " +
                'in more than one region (eg. "zone x = 1 & y = 1" can be added to region 1 & 2). ' +
                '"Zone x = 1 & y = 1" is the nearest zone on the right (from sensor\'s perspective, along the detection path).')
                .withFeature(e
                .numeric("region_id", ea.SET)
                .withValueMin(lumi.presence.constants.region_config_regionId_min)
                .withValueMax(lumi.presence.constants.region_config_regionId_max))
                .withFeature(e
                .list("zones", ea.SET, e
                .composite("Zone position", "zone_position", ea.SET)
                .withFeature(e
                .numeric("x", ea.SET)
                .withValueMin(lumi.presence.constants.region_config_zoneX_min)
                .withValueMax(lumi.presence.constants.region_config_zoneX_max))
                .withFeature(e
                .numeric("y", ea.SET)
                .withValueMin(lumi.presence.constants.region_config_zoneY_min)
                .withValueMax(lumi.presence.constants.region_config_zoneY_max)))
                .withDescription('list of dictionaries in the format {"x": 1, "y": 1}, {"x": 2, "y": 1}')),
            e
                .composite("region_delete", "region_delete", ea.SET)
                .withDescription("Region definition to be deleted from the device.")
                .withFeature(e
                .numeric("region_id", ea.SET)
                .withValueMin(lumi.presence.constants.region_config_regionId_min)
                .withValueMax(lumi.presence.constants.region_config_regionId_max)),
        ],
        configure: async (device, coordinatorEndpoint) => {
            device.softwareBuildID = `${device.applicationVersion}`;
            device.save();
            const endpoint = device.getEndpoint(1);
            await endpoint.read("manuSpecificLumi", [0x010c], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x0142], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x0144], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x0146], { manufacturerCode: manufacturerCode });
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["lumi.sensor_occupy.agl1"],
        model: "FP1E",
        vendor: "Aqara",
        description: "Presence sensor",
        fromZigbee: [lumi.fromZigbee.lumi_specific],
        toZigbee: [lumi.toZigbee.lumi_motion_sensitivity],
        exposes: [
            e.device_temperature(),
            e.power_outage_count(),
            e.motion_sensitivity_select(["low", "medium", "high"]).withDescription("Select motion sensitivity to use."),
        ],
        ota: true,
        configure: async (device, coordinatorEndpoint) => {
            // Retrieve motion sensitivity value
            const endpoint = device.getEndpoint(1);
            await endpoint.read("manuSpecificLumi", [0x010c], { manufacturerCode: manufacturerCode });
        },
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiZigbeeOTA(),
            lumi.lumiModernExtend.fp1ePresence(),
            lumi.lumiModernExtend.fp1eMovement(),
            lumi.lumiModernExtend.fp1eTargetDistance(),
            lumi.lumiModernExtend.fp1eDetectionRange(),
            lumi.lumiModernExtend.fp1eSpatialLearning(),
            lumi.lumiModernExtend.fp1eRestartDevice(),
            m.identify(),
            lumi.lumiModernExtend.fp1eAIInterference(),
            lumi.lumiModernExtend.fp1eAdaptiveSensitivity(),
        ],
    },
    {
        zigbeeModel: ["lumi.sensor_magnet"],
        model: "MCCGQ01LM",
        vendor: "Xiaomi",
        whiteLabel: [
            { vendor: "Xiaomi", model: "YTC4039GL" },
            { vendor: "Xiaomi", model: "YTC4005CN" },
            { vendor: "Xiaomi", model: "YTC4015CN" },
            { vendor: "Xiaomi", model: "ZHTZ02LM" },
        ],
        description: "Mi door and window sensor",
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_contact],
        toZigbee: [],
        exposes: [e.battery(), e.contact(), e.battery_voltage(), e.power_outage_count(false)],
        extend: [m.quirkCheckinInterval("1_HOUR")],
    },
    {
        zigbeeModel: ["lumi.sensor_magnet.aq2"],
        model: "MCCGQ11LM",
        vendor: "Aqara",
        description: "Door and window sensor",
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_contact],
        toZigbee: [],
        exposes: [e.battery(), e.contact(), e.device_temperature(), e.battery_voltage(), e.power_outage_count(false), e.trigger_count()],
        extend: [m.quirkCheckinInterval("1_HOUR"), m.forcePowerSource({ powerSource: "Battery" })],
    },
    {
        zigbeeModel: ["lumi.sensor_wleak.aq1"],
        model: "SJCGQ11LM",
        vendor: "Aqara",
        description: "Water leak sensor",
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        fromZigbee: [lumi.fromZigbee.lumi_basic],
        toZigbee: [],
        exposes: [e.battery(), e.battery_voltage(), e.device_temperature(), e.power_outage_count(false), e.trigger_count()],
        extend: [m.quirkCheckinInterval("1_HOUR"), m.iasZoneAlarm({ zoneType: "water_leak", zoneAttributes: ["alarm_1", "battery_low"] })],
    },
    {
        zigbeeModel: ["lumi.flood.agl02"],
        model: "SJCGQ12LM",
        vendor: "Aqara",
        description: "Water leak sensor T1",
        whiteLabel: [
            { vendor: "Aqara", model: "WL-S02D" },
            { vendor: "Yandex", model: "YNDX-00521" },
        ],
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        fromZigbee: [lumi.fromZigbee.lumi_basic, fz.ias_water_leak_alarm_1, lumi.fromZigbee.lumi_specific],
        toZigbee: [],
        exposes: [e.battery(), e.water_leak(), e.battery_low(), e.tamper(), e.battery_voltage()],
        version: "0.0.1",
        configure: async (device, coordinatorEndpoint) => {
            await ensureLumiIasEnrollment(device.getEndpoint(1), coordinatorEndpoint);
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), m.quirkCheckinInterval("1_HOUR"), lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["lumi.sensor_cube", "lumi.sensor_cube.aqgl01"],
        model: "MFKZQ01LM",
        vendor: "Aqara",
        description: "Cube",
        whiteLabel: [{ vendor: "Xiaomi", model: "MFKZQ01LM" }],
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_action_analog],
        exposes: [
            e.battery(),
            e.battery_voltage(),
            e.angle("action_angle"),
            e.device_temperature(),
            e.power_outage_count(false),
            e.cube_side("action_from_side"),
            e.cube_side("action_side"),
            e.cube_side("action_to_side"),
            e.cube_side("side"),
            e.action(["shake", "throw", "wakeup", "fall", "tap", "slide", "flip180", "flip90", "rotate_left", "rotate_right"]),
        ],
        toZigbee: [],
        extend: [m.quirkCheckinInterval("1_HOUR")],
    },
    {
        zigbeeModel: ["lumi.plug"],
        model: "ZNCZ02LM",
        description: "Mi smart plug",
        vendor: "Xiaomi",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_basic, fz.ignore_occupancy_report, fz.ignore_illuminance_report],
        toZigbee: [tz.on_off, lumi.toZigbee.lumi_switch_power_outage_memory, lumi.toZigbee.lumi_power],
        exposes: [e.switch(), e.power().withAccess(ea.STATE_GET), e.energy(), e.device_temperature(), e.power_outage_memory()],
        extend: [lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["lumi.plug.mitw01"],
        model: "ZNCZ03LM",
        description: "Mi smart plug TW",
        vendor: "Xiaomi",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_basic, fz.ignore_occupancy_report, fz.ignore_illuminance_report],
        toZigbee: [tz.on_off, lumi.toZigbee.lumi_power],
        exposes: [e.switch(), e.power().withAccess(ea.STATE_GET), e.energy(), e.device_temperature().withAccess(ea.STATE), e.voltage()],
    },
    {
        zigbeeModel: ["lumi.plug.mmeu01"],
        model: "ZNCZ04LM",
        description: "Mi smart plug EU",
        vendor: "Xiaomi",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_specific, fz.ignore_occupancy_report, fz.ignore_illuminance_report],
        toZigbee: [
            tz.on_off,
            lumi.toZigbee.lumi_power,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            lumi.toZigbee.lumi_auto_off,
            lumi.toZigbee.lumi_led_disabled_night,
            lumi.toZigbee.lumi_overload_protection,
        ],
        exposes: [
            e.switch(),
            e.power().withAccess(ea.STATE_GET),
            e.energy(),
            e.device_temperature().withAccess(ea.STATE),
            e.voltage(),
            e.current(),
            e.consumer_connected(),
            e.led_disabled_night(),
            e.power_outage_memory(),
            e.auto_off(20),
            e.overload_protection(100, 2300),
        ],
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["lumi.plug.maus01"],
        model: "ZNCZ12LM",
        description: "Smart plug US",
        vendor: "Aqara",
        fromZigbee: [
            fz.on_off,
            lumi.fromZigbee.lumi_power,
            lumi.fromZigbee.lumi_specific,
            lumi.fromZigbee.lumi_basic,
            fz.ignore_occupancy_report,
            fz.ignore_illuminance_report,
        ],
        toZigbee: [
            tz.on_off,
            lumi.toZigbee.lumi_power,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            lumi.toZigbee.lumi_auto_off,
            lumi.toZigbee.lumi_led_disabled_night,
            lumi.toZigbee.lumi_overload_protection,
        ],
        exposes: [
            e.switch(),
            e.power().withAccess(ea.STATE_GET),
            e.energy(),
            e.device_temperature().withAccess(ea.STATE),
            e.voltage(),
            e.current(),
            e.consumer_connected(),
            e.led_disabled_night(),
            e.power_outage_memory(),
            e.auto_off(20),
            e.overload_protection(100, 2300),
        ],
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["lumi.plug.maeu01"],
        model: "SP-EUC01",
        description: "Smart plug EU",
        vendor: "Aqara",
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            m.forceDeviceType({ type: "Router" }),
            lumiZigbeeOTA(),
            m.poll({
                // This device doesn't support temperature reporting.
                // Therefore we read the temperature every 30 min.
                key: "interval",
                defaultIntervalSeconds: 30 * 60,
                poll: async (device) => {
                    await device.getEndpoint(1)?.read("genDeviceTempCfg", ["currentTemperature"]);
                },
            }),
        ],
        fromZigbee: [
            fz.on_off,
            lumi.fromZigbee.lumi_basic,
            fz.electrical_measurement,
            fz.metering,
            lumi.fromZigbee.lumi_specific,
            lumi.fromZigbee.lumi_power,
            fz.device_temperature,
        ],
        toZigbee: [
            tz.on_off,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            lumi.toZigbee.lumi_led_disabled_night,
            lumi.toZigbee.lumi_overload_protection,
            lumi.toZigbee.lumi_auto_off,
            lumi.toZigbee.lumi_socket_button_lock,
        ],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff"]);
            await reporting.onOff(endpoint);
            // Not all plugs support electricity measurements:
            // - https://github.com/Koenkk/zigbee2mqtt/issues/6861
            // - https://github.com/Koenkk/zigbee-herdsman-converters/issues/1050#issuecomment-673111969
            // Voltage and current are not supported:
            // - https://github.com/Koenkk/zigbee-herdsman-converters/issues/1050
            try {
                await reporting.bind(endpoint, coordinatorEndpoint, ["haElectricalMeasurement"]);
                await endpoint.read("haElectricalMeasurement", ["acPowerMultiplier", "acPowerDivisor"]);
            }
            catch (e) {
                logger_1.logger.warning(`SP-EUC01 failed to setup electricity measurements (${e.message})`, NS);
                logger_1.logger.debug(`${e.stack}`, NS);
            }
            try {
                await reporting.bind(endpoint, coordinatorEndpoint, ["seMetering"]);
                await reporting.readMeteringMultiplierDivisor(endpoint);
                await reporting.currentSummDelivered(endpoint, { change: 0 });
            }
            catch (e) {
                logger_1.logger.warning(`SP-EUC01 failed to setup metering (${e.message})`, NS);
                logger_1.logger.debug(`${e.stack}`, NS);
            }
        },
        exposes: [
            e.switch(),
            e.power(),
            e.energy(),
            e.power_outage_memory(),
            e.voltage(),
            e.current(),
            e.device_temperature().withDescription("Device temperature (polled every 30 min)"),
            e.consumer_connected(),
            e.led_disabled_night(),
            e.overload_protection(100, 2300),
            e.auto_off(20),
            e.button_lock(),
        ],
    },
    {
        zigbeeModel: ["lumi.plug.aq1"],
        model: "ZNCZ11LM",
        vendor: "Aqara",
        description: "Smart plug",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, fz.ignore_occupancy_report, lumi.fromZigbee.lumi_basic],
        toZigbee: [
            tz.on_off,
            lumi.toZigbee.lumi_power,
            lumi.toZigbee.lumi_led_disabled_night,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            lumi.toZigbee.lumi_auto_off,
        ],
        exposes: [
            e.switch(),
            e.power().withAccess(ea.STATE_GET),
            e.energy(),
            e.device_temperature(),
            e.voltage(),
            e.power_outage_memory(),
            e.led_disabled_night(),
            e.auto_off(30),
        ],
        extend: [m.customTimeResponse("2000_LOCAL")],
    },
    {
        zigbeeModel: ["lumi.ctrl_86plug", "lumi.ctrl_86plug.aq1"],
        model: "QBCZ11LM",
        description: "Smart wall outlet",
        vendor: "Aqara",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_basic],
        toZigbee: [tz.on_off, lumi.toZigbee.lumi_switch_power_outage_memory, lumi.toZigbee.lumi_power],
        exposes: [
            e.switch(),
            e.power().withAccess(ea.STATE_GET),
            e.energy(),
            e.device_temperature().withAccess(ea.STATE),
            e.voltage(),
            e.power_outage_memory(),
        ],
        extend: [lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["lumi.plug.acn005"],
        model: "ZNQBCZ11LM",
        vendor: "Aqara",
        description: "Smart wall outlet H2 (USB)",
        fromZigbee: [lumi.fromZigbee.lumi_specific],
        toZigbee: [lumi.toZigbee.lumi_button_switch_mode],
        meta: { multiEndpoint: true, multiEndpointSkip: ["power", "energy"] },
        endpoint: () => {
            return { relay: 1, usb: 2 };
        },
        exposes: [
            e
                .enum("button_switch_mode", exposes.access.ALL, ["relay", "relay_and_usb"])
                .withDescription("Control both relay and usb or only the relay with the physical switch button"),
        ],
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumi.lumiModernExtend.lumiZigbeeOTA(),
            lumi.lumiModernExtend.lumiOnOff({ powerOutageMemory: "enum", endpointNames: ["relay", "usb"] }),
            lumi.lumiModernExtend.lumiLedDisabledNight(),
            lumi.lumiModernExtend.lumiPower(),
            lumi.lumiModernExtend.lumiElectricityMeter(),
            lumi.lumiModernExtend.lumiOverloadProtection(),
            lumi.lumiModernExtend.lumiButtonLock(),
        ],
    },
    {
        zigbeeModel: ["lumi.sensor_smoke"],
        model: "JTYJ-GD-01LM/BW",
        description: "Mijia Honeywell smoke detector",
        vendor: "Xiaomi",
        whiteLabel: [{ vendor: "Xiaomi", model: "YTC4020RT" }],
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_smoke],
        toZigbee: [lumi.toZigbee.lumi_sensitivity, lumi.toZigbee.lumi_selftest],
        exposes: [
            e.smoke(),
            e.battery_low(),
            e.tamper(),
            e.battery(),
            e.enum("sensitivity", ea.STATE_SET, ["low", "medium", "high"]),
            e.numeric("smoke_density", ea.STATE),
            e.enum("selftest", ea.SET, [""]),
            e.battery_voltage(),
            e.binary("test", ea.STATE, true, false).withDescription("Test mode activated"),
            e.device_temperature(),
            e.power_outage_count(false),
        ],
        extend: [m.quirkCheckinInterval("1_HOUR")],
    },
    {
        zigbeeModel: ["lumi.sensor_natgas"],
        model: "JTQJ-BF-01LM/BW",
        vendor: "Xiaomi",
        whiteLabel: [{ vendor: "Xiaomi", model: "YTC4019RT" }],
        description: "Mijia Honeywell gas leak detector",
        fromZigbee: [fz.ias_gas_alarm_1, lumi.fromZigbee.lumi_gas_sensitivity, lumi.fromZigbee.lumi_gas_density],
        toZigbee: [lumi.toZigbee.lumi_sensitivity, lumi.toZigbee.lumi_selftest],
        exposes: [
            e.gas(),
            e.tamper(),
            e.enum("sensitivity", ea.STATE_SET, ["low", "medium", "high"]),
            e.numeric("gas_density", ea.STATE),
            e.enum("selftest", ea.SET, [""]),
        ],
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            m.forceDeviceType({ type: "Router" }),
            m.forcePowerSource({ powerSource: "Mains (single phase)" }),
        ],
    },
    {
        zigbeeModel: ["lumi.sensor_gas.acn02"],
        model: "JT-BZ-01AQ/A",
        vendor: "Aqara",
        description: "Smart natural gas detector",
        whiteLabel: [{ vendor: "Aqara", model: "JT-BZ-03AQ/A" }],
        fromZigbee: [lumi.fromZigbee.lumi_specific],
        toZigbee: [
            lumi.toZigbee.lumi_alarm,
            lumi.toZigbee.lumi_density,
            lumi.toZigbee.lumi_gas_sensitivity,
            lumi.toZigbee.lumi_selftest,
            lumi.toZigbee.lumi_buzzer,
            lumi.toZigbee.lumi_buzzer_manual,
            lumi.toZigbee.lumi_linkage_alarm,
            lumi.toZigbee.lumi_state,
            lumi.toZigbee.lumi_power_outage_count,
        ],
        exposes: [
            e.gas().withAccess(ea.STATE_GET),
            e.numeric("gas_density", ea.STATE_GET).withUnit("%LEL").withDescription("Value of gas concentration"),
            e
                .enum("gas_sensitivity", ea.ALL, ["10%LEL", "15%LEL"])
                .withDescription('Gas concentration value at which an alarm is triggered ("10%LEL" is more sensitive than "15%LEL")'),
            e
                .enum("selftest", ea.SET, ["selftest"])
                .withDescription("Starts the self-test process (checking the indicator light and buzzer work properly)"),
            e.binary("test", ea.STATE, true, false).withDescription("Self-test in progress"),
            e
                .enum("buzzer", ea.SET, ["mute", "alarm"])
                .withDescription("The buzzer can be muted and alarmed manually. " +
                'During a gas alarm, the buzzer can be manually muted for 10 minutes ("mute"), but cannot be unmuted manually ' +
                "before this timeout expires. The buzzer cannot be pre-muted, as this function only works during a gas alarm. " +
                'During the absence of a gas alarm, the buzzer can be manually alarmed ("alarm") and disalarmed ("mute"), ' +
                'but for this "linkage_alarm" option must be enabled'),
            e.binary("buzzer_manual_alarm", ea.STATE_GET, true, false).withDescription("Buzzer alarmed (manually)"),
            e.binary("buzzer_manual_mute", ea.STATE_GET, true, false).withDescription("Buzzer muted (manually)"),
            e
                .binary("linkage_alarm", ea.ALL, true, false)
                .withDescription("When this option is enabled and a gas " +
                'alarm has occurred, then "linkage_alarm_state"=true, and when the gas alarm has ended or the buzzer has ' +
                'been manually muted, then "linkage_alarm_state"=false'),
            e.binary("linkage_alarm_state", ea.STATE, true, false).withDescription('"linkage_alarm" is triggered'),
            e
                .binary("state", ea.STATE_GET, "preparation", "work")
                .withDescription('"Preparation" or "work" ' +
                '(measurement of the gas concentration value and triggering of an alarm are only performed in the "work" state)'),
            e.power_outage_count().withAccess(ea.STATE_GET),
        ],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            await endpoint.write("manuSpecificLumi", { 331: { value: 1, type: 0x20 } }, { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x013a], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x013b], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x013d], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x0126], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x0139], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x010c], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x014b], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x0002], { manufacturerCode: manufacturerCode });
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["lumi.sensor_smoke.acn03"],
        model: "JY-GZ-01AQ",
        vendor: "Aqara",
        description: "Smart smoke detector",
        whiteLabel: [{ vendor: "Aqara", model: "JY-GZ-03AQ" }],
        fromZigbee: [lumi.fromZigbee.lumi_specific, fz.battery],
        toZigbee: [
            lumi.toZigbee.lumi_alarm,
            lumi.toZigbee.lumi_density,
            lumi.toZigbee.lumi_selftest,
            lumi.toZigbee.lumi_buzzer,
            lumi.toZigbee.lumi_buzzer_manual,
            lumi.toZigbee.lumi_heartbeat_indicator,
            lumi.toZigbee.lumi_linkage_alarm,
        ],
        ota: true,
        exposes: [
            e.smoke().withAccess(ea.STATE_GET),
            e.numeric("smoke_density", ea.STATE_GET).withDescription("Value of smoke concentration"),
            e.numeric("smoke_density_dbm", ea.STATE_GET).withUnit("dB/m").withDescription("Value of smoke concentration in dB/m"),
            e
                .enum("selftest", ea.SET, ["selftest"])
                .withDescription("Starts the self-test process (checking the indicator light and buzzer work properly)"),
            e.binary("test", ea.STATE, true, false).withDescription("Self-test in progress"),
            e
                .enum("buzzer", ea.SET, ["mute", "alarm"])
                .withDescription("The buzzer can be muted and alarmed manually. " +
                'During a smoke alarm, the buzzer can be manually muted for 80 seconds ("mute") and unmuted ("alarm"). ' +
                "The buzzer cannot be pre-muted, as this function only works during a smoke alarm. " +
                'During the absence of a smoke alarm, the buzzer can be manually alarmed ("alarm") and disalarmed ("mute"), ' +
                'but for this "linkage_alarm" option must be enabled'),
            e.binary("buzzer_manual_alarm", ea.STATE_GET, true, false).withDescription("Buzzer alarmed (manually)"),
            e.binary("buzzer_manual_mute", ea.STATE_GET, true, false).withDescription("Buzzer muted (manually)"),
            e
                .binary("heartbeat_indicator", ea.ALL, true, false)
                .withDescription("When this option is enabled then in the normal monitoring state, the green indicator light flashes every 60 seconds"),
            e
                .binary("linkage_alarm", ea.ALL, true, false)
                .withDescription("When this option is enabled and a smoke " +
                'alarm has occurred, then "linkage_alarm_state"=true, and when the smoke alarm has ended or the buzzer has ' +
                'been manually muted, then "linkage_alarm_state"=false'),
            e.binary("linkage_alarm_state", ea.STATE, true, false).withDescription('"linkage_alarm" is triggered'),
            e.battery(),
            e.battery_voltage(),
            e.power_outage_count(false),
        ],
        meta: { battery: { voltageToPercentage: { min: 2475, max: 3000 } } },
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            await endpoint.write("manuSpecificLumi", { 331: { value: 1, type: 0x20 } }, { manufacturerCode: manufacturerCode });
            await endpoint.read("genPowerCfg", ["batteryVoltage"]);
            await endpoint.read("manuSpecificLumi", [0x013a], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x013b], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x013c], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x013d], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x0126], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x014b], { manufacturerCode: manufacturerCode });
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), m.quirkCheckinInterval("1_HOUR"), lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["lumi.lock.v1"],
        model: "A6121",
        vendor: "Xiaomi",
        description: "Vima Smart Lock",
        fromZigbee: [lumi.fromZigbee.lumi_lock_report],
        exposes: [e.text("inserted", ea.STATE)],
        toZigbee: [],
    },
    {
        zigbeeModel: ["lumi.vibration.aq1"],
        model: "DJT11LM",
        vendor: "Aqara",
        description: "Vibration sensor",
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_vibration_analog],
        toZigbee: [lumi.toZigbee.lumi_vibration_sensitivity],
        exposes: [
            e.battery(),
            e.device_temperature(),
            e.vibration(),
            e.action(["vibration", "tilt", "drop"]),
            e.numeric("strength", ea.STATE),
            e.numeric("sensitivity", ea.STATE_SET).withDescription("Sensitivity, 1 = highest, 21 = lowest").withValueMin(1).withValueMax(21),
            e.angle_axis("angle_x"),
            e.angle_axis("angle_y"),
            e.angle_axis("angle_z"),
            e.x_axis(),
            e.y_axis(),
            e.z_axis(),
            e.battery_voltage(),
            e.power_outage_count(false),
        ],
        extend: [m.quirkCheckinInterval("1_HOUR")],
    },
    {
        zigbeeModel: ["lumi.vibration.agl01"],
        model: "DJT12LM",
        vendor: "Aqara",
        description: "Vibration sensor T1",
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiVibration(),
            // lumiMiscellaneous(),
            lumiReportInterval(),
            lumiSensitivityAdjustment(),
            lumiBattery({ voltageToPercentage: { min: 2850, max: 3000 } }),
            lumiZigbeeOTA(),
            m.quirkCheckinInterval("1_HOUR"),
        ],
    },
    {
        zigbeeModel: ["lumi.vibration.agl002"],
        model: "DWZTCGQ11LM",
        vendor: "Aqara",
        description: "Multi-state sensor P100",
        extend: [
            lumi.lumiModernExtend.addManuSpecificLumiCluster(),
            lumi.lumiModernExtend.lumiPreventReset(),
            lumi.lumiModernExtend.lumiBattery({
                voltageAttribute: 0x17,
                percentageAttribute: 0x18,
            }),
            lumi.lumiModernExtend.lumiZigbeeOTA(),
            m.enumLookup({
                name: "device_mode",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0116, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
                lookup: { door_window: 3, object: 5 },
                description: "Device operating mode",
                access: "STATE_SET",
                entityCategory: "config",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.enumLookup({
                name: "door_window_type",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x01eb, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
                lookup: { casement_window: 1, hopper_window: 2, composite_window: 3, hinged_door: 4 },
                description: "Door/window type (applies when device_mode = door_window)",
                access: "STATE_SET",
                label: "Door/window type",
                entityCategory: "config",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "sensitivity",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x010c, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
                valueMin: 1,
                valueMax: 10,
                description: "Detection sensitivity (1 = low, 10 = high)",
                access: "STATE_SET",
                entityCategory: "config",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "report_interval",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x01ec, type: zigbee_herdsman_1.Zcl.DataType.UINT32 },
                unit: "s",
                valueMin: 5,
                valueMax: 300,
                description: "Reporting interval in seconds. Also drives the device's 802.15.4 poll cadence — lower values are more responsive but reduce battery life.",
                access: "STATE_SET",
                entityCategory: "config",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.binary({
                name: "orientation_detection",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x01f0, type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN },
                valueOn: ["ON", 1],
                valueOff: ["OFF", 0],
                description: "Enable orientation event detection (object mode, requires device button press)",
                access: "STATE_SET",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.binary({
                name: "movement_detection",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x01ed, type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN },
                valueOn: ["ON", 1],
                valueOff: ["OFF", 0],
                description: "Enable movement event detection (object mode, requires device button press)",
                access: "STATE_SET",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.binary({
                name: "fall_detection",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x01d8, type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN },
                valueOn: ["ON", 1],
                valueOff: ["OFF", 0],
                description: "Enable fall event detection (object mode, requires device button press)",
                access: "STATE_SET",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.binary({
                name: "vibration_detection",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0107, type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN },
                valueOn: ["ON", 1],
                valueOff: ["OFF", 0],
                description: "Enable vibration event detection (object mode, requires device button press)",
                access: "STATE_SET",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.binary({
                name: "triple_tap_detection",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x01ef, type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN },
                valueOn: ["ON", 1],
                valueOff: ["OFF", 0],
                description: "Enable triple-tap event detection (object mode, requires device button press)",
                access: "STATE_SET",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.enumLookup({
                name: "orientation",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x01f1, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
                lookup: { face_up: 1, face_down: 2, vertical: 3, tilt: 4 },
                description: "Last reported orientation (relevant when action = orientation)",
                access: "STATE",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            // Primary actions on closuresDoorLock 0x0055
            m.actionEnumLookup({
                cluster: "closuresDoorLock",
                attribute: { ID: 0x0055, type: zigbee_herdsman_1.Zcl.DataType.UINT16 },
                actionLookup: { triple_tap: 0, movement: 1, vibration: 2, orientation: 3, fall: 4 },
                extraActions: ["static"],
            }),
            // and the static-state edge on manuSpecificLumi 0x01F3, declared as an
            // extraAction above. Emits true transition only (the device does
            // report the false transition)
            lumi.lumiModernExtend.lumiStaticStateAction(),
            m.binary({
                name: "contact",
                cluster: "genOnOff",
                attribute: "onOff",
                valueOn: [false, 1],
                valueOff: [true, 0],
                description: "Door/window state (door/window mode only)",
                access: "STATE",
            }),
            m.enumLookup({
                name: "device_posture",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x01ee, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
                lookup: { normal: 1, abnormal: 2 },
                description: "Door/window mounting orientation check — 'abnormal' if the sensor is incorrectly installed or needs calibration",
                access: "STATE",
                entityCategory: "diagnostic",
                zigbeeCommandOptions: { manufacturerCode },
            }),
        ],
    },
    {
        zigbeeModel: ["lumi.curtain"],
        model: "ZNCLDJ11LM",
        description: "Curtain controller",
        vendor: "Aqara",
        fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_curtain_position, lumi.fromZigbee.lumi_curtain_position_tilt],
        toZigbee: [lumi.toZigbee.lumi_curtain_position_state, lumi.toZigbee.lumi_curtain_options],
        exposes: [
            e.cover_position().setAccess("state", ea.ALL),
            e.binary("running", ea.STATE, true, false).withDescription("Whether the motor is moving or not"),
            e.enum("motor_state", ea.STATE, ["stopped", "opening", "closing"]).withDescription("Motor state"),
        ],
        extend: [lumiZigbeeOTA(), lumiReadPositionOnReport("genBasic")],
    },
    {
        zigbeeModel: ["lumi.curtain.aq2"],
        model: "ZNGZDJ11LM",
        description: "Roller shade controller",
        vendor: "Aqara",
        whiteLabel: [{ vendor: "Aqara", model: "SRSC-M01" }],
        fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_curtain_position, lumi.fromZigbee.lumi_curtain_position_tilt],
        toZigbee: [lumi.toZigbee.lumi_curtain_position_state, lumi.toZigbee.lumi_curtain_options],
        exposes: [
            e.cover_position().setAccess("state", ea.ALL),
            e.binary("running", ea.STATE, true, false).withDescription("Whether the motor is moving or not"),
        ],
        extend: [lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["lumi.curtain.vagl02"],
        model: "ZNGZDJ16LM",
        description: "Roller shade controller T1C",
        vendor: "Aqara",
        fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_curtain_position, lumi.fromZigbee.lumi_curtain_position_tilt],
        toZigbee: [lumi.toZigbee.lumi_curtain_position_state, lumi.toZigbee.lumi_curtain_options],
        exposes: [
            e.cover_position().setAccess("state", ea.ALL),
            e.binary("running", ea.STATE, true, false).withDescription("Whether the motor is moving or not"),
        ],
        extend: [lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["lumi.curtain.hagl04"],
        model: "ZNCLDJ12LM",
        vendor: "Aqara",
        description: "Curtain controller B1",
        fromZigbee: [
            lumi.fromZigbee.lumi_basic,
            lumi.fromZigbee.lumi_curtain_position,
            lumi.fromZigbee.lumi_curtain_position_tilt,
            lumi.fromZigbee.lumi_curtain_status,
        ],
        toZigbee: [lumi.toZigbee.lumi_curtain_position_state, lumi.toZigbee.lumi_curtain_options],
        exposes: [
            e.cover_position().setAccess("state", ea.ALL),
            e.battery(),
            e.binary("running", ea.STATE, true, false).withDescription("Whether the motor is moving or not"),
            e.enum("motor_state", ea.STATE, ["closing", "opening", "stopped"]).withDescription("The current state of the motor."),
            e.power_outage_count(),
        ],
        extend: [lumiZigbeeOTA(), lumiReadPositionOnReport("genAnalogOutput")],
    },
    {
        zigbeeModel: ["lumi.curtain.hagl07"],
        model: "ZNCLDJ14LM",
        vendor: "Aqara",
        description: "Curtain controller C2",
        fromZigbee: [
            lumi.fromZigbee.lumi_basic,
            lumi.fromZigbee.lumi_curtain_position,
            lumi.fromZigbee.lumi_curtain_status,
            lumi.fromZigbee.lumi_curtain_options,
        ],
        toZigbee: [
            lumi.toZigbee.lumi_curtain_position_state,
            lumi.toZigbee.lumi_curtain_hand_open,
            lumi.toZigbee.lumi_curtain_reverse,
            lumi.toZigbee.lumi_curtain_limits_calibration_ZNCLDJ14LM,
        ],
        exposes: [
            e.cover_position().setAccess("state", ea.ALL),
            e.binary("reverse_direction", ea.ALL, true, false).withDescription("Whether the curtain direction is inverted"),
            e.binary("hand_open", ea.ALL, true, false).withDescription("Pulling curtains by hand starts the motor"),
            e.binary("running", ea.STATE, true, false).withDescription("Whether the motor is moving or not"),
            e.enum("motor_state", ea.STATE, ["closing", "opening", "stopped"]).withDescription("The current state of the motor."),
            e.power_outage_count(),
        ],
        extend: [lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["lumi.curtain.acn04"],
        model: "ZNCLDJ01LM",
        vendor: "Aqara",
        description: "Curtain controller C3",
        toZigbee: [lumi.toZigbee.lumi_curtain_limits_calibration, lumi.toZigbee.lumi_curtain_automatic_calibration_ZNCLDJ01LM],
        exposes: [
            e.enum("limits_calibration", ea.SET, ["start", "end", "reset"]).withDescription("Calibrate the position limits"),
            e
                .enum("automatic_calibration", ea.SET, ["calibrate"])
                .withDescription("Performs an automatic calibration process similar to Aqara’s method to set curtain limits."),
        ],
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            m.windowCovering({ controls: ["lift"], coverInverted: true, configureReporting: true }),
            lumiCurtainSpeed(),
            lumiCurtainManualOpenClose(),
            lumiCurtainAdaptivePullingSpeed(),
            lumiCurtainManualStop(),
            lumiCurtainReverse(),
            lumiCurtainStatus(),
            lumiCurtainLastManualOperation(),
            lumiCurtainPosition(),
            lumiCurtainTraverseTime(),
            lumiCurtainCalibrationStatus(),
            lumiCurtainCalibrated(),
            lumiCurtainIdentifyBeep(),
            m.identify(),
            lumiZigbeeOTA(),
        ],
    },
    {
        zigbeeModel: ["lumi.curtain.acn018"],
        model: "C200",
        vendor: "Aqara",
        description: "Curtain motor",
        toZigbee: [lumi.toZigbee.lumi_curtain_limits_calibration, lumi.toZigbee.lumi_curtain_automatic_calibration_ZNCLDJ01LM],
        exposes: [
            e.enum("limits_calibration", ea.SET, ["start", "end", "reset"]).withDescription("Calibrate the position limits"),
            e
                .enum("automatic_calibration", ea.SET, ["calibrate"])
                .withDescription("Performs an automatic calibration process similar to Aqara’s method to set curtain limits."),
        ],
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            m.windowCovering({ controls: ["lift"], coverInverted: true, configureReporting: true }),
            lumiCurtainSpeed(),
            lumiCurtainManualOpenClose(),
            lumiCurtainAdaptivePullingSpeed(),
            lumiCurtainManualStop(),
            lumiCurtainReverse(),
            lumiCurtainStatus(),
            lumiCurtainLastManualOperation(),
            lumiCurtainPosition(),
            lumiCurtainTraverseTime(),
            lumiCurtainCalibrationStatus(),
            lumiCurtainCalibrated(),
            lumiCurtainIdentifyBeep(),
            m.identify(),
            lumiZigbeeOTA(),
        ],
    },
    {
        zigbeeModel: ["lumi.curtain.acn002"],
        model: "ZNJLBL01LM",
        description: "Roller shade driver E1",
        vendor: "Aqara",
        whiteLabel: [{ vendor: "Aqara", model: "RSD-M01" }],
        fromZigbee: [lumi.fromZigbee.lumi_curtain_position, lumi.fromZigbee.lumi_curtain_status, lumi.fromZigbee.lumi_specific],
        ota: true,
        toZigbee: [
            lumi.toZigbee.lumi_curtain_position_state,
            lumi.toZigbee.lumi_curtain_battery,
            lumi.toZigbee.lumi_curtain_charging_status,
            lumi.toZigbee.lumi_curtain_reverse,
        ],
        exposes: [
            e.cover_position().setAccess("state", ea.ALL),
            e.battery().withAccess(ea.STATE_GET),
            e.device_temperature(),
            e.binary("charging_status", ea.STATE_GET, true, false).withDescription("The current charging status."),
            e.binary("reverse_direction", ea.ALL, true, false).withDescription("Whether the curtain direction is inverted"),
            e.enum("motor_state", ea.STATE, ["closing", "opening", "stopped", "blocked"]).withDescription("The current state of the motor."),
            e.binary("running", ea.STATE, true, false).withDescription("Whether the motor is moving or not"),
        ],
        configure: async (device, coordinatorEndpoint) => {
            device.powerSource = "Battery";
            device.save();
            const endpoint = device.getEndpoint(1);
            await endpoint.read("manuSpecificLumi", [0x040a], { manufacturerCode: manufacturerCode });
        },
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            m.quirkAddEndpointCluster({
                endpointID: 1,
                inputClusters: ["manuSpecificLumi"],
            }),
            lumiZigbeeOTA(),
            lumiMotorSpeed(),
            lumiReadPositionOnReport("genMultistateOutput"),
        ],
    },
    {
        // 'lumi.curtain.acn003' - CN version (ZNCLBL01LM), 'lumi.curtain.agl001' - global version (CM-M01)
        zigbeeModel: ["lumi.curtain.acn003", "lumi.curtain.agl001"],
        model: "ZNCLBL01LM",
        vendor: "Aqara",
        whiteLabel: [
            { vendor: "Aqara", model: "CM-M01" },
            { vendor: "Aqara", model: "CM-M01R" },
        ],
        description: "Curtain driver E1",
        fromZigbee: [fz.battery, lumi.fromZigbee.lumi_curtain_position_tilt, lumi.fromZigbee.lumi_specific, fz.power_source],
        toZigbee: [
            lumi.toZigbee.lumi_curtain_position_state,
            lumi.toZigbee.lumi_curtain_battery_voltage,
            lumi.toZigbee.lumi_curtain_hooks_lock,
            lumi.toZigbee.lumi_curtain_hooks_state,
            lumi.toZigbee.lumi_curtain_hand_open,
            lumi.toZigbee.lumi_curtain_limits_calibration,
            tz.power_source,
            tz.battery_percentage_remaining,
        ],
        exposes: [
            e.cover_position().setAccess("state", ea.ALL),
            e.binary("hand_open", ea.ALL, true, false).withDescription("Pulling curtains by hand starts the motor"),
            e.enum("limits_calibration", ea.SET, ["start", "end", "reset"]).withDescription("Calibrate the position limits"),
            e.battery().withAccess(ea.STATE_GET),
            e.battery_voltage().withAccess(ea.STATE_GET),
            e.device_temperature(),
            e.illuminance(),
            e.action(["manual_open", "manual_close"]),
            e.enum("motor_state", ea.STATE, ["stopped", "opening", "closing", "pause"]).withDescription("Motor state"),
            e.binary("running", ea.STATE, true, false).withDescription("Whether the motor is moving or not"),
            e.enum("hooks_lock", ea.STATE_SET, ["LOCK", "UNLOCK"]).withDescription("Lock the curtain driver hooks"),
            e.enum("hooks_state", ea.STATE_GET, ["unlocked", "locked", "locking", "unlocking"]).withDescription("Hooks state"),
            e.numeric("target_position", ea.STATE).withUnit("%").withDescription("Target position"),
            e.enum("power_source", ea.STATE_GET, ["battery", "dc_source"]).withDescription("The current power source"),
            e.binary("charging", ea.STATE_GET, true, false).withDescription("The current charging state"),
        ],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            // Read correct version to replace version advertised by `genBasic` and `genOta`:
            // https://github.com/Koenkk/zigbee2mqtt/issues/15745
            await endpoint.read("manuSpecificLumi", [0x00ee], { manufacturerCode: manufacturerCode });
            await endpoint.read("genPowerCfg", ["batteryPercentageRemaining"]);
            await endpoint.read("manuSpecificLumi", [0x040b], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x0428], { manufacturerCode: manufacturerCode });
            await endpoint.read("genBasic", ["powerSource"]);
            await endpoint.read("closuresWindowCovering", ["currentPositionLiftPercentage"]);
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["lumi.relay.c2acn01"],
        model: "LLKZMK11LM",
        vendor: "Aqara",
        description: "Dual relay module",
        fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_power, fz.ignore_multistate_report, fz.on_off, lumi.fromZigbee.lumi_basic_raw],
        meta: { multiEndpoint: true },
        toZigbee: [tz.on_off, lumi.toZigbee.lumi_interlock, lumi.toZigbee.lumi_power, lumi.toZigbee.lumi_switch_power_outage_memory],
        endpoint: (device) => {
            return { l1: 1, l2: 2 };
        },
        exposes: [
            e.power().withAccess(ea.STATE_GET),
            e.energy(),
            e.device_temperature(),
            e.voltage(),
            e.current(),
            e.switch().withEndpoint("l1"),
            e.switch().withEndpoint("l2"),
            e.power_outage_count(false),
            e.power_outage_memory(),
            e.binary("interlock", ea.STATE_SET, true, false).withDescription("Enabling prevents both relais being on at the same time"),
        ],
        extend: [lumiZigbeeOTA(), m.forcePowerSource({ powerSource: "Mains (single phase)" })],
    },
    {
        zigbeeModel: ["lumi.switch.acn047"],
        model: "LLKZMK12LM",
        vendor: "Aqara",
        whiteLabel: [{ vendor: "Aqara", model: "DCM-K01" }],
        description: "Dual relay module T2",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_specific, lumi.fromZigbee.lumi_power],
        toZigbee: [tz.on_off],
        meta: { multiEndpoint: true, multiEndpointSkip: ["power", "energy"] },
        endpoint: (device) => {
            return { l1: 1, l2: 2 };
        },
        exposes: [
            e.switch().withEndpoint("l1"),
            e.switch().withEndpoint("l2"),
            e.power(),
            e.current(),
            e.energy(),
            e.voltage(),
            e.device_temperature(),
        ],
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiSwitchType(),
            lumiPowerOnBehavior({ lookup: { on: 0, previous: 1, off: 2, toggle: 3 } }),
            lumiOperationMode({ description: "Decoupled mode for 1st relay", endpointName: "l1" }),
            lumiOperationMode({ description: "Decoupled mode for 2nd relay", endpointName: "l2" }),
            lumiAction({ endpointNames: ["l1", "l2"] }),
            m.binary({
                name: "interlock",
                valueOn: ["ON", 1],
                valueOff: ["OFF", 0],
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x02d0, type: 0x10 },
                description: "Enabling prevents both relays being on at the same time (Interlock)",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.enumLookup({
                name: "mode",
                lookup: { power: 0, pulse: 1, dry: 3 },
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0289, type: 0x20 },
                description: "Work mode: Power mode, Dry mode with impulse, Dry mode",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "pulse_length",
                valueMin: 200,
                valueMax: 2000,
                unit: "ms",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x00eb, type: 0x21 },
                description: "Impulse length in Dry mode with impulse",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            lumiZigbeeOTA(),
        ],
    },
    {
        zigbeeModel: ["lumi.lock.acn02"],
        model: "ZNMS12LM",
        description: "Smart door lock S2",
        vendor: "Aqara",
        fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_door_lock_report, lumi.fromZigbee.lumi_door_lock_low_battery],
        toZigbee: [],
        exposes: [
            e.battery(),
            e.battery_voltage(),
            e.battery_low(),
            e.binary("state", ea.STATE, "UNLOCK", "LOCK"),
            e.binary("reverse", ea.STATE, "UNLOCK", "LOCK"),
            e.enum("action", ea.STATE, [
                "finger_not_match",
                "password_not_match",
                "reverse_lock",
                "reverse_lock_cancel",
                "locked",
                "lock_opened",
                "finger_add",
                "finger_delete",
                "password_add",
                "password_delete",
                "lock_opened_inside",
                "lock_opened_outside",
                "ring_bell",
                "change_language_to",
                "finger_open",
                "password_open",
                "door_closed",
            ]),
        ],
        meta: { battery: { voltageToPercentage: { min: 3000, max: 4200 } } },
        extend: [m.quirkCheckinInterval("1_HOUR"), lumiZigbeeOTA(), m.forceDeviceType({ type: "EndDevice" })],
    },
    {
        zigbeeModel: ["lumi.lock.acn03"],
        model: "ZNMS13LM",
        description: "Smart door lock S2 Pro",
        vendor: "Aqara",
        fromZigbee: [lumi.fromZigbee.lumi_door_lock_report],
        toZigbee: [],
        exposes: [
            e.binary("state", ea.STATE, "UNLOCK", "LOCK"),
            e.binary("reverse", ea.STATE, "UNLOCK", "LOCK"),
            e.enum("action", ea.STATE, [
                "finger_not_match",
                "password_not_match",
                "reverse_lock",
                "reverse_lock_cancel",
                "locked",
                "lock_opened",
                "finger_add",
                "finger_delete",
                "password_add",
                "password_delete",
                "lock_opened_inside",
                "lock_opened_outside",
                "ring_bell",
                "change_language_to",
                "finger_open",
                "password_open",
                "door_closed",
            ]),
        ],
        extend: [m.quirkCheckinInterval("1_HOUR"), m.forceDeviceType({ type: "EndDevice" })],
    },
    {
        zigbeeModel: ["lumi.lock.aq1"],
        model: "ZNMS11LM",
        description: "Smart door lock",
        vendor: "Aqara",
        fromZigbee: [lumi.fromZigbee.lumi_door_lock_report],
        toZigbee: [],
        exposes: [
            e.binary("state", ea.STATE, "UNLOCK", "LOCK"),
            e.binary("reverse", ea.STATE, "UNLOCK", "LOCK"),
            e.enum("action", ea.STATE, [
                "finger_not_match",
                "password_not_match",
                "reverse_lock",
                "reverse_lock_cancel",
                "locked",
                "lock_opened",
                "finger_add",
                "finger_delete",
                "password_add",
                "password_delete",
                "lock_opened_inside",
                "lock_opened_outside",
                "ring_bell",
                "change_language_to",
                "finger_open",
                "password_open",
                "door_closed",
            ]),
        ],
        extend: [m.quirkCheckinInterval("1_HOUR"), lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["lumi.remote.b286opcn01"],
        model: "WXCJKG11LM",
        vendor: "Aqara",
        description: "Opple wireless switch (single band)",
        fromZigbee: [
            lumi.fromZigbee.lumi_action_on,
            lumi.fromZigbee.lumi_action_off,
            fz.battery,
            lumi.fromZigbee.lumi_action_multistate,
            lumi.fromZigbee.lumi_specific,
        ],
        exposes: [
            e.battery(),
            e.battery_voltage(),
            e.action([
                "button_1_hold",
                "button_1_release",
                "button_1_single",
                "button_1_double",
                "button_1_triple",
                "button_2_hold",
                "button_2_release",
                "button_2_single",
                "button_2_double",
                "button_2_triple",
            ]),
            e
                .enum("operation_mode", ea.ALL, ["command", "event"])
                .withDescription('Operation mode, select "command" to enable bindings (wake up the device before changing modes!)'),
        ],
        toZigbee: [lumi.toZigbee.lumi_operation_mode_opple],
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), m.quirkCheckinInterval("1_HOUR")],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            await endpoint.write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode });
            await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff", "genPowerCfg"]);
        },
    },
    {
        zigbeeModel: ["lumi.remote.b486opcn01"],
        model: "WXCJKG12LM",
        vendor: "Aqara",
        description: "Opple wireless switch (double band)",
        fromZigbee: [
            lumi.fromZigbee.lumi_action_on,
            lumi.fromZigbee.lumi_action_off,
            lumi.fromZigbee.lumi_action_step,
            lumi.fromZigbee.lumi_action_step_color_temp,
            fz.battery,
            lumi.fromZigbee.lumi_action_multistate,
            lumi.fromZigbee.lumi_specific,
        ],
        exposes: [
            e.battery(),
            e.battery_voltage(),
            e.action([
                "button_1_hold",
                "button_1_release",
                "button_1_single",
                "button_1_double",
                "button_1_triple",
                "button_2_hold",
                "button_2_release",
                "button_2_single",
                "button_2_double",
                "button_2_triple",
                "button_3_hold",
                "button_3_release",
                "button_3_single",
                "button_3_double",
                "button_3_triple",
                "button_4_hold",
                "button_4_release",
                "button_4_single",
                "button_4_double",
                "button_4_triple",
            ]),
            e
                .enum("operation_mode", ea.ALL, ["command", "event"])
                .withDescription('Operation mode, select "command" to enable bindings (wake up the device before changing modes!)'),
        ],
        toZigbee: [lumi.toZigbee.lumi_operation_mode_opple],
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), m.quirkCheckinInterval("1_HOUR")],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            await endpoint.write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode });
            await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff", "genLevelCtrl", "lightingColorCtrl", "genPowerCfg"]);
        },
    },
    {
        zigbeeModel: ["lumi.remote.b686opcn01"],
        model: "WXCJKG13LM",
        vendor: "Aqara",
        description: "Opple wireless switch (triple band)",
        fromZigbee: [
            lumi.fromZigbee.lumi_action_on,
            lumi.fromZigbee.lumi_action_off,
            lumi.fromZigbee.lumi_action_step,
            lumi.fromZigbee.lumi_action_move,
            lumi.fromZigbee.lumi_action_stop,
            lumi.fromZigbee.lumi_action_step_color_temp,
            lumi.fromZigbee.lumi_action_move_color_temp,
            fz.battery,
            lumi.fromZigbee.lumi_action_multistate,
            lumi.fromZigbee.lumi_specific,
        ],
        exposes: [
            e.battery(),
            e.battery_voltage(),
            e.action([
                "button_1_hold",
                "button_1_release",
                "button_1_single",
                "button_1_double",
                "button_1_triple",
                "button_2_hold",
                "button_2_release",
                "button_2_single",
                "button_2_double",
                "button_2_triple",
                "button_3_hold",
                "button_3_release",
                "button_3_single",
                "button_3_double",
                "button_3_triple",
                "button_4_hold",
                "button_4_release",
                "button_4_single",
                "button_4_double",
                "button_4_triple",
                "button_5_hold",
                "button_5_release",
                "button_5_single",
                "button_5_double",
                "button_5_triple",
                "button_6_hold",
                "button_6_release",
                "button_6_single",
                "button_6_double",
                "button_6_triple",
            ]),
            e
                .enum("operation_mode", ea.ALL, ["command", "event"])
                .withDescription('Operation mode, select "command" to enable bindings (wake up the device before changing modes!)'),
            e.power_outage_count(false),
        ],
        toZigbee: [lumi.toZigbee.lumi_operation_mode_opple],
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), m.quirkCheckinInterval("1_HOUR")],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            await endpoint.write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode });
            await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff", "genLevelCtrl", "lightingColorCtrl", "genPowerCfg"]);
        },
    },
    {
        zigbeeModel: ["lumi.sen_ill.mgl01"],
        model: "GZCGQ01LM",
        vendor: "Xiaomi",
        whiteLabel: [{ vendor: "Xiaomi", model: "YTC4043GL" }],
        description: "Mi light sensor",
        fromZigbee: [fz.battery, lumi.fromZigbee.lumi_specific],
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), m.quirkCheckinInterval("1_HOUR"), m.illuminance()],
        exposes: [e.battery(), e.battery_voltage()],
    },
    {
        zigbeeModel: ["lumi.light.acn128"],
        model: "TDL01LM",
        vendor: "Aqara",
        description: "Spotlight T3",
        whiteLabel: [
            { vendor: "Aqara", model: "MZSD11LM" },
            { vendor: "Aqara", model: "MZSD12LM" },
            { vendor: "Aqara", model: "MZTD11LM" },
        ],
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiZigbeeOTA(),
            lumiLight({
                color: false,
                colorTemp: true,
                colorTempRange: [166, 370],
                powerOutageMemory: "enum",
                levelConfig: { features: ["on_transition_time", "off_transition_time", "on_level"] },
            }),
            m.numeric({
                name: "min_brightness",
                valueMin: 0,
                valueMax: 99,
                unit: "%",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0515, type: 0x20 },
                description: "Minimum brightness level",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "max_brightness",
                valueMin: 1,
                valueMax: 100,
                unit: "%",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0516, type: 0x20 },
                description: "Maximum brightness level",
                zigbeeCommandOptions: { manufacturerCode },
            }),
        ],
    },
    {
        zigbeeModel: ["lumi.light.rgbac1"],
        model: "ZNTGMK11LM",
        vendor: "Aqara",
        description: "Smart RGBW light controller",
        extend: [m.light({ colorTemp: { range: undefined }, color: { modes: ["xy", "hs"] } }), lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["lumi.light.cwacn1"],
        model: "ZNTGMK12LM",
        vendor: "Aqara",
        description: "Smart color temperature light controller",
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiLight({ colorTemp: true, powerOutageCount: true, deviceTemperature: true }),
            lumiZigbeeOTA(),
        ],
    },
    {
        zigbeeModel: ["lumi.light.cbacn1"],
        model: "HLQDQ01LM",
        vendor: "Aqara",
        description: "Smart LED controller",
        extend: [m.light(), lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["lumi.light.acn004"],
        model: "SSWQD02LM",
        vendor: "Aqara",
        description: "Smart dimmer controller T1 Pro",
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA(), lumiLight({ colorTemp: true, powerOutageMemory: "switch" })],
    },
    {
        zigbeeModel: ["lumi.dimmer.acn003"],
        model: "ZNDDQDQ11LM",
        vendor: "Aqara",
        description: "T1 light strip controller",
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumi.lumiModernExtend.lumiLight({ colorTemp: true, colorTempRange: [154, 370], color: false, powerOutageMemory: "enum" }),
            m.identify(),
            m.forcePowerSource({ powerSource: "Mains (single phase)" }),
            lumi.lumiModernExtend.lumiZigbeeOTA(),
            lumi.lumiModernExtend.lumiDimmingRangeMin(),
            lumi.lumiModernExtend.lumiDimmingRangeMax(),
            lumi.lumiModernExtend.lumiOffOnDuration(),
            lumi.lumiModernExtend.lumiOnOffDuration(),
            lumi.lumiModernExtend.lumiTransitionCurveCurvature(),
        ],
    },
    {
        zigbeeModel: ["lumi.dimmer.acn004"],
        model: "ZNDDQDQ12LM",
        vendor: "Aqara",
        description: "T1 light strip controller",
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumi.lumiModernExtend.lumiLight({ colorTemp: true, colorTempRange: [154, 370], color: false, powerOutageMemory: "enum" }),
            m.identify(),
            m.forcePowerSource({ powerSource: "Mains (single phase)" }),
            lumi.lumiModernExtend.lumiZigbeeOTA(),
            lumi.lumiModernExtend.lumiDimmingRangeMin(),
            lumi.lumiModernExtend.lumiDimmingRangeMax(),
            lumi.lumiModernExtend.lumiOffOnDuration(),
            lumi.lumiModernExtend.lumiOnOffDuration(),
            lumi.lumiModernExtend.lumiTransitionCurveCurvature(),
        ],
    },
    {
        zigbeeModel: ["lumi.dimmer.acn005"],
        model: "ZNDDQDQ13LM",
        vendor: "Aqara",
        description: "T1 light strip controller",
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumi.lumiModernExtend.lumiLight({ colorTemp: true, colorTempRange: [154, 370], color: false, powerOutageMemory: "enum" }),
            m.identify(),
            m.forcePowerSource({ powerSource: "Mains (single phase)" }),
            lumi.lumiModernExtend.lumiZigbeeOTA(),
            lumi.lumiModernExtend.lumiDimmingRangeMin(),
            lumi.lumiModernExtend.lumiDimmingRangeMax(),
            lumi.lumiModernExtend.lumiOffOnDuration(),
            lumi.lumiModernExtend.lumiOnOffDuration(),
            lumi.lumiModernExtend.lumiTransitionCurveCurvature(),
        ],
    },
    {
        zigbeeModel: ["lumi.light.acn026", "lumi.light.acn024", "lumi.light.acn025", "lumi.light.acn023"],
        model: "SSWQD03LM",
        vendor: "Aqara",
        description: "Spotlight T2",
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA(), lumiLight({ colorTemp: true, powerOutageMemory: "switch" })],
    },
    {
        zigbeeModel: ["lumi.light.acn036"],
        model: "SSWQDYH02",
        vendor: "Aqara",
        description: "Spotlight V1",
        whiteLabel: [
            { vendor: "Aqara", model: "ZNSD01LM" },
            { vendor: "Aqara", model: "ZNSD02LM" },
            { vendor: "Aqara", model: "ZNSD03LM" },
        ],
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiZigbeeOTA(),
            lumiLight({
                color: false,
                colorTemp: true,
                colorTempRange: [166, 370],
                powerOutageMemory: "enum",
                levelConfig: { features: ["on_transition_time", "off_transition_time", "on_level"] },
            }),
            m.numeric({
                name: "min_brightness",
                valueMin: 0,
                valueMax: 99,
                unit: "%",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0515, type: 0x20 },
                description: "Minimum brightness level",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "max_brightness",
                valueMin: 1,
                valueMax: 100,
                unit: "%",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0516, type: 0x20 },
                description: "Maximum brightness level",
                zigbeeCommandOptions: { manufacturerCode },
            }),
        ],
    },
    {
        zigbeeModel: ["lumi.light.acn040"],
        model: "SSWQD22LM",
        vendor: "Aqara",
        description: "Spotlight T2 Pro",
        whiteLabel: [
            { vendor: "Aqara", model: "ZNSD07LM" },
            { vendor: "Aqara", model: "ZNSD08LM" },
            { vendor: "Aqara", model: "ZNSD09LM" },
            { vendor: "Aqara", model: "ZNSD10LM" },
        ],
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiZigbeeOTA(),
            lumiLight({
                color: false,
                colorTemp: true,
                colorTempRange: [166, 370],
                levelConfig: { features: ["on_transition_time", "off_transition_time", "on_level"] },
            }),
            m.numeric({
                name: "min_brightness",
                valueMin: 0,
                valueMax: 99,
                unit: "%",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0515, type: 0x20 },
                description: "Minimum brightness level",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "max_brightness",
                valueMin: 1,
                valueMax: 100,
                unit: "%",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0516, type: 0x20 },
                description: "Maximum brightness level",
                zigbeeCommandOptions: { manufacturerCode },
            }),
        ],
    },
    {
        zigbeeModel: ["lumi.switch.n0agl1"],
        model: "SSM-U01",
        vendor: "Aqara",
        description: "Single switch module T1 (with neutral)",
        // Ignore energy metering reports, rely on aqara_opple: https://github.com/Koenkk/zigbee2mqtt/issues/10709
        fromZigbee: [
            fz.on_off,
            fz.device_temperature,
            lumi.fromZigbee.lumi_specific,
            fz.ignore_metering,
            fz.ignore_electrical_measurement,
            lumi.fromZigbee.lumi_power,
        ],
        exposes: [
            e.switch(),
            e.energy(),
            e.power(),
            e.device_temperature(),
            e.power_outage_memory(),
            e.power_outage_count(),
            e.switch_type(),
            e.voltage(),
            e.current(),
        ],
        toZigbee: [lumi.toZigbee.lumi_switch_type, tz.on_off, lumi.toZigbee.lumi_switch_power_outage_memory, lumi.toZigbee.lumi_led_disabled_night],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff", "genDeviceTempCfg"]);
            await reporting.onOff(endpoint);
            await reporting.deviceTemperature(endpoint);
        },
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiZigbeeOTA(),
            m.forceDeviceType({ type: "Router" }),
            m.forcePowerSource({ powerSource: "Mains (single phase)" }),
        ],
    },
    {
        zigbeeModel: ["lumi.switch.n0acn2"],
        model: "DLKZMK11LM",
        vendor: "Aqara",
        description: "Single switch module T1 (with neutral), CN",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_specific],
        toZigbee: [
            tz.on_off,
            lumi.toZigbee.lumi_power,
            lumi.toZigbee.lumi_switch_type,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            lumi.toZigbee.lumi_led_disabled_night,
        ],
        exposes: [
            e.switch(),
            e.power().withAccess(ea.STATE_GET),
            e.energy(),
            e.device_temperature().withAccess(ea.STATE),
            e.voltage(),
            e.current(),
            e.power_outage_memory(),
            e.led_disabled_night(),
            e.switch_type(),
        ],
        configure: async (device, coordinatorEndpoint) => {
            await device
                .getEndpoint(1)
                .write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA(), m.forcePowerSource({ powerSource: "Mains (single phase)" })],
    },
    {
        zigbeeModel: ["lumi.switch.l0agl1"],
        model: "SSM-U02",
        vendor: "Aqara",
        description: "Single switch module T1 (no neutral)",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_specific],
        exposes: [e.switch(), e.power_outage_memory(), e.switch_type(), e.power_outage_count(), e.device_temperature()],
        toZigbee: [lumi.toZigbee.lumi_switch_type, tz.on_off, lumi.toZigbee.lumi_switch_power_outage_memory],
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), m.forcePowerSource({ powerSource: "Mains (single phase)" })],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff"]);
            await reporting.onOff(endpoint);
        },
    },
    {
        zigbeeModel: ["lumi.switch.l0acn1"],
        model: "DLKZMK12LM",
        vendor: "Aqara",
        description: "Single switch module T1 (no neutral), CN",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_specific],
        exposes: [e.switch(), e.power_outage_memory(), e.switch_type()],
        toZigbee: [lumi.toZigbee.lumi_switch_type, tz.on_off, lumi.toZigbee.lumi_switch_power_outage_memory],
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), m.forcePowerSource({ powerSource: "Mains (single phase)" })],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff"]);
            await reporting.onOff(endpoint);
        },
    },
    {
        zigbeeModel: ["lumi.switch.n4acn4"],
        model: "ZNCJMB14LM",
        vendor: "Aqara",
        description: "Smart touch panel S1",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_smart_panel_ZNCJMB14LM],
        toZigbee: [tz.on_off, lumi.toZigbee.lumi_smart_panel_ZNCJMB14LM],
        meta: { multiEndpoint: true },
        endpoint: (device) => {
            return { left: 1, center: 2, right: 3 };
        },
        exposes: [
            e.switch().withEndpoint("left"),
            e.switch().withEndpoint("center"),
            e.switch().withEndpoint("right"),
            e.binary("standby_enabled", ea.STATE_SET, true, false).withDescription("Enable standby"),
            e.enum("theme", ea.STATE_SET, ["classic", "concise"]).withDescription("Display theme"),
            e.enum("beep_volume", ea.STATE_SET, ["mute", "low", "medium", "high"]).withDescription("Beep volume"),
            e
                .numeric("lcd_brightness", ea.STATE_SET)
                .withValueMin(1)
                .withValueMax(100)
                .withUnit("%")
                .withDescription("LCD brightness (will not persist if auto-brightness is enabled)"),
            e.enum("language", ea.STATE_SET, ["chinese", "english"]).withDescription("Interface language"),
            e.enum("screen_saver_style", ea.STATE_SET, ["classic", "analog clock"]).withDescription("Screen saver style"),
            e.numeric("standby_time", ea.STATE_SET).withValueMin(0).withValueMax(65534).withUnit("s").withDescription("Display standby time"),
            e.enum("font_size", ea.STATE_SET, ["small", "medium", "large"]).withDescription("Display font size"),
            e.binary("lcd_auto_brightness_enabled", ea.STATE_SET, true, false).withDescription("Enable LCD auto brightness"),
            e.enum("homepage", ea.STATE_SET, ["scene", "feel", "thermostat", "switch"]).withDescription("Default display homepage"),
            e.binary("screen_saver_enabled", ea.STATE_SET, true, false).withDescription("Enable screen saver"),
            e
                .numeric("standby_lcd_brightness", ea.STATE_SET)
                .withValueMin(1)
                .withValueMax(100)
                .withUnit("%")
                .withDescription("Standby LCD brightness"),
            e
                .enum("available_switches", ea.STATE_SET, ["none", "1", "2", "3", "1 and 2", "1 and 3", "2 and 3", "all"])
                .withDescription("Control which switches are available in the switches screen (none disables switches screen)"),
            e
                .composite("switch_1_text_icon", "switch_1_text_icon", ea.STATE_SET)
                .withDescription("Switch 1 text and icon")
                .withFeature(e.enum("switch_1_icon", ea.STATE_SET, ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"]).withDescription("Icon"))
                .withFeature(e.text("switch_1_text", ea.STATE_SET).withDescription("Text")),
            e
                .composite("switch_2_text_icon", "switch_2_text_icon", ea.STATE_SET)
                .withDescription("Switch 2 text and icon")
                .withFeature(e.enum("switch_2_icon", ea.STATE_SET, ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"]).withDescription("Icon"))
                .withFeature(e.text("switch_2_text", ea.STATE_SET).withDescription("Text")),
            e
                .composite("switch_3_text_icon", "switch_3_text_icon", ea.STATE_SET)
                .withDescription("Switch 3 text and icon")
                .withFeature(e.enum("switch_3_icon", ea.STATE_SET, ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"]).withDescription("Icon"))
                .withFeature(e.text("switch_3_text", ea.STATE_SET).withDescription("Text")),
        ],
        configure: async (device, coordinatorEndpoint) => {
            await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ["genOnOff"]);
            await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ["genOnOff"]);
            await reporting.bind(device.getEndpoint(3), coordinatorEndpoint, ["genOnOff"]);
            await reporting.onOff(device.getEndpoint(1));
            // await reporting.onOff(device.getEndpoint(2)); ToDo: Currently fails
            // await reporting.onOff(device.getEndpoint(3)); ToDo: Currently fails
        },
        extend: [lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["lumi.remote.b186acn03"],
        model: "WXKG05LM",
        vendor: "Aqara",
        description: "Wireless remote switch T1 (single rocker)",
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), m.quirkCheckinInterval("1_HOUR")],
        fromZigbee: [lumi.fromZigbee.lumi_action, lumi.fromZigbee.lumi_action_multistate, fz.battery, lumi.fromZigbee.lumi_specific],
        toZigbee: [],
        exposes: [e.action(["single", "double", "hold"]), e.battery()],
    },
    {
        zigbeeModel: ["lumi.remote.b28ac1"],
        model: "WXKG15LM",
        vendor: "Aqara",
        whiteLabel: [{ vendor: "Aqara", model: "WRS-R02" }],
        description: "Wireless remote switch H1 (double rocker)",
        fromZigbee: [fz.battery, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific, fz.command_toggle],
        toZigbee: [lumi.toZigbee.lumi_switch_click_mode, lumi.toZigbee.lumi_operation_mode_opple],
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } }, multiEndpoint: true },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), m.quirkCheckinInterval("1_HOUR")],
        exposes: [
            e.battery(),
            e.battery_voltage(),
            e.action([
                "single_left",
                "single_right",
                "single_both",
                "double_left",
                "double_right",
                "double_both",
                "triple_left",
                "triple_right",
                "triple_both",
                "hold_left",
                "hold_right",
                "hold_both",
            ]),
            e
                .enum("click_mode", ea.ALL, ["fast", "multi"])
                .withDescription("Click mode, fast: only supports single click which will be send immediately after clicking." +
                "multi: supports more events like double and hold"),
            e
                .enum("operation_mode", ea.ALL, ["command", "event"])
                .withDescription('Operation mode, select "command" to enable bindings (wake up the device before changing modes!)'),
        ],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint1 = device.getEndpoint(1);
            const endpoint2 = device.getEndpoint(3);
            // set "event" mode
            await endpoint1.write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode });
            // turn on the "multiple clicks" mode, otherwise the only "single click" events.
            // if value is 1 - there will be single clicks, 2 - multiple.
            await endpoint1.write("manuSpecificLumi", { 293: { value: 0x02, type: 0x20 } }, { manufacturerCode: manufacturerCode });
            await reporting.bind(endpoint1, coordinatorEndpoint, ["genOnOff", "genPowerCfg"]);
            await reporting.bind(endpoint2, coordinatorEndpoint, ["genOnOff"]);
            // TODO/BUG:
            // Did not understand how to separate the left and right keys in command mode -
            // the "toggleCommand" always arrives from the first endpoint
        },
    },
    {
        zigbeeModel: ["lumi.switch.b1lc04"],
        model: "QBKG38LM",
        vendor: "Aqara",
        description: "Smart wall switch E1 (no neutral, single rocker)",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
        toZigbee: [
            tz.on_off,
            lumi.toZigbee.lumi_switch_operation_mode_opple,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            lumi.toZigbee.lumi_switch_mode_switch,
            lumi.toZigbee.lumi_flip_indicator_light,
        ],
        exposes: [
            e.switch(),
            e.power_outage_memory(),
            e.action(["single", "double"]),
            e.device_temperature(),
            e.flip_indicator_light(),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for button"),
            e
                .enum("mode_switch", ea.ALL, ["anti_flicker_mode", "quick_mode"])
                .withDescription("Anti flicker mode can be used to solve blinking issues of some lights. Quick mode makes the device respond faster."),
        ],
        configure: async (device, coordinatorEndpoint) => {
            await device
                .getEndpoint(1)
                .write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA(), lumiPreventReset()],
    },
    {
        zigbeeModel: ["lumi.switch.b2lc04"],
        model: "QBKG39LM",
        vendor: "Aqara",
        description: "Smart wall switch E1 (no neutral, double rocker)",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
        toZigbee: [
            tz.on_off,
            lumi.toZigbee.lumi_switch_operation_mode_opple,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            lumi.toZigbee.lumi_switch_mode_switch,
            lumi.toZigbee.lumi_flip_indicator_light,
        ],
        meta: { multiEndpoint: true },
        endpoint: (device) => {
            return { left: 1, right: 2 };
        },
        exposes: [
            e.switch().withEndpoint("left"),
            e.switch().withEndpoint("right"),
            e.device_temperature(),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for left button").withEndpoint("left"),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for right button").withEndpoint("right"),
            e
                .enum("mode_switch", ea.ALL, ["anti_flicker_mode", "quick_mode"])
                .withDescription("Anti flicker mode can be used to solve blinking issues of some lights. Quick mode makes the device respond faster."),
            e.action(["single_left", "double_left", "single_right", "double_right", "single_both", "double_both"]),
            e.power_outage_memory(),
            e.flip_indicator_light(),
        ],
        configure: async (device, coordinatorEndpoint) => {
            await device
                .getEndpoint(1)
                .write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA(), lumiPreventReset()],
    },
    {
        zigbeeModel: ["lumi.airmonitor.acn01"],
        model: "VOCKQJK11LM",
        vendor: "Aqara",
        whiteLabel: [{ vendor: "Aqara", model: "AAQS-S01" }],
        description: "TVOC air quality monitor",
        fromZigbee: [fz.battery, lumi.fromZigbee.lumi_specific],
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        exposes: [e.device_temperature(), e.battery(), e.battery_voltage()],
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            m.quirkCheckinInterval("1_HOUR"),
            m.quirkAddEndpointCluster({
                endpointID: 1,
                inputClusters: ["msTemperatureMeasurement", "msRelativeHumidity", "genAnalogInput", "manuSpecificLumi"],
            }),
            lumiAirQuality(),
            lumiVoc(),
            m.temperature(),
            m.humidity(),
            lumiDisplayUnit(),
            lumiOutageCountRestoreBindReporting(),
            lumiZigbeeOTA(),
        ],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            const binds = ["genPowerCfg"];
            await reporting.bind(endpoint, coordinatorEndpoint, binds);
            await reporting.batteryVoltage(endpoint);
        },
    },
    {
        zigbeeModel: ["lumi.switch.b2nc01"],
        model: "QBKG41LM",
        vendor: "Aqara",
        description: "Smart wall switch E1 (with neutral, double rocker)",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
        toZigbee: [
            tz.on_off,
            lumi.toZigbee.lumi_switch_operation_mode_opple,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            lumi.toZigbee.lumi_flip_indicator_light,
        ],
        meta: { multiEndpoint: true },
        endpoint: (device) => {
            return { left: 1, right: 2 };
        },
        exposes: [
            e.switch().withEndpoint("left"),
            e.switch().withEndpoint("right"),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for left button").withEndpoint("left"),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for right button").withEndpoint("right"),
            e.action(["single_left", "double_left", "single_right", "double_right", "single_both", "double_both"]),
            e.power_outage_memory(),
            e.device_temperature(),
            e.flip_indicator_light(),
        ],
        configure: async (device, coordinatorEndpoint) => {
            await device
                .getEndpoint(1)
                .write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA(), lumiPreventReset()],
    },
    {
        zigbeeModel: ["lumi.plug.macn01"],
        model: "ZNCZ15LM",
        vendor: "Aqara",
        description: "Smart plug T1, CN",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_specific],
        toZigbee: [
            tz.on_off,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            lumi.toZigbee.lumi_led_disabled_night,
            lumi.toZigbee.lumi_overload_protection,
            lumi.toZigbee.lumi_socket_button_lock,
        ],
        exposes: [
            e.switch(),
            e.power().withAccess(ea.STATE),
            e.energy(),
            e.device_temperature().withAccess(ea.STATE),
            e.voltage(),
            e.current(),
            e.consumer_connected().withAccess(ea.STATE),
            e.power_outage_memory(),
            e.led_disabled_night(),
            e.button_lock(),
            e.overload_protection(100, 2500),
        ],
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["lumi.switch.b1nc01"],
        model: "QBKG40LM",
        vendor: "Aqara",
        description: "Smart wall switch E1 (with neutral, single rocker)",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
        toZigbee: [
            tz.on_off,
            lumi.toZigbee.lumi_switch_operation_mode_opple,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            lumi.toZigbee.lumi_flip_indicator_light,
        ],
        exposes: [
            e.switch(),
            e.action(["single", "double"]),
            e.power_outage_memory(),
            e.device_temperature(),
            e.flip_indicator_light(),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode"),
        ],
        configure: async (device, coordinatorEndpoint) => {
            await device
                .getEndpoint(1)
                .write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA(), lumiPreventReset()],
    },
    {
        zigbeeModel: ["lumi.remote.b1acn02"],
        model: "WXKG13LM",
        vendor: "Aqara",
        description: "Wireless mini switch T1",
        whiteLabel: [
            { vendor: "Aqara", model: "WB-R02D" },
            { vendor: "Yandex", model: "YNDX-00524" },
        ],
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        fromZigbee: [fz.battery, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
        toZigbee: [],
        exposes: [e.battery(), e.battery_voltage(), e.action(["single", "double", "triple", "quadruple", "quintuple", "hold", "release", "many"])],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint1 = device.getEndpoint(1);
            await endpoint1.write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), m.quirkCheckinInterval("1_HOUR"), lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["lumi.sen_ill.agl01"],
        model: "GZCGQ11LM",
        vendor: "Aqara",
        description: "Light sensor T1",
        fromZigbee: [fz.battery, lumi.fromZigbee.lumi_specific],
        toZigbee: [lumi.toZigbee.lumi_detection_period],
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        exposes: [
            e.battery(),
            e.battery_voltage(),
            e
                .numeric("detection_period", exposes.access.ALL)
                .withValueMin(1)
                .withValueMax(59)
                .withUnit("s")
                .withDescription("Time interval in seconds to report after light changes"),
        ],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            await device
                .getEndpoint(1)
                .write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
            await endpoint.read("manuSpecificLumi", [0x0000], { manufacturerCode: manufacturerCode });
        },
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            m.quirkCheckinInterval("1_HOUR"),
            lumiZigbeeOTA(),
            m.illuminance({ reporting: false }),
        ],
    },
    {
        zigbeeModel: ["lumi.plug.sacn03"],
        model: "QBCZ15LM",
        vendor: "Aqara",
        description: "Smart wall outlet H1 (USB)",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_specific],
        toZigbee: [
            tz.on_off,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            lumi.toZigbee.lumi_led_disabled_night,
            lumi.toZigbee.lumi_button_switch_mode,
            lumi.toZigbee.lumi_overload_protection,
            lumi.toZigbee.lumi_socket_button_lock,
        ],
        meta: { multiEndpoint: true, multiEndpointSkip: ["power", "energy"] },
        endpoint: () => {
            return { relay: 1, usb: 2 };
        },
        exposes: [
            e.switch().withEndpoint("relay"),
            e.switch().withEndpoint("usb"),
            e.power().withAccess(ea.STATE),
            e.energy(),
            e.device_temperature().withAccess(ea.STATE),
            e.voltage(),
            e.current(),
            e.power_outage_memory(),
            e.led_disabled_night(),
            e.button_lock(),
            e
                .enum("button_switch_mode", exposes.access.ALL, ["relay", "relay_and_usb"])
                .withDescription("Control both relay and usb or only the relay with the physical switch button"),
            e.overload_protection(100, 2500),
        ],
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["lumi.magnet.agl02"],
        model: "MCCGQ12LM",
        vendor: "Aqara",
        description: "Door and window sensor T1",
        whiteLabel: [
            { vendor: "Aqara", model: "DW-S03D" },
            { vendor: "Yandex", model: "YNDX-00520" },
        ],
        fromZigbee: [lumi.fromZigbee.lumi_contact, lumi.fromZigbee.lumi_specific, fz.ias_contact_alarm_1],
        toZigbee: [],
        exposes: [e.contact(), e.battery(), e.battery_voltage()],
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), m.quirkCheckinInterval("1_HOUR")],
    },
    {
        zigbeeModel: ["lumi.plug.sacn02"],
        model: "QBCZ14LM",
        vendor: "Aqara",
        description: "Smart wall outlet T1",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_specific],
        toZigbee: [
            tz.on_off,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            lumi.toZigbee.lumi_led_disabled_night,
            lumi.toZigbee.lumi_overload_protection,
            lumi.toZigbee.lumi_socket_button_lock,
        ],
        exposes: [
            e.switch(),
            e.power().withAccess(ea.STATE),
            e.energy(),
            e.device_temperature().withAccess(ea.STATE),
            e.voltage(),
            e.current(),
            e.power_outage_memory(),
            e.led_disabled_night(),
            e.button_lock(),
            e.overload_protection(100, 2500),
        ],
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["lumi.remote.rkba01"],
        model: "ZNXNKG02LM",
        vendor: "Aqara",
        description: "Smart rotary knob H1 (wireless)",
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            m.quirkCheckinInterval("1_HOUR"),
            lumiPreventReset(),
            lumiCommandMode(),
            lumiAction({ actionLookup: { hold: 0, single: 1, double: 2, release: 255 } }),
            lumiBattery({ voltageToPercentage: { min: 2850, max: 3000 } }),
            lumiKnobRotation(),
            m.enumLookup({
                name: "sensitivity",
                lookup: { low: 720, medium: 360, high: 180 },
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0234, type: 0x21 },
                description: "Rotation sensitivity",
                zigbeeCommandOptions: { manufacturerCode },
            }),
        ],
    },
    {
        zigbeeModel: ["lumi.remote.acn003"],
        model: "WXKG16LM",
        vendor: "Aqara",
        description: "Wireless remote switch E1 (single rocker)",
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), m.quirkCheckinInterval("1_HOUR")],
        fromZigbee: [lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
        toZigbee: [lumi.toZigbee.lumi_switch_click_mode],
        exposes: [
            e.battery(),
            e.battery_voltage(),
            e.action(["single", "double", "hold"]),
            e
                .enum("click_mode", ea.ALL, ["fast", "multi"])
                .withDescription("Click mode, fast: only supports single click which will be send immediately after clicking." +
                "multi: supports more events like double and hold"),
        ],
        configure: async (device, coordinatorEndpoint) => {
            await device
                .getEndpoint(1)
                .write("manuSpecificLumi", { 293: { value: 0x02, type: 0x20 } }, { manufacturerCode: manufacturerCode });
        },
    },
    {
        zigbeeModel: ["lumi.remote.acn004"],
        model: "WXKG17LM",
        vendor: "Aqara",
        description: "Wireless remote switch E1 (double rocker)",
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), m.quirkCheckinInterval("1_HOUR"), lumiPreventReset()],
        exposes: [
            e.battery(),
            e.battery_voltage(),
            e.action(["single_left", "single_right", "single_both", "double_left", "double_right", "hold_left", "hold_right"]),
            e
                .enum("click_mode", ea.ALL, ["fast", "multi"])
                .withDescription("Click mode, fast: only supports single click which will be send immediately after clicking, multi: supports more events like double and hold"),
        ],
        fromZigbee: [lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
        toZigbee: [lumi.toZigbee.lumi_switch_click_mode],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint1 = device.getEndpoint(1);
            // set multiclick mode
            await endpoint1.write("manuSpecificLumi", { 293: { value: 0x02, type: 0x20 } }, { manufacturerCode: manufacturerCode });
        },
    },
    {
        zigbeeModel: ["lumi.remote.b18ac1"],
        model: "WXKG14LM",
        vendor: "Aqara",
        description: "Wireless remote switch H1 (single rocker)",
        fromZigbee: [lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific, fz.command_toggle],
        toZigbee: [lumi.toZigbee.lumi_switch_click_mode, lumi.toZigbee.lumi_operation_mode_opple],
        exposes: [
            e.battery(),
            e.battery_voltage(),
            e.action(["single", "double", "triple", "hold"]),
            e
                .enum("click_mode", ea.ALL, ["fast", "multi"])
                .withDescription("Click mode, fast: only supports single click which will be send immediately after clicking." +
                "multi: supports more events like double and hold"),
            e
                .enum("operation_mode", ea.ALL, ["command", "event"])
                .withDescription('Operation mode, select "command" to enable bindings (wake up the device before changing modes!)'),
        ],
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), m.quirkCheckinInterval("1_HOUR")],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint1 = device.getEndpoint(1);
            await endpoint1.write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
            await endpoint1.read("manuSpecificLumi", [0x0125], { manufacturerCode: manufacturerCode });
        },
    },
    {
        zigbeeModel: ["lumi.airrtc.agl001"],
        model: "SRTS-A01",
        vendor: "Aqara",
        description: "Smart radiator thermostat E1",
        fromZigbee: [lumi.fromZigbee.lumi_trv, fz.thermostat, fz.battery],
        toZigbee: [lumi.toZigbee.lumi_trv, tz.thermostat_occupied_heating_setpoint],
        exposes: [
            e.setup().withDescription("Indicates if the device is in setup mode (E11)"),
            e
                .climate()
                .withSetpoint("occupied_heating_setpoint", 5, 30, 0.5)
                .withLocalTemperature(ea.STATE, "Current temperature measured by the internal or external sensor")
                .withSystemMode(["off", "heat"], ea.ALL)
                .withPreset(["manual", "away", "auto"])
                .setAccess("preset", ea.ALL),
            e.temperature_sensor_select(["internal", "external"]).withAccess(ea.ALL),
            e.external_temperature_input().withDescription("Input for remote temperature sensor (when sensor is set to external)"),
            e.calibrated().withDescription("Indicates if this valve is calibrated, use the calibrate option to calibrate"),
            e.enum("calibrate", ea.ALL, ["calibrate"]).withDescription("Calibrates the valve").withCategory("config"),
            e.child_lock().withAccess(ea.ALL),
            e.window_detection_bool(),
            e.window_open(),
            e.valve_detection_bool(),
            e
                .valve_alarm()
                .withDescription("Notifies of a temperature control abnormality if valve detection is enabled " +
                "(e.g., thermostat not installed correctly, valve failure or incorrect calibration, " +
                "incorrect link to external temperature sensor)"),
            e.away_preset_temperature().withAccess(ea.ALL),
            e.battery_voltage(),
            e.battery(),
            e.power_outage_count(),
            e.device_temperature(),
            e.schedule(),
            e
                .schedule_settings()
                .withDescription("Smart schedule configuration (default: mon,tue,wed,thu,fri|8:00,24.0|18:00,17.0|23:00,22.0|8:00,22.0)"),
        ],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            // Initialize battery percentage and voltage
            await endpoint.read("manuSpecificLumi", [0x040a], { manufacturerCode: manufacturerCode });
            await endpoint.read("genPowerCfg", ["batteryVoltage"]);
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), m.quirkCheckinInterval("1_HOUR"), lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["aqara.feeder.acn001"],
        model: "ZNCWWSQ01LM",
        vendor: "Aqara",
        description: "Smart pet feeder C1",
        whiteLabel: [{ vendor: "Aqara", model: "PETC1-M01" }],
        fromZigbee: [lumi.fromZigbee.lumi_feeder],
        toZigbee: [lumi.toZigbee.lumi_feeder],
        exposes: [
            e.enum("feed", ea.STATE_SET, ["", "START"]).withDescription("Start feeding"),
            e.enum("feeding_source", ea.STATE, ["schedule", "manual", "remote"]).withDescription("Feeding source"),
            e.numeric("feeding_size", ea.STATE).withDescription("Feeding size").withUnit("portion"),
            e.numeric("portions_per_day", ea.STATE).withDescription("Portions per day"),
            e.numeric("weight_per_day", ea.STATE).withDescription("Weight per day").withUnit("g"),
            e.binary("error", ea.STATE, true, false).withDescription("Indicates whether there is an error with the feeder"),
            e
                .list("schedule", ea.STATE_SET, e
                .composite("dayTime", "dayTime", exposes.access.STATE_SET)
                .withFeature(e.enum("days", exposes.access.STATE_SET, [
                "everyday",
                "workdays",
                "weekend",
                "mon",
                "tue",
                "wed",
                "thu",
                "fri",
                "sat",
                "sun",
                "mon-wed-fri-sun",
                "tue-thu-sat",
            ]))
                .withFeature(e.numeric("hour", exposes.access.STATE_SET))
                .withFeature(e.numeric("minute", exposes.access.STATE_SET))
                .withFeature(e.numeric("size", exposes.access.STATE_SET)))
                .withDescription("Feeding schedule"),
            e
                .binary("led_indicator", ea.STATE_SET, "ON", "OFF")
                .withLabel("Disable LED at night")
                .withDescription("LED indicator will be disabled every day from 21:00 to 09:00")
                .withCategory("config"),
            e.child_lock(),
            e.enum("mode", ea.STATE_SET, ["schedule", "manual"]).withDescription("Feeding mode"),
            e
                .numeric("serving_size", ea.STATE_SET)
                .withValueMin(1)
                .withValueMax(10)
                .withDescription("One serving size")
                .withUnit("portion")
                .withCategory("config"),
            e
                .numeric("portion_weight", ea.STATE_SET)
                .withValueMin(1)
                .withValueMax(20)
                .withDescription("Portion weight")
                .withUnit("g")
                .withCategory("config"),
        ],
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA(), m.forcePowerSource({ powerSource: "Mains (single phase)" })],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            await endpoint.read("manuSpecificLumi", [0xfff1], { manufacturerCode: manufacturerCode });
        },
    },
    {
        zigbeeModel: ["lumi.remote.acn007"],
        model: "WXKG20LM",
        vendor: "Aqara",
        description: "Wireless mini switch E1",
        fromZigbee: [fz.battery, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
        toZigbee: [],
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), m.quirkCheckinInterval("1_HOUR")],
        exposes: [
            e.battery(),
            e.battery_voltage(),
            e.action(["single", "double", "hold", "release"]),
            e.device_temperature(),
            e.power_outage_count(),
        ],
    },
    {
        zigbeeModel: ["lumi.remote.acn008"],
        model: "WXKG21LM",
        vendor: "Aqara",
        description: "Wireless remote switch H1M (single rocker)",
        fromZigbee: [fz.battery, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
        toZigbee: [lumi.toZigbee.lumi_switch_click_mode],
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), m.quirkCheckinInterval("1_HOUR")],
        exposes: [
            e.battery(),
            e.battery_voltage(),
            e.action(["single", "double", "hold"]),
            e
                .enum("click_mode", ea.ALL, ["fast", "multi"])
                .withDescription("Click mode, fast: only supports single click which will be send immediately after clicking." +
                "multi: supports more events like double and hold"),
        ],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint1 = device.getEndpoint(1);
            // set "event" mode
            await endpoint1.write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: lumi.manufacturerCode });
            // turn on the "multiple clicks" mode, otherwise the only "single click" events.
            // if value is 1 - there will be single clicks, 2 - multiple.
            await endpoint1.write("manuSpecificLumi", { 293: { value: 0x02, type: 0x20 } }, { manufacturerCode: lumi.manufacturerCode });
            await reporting.bind(endpoint1, coordinatorEndpoint, ["genOnOff", "genPowerCfg"]);
        },
    },
    {
        zigbeeModel: ["lumi.remote.acn009"],
        model: "WXKG22LM",
        vendor: "Aqara",
        description: "Wireless remote switch H1M (double rocker)",
        fromZigbee: [fz.battery, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific, fz.command_toggle],
        toZigbee: [lumi.toZigbee.lumi_switch_click_mode, lumi.toZigbee.lumi_operation_mode_opple],
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } }, multiEndpoint: true },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), m.quirkCheckinInterval("1_HOUR")],
        exposes: [
            e.battery(),
            e.battery_voltage(),
            e.action([
                "single_left",
                "single_right",
                "single_both",
                "double_left",
                "double_right",
                "double_both",
                "triple_left",
                "triple_right",
                "triple_both",
                "hold_left",
                "hold_right",
                "hold_both",
            ]),
            e
                .enum("click_mode", ea.ALL, ["fast", "multi"])
                .withDescription("Click mode, fast: only supports single click which will be send immediately after clicking." +
                "multi: supports more events like double and hold"),
            e
                .enum("operation_mode", ea.ALL, ["command", "event"])
                .withDescription('Operation mode, select "command" to enable bindings (wake up the device before changing modes!)'),
        ],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint1 = device.getEndpoint(1);
            const endpoint2 = device.getEndpoint(3);
            // set "event" mode
            await endpoint1.write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode });
            // turn on the "multiple clicks" mode, otherwise the only "single click" events.
            // if value is 1 - there will be single clicks, 2 - multiple.
            await endpoint1.write("manuSpecificLumi", { 293: { value: 0x02, type: 0x20 } }, { manufacturerCode: manufacturerCode });
            await reporting.bind(endpoint1, coordinatorEndpoint, ["genOnOff", "genPowerCfg"]);
            await reporting.bind(endpoint2, coordinatorEndpoint, ["genOnOff"]);
            // TODO/BUG:
            // Did not understand how to separate the left and right keys in command mode -
            // the "toggleCommand" always arrives from the first endpoint
        },
    },
    {
        zigbeeModel: ["lumi.remote.b286acn03"],
        model: "WXKG04LM",
        vendor: "Aqara",
        description: "Wireless remote switch T1 (double rocker)",
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        fromZigbee: [lumi.fromZigbee.lumi_basic, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
        toZigbee: [],
        endpoint: (device) => {
            return { left: 1, right: 2, both: 3 };
        },
        exposes: [
            e.battery(),
            e.battery_voltage(),
            e.action([
                "button_1_hold",
                "button_1_release",
                "button_1_single",
                "button_1_double",
                "button_1_triple",
                "button_2_hold",
                "button_2_release",
                "button_2_single",
                "button_2_double",
                "button_2_triple",
                "button_3_hold",
                "button_3_release",
                "button_3_single",
                "button_3_double",
                "button_3_triple",
            ]),
        ],
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), m.quirkCheckinInterval("1_HOUR"), lumiZigbeeOTA()],
    },
    {
        zigbeeModel: ["lumi.switch.acn048"],
        model: "ZNQBKG38LM",
        vendor: "Aqara",
        description: "Smart wall switch Z1 (single rocker)",
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiZigbeeOTA(),
            lumiPreventReset(),
            lumiOnOff({ operationMode: true, powerOutageMemory: "enum", lockRelay: true }),
            lumiAction(),
            lumiElectricityMeter(),
            lumiPower(),
            lumiLedDisabledNight(),
            lumiClickMode({ attribute: { ID: 0x0286, type: 0x20 } }),
            lumiSetEventMode(),
        ],
    },
    {
        zigbeeModel: ["lumi.switch.acn049"],
        model: "ZNQBKG39LM",
        vendor: "Aqara",
        description: "Smart wall switch Z1 (double rocker)",
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiZigbeeOTA(),
            lumiPreventReset(),
            m.deviceEndpoints({ endpoints: { top: 1, bottom: 2 } }),
            lumiOnOff({
                operationMode: true,
                powerOutageMemory: "enum",
                lockRelay: true,
                endpointNames: ["top", "bottom"],
            }),
            lumiAction({
                actionLookup: { hold: 0, single: 1, double: 2, release: 255 },
                endpointNames: ["top", "bottom"],
            }),
            lumiElectricityMeter(),
            lumiPower(),
            lumiLedDisabledNight(),
            lumiClickMode({ attribute: { ID: 0x0286, type: 0x20 } }),
            lumiSetEventMode(),
        ],
    },
    {
        zigbeeModel: ["lumi.switch.acn054"],
        model: "ZNQBKG40LM",
        vendor: "Aqara",
        description: "Smart wall switch Z1 (triple rocker)",
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiZigbeeOTA(),
            lumiPreventReset(),
            m.deviceEndpoints({ endpoints: { top: 1, center: 2, bottom: 3 } }),
            lumiOnOff({
                operationMode: true,
                powerOutageMemory: "enum",
                lockRelay: true,
                endpointNames: ["top", "center", "bottom"],
            }),
            lumiAction({
                actionLookup: { hold: 0, single: 1, double: 2, release: 255 },
                endpointNames: ["top", "center", "bottom"],
            }),
            lumiElectricityMeter(),
            lumiPower(),
            lumiLedDisabledNight(),
            lumiClickMode({ attribute: { ID: 0x0286, type: 0x20 } }),
            lumiSetEventMode(),
        ],
    },
    {
        zigbeeModel: ["lumi.switch.acn055"],
        model: "ZNQBKG41LM",
        vendor: "Aqara",
        description: "Smart wall switch Z1 (quadruple rocker)",
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiZigbeeOTA(),
            lumiPreventReset(),
            m.deviceEndpoints({ endpoints: { top: 1, center: 2, bottom: 3, wireless: 4 } }),
            lumiOnOff({
                operationMode: true,
                powerOutageMemory: "enum",
                lockRelay: true,
                endpointNames: ["top", "center", "bottom"],
            }),
            lumiAction({
                actionLookup: { hold: 0, single: 1, double: 2, release: 255 },
                endpointNames: ["top", "center", "bottom", "wireless"],
            }),
            lumiElectricityMeter(),
            lumiPower(),
            lumiLedDisabledNight(),
            lumiClickMode({ attribute: { ID: 0x0286, type: 0x20 } }),
            lumiSetEventMode(),
        ],
    },
    {
        zigbeeModel: ["lumi.switch.acn056"],
        model: "ZNQBKG42LM",
        vendor: "Aqara",
        description: "Smart wall switch Z1 Pro (single rocker)",
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiZigbeeOTA(),
            lumiPreventReset(),
            lumiOnOff({ operationMode: true, powerOutageMemory: "enum", lockRelay: true }),
            lumiAction({ extraActions: ["slider_single", "slider_double", "slider_hold", "slider_up", "slider_down"] }),
            lumiElectricityMeter(),
            lumiPower(),
            lumiLedDisabledNight(),
            lumiClickMode({ attribute: { ID: 0x0286, type: 0x20 } }),
            lumiSlider(),
            lumiSwitchMode(),
        ],
    },
    {
        zigbeeModel: ["lumi.switch.acn057"],
        model: "ZNQBKG43LM",
        vendor: "Aqara",
        description: "Smart wall switch Z1 Pro (double rocker)",
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiZigbeeOTA(),
            lumiPreventReset(),
            m.deviceEndpoints({ endpoints: { top: 1, bottom: 2 } }),
            lumiOnOff({
                operationMode: true,
                powerOutageMemory: "enum",
                lockRelay: true,
                endpointNames: ["top", "bottom"],
            }),
            lumiAction({
                actionLookup: { hold: 0, single: 1, double: 2, release: 255 },
                endpointNames: ["top", "bottom"],
                extraActions: ["slider_single", "slider_double", "slider_hold", "slider_up", "slider_down"],
            }),
            lumiElectricityMeter(),
            lumiPower(),
            lumiLedDisabledNight(),
            lumiClickMode({ attribute: { ID: 0x0286, type: 0x20 } }),
            lumiSlider(),
            lumiSwitchMode(),
        ],
    },
    {
        zigbeeModel: ["lumi.switch.acn058"],
        model: "ZNQBKG44LM",
        vendor: "Aqara",
        description: "Smart wall switch Z1 Pro (triple rocker)",
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiZigbeeOTA(),
            lumiPreventReset(),
            m.deviceEndpoints({ endpoints: { top: 1, center: 2, bottom: 3 } }),
            lumiOnOff({
                operationMode: true,
                powerOutageMemory: "enum",
                lockRelay: true,
                endpointNames: ["top", "center", "bottom"],
            }),
            lumiAction({
                actionLookup: { hold: 0, single: 1, double: 2, release: 255 },
                endpointNames: ["top", "center", "bottom"],
                extraActions: ["slider_single", "slider_double", "slider_hold", "slider_up", "slider_down"],
            }),
            lumiElectricityMeter(),
            lumiPower(),
            lumiLedDisabledNight(),
            lumiClickMode({ attribute: { ID: 0x0286, type: 0x20 } }),
            lumiSlider(),
            lumiSwitchMode(),
        ],
    },
    {
        zigbeeModel: ["lumi.switch.acn059"],
        model: "ZNQBKG45LM",
        vendor: "Aqara",
        description: "Smart wall switch Z1 Pro (quadruple rocker)",
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiZigbeeOTA(),
            lumiPreventReset(),
            m.deviceEndpoints({ endpoints: { top: 1, center: 2, bottom: 3, wireless: 4 } }),
            lumiOnOff({
                operationMode: true,
                powerOutageMemory: "enum",
                lockRelay: true,
                endpointNames: ["top", "center", "bottom"],
            }),
            lumiAction({
                actionLookup: { hold: 0, single: 1, double: 2, release: 255 },
                endpointNames: ["top", "center", "bottom", "wireless"],
                extraActions: ["slider_single", "slider_double", "slider_hold", "slider_up", "slider_down"],
            }),
            lumiElectricityMeter(),
            lumiPower(),
            lumiLedDisabledNight(),
            lumiClickMode({ attribute: { ID: 0x0286, type: 0x20 } }),
            lumiSlider(),
            lumiSwitchMode(),
        ],
    },
    {
        zigbeeModel: ["lumi.switch.acn061"],
        model: "WS-K01D",
        vendor: "Aqara",
        description: "Smart wall switch H1 20A (with neutral, single rocker)",
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiZigbeeOTA(),
            lumiPreventReset(),
            lumiOnOff({ operationMode: true, powerOutageMemory: "binary" }),
            lumiAction({ actionLookup: { single: 1, double: 2 } }),
            lumiElectricityMeter(),
            lumiPower(),
            lumiLedDisabledNight(),
            lumiSetEventMode(),
            lumiFlipIndicatorLight(),
        ],
    },
    {
        zigbeeModel: ["lumi.remote.cagl02"],
        model: "CTP-R01",
        vendor: "Aqara",
        whiteLabel: [{ vendor: "Aqara", model: "MFCZQ12LM" }],
        description: "Cube T1 Pro",
        meta: { battery: { voltageToPercentage: { min: 2850, max: 3000 } } },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), m.quirkCheckinInterval("1_HOUR"), lumiZigbeeOTA()],
        fromZigbee: [
            lumi.fromZigbee.lumi_specific,
            lumi.fromZigbee.lumi_action_multistate,
            lumi.fromZigbee.lumi_action_analog,
            fz.ignore_onoff_report,
        ],
        toZigbee: [lumi.toZigbee.lumi_cube_operation_mode],
        exposes: [
            e.battery(),
            e.battery_voltage(),
            e.power_outage_count(false),
            e
                .enum("operation_mode", ea.SET, ["action_mode", "scene_mode"])
                .withDescription("[Soft Switch]: There is a configuration window, opens once an hour on itself, " +
                "only during which the cube will respond to mode switch. " +
                "Mode switch will be scheduled to take effect when the window becomes available. " +
                "You can also give it a throw action (no backward motion) to force a respond! " +
                "Otherwise, you may open lid and click LINK once to make the cube respond immediately. " +
                "[Hard Switch]: Open lid and click LINK button 5 times."),
            e.cube_side("side"),
            e
                .action([
                "shake",
                "throw",
                "tap",
                "slide",
                "flip180",
                "flip90",
                "hold",
                "side_up",
                "rotate_left",
                "rotate_right",
                "1_min_inactivity",
                "flip_to_side",
            ])
                .withDescription("Triggered action"),
            e.cube_side("action_from_side"),
            e.angle("action_angle"),
        ],
        configure: async (device, coordinatorEndpoint) => {
            device.softwareBuildID = `0.0.0_00${device.applicationVersion}`;
            device.save();
            const endpoint = device.getEndpoint(1);
            await endpoint.write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableDefaultResponse: true, disableResponse: true });
            await endpoint.read("manuSpecificLumi", [0x148], {
                manufacturerCode: manufacturerCode,
                disableDefaultResponse: true,
                disableResponse: true,
            });
        },
    },
    {
        zigbeeModel: ["lumi.switch.acn040"],
        model: "ZNQBKG31LM",
        vendor: "Aqara",
        description: "Smart wall switch E1 (with neutral, triple rocker)",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
        toZigbee: [
            tz.on_off,
            lumi.toZigbee.lumi_switch_operation_mode_opple,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            lumi.toZigbee.lumi_switch_mode_switch,
            lumi.toZigbee.lumi_flip_indicator_light,
        ],
        endpoint: (device) => {
            return { left: 1, center: 2, right: 3 };
        },
        meta: { multiEndpoint: true },
        exposes: [
            e.switch().withEndpoint("left"),
            e.switch().withEndpoint("center"),
            e.switch().withEndpoint("right"),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for left button").withEndpoint("left"),
            e
                .enum("operation_mode", ea.ALL, ["control_relay", "decoupled"])
                .withDescription("Decoupled mode for center button")
                .withEndpoint("center"),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for right button").withEndpoint("right"),
            e.action([
                "single_left",
                "double_left",
                "single_center",
                "double_center",
                "single_right",
                "double_right",
                "single_left_center",
                "double_left_center",
                "single_left_right",
                "double_left_right",
                "single_center_right",
                "double_center_right",
                "single_all",
                "double_all",
            ]),
            e.power_outage_memory(),
            e.device_temperature(),
            e.flip_indicator_light(),
        ],
        configure: async (device, coordinatorEndpoint) => {
            await device
                .getEndpoint(1)
                .write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA(), lumiPreventReset()],
    },
    {
        zigbeeModel: ["lumi.switch.acn029"],
        model: "ZNQBKG24LM",
        vendor: "Aqara",
        description: "Smart wall switch H1M (with neutral, single rocker)",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_power, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
        toZigbee: [
            tz.on_off,
            lumi.toZigbee.lumi_switch_operation_mode_opple,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            lumi.toZigbee.lumi_led_disabled_night,
            lumi.toZigbee.lumi_flip_indicator_light,
        ],
        exposes: [
            e.switch(),
            e.power(),
            e.energy(),
            e.voltage(),
            e.device_temperature(),
            e.action(["single", "double"]),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode"),
            e.power_outage_memory(),
            e.led_disabled_night(),
            e.flip_indicator_light(),
        ],
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA(), lumiPreventReset()],
    },
    {
        zigbeeModel: ["lumi.switch.acn030"],
        model: "ZNQBKG25LM",
        vendor: "Aqara",
        description: "Smart wall switch H1M (with neutral, double rocker)",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific, lumi.fromZigbee.lumi_power],
        toZigbee: [
            tz.on_off,
            lumi.toZigbee.lumi_switch_operation_mode_opple,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            lumi.toZigbee.lumi_led_disabled_night,
            lumi.toZigbee.lumi_flip_indicator_light,
        ],
        endpoint: (device) => {
            return { left: 1, right: 2 };
        },
        meta: { multiEndpoint: true, multiEndpointSkip: ["power", "energy"] },
        exposes: [
            e.power(),
            e.energy(),
            e.voltage(),
            e.switch().withEndpoint("left"),
            e.switch().withEndpoint("right"),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for left button").withEndpoint("left"),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for right button").withEndpoint("right"),
            e.action([
                "single_left",
                "double_left",
                "single_right",
                "double_right",
                "single_left_right",
                "double_left_right",
                "single_all",
                "double_all",
            ]),
            e.power_outage_memory(),
            e.led_disabled_night(),
            e.device_temperature(),
            e.flip_indicator_light(),
        ],
        configure: async (device, coordinatorEndpoint) => {
            await device
                .getEndpoint(1)
                .write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA(), lumiPreventReset()],
    },
    {
        zigbeeModel: ["lumi.switch.acn031"],
        model: "ZNQBKG26LM",
        vendor: "Aqara",
        description: "Smart wall switch H1M (with neutral, triple rocker)",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific, lumi.fromZigbee.lumi_power],
        toZigbee: [
            tz.on_off,
            lumi.toZigbee.lumi_switch_operation_mode_opple,
            lumi.toZigbee.lumi_switch_power_outage_memory,
            lumi.toZigbee.lumi_led_disabled_night,
            lumi.toZigbee.lumi_flip_indicator_light,
        ],
        endpoint: (device) => {
            return { left: 1, center: 2, right: 3 };
        },
        meta: { multiEndpoint: true, multiEndpointSkip: ["power", "energy"] },
        exposes: [
            e.power(),
            e.energy(),
            e.voltage(),
            e.switch().withEndpoint("left"),
            e.switch().withEndpoint("center"),
            e.switch().withEndpoint("right"),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for left button").withEndpoint("left"),
            e
                .enum("operation_mode", ea.ALL, ["control_relay", "decoupled"])
                .withDescription("Decoupled mode for center button")
                .withEndpoint("center"),
            e.enum("operation_mode", ea.ALL, ["control_relay", "decoupled"]).withDescription("Decoupled mode for right button").withEndpoint("right"),
            e.action([
                "single_left",
                "double_left",
                "single_center",
                "double_center",
                "single_right",
                "double_right",
                "single_left_center",
                "double_left_center",
                "single_left_right",
                "double_left_right",
                "single_center_right",
                "double_center_right",
                "single_all",
                "double_all",
            ]),
            e.power_outage_memory(),
            e.led_disabled_night(),
            e.device_temperature(),
            e.flip_indicator_light(),
        ],
        configure: async (device, coordinatorEndpoint) => {
            await device
                .getEndpoint(1)
                .write("manuSpecificLumi", { mode: 1 }, { manufacturerCode: manufacturerCode, disableResponse: true });
        },
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA(), lumiPreventReset()],
    },
    {
        zigbeeModel: ["lumi.plug.aeu001"],
        model: "WP-P01D",
        vendor: "Aqara",
        description: "Smart wall outlet H2 EU",
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiZigbeeOTA(),
            lumiOnOff({ powerOutageMemory: "enum" }),
            lumiPower(),
            lumiElectricityMeter(),
            lumiOverloadProtection(),
            lumiLedIndicator(),
            lumiButtonLock(),
            m.binary({
                name: "charging_protection",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0202, type: 0x10 },
                valueOn: ["ON", 1],
                valueOff: ["OFF", 0],
                description: "Turn off the outlet if the power is below the set limit for half an hour",
                access: "ALL",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "charging_limit",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0206, type: 0x39 },
                valueMin: 0.1,
                valueMax: 2,
                valueStep: 0.1,
                unit: "W",
                description: "Charging protection power limit",
                access: "ALL",
                zigbeeCommandOptions: { manufacturerCode },
            }),
        ],
    },
    {
        zigbeeModel: ["lumi.light.acn032", "lumi.light.acn031"],
        model: "CL-L02D",
        vendor: "Aqara",
        description: "Ceiling light T1M",
        whiteLabel: [
            {
                model: "HCXDD12LM",
                vendor: "Aqara",
                description: "Ceiling light T1",
                fingerprint: [{ modelID: "lumi.light.acn031" }],
            },
        ],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            await endpoint.read("manuSpecificLumi", [0x0515], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x0516], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x051f], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x0520], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x0522], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x0523], { manufacturerCode: manufacturerCode });
            await endpoint.read("genLevelCtrl", [0x0012], {});
            await endpoint.read("genLevelCtrl", [0x0013], {});
        },
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            m.deviceEndpoints({ endpoints: { white: 1, rgb: 2 } }),
            lumiLight({ colorTemp: true, endpointNames: ["white"] }),
            lumiLight({
                colorTemp: true,
                deviceTemperature: false,
                powerOutageCount: false,
                color: { modes: ["xy"] },
                endpointNames: ["rgb"],
            }),
            m.forcePowerSource({ powerSource: "Mains (single phase)" }),
            lumiPowerOnBehavior({ lookup: { on: 0, previous: 1, off: 2 } }),
            m.identify(),
            lumiZigbeeOTA(),
            lumi.lumiModernExtend.lumiDimmingRangeMin(),
            lumi.lumiModernExtend.lumiDimmingRangeMax(),
            lumi.lumiModernExtend.lumiOnOffDuration(),
            lumi.lumiModernExtend.lumiOffOnDuration(),
            lumi.lumiModernExtend.lumiT1MEffect(),
            lumi.lumiModernExtend.lumiRGBEffectSpeed(),
            lumi.lumiModernExtend.lumiRGBEffectColors(),
            lumi.lumiModernExtend.lumiSegmentColors(),
        ],
    },
    {
        zigbeeModel: ["lumi.switch.rkna01"],
        model: "ZNXNKG01LM",
        vendor: "Aqara",
        description: "Smart rotary knob H1 (with neutral)",
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiPreventReset(),
            m.deviceEndpoints({ endpoints: { left: 1, center: 2, right: 3 } }),
            lumiOnOff({ powerOutageMemory: "binary", endpointNames: ["left", "center", "right"] }),
            lumiCommandMode(),
            lumiAction({ actionLookup: { hold: 0, single: 1, double: 2, release: 255 } }),
            lumiKnobRotation(),
            lumiElectricityMeter(),
            lumiPower(),
            lumiZigbeeOTA(),
        ],
    },
    {
        zigbeeModel: ["lumi.valve.agl001"],
        model: "VC-X01D",
        vendor: "Aqara",
        description: "Valve controller T1",
        extend: [lumiZigbeeOTA(), m.onOff({ powerOnBehavior: false }), m.battery({ dontDividePercentage: true })],
    },
    {
        zigbeeModel: ["lumi.switch.agl009"],
        model: "WS-K07E",
        vendor: "Aqara",
        description: "Light switch H2 EU (single rocker)",
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiZigbeeOTA(),
            lumiPreventLeave(),
            m.deviceEndpoints({ endpoints: { up: 1, down: 4 } }),
            m.bindCluster({ endpointNames: ["up", "down"], cluster: "manuSpecificLumi", clusterType: "input" }),
            m.bindCluster({ endpointNames: ["up"], cluster: "genOnOff", clusterType: "input" }),
            // Configuring reporting for current fails
            // https://github.com/Koenkk/zigbee2mqtt/issues/27525
            m.electricityMeter({ voltage: false, current: { divisor: 1, multiplier: 1 }, configureReporting: false }),
            lumiLedIndicator(),
            lumiFlipIndicatorLight(),
            lumiAction({ endpointNames: ["up", "down"], actionLookup: { hold: 0, single: 1, double: 2, release: 255 } }),
            lumiOnOff({ powerOutageMemory: "enum", endpointNames: ["up"] }),
            lumiOperationMode({ description: "Decoupled mode for switch", endpointName: "up" }),
            lumiLockRelay({ description: "Lock switch", endpointName: "up" }),
            lumiMultiClick({ description: "Multi-click mode for down button", endpointName: "down" }),
        ],
    },
    {
        zigbeeModel: ["lumi.light.agl001", "lumi.light.agl003", "lumi.light.agl005", "lumi.light.agl007"],
        model: "T2_E27",
        vendor: "Aqara",
        description: "E27 RGB led bulb",
        whiteLabel: [
            {
                model: "T2_GU10",
                vendor: "Aqara",
                description: "GU10 RGB led bulb",
                fingerprint: [{ modelID: "lumi.light.agl005" }, { modelID: "lumi.light.agl007" }],
            },
            {
                model: "T2_E26",
                vendor: "Aqara",
                description: "E26 RGB led bulb",
                fingerprint: [{ modelID: "lumi.light.agl001" }],
            },
        ],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            await endpoint.read("manuSpecificLumi", [0x0515], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x0516], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x051f], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x0520], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x0523], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x0528], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x052c], { manufacturerCode: manufacturerCode });
            await endpoint.read("genLevelCtrl", [0x0012], {});
            await endpoint.read("genLevelCtrl", [0x0013], {});
        },
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiLight({ colorTemp: true, color: true, colorTempRange: [111, 500] }),
            lumiPowerOnBehavior({ lookup: { off: 0, on: 1, reverse: 2, restore: 3 } }),
            m.identify(),
            m.forcePowerSource({ powerSource: "Mains (single phase)" }),
            lumiZigbeeOTA(),
            lumi.lumiModernExtend.lumiDimmingRangeMin(),
            lumi.lumiModernExtend.lumiDimmingRangeMax(),
            lumi.lumiModernExtend.lumiOffOnDuration(),
            lumi.lumiModernExtend.lumiOnOffDuration(),
            lumi.lumiModernExtend.lumiTransitionCurveCurvature(),
            lumi.lumiModernExtend.lumiTransitionInitialBrightness(),
            lumi.lumiModernExtend.lumiRGBEffect({ off: 0, breathing: 1, candlelight: 2, fading: 3, flash: 4 }),
            lumi.lumiModernExtend.lumiRGBEffectSpeed(),
            lumi.lumiModernExtend.lumiRGBEffectColors(),
        ],
    },
    {
        zigbeeModel: ["lumi.light.agl002", "lumi.light.agl004", "lumi.light.agl006", "lumi.light.agl008"],
        model: "T2_E27_CCT",
        vendor: "Aqara",
        description: "E27 CCT led bulb",
        whiteLabel: [
            {
                model: "T2_GU10_CCT",
                vendor: "Aqara",
                description: "GU10 CCT led bulb",
                fingerprint: [{ modelID: "lumi.light.agl006" }, { modelID: "lumi.light.agl008" }],
            },
            {
                model: "T2_E26_CCT",
                vendor: "Aqara",
                description: "E26 CCT led bulb",
                fingerprint: [{ modelID: "lumi.light.agl002" }],
            },
        ],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            await endpoint.read("manuSpecificLumi", [0x0515], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x0516], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x0528], { manufacturerCode: manufacturerCode });
            await endpoint.read("manuSpecificLumi", [0x052c], { manufacturerCode: manufacturerCode });
            await endpoint.read("genLevelCtrl", [0x0012], {});
            await endpoint.read("genLevelCtrl", [0x0013], {});
        },
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiLight({ colorTemp: true, colorTempRange: [153, 370] }),
            lumiPowerOnBehavior({ lookup: { off: 0, on: 1, reverse: 2, restore: 3 } }),
            m.identify(),
            m.forcePowerSource({ powerSource: "Mains (single phase)" }),
            lumiZigbeeOTA(),
            lumi.lumiModernExtend.lumiDimmingRangeMin(),
            lumi.lumiModernExtend.lumiDimmingRangeMax(),
            lumi.lumiModernExtend.lumiOffOnDuration(),
            lumi.lumiModernExtend.lumiOnOffDuration(),
            lumi.lumiModernExtend.lumiTransitionCurveCurvature(),
            lumi.lumiModernExtend.lumiTransitionInitialBrightness(),
        ],
    },
    {
        zigbeeModel: ["lumi.switch.agl010"],
        whiteLabel: [{ model: "WS-K08D", vendor: "Aqara" }],
        model: "WS-K08E",
        vendor: "Aqara",
        description: "Light switch H2 EU (double rocker)",
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiZigbeeOTA(),
            lumiPreventLeave(),
            m.deviceEndpoints({ endpoints: { left: 1, right: 2, left_down: 4, right_down: 5 } }),
            m.bindCluster({ endpointNames: ["left", "left_down", "right", "right_down"], cluster: "manuSpecificLumi", clusterType: "input" }),
            m.bindCluster({ endpointNames: ["left", "right"], cluster: "genOnOff", clusterType: "input" }),
            // Configuring reporting for current fails
            // https://github.com/Koenkk/zigbee2mqtt/issues/27525
            m.electricityMeter({ voltage: false, current: { divisor: 1, multiplier: 1 }, configureReporting: false }),
            lumiLedIndicator(),
            lumiFlipIndicatorLight(),
            lumiAction({ endpointNames: ["left", "left_down", "right", "right_down"], actionLookup: { hold: 0, single: 1, double: 2, release: 255 } }),
            lumiOnOff({ powerOutageMemory: "enum", endpointNames: ["left", "right"] }),
            lumiOperationMode({ description: "Decoupled mode for left switch", endpointName: "left" }),
            lumiOperationMode({ description: "Decoupled mode for right switch", endpointName: "right" }),
            lumiLockRelay({ description: "Lock left switch", endpointName: "left" }),
            lumiLockRelay({ description: "Lock right switch", endpointName: "right" }),
            lumiMultiClick({ description: "Multi-click mode for left down button", endpointName: "left_down" }),
            lumiMultiClick({ description: "Multi-click mode for right down button", endpointName: "right_down" }),
        ],
    },
    {
        zigbeeModel: ["lumi.switch.aeu003"],
        model: "DS-K02D/DS-K02E",
        vendor: "Aqara",
        description: "Aqara Shutter Switch H2 EU",
        meta: {
            overrideHaDiscoveryPayload: (payload) => {
                if (payload.position_topic && payload.set_position_topic) {
                    payload.device_class = "shutter";
                }
            },
        },
        version: "0.0.2",
        configure: configureAqaraH2EuShutterSwitch,
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiAqaraH2EuShutterSwitchAction(),
            lumiZigbeeOTA(),
            m.deviceEndpoints({
                endpoints: aqaraH2EuShutterSwitchEndpoints,
                multiEndpointSkip: aqaraH2EuShutterSwitchMultiEndpointSkip,
            }),
            m.electricityMeter({ cluster: "metering", power: false, energy: { divisor: 1000 } }),
            m.windowCovering({ controls: ["lift"], coverInverted: true, configureReporting: true }),
            lumiMultiClick({ description: "Multi-click mode for top wireless button", endpointName: "top_wireless_button" }),
            lumiMultiClick({ description: "Multi-click mode for bottom wireless button", endpointName: "bottom_wireless_button" }),
        ],
    },
    {
        zigbeeModel: ["lumi.switch.agl011"],
        model: "KD-R01D",
        vendor: "Aqara",
        description: "Dimmer switch H2 EU",
        exposes: [e.device_temperature()],
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiZigbeeOTA(),
            lumiPreventLeave(),
            m.bindCluster({ cluster: "genOnOff", clusterType: "input" }),
            m.bindCluster({ cluster: "genLevelCtrl", clusterType: "input" }),
            lumiPower(),
            lumiElectricityMeter(),
            lumiLedIndicator(),
            lumiFlipIndicatorLight(),
            lumiPowerOnBehavior(),
            m.light({ powerOnBehavior: false }),
            lumiKnobRotation({ withButtonState: false }),
            lumiOperationMode({ description: "Decoupled mode for knob" }),
            lumiAction({ actionLookup: { hold: 0, single: 1, double: 2, release: 255 } }),
            lumiMultiClick(),
            m.enumLookup({
                name: "sensitivity",
                lookup: { low: 720, medium: 360, high: 180 },
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0234, type: 0x21 },
                description: "Rotation sensitivity",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.enumLookup({
                name: "phase",
                lookup: { forward: 0, reverse: 1 },
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x030a, type: 0x20 },
                description: "Dimming phase",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "min_brightness",
                valueMin: 0,
                valueMax: 99,
                unit: "%",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0515, type: 0x20 },
                description: "Minimum brightness level",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "max_brightness",
                valueMin: 1,
                valueMax: 100,
                unit: "%",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0516, type: 0x20 },
                description: "Maximum brightness level",
                zigbeeCommandOptions: { manufacturerCode },
            }),
        ],
    },
    {
        zigbeeModel: ["lumi.switch.agl007"],
        model: "WS-K05E",
        vendor: "Aqara",
        description: "Dimmer Switch H2 US",
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiLight({
                effect: false,
                powerOnBehavior: false,
                powerOutageCount: true,
                deviceTemperature: true,
                configureReporting: true,
                levelConfig: {
                    features: ["execute_if_off", "on_transition_time", "off_transition_time", "on_level"],
                },
            }),
            m.deviceEndpoints({
                endpoints: { power: 1, bright: 2, dim: 3, 21: 21, 71: 71, 72: 72 },
            }),
            lumiZigbeeOTA(),
            lumiPreventLeave(),
            lumiPreventReset(),
            m.bindCluster({ cluster: "genOnOff", clusterType: "input" }),
            m.bindCluster({ cluster: "genLevelCtrl", clusterType: "input" }),
            m.bindCluster({ cluster: "manuSpecificLumi", clusterType: "input" }),
            lumiPower(),
            lumiElectricityMeter(),
            lumiLedIndicator(),
            lumiFlipIndicatorLight(),
            lumiSwitchMode(),
            lumiSetEventMode(),
            lumiOperationMode({
                description: "Decoupled mode for the load relay (decoupling power disables bright/dim buttons)",
                endpointName: "power",
            }),
            lumiOperationMode({
                description: "Decoupled mode for the brightness up button (disabled when power is decoupled)",
                endpointName: "bright",
            }),
            lumiOperationMode({
                description: "Decoupled mode for the brightness down button (disabled when power is decoupled)",
                endpointName: "dim",
            }),
            lumiPowerOnBehavior(),
            lumiAction({
                actionLookup: { hold: 0, single: 1, double: 2, release: 255 },
                endpointNames: ["power", "bright", "dim"],
            }),
            lumiMultiClick({
                description: "Multi-click mode for power button",
                endpointName: "power",
            }),
            lumiMultiClick({
                description: "Multi-click mode for brightness up button",
                endpointName: "bright",
            }),
            lumiMultiClick({
                description: "Multi-click mode for brightness down button",
                endpointName: "dim",
            }),
            m.enumLookup({
                name: "phase",
                lookup: { forward: 0, reverse: 1 },
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x030a, type: 0x20 },
                description: "Dimming phase",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "min_brightness",
                valueMin: 0,
                valueMax: 99,
                unit: "%",
                access: "STATE_SET",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0515, type: 0x20 },
                description: "Minimum brightness level",
                entityCategory: "config",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "max_brightness",
                valueMin: 1,
                valueMax: 100,
                unit: "%",
                access: "STATE_SET",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0516, type: 0x20 },
                description: "Maximum brightness level",
                entityCategory: "config",
                zigbeeCommandOptions: { manufacturerCode },
            }),
        ],
        meta: {
            multiEndpoint: true,
            multiEndpointSkip: ["state", "brightness", "level_config"],
        },
    },
    {
        zigbeeModel: ["lumi.switch.agl006"],
        model: "WS-K04E",
        vendor: "Aqara",
        description: "Light Switch H2 US (quadruple rocker)",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiZigbeeOTA(),
            lumiPreventReset(),
            m.deviceEndpoints({ endpoints: { top: 1, center: 2, bottom: 3, wireless: 4 } }),
            m.bindCluster({ endpointNames: ["top", "center", "bottom", "wireless"], cluster: "manuSpecificLumi", clusterType: "input" }),
            m.bindCluster({ endpointNames: ["top", "center", "bottom"], cluster: "genOnOff", clusterType: "input" }),
            lumiPower(),
            lumiOnOff({
                operationMode: true,
                powerOutageMemory: "enum",
                lockRelay: true,
                endpointNames: ["top", "center", "bottom"],
            }),
            lumiAction({
                actionLookup: { hold: 0, single: 1, double: 2, release: 255 },
                endpointNames: ["top", "center", "bottom", "wireless"],
            }),
            lumiMultiClick({ description: "Multi-click mode for wireless button", endpointName: "wireless" }),
            lumiLedDisabledNight(),
            lumiFlipIndicatorLight(),
            lumiSwitchMode(),
        ],
    },
    {
        zigbeeModel: ["lumi.switch.agl004"],
        model: "WS-K02E",
        vendor: "Aqara",
        description: "Light Switch H2 US (double rocker)",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiZigbeeOTA(),
            lumiPreventReset(),
            m.deviceEndpoints({ endpoints: { top: 1, wireless: 4 } }),
            m.bindCluster({ endpointNames: ["top", "wireless"], cluster: "manuSpecificLumi", clusterType: "input" }),
            m.bindCluster({ endpointNames: ["top"], cluster: "genOnOff", clusterType: "input" }),
            lumiPower(),
            lumiOnOff({
                operationMode: true,
                powerOutageMemory: "enum",
                lockRelay: true,
                endpointNames: ["top"],
            }),
            lumiAction({
                actionLookup: { hold: 0, single: 1, double: 2, release: 255 },
                endpointNames: ["top", "wireless"],
            }),
            lumiMultiClick({ description: "Multi-click mode for wireless button", endpointName: "wireless" }),
            lumiLedDisabledNight(),
            lumiFlipIndicatorLight(),
            lumiSwitchMode(),
        ],
    },
    {
        zigbeeModel: ["lumi.sensor_ht.agl001"],
        model: "TH-S04D",
        vendor: "Aqara",
        description: "Climate Sensor W100",
        fromZigbee: [lumi.fromZigbee.lumi_specific, lumi.fromZigbee.w100_specific, lumi.fromZigbee.w100_temperature],
        toZigbee: [lumi.toZigbee.w100_pmtsd, lumi.toZigbee.w100_mode],
        exposes: [
            e
                .binary("thermostat_mode", ea.ALL, "ON", "OFF")
                .withDescription("ON: Enables thermostat mode, buttons send encrypted payloads, and the middle line is displayed. OFF: Disables thermostat mode, buttons send actions, and the middle line is hidden."),
            e
                .climate()
                .withSystemMode(["off", "heat", "cool", "auto"])
                .withFanMode(["auto", "low", "medium", "high"])
                .withSetpoint("occupied_heating_setpoint", 5, 30, 0.5)
                .withLocalTemperature()
                .withDescription("Climate control (HVAC Mode & Target Temperature): Use when thermostat_mode is ON. Configure min/max temperature range in device-specific Settings."),
            e.action(["W100_PMTSD_request"]).withDescription("PMTSD request sent by the W100 via the 08000844 sequence"),
            e
                .text("PMTSD_from_W100_Data", ea.STATE)
                .withDescription('Latest PMTSD values sent by the W100 when manually changed, formatted as "YYYY-MM-DD HH:mm:ss_Px_Mx_Tx_Sx_Dx"'),
            e.battery(),
        ],
        options: [
            e
                .numeric("min_target_temp", ea.STATE_SET)
                .withValueMin(-20)
                .withValueMax(60)
                .withValueStep(0.5)
                .withUnit("°C")
                .withCategory("config")
                .withDescription("Minimum target temperature for the thermostat (default: 5°C)"),
            e
                .numeric("max_target_temp", ea.STATE_SET)
                .withValueMin(-20)
                .withValueMax(60)
                .withValueStep(0.5)
                .withUnit("°C")
                .withCategory("config")
                .withDescription("Maximum target temperature for the thermostat (default: 30°C)"),
        ],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            if (!device.meta)
                device.meta = {};
            // biome-ignore lint/suspicious/noExplicitAny: ignored using `--suppress`
            if (!device.meta.state)
                device.meta.state = {};
            // Send thermostat_mode = OFF. We construct a fake meta object as convertSet needs it.
            // biome-ignore lint/suspicious/noExplicitAny: ignored using `--suppress`
            const meta = { device, state: device.meta.state, logger: logger_1.logger };
            try {
                // biome-ignore lint/suspicious/noExplicitAny: ignored using `--suppress`
                await lumi.toZigbee.w100_mode.convertSet(endpoint, "thermostat_mode", "OFF", meta);
            }
            catch (_error) {
                // ignore
            }
            await reporting.bind(endpoint, coordinatorEndpoint, ["msTemperatureMeasurement"]);
            await endpoint.configureReporting("msTemperatureMeasurement", [
                {
                    attribute: "measuredValue",
                    minimumReportInterval: 10,
                    maximumReportInterval: 3600,
                    reportableChange: 100,
                },
            ]);
            logger_1.logger.info("Aqara W100: configure completed", NS);
        },
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiZigbeeOTA(),
            m.temperature(),
            m.humidity(),
            lumiExternalSensor(),
            m.deviceEndpoints({ endpoints: { plus: 1, center: 2, minus: 3 } }),
            lumiAction({
                actionLookup: { hold: 0, single: 1, double: 2, release: 255 },
                endpointNames: ["plus", "center", "minus"],
            }),
            m.binary({
                name: "auto_hide_middle_line",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0173, type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN },
                valueOn: [true, 0],
                valueOff: [false, 1],
                description: "Applies only when thermostat mode is enabled. True: Hides the middle line after 30 seconds of inactivity. False: Always displays the middle line.",
                access: "ALL",
                entityCategory: "config",
                zigbeeCommandOptions: { manufacturerCode },
                reporting: false,
            }),
            m.numeric({
                name: "high_temperature",
                valueMin: 26,
                valueMax: 60,
                valueStep: 0.5,
                scale: 100,
                unit: "°C",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0167, type: zigbee_herdsman_1.Zcl.DataType.INT16 },
                description: "High temperature alert",
                entityCategory: "config",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "low_temperature",
                valueMin: -20,
                valueMax: 20,
                valueStep: 0.5,
                scale: 100,
                unit: "°C",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0166, type: zigbee_herdsman_1.Zcl.DataType.INT16 },
                description: "Low temperature alert",
                entityCategory: "config",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "high_humidity",
                valueMin: 65,
                valueMax: 100,
                valueStep: 1,
                scale: 100,
                unit: "%",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x016e, type: zigbee_herdsman_1.Zcl.DataType.INT16 },
                description: "High humidity alert",
                entityCategory: "config",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "low_humidity",
                valueMin: 0,
                valueMax: 30,
                valueStep: 1,
                scale: 100,
                unit: "%",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x016d, type: zigbee_herdsman_1.Zcl.DataType.INT16 },
                description: "Low humidity alert",
                entityCategory: "config",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.enumLookup({
                name: "sampling",
                lookup: { low: 1, standard: 2, high: 3, custom: 4 },
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0170, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
                description: "Temperature and Humidity sampling settings",
                entityCategory: "config",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "period",
                valueMin: 0.5,
                valueMax: 600,
                valueStep: 0.5,
                scale: 1000,
                unit: "sec",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0162, type: zigbee_herdsman_1.Zcl.DataType.UINT32 },
                description: "Sampling period",
                entityCategory: "config",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.enumLookup({
                name: "temp_report_mode",
                lookup: { no: 0, threshold: 1, period: 2, threshold_period: 3 },
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0165, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
                description: "Temperature reporting mode",
                entityCategory: "config",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "temp_period",
                valueMin: 1,
                valueMax: 600,
                valueStep: 1,
                scale: 1000,
                unit: "sec",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0163, type: zigbee_herdsman_1.Zcl.DataType.UINT32 },
                description: "Temperature reporting period",
                entityCategory: "config",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "temp_threshold",
                valueMin: 0.2,
                valueMax: 3,
                valueStep: 0.1,
                scale: 100,
                unit: "°C",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0164, type: zigbee_herdsman_1.Zcl.DataType.UINT16 },
                description: "Temperature reporting threshold",
                entityCategory: "config",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.enumLookup({
                name: "humi_report_mode",
                lookup: { no: 0, threshold: 1, period: 2, threshold_period: 3 },
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x016c, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
                description: "Humidity reporting mode",
                entityCategory: "config",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "humi_period",
                valueMin: 1,
                valueMax: 600,
                valueStep: 1,
                scale: 1000,
                unit: "sec",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x016a, type: zigbee_herdsman_1.Zcl.DataType.UINT32 },
                description: "Humidity reporting period",
                entityCategory: "config",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "humi_threshold",
                valueMin: 2,
                valueMax: 10,
                valueStep: 0.5,
                scale: 100,
                unit: "%",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x016b, type: zigbee_herdsman_1.Zcl.DataType.UINT16 },
                description: "Humidity reporting threshold",
                entityCategory: "config",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.identify(),
        ],
    },
    {
        zigbeeModel: ["lumi.switch.agl005"],
        model: "WS-K03E",
        vendor: "Aqara",
        description: "Light Switch H2 US (2 Buttons, 2 Channels)",
        fromZigbee: [fz.on_off, lumi.fromZigbee.lumi_action_multistate, lumi.fromZigbee.lumi_specific],
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumiZigbeeOTA(),
            lumiPreventReset(),
            m.deviceEndpoints({ endpoints: { up: 1, down: 2 } }),
            m.bindCluster({ endpointNames: ["up", "down"], cluster: "manuSpecificLumi", clusterType: "input" }),
            m.bindCluster({ endpointNames: ["up", "down"], cluster: "genOnOff", clusterType: "input" }),
            lumiPower(),
            lumiOnOff({
                operationMode: true,
                powerOutageMemory: "enum",
                lockRelay: true,
                endpointNames: ["up", "down"],
            }),
            lumiAction({
                actionLookup: { hold: 0, single: 1, double: 2, release: 255 },
                endpointNames: ["up", "down"],
            }),
            lumiLedDisabledNight(),
            lumiFlipIndicatorLight(),
            lumiSwitchMode(),
        ],
    },
    {
        zigbeeModel: ["lumi.light.acn006"],
        model: "H1-EU",
        vendor: "Aqara",
        description: "Pro track light",
        extend: [m.light({ colorTemp: { range: [166, 370] } })],
    },
    {
        zigbeeModel: ["lumi.airrtc.aeu005"],
        model: "WT-A03E",
        vendor: "Aqara",
        description: "Radiator thermostat W600",
        meta: {
            overrideHaDiscoveryPayload: (payload) => {
                if (payload.mode_command_topic?.endsWith("/system_mode")) {
                    payload.mode_state_template =
                        "{% if value_json is defined and value_json.system_mode is defined and value_json.system_mode in ['off', 'heat', 'auto'] %}" +
                            "{{ value_json.system_mode }}" +
                            "{% else %}off{% endif %}";
                    payload.preset_mode_value_template =
                        "{% if value_json is defined and value_json.preset is defined and value_json.preset in ['home', 'away', 'sleep', 'vacation', 'wind_down'] %}" +
                            "{{ value_json.preset }}" +
                            "{% else %}none{% endif %}";
                    payload.temperature_state_template =
                        "{% if value_json is defined and value_json.occupied_heating_setpoint is defined and value_json.occupied_heating_setpoint is not none %}" +
                            "{{ value_json.occupied_heating_setpoint }}" +
                            "{% else %}None{% endif %}";
                    payload.current_temperature_template =
                        "{% if value_json is defined and value_json.local_temperature is defined and value_json.local_temperature is not none %}" +
                            "{{ value_json.local_temperature }}" +
                            "{% else %}None{% endif %}";
                }
                if (typeof payload.value_template === "string" && payload.value_template.includes("value_json.override_active")) {
                    payload.icon = "mdi:cursor-pointer";
                }
                if (typeof payload.value_template === "string" && payload.value_template.includes("value_json.schedule_upload_status")) {
                    payload.icon = "mdi:upload-multiple";
                }
                if (typeof payload.value_template === "string" && payload.value_template.includes("value_json.calibrated")) {
                    payload.icon = "mdi:tune";
                }
            },
        },
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            m.customTimeResponse("2000_LOCAL"),
            w600Heartbeat(),
            w600Thermostat(),
            w600ExternalTempSensor(),
            m.enumLookup({
                name: "calibrate",
                lookup: { start: 1 },
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0270, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
                description: "Start valve calibration",
                access: "SET",
                label: "Calibrate",
                entityCategory: "config",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.enumLookup({
                name: "calibrated",
                lookup: { not_ready: 0, ready: 1, error: 2, in_progress: 3 },
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x027b, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
                description: "Valve calibration state",
                access: "STATE_GET",
                label: "Calibration status",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.binary({
                name: "temperature_control_abnormal_notification",
                valueOn: ["ON", 1],
                valueOff: ["OFF", 0],
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0274, type: 0x20 },
                description: "Enable or disable reporting of abnormal temperature control status. When enabled, the valve alarm is set to true if an abnormality is detected",
                access: "ALL",
                label: "Temperature control abnormal notification",
                entityCategory: "config",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.binary({
                name: "display_flip",
                valueOn: ["ON", 1],
                valueOff: ["OFF", 0],
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0330, type: 0x20 },
                description: "Flip the display orientation",
                access: "ALL",
                label: "Display flip",
                entityCategory: "config",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            w600Schedule(),
            m.binary({
                name: "window_detection",
                valueOn: ["ON", 1],
                valueOff: ["OFF", 0],
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0273, type: 0x20 },
                description: "Enable or disable open window detection. When enabled, the window_open is set to true if an open window is detected",
                access: "ALL",
                label: "Open window detection",
                entityCategory: "config",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.binary({
                name: "child_lock",
                valueOn: ["LOCK", 1],
                valueOff: ["UNLOCK", 0],
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0277, type: 0x20 },
                description: "Lock or unlock the physical controls on the device",
                access: "ALL",
                label: "Child lock",
                entityCategory: "config",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "anti_freeze_temperature",
                valueMin: 5,
                valueMax: 15,
                valueStep: 0.5,
                scale: 100,
                unit: "°C",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0279, type: zigbee_herdsman_1.Zcl.DataType.UINT32 },
                description: "Minimum temperature limit for frost protection. Turns the thermostat on regardless of setpoint if the temperature drops below this.",
                entityCategory: "config",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            w600PresetTemperatureTable(),
            w600WeeklySchedule(),
            w600ValvePosition(),
            m.identify(),
            lumiZigbeeOTA(),
        ],
    },
    {
        zigbeeModel: ["lumi.airrtc.aeu001"],
        model: "UT-A01E",
        vendor: "Aqara",
        description: "Floor heating thermostat W500",
        ota: true,
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            m.electricityMeter({ current: false, voltage: false, power: { divisor: 1 }, energy: { divisor: 1000 } }),
            m.thermostat({
                setpoints: { values: { occupiedHeatingSetpoint: { min: 5, max: 40, step: 0.5 } }, configure: { skip: true } },
                localTemperatureCalibration: { values: true },
                temperatureSetpointHold: { configure: { skip: true } },
                temperatureSetpointHoldDuration: true,
                systemMode: { values: ["off", "heat"] },
                runningState: {
                    values: ["idle", "heat", "cool", "fan_only"],
                },
                setpointsLimit: {
                    maxHeatSetpointLimit: { min: 5, max: 30, step: 0.5 },
                    minHeatSetpointLimit: { min: 5, max: 30, step: 0.5 },
                },
            }),
            m.enumLookup({
                name: "preset",
                lookup: { home: 1, away: 2, sleep: 3, vacation: 5, evening: 6, manual: 8 },
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0311, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
                description: "Preset",
                access: "ALL",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.enumLookup({
                name: "state",
                lookup: { working: 0, idle: 2 },
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0310, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
                description: "State",
                access: "STATE_GET",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.humidity({ reporting: false }),
            m.enumLookup({
                name: "sensor",
                lookup: { internal: 0, external: 1, ntc: 2 },
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0280, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
                description: "Temperature sensor source",
                access: "ALL",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.enumLookup({
                name: "ntc_sensor_type",
                lookup: { ntc_10k: 10, ntc_50k: 50, ntc_100k: 100, unknown: 10000 },
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0315, type: zigbee_herdsman_1.Zcl.DataType.UINT32 },
                description: "NTC sensor type (k - KOhm)",
                access: "ALL",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.binary({
                name: "window_detection",
                valueOn: ["ON", 1],
                valueOff: ["OFF", 0],
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0273, type: 0x20 },
                description: "Enables/disables window detection on the device",
                access: "ALL",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            lumi.lumiModernExtend.lumiPowerOutageMemory(),
            m.binary({
                name: "child_lock",
                valueOn: ["LOCK", 1],
                valueOff: ["UNLOCK", 0],
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0277, type: 0x20 },
                description: "Enables/disables physical input on the device",
                access: "ALL",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "hysteresis",
                valueMin: 0,
                valueMax: 3,
                valueStep: 0.5,
                scale: 10,
                unit: "°C",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x030c, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
                description: "Hysteresis",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.identify(),
        ],
    },
    {
        zigbeeModel: ["lumi.sensor_occupy.agl8"],
        model: "PS-S04D",
        vendor: "Aqara",
        description: "Presence sensor FP300",
        fromZigbee: [lumi.fromZigbee.lumi_specific],
        toZigbee: [lumi.toZigbee.lumi_presence, lumi.toZigbee.lumi_motion_sensitivity],
        exposes: [e.power_outage_count(), e.motion_sensitivity_select(["low", "medium", "high"]).withDescription("Presence Detection Sensitivity.")],
        version: "0.0.2",
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            await endpoint.read("manuSpecificLumi", [0x00ee], { manufacturerCode: manufacturerCode }); // Read OTA data; makes the device expose more attributes related to OTA
            await endpoint.read("manuSpecificLumi", [0x010c], { manufacturerCode: manufacturerCode }); // Read motion sensitivity
            await endpoint.read("manuSpecificLumi", [0x0142], { manufacturerCode: manufacturerCode }); // Read current presence
            await endpoint.read("manuSpecificLumi", [0x014f], { manufacturerCode: manufacturerCode }); // Read current PIR interval
            await endpoint.read("manuSpecificLumi", [0x0197], { manufacturerCode: manufacturerCode }); // Read current absence delay timer value
            await endpoint.read("manuSpecificLumi", [0x019a], { manufacturerCode: manufacturerCode }); // Read detection range
            await endpoint.read("manuSpecificLumi", [0x00f7], { manufacturerCode: manufacturerCode }); // Read battery data; firmware 0.0.0_6542 does not push the 0x00F7 struct on its own
            // Configure reporting so presence (0x0142) and PIR detection (0x014d) update autonomously.
            await reporting.bind(endpoint, coordinatorEndpoint, ["manuSpecificLumi"]);
            await endpoint.configureReporting("manuSpecificLumi", [
                { attribute: { ID: 0x0142, type: zigbee_herdsman_1.Zcl.DataType.UINT8 }, minimumReportInterval: 0, maximumReportInterval: 3600, reportableChange: 1 },
                { attribute: { ID: 0x014d, type: zigbee_herdsman_1.Zcl.DataType.UINT8 }, minimumReportInterval: 0, maximumReportInterval: 3600, reportableChange: 1 },
            ], { manufacturerCode: manufacturerCode });
        },
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumi.lumiModernExtend.lumiPreventLeave(),
            m.quirkCheckinInterval("1_HOUR"), // No genPollCtrl; gives the request queue a lifetime so fp300BatteryPoll's queued read survives until the device wakes
            lumi.lumiModernExtend.lumiBattery({
                voltageAttribute: 0x0017, // Attribute: 23 (battery voltage in mV)
                percentageAttribute: 0x0018, // Attribute: 24 (battery percentage, the device's own gauge; tracks discharge consistently with attribute 23)
            }),
            lumi.lumiModernExtend.fp300BatteryPoll(),
            lumi.lumiModernExtend.fp1ePresence(),
            lumi.lumiModernExtend.fp300PIRDetection(),
            m.enumLookup({
                name: "presence_detection_options",
                lookup: { both: 0, mmwave: 1, pir: 2 },
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0199, type: zigbee_herdsman_1.Zcl.DataType.UINT8 }, // Attribute: 409
                description: "Presence detection sensor type",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            lumi.lumiModernExtend.fp1eAIInterference(),
            lumi.lumiModernExtend.fp1eAdaptiveSensitivity(),
            m.numeric({
                name: "absence_delay_timer",
                valueMin: 1,
                valueMax: 300,
                valueStep: 1,
                scale: 1,
                unit: "sec",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0197, type: zigbee_herdsman_1.Zcl.DataType.UINT32 }, // Attribute: 407
                description: "Value for delay before the device reports absence when no presence is detected",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "pir_detection_interval",
                valueMin: 2, // Min: 2S
                valueMax: 300, // Max: 300s
                valueStep: 1, // Step: 1s
                scale: 1,
                unit: "sec",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x014f, type: zigbee_herdsman_1.Zcl.DataType.UINT16 }, // Attribute: 335
                description: "Higher detection frequency results in higher accuracy but lower battery life.",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.illuminance(),
            m.humidity(),
            m.temperature(),
            lumi.lumiModernExtend.fp1eSpatialLearning(),
            lumi.lumiModernExtend.fp1eRestartDevice(),
            m.identify(),
            // Sampling parameters
            m.enumLookup({
                name: "temp_and_humidity_sampling",
                lookup: { off: 0, low: 1, medium: 2, high: 3, custom: 4 },
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0170, type: zigbee_herdsman_1.Zcl.DataType.UINT8 }, // Attribute: 368
                description: "Sampling time frequency, increasing affects battery life. Setting to custom allows specifying period, interval & threshold.",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "temp_and_humidity_sampling_period",
                valueMin: 0.5, // Min: 500ms
                valueMax: 3600, // Max: 1h = 3600s
                valueStep: 0.5, // Step: 500ms
                scale: 1000,
                unit: "sec",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0162, type: zigbee_herdsman_1.Zcl.DataType.UINT32 }, // Attribute: 354
                description: "How often temp & humidity readings are taken on the device when in custom mode.",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            // Temperature
            m.numeric({
                name: "temp_reporting_interval",
                valueMin: 600, // Min: 10min = 600s
                valueMax: 3600, // Max: 1h = 3600s
                valueStep: 600, // Step: 10min = 600s
                scale: 1000,
                unit: "sec",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0163, type: zigbee_herdsman_1.Zcl.DataType.UINT32 }, // Attribute: 355
                description: "Custom time interval for temperature data reporting.",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "temp_reporting_threshold",
                valueMin: 0.2, // Min: 0,2 C
                valueMax: 3, // Max: 3,0 C
                valueStep: 0.1, // Step: 0,1 C
                scale: 100,
                unit: "°C",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0164, type: zigbee_herdsman_1.Zcl.DataType.UINT16 }, // Attribute: 356
                description: "Reporting will trigger as temperature change reaches this value when in custom mode.",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.enumLookup({
                name: "temp_reporting_mode",
                lookup: { threshold: 1, "reporting interval": 2, "threshold and interval": 3 },
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0165, type: zigbee_herdsman_1.Zcl.DataType.UINT8 }, // Attribute: 357
                description: "Temperature reporting type when in custom mode.",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            // Humidity
            m.numeric({
                name: "humidity_reporting_interval",
                valueMin: 600, // Min: 10min = 600s
                valueMax: 3600, // Max: 1h = 3600s
                valueStep: 600, // Step: 10min = 600s
                scale: 1000,
                unit: "sec",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x016a, type: zigbee_herdsman_1.Zcl.DataType.UINT32 }, // Attribute: 362
                description: "Custom time interval for humidity data reporting.",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "humidity_reporting_threshold",
                valueMin: 2, // Min: 2%
                valueMax: 15, // Max: 15%
                valueStep: 0.5, // Step: 0,5%
                scale: 100,
                unit: "%",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x016b, type: zigbee_herdsman_1.Zcl.DataType.UINT16 }, // Attribute: 363
                description: "Reporting will trigger as humidity change reaches this value when in custom mode.",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.enumLookup({
                name: "humidity_report_mode",
                lookup: { threshold: 1, "reporting interval": 2, "threshold and interval": 3 },
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x016c, type: zigbee_herdsman_1.Zcl.DataType.UINT8 }, // Attribute: 364
                description: "Humidity reporting type when in custom mode.",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            // Illuminance
            m.enumLookup({
                name: "light_sampling",
                lookup: { off: 0, low: 1, medium: 2, high: 3, custom: 4 },
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0192, type: zigbee_herdsman_1.Zcl.DataType.UINT8 }, // Attribute: 402
                description: "Sampling time frequency, increasing affects battery life. Setting to custom allows specifying period, interval & threshold.",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "light_sampling_period",
                valueMin: 0.5, // Min: 500ms
                valueMax: 3600, // Max: 1h = 3600s
                valueStep: 0.5, // Step: 500ms
                scale: 1000,
                unit: "sec",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0193, type: zigbee_herdsman_1.Zcl.DataType.UINT32 }, // Attribute: 403
                description: "How often illumination readings are taken on the device when in custom mode.",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "light_reporting_interval",
                valueMin: 20, // Min: 20s
                valueMax: 3600, // Max: 1h = 3600s
                valueStep: 20, // Step: 20s
                scale: 1000,
                unit: "sec",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0194, type: zigbee_herdsman_1.Zcl.DataType.UINT32 }, // attribute 404
                description: "Custom interval for illumination data reporting.",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "light_reporting_threshold",
                valueMin: 3, // Min: 3%
                valueMax: 20, /// Max: 20%
                valueStep: 0.5, // Step: 0,5%
                scale: 100,
                unit: "%",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0195, type: zigbee_herdsman_1.Zcl.DataType.UINT16 }, // Attribute: 405
                description: "Reporting will trigger as illumination percentage change reaches this value when in custom mode.",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.enumLookup({
                name: "light_report_mode",
                lookup: { threshold: 1, "reporting interval": 2, "threshold and interval": 3 },
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0196, type: zigbee_herdsman_1.Zcl.DataType.UINT8 }, // Attribute: 406
                description: "illumination reporting type when in custom mode.",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            // Read current target distance
            lumi.lumiModernExtend.fp300TrackDistance(),
            lumi.lumiModernExtend.fp1eTargetDistance(), // Same attribute. Need to send 0x0198 to start tracking
            // Set detection range
            lumi.lumiModernExtend.fp300DetectionRange(),
            // LED Indicator
            lumi.lumiModernExtend.lumiLedDisabledNight(),
            lumi.lumiModernExtend.lumiLedDisabledNightTime(),
            // OTA
            m.quirkCheckinInterval("1_HOUR"),
            lumi.lumiModernExtend.lumiZigbeeOTA(),
        ],
    },
    {
        zigbeeModel: ["aqara.toilet.acn002", "lumi.sen_gas.hrcn01"], // The reason for adding lumi.sen_gas.hrcn01 is that the model number reported by a toilet is exactly this
        model: "ACN002",
        vendor: "Aqara",
        description: "Smart Toilet T1",
        fromZigbee: [lumi.fromZigbee.lumi_toilet],
        toZigbee: [lumi.toZigbee.lumi_toilet],
        exposes: [
            e.binary("lid_switch", ea.STATE_SET, "OPEN", "CLOSE").withDescription("Lid status"),
            e.binary("seat_switch", ea.STATE_SET, "OPEN", "CLOSE").withDescription("Seat status"),
            e.binary("night_light", ea.STATE_SET, "ON", "OFF").withDescription("Night light"),
            e
                .enum("seat_temp", ea.STATE_SET, ["Off", "Temp_31C", "Temp_33C", "Temp_35C", "Temp_37C", "Temp_39C"])
                .withDescription("Seat heating temperature"),
            e
                .enum("cleaning_mode", ea.STATE_SET, ["Stop", "Rear", "Rear_Moving", "Female", "Female_Moving", "Child"])
                .withDescription("Cleaning mode"),
            e
                .enum("water_temp", ea.STATE_SET, ["Off", "Temp_31C", "Temp_33C", "Temp_35C", "Temp_37C", "Temp_39C"])
                .withDescription("Cleaning water temperature"),
            e
                .enum("water_pressure", ea.STATE_SET, ["Weak", "Slightly_Weak", "Middle", "Slightly_Strong", "Strong"])
                .withDescription("Water pressure"),
            e
                .enum("nozzle_position", ea.STATE_SET, ["Back", "Slightly_Back", "Middle", "Slightly_Front", "Front"])
                .withDescription("Nozzle position"),
            e
                .enum("dryer_temp", ea.STATE_SET, ["Off", "Normal", "Low", "Mid_Low", "Middle", "Mid_High", "High"])
                .withDescription("Dryer wind temperature"),
            e.enum("nozzle_clean", ea.STATE_SET, ["Off", "Auto", "Manual"]).withDescription("Nozzle self-cleaning"),
            e.binary("occupancy_status", ea.STATE, true, false).withDescription("Occupancy status"),
            e.enum("stop_button", ea.SET, ["STOP"]).withDescription("Stop operation"),
            e.enum("flush_big", ea.SET, ["FLUSH"]).withDescription("Full flush"),
            e.enum("flush_small", ea.SET, ["FLUSH"]).withDescription("Small flush"),
            e.enum("foam_shield", ea.SET, ["RELEASE"]).withDescription("Release splash-proof foam"),
            e.binary("pre_mist_switch", ea.STATE_SET, "ON", "OFF").withDescription("Pre-mist when sitting").withCategory("config"),
            e.binary("auto_foam_on_sit", ea.STATE_SET, "ON", "OFF").withDescription("Automatic foam when sitting").withCategory("config"),
            e.binary("auto_foam_on_leave", ea.STATE_SET, "ON", "OFF").withDescription("Automatic foam when leaving").withCategory("config"),
            e.binary("child_seat_mode", ea.STATE_SET, "ON", "OFF").withDescription("Child seat mode").withCategory("config"),
            e.binary("foot_sensor_switch", ea.STATE_SET, "ON", "OFF").withDescription("Foot sensor").withCategory("config"),
            e.binary("auto_flush_after_leave", ea.STATE_SET, "ON", "OFF").withDescription("Auto flush after leaving").withCategory("config"),
            e.binary("beeper_switch", ea.STATE_SET, "ON", "OFF").withDescription("Beeper sound").withCategory("config"),
        ],
        extend: [lumi.modernExtend.addManuSpecificLumiCluster(), lumiZigbeeOTA(), m.forcePowerSource({ powerSource: "Mains (single phase)" })],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            await endpoint.read("manuSpecificLumi", [0xfff1], { manufacturerCode: manufacturerCode });
        },
    },
    {
        zigbeeModel: ["lumi.sensor_occupy.acn1"],
        model: "FP310",
        vendor: "Aqara",
        description: "Presence sensor FP310",
        fromZigbee: [lumi.fromZigbee.lumi_specific],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            await endpoint.read("manuSpecificLumi", [0x00ee], { manufacturerCode: manufacturerCode }); // Read OTA data; makes the device expose more attributes related to OTA
            await endpoint.read("manuSpecificLumi", [0x010c], { manufacturerCode: manufacturerCode }); // Read motion sensitivity
            await endpoint.read("manuSpecificLumi", [0x0142], { manufacturerCode: manufacturerCode }); // Read current presence
            await endpoint.read("manuSpecificLumi", [0x0197], { manufacturerCode: manufacturerCode }); // Read current absence delay timer value
            await endpoint.read("manuSpecificLumi", [0x019a], { manufacturerCode: manufacturerCode }); // Read detection range
        },
        extend: [
            lumi.modernExtend.addManuSpecificLumiCluster(),
            lumi.lumiModernExtend.lumiPreventLeave(),
            lumi.lumiModernExtend.lumiBattery({
                voltageToPercentage: { min: 2850, max: 3000 },
                voltageAttribute: 0x0017, // Attribute: 23
                //percentageAttribute: 0x0018 // Attribute: 24 // TODO: Should confirm to be sure
            }),
            lumi.lumiModernExtend.fp1ePresence(),
            m.illuminance(),
            m.humidity(),
            m.temperature(),
            m.enumLookup({
                name: "presence_sensitivity",
                lookup: { low: 1, medium: 2, high: 3 },
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x010c, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
                description: "Presence Detection Sensitivity",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "absence_delay_timer",
                valueMin: 10,
                valueMax: 300,
                valueStep: 5,
                scale: 1,
                unit: "sec",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0197, type: zigbee_herdsman_1.Zcl.DataType.UINT32 }, // Attribute: 407
                description: "Value for delay before the device reports absence when no presence is detected",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            lumi.lumiModernExtend.fp1eSpatialLearning(),
            lumi.lumiModernExtend.fp1eRestartDevice(),
            // AI
            lumi.lumiModernExtend.fp1eAIInterference(),
            lumi.lumiModernExtend.fp1eAdaptiveSensitivity(),
            // Sampling parameters
            m.enumLookup({
                name: "temp_and_humidity_sampling",
                lookup: { off: 0, low: 1, medium: 2, high: 3, custom: 4 },
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0170, type: zigbee_herdsman_1.Zcl.DataType.UINT8 }, // Attribute: 368
                description: "Sampling time frequency, increasing affects battery life. Setting to custom allows specifying period, interval & threshold.",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "temp_and_humidity_sampling_period",
                valueMin: 0.5, // Min: 500ms
                valueMax: 3600, // Max: 1h = 3600s
                valueStep: 0.5, // Step: 500ms
                scale: 1000,
                unit: "sec",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0162, type: zigbee_herdsman_1.Zcl.DataType.UINT32 }, // Attribute: 354
                description: "How often temp & humidity readings are taken on the device when in custom mode.",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            // Temperature
            m.numeric({
                name: "temp_reporting_interval",
                valueMin: 600, // Min: 10min = 600s
                valueMax: 3600, // Max: 1h = 3600s
                valueStep: 600, // Step: 10min = 600s
                scale: 1000,
                unit: "sec",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0163, type: zigbee_herdsman_1.Zcl.DataType.UINT32 }, // Attribute: 355
                description: "Custom time interval for temperature data reporting.",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "temp_reporting_threshold",
                valueMin: 0.2, // Min: 0,2 C
                valueMax: 3, // Max: 3,0 C
                valueStep: 0.1, // Step: 0,1 C
                scale: 100,
                unit: "°C",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0164, type: zigbee_herdsman_1.Zcl.DataType.UINT16 }, // Attribute: 356
                description: "Reporting will trigger as temperature change reaches this value when in custom mode.",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.enumLookup({
                name: "temp_reporting_mode",
                lookup: { threshold: 1, "reporting interval": 2, "threshold and interval": 3 },
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0165, type: zigbee_herdsman_1.Zcl.DataType.UINT8 }, // Attribute: 357
                description: "Temperature reporting type when in custom mode.",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            // Humidity
            m.numeric({
                name: "humidity_reporting_interval",
                valueMin: 600, // Min: 10min = 600s
                valueMax: 3600, // Max: 1h = 3600s
                valueStep: 600, // Step: 10min = 600s
                scale: 1000,
                unit: "sec",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x016a, type: zigbee_herdsman_1.Zcl.DataType.UINT32 }, // Attribute: 362
                description: "Custom time interval for humidity data reporting.",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "humidity_reporting_threshold",
                valueMin: 2, // Min: 2%
                valueMax: 15, // Max: 15%
                valueStep: 0.5, // Step: 0,5%
                scale: 100,
                unit: "%",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x016b, type: zigbee_herdsman_1.Zcl.DataType.UINT16 }, // Attribute: 363
                description: "Reporting will trigger as humidity change reaches this value when in custom mode.",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.enumLookup({
                name: "humidity_report_mode",
                lookup: { threshold: 1, "reporting interval": 2, "threshold and interval": 3 },
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x016c, type: zigbee_herdsman_1.Zcl.DataType.UINT8 }, // Attribute: 364
                description: "Humidity reporting type when in custom mode.",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            // Illuminance
            m.enumLookup({
                name: "light_sampling",
                lookup: { off: 0, low: 1, medium: 2, high: 3, custom: 4 },
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0192, type: zigbee_herdsman_1.Zcl.DataType.UINT8 }, // Attribute: 402
                description: "Sampling time frequency, increasing affects battery life. Setting to custom allows specifying period, interval & threshold.",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "light_sampling_period",
                valueMin: 0.5, // Min: 500ms
                valueMax: 3600, // Max: 1h = 3600s
                valueStep: 0.5, // Step: 500ms
                scale: 1000,
                unit: "sec",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0193, type: zigbee_herdsman_1.Zcl.DataType.UINT32 }, // Attribute: 403
                description: "How often illumination readings are taken on the device when in custom mode.",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "light_reporting_interval",
                valueMin: 20, // Min: 20s
                valueMax: 3600, // Max: 1h = 3600s
                valueStep: 20, // Step: 20s
                scale: 1000,
                unit: "sec",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0194, type: zigbee_herdsman_1.Zcl.DataType.UINT32 }, // attribute 404
                description: "Custom interval for illumination data reporting.",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.numeric({
                name: "light_reporting_threshold",
                valueMin: 3, // Min: 3%
                valueMax: 20, /// Max: 20%
                valueStep: 0.5, // Step: 0,5%
                scale: 100,
                unit: "%",
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0195, type: zigbee_herdsman_1.Zcl.DataType.UINT16 }, // Attribute: 405
                description: "Reporting will trigger as illumination percentage change reaches this value when in custom mode.",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            m.enumLookup({
                name: "light_report_mode",
                lookup: { threshold: 1, "reporting interval": 2, "threshold and interval": 3 },
                cluster: "manuSpecificLumi",
                attribute: { ID: 0x0196, type: zigbee_herdsman_1.Zcl.DataType.UINT8 }, // Attribute: 406
                description: "illumination reporting type when in custom mode.",
                zigbeeCommandOptions: { manufacturerCode },
            }),
            // Read current target distance
            lumi.lumiModernExtend.fp300TrackDistance(),
            lumi.lumiModernExtend.fp1eTargetDistance(), // Same attribute. Need to send 0x0198 to start tracking
            // Set detection range
            fp310DetectionRange(),
            // LED Indicator
            lumi.lumiModernExtend.lumiLedDisabledNight(),
            lumi.lumiModernExtend.lumiLedDisabledNightTime(),
            m.identify(),
            // OTA
            m.quirkCheckinInterval("1_HOUR"),
            lumi.lumiModernExtend.lumiZigbeeOTA(),
        ],
    },
];
//# sourceMappingURL=lumi.js.map