UNPKG

zigbee-herdsman-converters

Version:

Collection of device converters to be used with zigbee-herdsman

1,866 lines 89.5 kB
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.definitions = void 0;
const zigbee_herdsman_1 = require("zigbee-herdsman");
const fz = __importStar(require("../converters/fromZigbee"));
const tz = __importStar(require("../converters/toZigbee"));
const constants = __importStar(require("../lib/constants"));
const exposes = __importStar(require("../lib/exposes"));
const m = __importStar(require("../lib/modernExtend"));
const reporting = __importStar(require("../lib/reporting"));
const utils = __importStar(require("../lib/utils"));
const utils_1 = require("../lib/utils");
const e = exposes.presets;
const ea = exposes.access;
const setTime = async (device, sendPolicy) => {
    const endpoint = device.getEndpoint(1);
    const { time, timeZone, dstStart, dstEnd, dstShift } = (0, zigbee_herdsman_1.getTimeClusterAttributes)();
    await endpoint.write("genTime", {
        time,
        timeStatus: 0x02, // bit 1 = synchronized (per Danfoss spec §1.2)
        timeZone,
        dstStart,
        dstEnd,
        dstShift,
    }, sendPolicy ? { sendPolicy } : undefined);
};
const danfossExtend = {
    addDanfossHvacThermostatCluster: () => m.deviceAddCustomCluster("hvacThermostat", {
        name: "hvacThermostat",
        ID: zigbee_herdsman_1.Zcl.Clusters.hvacThermostat.ID,
        attributes: {
            danfossWindowOpenInternal: {
                name: "danfossWindowOpenInternal",
                ID: 0x4000,
                type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
                max: 0xff,
            },
            danfossWindowOpenExternal: {
                name: "danfossWindowOpenExternal",
                ID: 0x4003,
                type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
            },
            danfossDayOfWeek: {
                name: "danfossDayOfWeek",
                ID: 0x4010,
                type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
                max: 0xff,
            },
            danfossTriggerTime: {
                name: "danfossTriggerTime",
                ID: 0x4011,
                type: zigbee_herdsman_1.Zcl.DataType.UINT16,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
                max: 0xffff,
            },
            danfossMountedModeActive: {
                name: "danfossMountedModeActive",
                ID: 0x4012,
                type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
            },
            danfossMountedModeControl: {
                name: "danfossMountedModeControl",
                ID: 0x4013,
                type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
            },
            danfossThermostatOrientation: {
                name: "danfossThermostatOrientation",
                ID: 0x4014,
                type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
            },
            danfossExternalMeasuredRoomSensor: {
                name: "danfossExternalMeasuredRoomSensor",
                ID: 0x4015,
                type: zigbee_herdsman_1.Zcl.DataType.INT16,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
                min: -32768,
                max: 32767,
            },
            danfossRadiatorCovered: {
                name: "danfossRadiatorCovered",
                ID: 0x4016,
                type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
            },
            danfossAlgorithmScaleFactor: {
                name: "danfossAlgorithmScaleFactor",
                ID: 0x4020,
                type: zigbee_herdsman_1.Zcl.DataType.UINT8,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
                max: 0xff,
            },
            danfossHeatAvailable: {
                name: "danfossHeatAvailable",
                ID: 0x4030,
                type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
            },
            danfossHeatRequired: {
                name: "danfossHeatRequired",
                ID: 0x4031,
                type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
            },
            danfossLoadBalancingEnable: {
                name: "danfossLoadBalancingEnable",
                ID: 0x4032,
                type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
            },
            danfossLoadRoomMean: {
                name: "danfossLoadRoomMean",
                ID: 0x4040,
                type: zigbee_herdsman_1.Zcl.DataType.INT16,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
                min: -32768,
                max: 32767,
            },
            danfossLoadEstimate: {
                name: "danfossLoadEstimate",
                ID: 0x404a,
                type: zigbee_herdsman_1.Zcl.DataType.INT16,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
                min: -32768,
                max: 32767,
            },
            danfossRegulationSetpointOffset: {
                name: "danfossRegulationSetpointOffset",
                ID: 0x404b,
                type: zigbee_herdsman_1.Zcl.DataType.INT8,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
                min: -128,
                max: 127,
            },
            danfossAdaptionRunControl: {
                name: "danfossAdaptionRunControl",
                ID: 0x404c,
                type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
                max: 0xff,
            },
            danfossAdaptionRunStatus: {
                name: "danfossAdaptionRunStatus",
                ID: 0x404d,
                type: zigbee_herdsman_1.Zcl.DataType.BITMAP8,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
            },
            danfossAdaptionRunSettings: {
                name: "danfossAdaptionRunSettings",
                ID: 0x404e,
                type: zigbee_herdsman_1.Zcl.DataType.BITMAP8,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
            },
            danfossPreheatStatus: {
                name: "danfossPreheatStatus",
                ID: 0x404f,
                type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
            },
            danfossPreheatTime: {
                name: "danfossPreheatTime",
                ID: 0x4050,
                type: zigbee_herdsman_1.Zcl.DataType.UINT32,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
            },
            danfossWindowOpenFeatureEnable: {
                name: "danfossWindowOpenFeatureEnable",
                ID: 0x4051,
                type: zigbee_herdsman_1.Zcl.DataType.BOOLEAN,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
            },
            danfossRoomStatusCode: {
                name: "danfossRoomStatusCode",
                ID: 0x4100,
                type: zigbee_herdsman_1.Zcl.DataType.BITMAP16,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
            },
            danfossOutputStatus: {
                name: "danfossOutputStatus",
                ID: 0x4110,
                type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
                max: 0xff,
            },
            danfossRoomFloorSensorMode: {
                name: "danfossRoomFloorSensorMode",
                ID: 0x4120,
                type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
                max: 0xff,
            },
            danfossFloorMinSetpoint: {
                name: "danfossFloorMinSetpoint",
                ID: 0x4121,
                type: zigbee_herdsman_1.Zcl.DataType.INT16,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
                min: -32768,
                max: 32767,
            },
            danfossFloorMaxSetpoint: {
                name: "danfossFloorMaxSetpoint",
                ID: 0x4122,
                type: zigbee_herdsman_1.Zcl.DataType.INT16,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
                min: -32768,
                max: 32767,
            },
            danfossScheduleTypeUsed: {
                name: "danfossScheduleTypeUsed",
                ID: 0x4130,
                type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
                max: 0xff,
            },
            danfossIcon2PreHeat: {
                name: "danfossIcon2PreHeat",
                ID: 0x4131,
                type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
                max: 0xff,
            },
            danfossIcon2PreHeatStatus: {
                name: "danfossIcon2PreHeatStatus",
                ID: 0x414f,
                type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
                max: 0xff,
            },
        },
        commands: {
            danfossSetpointCommand: {
                name: "danfossSetpointCommand",
                ID: 0x40,
                parameters: [
                    { name: "setpointType", type: zigbee_herdsman_1.Zcl.DataType.ENUM8, max: 0xff },
                    { name: "setpoint", type: zigbee_herdsman_1.Zcl.DataType.INT16, min: -32768, max: 32767 },
                ],
            },
            danfossPreHeatCommand: {
                name: "danfossPreHeatCommand",
                ID: 0x42,
                parameters: [
                    { name: "type", type: zigbee_herdsman_1.Zcl.DataType.ENUM8, max: 0xff },
                    { name: "timestamp", type: zigbee_herdsman_1.Zcl.DataType.UINT32 },
                ],
            },
        },
        commandsResponse: {},
    }),
    addDanfossHvacUserInterfaceCfgCluster: () => m.deviceAddCustomCluster("hvacUserInterfaceCfg", {
        name: "hvacUserInterfaceCfg",
        ID: zigbee_herdsman_1.Zcl.Clusters.hvacUserInterfaceCfg.ID,
        attributes: {
            danfossViewingDirection: {
                name: "danfossViewingDirection",
                ID: 0x4000,
                type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
                max: 0xff,
            },
        },
        commands: {},
        commandsResponse: {},
    }),
    addDanfossHaDiagnosticCluster: () => m.deviceAddCustomCluster("haDiagnostic", {
        name: "haDiagnostic",
        ID: zigbee_herdsman_1.Zcl.Clusters.haDiagnostic.ID,
        attributes: {
            danfossSystemStatusCode: {
                name: "danfossSystemStatusCode",
                ID: 0x4000,
                type: zigbee_herdsman_1.Zcl.DataType.BITMAP16,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
            },
            danfossHeatSupplyRequest: {
                name: "danfossHeatSupplyRequest",
                ID: 0x4031,
                type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
                max: 0xff,
            },
            danfossSystemStatusWater: {
                name: "danfossSystemStatusWater",
                ID: 0x4200,
                type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
                max: 0xff,
            },
            danfossMultimasterRole: {
                name: "danfossMultimasterRole",
                ID: 0x4201,
                type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
                max: 0xff,
            },
            danfossIconApplication: {
                name: "danfossIconApplication",
                ID: 0x4210,
                type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
                max: 0xff,
            },
            danfossIconForcedHeatingCooling: {
                name: "danfossIconForcedHeatingCooling",
                ID: 0x4220,
                type: zigbee_herdsman_1.Zcl.DataType.ENUM8,
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                write: true,
                max: 0xff,
            },
        },
        commands: {},
        commandsResponse: {},
    }),
    absMaxHeatSetpointLimit: (args) => m.numeric({
        name: "abs_max_heat_setpoint_limit",
        cluster: "hvacThermostat",
        attribute: "absMaxHeatSetpointLimit",
        description: "Absolute Maximum Heating Setpoint Limit.",
        unit: "°C",
        scale: 100,
        entityCategory: "diagnostic",
        access: "STATE_GET",
        ...args,
    }),
    keypadLockout: (args) => m.enumLookup({
        name: "keypad_lockout",
        cluster: "hvacUserInterfaceCfg",
        attribute: "keypadLockout",
        description: "Enables/disables physical input on the device",
        lookup: {
            unlock: 0,
            lock: 1,
        },
        access: "ALL",
        entityCategory: "config",
        fzConvert: (model, msg, publish, options, meta) => {
            const result = {};
            if ("keypadLockout" in msg.data) {
                result[(0, utils_1.postfixWithEndpointName)("keypad_lockout", msg, model, meta)] = msg.data.keypadLockout > 0 ? "lock" : "unlock";
            }
            return result;
        },
        ...args,
    }),
    danfossMountedModeActive: (args) => m.binary({
        name: "mounted_mode_active",
        cluster: "hvacThermostat",
        attribute: "danfossMountedModeActive",
        description: "Is the unit in mounting mode. This is set to `false` for mounted (already on the radiator) or `true` for not mounted (after factory reset)",
        valueOn: [true, 1],
        valueOff: [false, 0],
        access: "STATE_GET",
        entityCategory: "diagnostic",
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
        ...args,
    }),
    danfossMountedModeControl: (args) => m.binary({
        name: "mounted_mode_control",
        cluster: "hvacThermostat",
        attribute: "danfossMountedModeControl",
        description: "Set the unit mounting mode. `false` Go to Mounted Mode or `true` Go to Mounting Mode",
        valueOn: [true, 1],
        valueOff: [false, 0],
        access: "ALL",
        entityCategory: "config",
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
        ...args,
    }),
    danfossThermostatOrientation: (args) => m.binary({
        name: "thermostat_orientation",
        cluster: "hvacThermostat",
        attribute: "danfossThermostatOrientation",
        description: "Thermostat Orientation. This is important for the PID in how it assesses temperature.",
        valueOn: ["vertical", 1],
        valueOff: ["horizontal", 0],
        access: "ALL",
        entityCategory: "config",
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
        ...args,
    }),
    danfossViewingDirection: (args) => m.binary({
        name: "viewing_direction",
        cluster: "hvacUserInterfaceCfg",
        attribute: "danfossViewingDirection",
        description: "Viewing/display direction",
        valueOn: ["upside-down", true],
        valueOff: ["normal", false],
        access: "ALL",
        entityCategory: "config",
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
        ...args,
    }),
    danfossHeatAvailable: (args) => m.binary({
        name: "heat_available",
        cluster: "hvacThermostat",
        attribute: "danfossHeatAvailable",
        description: "Not clear how this affects operation. However, it would appear that the device does not execute any " +
            "motor functions if this is set to false. This may be a means to conserve battery during periods that the heating " +
            "system is not energized (e.g. during summer).",
        valueOn: [true, 1],
        valueOff: [false, 0],
        access: "ALL",
        entityCategory: "config",
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
        ...args,
    }),
    danfossHeatRequired: (args) => m.binary({
        name: "heat_required",
        cluster: "hvacThermostat",
        attribute: "danfossHeatRequired",
        description: "Whether or not the unit needs warm water.",
        valueOn: [true, 1],
        valueOff: [false, 0],
        access: "STATE_GET",
        entityCategory: "diagnostic",
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
        ...args,
    }),
    setpointChangeSource: (args) => m.enumLookup({
        name: "setpoint_change_source",
        cluster: "hvacThermostat",
        attribute: "setpointChangeSource",
        description: "Values observed",
        access: "STATE",
        lookup: {
            manual: 0,
            schedule: 1,
            externally: 2,
        },
        entityCategory: "diagnostic",
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
        ...args,
    }),
    occupiedHeatingSetpointScheduled: (args) => m.numeric({
        name: "occupied_heating_setpoint_scheduled",
        cluster: "hvacThermostat",
        attribute: "occupiedHeatingSetpoint",
        description: "Scheduled change of the setpoint. Alternative method for changing the setpoint. " +
            "In the opposite to occupied_heating_setpoint it does not trigger an aggressive " +
            "response from the actuator. (more suitable for scheduled changes)",
        access: "ALL",
        unit: "°C",
        valueMin: 5,
        valueMax: 35,
        valueStep: 0.5,
        scale: 100,
        // fzConvert:
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
        ...args,
    }),
    danfossExternalMeasuredRoomSensor: (args) => m.numeric({
        name: "external_measured_room_sensor",
        cluster: "hvacThermostat",
        attribute: "danfossExternalMeasuredRoomSensor",
        description: "The temperature sensor of the TRV is — due to its design — relatively close to the heat source " +
            "(i.e. the hot water in the radiator). Thus there are situations where the `local_temperature` measured by the " +
            "TRV is not accurate enough: If the radiator is covered behind curtains or furniture, if the room is rather big, or " +
            "if the radiator itself is big and the flow temperature is high, then the temperature in the room may easily diverge " +
            "from the `local_temperature` measured by the TRV by 5°C to 8°C. In this case you might choose to use an external " +
            "room sensor and send the measured value of the external room sensor to the `External_measured_room_sensor` property. " +
            "The way the TRV operates on the `External_measured_room_sensor` depends on the setting of the `Radiator_covered` " +
            "property: If `Radiator_covered` is `false` (Auto Offset Mode): You *must* set the `External_measured_room_sensor` " +
            "property *at least* every 3 hours. After 3 hours the TRV disables this function and resets the value of the " +
            "`External_measured_room_sensor` property to -8000 (disabled). You *should* set the `External_measured_room_sensor` " +
            "property *at most* every 30 minutes or every 0.1°C change in measured room temperature. " +
            "If `Radiator_covered` is `true` (Room Sensor Mode): You *must* set the `External_measured_room_sensor` property *at " +
            "least* every 30 minutes. After 35 minutes the TRV disables this function and resets the value of the " +
            "`External_measured_room_sensor` property to -8000 (disabled). You *should* set the `External_measured_room_sensor` " +
            "property *at most* every 5 minutes or every 0.1°C change in measured room temperature. " +
            "The unit of this value is 0.01 `°C` (so e.g. 21°C would be represented as 2100).",
        valueMin: -8000,
        valueMax: 3500,
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
        ...args,
    }),
    danfossRadiatorCovered: (args) => m.binary({
        name: "radiator_covered",
        cluster: "hvacThermostat",
        attribute: "danfossRadiatorCovered",
        description: "Controls whether the TRV should solely rely on an external room sensor or operate in offset mode. " +
            "`false` = Auto Offset Mode (use this e.g. for exposed radiators) or `true` = Room Sensor Mode (use this e.g. for " +
            "covered radiators). Please note that this flag only controls how the TRV operates on the value of " +
            "`External_measured_room_sensor`; only setting this flag without setting the `External_measured_room_sensor` " +
            "has no (noticeable?) effect.",
        valueOn: [true, 1],
        valueOff: [false, 0],
        access: "ALL",
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
        ...args,
    }),
    danfossWindowOpenFeatureEnable: (args) => m.binary({
        name: "window_open_feature",
        cluster: "hvacThermostat",
        attribute: "danfossWindowOpenFeatureEnable",
        description: "Whether or not the window open feature is enabled",
        valueOn: [true, 1],
        valueOff: [false, 0],
        access: "ALL",
        entityCategory: "config",
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
        ...args,
    }),
    danfossWindowOpenInternal: (args) => m.enumLookup({
        name: "window_open_internal",
        cluster: "hvacThermostat",
        attribute: "danfossWindowOpenInternal",
        description: "0=Quarantine, 1=Windows are closed, 2=Hold - Windows are maybe about to open, " +
            "3=Open window detected, 4=In window open state from external but detected closed locally",
        lookup: {
            quarantine: 0,
            closed: 1,
            hold: 2,
            open: 3,
            external_open: 4,
        },
        access: "STATE_GET",
        entityCategory: "diagnostic",
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
        ...args,
    }),
    danfossWindowOpenExternal: (args) => m.binary({
        name: "window_open_external",
        cluster: "hvacThermostat",
        attribute: "danfossWindowOpenExternal",
        description: "Set if the window is open or closed. This setting will trigger a change in the internal window and heating demand.",
        valueOn: [true, 1],
        valueOff: [false, 0],
        access: "ALL",
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
        ...args,
    }),
    danfossDayOfWeek: (args) => m.enumLookup({
        name: "day_of_week",
        cluster: "hvacThermostat",
        attribute: "danfossDayOfWeek",
        lookup: {
            sunday: 0,
            monday: 1,
            tuesday: 2,
            wednesday: 3,
            thursday: 4,
            friday: 5,
            saturday: 6,
            away_or_vacation: 7,
        },
        description: "Exercise day of week: 0=Sun...6=Sat, 7=undefined",
        access: "ALL",
        entityCategory: "config",
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
        ...args,
    }),
    danfossTriggerTime: (args) => m.numeric({
        name: "trigger_time",
        cluster: "hvacThermostat",
        attribute: "danfossTriggerTime",
        description: "Exercise trigger time. Minutes since midnight (65535=undefined). Range 0 to 1439",
        valueMin: 0,
        valueMax: 1439,
        access: "ALL",
        entityCategory: "config",
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
        ...args,
    }),
    danfossTriggerTime2: () => {
        return {
            isModernExtend: true,
            exposes: [
                e
                    .text("trigger_time", ea.ALL)
                    .withDescription("Exercise trigger time. Format: 'HH:MM' (e.g., '14:30'). Send 'undefined' to disable. Note: during DST, the valve may exercise earlier than configured due to a firmware limitation (the TRV uses standard time instead of wall-clock time)")
                    .withCategory("config"),
            ],
            fromZigbee: [
                {
                    cluster: "hvacThermostat",
                    type: ["attributeReport", "readResponse"],
                    convert: (model, msg, publish, options, meta) => {
                        if (msg.data.danfossTriggerTime !== undefined) {
                            const val = msg.data.danfossTriggerTime;
                            if (val === 65535) {
                                return { trigger_time: "undefined" };
                            }
                            const hours = Math.floor(val / 60)
                                .toString()
                                .padStart(2, "0");
                            const mins = (val % 60).toString().padStart(2, "0");
                            return { trigger_time: `${hours}:${mins}` };
                        }
                    },
                },
            ],
            toZigbee: [
                {
                    key: ["trigger_time"],
                    convertSet: async (entity, key, value, meta) => {
                        let val = 65535; // Default to undefined (65535)
                        if (typeof value === "string" && value.toLowerCase() !== "undefined") {
                            const [hours, mins] = value.split(":").map(Number);
                            if (!Number.isNaN(hours) && !Number.isNaN(mins)) {
                                val = hours * 60 + mins;
                            }
                            else {
                                throw new Error(`Invalid time format for trigger_time: '${value}'. Please use 'HH:MM'.`);
                            }
                        }
                        await entity.write("hvacThermostat", { danfossTriggerTime: val }, { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S });
                        return { state: { trigger_time: value } };
                    },
                    convertGet: async (entity, key, meta) => {
                        await entity.read("hvacThermostat", ["danfossTriggerTime"], {
                            manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                        });
                    },
                },
            ],
        };
    },
    danfossAlgorithmScaleFactor: (args) => m.numeric({
        name: "algorithm_scale_factor",
        cluster: "hvacThermostat",
        attribute: "danfossAlgorithmScaleFactor",
        description: 'Scale factor of setpoint filter timeconstant ("aggressiveness" of control algorithm) 1= Quick ... 5=Moderate ... 10=Slow',
        valueMin: 1,
        valueMax: 10,
        access: "ALL",
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
        ...args,
    }),
    danfossLoadBalancingEnable: (args) => m.binary({
        name: "load_balancing_enable",
        cluster: "hvacThermostat",
        attribute: "danfossLoadBalancingEnable",
        description: "Whether or not the thermostat acts as standalone thermostat or shares load with other thermostats in the room. The gateway must update load_room_mean if enabled.",
        valueOn: [true, 1],
        valueOff: [false, 0],
        access: "ALL",
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
        ...args,
    }),
    danfossLoadRoomMean: (args) => m.numeric({
        name: "load_room_mean",
        cluster: "hvacThermostat",
        attribute: "danfossLoadRoomMean",
        description: "Mean radiator load for room calculated by gateway for load balancing purposes (-8000=undefined)",
        valueMin: -8000,
        valueMax: 3600,
        access: "ALL",
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
        ...args,
    }),
    danfossLoadEstimate: (args) => m.numeric({
        name: "load_estimate",
        cluster: "hvacThermostat",
        attribute: "danfossLoadEstimate",
        description: "Load estimate on this radiator",
        valueMin: -8000,
        valueMax: 3600,
        access: "STATE_GET",
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
        ...args,
    }),
    danfossPreheatStatus: (args) => m.binary({
        name: "preheat_status",
        cluster: "hvacThermostat",
        attribute: "danfossPreheatStatus",
        description: "Specific for pre-heat running in Zigbee Weekly Schedule mode",
        valueOn: [true, 1],
        valueOff: [false, 0],
        access: "STATE_GET",
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
        ...args,
    }),
    danfossPreheatTime: (args) => m.numeric({
        name: "preheat_time",
        cluster: "hvacThermostat",
        attribute: "danfossPreheatTime",
        description: "Timestamp of the scheduled setpoint currently being preheated to (read-only)",
        access: "STATE_GET",
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
        ...args,
    }),
    danfossAdaptionRunStatus: (args) => m.enumLookup({
        name: "adaptation_run_status",
        cluster: "hvacThermostat",
        attribute: "danfossAdaptionRunStatus",
        description: "Status of adaptation run: None (before first run), In Progress, Valve Characteristic Found, Valve Characteristic Lost",
        lookup: {
            none: 0,
            in_progress: 1,
            found: 2,
            lost: 3,
            lost_in_progress: 4,
        },
        access: "STATE_GET",
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
        ...args,
    }),
    danfossAdaptionRunSettings: (args) => m.binary({
        name: "adaptation_run_settings",
        cluster: "hvacThermostat",
        attribute: "danfossAdaptionRunSettings",
        description: "Automatic adaptation run enabled (the one during the night)",
        valueOn: [true, 1],
        valueOff: [false, 0],
        access: "ALL",
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
        ...args,
    }),
    danfossAdaptionRunControl: (args) => m.enumLookup({
        name: "adaptation_run_control",
        cluster: "hvacThermostat",
        attribute: "danfossAdaptionRunControl",
        description: "Adaptation run control: Initiate Adaptation Run or Cancel Adaptation Run",
        lookup: {
            idle: 0,
            initiate_adaptation: 1,
            cancel_adaptation: 2,
        },
        access: "ALL",
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
        ...args,
    }),
    danfossRegulationSetpointOffset: (args) => m.numeric({
        name: "regulation_setpoint_offset",
        cluster: "hvacThermostat",
        attribute: "danfossRegulationSetpointOffset",
        description: "Regulation SetPoint Offset in range -2.5°C to 2.5°C in steps of 0.1°C.",
        valueMin: -2.5,
        valueMax: 2.5,
        valueStep: 0.1,
        scale: 10,
        unit: "°C",
        access: "ALL",
        entityCategory: "config",
        zigbeeCommandOptions: { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S },
        ...args,
    }),
    danfossThermostat: (options) => {
        const extend = m.thermostat(options);
        const danfossSetpointConverter = {
            key: ["occupied_heating_setpoint", "occupied_heating_setpoint_scheduled"],
            convertSet: async (entity, key, value, meta) => {
                utils.assertNumber(value, key);
                const isScheduled = key === "occupied_heating_setpoint_scheduled";
                const payload = {
                    setpointType: isScheduled ? 0 : 1, // 0 for scheduled, 1 for aggressive
                    setpoint: Math.round(value * 2) * 50,
                };
                // Send the command
                await entity.command("hvacThermostat", "danfossSetpointCommand", payload, { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S });
                if (!isScheduled) {
                    await entity.command("hvacThermostat", "danfossSetpointCommand", payload, { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S });
                }
            },
            convertGet: async (entity, key, meta) => {
                await entity.read("hvacThermostat", ["occupiedHeatingSetpoint"]);
            },
        };
        extend.toZigbee.unshift(danfossSetpointConverter);
        const climateExpose = extend.exposes.find((exp) => typeof exp !== "function" && "type" in exp && exp.type === "climate");
        if (climateExpose) {
            climateExpose.withRunningState(["idle", "heat"]);
            const runningStateFeature = climateExpose.features.find((f) => typeof f !== "function" && "name" in f && f.name === "running_state");
            if (runningStateFeature) {
                runningStateFeature.withDescription("Running state based on danfossOutputStatus and danfossHeatRequired");
            }
        }
        extend.exposes.push(e
            .numeric("occupied_heating_setpoint_scheduled", ea.ALL)
            .withValueMin(5)
            .withValueMax(35)
            .withValueStep(0.5)
            .withUnit("°C")
            .withDescription("Scheduled change of the setpoint. Alternative method for changing the setpoint. In contrast to occupied heating setpoint it does not trigger an aggressive response from the actuator. (more suitable for scheduled changes)"));
        extend.fromZigbee.push({
            cluster: "hvacThermostat",
            type: ["attributeReport", "readResponse"],
            convert: (model, msg, publish, options, meta) => {
                const result = {};
                if ("danfossHeatRequired" in msg.data || "danfossOutputStatus" in msg.data) {
                    const isHeating = (msg.data.danfossOutputStatus ?? msg.data.danfossHeatRequired) === 1;
                    result.running_state = isHeating ? "heat" : "idle";
                }
                if ("occupiedHeatingSetpoint" in msg.data) {
                    const value = (0, utils_1.precisionRound)(msg.data.occupiedHeatingSetpoint, 2) / 100;
                    result[(0, utils_1.postfixWithEndpointName)("occupied_heating_setpoint", msg, model, meta)] = value;
                    result[(0, utils_1.postfixWithEndpointName)("occupied_heating_setpoint_scheduled", msg, model, meta)] = value;
                }
                return result;
            },
        });
        extend.toZigbee.push({
            key: ["running_state"],
            convertGet: async (entity, key, meta) => {
                await entity.read("hvacThermostat", ["danfossHeatRequired"], {
                    manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
                });
            },
        });
        extend.configure.push(m.setupConfigureForReading("hvacThermostat", ["systemMode"]), m.setupConfigureForReading("hvacUserInterfaceCfg", ["keypadLockout"]), async (device, coordinatorEndpoint) => {
            await setTime(device);
        });
        return extend;
    },
    danfossTimeSyncOnAnnounce: () => ({
        isModernExtend: true,
        onEvent: [
            async (event) => {
                if (event.type === "deviceAnnounce") {
                    await setTime(event.data.device, "queue");
                }
            },
        ],
    }),
};
const tzLocal = {
    devi_occupied_heating_setpoint: {
        key: ["occupied_heating_setpoint"],
        convertSet: async (entity, key, value, meta) => {
            utils.assertNumber(value, key);
            // Work around the thermostat display clamp when crossing below 15C.
            if (value < 15) {
                await entity.write("hvacThermostat", { occupiedHeatingSetpoint: 1500 });
                await utils.sleep(3000);
            }
            await entity.write("hvacThermostat", { occupiedHeatingSetpoint: Math.round(value * 100) });
            return { state: { occupied_heating_setpoint: value } };
        },
        convertGet: async (entity, key, meta) => {
            await entity.read("hvacThermostat", ["occupiedHeatingSetpoint"]);
        },
    },
    danfoss_output_status: {
        key: ["output_status"],
        convertGet: async (entity, key, meta) => {
            await entity.read("hvacThermostat", ["danfossOutputStatus"], {
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
            });
        },
    },
    danfoss_room_status_code: {
        key: ["room_status_code"],
        convertGet: async (entity, key, meta) => {
            await entity.read("hvacThermostat", ["danfossRoomStatusCode"], {
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
            });
        },
    },
    danfoss_floor_sensor_mode: {
        key: ["room_floor_sensor_mode"],
        convertGet: async (entity, key, meta) => {
            await entity.read("hvacThermostat", ["danfossRoomFloorSensorMode"], {
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
            });
        },
    },
    danfoss_floor_min_setpoint: {
        key: ["floor_min_setpoint"],
        convertSet: async (entity, key, value, meta) => {
            utils.assertNumber(value, key);
            const danfossFloorMinSetpoint = Number((Math.round(Number((value * 2).toFixed(1))) / 2).toFixed(1)) * 100;
            await entity.write("hvacThermostat", { danfossFloorMinSetpoint }, { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S });
            return { state: { floor_min_setpoint: value } };
        },
        convertGet: async (entity, key, meta) => {
            await entity.read("hvacThermostat", ["danfossFloorMinSetpoint"], {
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
            });
        },
    },
    danfoss_floor_max_setpoint: {
        key: ["floor_max_setpoint"],
        convertSet: async (entity, key, value, meta) => {
            utils.assertNumber(value, key);
            const danfossFloorMaxSetpoint = Number((Math.round(Number((value * 2).toFixed(1))) / 2).toFixed(1)) * 100;
            await entity.write("hvacThermostat", { danfossFloorMaxSetpoint }, { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S });
            return { state: { floor_max_setpoint: value } };
        },
        convertGet: async (entity, key, meta) => {
            await entity.read("hvacThermostat", ["danfossFloorMaxSetpoint"], {
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
            });
        },
    },
    danfoss_schedule_type_used: {
        key: ["schedule_type_used"],
        convertGet: async (entity, key, meta) => {
            await entity.read("hvacThermostat", ["danfossScheduleTypeUsed"], {
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
            });
        },
    },
    danfoss_icon2_pre_heat: {
        key: ["icon2_pre_heat"],
        convertGet: async (entity, key, meta) => {
            await entity.read("hvacThermostat", ["danfossIcon2PreHeat"], {
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
            });
        },
    },
    danfoss_icon2_pre_heat_status: {
        key: ["icon2_pre_heat_status"],
        convertGet: async (entity, key, meta) => {
            await entity.read("hvacThermostat", ["danfossIcon2PreHeatStatus"], {
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
            });
        },
    },
    danfoss_preheat_command: {
        key: ["preheat_command"],
        convertSet: async (entity, key, value, meta) => {
            utils.assertObject(value);
            const payload = {
                type: 0x00, // Force preheat
                timestamp: value.timestamp,
            };
            await entity.command("hvacThermostat", "danfossPreHeatCommand", payload, { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S });
        },
    },
    danfoss_system_status_code: {
        key: ["system_status_code"],
        convertGet: async (entity, key, meta) => {
            await entity.read("haDiagnostic", ["danfossSystemStatusCode"], {
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
            });
        },
    },
    danfoss_heat_supply_request: {
        key: ["heat_supply_request"],
        convertGet: async (entity, key, meta) => {
            await entity.read("haDiagnostic", ["danfossHeatSupplyRequest"], {
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
            });
        },
    },
    danfoss_system_status_water: {
        key: ["system_status_water"],
        convertGet: async (entity, key, meta) => {
            await entity.read("haDiagnostic", ["danfossSystemStatusWater"], {
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
            });
        },
    },
    danfoss_multimaster_role: {
        key: ["multimaster_role"],
        convertGet: async (entity, key, meta) => {
            await entity.read("haDiagnostic", ["danfossMultimasterRole"], {
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
            });
        },
    },
    danfoss_icon_application: {
        key: ["icon_application"],
        convertGet: async (entity, key, meta) => {
            await entity.read("haDiagnostic", ["danfossIconApplication"], {
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
            });
        },
    },
    danfoss_icon_forced_heating_cooling: {
        key: ["icon_forced_heating_cooling"],
        convertGet: async (entity, key, meta) => {
            await entity.read("haDiagnostic", ["danfossIconForcedHeatingCooling"], {
                manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S,
            });
        },
    },
};
const fzLocal = {
    devi_thermostat: {
        cluster: "hvacThermostat",
        type: ["attributeReport", "readResponse"],
        convert: (model, msg, publish, options, meta) => {
            const result = fz.thermostat.convert(model, msg, publish, options, meta);
            if (result.local_temperature !== undefined) {
                result.floor_temperature = result.local_temperature;
            }
            const localTemperature = result.local_temperature !== undefined ? result.local_temperature : meta.state.local_temperature;
            const heatingSetpoint = result.occupied_heating_setpoint !== undefined
                ? result.occupied_heating_setpoint
                : meta.state.occupied_heating_setpoint;
            if (localTemperature !== undefined && heatingSetpoint !== undefined) {
                result.running_state = localTemperature < heatingSetpoint ? "heat" : "idle";
            }
            return result;
        },
    },
    devi_room_temperature: {
        cluster: "msTemperatureMeasurement",
        type: ["attributeReport", "readResponse"],
        convert: (model, msg, publish, options, meta) => {
            if (msg.data.measuredValue !== undefined) {
                const value = msg.data.measuredValue;
                return { room_temperature: value !== null && value !== -32768 ? (0, utils_1.precisionRound)(value, 2) / 100 : null };
            }
        },
    },
    danfoss_thermostat: {
        cluster: "hvacThermostat",
        type: ["attributeReport", "readResponse"],
        convert: (model, msg, publish, options, meta) => {
            const result = {};
            // Danfoss Icon Converters
            if (msg.data.danfossRoomStatusCode !== undefined) {
                result[(0, utils_1.postfixWithEndpointName)("room_status_code", msg, model, meta)] =
                    constants.danfossRoomStatusCode[msg.data.danfossRoomStatusCode] !== undefined
                        ? constants.danfossRoomStatusCode[msg.data.danfossRoomStatusCode]
                        : msg.data.danfossRoomStatusCode;
            }
            if (msg.data.danfossOutputStatus !== undefined) {
                if (msg.data.danfossOutputStatus === 1) {
                    result[(0, utils_1.postfixWithEndpointName)("output_status", msg, model, meta)] = "active";
                    result[(0, utils_1.postfixWithEndpointName)("running_state", msg, model, meta)] = "heat";
                }
                else {
                    result[(0, utils_1.postfixWithEndpointName)("output_status", msg, model, meta)] = "inactive";
                    result[(0, utils_1.postfixWithEndpointName)("running_state", msg, model, meta)] = "idle";
                }
            }
            return result;
        },
    },
    danfoss_hvac_ui: {
        cluster: "hvacUserInterfaceCfg",
        type: ["attributeReport", "readResponse"],
        convert: (model, msg, publish, options, meta) => {
            const result = {};
            if (msg.data.danfossViewingDirection !== undefined) {
                result[(0, utils_1.postfixWithEndpointName)("viewing_direction", msg, model, meta)] = msg.data.danfossViewingDirection === 1;
            }
            return result;
        },
    },
    danfoss_icon_floor_sensor: {
        cluster: "hvacThermostat",
        type: ["attributeReport", "readResponse"],
        convert: (model, msg, publish, options, meta) => {
            const result = {};
            if (msg.data.danfossRoomFloorSensorMode !== undefined) {
                result[(0, utils_1.postfixWithEndpointName)("room_floor_sensor_mode", msg, model, meta)] =
                    constants.danfossRoomFloorSensorMode[msg.data.danfossRoomFloorSensorMode] !== undefined
                        ? constants.danfossRoomFloorSensorMode[msg.data.danfossRoomFloorSensorMode]
                        : msg.data.danfossRoomFloorSensorMode;
            }
            if (msg.data.danfossFloorMinSetpoint !== undefined) {
                const value = (0, utils_1.precisionRound)(msg.data.danfossFloorMinSetpoint, 2) / 100;
                if (value >= -273.15) {
                    result[(0, utils_1.postfixWithEndpointName)("floor_min_setpoint", msg, model, meta)] = value;
                }
            }
            if (msg.data.danfossFloorMaxSetpoint !== undefined) {
                const value = (0, utils_1.precisionRound)(msg.data.danfossFloorMaxSetpoint, 2) / 100;
                if (value >= -273.15) {
                    result[(0, utils_1.postfixWithEndpointName)("floor_max_setpoint", msg, model, meta)] = value;
                }
            }
            if (msg.data.danfossScheduleTypeUsed !== undefined) {
                result[(0, utils_1.postfixWithEndpointName)("schedule_type_used", msg, model, meta)] =
                    constants.danfossScheduleTypeUsed[msg.data.danfossScheduleTypeUsed] !== undefined
                        ? constants.danfossScheduleTypeUsed[msg.data.danfossScheduleTypeUsed]
                        : msg.data.danfossScheduleTypeUsed;
            }
            if (msg.data.danfossIcon2PreHeat !== undefined) {
                result[(0, utils_1.postfixWithEndpointName)("icon2_pre_heat", msg, model, meta)] =
                    constants.danfossIcon2PreHeat[msg.data.danfossIcon2PreHeat] !== undefined
                        ? constants.danfossIcon2PreHeat[msg.data.danfossIcon2PreHeat]
                        : msg.data.danfossIcon2PreHeat;
            }
            if (msg.data.danfossIcon2PreHeatStatus !== undefined) {
                result[(0, utils_1.postfixWithEndpointName)("icon2_pre_heat_status", msg, model, meta)] =
                    constants.danfossIcon2PreHeatStatus[msg.data.danfossIcon2PreHeatStatus] !== undefined
                        ? constants.danfossIcon2PreHeatStatus[msg.data.danfossIcon2PreHeatStatus]
                        : msg.data.danfossIcon2PreHeatStatus;
            }
            return result;
        },
    },
    danfoss_icon_battery: {
        cluster: "genPowerCfg",
        type: ["attributeReport", "readResponse"],
        convert: (model, msg, publish, options, meta) => {
            const result = {};
            if (msg.data.batteryPercentageRemaining !== undefined) {
                // Some devices do not comply to the ZCL and report a
                // batteryPercentageRemaining of 100 when the battery is full (should be 200).
                const dontDividePercentage = model.meta?.battery?.dontDividePercentage;
                let percentage = msg.data.batteryPercentageRemaining;
                percentage = dontDividePercentage ? percentage : percentage / 2;
                result[(0, utils_1.postfixWithEndpointName)("battery", msg, model, meta)] = (0, utils_1.precisionRound)(percentage, 2);
            }
            return result;
        },
    },
    danfoss_icon_regulator: {
        cluster: "haDiagnostic",
        type: ["attributeReport", "readResponse"],
        convert: (model, msg, publish, options, meta) => {
            const result = {};
            if (msg.data.danfossSystemStatusCode !== undefined) {
                result[(0, utils_1.postfixWithEndpointName)("system_status_code", msg, model, meta)] =
                    constants.danfossSystemStatusCode[msg.data.danfossSystemStatusCode] !== undefined
                        ? constants.danfossSystemStatusCode[msg.data.danfossSystemStatusCode]
                        : msg.data.danfossSystemStatusCode;
            }
            if (msg.data.danfossHeatSupplyRequest !== undefined) {
                result[(0, utils_1.postfixWithEndpointName)("heat_supply_request", msg, model, meta)] =
                    constants.danfossHeatsupplyRequest[msg.data.danfossHeatSupplyRequest] !== undefined
                        ? constants.danfossHeatsupplyRequest[msg.data.danfossHeatSupplyRequest]
                        : msg.data.danfossHeatSupplyRequest;
            }
            if (msg.data.danfossSystemStatusWater !== undefined) {
                result[(0, utils_1.postfixWithEndpointName)("system_status_water", msg, model, meta)] =
                    constants.danfossSystemStatusWater[msg.data.danfossSystemStatusWater] !== undefined
                        ? constants.danfossSystemStatusWater[msg.data.danfossSystemStatusWater]
                        : msg.data.danfossSystemStatusWater;
            }
            if (msg.data.danfossMultimasterRole !== undefined) {
                result[(0, utils_1.postfixWithEndpointName)("multimaster_role", msg, model, meta)] =
                    constants.danfossMultimasterRole[msg.data.danfossMultimasterRole] !== undefined
                        ? constants.danfossMultimasterRole[msg.data.danfossMultimasterRole]
                        : msg.data.danfossMultimasterRole;
            }
            if (msg.data.danfossIconApplication !== undefined) {
                result[(0, utils_1.postfixWithEndpointName)("icon_application", msg, model, meta)] =
                    constants.danfossIconApplication[msg.data.danfossIconApplication] !== undefined
                        ? constants.danfossIconApplication[msg.data.danfossIconApplication]
                        : msg.data.danfossIconApplication;
            }
            if (msg.data.danfossIconForcedHeatingCooling !== undefined) {
                result[(0, utils_1.postfixWithEndpointName)("icon_forced_heating_cooling", msg, model, meta)] =
                    constants.danfossIconForcedHeatingCooling[msg.data.danfossIconForcedHeatingCooling] !== undefined
                        ? constants.danfossIconForcedHeatingCooling[msg.data.danfossIconForcedHeatingCooling]
                        : msg.data.danfossIconForcedHeatingCooling;
            }
            return result;
        },
    },
    danfoss_icon_hvac_user_interface: {
        cluster: "hvacUserInterfaceCfg",
        type: ["attributeReport", "readResponse"],
        convert: (model, msg, publish, options, meta) => {
            const result = {};
            if (msg.data.keypadLockout !== undefined) {
                result[(0, utils_1.postfixWithEndpointName)("keypad_lockout", msg, model, meta)] =
                    constants.keypadLockoutMode[msg.data.keypadLockout] !== undefined
                        ? constants.keypadLockoutMode[msg.data.keypadLockout]
                        : msg.data.keypadLockout;
            }
            if (msg.data.tempDisplayMode !== undefined) {
                result[(0, utils_1.postfixWithEndpointName)("temperature_display_mode", msg, model, meta)] =
                    constants.temperatureDisplayMode[msg.data.tempDisplayMode] !== undefined
                        ? constants.temperatureDisplayMode[msg.data.tempDisplayMode]
                        : msg.data.tempDisplayMode;
            }
            return result;
        },
    },
    danfoss_system_status_code: {
        cluster: "haDiagnostic",
        type: ["attributeReport", "readResponse"],
        convert: (model, msg, publish, options, meta) => {
            const result = {};
            if (msg.data.danfossSystemStatusCode !== undefined) {
                const code = msg.data.danfossSystemStatusCode;
                const errors = [];
                for (const [bit, name] of Object.entries(constants.danfossAllySystemStatusCode)) {
                    if (code & (1 << Number(bit))) {
                        errors.push(name);
                    }
                }
                result.system_status_code = errors.length > 0 ? errors.join(",") : "ok";
            }
            return result;
        },
    },
};
exports.definitions = [
    {
        zigbeeModel: ["devi_f"],
        model: "140F1170",
        vendor: "DEVI",
        description: "DEVIreg InControl floor heating thermostat",
        ota: true,
        meta: { thermostat: { dontMapPIHeatingDemand: true } },
        fromZigbee: [fzLocal.devi_thermostat, fz.hvac_user_interface, fzLocal.devi_room_temperature],
        toZigbee: [
            tzLocal.devi_occupied_heating_setpoint,
            tz.thermostat_local_temperature,
            tz.thermostat_local_temperature_calibration,
            tz.thermostat_system_mode,
            tz.thermostat_min_heat_setpoint_limit,
            tz.thermostat_max_heat_setpoint_limit,
            tz.thermostat_keypad_lockout,
        ],
        exposes: [
            e
                .climate()
                .withLocalTemperature()
                .withSetpoint("occupied_heating_setpoint", 5, 30, 0.5)
                .withSystemMode(["heat"])
                .withRunningState(["idle", "heat"], ea.STATE)
                .withLocalTemperatureCalibration(-12.8, 12.7, 0.1),
            e.numeric("floor_temperature", ea.STATE).withUnit("°C").withDescription("Floor temperature"),
            e.numeric("room_temperature", ea.STATE).withUnit("°C").withDescription("Room temperature from optional external sensor"),
            e.keypad_lockout(),
        ],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            await reporting.bind(endpoint, coordinatorEndpoint, ["hvacThermostat", "hvacUserInterfaceCfg", "msTemperatureMeasurement"]);
            await reporting.thermostatTemperature(endpoint);
            await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
            await reporting.thermostatKeypadLockMode(endpoint);
            try {
                await reporting.temperature(endpoint);
            }
            catch {
                // Optional external room sensor may not be connected.
            }
            await endpoint.read("hvacThermostat", [
                "localTemp",
                "occupiedHeatingSetpoint",
                "systemMode",
                "minHeatSetpointLimit",
                "maxHeatSetpointLimit",
            ]);
            await endpoint.read("hvacUserInterfaceCfg", ["keypadLockout"]);
        },
    },
    {
        zigbeeModel: ["eTRV0100", "eTRV0101", "eTRV0103", "TRV001", "TRV003", "eT093WRO", "eT093WRG"],
        model: "014G2461",
        vendor: "Danfoss",
        description: "Ally thermostat",
        whiteLabel: [
            { vendor: "Danfoss", model: "014G2463" },
            { vendor: "Hive", model: "UK7004240", description: "Radiator valve", fingerprint: [{ modelID: "TRV001" }, { modelID: "TRV003" }] },
            { vendor: "Popp", model: "701721", description: "Smart thermostat", fingerprint: [{ modelID: "eT093WRO" }, { modelID: "eT093WRG" }] },
        ],
        ota: true,
        meta: { thermostat: { dontMapPIHeatingDemand: true } },
        extend: [
            danfossExtend.addDanfossHvacThermostatCluster(),
            danfossExtend.addDanfossHvacUserInterfaceCfgCluster(),
            danfossExtend.addDanfossHaDiagnosticCluster(),
            danfossExtend.danfossThermostat({
                setpoints: { values: { occupiedHeatingSetpoint: { min: 5, max: 35, step: 0.5 } } },
                piHeatingDemand: { values: true },
                systemMode: { values: ["heat"] },
                programmingOperationMode: { values: ["setpoint", "schedule", "schedule_with_preheat", "eco"] },
                // weeklySchedule: {values: ["heat"]},   // gives an error in test:
                // test/checks.test.ts > Check definitions > respect snake case naming conventions for exposes and options
                // Error: Definitions not using snake case for expose/option:
                // Danfoss|014G2461|expose.name=transitionTime
                // Danfoss|014G2461|expose.name=heatSetpoint
                setpointsLimit: {
                    maxHeatSetpointLimit: { min: 5, max: 35, step: 0.5 },
                },
            }),
            danfossExtend.absMaxHeatSetpointLimit({
                description: "Absolute Maximum Heating Setpoint Limit for the device. Adjust the 'Max heat setpoint limit' accordingly.",
            }),
            m.battery(),
            danfossExtend.keypadLockout(),
            danfossExtend.danfossMountedModeActive(),
            danfossExtend.danfossMountedModeControl(),
            danfossExtend.danfossThermostatOrientation(),
            danfossExtend.danfossViewingDirection(),
            danfossExtend.danfossHeatAvailable(),
            danfossExtend.danfossHeatRequired(),
            danfossExtend.setpointChangeSource(),
            danfossExtend.danfossExternalMeasuredRoomSensor(),
            danfossExtend.danfossRadiatorCovered(),
            danfossExtend.danfossWindowOpenFeatureEnable(),
            danfossExtend.danfossWindowOpenInternal(),
            danfossExtend.danfossWindowOpenExternal(),
            danfossExtend.danfossDayOfWeek(),
            danfossExtend.danfossTriggerTime2(),
            danfossExtend.danfossAlgorithmScaleFactor(),
            danfossExtend.danfossLoadBalancingEnable(),
            danfossExtend.danfossLoadRoomMean(),
            danfossExtend.danfossLoadEstimate(),
            danfossExtend.danfossPreheatStatus(),
            danfossExtend.danfossPreheatTime(),
            danfossExtend.danfossAdaptionRunStatus(),
            danfossExtend.danfossAdaptionRunSettings(),
            danfossExtend.danfossAdaptionRunControl(),
            danfossExtend.danfossRegulationSetpointOffset(),
            danfossExtend.danfossTimeSyncOnAnnounce(),
            m.poll({
                key: "danfossTime",
                defaultIntervalSeconds: 60 * 60 * 24,
                poll: async (device) => {
                    await setTime(device, "queue");
                },
            }),
        ],
        exposes: [
            e
                .text("system_status_code", ea.STATE_GET)
                .withDescription("Diagnostic error codes (e.g. 'invalid_clock_information,low_battery'). 'ok' when no errors.")
                .withCategory("diagnostic"),
        ],
        fromZigbee: [fz.thermostat_weekly_schedule, fzLocal.danfoss_system_status_code],
        toZigbee: [
            tz.thermostat_weekly_schedule,
            tz.thermostat_clear_weekly_schedule,
            tzLocal.danfoss_system_status_code,
            tzLocal.danfoss_preheat_command,
        ],
        configure: async (device, coordinatorEndpoint) => {
            const endpoint = device.getEndpoint(1);
            const options = { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S };
            try {
                await reporting.bind(endpoint, coordinatorEndpoint, ["haDiagnostic"]);
            }
            catch {
                // Bind may fail if already bound (Danfoss rejects duplicate binds)
            }
            await endpoint.configureReporting("haDiagnostic", [
                {
                    attribute: "danfossSystemStatusCode",
                    minimumReportInterval: 0,
                    maximumReportInterval: constants.repInterval.HOUR,
                    reportableChange: 1,
                },
            ], options);
            await endpoint.read("haDiagnostic", ["danfossSystemStatusCode"], options);
        },
    },
    {
        fingerprint: [
            { modelID: "0x0200", manufacturerName: "Danfoss" }, // Icon Basic Main Controller
            { modelID: "0x8020", manufacturerName: "Danfoss" }, // RT24V Display
            { modelID: "0x8021", manufacturerName: "Danfoss" }, // RT24V Display  Floor sensor
            { modelID: "0x8030", manufacturerName: "Danfoss" }, // RTbattery Display
            { modelID: "0x8031", manufacturerName: "Danfoss" }, // RTbattery Display Infrared
            { modelID: "0x8034", manufacturerName: "Danfoss" }, // RTbattery Dial
            { modelID: "0x8035", manufacturerName: "Danfoss" }, // RTbattery Dial Infrared
        ],
        model: "Icon",
        vendor: "Danfoss",
        description: "Icon Main Controller with Zigbee Module, Room Thermostat",
        extend: [danfossExtend.addDanfossHvacThermostatCluster(), danfossExtend.addDanfossHaDiagnosticCluster()],
        fromZigbee: [
            fzLocal.danfoss_icon_battery,
            fz.thermostat,
            fzLocal.danfoss_thermostat,
            fzLocal.danfoss_hvac_ui,
            fzLocal.danfoss_icon_regulator,
            fzLocal.danfoss_icon_floor_sensor,
            fz.temperature,
        ],
        toZigbee: [
            tz.thermostat_local_temperature,
            tz.thermostat_occupied_heating_setpoint,
            tz.thermostat_min_heat_setpoint_limit,
            tz.thermostat_max_heat_setpoint_limit,
            tz.thermostat_system_mode,
            tzLocal.danfoss_room_status_code,
            tzLocal.danfoss_output_status,
            tzLocal.danfoss_floor_sensor_mode,
            tzLocal.danfoss_floor_min_setpoint,
            tzLocal.danfoss_floor_max_setpoint,
            tz.temperature,
            tzLocal.danfoss_system_status_code,
            tzLocal.danfoss_system_status_water,
            tzLocal.danfoss_multimaster_role,
            tzLocal.danfoss_icon_application,
        ],
        meta: { multiEndpoint: true, thermostat: { dontMapPIHeatingDemand: true } },
        endpoint: (device) => {
            return {
                l1: 1,
                l2: 2,
                l3: 3,
                l4: 4,
                l5: 5,
                l6: 6,
                l7: 7,
                l8: 8,
                l9: 9,
                l10: 10,
                l11: 11,
                l12: 12,
                l13: 13,
                l14: 14,
                l15: 15,
                l16: 232,
            };
        },
        exposes: (device) => {
            // On a real controller only populated rooms register a Zigbee endpoint
            // (getEndpoint(i) is undefined for an unwired room), so expose only those.
            // A dummy device (docs generation) or one not yet interviewed has no usable
            // endpoint list, so expose the full l1..l15 + l16 set instead.
            const roomEndpoints = [];
            let hasMainController = true;
            if ("endpoints" in device && device.endpoints.length > 0) {
                for (let i = 1; i <= 15; i++) {
                    if (device.getEndpoint(i) !== undefined) {
                        roomEndpoints.push(i);
                    }
                }
                hasMainController = device.getEndpoint(232) !== undefined;
            }
            else {
                for (let i = 1; i <= 15; i++) {
                    roomEndpoints.push(i);
                }
            }
            const features = [];
            for (const i of roomEndpoints) {
                const epName = `l${i}`;
                features.push(e.battery().withEndpoint(epName));
                features.push(e
                    .climate()
                    .withSetpoint("occupied_heating_setpoint", 5, 35, 0.5)
                    .withLocalTemperature()
                    .withSystemMode(["heat"])
                    .withRunningState(["idle", "heat"], ea.STATE)
                    .withEndpoint(epName));
                features.push(e
                    .numeric("abs_min_heat_setpoint_limit", ea.STATE)
                    .withUnit("°C")
                    .withEndpoint(epName)
                    .withDescription("Absolute min temperature allowed on the device"));
                features.push(e
                    .numeric("abs_max_heat_setpoint_limit", ea.STATE)
                    .withUnit("°C")
                    .withEndpoint(epName)
                    .withDescription("Absolute max temperature allowed on the device"));
                features.push(e
                    .numeric("min_heat_setpoint_limit", ea.ALL)
                    .withValueMin(4)
                    .withValueMax(35)
                    .withValueStep(0.5)
                    .withUnit("°C")
                    .withEndpoint(epName)
                    .withDescription("Min temperature limit set on the device"));
                features.push(e
                    .numeric("max_heat_setpoint_limit", ea.ALL)
                    .withValueMin(4)
                    .withValueMax(35)
                    .withValueStep(0.5)
                    .withUnit("°C")
                    .withEndpoint(epName)
                    .withDescription("Max temperature limit set on the device"));
                features.push(e.enum("setpoint_change_source", ea.STATE, ["manual", "schedule", "externally"]).withEndpoint(epName));
                features.push(e.enum("output_status", ea.STATE_GET, ["inactive", "active"]).withEndpoint(epName).withDescription("Actuator status"));
                features.push(e
                    .enum("room_status_code", ea.STATE_GET, [
                    "no_error",
                    "missing_rt",
                    "rt_touch_error",
                    "floor_sensor_short_circuit",
                    "floor_sensor_disconnected",
                ])
                    .withEndpoint(epName)
                    .withDescription("Thermostat status"));
                features.push(e
                    .enum("room_floor_sensor_mode", ea.STATE_GET, ["comfort", "floor_only", "dual_mode"])
                    .withEndpoint(epName)
                    .withDescription("Floor sensor mode"));
                features.push(e
                    .numeric("floor_min_setpoint", ea.ALL)
                    .withValueMin(18)
                    .withValueMax(35)
                    .withValueStep(0.5)
                    .withUnit("°C")
                    .withEndpoint(epName)
                    .withDescription("Min floor temperature"));
                features.push(e
                    .numeric("floor_max_setpoint", ea.ALL)
                    .withValueMin(18)
                    .withValueMax(35)
                    .withValueStep(0.5)
                    .withUnit("°C")
                    .withEndpoint(epName)
                    .withDescription("Max floor temperature"));
                features.push(e.numeric("temperature", ea.STATE_GET).withUnit("°C").withEndpoint(epName).withDescription("Floor temperature"));
            }
            if (hasMainController) {
                features.push(e
                    .enum("system_status_code", ea.STATE_GET, [
                    "no_error",
                    "missing_expansion_board",
                    "missing_radio_module",
                    "missing_command_module",
                    "missing_master_rail",
                    "missing_slave_rail_no_1",
                    "missing_slave_rail_no_2",
                    "pt1000_input_short_circuit",
                    "pt1000_input_open_circuit",
                    "error_on_one_or_more_output",
                ])
                    .withEndpoint("l16")
                    .withDescription("Main Controller Status"));
                features.push(e
                    .enum("system_status_water", ea.STATE_GET, ["hot_water_flow_in_pipes", "cool_water_flow_in_pipes"])
                    .withEndpoint("l16")
                    .withDescription("Main Controller Water Status"));
                features.push(e
                    .enum("multimaster_role", ea.STATE_GET, ["invalid_unused", "master", "slave_1", "slave_2"])
                    .withEndpoint("l16")
                    .withDescription("Main Controller Role"));
                features.push(e
                    .enum("icon_application", ea.STATE_GET, Array.from({ length: 21 }, (_, n) => `${n}`))
                    .withEndpoint("l16")
                    .withDescription("Main Controller application"));
            }
            return features;
        },
        configure: async (device, coordinatorEndpoint) => {
            const options = { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S };
            for (let i = 1; i <= 15; i++) {
                const endpoint = device.getEndpoint(i);
                if (typeof endpoint !== "undefined") {
                    await reporting.bind(endpoint, coordinatorEndpoint, ["genPowerCfg", "hvacThermostat"]);
                    await reporting.batteryPercentageRemaining(endpoint);
                    await reporting.thermostatTemperature(endpoint);
                    await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
                    await reporting.temperature(endpoint, { change: 10 });
                    await endpoint.configureReporting("hvacThermostat", [
                        {
                            attribute: "danfossOutputStatus",
                            minimumReportInterval: 0,
                            maximumReportInterval: constants.repInterval.HOUR,
                            reportableChange: 1,
                        },
                    ], options);
                    await endpoint.read("genPowerCfg", ["batteryPercentageRemaining"]);
                    await endpoint.read("hvacThermostat", [
                        "localTemp",
                        "occupiedHeatingSetpoint",
                        "setpointChangeSource",
                        "absMinHeatSetpointLimit",
                        "absMaxHeatSetpointLimit",
                        "minHeatSetpointLimit",
                        "maxHeatSetpointLimit",
                        "systemMode",
                    ]);
                    await endpoint.read("hvacThermostat", [
                        "danfossRoomStatusCode",
                        "danfossOutputStatus",
                        "danfossRoomFloorSensorMode",
                        "danfossFloorMinSetpoint",
                        "danfossFloorMaxSetpoint",
                    ], options);
                }
            }
            // Danfoss Icon Main Controller Specific Endpoint
            const mainController = device.getEndpoint(232);
            await reporting.bind(mainController, coordinatorEndpoint, ["haDiagnostic"]);
            await mainController.read("haDiagnostic", ["danfossSystemStatusCode", "danfossSystemStatusWater", "danfossMultimasterRole"], options);
            // Read separately: older 0x80xx firmware variants may not support this attribute,
            // so an UNSUPPORTED_ATTRIBUTE must not fail the reads above.
            await mainController.read("haDiagnostic", ["danfossIconApplication"], options);
        },
    },
    {
        fingerprint: [
            { modelID: "0x0210", manufacturerName: "Danfoss" }, // Icon2 Basic Main Controller
            { modelID: "0x0211", manufacturerName: "Danfoss" }, // Icon2 Advanced Main Controller
            { modelID: "0x8040", manufacturerName: "Danfoss" }, // Icon2 Room Thermostat
            { modelID: "0x8041", manufacturerName: "Danfoss" }, // Icon2 Featured (Infrared) Room Thermostat
            { modelID: "0x0042", manufacturerName: "Danfoss" }, // Icon2 Sensor
        ],
        model: "Icon2",
        vendor: "Danfoss",
        description: "Icon2 Main Controller, Room Thermostat or Sensor",
        ota: true,
        extend: [danfossExtend.addDanfossHvacThermostatCluster(), danfossExtend.addDanfossHaDiagnosticCluster()],
        fromZigbee: [
            fzLocal.danfoss_icon_battery,
            fz.thermostat,
            fzLocal.danfoss_thermostat,
            fzLocal.danfoss_hvac_ui,
            fzLocal.danfoss_icon_floor_sensor,
            fzLocal.danfoss_icon_hvac_user_interface,
            fz.temperature,
            fz.humidity,
            fzLocal.danfoss_icon_regulator,
        ],
        toZigbee: [
            tz.thermostat_local_temperature,
            tz.thermostat_occupied_heating_setpoint,
            tz.thermostat_min_heat_setpoint_limit,
            tz.thermostat_max_heat_setpoint_limit,
            tz.thermostat_system_mode,
            tzLocal.danfoss_room_status_code,
            tzLocal.danfoss_output_status,
            tzLocal.danfoss_floor_sensor_mode,
            tzLocal.danfoss_floor_min_setpoint,
            tzLocal.danfoss_floor_max_setpoint,
            tzLocal.danfoss_schedule_type_used,
            tzLocal.danfoss_icon2_pre_heat,
            tzLocal.danfoss_icon2_pre_heat_status,
            tz.thermostat_keypad_lockout,
            tz.temperature,
            tz.humidity,
            tzLocal.danfoss_system_status_code,
            tzLocal.danfoss_heat_supply_request,
            tzLocal.danfoss_system_status_water,
            tzLocal.danfoss_multimaster_role,
            tzLocal.danfoss_icon_application,
            tzLocal.danfoss_icon_forced_heating_cooling,
        ],
        meta: { multiEndpoint: true, thermostat: { dontMapPIHeatingDemand: true } },
        exposes: [].concat(((endpointsCount) => {
            const features = [];
            for (let i = 1; i <= endpointsCount; i++) {
                if (i < 16) {
                    const epName = `${i}`;
                    features.push(e.battery().withEndpoint(epName));
                    features.push(e
                        .climate()
                        .withSetpoint("occupied_heating_setpoint", 5, 35, 0.5)
                        .withLocalTemperature()
                        .withSystemMode(["heat"])
                        .withRunningState(["idle", "heat"], ea.STATE)
                        .withEndpoint(epName));
                    features.push(e
                        .numeric("min_heat_setpoint_limit", ea.ALL)
                        .withValueMin(4)
                        .withValueMax(35)
                        .withValueStep(0.5)
                        .withUnit("°C")
                        .withEndpoint(epName)
                        .withDescription("Min temperature limit set on the device"));
                    features.push(e
                        .numeric("max_heat_setpoint_limit", ea.ALL)
                        .withValueMin(4)
                        .withValueMax(35)
                        .withValueStep(0.5)
                        .withUnit("°C")
                        .withEndpoint(epName)
                        .withDescription("Max temperature limit set on the device"));
                    features.push(e.enum("setpoint_change_source", ea.STATE, ["manual", "schedule", "externally"]).withEndpoint(epName));
                    features.push(e.enum("output_status", ea.STATE_GET, ["inactive", "active"]).withEndpoint(epName).withDescription("Actuator status"));
                    features.push(e
                        .enum("room_status_code", ea.STATE_GET, [
                        "no_error",
                        "missing_rt",
                        "rt_touch_error",
                        "floor_sensor_short_circuit",
                        "floor_sensor_disconnected",
                    ])
                        .withEndpoint(epName)
                        .withDescription("Thermostat status"));
                    features.push(e
                        .enum("room_floor_sensor_mode", ea.STATE_GET, ["comfort", "floor_only", "dual_mode"])
                        .withEndpoint(epName)
                        .withDescription("Floor sensor mode"));
                    features.push(e
                        .numeric("floor_min_setpoint", ea.ALL)
                        .withValueMin(18)
                        .withValueMax(35)
                        .withValueStep(0.5)
                        .withUnit("°C")
                        .withEndpoint(epName)
                        .withDescription("Min floor temperature"));
                    features.push(e
                        .numeric("floor_max_setpoint", ea.ALL)
                        .withValueMin(18)
                        .withValueMax(35)
                        .withValueStep(0.5)
                        .withUnit("°C")
                        .withEndpoint(epName)
                        .withDescription("Max floor temperature"));
                    features.push(e
                        .enum("schedule_type_used", ea.STATE_GET, ["regular_schedule_selected", "vacation_schedule_selected"])
                        .withEndpoint(epName)
                        .withDescription("Danfoss schedule mode"));
                    features.push(e
                        .enum("icon2_pre_heat", ea.STATE_GET, ["disable", "enable"])
                        .withEndpoint(epName)
                        .withDescription("Danfoss pre heat control"));
                    features.push(e
                        .enum("icon2_pre_heat_status", ea.STATE_GET, ["disable", "enable"])
                        .withEndpoint(epName)
                        .withDescription("Danfoss pre heat status"));
                    features.push(e.numeric("temperature", ea.STATE_GET).withUnit("°C").withEndpoint(epName).withDescription("Floor temperature"));
                    features.push(e.numeric("humidity", ea.STATE_GET).withUnit("%").withEndpoint(epName).withDescription("Humidity"));
                }
                else {
                    features.push(e
                        .enum("system_status_code", ea.STATE_GET, [
                        "no_error",
                        "missing_expansion_board",
                        "missing_radio_module",
                        "missing_command_module",
                        "missing_master_rail",
                        "missing_slave_rail_no_1",
                        "missing_slave_rail_no_2",
                        "pt1000_input_short_circuit",
                        "pt1000_input_open_circuit",
                        "error_on_one_or_more_output",
                    ])
                        .withEndpoint("232")
                        .withDescription("Main Controller Status"));
                    features.push(e
                        .enum("heat_supply_request", ea.STATE_GET, ["none", "heat_supply_request"])
                        .withEndpoint("232")
                        .withDescription("Danfoss heat supply request"));
                    features.push(e
                        .enum("system_status_water", ea.STATE_GET, ["hot_water_flow_in_pipes", "cool_water_flow_in_pipes"])
                        .withEndpoint("232")
                        .withDescription("Main Controller Water Status"));
                    features.push(e
                        .enum("multimaster_role", ea.STATE_GET, ["invalid_unused", "master", "slave_1", "slave_2"])
                        .withEndpoint("232")
                        .withDescription("Main Controller Role"));
                    features.push(e
                        .enum("icon_application", ea.STATE_GET, Array.from({ length: 21 }, (_, n) => `${n}`))
                        .withEndpoint("232")
                        .withDescription("Main Controller application"));
                    features.push(e
                        .enum("icon_forced_heating_cooling", ea.STATE_GET, ["force_heating", "force_cooling", "none"])
                        .withEndpoint("232")
                        .withDescription("Main Controller application"));
                }
            }
            return features;
        })(16)),
        configure: async (device, coordinatorEndpoint) => {
            const options = { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.DANFOSS_A_S };
            // Danfoss Icon2 Main Controller Specific Endpoint
            const mainController = device.getEndpoint(232);
            for (let i = 1; i <= 15; i++) {
                const endpoint = device.getEndpoint(i);
                if (typeof endpoint === "undefined") {
                    continue;
                }
                await reporting.bind(endpoint, coordinatorEndpoint, [
                    "genPowerCfg",
                    "hvacThermostat",
                    "hvacUserInterfaceCfg",
                    "msTemperatureMeasurement",
                    "msRelativeHumidity",
                ]);
                await reporting.batteryPercentageRemaining(endpoint);
                await reporting.thermostatTemperature(endpoint);
                await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
                await reporting.temperature(endpoint, { change: 10 });
                await reporting.humidity(endpoint);
                await endpoint.read("genPowerCfg", ["batteryPercentageRemaining"]);
                await endpoint.read("hvacThermostat", [
                    "localTemp",
                    "occupiedHeatingSetpoint",
                    "minHeatSetpointLimit",
                    "maxHeatSetpointLimit",
                    "systemMode",
                ]);
                await endpoint.read("hvacThermostat", ["danfossRoomFloorSensorMode", "danfossFloorMinSetpoint", "danfossFloorMaxSetpoint"], options);
                await endpoint.read("hvacUserInterfaceCfg", ["keypadLockout"]);
                await endpoint.read("msTemperatureMeasurement", ["measuredValue"]);
                await endpoint.read("msRelativeHumidity", ["measuredValue"]);
                // Different attributes depending on if it's Main Сontroller or a single thermostat
                if (typeof mainController === "undefined") {
                    await endpoint.read("genBasic", ["modelId", "powerSource"]);
                }
                else {
                    await endpoint.configureReporting("hvacThermostat", [
                        {
                            attribute: "danfossOutputStatus",
                            minimumReportInterval: 0,
                            maximumReportInterval: constants.repInterval.HOUR,
                            reportableChange: 1,
                        },
                    ], options);
                    await endpoint.read("hvacThermostat", ["setpointChangeSource"]);
                    await endpoint.read("hvacThermostat", ["danfossRoomStatusCode", "danfossOutputStatus"], options);
                }
            }
            // Danfoss Icon2 Main Controller Specific
            if (typeof mainController !== "undefined") {
                await reporting.bind(mainController, coordinatorEndpoint, ["genBasic", "haDiagnostic"]);
                await mainController.read("genBasic", ["modelId", "powerSource", "appVersion", "stackVersion", "hwVersion", "dateCode"]);
                await mainController.read("haDiagnostic", [
                    "danfossSystemStatusCode",
                    "danfossHeatSupplyRequest",
                    "danfossSystemStatusWater",
                    "danfossMultimasterRole",
                    "danfossIconApplication",
                    "danfossIconForcedHeatingCooling",
                ], options);
            }
        },
    },
];
//# sourceMappingURL=danfoss.js.map