"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.definitions = void 0;
const zigbee_herdsman_1 = require("zigbee-herdsman");
const fz = __importStar(require("../converters/fromZigbee"));
const exposes = __importStar(require("../lib/exposes"));
const logger_1 = require("../lib/logger");
const m = __importStar(require("../lib/modernExtend"));
const utils = __importStar(require("../lib/utils"));
const utils_1 = require("../lib/utils");
const e = exposes.presets;
const ea = exposes.access;
const SHELLY_ENDPOINT_ID = 239;
const SHELLY_OPTIONS = { profileId: zigbee_herdsman_1.ZSpec.CUSTOM_SHELLY_PROFILE_ID };
const NS = "zhc:shelly";
const HA_ELECTRICAL_MEASUREMENT_CLUSTER_ID = 0x0b04;
const HA_ELECTRICAL_MEASUREMENT_POWER_FACTOR_ATTR_ID = 0x0510;
const shellyModernExtend = {
    shellyPowerFactorInt16Fix() {
        // Shelly Gen4 devices report haElectricalMeasurement.powerFactor (0x0510) as INT16 (0x29)
        // while zigbee-herdsman defines it as INT8 (0x28). This breaks configureReporting (INVALID_DATA_TYPE).
        return m.deviceAddCustomCluster("haElectricalMeasurement", {
            ID: HA_ELECTRICAL_MEASUREMENT_CLUSTER_ID,
            attributes: {
                powerFactor: { ID: HA_ELECTRICAL_MEASUREMENT_POWER_FACTOR_ATTR_ID, type: zigbee_herdsman_1.Zcl.DataType.INT16 },
            },
            commands: {},
            commandsResponse: {},
        });
    },
    shellyCustomClusters() {
        return [
            m.deviceAddCustomCluster("shellyRPCCluster", {
                ID: 0xfc01,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SHELLY,
                attributes: {
                    data: { ID: 0x0000, type: zigbee_herdsman_1.Zcl.DataType.CHAR_STR, write: true },
                    txCtl: { ID: 0x0001, type: zigbee_herdsman_1.Zcl.DataType.UINT32, write: true, max: 0xffffffff },
                    rxCtl: { ID: 0x0002, type: zigbee_herdsman_1.Zcl.DataType.UINT32, write: true, max: 0xffffffff },
                },
                commands: {},
                commandsResponse: {},
            }),
            m.deviceAddCustomCluster("shellyWiFiSetupCluster", {
                ID: 0xfc02,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SHELLY,
                attributes: {
                    status: { ID: 0x0000, type: zigbee_herdsman_1.Zcl.DataType.CHAR_STR, write: true },
                    ip: { ID: 0x0001, type: zigbee_herdsman_1.Zcl.DataType.CHAR_STR, write: true },
                    actionCode: { ID: 0x0002, type: zigbee_herdsman_1.Zcl.DataType.UINT8, write: true, max: 0xff },
                    dhcp: { ID: 0x0003, type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN, write: true },
                    enabled: { ID: 0x0004, type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN, write: true },
                    ssid: { ID: 0x0005, type: zigbee_herdsman_1.Zcl.DataType.CHAR_STR, write: true },
                    password: { ID: 0x0006, type: zigbee_herdsman_1.Zcl.DataType.CHAR_STR, write: true },
                    staticIp: { ID: 0x0007, type: zigbee_herdsman_1.Zcl.DataType.CHAR_STR, write: true },
                    netMask: { ID: 0x0008, type: zigbee_herdsman_1.Zcl.DataType.CHAR_STR, write: true },
                    gateway: { ID: 0x0009, type: zigbee_herdsman_1.Zcl.DataType.CHAR_STR, write: true },
                    nameServer: { ID: 0x000a, type: zigbee_herdsman_1.Zcl.DataType.CHAR_STR, write: true },
                },
                commands: {},
                commandsResponse: {},
            }),
        ];
    },
    shellyRPCSetup(features = []) {
        // Set helper variables
        const shellyRPCBugFixed = false; // For firmware 20250819-150402/ga0def2d
        const featureDev = features.includes("Dev");
        const featurePowerstripUI = features.includes("PowerstripUI");
        // Generic helper functions
        const validateTime = (value) => {
            const hhmmRegex = /^([01][0-9]|2[0-3]):[0-5][0-9]$/;
            if (value === undefined || !value.match(hhmmRegex)) {
                throw new Error(`Invalid time "${value}"`);
            }
        };
        // RPC helper functions
        let rpcSending = false;
        const rpcSendRaw = async (endpoint, message) => {
            // Since RPC messages require multiple writes to complete, we have to make sure
            // we're not interleaving them accidentally. This is good enough for now, at least
            // until the RPC receive firmware bug is fixed by Shelly.
            while (rpcSending) {
                await (0, utils_1.sleep)(200);
            }
            try {
                rpcSending = true;
                const splitBytes = 40;
                logger_1.logger.debug(">>> shellyRPC write TxCtl", NS);
                const txCtl = message.length;
                await endpoint.write("shellyRPCCluster", { txCtl: txCtl }, SHELLY_OPTIONS);
                logger_1.logger.debug(`>>> TxCtl: ${txCtl}`, NS);
                logger_1.logger.debug(">>> shellyRPC write Data", NS);
                let dataToSend = message;
                while (dataToSend.length > 0) {
                    const data = dataToSend.substring(0, splitBytes);
                    dataToSend = dataToSend.substring(splitBytes);
                    await endpoint.write("shellyRPCCluster", { data: data }, SHELLY_OPTIONS);
                    logger_1.logger.debug(`>>> Data: ${data}`, NS);
                }
            }
            finally {
                rpcSending = false;
            }
        };
        const rpcSend = async (endpoint, method, params = undefined) => {
            const command = {
                id: 1, // We can't read replies anyway so don't care for now
                method: method,
                params: params,
            };
            return await rpcSendRaw(endpoint, JSON.stringify(command));
        };
        const rpcReceive = async (endpoint, key) => {
            logger_1.logger.debug(`||| shellyRPC rpcReceive(${key})`, NS);
            if (key === "rpc_rxctl") {
                logger_1.logger.debug(">>> shellyRPC read RxCtl", NS);
                const result = await endpoint.read("shellyRPCCluster", ["rxCtl"], SHELLY_OPTIONS);
                logger_1.logger.debug(`<<< RxCtl: ${JSON.stringify(result)}`, NS);
            }
            else if (key === "rpc_data") {
                logger_1.logger.debug(">>> shellyRPC read Data", NS);
                const result = await endpoint.read("shellyRPCCluster", ["data"], { ...SHELLY_OPTIONS, timeout: 1000 });
                logger_1.logger.debug(`<<< Data: ${JSON.stringify(result)}`, NS);
            }
        };
        // Features for exposes
        const featurePercentage = (name, label) => {
            return e.numeric(name, ea.STATE_SET).withValueMin(0).withValueMax(100).withValueStep(1).withLabel(label).withUnit("%");
        };
        const featureButtonEnabled = (id) => {
            return e.binary(`switch_${id}`, ea.STATE_SET, "momentary", "detached").withLabel(`Endpoint: ${id + 1}`);
        };
        const exposes = [];
        const exposesDev = [
            e
                .text("rpc_tx", ea.STATE_SET)
                .withLabel("TX Data")
                .withDescription("See https://shelly-api-docs.shelly.cloud/gen2/Devices/Gen4/ShellyPowerStripG4"),
            e.text("rpc_rxctl", ea.STATE_GET).withLabel("RxCtl").withDescription("RX bytes available").withCategory("diagnostic"),
            e.text("rpc_data", ea.STATE_GET).withLabel("Data").withDescription("RX Data").withCategory("diagnostic"),
        ];
        const exposesPowerstripUI = [
            e
                .enum("led_mode", ea.STATE_SET, ["off", "switch", "power"])
                .withLabel("LED Mode")
                .withDescription("Controls the behaviour of the LED rings around the sockets")
                .withCategory("config"),
            e
                .composite("led_colors", "led_colors", ea.ALL)
                .withFeature(featurePercentage("on_r", "Red (on)"))
                .withFeature(featurePercentage("on_g", "Green (on)"))
                .withFeature(featurePercentage("on_b", "Blue (on)"))
                .withFeature(featurePercentage("on_brightness", "Brightness (on)"))
                .withFeature(featurePercentage("off_r", "Red (off)"))
                .withFeature(featurePercentage("off_g", "Green (off)"))
                .withFeature(featurePercentage("off_b", "Blue (off)"))
                .withFeature(featurePercentage("off_brightness", "Brightness (off)"))
                .withLabel("LED colors in 'switch' mode")
                .withCategory("config"),
            featurePercentage("led_power_brightness", "LED brightness in 'power' mode").withCategory("config"),
            e
                .composite("led_night_mode", "led_night_mode", ea.ALL)
                .withFeature(e.binary("enable", ea.STATE_SET, true, false))
                .withFeature(featurePercentage("brightness", "Brightness"))
                .withFeature(e.text("from", ea.STATE_SET).withLabel("Active from").withDescription("hh:mm"))
                .withFeature(e.text("until", ea.STATE_SET).withLabel("Active until").withDescription("hh:mm"))
                .withLabel("LED night mode")
                .withDescription("Adjust LED brightness during night time")
                .withCategory("config"),
            e
                .composite("buttons_enabled", "buttons_enabled", ea.ALL)
                .withFeature(featureButtonEnabled(0))
                .withFeature(featureButtonEnabled(1))
                .withFeature(featureButtonEnabled(2))
                .withFeature(featureButtonEnabled(3))
                .withLabel("Buttons enabled")
                .withCategory("config"),
        ];
        const fromZigbee = [
            {
                cluster: "shellyRPCCluster",
                type: ["attributeReport", "readResponse"],
                convert: (model, msg, publish, options, meta) => {
                    const state = {};
                    // Diagnostic data
                    if (msg.data.rxCtl !== undefined) {
                        state.rpc_rxctl = msg.data.rxCtl;
                        state.rpc_data = "";
                    }
                    if (msg.data.data !== undefined)
                        state.rpc_data = meta.state.rpc_data + msg.data.data;
                    return state;
                },
            },
        ];
        const toZigbee = [];
        const toZigbeeDev = [
            {
                key: ["rpc_rxctl", "rpc_data"],
                convertGet: async (entity, key, meta) => {
                    const ep = (0, utils_1.determineEndpoint)(entity, meta, "shellyRPCCluster");
                    await rpcReceive(ep, key);
                },
            },
            {
                key: ["rpc_tx"],
                convertSet: async (entity, key, value, meta) => {
                    logger_1.logger.debug(`>>> toZigbee.convertSet(${key}): ${value}`, NS);
                    const ep = (0, utils_1.determineEndpoint)(entity, meta, "shellyRPCCluster");
                    await rpcSendRaw(ep, value);
                    await rpcReceive(ep, "rpc_rxctl");
                    if (shellyRPCBugFixed) {
                        await rpcReceive(ep, "rpc_data");
                    }
                    else {
                        return { state: { rpc_data: "[Refresh for response]" } };
                    }
                },
            },
        ];
        const toZigbeePowerstripUI = [
            {
                key: ["led_mode"],
                convertSet: async (entity, key, value, meta) => {
                    const ep = (0, utils_1.determineEndpoint)(entity, meta, "shellyRPCCluster");
                    await rpcSend(ep, "POWERSTRIP_UI.SetConfig", {
                        config: {
                            leds: {
                                mode: value,
                            },
                        },
                    });
                },
            },
            {
                key: ["led_colors"],
                convertSet: async (entity, key, value, meta) => {
                    (0, utils_1.assertObject)(value);
                    const ep = (0, utils_1.determineEndpoint)(entity, meta, "shellyRPCCluster");
                    await rpcSend(ep, "POWERSTRIP_UI.SetConfig", {
                        config: {
                            leds: {
                                colors: {
                                    "switch:0": {
                                        on: {
                                            rgb: [value.on_r ?? 0, value.on_g ?? 0, value.on_b ?? 0],
                                            brightness: value.on_brightness ?? 0,
                                        },
                                        off: {
                                            rgb: [value.off_r ?? 0, value.off_g ?? 0, value.off_b ?? 0],
                                            brightness: value.off_brightness ?? 0,
                                        },
                                    },
                                },
                            },
                        },
                    });
                },
            },
            {
                key: ["led_power_brightness"],
                convertSet: async (entity, key, value, meta) => {
                    const ep = (0, utils_1.determineEndpoint)(entity, meta, "shellyRPCCluster");
                    await rpcSend(ep, "POWERSTRIP_UI.SetConfig", {
                        config: {
                            leds: {
                                colors: {
                                    power: {
                                        brightness: value ?? 0,
                                    },
                                },
                            },
                        },
                    });
                },
            },
            {
                key: ["led_night_mode"],
                convertSet: async (entity, key, value, meta) => {
                    (0, utils_1.assertObject)(value);
                    validateTime(value.from);
                    validateTime(value.until);
                    const ep = (0, utils_1.determineEndpoint)(entity, meta, "shellyRPCCluster");
                    await rpcSend(ep, "POWERSTRIP_UI.SetConfig", {
                        config: {
                            leds: {
                                night_mode: {
                                    enable: value.enable,
                                    brightness: value.brightness,
                                    active_between: [value.from, value.until],
                                },
                            },
                        },
                    });
                },
            },
            {
                key: ["buttons_enabled"],
                convertSet: async (entity, key, value, meta) => {
                    (0, utils_1.assertObject)(value);
                    const ep = (0, utils_1.determineEndpoint)(entity, meta, "shellyRPCCluster");
                    await rpcSend(ep, "POWERSTRIP_UI.SetConfig", {
                        config: {
                            controls: {
                                "switch:0": {
                                    in_mode: value.switch_0,
                                },
                                "switch:1": {
                                    in_mode: value.switch_1,
                                },
                                "switch:2": {
                                    in_mode: value.switch_2,
                                },
                                "switch:3": {
                                    in_mode: value.switch_3,
                                },
                            },
                        },
                    });
                },
            },
        ];
        if (featureDev) {
            exposes.push(...exposesDev);
            toZigbee.push(...toZigbeeDev);
        }
        if (featurePowerstripUI) {
            exposes.push(...exposesPowerstripUI);
            toZigbee.push(...toZigbeePowerstripUI);
        }
        return { exposes, fromZigbee, toZigbee, isModernExtend: true };
    },
    shellyWiFiSetup() {
        // biome-ignore lint/suspicious/noExplicitAny: generic
        const refresh = async (endpoint) => {
            await endpoint.write("shellyWiFiSetupCluster", { actionCode: 0 }, SHELLY_OPTIONS);
            await endpoint.read("shellyWiFiSetupCluster", ["status", "ip", "enabled", "dhcp", "ssid"], SHELLY_OPTIONS);
            await endpoint.read("shellyWiFiSetupCluster", ["staticIp", "netMask"], SHELLY_OPTIONS);
            await endpoint.read("shellyWiFiSetupCluster", ["gateway", "nameServer"], SHELLY_OPTIONS);
        };
        const exposes = [
            e.text("wifi_status", ea.STATE_GET).withLabel("Wi-Fi status").withDescription("Current connection status").withCategory("diagnostic"),
            e
                .text("ip_address", ea.STATE_GET)
                .withLabel("IP address")
                .withDescription("IP address currently assigned to the device")
                .withCategory("diagnostic"),
            e
                .binary("dhcp_enabled", ea.STATE_GET, true, false)
                .withLabel("DHCP enabled")
                .withDescription("Indicates whether DHCP is used to automatically assign network settings")
                .withCategory("diagnostic"),
            e
                .composite("wifi_config", "wifi_config", ea.ALL)
                .withFeature(e.binary("enabled", ea.STATE_SET, true, false).withLabel("Wi-Fi enabled").withDescription("Enable/disable Wi-Fi connectivity"))
                .withFeature(e.text("ssid", ea.STATE_SET).withLabel("Network").withDescription("Name (SSID) of the Wi-Fi network to connect to"))
                .withFeature(e.text("password", ea.SET).withLabel("Password").withDescription("Password for the selected Wi-Fi network"))
                .withFeature(e
                .text("static_ip", ea.STATE_SET)
                .withLabel("IPv4 address")
                .withDescription("Manually assigned IP address (used when DHCP is disabled)"))
                .withFeature(e.text("net_mask", ea.STATE_SET).withLabel("Network mask").withDescription("Subnet mask for the static IP configuration"))
                .withFeature(e.text("gateway", ea.STATE_SET).withLabel("Gateway").withDescription("Default gateway address for static IP configuration"))
                .withFeature(e.text("name_server", ea.STATE_SET).withLabel("DNS").withDescription("Name server address for static IP configuration"))
                .withLabel("Wi-Fi Configuration")
                .withCategory("config"),
        ];
        // biome-ignore lint/suspicious/noExplicitAny: generic
        const fromZigbee = [
            {
                cluster: "shellyWiFiSetupCluster",
                type: ["attributeReport", "readResponse"],
                convert: (model, msg, publish, options, meta) => {
                    const wifi_config = {};
                    const state = { wifi_config };
                    // Diagnostic data
                    if (msg.data.status !== undefined)
                        state.wifi_status = msg.data.status;
                    if (msg.data.ip !== undefined)
                        state.ip_address = msg.data.ip;
                    if (msg.data.dhcp !== undefined)
                        state.dhcp_enabled = msg.data.dhcp === 1;
                    // Wi-Fi config
                    if (msg.data.enabled !== undefined)
                        wifi_config.enabled = msg.data.enabled === 1;
                    if (msg.data.ssid !== undefined)
                        wifi_config.ssid = msg.data.ssid;
                    if (msg.data.staticIp !== undefined)
                        wifi_config.static_ip = msg.data.staticIp;
                    if (msg.data.netMask !== undefined)
                        wifi_config.net_mask = msg.data.netMask;
                    if (msg.data.gateway !== undefined)
                        wifi_config.gateway = msg.data.gateway;
                    if (msg.data.nameServer !== undefined)
                        wifi_config.name_server = msg.data.nameServer;
                    // Cleanup empty keys
                    for (const key in wifi_config) {
                        if (wifi_config[key] === "") {
                            wifi_config[key] = undefined;
                        }
                    }
                    return state;
                },
            },
        ];
        const toZigbee = [
            {
                key: ["wifi_status", "ip_address", "dhcp_enabled"],
                convertGet: async (entity, key, meta) => {
                    const ep = (0, utils_1.determineEndpoint)(entity, meta, "shellyWiFiSetupCluster");
                    await refresh(ep);
                },
            },
            {
                key: ["wifi_config"],
                convertGet: async (entity, key, meta) => {
                    const ep = (0, utils_1.determineEndpoint)(entity, meta, "shellyWiFiSetupCluster");
                    await refresh(ep);
                },
                convertSet: async (entity, key, value, meta) => {
                    (0, utils_1.assertObject)(value);
                    const ep = (0, utils_1.determineEndpoint)(entity, meta, "shellyWiFiSetupCluster");
                    const attr1 = {
                        enabled: value.enabled === true,
                        ssid: value.ssid || "",
                    };
                    await ep.write("shellyWiFiSetupCluster", attr1, SHELLY_OPTIONS);
                    const attr2 = {
                        password: value.password || "",
                    };
                    await ep.write("shellyWiFiSetupCluster", attr2, SHELLY_OPTIONS);
                    const attr3 = {
                        staticIp: value.static_ip || "",
                        netMask: value.net_mask || "",
                    };
                    await ep.write("shellyWiFiSetupCluster", attr3, SHELLY_OPTIONS);
                    const attr4 = {
                        gateway: value.gateway || "",
                        nameServer: value.name_server || "",
                    };
                    await ep.write("shellyWiFiSetupCluster", attr4, SHELLY_OPTIONS);
                    const attr5 = {
                        actionCode: 1,
                    };
                    await ep.write("shellyWiFiSetupCluster", attr5, SHELLY_OPTIONS);
                    return {
                        state: {
                            wifi_config: {
                                enabled: attr1.enabled,
                                ssid: attr1.ssid === "" ? undefined : attr1.ssid,
                                static_ip: attr3.staticIp === "" ? undefined : attr3.staticIp,
                                net_mask: attr3.netMask === "" ? undefined : attr3.netMask,
                                gateway: attr4.gateway === "" ? undefined : attr4.gateway,
                                name_server: attr4.nameServer === "" ? undefined : attr4.nameServer,
                            },
                        },
                    };
                },
            },
        ];
        const configure = [
            async (device, coordinatorEndpoint, definition) => {
                const ep = device.getEndpoint(SHELLY_ENDPOINT_ID);
                await refresh(ep);
            },
        ];
        return { exposes, fromZigbee, toZigbee, configure, isModernExtend: true };
    },
};
const fzLocal = {
    one_button_events: {
        cluster: "genOnOff",
        type: ["commandToggle"],
        convert: (model, msg, publish, options, meta) => {
            const event = utils.getFromLookup(msg.endpoint.ID, { 1: "single", 2: "double", 3: "triple" });
            return { action: event };
        },
    },
    four_buttons_single_events: {
        cluster: "genOnOff",
        type: ["commandOn", "commandOff"],
        convert: (model, msg, publish, options, meta) => {
            const event = utils.getFromLookup(`${msg.endpoint.ID}_${msg.type}`, {
                "1_commandOn": "1_single",
                "1_commandOff": "2_single",
                "2_commandOn": "3_single",
                "2_commandOff": "4_single",
            });
            return { action: event };
        },
    },
    four_buttons_hold_events: {
        cluster: "genLevelCtrl",
        type: ["commandStep"],
        convert: (model, msg, publish, options, meta) => {
            const event = utils.getFromLookup(`${msg.endpoint.ID}_${msg.data.stepmode}`, {
                "1_0": "1_hold",
                "1_1": "2_hold",
                "2_0": "3_hold",
                "2_1": "4_hold",
            });
            return { action: event };
        },
    },
};
exports.definitions = [
    {
        zigbeeModel: ["Mini1", "1 Mini"],
        model: "S4SW-001X8EU",
        vendor: "Shelly",
        description: "1 Mini Gen 4",
        extend: [m.onOff({ powerOnBehavior: false }), ...shellyModernExtend.shellyCustomClusters(), shellyModernExtend.shellyWiFiSetup()],
    },
    {
        fingerprint: [{ modelID: "1", manufacturerName: "Shelly" }],
        model: "S4SW-001X16EU",
        vendor: "Shelly",
        description: "1 Gen 4",
        extend: [m.onOff({ powerOnBehavior: false }), ...shellyModernExtend.shellyCustomClusters(), shellyModernExtend.shellyWiFiSetup()],
    },
    {
        zigbeeModel: ["Mini1PM", "1PM Mini"],
        model: "S4SW-001P8EU",
        vendor: "Shelly",
        description: "1PM Mini Gen 4",
        extend: [
            m.onOff({ powerOnBehavior: false }),
            m.electricityMeter({ producedEnergy: true, acFrequency: true }),
            shellyModernExtend.shellyPowerFactorInt16Fix(),
            ...shellyModernExtend.shellyCustomClusters(),
            shellyModernExtend.shellyWiFiSetup(),
        ],
    },
    {
        zigbeeModel: ["1PM"],
        model: "S4SW-001P16EU",
        vendor: "Shelly",
        description: "1PM Gen 4",
        extend: [
            m.onOff({ powerOnBehavior: false }),
            m.electricityMeter({ producedEnergy: true, acFrequency: true }),
            shellyModernExtend.shellyPowerFactorInt16Fix(),
            ...shellyModernExtend.shellyCustomClusters(),
            shellyModernExtend.shellyWiFiSetup(),
        ],
    },
    {
        zigbeeModel: ["EM Mini"],
        model: "S4EM-001PXCEU16",
        vendor: "Shelly",
        description: "EM Mini Gen4",
        extend: [
            m.electricityMeter({ producedEnergy: true, acFrequency: true }),
            shellyModernExtend.shellyPowerFactorInt16Fix(),
            ...shellyModernExtend.shellyCustomClusters(),
            shellyModernExtend.shellyWiFiSetup(),
        ],
    },
    {
        fingerprint: [
            {
                type: "Router",
                manufacturerName: "Shelly",
                modelID: "2PM",
                endpoints: [
                    { ID: 1, profileID: 260, deviceID: 514, inputClusters: [0, 3, 4, 5, 258], outputClusters: [] },
                    { ID: 239, profileID: 49153, deviceID: 8193, inputClusters: [64513, 64514], outputClusters: [] },
                    { ID: 242, profileID: 41440, deviceID: 97, inputClusters: [], outputClusters: [33] },
                ],
            },
        ],
        model: "S4SW-002P16EU-COVER",
        vendor: "Shelly",
        description: "2PM Gen4 (Cover mode)",
        extend: [m.windowCovering({ controls: ["lift", "tilt"] }), ...shellyModernExtend.shellyCustomClusters(), shellyModernExtend.shellyWiFiSetup()],
    },
    {
        fingerprint: [
            {
                type: "Router",
                manufacturerName: "Shelly",
                modelID: "2PM",
                endpoints: [
                    { ID: 1, profileID: 260, deviceID: 266, inputClusters: [0, 3, 4, 5, 6, 2820, 1794], outputClusters: [] },
                    { ID: 2, profileID: 260, deviceID: 266, inputClusters: [4, 5, 6, 2820, 1794], outputClusters: [] },
                    { ID: 239, profileID: 49153, deviceID: 8193, inputClusters: [64513, 64514], outputClusters: [] },
                    { ID: 242, profileID: 41440, deviceID: 97, inputClusters: [], outputClusters: [33] },
                ],
            },
        ],
        model: "S4SW-002P16EU-SWITCH",
        vendor: "Shelly",
        description: "2PM Gen4 (Switch mode)",
        extend: [
            m.deviceEndpoints({ endpoints: { l1: 1, l2: 2 } }),
            m.onOff({ powerOnBehavior: false, endpointNames: ["l1", "l2"] }),
            m.electricityMeter({ producedEnergy: true, acFrequency: true, endpointNames: ["l1", "l2"] }),
            shellyModernExtend.shellyPowerFactorInt16Fix(),
            ...shellyModernExtend.shellyCustomClusters(),
            shellyModernExtend.shellyWiFiSetup(),
        ],
    },
    {
        fingerprint: [{ modelID: "Plug US", manufacturerName: "Shelly" }],
        model: "S4PL-00116US",
        vendor: "Shelly",
        description: "Plug US Gen4",
        extend: [
            m.onOff({ powerOnBehavior: false }),
            m.electricityMeter(),
            shellyModernExtend.shellyPowerFactorInt16Fix(),
            ...shellyModernExtend.shellyCustomClusters(),
            shellyModernExtend.shellyWiFiSetup(),
        ],
    },
    {
        fingerprint: [{ modelID: "Power Strip", manufacturerName: "Shelly" }],
        model: "S4PL-00416EU",
        vendor: "Shelly",
        description: "Power strip 4 Gen4",
        extend: [
            m.deviceEndpoints({ endpoints: { "1": 1, "2": 2, "3": 3, "4": 4 } }),
            m.onOff({ powerOnBehavior: false, endpointNames: ["1", "2", "3", "4"] }),
            m.electricityMeter({ endpointNames: ["1", "2", "3", "4"] }),
            shellyModernExtend.shellyPowerFactorInt16Fix(),
            ...shellyModernExtend.shellyCustomClusters(),
            shellyModernExtend.shellyRPCSetup(["PowerstripUI"]),
            shellyModernExtend.shellyWiFiSetup(),
        ],
    },
    {
        fingerprint: [{ modelID: "Flood", manufacturerName: "Shelly" }],
        model: "S4SN-0071A",
        vendor: "Shelly",
        description: "Flood Gen 4",
        extend: [
            m.battery(),
            m.iasZoneAlarm({ zoneType: "water_leak", zoneAttributes: ["alarm_1", "tamper", "battery_low"] }),
            ...shellyModernExtend.shellyCustomClusters(),
            shellyModernExtend.shellyWiFiSetup(),
        ],
    },
    {
        fingerprint: [{ modelID: "Ecowitt WS90", manufacturerName: "Shelly" }],
        model: "WS90",
        vendor: "Shelly",
        description: "Weather station",
        extend: [
            m.battery(),
            m.illuminance(),
            m.temperature(),
            m.pressure(),
            m.humidity(),
            m.deviceAddCustomCluster("shellyWS90Wind", {
                ID: 0xfc01,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SHELLY,
                attributes: {},
                commands: {},
                commandsResponse: {},
            }),
            m.numeric({
                name: "wind_speed",
                cluster: "shellyWS90Wind",
                attribute: { ID: 0x0000, type: zigbee_herdsman_1.Zcl.DataType.UINT16 },
                valueMin: 0,
                valueMax: 140,
                reporting: { min: "10_SECONDS", max: "1_HOUR", change: 1 },
                description: "Wind speed in m/s",
                scale: 10,
                unit: "m/s",
                access: "STATE_GET",
            }),
            m.numeric({
                name: "wind_direction",
                cluster: "shellyWS90Wind",
                attribute: { ID: 0x0004, type: zigbee_herdsman_1.Zcl.DataType.UINT16 },
                valueMin: 0,
                valueMax: 360,
                reporting: { min: "10_SECONDS", max: "1_HOUR", change: 1 },
                description: "Wind direction in degrees",
                scale: 10,
                unit: "°",
                access: "STATE_GET",
            }),
            m.numeric({
                name: "gust_speed",
                cluster: "shellyWS90Wind",
                attribute: { ID: 0x0007, type: zigbee_herdsman_1.Zcl.DataType.UINT16 },
                valueMin: 0,
                valueMax: 140,
                reporting: { min: "10_SECONDS", max: "1_HOUR", change: 1 },
                description: "Gust speed in m/s",
                scale: 10,
                unit: "m/s",
                access: "STATE_GET",
            }),
            m.deviceAddCustomCluster("shellyWS90UV", {
                ID: 0xfc02,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SHELLY,
                attributes: {},
                commands: {},
                commandsResponse: {},
            }),
            m.numeric({
                name: "uv_index",
                cluster: "shellyWS90UV",
                attribute: { ID: 0x0000, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
                valueMin: 0,
                valueMax: 11,
                reporting: { min: "10_SECONDS", max: "1_HOUR", change: 1 },
                description: "UV index",
                scale: 10,
                access: "STATE_GET",
            }),
            m.deviceAddCustomCluster("shellyWS90Rain", {
                ID: 0xfc03,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SHELLY,
                attributes: {},
                commands: {},
                commandsResponse: {},
            }),
            m.binary({
                name: "rain_status",
                cluster: "shellyWS90Rain",
                attribute: { ID: 0x0000, type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN },
                valueOn: [true, 1],
                valueOff: [false, 0],
                reporting: { min: "10_SECONDS", max: "1_HOUR", change: 1 },
                description: "Rain status",
                access: "STATE_GET",
            }),
            m.numeric({
                name: "precipitation",
                cluster: "shellyWS90Rain",
                attribute: { ID: 0x0001, type: zigbee_herdsman_1.Zcl.DataType.UINT24 },
                valueMin: 0,
                valueMax: 100000,
                reporting: { min: "10_SECONDS", max: "1_HOUR", change: 1 },
                description: "Precipitation",
                unit: "mm",
                scale: 10,
                access: "STATE_GET",
            }),
        ],
    },
    {
        fingerprint: [{ modelID: "Dimmer", manufacturerName: "Shelly" }],
        model: "S4DM-0A101WWL",
        vendor: "Shelly",
        description: "Dimmer Gen4",
        extend: [
            m.light({ configureReporting: true }),
            m.electricityMeter(),
            shellyModernExtend.shellyPowerFactorInt16Fix(),
            ...shellyModernExtend.shellyCustomClusters(),
            shellyModernExtend.shellyWiFiSetup(),
        ],
    },
    {
        fingerprint: [{ modelID: "BLU H&T ZB", manufacturerName: "Shelly" }],
        model: "SBHT-203C",
        vendor: "Shelly",
        description: "Humidity & temperature sensor",
        extend: [m.battery(), m.temperature(), m.humidity()],
    },
    {
        fingerprint: [{ modelID: "BLU H&T Display ZB", manufacturerName: "Shelly" }],
        model: "SBHT-103C",
        vendor: "Shelly",
        description: "BLU H&T display Zigbee",
        extend: [m.battery(), m.temperature(), m.humidity()],
    },
    {
        fingerprint: [{ modelID: "BLU Remote Control ZB", manufacturerName: "Shelly" }],
        model: "SBRC-005B-B",
        vendor: "Shelly",
        description: "BLU Remote Control ZB",
        exposes: [
            e.action(["on", "off", "brightness_step_up", "brightness_step_down"]),
            e.numeric("action_group", ea.STATE).withDescription("Group ID associated with the action command."),
            e.numeric("action_step_size", ea.STATE).withDescription("Step size value used for brightness step actions."),
            e.numeric("action_transition_time", ea.STATE).withDescription("Transition time in seconds for the action."),
        ],
        extend: [
            m.battery(),
            m.commandsOnOff({ commands: ["on", "off"] }),
            m.commandsLevelCtrl({ commands: ["brightness_step_up", "brightness_step_down"] }),
            m.identify(),
        ],
    },
    {
        fingerprint: [{ modelID: "BLU Button Tough 1 ZB", manufacturerName: "Shelly" }],
        model: "SBBT-102C",
        vendor: "Shelly",
        description: "BLU Button Tough 1 ZB",
        fromZigbee: [fzLocal.one_button_events],
        exposes: [e.action(["single", "double", "triple"])],
        extend: [m.battery(), m.deviceEndpoints({ endpoints: { "1": 1, "2": 2, "3": 3 } }), m.identify()],
    },
    {
        fingerprint: [{ modelID: "BLU RC Button 4 ZB", manufacturerName: "Shelly" }],
        model: "SBBT-104CUS",
        vendor: "Shelly",
        description: "BLU RC Button 4 ZB",
        fromZigbee: [fzLocal.four_buttons_single_events, fzLocal.four_buttons_hold_events],
        exposes: [e.action(["1_single", "2_single", "3_single", "4_single", "1_hold", "2_hold", "3_hold", "4_hold"])],
        extend: [m.battery(), m.deviceEndpoints({ endpoints: { "1": 1, "2": 2, "3": 3, "4": 4 } }), m.identify()],
    },
    {
        zigbeeModel: ["BLU Wall Switch 4 ZB"],
        model: "SBBT-004CEU",
        vendor: "Shelly",
        description: "BLU Wall Switch 4 ZB",
        whiteLabel: [{ vendor: "Shelly", model: "SBBT-104CEU", description: "BLU Wall Switch 4 ZB DK" }],
        fromZigbee: [fzLocal.four_buttons_single_events, fzLocal.four_buttons_hold_events],
        exposes: [e.action(["1_single", "2_single", "3_single", "4_single", "1_hold", "2_hold", "3_hold", "4_hold"])],
        extend: [m.battery(), m.deviceEndpoints({ endpoints: { "1": 1, "2": 2, "3": 3, "4": 4 } }), m.identify()],
    },
    {
        zigbeeModel: ["BLU TRV"],
        model: "SBTR-001AEU",
        vendor: "Shelly",
        description: "Thermostatic radiator valve",
        fromZigbee: [
            fz.thermostat,
            {
                cluster: "hvacThermostat",
                type: ["attributeReport", "readResponse"],
                convert: (model, msg, publish, options, meta) => {
                    const result = {};
                    if (msg.data.alarmMask !== undefined) {
                        const alarmMask = msg.data.alarmMask;
                        result.calibration_ok = !((alarmMask & (1 << 2)) > 0);
                    }
                    return result;
                },
            },
        ],
        toZigbee: [
            {
                key: ["calibrate"],
                convertSet: async (entity, key, value, meta) => {
                    await entity.command("shellyTRVManualMode", "calibrate", {}, { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SHELLY });
                },
            },
        ],
        exposes: [
            e.binary("calibration_ok", ea.STATE, true, false).withDescription("Calibration OK").withCategory("diagnostic"),
            e.enum("calibrate", ea.SET, ["trigger"]).withDescription("Trigger valve calibration").withCategory("config"),
        ],
        extend: [
            m.battery(),
            m.thermostat({
                localTemperatureCalibration: { values: { min: -10, max: 10, step: 0.1 } },
                setpoints: {
                    values: {
                        occupiedHeatingSetpoint: { min: 4, max: 30, step: 0.1 },
                        unoccupiedHeatingSetpoint: { min: 4, max: 30, step: 0.1 },
                    },
                },
                setpointsLimit: {
                    minHeatSetpointLimit: { min: 4, max: 30, step: 0.1 },
                    maxHeatSetpointLimit: { min: 4, max: 30, step: 0.1 },
                },
                systemMode: { values: ["off", "auto", "heat"] },
                piHeatingDemand: { values: true },
            }),
            m.deviceAddCustomCluster("shellyTRVManualMode", {
                ID: 0xfc24,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.SHELLY,
                attributes: {
                    manualMode: { ID: 0x0000, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
                    position: { ID: 0x0001, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
                },
                commands: {
                    calibrate: { ID: 0x0000, parameters: [] },
                },
                commandsResponse: {},
            }),
            m.binary({
                name: "manual_mode",
                cluster: "shellyTRVManualMode",
                attribute: { ID: 0x0000, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
                valueOn: [true, 1],
                valueOff: [false, 0],
                description: "Manual mode (0 = auto, 1 = manual)",
                access: "ALL",
            }),
            m.numeric({
                name: "valve_position",
                cluster: "shellyTRVManualMode",
                attribute: { ID: 0x0001, type: zigbee_herdsman_1.Zcl.DataType.UINT8 },
                valueMin: 0,
                valueMax: 100,
                reporting: { min: "10_SECONDS", max: "1_HOUR", change: 1 },
                description: "Valve position (0-100%)",
                unit: "%",
                access: "ALL",
            }),
            m.identify(),
        ],
    },
];
//# sourceMappingURL=shelly.js.map