"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.m = exports.VZM36_ATTRIBUTES = exports.VZM35_ATTRIBUTES = exports.VZM32_MMWAVE_ATTRIBUTES = exports.VZM32_ATTRIBUTES = exports.VZM31_ATTRIBUTES = exports.VZM30_ATTRIBUTES = exports.Model = exports.INOVELLI = exports.MMWAVE_CLUSTER_NAME = exports.CLUSTER_NAME = void 0;
const zigbee_herdsman_1 = require("zigbee-herdsman");
const enums_1 = require("zigbee-herdsman/dist/zspec/zcl/definition/enums");
const fz = __importStar(require("../converters/fromZigbee"));
const tz = __importStar(require("../converters/toZigbee"));
const exposes = __importStar(require("./exposes"));
const m = __importStar(require("./modernExtend"));
const reporting = __importStar(require("./reporting"));
const globalStore = __importStar(require("./store"));
const utils = __importStar(require("./utils"));
const e = exposes.presets;
const ea = exposes.access;
const clickLookup = {
    0: "single",
    1: "release",
    2: "held",
    3: "double",
    4: "triple",
    5: "quadruple",
    6: "quintuple",
};
const buttonLookup = {
    1: "down",
    2: "up",
    3: "config",
    4: "aux_down",
    5: "aux_up",
    6: "aux_config",
};
const ledEffects = {
    off: 0,
    solid: 1,
    fast_blink: 2,
    slow_blink: 3,
    pulse: 4,
    chase: 5,
    open_close: 6,
    small_to_big: 7,
    aurora: 8,
    slow_falling: 9,
    medium_falling: 10,
    fast_falling: 11,
    slow_rising: 12,
    medium_rising: 13,
    fast_rising: 14,
    medium_blink: 15,
    slow_chase: 16,
    fast_chase: 17,
    fast_siren: 18,
    slow_siren: 19,
    clear_effect: 255,
};
const individualLedEffects = {
    off: 0,
    solid: 1,
    fast_blink: 2,
    slow_blink: 3,
    pulse: 4,
    chase: 5,
    falling: 6,
    rising: 7,
    aurora: 8,
    clear_effect: 255,
};
const mmWaveControlCommands = {
    reset_mmwave_module: 0,
    set_interference: 1,
    query_areas: 2,
    clear_interference: 3,
    reset_detection_area: 4,
    clear_stay_areas: 5,
};
const INOVELLI_CLUSTER_NAME = "manuSpecificInovelli";
const INOVELLI_MMWAVE_CLUSTER_NAME = "manuSpecificInovelliMMWave";
exports.CLUSTER_NAME = INOVELLI_CLUSTER_NAME;
exports.MMWAVE_CLUSTER_NAME = INOVELLI_MMWAVE_CLUSTER_NAME;
exports.INOVELLI = 0x122f;
const inovelliExtend = {
    addCustomCluster: () => m.deviceAddCustomCluster(INOVELLI_CLUSTER_NAME, {
        name: INOVELLI_CLUSTER_NAME,
        ID: 64561,
        manufacturerCode: 0x122f,
        attributes: {
            dimmingSpeedUpRemote: { name: "dimmingSpeedUpRemote", ID: 0x0001, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            dimmingSpeedUpLocal: { name: "dimmingSpeedUpLocal", ID: 0x0002, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            rampRateOffToOnRemote: { name: "rampRateOffToOnRemote", ID: 0x0003, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            rampRateOffToOnLocal: { name: "rampRateOffToOnLocal", ID: 0x0004, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            dimmingSpeedDownRemote: { name: "dimmingSpeedDownRemote", ID: 0x0005, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            dimmingSpeedDownLocal: { name: "dimmingSpeedDownLocal", ID: 0x0006, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            rampRateOnToOffRemote: { name: "rampRateOnToOffRemote", ID: 0x0007, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            rampRateOnToOffLocal: { name: "rampRateOnToOffLocal", ID: 0x0008, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            minimumLevel: { name: "minimumLevel", ID: 0x0009, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            maximumLevel: { name: "maximumLevel", ID: 0x000a, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            invertSwitch: { name: "invertSwitch", ID: 0x000b, type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN, write: true },
            autoTimerOff: { name: "autoTimerOff", ID: 0x000c, type: zigbee_herdsman_1.Zcl.DataType.UINT16, write: true, max: 0xffff },
            defaultLevelLocal: { name: "defaultLevelLocal", ID: 0x000d, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            defaultLevelRemote: { name: "defaultLevelRemote", ID: 0x000e, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            stateAfterPowerRestored: { name: "stateAfterPowerRestored", ID: 0x000f, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            loadLevelIndicatorTimeout: { name: "loadLevelIndicatorTimeout", ID: 0x0011, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            activePowerReports: { name: "activePowerReports", ID: 0x0012, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            periodicPowerAndEnergyReports: {
                name: "periodicPowerAndEnergyReports",
                ID: 0x0013,
                type: zigbee_herdsman_1.Zcl.DataType.UINT16,
                write: true,
                max: 0xffff,
            },
            activeEnergyReports: { name: "activeEnergyReports", ID: 0x0014, type: zigbee_herdsman_1.Zcl.DataType.UINT16, write: true, max: 0xffff },
            powerType: { name: "powerType", ID: 0x0015, type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN, write: true },
            switchType: { name: "switchType", ID: 0x0016, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            quickStartTime: { name: "quickStartTime", ID: 0x0017, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            quickStartLevel: { name: "quickStartLevel", ID: 0x0018, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            higherOutputInNonNeutral: { name: "higherOutputInNonNeutral", ID: 0x0019, type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN, write: true },
            dimmingMode: { name: "dimmingMode", ID: 0x001a, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            dimmingAlgorithm: { name: "dimmingAlgorithm", ID: 0x001b, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            auxDetectionLevel: { name: "auxDetectionLevel", ID: 0x007c, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            dumbDetectionLevel: { name: "dumbDetectionLevel", ID: 0x00a5, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            nonNeutralAuxMediumGear: { name: "nonNeutralAuxMediumGear", ID: 0x001e, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            nonNeutralAuxLowGear: { name: "nonNeutralAuxLowGear", ID: 0x001f, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            internalTemperature: { name: "internalTemperature", ID: 0x0020, type: zigbee_herdsman_1.Zcl.DataType.INT8, write: true, max: 0xff },
            overheat: { name: "overheat", ID: 0x0021, type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN, write: true },
            otaImageType: { name: "otaImageType", ID: 0x0022, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            buttonDelay: { name: "buttonDelay", ID: 0x0032, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            deviceBindNumber: { name: "deviceBindNumber", ID: 0x0033, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            smartBulbMode: { name: "smartBulbMode", ID: 0x0034, type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN, write: true },
            doubleTapUpToParam55: { name: "doubleTapUpToParam55", ID: 0x0035, type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN, write: true },
            doubleTapDownToParam56: { name: "doubleTapDownToParam56", ID: 0x0036, type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN, write: true },
            brightnessLevelForDoubleTapUp: { name: "brightnessLevelForDoubleTapUp", ID: 0x0037, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            brightnessLevelForDoubleTapDown: {
                name: "brightnessLevelForDoubleTapDown",
                ID: 0x0038,
                type: zigbee_herdsman_1.Zcl.DataType.UINT8,
                write: true,
                max: 0xff,
            },
            defaultLed1ColorWhenOn: { name: "defaultLed1ColorWhenOn", ID: 0x003c, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            defaultLed1ColorWhenOff: { name: "defaultLed1ColorWhenOff", ID: 0x003d, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            defaultLed1IntensityWhenOn: { name: "defaultLed1IntensityWhenOn", ID: 0x003e, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            defaultLed1IntensityWhenOff: { name: "defaultLed1IntensityWhenOff", ID: 0x003f, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            defaultLed2ColorWhenOn: { name: "defaultLed2ColorWhenOn", ID: 0x0041, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            defaultLed2ColorWhenOff: { name: "defaultLed2ColorWhenOff", ID: 0x0042, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            defaultLed2IntensityWhenOn: { name: "defaultLed2IntensityWhenOn", ID: 0x0043, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            defaultLed2IntensityWhenOff: { name: "defaultLed2IntensityWhenOff", ID: 0x0044, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            defaultLed3ColorWhenOn: { name: "defaultLed3ColorWhenOn", ID: 0x0046, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            defaultLed3ColorWhenOff: { name: "defaultLed3ColorWhenOff", ID: 0x0047, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            defaultLed3IntensityWhenOn: { name: "defaultLed3IntensityWhenOn", ID: 0x0048, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            defaultLed3IntensityWhenOff: { name: "defaultLed3IntensityWhenOff", ID: 0x0049, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            defaultLed4ColorWhenOn: { name: "defaultLed4ColorWhenOn", ID: 0x004b, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            defaultLed4ColorWhenOff: { name: "defaultLed4ColorWhenOff", ID: 0x004c, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            defaultLed4IntensityWhenOn: { name: "defaultLed4IntensityWhenOn", ID: 0x004d, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            defaultLed4IntensityWhenOff: { name: "defaultLed4IntensityWhenOff", ID: 0x004e, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            defaultLed5ColorWhenOn: { name: "defaultLed5ColorWhenOn", ID: 0x0050, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            defaultLed5ColorWhenOff: { name: "defaultLed5ColorWhenOff", ID: 0x0051, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            defaultLed5IntensityWhenOn: { name: "defaultLed5IntensityWhenOn", ID: 0x0052, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            defaultLed5IntensityWhenOff: { name: "defaultLed5IntensityWhenOff", ID: 0x0053, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            defaultLed6ColorWhenOn: { name: "defaultLed6ColorWhenOn", ID: 0x0055, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            defaultLed6ColorWhenOff: { name: "defaultLed6ColorWhenOff", ID: 0x0056, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            defaultLed6IntensityWhenOn: { name: "defaultLed6IntensityWhenOn", ID: 0x0057, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            defaultLed6IntensityWhenOff: { name: "defaultLed6IntensityWhenOff", ID: 0x0058, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            defaultLed7ColorWhenOn: { name: "defaultLed7ColorWhenOn", ID: 0x005a, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            defaultLed7ColorWhenOff: { name: "defaultLed7ColorWhenOff", ID: 0x005b, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            defaultLed7IntensityWhenOn: { name: "defaultLed7IntensityWhenOn", ID: 0x005c, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            defaultLed7IntensityWhenOff: { name: "defaultLed7IntensityWhenOff", ID: 0x005d, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            ledColorWhenOn: { name: "ledColorWhenOn", ID: 0x005f, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            ledColorWhenOff: { name: "ledColorWhenOff", ID: 0x060, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            ledIntensityWhenOn: { name: "ledIntensityWhenOn", ID: 0x0061, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            ledIntensityWhenOff: { name: "ledIntensityWhenOff", ID: 0x0062, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            ledBarScaling: { name: "ledBarScaling", ID: 0x0064, type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN, write: true },
            mmwaveControlWiredDevice: { name: "mmwaveControlWiredDevice", ID: 0x006e, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            mmWaveRoomSizePreset: { name: "mmWaveRoomSizePreset", ID: 0x0075, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            singleTapBehavior: { name: "singleTapBehavior", ID: 0x0078, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            fanTimerMode: { name: "fanTimerMode", ID: 0x0079, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            auxSwitchUniqueScenes: { name: "auxSwitchUniqueScenes", ID: 0x007b, type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN, write: true },
            bindingOffToOnSyncLevel: { name: "bindingOffToOnSyncLevel", ID: 0x007d, type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN, write: true },
            breezeMode: { name: "breezeMode", ID: 0x0081, type: zigbee_herdsman_1.Zcl.DataType.UINT32, write: true, max: 0xffffffff },
            fanControlMode: { name: "fanControlMode", ID: 0x0082, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            lowLevelForFanControlMode: { name: "lowLevelForFanControlMode", ID: 0x0083, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            mediumLevelForFanControlMode: { name: "mediumLevelForFanControlMode", ID: 0x0084, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            highLevelForFanControlMode: { name: "highLevelForFanControlMode", ID: 0x0085, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            ledColorForFanControlMode: { name: "ledColorForFanControlMode", ID: 0x0086, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
            localProtection: { name: "localProtection", ID: 0x0100, type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN, write: true },
            remoteProtection: { name: "remoteProtection", ID: 0x0101, type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN, write: true },
            outputMode: { name: "outputMode", ID: 0x0102, type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN, write: true },
            onOffLedMode: { name: "onOffLedMode", ID: 0x0103, type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN, write: true },
            firmwareUpdateInProgressIndicator: { name: "firmwareUpdateInProgressIndicator", ID: 0x0104, type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN, write: true },
            relayClick: { name: "relayClick", ID: 0x105, type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN, write: true },
            doubleTapClearNotifications: { name: "doubleTapClearNotifications", ID: 0x106, type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN, write: true },
            fanLedLevelType: { name: "fanLedLevelType", ID: 0x0107, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
        },
        commands: {
            ledEffect: {
                name: "ledEffect",
                ID: 1,
                parameters: [
                    { name: "effect", type: zigbee_herdsman_1.Zcl.DataType.UINT8, max: 0xff },
                    { name: "color", type: zigbee_herdsman_1.Zcl.DataType.UINT8, max: 0xff },
                    { name: "level", type: zigbee_herdsman_1.Zcl.DataType.UINT8, max: 0xff },
                    { name: "duration", type: zigbee_herdsman_1.Zcl.DataType.UINT8, max: 0xff },
                ],
            },
            energyReset: {
                name: "energyReset",
                ID: 2,
                parameters: [],
            },
            individualLedEffect: {
                name: "individualLedEffect",
                ID: 3,
                parameters: [
                    { name: "led", type: zigbee_herdsman_1.Zcl.DataType.UINT8, max: 0xff },
                    { name: "effect", type: zigbee_herdsman_1.Zcl.DataType.UINT8, max: 0xff },
                    { name: "color", type: zigbee_herdsman_1.Zcl.DataType.UINT8, max: 0xff },
                    { name: "level", type: zigbee_herdsman_1.Zcl.DataType.UINT8, max: 0xff },
                    { name: "duration", type: zigbee_herdsman_1.Zcl.DataType.UINT8, max: 0xff },
                ],
            },
            ledEffectComplete: {
                name: "ledEffectComplete",
                ID: 0x24,
                parameters: [{ name: "notificationType", type: zigbee_herdsman_1.Zcl.DataType.INT8, min: -128 }],
            },
        },
        commandsResponse: {},
    }),
    addCustomMMWaveCluster: () => {
        const mmWaveCommandAreaParameters = [
            { name: "areaId", type: zigbee_herdsman_1.Zcl.DataType.UINT8, max: 3 },
            { name: "xMin", type: zigbee_herdsman_1.Zcl.DataType.INT16, min: -600, max: 600 },
            { name: "xMax", type: zigbee_herdsman_1.Zcl.DataType.INT16, min: -600, max: 600 },
            { name: "yMin", type: zigbee_herdsman_1.Zcl.DataType.INT16, min: -600, max: 600 },
            { name: "yMax", type: zigbee_herdsman_1.Zcl.DataType.INT16, min: -600, max: 600 },
            { name: "zMin", type: zigbee_herdsman_1.Zcl.DataType.INT16, min: -600, max: 600 },
            { name: "zMax", type: zigbee_herdsman_1.Zcl.DataType.INT16, min: -600, max: 600 },
        ];
        const mmWaveCommandResponseAreaParameters = [
            { name: "count", type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
            { name: "xMin1", type: zigbee_herdsman_1.Zcl.DataType.INT16 },
            { name: "xMax1", type: zigbee_herdsman_1.Zcl.DataType.INT16 },
            { name: "yMin1", type: zigbee_herdsman_1.Zcl.DataType.INT16 },
            { name: "yMax1", type: zigbee_herdsman_1.Zcl.DataType.INT16 },
            { name: "zMin1", type: zigbee_herdsman_1.Zcl.DataType.INT16 },
            { name: "zMax1", type: zigbee_herdsman_1.Zcl.DataType.INT16 },
            { name: "xMin2", type: zigbee_herdsman_1.Zcl.DataType.INT16 },
            { name: "xMax2", type: zigbee_herdsman_1.Zcl.DataType.INT16 },
            { name: "yMin2", type: zigbee_herdsman_1.Zcl.DataType.INT16 },
            { name: "yMax2", type: zigbee_herdsman_1.Zcl.DataType.INT16 },
            { name: "zMin2", type: zigbee_herdsman_1.Zcl.DataType.INT16 },
            { name: "zMax2", type: zigbee_herdsman_1.Zcl.DataType.INT16 },
            { name: "xMin3", type: zigbee_herdsman_1.Zcl.DataType.INT16 },
            { name: "xMax3", type: zigbee_herdsman_1.Zcl.DataType.INT16 },
            { name: "yMin3", type: zigbee_herdsman_1.Zcl.DataType.INT16 },
            { name: "yMax3", type: zigbee_herdsman_1.Zcl.DataType.INT16 },
            { name: "zMin3", type: zigbee_herdsman_1.Zcl.DataType.INT16 },
            { name: "zMax3", type: zigbee_herdsman_1.Zcl.DataType.INT16 },
            { name: "xMin4", type: zigbee_herdsman_1.Zcl.DataType.INT16 },
            { name: "xMax4", type: zigbee_herdsman_1.Zcl.DataType.INT16 },
            { name: "yMin4", type: zigbee_herdsman_1.Zcl.DataType.INT16 },
            { name: "yMax4", type: zigbee_herdsman_1.Zcl.DataType.INT16 },
            { name: "zMin4", type: zigbee_herdsman_1.Zcl.DataType.INT16 },
            { name: "zMax4", type: zigbee_herdsman_1.Zcl.DataType.INT16 },
        ];
        return m.deviceAddCustomCluster(INOVELLI_MMWAVE_CLUSTER_NAME, {
            name: INOVELLI_MMWAVE_CLUSTER_NAME,
            ID: 64562, // 0xfc32
            manufacturerCode: 0x122f,
            attributes: {
                mmWaveHoldTime: { name: "mmWaveHoldTime", ID: 0x0072, type: zigbee_herdsman_1.Zcl.DataType.UINT32, write: true, max: 0xffffffff },
                mmWaveDetectSensitivity: { name: "mmWaveDetectSensitivity", ID: 0x0070, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
                mmWaveDetectTrigger: { name: "mmWaveDetectTrigger", ID: 0x0071, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
                mmWaveTargetInfoReport: { name: "mmWaveTargetInfoReport", ID: 0x006b, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
                mmWaveStayLife: { name: "mmWaveStayLife", ID: 0x006c, type: zigbee_herdsman_1.Zcl.DataType.UINT32, write: true, max: 0xffffffff },
                mmWaveVersion: { name: "mmWaveVersion", ID: 0x0073, type: zigbee_herdsman_1.Zcl.DataType.UINT32, write: true, max: 0xffffffff },
                mmWaveHeightMin: { name: "mmWaveHeightMin", ID: 0x0065, type: zigbee_herdsman_1.Zcl.DataType.INT16, write: true, min: -32768 },
                mmWaveHeightMax: { name: "mmWaveHeightMax", ID: 0x0066, type: zigbee_herdsman_1.Zcl.DataType.INT16, write: true, min: -32768 },
                mmWaveWidthMin: { name: "mmWaveWidthMin", ID: 0x0067, type: zigbee_herdsman_1.Zcl.DataType.INT16, write: true, min: -32768 },
                mmWaveWidthMax: { name: "mmWaveWidthMax", ID: 0x0068, type: zigbee_herdsman_1.Zcl.DataType.INT16, write: true, min: -32768 },
                mmWaveDepthMin: { name: "mmWaveDepthMin", ID: 0x0069, type: zigbee_herdsman_1.Zcl.DataType.INT16, write: true, min: -32768 },
                mmWaveDepthMax: { name: "mmWaveDepthMax", ID: 0x006a, type: zigbee_herdsman_1.Zcl.DataType.INT16, write: true, min: -32768 },
            },
            commands: {
                mmWaveControl: {
                    name: "mmWaveControl",
                    ID: 0,
                    parameters: [{ name: "controlID", type: zigbee_herdsman_1.Zcl.DataType.UINT8, max: 0xff }],
                },
                setInterferenceArea: {
                    name: "setInterferenceArea",
                    ID: 1,
                    parameters: mmWaveCommandAreaParameters,
                },
                setDetectionArea: {
                    name: "setDetectionArea",
                    ID: 2,
                    parameters: mmWaveCommandAreaParameters,
                },
                setStayArea: {
                    name: "setStayArea",
                    ID: 3,
                    parameters: mmWaveCommandAreaParameters,
                },
            },
            commandsResponse: {
                anyoneInReportingArea: {
                    name: "anyoneInReportingArea",
                    ID: 0,
                    parameters: [
                        { name: "area1", type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
                        { name: "area2", type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
                        { name: "area3", type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
                        { name: "area4", type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
                    ],
                },
                reportTargetInfo: {
                    name: "reportTargetInfo",
                    ID: 1,
                    parameters: [
                        { name: "targetNum", type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
                        { name: "targets", type: enums_1.BuffaloZclDataType.BUFFER },
                    ],
                },
                reportInterferenceArea: {
                    name: "reportInterferenceArea",
                    ID: 2,
                    parameters: mmWaveCommandResponseAreaParameters,
                },
                reportDetectionArea: {
                    name: "reportDetectionArea",
                    ID: 3,
                    parameters: mmWaveCommandResponseAreaParameters,
                },
                reportStayArea: {
                    name: "reportStayArea",
                    ID: 4,
                    parameters: mmWaveCommandResponseAreaParameters,
                },
            },
        });
    },
    parameters: ({ attrs, model, splitValuesByEndpoint = false, }) => {
        const fromZigbee = [];
        const toZigbee = [];
        for (const attr of attrs) {
            fromZigbee.push(fzLocal.inovelli(attr.attributes, attr.clusterName, splitValuesByEndpoint, model));
            toZigbee.push(tzLocal.inovelli_parameters(attr.attributes, attr.clusterName, model), tzLocal.inovelli_parameters_read_only(attr.attributes, attr.clusterName));
        }
        const dynamicExposes = (device, _options) => {
            const result = [];
            if (utils.isDummyDevice(device)) {
                for (const attr of attrs) {
                    attributesToExposeList(adjustAttributesForDevice(attr.attributes, model), result);
                }
            }
            else {
                const fw = device.softwareBuildID ? parseFirmwareVersion(device.softwareBuildID) : undefined;
                for (const attr of attrs) {
                    attributesToExposeList(adjustAttributesForDevice(attr.attributes, model, fw), result);
                }
            }
            return result;
        };
        const configure = [
            async (device, coordinatorEndpoint, definition) => {
                const endpoint = device.getEndpoint(1);
                await reporting.bind(endpoint, coordinatorEndpoint, [INOVELLI_CLUSTER_NAME]);
                let endpoint2;
                if (splitValuesByEndpoint) {
                    endpoint2 = device.getEndpoint(2);
                    await reporting.bind(endpoint2, coordinatorEndpoint, [INOVELLI_CLUSTER_NAME]);
                }
                const fw = device.softwareBuildID ? parseFirmwareVersion(device.softwareBuildID) : undefined;
                for (const attr of attrs) {
                    const filtered = adjustAttributesForDevice(attr.attributes, model, fw);
                    if (!splitValuesByEndpoint || !endpoint2) {
                        await chunkedRead(endpoint, Object.keys(filtered), attr.clusterName);
                    }
                    else {
                        await chunkedRead(endpoint, Object.keys(filtered).flatMap((key) => {
                            const keysplit = key.split("_");
                            if (keysplit.length === 2) {
                                if (Number(keysplit[1]) === 1) {
                                    return [keysplit[0]];
                                }
                                return [];
                            }
                            return [key];
                        }), attr.clusterName);
                        await chunkedRead(endpoint2, Object.keys(filtered).flatMap((key) => {
                            const keysplit = key.split("_");
                            if (keysplit.length === 2) {
                                if (Number(keysplit[1]) === 2) {
                                    return [keysplit[0]];
                                }
                            }
                            return [];
                        }), attr.clusterName);
                    }
                }
            },
        ];
        return {
            fromZigbee,
            toZigbee,
            exposes: [dynamicExposes],
            configure,
            isModernExtend: true,
        };
    },
    ledEffects: () => {
        return {
            fromZigbee: [fzLocal.led_effect_complete],
            toZigbee: [tzLocal.inovelli_led_effect, tzLocal.inovelli_individual_led_effect],
            exposes: [exposeLedEffects(), exposeIndividualLedEffects(), exposeLedEffectComplete()],
            isModernExtend: true,
        };
    },
    buttonTaps: () => {
        const configure = [
            async (device, coordinatorEndpoint, definition) => {
                const endpoint2 = device.getEndpoint(2);
                await reporting.bind(endpoint2, coordinatorEndpoint, [INOVELLI_CLUSTER_NAME]);
            },
        ];
        return {
            fromZigbee: [fzLocal.button_taps],
            exposes: [e.action(BUTTON_TAP_SEQUENCES)],
            configure,
            isModernExtend: true,
        };
    },
    light: ({ splitValuesByEndpoint = false } = {}) => {
        const fromZigbee = [fzLocal.on_off_for_endpoint(1, "state"), fzLocal.brightness];
        if (!splitValuesByEndpoint) {
            fromZigbee.push(fz.level_config, fz.power_on_behavior);
        }
        const configure = [
            async (device, coordinatorEndpoint, definition) => {
                const endpoint = device.getEndpoint(1);
                await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff", "genLevelCtrl"]);
                await reporting.onOff(endpoint);
            },
        ];
        return {
            fromZigbee,
            toZigbee: [
                tzLocal.light_onoff_brightness_inovelli,
                tz.power_on_behavior,
                tz.ignore_transition,
                tz.light_brightness_move,
                tz.light_brightness_step,
                tz.level_config,
            ],
            exposes: [e.light_brightness()],
            configure,
            isModernExtend: true,
        };
    },
    fan: ({ endpointId, splitValuesByEndpoint = false }) => {
        return {
            fromZigbee: [fzLocal.fan_mode(endpointId), fzLocal.breeze_mode(endpointId), fzLocal.fan_state(endpointId)],
            toZigbee: [tzLocal.fan_mode(endpointId), tzLocal.breezeMode(endpointId), tzLocal.fan_state(endpointId)],
            exposes: [e.fan().withState("fan_state").withModes(Object.keys(FAN_MODES)), exposeBreezeMode()],
            configure: [
                async (device, coordinatorEndpoint, definition) => {
                    const endpoint = device.getEndpoint(endpointId);
                    await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff", "genLevelCtrl"]);
                    await reporting.onOff(endpoint);
                },
            ],
            isModernExtend: true,
        };
    },
    mmWave: () => {
        const configure = [
            async (device, coordinatorEndpoint, definition) => {
                const endpoint = device.getEndpoint(1);
                await reporting.bind(endpoint, coordinatorEndpoint, [INOVELLI_MMWAVE_CLUSTER_NAME]);
                await endpoint.command(INOVELLI_MMWAVE_CLUSTER_NAME, "mmWaveControl", {
                    controlID: mmWaveControlCommands.query_areas,
                }, { disableResponse: true, disableDefaultResponse: true });
            },
        ];
        return {
            fromZigbee: [fzLocal.anyone_in_reporting_area, fzLocal.report_areas, fzLocal.report_target_info],
            toZigbee: [
                tzLocal.inovelli_mmwave_control_commands,
                tzLocal.mmwave_detection_areas,
                tzLocal.mmwave_interference_areas,
                tzLocal.mmwave_stay_areas,
            ],
            exposes: [
                exposeMMWaveControl(),
                ...exposeMMWaveAreas(),
                exposeInterferenceAreas(),
                exposeDetectionAreas(),
                exposeStayAreas(),
                exposeMMWaveTargets(),
            ],
            configure: configure,
            isModernExtend: true,
        };
    },
    energyReset: () => {
        return {
            toZigbee: [tzLocal.inovelli_energy_reset],
            exposes: [exposeEnergyReset()],
            isModernExtend: true,
        };
    },
};
exports.m = inovelliExtend;
const FAN_MODES = { off: 0, low: 2, smart: 4, medium: 86, high: 170, on: 255 };
const BREEZE_MODES = ["off", "low", "medium", "high"];
const LED_NOTIFICATION_TYPES = {
    0: "LED_1",
    1: "LED_2",
    2: "LED_3",
    3: "LED_4",
    4: "LED_5",
    5: "LED_6",
    6: "LED_7",
    16: "ALL_LEDS",
    "-1": "CONFIG_BUTTON_DOUBLE_PRESS",
};
exports.Model = {
    VZM30: "VZM30-SN",
    VZM31: "VZM31-SN",
    VZM32: "VZM32-SN",
    VZM35: "VZM35-SN",
    VZM36: "VZM36",
};
// Converts brightness level to a fan mode
const intToFanMode = (value) => {
    let selectedMode = "low";
    if (value >= FAN_MODES.low) {
        selectedMode = "low";
    }
    if (value >= FAN_MODES.medium) {
        selectedMode = "medium";
    }
    if (value >= FAN_MODES.high) {
        selectedMode = "high";
    }
    if (value === 4) {
        selectedMode = "smart";
    }
    if (value === 0) {
        selectedMode = "off";
    }
    return selectedMode;
};
/**
 * Convert speed string to int needed for breeze mode calculation.
 * @param speedIn - speed string
 * @returns low = 1, medium = 2, high = 3, off = 0
 */
const speedToInt = (speedIn) => {
    switch (speedIn) {
        case "low":
            return 1;
        case "medium":
            return 2;
        case "high":
            return 3;
        default:
            return 0;
    }
};
const parseFirmwareVersion = (version) => {
    const match = version.match(/(\d+)\.(\d+)/);
    if (!match)
        return undefined;
    return [Number.parseInt(match[1], 10), Number.parseInt(match[2], 10)];
};
const fwGte = (firmware, target) => {
    return firmware[0] > target[0] || (firmware[0] === target[0] && firmware[1] >= target[1]);
};
const resolveValueMap = (attr, model) => {
    if (!attr.modelValues)
        return undefined;
    const entry = model ? attr.modelValues[model] : undefined;
    return entry?.values ?? attr.modelValues.default.values;
};
const adjustAttributesForDevice = (attributes, model, firmware) => {
    const result = {};
    for (const [key, attr] of Object.entries(attributes)) {
        if (attr.addedInFirmware) {
            const threshold = attr.addedInFirmware[model];
            if (!threshold)
                continue;
            if (firmware && !fwGte(firmware, threshold))
                continue;
        }
        if (attr.modelValues) {
            const entry = attr.modelValues[model] ?? attr.modelValues.default;
            const baseValues = { ...(entry.values ?? attr.modelValues.default.values) };
            if (firmware && entry.conditionalValues) {
                for (const [valueName, constraint] of Object.entries(entry.conditionalValues)) {
                    if (!(valueName in baseValues))
                        continue;
                    if (constraint.addedInFirmware && !fwGte(firmware, constraint.addedInFirmware)) {
                        delete baseValues[valueName];
                    }
                    if (constraint.removedInFirmware && fwGte(firmware, constraint.removedInFirmware)) {
                        delete baseValues[valueName];
                    }
                }
            }
            const { modelValues: _, ...rest } = attr;
            result[key] = { ...rest, values: baseValues };
            continue;
        }
        result[key] = attr;
    }
    return result;
};
// Create Expose list with Inovelli Parameters definitions
const attributesToExposeList = (attributes, exposesList) => {
    Object.keys(attributes).forEach((key) => {
        if (attributes[key].displayType === "enum") {
            const enumE = e
                .enum(key, attributes[key].readOnly ? ea.STATE_GET : ea.ALL, Object.keys(attributes[key].values ?? {}))
                .withDescription(attributes[key].description);
            if (!attributes[key].readOnly) {
                enumE.withCategory(attributes[key].category ?? "config");
            }
            exposesList.push(enumE);
        }
        else if (attributes[key].displayType === "binary" || attributes[key].displayType === "switch") {
            const binary = e
                .binary(key, attributes[key].readOnly ? ea.STATE_GET : ea.ALL, 
            // @ts-expect-error ignore
            attributes[key].values.Enabled, attributes[key].values.Disabled)
                .withDescription(attributes[key].description);
            if (!attributes[key].readOnly) {
                binary.withCategory(attributes[key].category ?? "config");
            }
            exposesList.push(binary);
        }
        else {
            const numeric = e
                .numeric(key, attributes[key].readOnly ? ea.STATE_GET : ea.ALL)
                .withValueMin(attributes[key].min)
                .withValueMax(attributes[key].max);
            if (attributes[key].values) {
                Object.keys(attributes[key].values).forEach((value) => {
                    numeric.withPreset(value, attributes[key].values[value], "");
                });
            }
            if (attributes[key].unit) {
                numeric.withUnit(attributes[key].unit);
            }
            numeric.withDescription(attributes[key].description);
            if (!attributes[key].readOnly) {
                numeric.withCategory(attributes[key].category ?? "config");
            }
            exposesList.push(numeric);
        }
    });
};
/**
 * Attribute composition: COMMON_ATTRIBUTES is the base; COMMON_DIMMER_*, COMMON_DIMMABLE_LIGHT_*,
 * COMMON_DIMMER_ON_OFF_* extend it; VZM*_ATTRIBUTES are device-specific compositions. Only VZM* are exported.
 */
/**
 * Common Attributes
 *
 * These attributes are shared between all devices with the manufacturer specific Inovelli cluster
 * Some of the descriptions, max, min or value properties may be overridden for each device
 */
const COMMON_ATTRIBUTES = {
    dimmingSpeedUpRemote: {
        id: 1,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 127,
        description: "This changes the speed that the light dims up when controlled from the hub. " +
            "A setting of 0 turns the light immediately on. Increasing the value slows down the transition speed. " +
            "Every number represents 100ms. Default = 25 (2.5s)",
    },
    dimmingSpeedUpLocal: {
        id: 2,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 127,
        description: "This changes the speed that the light dims up when controlled at the switch. " +
            "A setting of 0 turns the light immediately on. Increasing the value slows down the transition speed. " +
            "Every number represents 100ms. Default = 127 - Keep in sync with dimmingSpeedUpRemote setting.",
    },
    rampRateOffToOnRemote: {
        id: 3,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 127,
        description: "This changes the speed that the light turns on when controlled from the hub. " +
            "A setting of 0 turns the light immediately on. Increasing the value slows down the transition speed. " +
            "Every number represents 100ms. Default = 127 - Keep in sync with dimmingSpeedUpRemote setting.",
    },
    rampRateOffToOnLocal: {
        id: 4,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 127,
        description: "This changes the speed that the light turns on when controlled at the switch. " +
            "A setting of 0 turns the light immediately on. Increasing the value slows down the transition speed. " +
            "Every number represents 100ms. Default = 127 - Keep in sync with dimmingSpeedUpRemote setting.",
    },
    dimmingSpeedDownRemote: {
        id: 5,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 127,
        description: "This changes the speed that the light dims down when controlled from the hub. " +
            "A setting of 0 turns the light immediately off. Increasing the value slows down the transition speed. " +
            "Every number represents 100ms. Default = 127 - Keep in sync with dimmingSpeedUpRemote setting.",
    },
    dimmingSpeedDownLocal: {
        id: 6,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 127,
        description: "This changes the speed that the light dims down when controlled at the switch. " +
            "A setting of 0 turns the light immediately off. Increasing the value slows down the transition speed. " +
            "Every number represents 100ms. Default = 127 - Keep in sync with dimmingSpeedUpLocal setting.",
    },
    rampRateOnToOffRemote: {
        id: 7,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 127,
        description: "This changes the speed that the light turns off when controlled from the hub. " +
            "A setting of 'instant' turns the light immediately off. Increasing the value slows down the transition speed. " +
            "Every number represents 100ms. Default = 127 - Keep in sync with rampRateOffToOnRemote setting.",
    },
    rampRateOnToOffLocal: {
        id: 8,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 127,
        description: "This changes the speed that the light turns off when controlled at the switch. " +
            "A setting of 'instant' turns the light immediately off. Increasing the value slows down the transition speed. " +
            "Every number represents 100ms. Default = 127 - Keep in sync with rampRateOffToOnLocal setting.",
    },
    invertSwitch: {
        id: 11,
        dataType: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
        displayType: "enum",
        modelValues: { default: { values: { Yes: 1, No: 0 } } },
        min: 0,
        max: 1,
        description: "Inverts the orientation of the switch." +
            " Useful when the switch is installed upside down. Essentially up becomes down and down becomes up.",
    },
    autoTimerOff: {
        id: 12,
        min: 0,
        max: 32767,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT16,
        unit: "seconds",
        modelValues: { default: { values: { Disabled: 0 } } },
        description: "Automatically turns the switch off after this many seconds." +
            " When the switch is turned on a timer is started. When the timer expires, the switch is turned off. 0 = Auto off is disabled.",
    },
    defaultLevelLocal: {
        id: 13,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 255,
        description: "Default level for the load when it is turned on at the switch." +
            " A setting of 255 means that the switch will return to the level that it was on before it was turned off.",
    },
    defaultLevelRemote: {
        id: 14,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 255,
        description: "Default level for the load when it is turned on from the hub." +
            " A setting of 255 means that the switch will return to the level that it was on before it was turned off.",
    },
    stateAfterPowerRestored: {
        id: 15,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 255,
        description: "The state the switch should return to when power is restored after power failure. 0 = off, 1-254 = level, 255 = previous.",
    },
    loadLevelIndicatorTimeout: {
        id: 17,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        description: "Shows the level that the load is at for x number of seconds after the load is adjusted" +
            " and then returns to the Default LED state. 0 = Stay Off, 1-10 = seconds, 11 = Stay On.",
        displayType: "enum",
        modelValues: {
            default: {
                values: {
                    "Stay Off": 0,
                    "1 Second": 1,
                    "2 Seconds": 2,
                    "3 Seconds": 3,
                    "4 Seconds": 4,
                    "5 Seconds": 5,
                    "6 Seconds": 6,
                    "7 Seconds": 7,
                    "8 Seconds": 8,
                    "9 Seconds": 9,
                    "10 Seconds": 10,
                    "Stay On": 11,
                },
            },
        },
        min: 0,
        max: 11,
    },
    switchType: {
        id: 22,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        displayType: "enum",
        modelValues: {
            default: { values: { "Single Pole": 0, "Aux Switch": 1 } },
            [exports.Model.VZM31]: {
                values: { "Single Pole": 0, "3-Way Dumb Switch": 1, "3-Way Aux Switch": 2, "Single-Pole Full Sine Wave": 3 },
                conditionalValues: { "Single-Pole Full Sine Wave": { removedInFirmware: [3, 0] } },
            },
        },
        min: 0,
        max: 3,
        description: "Set the switch configuration.",
    },
    internalTemperature: {
        id: 32,
        dataType: zigbee_herdsman_1.Zcl.DataType.INT8,
        min: 0,
        max: 127,
        readOnly: true,
        description: "The temperature measured by the temperature sensor inside the chip, in degrees Celsius",
        category: "diagnostic",
        unit: "°C",
    },
    overheat: {
        id: 33,
        dataType: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
        displayType: "enum",
        modelValues: { default: { values: { "No Alert": 0, Overheated: 1 } } },
        min: 0,
        max: 1,
        readOnly: true,
        description: "Indicates if the internal chipset is currently in an overheated state.",
    },
    buttonDelay: {
        id: 50,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        modelValues: {
            default: {
                values: {
                    "0ms": 0,
                    "100ms": 1,
                    "200ms": 2,
                    "300ms": 3,
                    "400ms": 4,
                    "500ms": 5,
                    "600ms": 6,
                    "700ms": 7,
                    "800ms": 8,
                    "900ms": 9,
                },
            },
        },
        displayType: "enum",
        min: 0,
        max: 9,
        description: "This will set the button press delay. 0 = no delay (Disables Button Press Events), Default = 500ms.",
    },
    deviceBindNumber: {
        id: 51,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        readOnly: true,
        description: "The number of devices currently bound (excluding gateways) and counts one group as two devices",
    },
    smartBulbMode: {
        id: 52,
        dataType: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
        displayType: "enum",
        modelValues: {
            default: { values: { Disabled: 0, "Smart Bulb Mode": 1 } },
            [exports.Model.VZM35]: { values: { Disabled: 0, "Smart Fan Mode": 1 } },
        },
        description: "For use with Smart Bulbs that need constant power and are controlled via commands rather than power.",
    },
    doubleTapUpToParam55: {
        id: 53,
        dataType: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
        displayType: "enum",
        modelValues: { default: { values: { Disabled: 0, Enabled: 1 } } },
        description: "Enable or Disable setting level to parameter 55 on double-tap UP.",
    },
    doubleTapDownToParam56: {
        id: 54,
        dataType: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
        displayType: "enum",
        modelValues: { default: { values: { Disabled: 0, Enabled: 1 } } },
        description: "Enable or Disable setting level to parameter 56 on double-tap DOWN.",
    },
    brightnessLevelForDoubleTapUp: {
        id: 55,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 2,
        max: 255,
        description: "Set this level on double-tap UP (if enabled by P53). 255 = send ON command.",
    },
    brightnessLevelForDoubleTapDown: {
        id: 56,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 255,
        description: "Set this level on double-tap DOWN (if enabled by P54). 255 = send OFF command.",
    },
    ledColorWhenOn: {
        id: 95,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 255,
        modelValues: {
            default: {
                values: {
                    Red: 0,
                    Orange: 21,
                    Yellow: 42,
                    Green: 85,
                    Cyan: 127,
                    Blue: 170,
                    Violet: 212,
                    Pink: 234,
                    White: 255,
                },
            },
        },
        description: "Set the color of the LED Indicator when the load is on.",
    },
    ledColorWhenOff: {
        id: 96,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 255,
        modelValues: {
            default: {
                values: {
                    Red: 0,
                    Orange: 21,
                    Yellow: 42,
                    Green: 85,
                    Cyan: 127,
                    Blue: 170,
                    Violet: 212,
                    Pink: 234,
                    White: 255,
                },
            },
        },
        description: "Set the color of the LED Indicator when the load is off.",
    },
    ledIntensityWhenOn: {
        id: 97,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 100,
        description: "Set the intensity of the LED Indicator when the load is on.",
    },
    ledIntensityWhenOff: {
        id: 98,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 100,
        description: "Set the intensity of the LED Indicator when the load is off.",
    },
    singleTapBehavior: {
        id: 120,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        displayType: "enum",
        modelValues: { default: { values: { "Old Behavior": 0, "New Behavior": 1, "Down Always Off": 2 } } },
        description: "Behavior of single tapping the on or off button. Old behavior turns the switch on or off. " +
            "New behavior cycles through the levels set by P131-133. Down Always Off is like the new behavior but " +
            "down always turns the switch off instead of going to next lower speed.",
    },
    fanControlMode: {
        id: 130,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        displayType: "enum",
        modelValues: {
            default: { values: { Disabled: 0, "Multi Tap": 1, Cycle: 2, Toggle: 3 } },
            [exports.Model.VZM31]: {
                conditionalValues: { Toggle: { addedInFirmware: [3, 0] } },
            },
        },
        description: "Which mode to use when binding EP3 (config button) to another device (like a fan module).",
    },
    lowLevelForFanControlMode: {
        id: 131,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 2,
        max: 254,
        description: "Level to send to device bound to EP3 when set to low.",
    },
    mediumLevelForFanControlMode: {
        id: 132,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 2,
        max: 254,
        description: "Level to send to device bound to EP3 when set to medium.",
    },
    highLevelForFanControlMode: {
        id: 133,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 2,
        max: 254,
        description: "Level to send to device bound to EP3 when set to high.",
    },
    ledColorForFanControlMode: {
        id: 134,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 255,
        modelValues: {
            default: {
                values: {
                    Red: 0,
                    Orange: 21,
                    Yellow: 42,
                    Green: 85,
                    Cyan: 127,
                    Blue: 170,
                    Violet: 212,
                    Pink: 234,
                    White: 255,
                },
            },
        },
        description: "LED color used to display fan control mode.",
    },
    auxSwitchUniqueScenes: {
        id: 123,
        dataType: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
        displayType: "enum",
        modelValues: { default: { values: { Disabled: 0, Enabled: 1 } } },
        description: "Have unique scene numbers for scenes activated with the aux switch.",
    },
    bindingOffToOnSyncLevel: {
        id: 125,
        dataType: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
        displayType: "enum",
        modelValues: { default: { values: { Disabled: 0, Enabled: 1 } } },
        description: "Send Move_To_Level using Default Level with Off/On to bound devices.",
    },
    localProtection: {
        id: 256,
        dataType: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
        modelValues: { default: { values: { Disabled: 0, Enabled: 1 } } },
        description: "Ability to control switch from the wall.",
        displayType: "enum",
    },
    remoteProtection: {
        id: 257,
        dataType: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
        modelValues: { default: { values: { Disabled: 0, Enabled: 1 } } },
        readOnly: true,
        description: "Ability to control switch from the hub.",
        displayType: "enum",
    },
    onOffLedMode: {
        id: 259,
        min: 0,
        max: 1,
        modelValues: { default: { values: { All: 0, One: 1 } } },
        dataType: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
        description: "When the device is in On/Off mode, use full LED bar or just one LED.",
        displayType: "enum",
    },
    firmwareUpdateInProgressIndicator: {
        id: 260,
        dataType: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
        modelValues: { default: { values: { Disabled: 0, Enabled: 1 } } },
        description: "Display progress on LED bar during firmware update.",
        displayType: "enum",
    },
    defaultLed1ColorWhenOn: {
        id: 60,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 255,
        description: "0-254:This is the color of the LED strip in a hex representation. 255:Synchronization with default all LED strip color parameter.",
    },
    defaultLed1ColorWhenOff: {
        id: 61,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 255,
        description: "0-254:This is the color of the LED strip in a hex representation. 255:Synchronization with default all LED strip color parameter.",
    },
    defaultLed1IntensityWhenOn: {
        id: 62,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 101,
        description: "Intensity of LED strip when on. 101 = Synchronized with default all LED strip intensity parameter.",
    },
    defaultLed1IntensityWhenOff: {
        id: 63,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 101,
        description: "Intensity of LED strip when off. 101 = Synchronized with default all LED strip intensity parameter.",
    },
    defaultLed2ColorWhenOn: {
        id: 65,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 255,
        description: "0-254:This is the color of the LED strip in a hex representation. 255:Synchronization with default all LED strip color parameter.",
    },
    defaultLed2ColorWhenOff: {
        id: 66,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 255,
        description: "0-254:This is the color of the LED strip in a hex representation. 255:Synchronization with default all LED strip color parameter.",
    },
    defaultLed2IntensityWhenOn: {
        id: 67,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 101,
        description: "Intensity of LED strip when on. 101 = Synchronized with default all LED strip intensity parameter.",
    },
    defaultLed2IntensityWhenOff: {
        id: 68,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 101,
        description: "Intensity of LED strip when off. 101 = Synchronized with default all LED strip intensity parameter.",
    },
    defaultLed3ColorWhenOn: {
        id: 70,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 255,
        description: "0-254:This is the color of the LED strip in a hex representation. 255:Synchronization with default all LED strip color parameter.",
    },
    defaultLed3ColorWhenOff: {
        id: 71,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 255,
        description: "0-254:This is the color of the LED strip in a hex representation. 255:Synchronization with default all LED strip color parameter.",
    },
    defaultLed3IntensityWhenOn: {
        id: 72,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 101,
        description: "Intensity of LED strip when on. 101 = Synchronized with default all LED strip intensity parameter.",
    },
    defaultLed3IntensityWhenOff: {
        id: 73,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 101,
        description: "Intensity of LED strip when off. 101 = Synchronized with default all LED strip intensity parameter.",
    },
    defaultLed4ColorWhenOn: {
        id: 75,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 255,
        description: "0-254:This is the color of the LED strip in a hex representation. 255:Synchronization with default all LED strip color parameter.",
    },
    defaultLed4ColorWhenOff: {
        id: 76,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 255,
        description: "0-254:This is the color of the LED strip in a hex representation. 255:Synchronization with default all LED strip color parameter.",
    },
    defaultLed4IntensityWhenOn: {
        id: 77,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 101,
        description: "Intensity of LED strip when on. 101 = Synchronized with default all LED strip intensity parameter.",
    },
    defaultLed4IntensityWhenOff: {
        id: 78,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 101,
        description: "Intensity of LED strip when off. 101 = Synchronized with default all LED strip intensity parameter.",
    },
    defaultLed5ColorWhenOn: {
        id: 80,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 255,
        description: "0-254:This is the color of the LED strip in a hex representation. 255:Synchronization with default all LED strip color parameter.",
    },
    defaultLed5ColorWhenOff: {
        id: 81,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 255,
        description: "0-254:This is the color of the LED strip in a hex representation. 255:Synchronization with default all LED strip color parameter.",
    },
    defaultLed5IntensityWhenOn: {
        id: 82,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 101,
        description: "Intensity of LED strip when on. 101 = Synchronized with default all LED strip intensity parameter.",
    },
    defaultLed5IntensityWhenOff: {
        id: 83,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 101,
        description: "Intensity of LED strip when off. 101 = Synchronized with default all LED strip intensity parameter.",
    },
    defaultLed6ColorWhenOn: {
        id: 85,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 255,
        description: "0-254:This is the color of the LED strip in a hex representation. 255:Synchronization with default all LED strip color parameter.",
    },
    defaultLed6ColorWhenOff: {
        id: 86,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 255,
        description: "0-254:This is the color of the LED strip in a hex representation. 255:Synchronization with default all LED strip color parameter.",
    },
    defaultLed6IntensityWhenOn: {
        id: 87,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 101,
        description: "Intensity of LED strip when on. 101 = Synchronized with default all LED strip intensity parameter.",
    },
    defaultLed6IntensityWhenOff: {
        id: 88,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 101,
        description: "Intensity of LED strip when off. 101 = Synchronized with default all LED strip intensity parameter.",
    },
    defaultLed7ColorWhenOn: {
        id: 90,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 255,
        description: "0-254:This is the color of the LED strip in a hex representation. 255:Synchronization with default all LED strip color parameter.",
    },
    defaultLed7ColorWhenOff: {
        id: 91,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 255,
        description: "0-254:This is the color of the LED strip in a hex representation. 255:Synchronization with default all LED strip color parameter.",
    },
    defaultLed7IntensityWhenOn: {
        id: 92,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 101,
        description: "Intensity of LED strip when on. 101 = Synchronized with default all LED strip intensity parameter.",
    },
    defaultLed7IntensityWhenOff: {
        id: 93,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 101,
        description: "Intensity of LED strip when off. 101 = Synchronized with default all LED strip intensity parameter.",
    },
    fanTimerMode: {
        id: 121,
        dataType: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
        displayType: "enum",
        modelValues: { default: { values: { Disabled: 0, Enabled: 1 } } },
        description: "Enable or disable advanced timer mode to have the switch act like a bathroom fan timer",
    },
    doubleTapClearNotifications: {
        id: 262,
        dataType: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
        min: 0,
        max: 1,
        description: "Double-Tap the Config button to clear notifications.",
        modelValues: { default: { values: { "Enabled (Default)": 0, Disabled: 1 } } },
        displayType: "enum",
    },
    fanLedLevelType: {
        id: 263,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 10,
        modelValues: { default: { values: { "Limitless (like VZM31)": 0, "Adaptive LED": 10 } } },
        description: "Level display of the LED Strip",
    },
};
/**
 * Common Dimmer Attributes
 *
 * These attributes are shared between all devices that act like dimmers (including dimmers + fan switches) with
 * the manufacturer specific Inovelli cluster. These are not shared with on/off switches.
 * Some of the descriptions, max, min or value properties may be overridden for each device
 */
const COMMON_DIMMER_ATTRIBUTES = {
    ...COMMON_ATTRIBUTES,
    minimumLevel: {
        id: 9,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 1,
        max: 254,
        description: "The minimum level that the dimmer allows the bulb to be dimmed to. " +
            "Useful when the user has an LED bulb that does not turn on or flickers at a lower level.",
    },
    maximumLevel: {
        id: 10,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 2,
        max: 255,
        description: "The maximum level that the dimmer allows the bulb to be dimmed to." +
            "Useful when the user has an LED bulb that reaches its maximum level before the " +
            "dimmer value of 99 or when the user wants to limit the maximum brightness.",
    },
    powerType: {
        id: 21,
        dataType: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
        displayType: "enum",
        modelValues: { default: { values: { "Non Neutral": 0, Neutral: 1 } } },
        min: 0,
        max: 1,
        readOnly: true,
        description: "Set the power type for the device.",
    },
    outputMode: {
        id: 258,
        min: 0,
        max: 1,
        modelValues: {
            default: { values: { Dimmer: 0, "On/Off": 1 } },
            [exports.Model.VZM35]: { values: { "Ceiling Fan (3-Speed)": 0, "Exhaust Fan (On/Off)": 1 } },
        },
        dataType: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
        description: "Use device as a Dimmer or an On/Off switch.",
        displayType: "enum",
    },
};
/**
 * Common Dimmable light Attributes
 *
 * These attributes are shared between all devices that are dimmable light switches with
 * the manufacturer specific Inovelli cluster. These are not shared with fans or on/off switches.
 * Some of the descriptions, max, min or value properties may be overridden for each device
 */
const COMMON_DIMMABLE_LIGHT_ATTRIBUTES = {
    quickStartTime: {
        id: 23,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 60,
        description: "Duration of full power output while lamp transitions from Off to On. In 60th of second. 0 = disable, 1 = 1/60s, 60 = 1s",
    },
    quickStartLevel: {
        id: 24,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 1,
        max: 254,
        description: "Level of power output during Quick Start Light time (P23).",
    },
    higherOutputInNonNeutral: {
        id: 25,
        dataType: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
        displayType: "enum",
        modelValues: { default: { values: { "Disabled (default)": 0, Enabled: 1 } } },
        min: 0,
        max: 1,
        description: "Increase level in non-neutral mode",
    },
    dimmingMode: {
        id: 26,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        displayType: "enum",
        modelValues: { default: { values: { "Leading edge": 0, "Trailing edge": 1 } } },
        min: 0,
        max: 1,
        readOnly: true,
        description: "Switches the dimming mode from leading edge (default) to trailing edge. " +
            "1. Trailing Edge is only available on neutral single-pole and neutral multi-way with an " +
            "aux/add-on switch (multi-way with a dumb/existing switch and non-neutral setups are not supported and " +
            "will default back to Leading Edge). This parameter can only be changed at the switch.",
    },
    dimmingAlgorithm: {
        id: 27,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        displayType: "enum",
        modelValues: { default: { values: { "Old dimming algorithm (v2.18)": 0, "New dimming algorithm (v3.04)": 1 } } },
        addedInFirmware: { [exports.Model.VZM31]: [3, 5] },
        min: 0,
        max: 1,
        description: "Switches the dimming algorithm from old to new. When switching the algorithm, the switch will restart. " +
            "Some non-neutral setups may not support the new algorithm, in which case you can use the old algorithm." +
            "0 = old dimming algorithm (v2.18), 1 = new dimming algorithm (v3.04+) (default).",
    },
    auxDetectionLevel: {
        id: 124,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        addedInFirmware: { [exports.Model.VZM31]: [3, 5] },
        min: 0,
        max: 4,
        description: "Aux detection level (P124). Range: 0-4, default: 1. " +
            "If you are having issues with the aux function, start setting from 0 and continue until the aux function operates normally.",
    },
    dumbDetectionLevel: {
        id: 165,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        addedInFirmware: { [exports.Model.VZM31]: [3, 7] },
        min: 0,
        max: 4,
        description: "Dumb detection level (P165). Range: 0-4, default: 0. " +
            "If the dumb switch function is not working correctly, start at 0 and increase until it operates normally.",
    },
};
/**
 * Common Dimmer or On/Off Attributes
 *
 * These attributes are shared between all devices that are light switches (either dimmers or on/off) with
 * the manufacturer specific Inovelli cluster. These are not shared with fans.
 * Some of the descriptions, max, min or value properties may be overridden for each device
 */
const COMMON_DIMMER_ON_OFF_ATTRIBUTES = {
    ledBarScaling: {
        id: 100,
        dataType: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
        displayType: "enum",
        modelValues: { default: { values: { "Gen3 method (VZM-style)": 0, "Gen2 method (LZW-style)": 1 } } },
        description: "Method used for scaling.",
    },
    activePowerReports: {
        id: 18,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 100,
        description: "Percent power level change that will result in a new power report being sent. 0 = Disabled",
    },
    periodicPowerAndEnergyReports: {
        id: 19,
        min: 0,
        max: 32767,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT16,
        description: "Time period between consecutive power & energy reports being sent (in seconds). The timer is reset after each report is sent.",
    },
    activeEnergyReports: {
        id: 20,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT16,
        min: 0,
        max: 32767,
        description: "Energy reports Energy level change which will result in sending a new energy report." +
            "0 = disabled, 1-32767 = 0.01kWh-327.67kWh. Default setting: 10 (0.1 kWh)",
    },
};
exports.VZM30_ATTRIBUTES = {
    ...COMMON_ATTRIBUTES,
    ...COMMON_DIMMER_ON_OFF_ATTRIBUTES,
    outputMode: {
        ...COMMON_DIMMER_ATTRIBUTES.outputMode,
        description: "Use device as a Dimmer or an On/Off switch. Only applies when controlling bound devices.",
    },
};
exports.VZM31_ATTRIBUTES = {
    // Temporarily exclude fanTimerMode from the VZM31. While the specifications indicate that this attribute should be present, it's missing in the current firmware (2.18). This can be removed once the firmware bug is corrected.
    ...Object.fromEntries(Object.entries(COMMON_DIMMER_ATTRIBUTES).filter(([key]) => key !== "fanTimerMode")),
    ...COMMON_DIMMER_ON_OFF_ATTRIBUTES,
    ...COMMON_DIMMABLE_LIGHT_ATTRIBUTES,
    relayClick: {
        id: 261,
        dataType: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
        min: 0,
        max: 1,
        description: "In neutral on/off setups, the default is to have a clicking sound to notify you that the relay " +
            "is open or closed. You may disable this sound by creating a, “simulated” on/off where the switch " +
            "only will turn onto 100 or off to 0.",
        modelValues: { default: { values: { "Disabled (Click Sound On)": 0, "Enabled (Click Sound Off)": 1 } } },
        displayType: "enum",
    },
};
exports.VZM32_ATTRIBUTES = {
    ...COMMON_DIMMER_ATTRIBUTES,
    ...COMMON_DIMMER_ON_OFF_ATTRIBUTES,
    ...COMMON_DIMMABLE_LIGHT_ATTRIBUTES,
    otaImageType: {
        id: 34,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        displayType: "enum",
        modelValues: {
            default: {
                values: {
                    "Zigbee (259)": 0,
                    "mmWave (260)": 1,
                    "Alternating (259 & 260) (default)": 2,
                },
            },
        },
        min: 0,
        max: 2,
        description: "Which endpoint should the switch advertise for OTA update (Zigbee, mmWave, or both).",
    },
    mmwaveControlWiredDevice: {
        id: 110,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        displayType: "enum",
        modelValues: {
            default: {
                values: {
                    Disabled: 0,
                    "Occupancy (default)": 1,
                    Vacancy: 2,
                    "Wasteful Occupancy": 3,
                    "Mirrored Occupancy": 4,
                    "Mirrored Vacancy": 5,
                    "Mirrored Wasteful Occupancy": 6,
                },
            },
        },
        min: 0,
        max: 6,
        description: "Controls whether the wired load is automatically turned on / off by the presence detector. " +
            "0 = Disabled (manual control of the load), " +
            "1 = Occupancy (default; turn on automatically with presence; turn off automatically without presence), " +
            "2 = Vacancy (does not turn on automatically; turn off automatically without presence), " +
            "3 = Wasteful Occupancy (turn on automatically with presence; does not turn off automatically), " +
            "4 = Mirrored Occupancy (turn on automatically without presence; turn off automatically with presence), " +
            "5 = Mirrored Vacancy (turn on automatically without presence; does not turn off automatically), " +
            "6 = Mirrored Wasteful Occupancy (does not turn on automatically; turns off automatically with presence).",
    },
    mmWaveRoomSizePreset: {
        id: 117,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        displayType: "enum",
        modelValues: {
            default: {
                values: {
                    Custom: 0,
                    Small: 1,
                    Medium: 2,
                    Large: 3,
                },
            },
        },
        min: 0,
        max: 3,
        description: "Allows selection of predefined room dimensions for mmWave sensor processing. Useful for optimizing " +
            "detection zones based on installation environment. Defaults to Custom which allows for manual dimension configuration " +
            "via other parameters. \nOptions: 0=Custom (User-defined), 1=Small (X: −100 to 100, Y: 0 to 200, Z: −100 to 100), " +
            "2=Medium (X: −160 to 160, Y: 0 to 280, Z: −100 to 100), 3=Large (X: −210 to 210, Y: 0 to 360, Z: −100 to 100)",
    },
};
exports.VZM32_MMWAVE_ATTRIBUTES = {
    mmWaveHoldTime: {
        id: 114,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT32,
        min: 0,
        max: 4294967295,
        description: "This changes the duration, measured in seconds, after the mmWave radar detects transition from " +
            "the presence of a person to their absence. Default = 10 (seconds).",
    },
    mmWaveDetectSensitivity: {
        id: 112,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        displayType: "enum",
        modelValues: { default: { values: { Low: 0, Medium: 1, "High (default)": 2 } } },
        min: 0,
        max: 2,
        description: "The sensitivity of the mmWave sensor.",
    },
    mmWaveDetectTrigger: {
        id: 113,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        displayType: "enum",
        modelValues: { default: { values: { "Slow (5s)": 0, "Medium (1s)": 1, "Fast (0.2s, default)": 2 } } },
        min: 0,
        max: 2,
        description: "The time from detecting a person to triggering an action.",
    },
    mmWaveTargetInfoReport: {
        id: 107,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        displayType: "enum",
        modelValues: { default: { values: { "Disable (default)": 0, Enable: 1 } } },
        min: 0,
        max: 1,
        description: "Send target info report when bound to mmWave cluster.",
    },
    mmWaveStayLife: {
        id: 108,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT32,
        min: 0,
        max: 4294967295,
        description: "The delay time of the stay area is set to 50ms when it is set to 1, to 1 second when it is set to 20, and the default value is 300, that is, 15 seconds",
    },
    mmWaveVersion: {
        id: 115,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT32,
        min: 0,
        max: 4294967295,
        readOnly: true,
        description: "The firmware version number of the mmWave module.",
    },
    mmWaveHeightMin: {
        id: 101,
        dataType: zigbee_herdsman_1.Zcl.DataType.INT16,
        min: -600,
        max: 600,
        readOnly: false,
        description: "Defines the detection area (negative values are below the switch, positive values are above)",
    },
    mmWaveHeightMax: {
        id: 102,
        dataType: zigbee_herdsman_1.Zcl.DataType.INT16,
        min: -600,
        max: 600,
        readOnly: false,
        description: "Defines the detection area (negative values are below the switch, positive values are above)",
    },
    mmWaveWidthMin: {
        id: 103,
        dataType: zigbee_herdsman_1.Zcl.DataType.INT16,
        min: -600,
        max: 600,
        readOnly: false,
        description: "Defines the detection area (negative values are left of the switch facing away from the wall, positive values are right)",
    },
    mmWaveWidthMax: {
        id: 104,
        dataType: zigbee_herdsman_1.Zcl.DataType.INT16,
        min: -600,
        max: 600,
        readOnly: false,
        description: "Defines the detection area (negative values are left of the switch facing away from the wall, positive values are right)",
    },
    mmWaveDepthMin: {
        id: 105,
        dataType: zigbee_herdsman_1.Zcl.DataType.INT16,
        min: 0,
        max: 600,
        readOnly: false,
        description: "Defines the detection area in front of the switch",
    },
    mmWaveDepthMax: {
        id: 106,
        dataType: zigbee_herdsman_1.Zcl.DataType.INT16,
        min: 0,
        max: 600,
        readOnly: false,
        description: "Defines the detection area in front of the switch",
    },
};
exports.VZM35_ATTRIBUTES = {
    ...COMMON_DIMMER_ATTRIBUTES,
    minimumLevel: {
        ...COMMON_DIMMER_ATTRIBUTES.minimumLevel,
        description: "1-84: The level corresponding to the fan is Low, Medium, High. " +
            "85-170: The level corresponding to the fan is Medium, Medium, High. " +
            "170-254: The level corresponding to the fan is High, High, High ",
    },
    maximumLevel: {
        ...COMMON_DIMMER_ATTRIBUTES.maximumLevel,
        description: "2-84: The level corresponding to the fan is Low, Medium, High.",
    },
    smartBulbMode: {
        ...COMMON_ATTRIBUTES.smartBulbMode,
        description: "For use with Smart Fans that need constant power and are controlled via commands rather than power.",
    },
    quickStartTime: {
        id: 23,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 0,
        max: 60,
        description: "Duration of full power output while fan tranisitions from Off to On. In 60th of second. 0 = disable, 1 = 1/60s, 60 = 1s",
    },
    nonNeutralAuxMediumGear: {
        id: 30,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 42,
        max: 135,
        description: "Identification value in Non-nuetral, medium gear, aux switch",
    },
    nonNeutralAuxLowGear: {
        id: 31,
        dataType: zigbee_herdsman_1.Zcl.DataType.UINT8,
        min: 42,
        max: 135,
        description: "Identification value in Non-nuetral, low gear, aux switch",
    },
    outputMode: {
        ...COMMON_DIMMER_ATTRIBUTES.outputMode,
        description: "Use device in ceiling fan (3-Speed) or in exhaust fan (On/Off) mode.",
    },
};
exports.VZM36_ATTRIBUTES = {
    // biome-ignore lint/style/useNamingConvention: endpoint-suffixed MQTT attribute key; changing it would break existing MQTT naming conventions
    dimmingSpeedUpRemote_1: { ...COMMON_ATTRIBUTES.dimmingSpeedUpRemote },
    // biome-ignore lint/style/useNamingConvention: endpoint-suffixed MQTT attribute key; changing it would break existing MQTT naming conventions
    rampRateOffToOnRemote_1: { ...COMMON_ATTRIBUTES.rampRateOffToOnRemote },
    // biome-ignore lint/style/useNamingConvention: endpoint-suffixed MQTT attribute key; changing it would break existing MQTT naming conventions
    dimmingSpeedDownRemote_1: { ...COMMON_ATTRIBUTES.dimmingSpeedDownRemote },
    // biome-ignore lint/style/useNamingConvention: endpoint-suffixed MQTT attribute key; changing it would break existing MQTT naming conventions
    rampRateOnToOffRemote_1: { ...COMMON_ATTRIBUTES.rampRateOnToOffRemote },
    // biome-ignore lint/style/useNamingConvention: endpoint-suffixed MQTT attribute key; changing it would break existing MQTT naming conventions
    minimumLevel_1: { ...COMMON_DIMMER_ATTRIBUTES.minimumLevel },
    // biome-ignore lint/style/useNamingConvention: endpoint-suffixed MQTT attribute key; changing it would break existing MQTT naming conventions
    maximumLevel_1: { ...COMMON_DIMMER_ATTRIBUTES.maximumLevel },
    // biome-ignore lint/style/useNamingConvention: endpoint-suffixed MQTT attribute key; changing it would break existing MQTT naming conventions
    autoTimerOff_1: {
        ...COMMON_ATTRIBUTES.autoTimerOff,
        description: "Automatically turns the light off after this many seconds." +
            " When the light is turned on a timer is started. When the timer expires, the light is turned off. 0 = Auto off is disabled.",
    },
    // biome-ignore lint/style/useNamingConvention: endpoint-suffixed MQTT attribute key; changing it would break existing MQTT naming conventions
    defaultLevelRemote_1: {
        ...COMMON_ATTRIBUTES.defaultLevelRemote,
        description: "Default level for the light when it is turned on from the hub." +
            " A setting of 255 means that the light will return to the level that it was on before it was turned off.",
    },
    // biome-ignore lint/style/useNamingConvention: endpoint-suffixed MQTT attribute key; changing it would break existing MQTT naming conventions
    stateAfterPowerRestored_1: {
        ...COMMON_ATTRIBUTES.stateAfterPowerRestored,
        description: "The state the light should return to when power is restored after power failure. 0 = off, 1-254 = level, 255 = previous.",
    },
    // biome-ignore lint/style/useNamingConvention: endpoint-suffixed MQTT attribute key; changing it would break existing MQTT naming conventions
    quickStartTime_1: { ...COMMON_DIMMABLE_LIGHT_ATTRIBUTES.quickStartTime },
    // biome-ignore lint/style/useNamingConvention: endpoint-suffixed MQTT attribute key; changing it would break existing MQTT naming conventions
    quickStartLevel_1: { ...COMMON_DIMMABLE_LIGHT_ATTRIBUTES.quickStartLevel },
    // biome-ignore lint/style/useNamingConvention: endpoint-suffixed MQTT attribute key; changing it would break existing MQTT naming conventions
    higherOutputInNonNeutral_1: {
        ...COMMON_DIMMABLE_LIGHT_ATTRIBUTES.higherOutputInNonNeutral,
        description: "Increase level in non-neutral mode for light.",
    },
    // biome-ignore lint/style/useNamingConvention: endpoint-suffixed MQTT attribute key; changing it would break existing MQTT naming conventions
    dimmingMode_1: {
        ...COMMON_DIMMABLE_LIGHT_ATTRIBUTES.dimmingMode,
        readOnly: false,
        description: "Switches the dimming mode from leading edge (default) to trailing edge. " +
            "1. Trailing Edge is only available on neutral single-pole and neutral multi-way with an " +
            "aux/add-on switch (multi-way with a dumb/existing switch and non-neutral setups are not supported and " +
            "will default back to Leading Edge).",
    },
    // biome-ignore lint/style/useNamingConvention: endpoint-suffixed MQTT attribute key; changing it would break existing MQTT naming conventions
    smartBulbMode_1: { ...COMMON_ATTRIBUTES.smartBulbMode },
    // biome-ignore lint/style/useNamingConvention: endpoint-suffixed MQTT attribute key; changing it would break existing MQTT naming conventions
    ledColorWhenOn_1: { ...COMMON_ATTRIBUTES.ledColorWhenOn },
    // biome-ignore lint/style/useNamingConvention: endpoint-suffixed MQTT attribute key; changing it would break existing MQTT naming conventions
    ledIntensityWhenOn_1: { ...COMMON_ATTRIBUTES.ledIntensityWhenOn },
    // remote protection is readonly...
    // biome-ignore lint/style/useNamingConvention: endpoint-suffixed MQTT attribute key; changing it would break existing MQTT naming conventions
    outputMode_1: { ...COMMON_DIMMER_ATTRIBUTES.outputMode },
    // Endpoint 2 (Fan)
    // biome-ignore lint/style/useNamingConvention: endpoint-suffixed MQTT attribute key; changing it would break existing MQTT naming conventions
    dimmingSpeedUpRemote_2: {
        ...COMMON_ATTRIBUTES.dimmingSpeedUpRemote,
        description: "This changes the speed that the fan ramps up when controlled from the hub. " +
            "A setting of 0 turns the fan immediately on. Increasing the value slows down the transition speed. " +
            "Every number represents 100ms. Default = 25 (2.5s)",
    },
    // biome-ignore lint/style/useNamingConvention: endpoint-suffixed MQTT attribute key; changing it would break existing MQTT naming conventions
    rampRateOffToOnRemote_2: {
        ...COMMON_ATTRIBUTES.rampRateOffToOnRemote,
        description: "This changes the speed that the fan turns on when controlled from the hub. " +
            "A setting of 0 turns the fan immediately on. Increasing the value slows down the transition speed. " +
            "Every number represents 100ms. Default = 127 - Keep in sync with dimmingSpeedUpRemote setting.",
    },
    // biome-ignore lint/style/useNamingConvention: endpoint-suffixed MQTT attribute key; changing it would break existing MQTT naming conventions
    dimmingSpeedDownRemote_2: {
        ...COMMON_ATTRIBUTES.dimmingSpeedDownRemote,
        description: "This changes the speed that the fan ramps down when controlled from the hub. " +
            "A setting of 0 turns the fan immediately off. Increasing the value slows down the transition speed. " +
            "Every number represents 100ms. Default = 127 - Keep in sync with dimmingSpeedUpRemote setting.",
    },
    // biome-ignore lint/style/useNamingConvention: endpoint-suffixed MQTT attribute key; changing it would break existing MQTT naming conventions
    rampRateOnToOffRemote_2: {
        ...COMMON_ATTRIBUTES.rampRateOnToOffRemote,
        description: "This changes the speed that the fan turns off when controlled from the hub. " +
            "A setting of 'instant' turns the fan immediately off. Increasing the value slows down the transition speed. " +
            "Every number represents 100ms. Default = 127 - Keep in sync with rampRateOffToOnRemote setting.",
    },
    // biome-ignore lint/style/useNamingConvention: endpoint-suffixed MQTT attribute key; changing it would break existing MQTT naming conventions
    minimumLevel_2: {
        ...COMMON_DIMMER_ATTRIBUTES.minimumLevel,
        description: "The minimum level that the fan can be set to.",
    },
    // biome-ignore lint/style/useNamingConvention: endpoint-suffixed MQTT attribute key; changing it would break existing MQTT naming conventions
    maximumLevel_2: {
        ...COMMON_DIMMER_ATTRIBUTES.maximumLevel,
        description: "The maximum level that the fan can be set to.",
    },
    // biome-ignore lint/style/useNamingConvention: endpoint-suffixed MQTT attribute key; changing it would break existing MQTT naming conventions
    autoTimerOff_2: {
        ...COMMON_ATTRIBUTES.autoTimerOff,
        description: "Automatically turns the fan off after this many seconds." +
            " When the fan is turned on a timer is started. When the timer expires, the switch is turned off. 0 = Auto off is disabled.",
    },
    // biome-ignore lint/style/useNamingConvention: endpoint-suffixed MQTT attribute key; changing it would break existing MQTT naming conventions
    defaultLevelRemote_2: {
        ...COMMON_ATTRIBUTES.defaultLevelRemote,
        description: "Default level for the fan when it is turned on from the hub." +
            " A setting of 255 means that the fan will return to the level that it was on before it was turned off.",
    },
    // biome-ignore lint/style/useNamingConvention: endpoint-suffixed MQTT attribute key; changing it would break existing MQTT naming conventions
    stateAfterPowerRestored_2: {
        ...COMMON_ATTRIBUTES.stateAfterPowerRestored,
        description: "The state the fan should return to when power is restored after power failure. 0 = off, 1-254 = level, 255 = previous.",
    },
    // biome-ignore lint/style/useNamingConvention: endpoint-suffixed MQTT attribute key; changing it would break existing MQTT naming conventions
    quickStartTime_2: {
        ...COMMON_DIMMABLE_LIGHT_ATTRIBUTES.quickStartTime,
        description: "Duration of full power output while fan transitions from Off to On. In 60th of second. 0 = disable, 1 = 1/60s, 60 = 1s",
    },
    // power type readonly
    // internal temp readonly
    // overheat readonly
    // biome-ignore lint/style/useNamingConvention: endpoint-suffixed MQTT attribute key; changing it would break existing MQTT naming conventions
    smartBulbMode_2: {
        ...COMMON_DIMMER_ATTRIBUTES.smartBulbMode,
        modelValues: { default: { values: { Disabled: 0, "Smart Fan Mode": 1 } } },
        description: "For use with Smart Fans that need constant power and are controlled via commands rather than power.",
    },
    // remote protection readonly..
    // biome-ignore lint/style/useNamingConvention: endpoint-suffixed MQTT attribute key; changing it would break existing MQTT naming conventions
    outputMode_2: {
        ...COMMON_DIMMER_ATTRIBUTES.outputMode,
        modelValues: { default: { values: { "Ceiling Fan (3-Speed)": 0, "Exhaust Fan (On/Off)": 1 } } },
        description: "Use device in ceiling fan (3-Speed) or in exhaust fan (On/Off) mode.",
    },
};
function createMmWaveCompositeAreaConverter(key, command) {
    return {
        key: [key],
        convertSet: async (entity, key, values, meta) => {
            utils.assertObject(values);
            // The composite structure has area1, area2, area3, area4 as keys
            const areaKeys = ["area1", "area2", "area3", "area4"];
            const state = { [key]: {} };
            const compositeState = state[key];
            // Process each area that's provided in the composite
            for (const areaKey of areaKeys) {
                if (areaKey in values && utils.isObject(values[areaKey])) {
                    const areaData = values[areaKey];
                    // Extract area number from "area1" -> 1, "area2" -> 2, etc.
                    const areaId = Number.parseInt(areaKey.replace("area", ""), 10);
                    const payload = {
                        // areaID is zero indexed
                        areaId: areaId - 1,
                        xMin: areaData.width_min,
                        xMax: areaData.width_max,
                        yMin: areaData.depth_min,
                        yMax: areaData.depth_max,
                        zMin: areaData.height_min,
                        zMax: areaData.height_max,
                    };
                    await entity.command(INOVELLI_MMWAVE_CLUSTER_NAME, command, payload, {
                        disableResponse: true,
                        disableDefaultResponse: true,
                    });
                    // Store the area data in the state
                    compositeState[areaKey] = areaData;
                }
            }
            // Query areas after all updates are complete
            if (Object.keys(compositeState).length > 0) {
                await entity.command(INOVELLI_MMWAVE_CLUSTER_NAME, "mmWaveControl", {
                    controlID: mmWaveControlCommands.query_areas,
                }, { disableResponse: true, disableDefaultResponse: true });
            }
            return { state };
        },
    };
}
/**
 * For devices with split values by endpoint (e.g. VZM36), parameter keys use the form "attributeName_endpointId"
 * (e.g. "brightness_1", "defaultLevelRemote_2"). This helper resolves such a key to the endpoint to use and the
 * base attribute name for cluster read/write. If the key has no underscore suffix, the original entity and key are returned.
 */
function resolveEndpointAndKey(entity, key, meta) {
    const keysplit = key.split("_");
    if (keysplit.length === 2) {
        return {
            entityToUse: meta.device.getEndpoint(Number(keysplit[1])),
            keyToUse: keysplit[0],
        };
    }
    return { entityToUse: entity, keyToUse: key };
}
const tzLocal = {
    inovelli_parameters: (attributes, cluster, model) => ({
        key: Object.keys(attributes).filter((a) => !attributes[a].readOnly),
        convertSet: async (entity, key, value, meta) => {
            // Walk meta.message rather than just `key`: Z2M dispatches this converter once per SET payload,
            // so writing only `key` silently drops every other Inovelli key (issue #11698). Bucket by the
            // resolved endpoint so VZM36 _1/_2 suffixed keys still route correctly.
            const buckets = new Map();
            for (const [msgKey, msgValue] of Object.entries(meta.message)) {
                const attribute = attributes[msgKey];
                if (!attribute || attribute.readOnly) {
                    continue;
                }
                const { entityToUse } = resolveEndpointAndKey(entity, msgKey, meta);
                const valueMap = resolveValueMap(attribute, model);
                const writeValue = attribute.displayType === "enum" ? valueMap?.[msgValue] : msgValue;
                let bucket = buckets.get(entityToUse);
                if (!bucket) {
                    bucket = { payload: {}, state: {} };
                    buckets.set(entityToUse, bucket);
                }
                bucket.payload[attribute.id] = { value: writeValue, type: attribute.dataType };
                bucket.state[msgKey] = msgValue;
            }
            if (buckets.size === 0) {
                return;
            }
            const combinedState = {};
            for (const [entityToUse, bucket] of buckets) {
                await entityToUse.write(cluster, bucket.payload, {
                    manufacturerCode: exports.INOVELLI,
                });
                Object.assign(combinedState, bucket.state);
            }
            return { state: combinedState };
        },
        convertGet: async (entity, key, meta) => {
            const { entityToUse, keyToUse } = resolveEndpointAndKey(entity, key, meta);
            // XXX: far too dynamic to properly type
            await entityToUse.read(cluster, [keyToUse], {
                manufacturerCode: exports.INOVELLI,
            });
        },
    }),
    inovelli_parameters_read_only: (attributes, cluster) => ({
        key: Object.keys(attributes).filter((a) => attributes[a].readOnly),
        convertGet: async (entity, key, meta) => {
            const { entityToUse, keyToUse } = resolveEndpointAndKey(entity, key, meta);
            // XXX: far too dynamic to properly type
            await entityToUse.read(cluster, [keyToUse], {
                manufacturerCode: exports.INOVELLI,
            });
        },
    }),
    inovelli_led_effect: {
        key: ["led_effect"],
        convertSet: async (entity, key, values, meta) => {
            utils.assertObject(values);
            await entity.command(INOVELLI_CLUSTER_NAME, "ledEffect", {
                effect: ledEffects[values.effect],
                color: Math.min(Math.max(0, values.color), 255),
                level: Math.min(Math.max(0, values.level), 100),
                duration: Math.min(Math.max(0, values.duration), 255),
            }, { disableResponse: true, disableDefaultResponse: true });
            return { state: { [key]: values } };
        },
    },
    inovelli_energy_reset: {
        key: ["energy_reset"],
        convertSet: async (entity, key, values, meta) => {
            await entity.command(INOVELLI_CLUSTER_NAME, "energyReset", {}, { disableResponse: true, disableDefaultResponse: true });
        },
    },
    inovelli_individual_led_effect: {
        key: ["individual_led_effect"],
        convertSet: async (entity, key, values, meta) => {
            utils.assertObject(values);
            await entity.command(INOVELLI_CLUSTER_NAME, "individualLedEffect", {
                led: Math.min(Math.max(1, Number.parseInt(values.led, 10)), 7) - 1,
                effect: individualLedEffects[values.effect],
                color: Math.min(Math.max(0, values.color), 255),
                level: Math.min(Math.max(0, values.level), 100),
                duration: Math.min(Math.max(0, values.duration), 255),
            }, { disableResponse: true, disableDefaultResponse: true });
            return { state: { [key]: values } };
        },
    },
    inovelli_mmwave_control_commands: {
        key: ["mmwave_control_commands"],
        convertSet: async (entity, key, values, meta) => {
            utils.assertObject(values);
            await entity.command(INOVELLI_MMWAVE_CLUSTER_NAME, "mmWaveControl", {
                controlID: mmWaveControlCommands[values.controlID],
            }, { disableResponse: true, disableDefaultResponse: true });
            return { state: { [key]: values } };
        },
    },
    mmwave_detection_areas: createMmWaveCompositeAreaConverter("mmwave_detection_areas", "setDetectionArea"),
    mmwave_interference_areas: createMmWaveCompositeAreaConverter("mmwave_interference_areas", "setInterferenceArea"),
    mmwave_stay_areas: createMmWaveCompositeAreaConverter("mmwave_stay_areas", "setStayArea"),
    /*
     * Inovelli devices have a default transition property that the device should
     * fallback to if a transition is not specified by passing 0xffff
     *
     */
    light_onoff_brightness_inovelli: {
        ...tz.light_onoff_brightness,
        convertSet: async (entity, key, value, meta) => {
            const { message } = meta;
            const transition = utils.getTransition(entity, "brightness", meta);
            const state = utils.isString(message.state) ? message.state.toLowerCase() : null;
            // If transition is not specified and command is on (with no brightness), off or toggle, use on_off converter
            let brightness;
            if (message.brightness != null) {
                brightness = Number(message.brightness);
            }
            else if (message.brightness_percent != null) {
                brightness = utils.mapNumberRange(Number(message.brightness_percent), 0, 100, 0, 255);
            }
            if ((state === "toggle" || state === "off" || (brightness === undefined && state === "on")) && !transition.specified) {
                const localMeta = {
                    ...meta,
                    converterOptions: {
                        ctrlbits: 0,
                        ontime: message.on_time != null ? Math.round(message.on_time * 10) : 0xffff,
                        offwaittime: message.off_wait_time != null ? Math.round(message.off_wait_time * 10) : 0xffff,
                    },
                };
                return await tz.on_off.convertSet(entity, key, value, localMeta);
            }
            const localMeta = {
                ...meta,
                message: {
                    ...message,
                    transition: (!transition.specified ? 0xffff : transition.time) / 10,
                },
            };
            return await tz.light_onoff_brightness.convertSet(entity, key, value, localMeta);
        },
    },
    fan_mode: (endpointId) => ({
        key: ["fan_mode"],
        convertSet: async (entity, key, value, meta) => {
            utils.assertString(value);
            const endpoint = meta.device.getEndpoint(endpointId);
            await endpoint.command("genLevelCtrl", "moveToLevelWithOnOff", {
                level: FAN_MODES[value],
                transtime: 0xffff,
                optionsMask: 0,
                optionsOverride: 0,
            }, utils.getOptions(meta.mapped, entity));
            meta.state[key] = value;
            if (endpointId === 2) {
                return {
                    state: {
                        [key]: value,
                        fan_state: "ON",
                    },
                };
            }
            return {
                state: {
                    [key]: value,
                    state: "ON",
                },
            };
        },
        convertGet: async (entity, key, meta) => {
            const endpoint = meta.device.getEndpoint(endpointId);
            await endpoint.read("genLevelCtrl", ["currentLevel"]);
        },
    }),
    fan_state: (endpointId) => ({
        key: ["fan_state", "on_time", "off_wait_time"],
        convertSet: async (entity, key, value, meta) => {
            const targetEntity = endpointId != null ? meta.device.getEndpoint(endpointId) : entity;
            const localMeta = {
                ...meta,
                message: {
                    ...meta.message,
                    state: meta.message.fan_state,
                },
                state: {
                    ...meta.state,
                    state: meta.state.fan_state,
                },
            };
            const result = (await tz.on_off.convertSet(targetEntity, key, value, localMeta));
            if (result?.state?.state != null) {
                return { state: { fan_state: result.state.state } };
            }
            return result ?? {};
        },
        convertGet: async (entity, key, meta) => {
            const targetEntity = endpointId != null ? meta.device.getEndpoint(endpointId) : entity;
            await tz.on_off.convertGet(targetEntity, key, meta);
        },
    }),
    breezeMode: (endpointId) => ({
        key: ["breezeMode"],
        convertSet: async (entity, key, value, meta) => {
            utils.assertObject(value);
            // Calculate the value..
            let configValue = 0;
            let term = false;
            configValue += speedToInt(value.speed1);
            configValue += (Number(value.time1) / 5) * 4;
            let speed = speedToInt(value.speed2);
            if (speed !== 0) {
                configValue += speed * 64;
                configValue += (value.time2 / 5) * 256;
            }
            else {
                term = true;
            }
            speed = speedToInt(value.speed3);
            if (speed !== 0 && !term) {
                configValue += speed * 4096;
                configValue += (value.time3 / 5) * 16384;
            }
            else {
                term = true;
            }
            speed = speedToInt(value.speed4);
            if (speed !== 0 && !term) {
                configValue += speed * 262144;
                configValue += (value.time4 / 5) * 1048576;
            }
            else {
                term = true;
            }
            speed = speedToInt(value.speed5);
            if (speed !== 0 && !term) {
                configValue += speed * 16777216;
                configValue += (value.time5 / 5) * 67108864;
            }
            else {
                term = true;
            }
            const endpoint = meta.device.getEndpoint(endpointId);
            const payload = { breezeMode: configValue.toString() };
            await endpoint.write(INOVELLI_CLUSTER_NAME, payload, {
                manufacturerCode: exports.INOVELLI,
            });
            return { state: { [key]: value } };
        },
    }),
};
const fzLocal = {
    inovelli: (attributes, cluster, splitValuesByEndpoint = false, deviceModel) => ({
        cluster: cluster,
        type: ["readResponse", "attributeReport"],
        convert: (model, msg, publish, options, meta) => {
            const result = {};
            for (const c of Object.keys(msg.data)) {
                const key = splitValuesByEndpoint ? `${c}_${msg.endpoint.ID}` : c;
                const raw = msg.data[c];
                if (attributes[key] && attributes[key].displayType === "enum") {
                    const valueMap = resolveValueMap(attributes[key], deviceModel);
                    result[key] = valueMap ? Object.keys(valueMap).find((k) => valueMap[k] === raw) : raw;
                }
                else {
                    result[key] = raw;
                }
            }
            return result;
        },
    }),
    /**
     * Decodes raw button-tap scene frames sent by the device on endpoint 2 of `manuSpecificInovelli`.
     *
     * Frame layout (bytes 4-6 are the scene tuple, the rest of the frame is ignored here):
     *   data[4]: marker — must be 0x00, otherwise the frame is a different opcode.
     *   data[5]: button index (`buttonLookup`): 1=down, 2=up, 3=config, 4-6=aux_*.
     *   data[6]: tap kind (`clickLookup`): 0=pressed, 1=released, 2=held, 3-6=2x..5x.
     */
    button_taps: {
        cluster: INOVELLI_CLUSTER_NAME,
        type: ["raw"],
        convert: (model, msg, publish, options, meta) => {
            if (msg.endpoint.ID !== 2 || msg.data[4] !== 0x00)
                return;
            const button = buttonLookup[msg.data[5]];
            const action = clickLookup[msg.data[6]];
            return { action: `${button}_${action}` };
        },
    },
    fan_mode: (endpointId) => ({
        cluster: "genLevelCtrl",
        type: ["attributeReport", "readResponse"],
        convert: (model, msg, publish, options, meta) => {
            if (msg.endpoint.ID === endpointId) {
                if (msg.data.currentLevel !== undefined) {
                    const mode = intToFanMode(msg.data.currentLevel || 1);
                    return {
                        fan_mode: mode,
                    };
                }
            }
        },
    }),
    fan_state: (endpointId) => ({
        cluster: "genOnOff",
        type: ["attributeReport", "readResponse"],
        convert: (model, msg, publish, options, meta) => {
            if (msg.data.onOff === undefined) {
                return;
            }
            if (endpointId != null && msg.endpoint.ID !== endpointId) {
                return;
            }
            return { fan_state: msg.data.onOff === 1 ? "ON" : "OFF" };
        },
    }),
    on_off_for_endpoint: (endpointId, stateKey) => ({
        cluster: "genOnOff",
        type: ["attributeReport", "readResponse"],
        convert: (model, msg, publish, options, meta) => {
            if (msg.endpoint.ID !== endpointId || msg.data.onOff === undefined) {
                return;
            }
            return { [stateKey]: msg.data.onOff === 1 ? "ON" : "OFF" };
        },
    }),
    brightness: {
        cluster: "genLevelCtrl",
        type: ["attributeReport", "readResponse"],
        convert: (model, msg, publish, options, meta) => {
            if (msg.endpoint.ID === 1) {
                if (msg.data.currentLevel !== undefined) {
                    return { brightness: msg.data.currentLevel };
                }
            }
        },
    },
    /**
     * Decode breeze mode value:
     *
     * 0: disable
     * 1~0xffffffff: custom (using user configuration parameters) 4bytes
     * Up to 5 different options. First two bits determine the speed. Next four bits is time * 5 seconds.
     * 1111 11 1111 11 1111 11 1111 11 1111 11
     * Setting byte: 00-off, 01-low, 10-meduim, 11-high
     * Each 6 bit word is stored in ascending order, step one word being LSB
     *
     * Extract each nybble of the word, then reverse the calculation to get the setting for each.
     */
    breeze_mode: (endpointId) => ({
        cluster: INOVELLI_CLUSTER_NAME,
        type: ["attributeReport", "readResponse"],
        convert: (model, msg, publish, options, meta) => {
            if (msg.endpoint.ID === endpointId) {
                // TODO: typo?
                if (msg.data.breezeMode !== undefined) {
                    const bitmasks = [3, 60, 192, 3840, 12288, 245760, 786432, 15728640, 50331648, 1006632960];
                    const raw = msg.data.breezeMode;
                    const s1 = BREEZE_MODES[raw & bitmasks[0]];
                    const s2 = BREEZE_MODES[(raw & bitmasks[2]) / 64];
                    const s3 = BREEZE_MODES[(raw & bitmasks[4]) / 4096];
                    const s4 = BREEZE_MODES[(raw & bitmasks[6]) / 262144];
                    const s5 = BREEZE_MODES[(raw & bitmasks[8]) / 16777216];
                    const d1 = ((raw & bitmasks[1]) / 4) * 5;
                    const d2 = ((raw & bitmasks[3]) / 256) * 5;
                    const d3 = ((raw & bitmasks[5]) / 16384) * 5;
                    const d4 = ((raw & bitmasks[7]) / 1048576) * 5;
                    const d5 = ((raw & bitmasks[9]) / 67108864) * 5;
                    return {
                        breeze_mode: {
                            speed1: s1,
                            duration1: d1,
                            speed2: s2,
                            duration2: d2,
                            speed3: s3,
                            duration3: d3,
                            speed4: s4,
                            duration4: d4,
                            speed5: s5,
                            duration5: d5,
                        },
                    };
                }
            }
        },
    }),
    led_effect_complete: {
        cluster: INOVELLI_CLUSTER_NAME,
        type: ["commandLedEffectComplete"],
        convert: (model, msg, publish, options, meta) => {
            const value = msg.data.notificationType in LED_NOTIFICATION_TYPES ? LED_NOTIFICATION_TYPES[msg.data.notificationType] : "Unknown";
            // notificationComplete is a transient event vs a stateful change
            // treat it similar to an action by publishing "" to clear it on the next tick
            clearTimeout(globalStore.getValue(msg.endpoint, "notification_complete_clear"));
            const timer = setTimeout(() => {
                publish({ notificationComplete: "" });
                globalStore.clearValue(msg.endpoint, "notification_complete_clear");
            }, 0).unref();
            globalStore.putValue(msg.endpoint, "notification_complete_clear", timer);
            return { notificationComplete: value };
        },
    },
    report_target_info: {
        cluster: INOVELLI_MMWAVE_CLUSTER_NAME,
        type: ["commandReportTargetInfo"],
        convert: (model, msg, publish, options, meta) => {
            // Per Inovelli cluster docs: each target is x,y,z,dop (int16) + id (int8) = 9 bytes, after targetNum.
            const stride = 9;
            const buf = msg.data.targets;
            const targets = [];
            const count = Math.min(msg.data.targetNum, Math.floor(buf.length / stride));
            for (let i = 0; i < count; i++) {
                const o = i * stride;
                const x = buf.readInt16LE(o);
                const y = buf.readInt16LE(o + 2);
                const z = buf.readInt16LE(o + 4);
                const dop = buf.readInt16LE(o + 6);
                const id = buf.readInt8(o + 8);
                targets.push({ id, x, y, z, dop });
            }
            return { mmwave_targets: targets };
        },
    },
    report_areas: {
        cluster: INOVELLI_MMWAVE_CLUSTER_NAME,
        type: ["commandReportInterferenceArea", "commandReportDetectionArea", "commandReportStayArea"],
        convert: (model, msg, publish, options, meta) => {
            const areas = {};
            const data = msg.data;
            for (let i = 1; i <= 4; i++) {
                areas[`area${i}`] = {
                    width_min: data[`xMin${i}`],
                    width_max: data[`xMax${i}`],
                    height_min: data[`zMin${i}`],
                    height_max: data[`zMax${i}`],
                    depth_min: data[`yMin${i}`],
                    depth_max: data[`yMax${i}`],
                };
            }
            const result = {};
            // Map command types to the new property names
            const propertyMap = {
                commandReportInterferenceArea: "mmwave_interference_areas",
                commandReportDetectionArea: "mmwave_detection_areas",
                commandReportStayArea: "mmwave_stay_areas",
            };
            result[propertyMap[msg.type]] = areas;
            return result;
        },
    },
    anyone_in_reporting_area: {
        cluster: INOVELLI_MMWAVE_CLUSTER_NAME,
        type: ["commandAnyoneInReportingArea"],
        convert: (model, msg, publish, options, meta) => {
            return {
                mmwave_area1_occupancy: msg.data.area1 === 1,
                mmwave_area2_occupancy: msg.data.area2 === 1,
                mmwave_area3_occupancy: msg.data.area3 === 1,
                mmwave_area4_occupancy: msg.data.area4 === 1,
            };
        },
    },
};
const exposeLedEffects = () => {
    return e
        .composite("led_effect", "led_effect", ea.STATE_SET)
        .withFeature(e.enum("effect", ea.STATE_SET, Object.keys(ledEffects)).withDescription("Animation Effect to use for the LEDs"))
        .withFeature(e
        .numeric("color", ea.STATE_SET)
        .withValueMin(0)
        .withValueMax(255)
        .withDescription("Calculated by using a hue color circle(value/255*360) If color = 255 display white"))
        .withFeature(e.numeric("level", ea.STATE_SET).withValueMin(0).withValueMax(100).withDescription("Brightness of the LEDs"))
        .withFeature(e
        .numeric("duration", ea.STATE_SET)
        .withValueMin(0)
        .withValueMax(255)
        .withDescription("1-60 is in seconds calculated 61-120 is in minutes calculated by(value-60) " +
        "Example a value of 65 would be 65-60 = 5 minutes - 120-254 Is in hours calculated by(value-120) " +
        "Example a value of 132 would be 132-120 would be 12 hours. - 255 Indefinitely"))
        .withCategory("config");
};
const exposeIndividualLedEffects = () => {
    return e
        .composite("individual_led_effect", "individual_led_effect", ea.STATE_SET)
        .withFeature(e.enum("led", ea.STATE_SET, ["1", "2", "3", "4", "5", "6", "7"]).withDescription("Individual LED to target."))
        .withFeature(e.enum("effect", ea.STATE_SET, Object.keys(individualLedEffects)).withDescription("Animation Effect to use for the LED"))
        .withFeature(e
        .numeric("color", ea.STATE_SET)
        .withValueMin(0)
        .withValueMax(255)
        .withDescription("Calculated by using a hue color circle(value/255*360) If color = 255 display white"))
        .withFeature(e.numeric("level", ea.STATE_SET).withValueMin(0).withValueMax(100).withDescription("Brightness of the LED"))
        .withFeature(e
        .numeric("duration", ea.STATE_SET)
        .withValueMin(0)
        .withValueMax(255)
        .withDescription("1-60 is in seconds calculated 61-120 is in minutes calculated by(value-60) " +
        "Example a value of 65 would be 65-60 = 5 minutes - 120-254 Is in hours calculated by(value-120) " +
        " Example a value of 132 would be 132-120 would be 12 hours. - 255 Indefinitely"))
        .withCategory("config");
};
const exposeBreezeMode = () => {
    return e
        .composite("breeze mode", "breezeMode", ea.STATE_SET)
        .withFeature(e.enum("speed1", ea.STATE_SET, ["low", "medium", "high"]).withDescription("Step 1 Speed"))
        .withFeature(e.numeric("time1", ea.STATE_SET).withValueMin(1).withValueMax(80).withDescription("Duration (s) for fan in Step 1  "))
        .withFeature(e.enum("speed2", ea.STATE_SET, ["low", "medium", "high"]).withDescription("Step 2 Speed"))
        .withFeature(e.numeric("time2", ea.STATE_SET).withValueMin(1).withValueMax(80).withDescription("Duration (s) for fan in Step 2  "))
        .withFeature(e.enum("speed3", ea.STATE_SET, ["low", "medium", "high"]).withDescription("Step 3 Speed"))
        .withFeature(e.numeric("time3", ea.STATE_SET).withValueMin(1).withValueMax(80).withDescription("Duration (s) for fan in Step 3  "))
        .withFeature(e.enum("speed4", ea.STATE_SET, ["low", "medium", "high"]).withDescription("Step 4 Speed"))
        .withFeature(e.numeric("time4", ea.STATE_SET).withValueMin(1).withValueMax(80).withDescription("Duration (s) for fan in Step 4  "))
        .withFeature(e.enum("speed5", ea.STATE_SET, ["low", "medium", "high"]).withDescription("Step 5 Speed"))
        .withFeature(e.numeric("time5", ea.STATE_SET).withValueMin(1).withValueMax(80).withDescription("Duration (s) for fan in Step 5  "))
        .withCategory("config");
};
const exposeMMWaveControl = () => {
    return e
        .composite("mmwave_control_commands", "mmwave_control_commands", ea.STATE_SET)
        .withFeature(e.enum("controlID", ea.STATE_SET, Object.keys(mmWaveControlCommands)).withDescription("Which mmWave Control command to send"))
        .withCategory("config");
};
const exposeLedEffectComplete = () => {
    return e
        .enum("notificationComplete", ea.STATE, Object.values(LED_NOTIFICATION_TYPES))
        .withDescription("Indication that a specific notification has completed.")
        .withCategory("diagnostic");
};
const exposeEnergyReset = () => {
    return e.enum("energy_reset", ea.SET, ["reset"]).withDescription("Reset energy meter").withCategory("config");
};
const exposeMMWaveAreas = () => {
    return [
        e
            .binary("area1Occupancy", ea.STATE, true, false)
            .withProperty("mmwave_area1_occupancy")
            .withDescription("Indicates whether the device detected occupancy in Area 1"),
        e
            .binary("area2Occupancy", ea.STATE, true, false)
            .withProperty("mmwave_area2_occupancy")
            .withDescription("Indicates whether the device detected occupancy in Area 2"),
        e
            .binary("area3Occupancy", ea.STATE, true, false)
            .withProperty("mmwave_area3_occupancy")
            .withDescription("Indicates whether the device detected occupancy in Area 3"),
        e
            .binary("area4Occupancy", ea.STATE, true, false)
            .withProperty("mmwave_area4_occupancy")
            .withDescription("Indicates whether the device detected occupancy in Area 4"),
    ];
};
const createAreaComposite = (areaName, property) => {
    return e
        .composite(areaName, property, ea.STATE)
        .withFeature(e
        .numeric("width_min", ea.STATE_SET)
        .withValueMin(-600)
        .withValueMax(600)
        .withDescription("Defines the area (negative values are left of the switch facing away from the wall, positive values are right)"))
        .withFeature(e
        .numeric("width_max", ea.STATE_SET)
        .withValueMin(-600)
        .withValueMax(600)
        .withDescription("Defines the area (negative values are left of the switch facing away from the wall, positive values are right)"))
        .withFeature(e
        .numeric("height_min", ea.STATE_SET)
        .withValueMin(-600)
        .withValueMax(600)
        .withDescription("Defines the area (negative values are below the switch, positive values are above)"))
        .withFeature(e
        .numeric("height_max", ea.STATE_SET)
        .withValueMin(-600)
        .withValueMax(600)
        .withDescription("Defines the area (negative values are below the switch, positive values are above)"))
        .withFeature(e.numeric("depth_min", ea.STATE_SET).withValueMin(0).withValueMax(600).withDescription("Defines the area in front of the switch"))
        .withFeature(e.numeric("depth_max", ea.STATE_SET).withValueMin(0).withValueMax(600).withDescription("Defines the area in front of the switch"));
};
const exposeDetectionAreas = () => {
    return e
        .composite("mmwave_detection_areas", "mmwave_detection_areas", ea.STATE_SET)
        .withDescription("Defines one or more active detection zones where the sensor reports movement or occupancy. Up to four detection zones can be set.")
        .withFeature(createAreaComposite("area_1", "area1"))
        .withFeature(createAreaComposite("area_2", "area2"))
        .withFeature(createAreaComposite("area_3", "area3"))
        .withFeature(createAreaComposite("area_4", "area4"))
        .withCategory("config");
};
const exposeInterferenceAreas = () => {
    return e
        .composite("mmwave_interference_areas", "mmwave_interference_areas", ea.STATE_SET)
        .withDescription("Manually defines the coordinates of an interference area, which is an ignored zone where targets are not reported as present. Up to four zones can be defined.")
        .withFeature(createAreaComposite("area_1", "area1"))
        .withFeature(createAreaComposite("area_2", "area2"))
        .withFeature(createAreaComposite("area_3", "area3"))
        .withFeature(createAreaComposite("area_4", "area4"))
        .withCategory("config");
};
const exposeStayAreas = () => {
    return e
        .composite("mmwave_stay_areas", "mmwave_stay_areas", ea.STATE_SET)
        .withDescription("Defines one or more stay areas where stationary presence should still be detected. Up to four stay zones can be configured.")
        .withFeature(createAreaComposite("area_1", "area1"))
        .withFeature(createAreaComposite("area_2", "area2"))
        .withFeature(createAreaComposite("area_3", "area3"))
        .withFeature(createAreaComposite("area_4", "area4"))
        .withCategory("config");
};
const exposeMMWaveTargets = () => {
    const targetComposite = e
        .composite("target", "target", ea.STATE)
        .withFeature(e.numeric("id", ea.STATE).withDescription("Target ID"))
        .withFeature(e.numeric("x", ea.STATE).withUnit("cm").withDescription("X-axis coordinate of the target in centimeters"))
        .withFeature(e.numeric("y", ea.STATE).withUnit("cm").withDescription("Y-axis coordinate of the target in centimeters"))
        .withFeature(e.numeric("z", ea.STATE).withUnit("cm").withDescription("Z-axis coordinate of the target in centimeters"))
        .withFeature(e.numeric("dop", ea.STATE).withDescription("Doppler shift speed of the target"));
    return e
        .list("mmwave_targets", ea.STATE, targetComposite)
        .withLengthMin(0)
        .withLengthMax(4)
        .withDescription("All of the detected mmWave targets")
        .withCategory("diagnostic");
};
const BUTTON_TAP_SEQUENCES = [
    "down_single",
    "up_single",
    "config_single",
    "down_release",
    "up_release",
    "config_release",
    "down_held",
    "up_held",
    "config_held",
    "down_double",
    "up_double",
    "config_double",
    "down_triple",
    "up_triple",
    "config_triple",
    "down_quadruple",
    "up_quadruple",
    "config_quadruple",
    "down_quintuple",
    "up_quintuple",
    "config_quintuple",
];
/*
 * Inovelli devices have a huge number of attributes. Calling endpoint.read() in a single call
 * for all attributes causes timeouts even with the timeout set to an absurdly high number (2 minutes)
 */
const chunkedRead = async (endpoint, attributes, cluster) => {
    const chunkSize = 10;
    for (let i = 0; i < attributes.length; i += chunkSize) {
        // XXX: far too dynamic to properly type
        await endpoint.read(cluster, attributes.slice(i, i + chunkSize));
    }
};
//# sourceMappingURL=inovelli.js.map