zigbee-herdsman-converters 25.35.0 → 25.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/devices/bosch.d.ts.map +1 -1
  3. package/dist/devices/bosch.js +513 -63
  4. package/dist/devices/bosch.js.map +1 -1
  5. package/dist/devices/index.d.ts.map +1 -1
  6. package/dist/devices/index.js +2 -0
  7. package/dist/devices/index.js.map +1 -1
  8. package/dist/devices/lumi.js +2 -2
  9. package/dist/devices/lumi.js.map +1 -1
  10. package/dist/devices/schneider_electric.d.ts.map +1 -1
  11. package/dist/devices/schneider_electric.js +6 -2
  12. package/dist/devices/schneider_electric.js.map +1 -1
  13. package/dist/devices/slc.d.ts +3 -0
  14. package/dist/devices/slc.d.ts.map +1 -0
  15. package/dist/devices/slc.js +50 -0
  16. package/dist/devices/slc.js.map +1 -0
  17. package/dist/devices/tuya.d.ts.map +1 -1
  18. package/dist/devices/tuya.js +35 -9
  19. package/dist/devices/tuya.js.map +1 -1
  20. package/dist/lib/bosch.d.ts +3 -98
  21. package/dist/lib/bosch.d.ts.map +1 -1
  22. package/dist/lib/bosch.js +23 -543
  23. package/dist/lib/bosch.js.map +1 -1
  24. package/dist/lib/exposes.d.ts +2 -0
  25. package/dist/lib/exposes.d.ts.map +1 -1
  26. package/dist/lib/exposes.js +15 -0
  27. package/dist/lib/exposes.js.map +1 -1
  28. package/dist/lib/modernExtend.d.ts +0 -4
  29. package/dist/lib/modernExtend.d.ts.map +1 -1
  30. package/dist/lib/modernExtend.js +2 -5
  31. package/dist/lib/modernExtend.js.map +1 -1
  32. package/dist/lib/tuya.d.ts.map +1 -1
  33. package/dist/lib/tuya.js +3 -14
  34. package/dist/lib/tuya.js.map +1 -1
  35. package/dist/lib/utils.d.ts +1 -0
  36. package/dist/lib/utils.d.ts.map +1 -1
  37. package/dist/lib/utils.js +15 -1
  38. package/dist/lib/utils.js.map +1 -1
  39. package/dist/models-index.json +1 -1
  40. package/package.json +1 -1
package/dist/lib/bosch.js CHANGED
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.boschThermostatExtend = exports.boschSmartPlugExtend = exports.boschBsenExtend = exports.boschDoorWindowContactExtend = exports.boschBsirExtend = exports.boschBmctExtend = exports.boschGeneralExtend = exports.manufacturerOptions = void 0;
36
+ exports.boschSmartPlugExtend = exports.boschBsenExtend = exports.boschDoorWindowContactExtend = exports.boschBsirExtend = exports.boschBmctExtend = exports.boschGeneralExtend = exports.manufacturerOptions = void 0;
37
37
  const zigbee_herdsman_1 = require("zigbee-herdsman");
38
38
  const fz = __importStar(require("../converters/fromZigbee"));
39
39
  const tz = __importStar(require("../converters/toZigbee"));
@@ -49,20 +49,10 @@ const ea = exposes.access;
49
49
  const NS = "zhc:bosch";
50
50
  exports.manufacturerOptions = { manufacturerCode: zigbee_herdsman_1.Zcl.ManufacturerCode.ROBERT_BOSCH_GMBH };
51
51
  exports.boschGeneralExtend = {
52
- /** Some Bosch devices ask the coordinator for their ZCL version
53
- * during deviceAnnouncement. Without answer, these devices regularly
54
- * re-join the network. To avoid that, we have to make sure that a readRequest
55
- * for the zclVersion is always being answered. The answered zclVersion is
56
- * taken from the Bosch Smart Home Controller II.
57
- *
58
- * Exception: BTH-RM and BTH-RM230Z ask the coordinator at regular
59
- * intervals for their zclVersion (maybe availability check like Z2M does?)
60
- * and *not* during interview! To avoid code-duplication, we handle that
61
- * case here as well. */
62
52
  handleZclVersionReadRequest: () => {
63
53
  const onEvent = [
64
54
  (event) => {
65
- if (event.type !== "start") {
55
+ if (event.type !== "deviceAnnounce") {
66
56
  return;
67
57
  }
68
58
  event.data.device.customReadResponse = (frame, endpoint) => {
@@ -85,7 +75,7 @@ exports.boschGeneralExtend = {
85
75
  isModernExtend: true,
86
76
  };
87
77
  },
88
- customMeteringCluster: () => m.deviceAddCustomCluster("seMetering", {
78
+ customSeMeteringCluster: () => m.deviceAddCustomCluster("seMetering", {
89
79
  ID: zigbee_herdsman_1.Zcl.Clusters.seMetering.ID,
90
80
  attributes: {},
91
81
  commands: {
@@ -117,12 +107,6 @@ exports.boschGeneralExtend = {
117
107
  isModernExtend: true,
118
108
  };
119
109
  },
120
- batteryWithPercentageAndLowStatus: (args) => m.battery({
121
- percentage: true,
122
- lowStatus: true,
123
- lowStatusReportingConfig: { min: "MIN", max: "MAX", change: null },
124
- ...args,
125
- }),
126
110
  autoOff: (args) => {
127
111
  const { endpoint } = args ?? {};
128
112
  const offOnLookup = {
@@ -1150,6 +1134,20 @@ exports.boschBsirExtend = {
1150
1134
  },
1151
1135
  access: "STATE_GET",
1152
1136
  }),
1137
+ battery: () => m.battery({
1138
+ percentage: true,
1139
+ percentageReportingConfig: {
1140
+ min: "MIN",
1141
+ max: "MAX",
1142
+ change: 1,
1143
+ },
1144
+ lowStatus: true,
1145
+ lowStatusReportingConfig: {
1146
+ min: "MIN",
1147
+ max: "MAX",
1148
+ change: 0,
1149
+ },
1150
+ }),
1153
1151
  lightDelay: () => m.numeric({
1154
1152
  name: "light_delay",
1155
1153
  cluster: "ssIasWd",
@@ -1368,6 +1366,11 @@ exports.boschDoorWindowContactExtend = {
1368
1366
  commands: {},
1369
1367
  commandsResponse: {},
1370
1368
  }),
1369
+ battery: () => m.battery({
1370
+ percentage: true,
1371
+ lowStatus: true,
1372
+ lowStatusReportingConfig: { min: "MIN", max: "MAX", change: 0 },
1373
+ }),
1371
1374
  reportContactState: () => m.iasZoneAlarm({
1372
1375
  zoneType: "contact",
1373
1376
  zoneAttributes: ["alarm_1"],
@@ -1657,7 +1660,7 @@ exports.boschBsenExtend = {
1657
1660
  voltageReporting: true,
1658
1661
  voltageToPercentage: { min: 2500, max: 3000 },
1659
1662
  lowStatus: true,
1660
- lowStatusReportingConfig: { min: "MIN", max: "MAX", change: null },
1663
+ lowStatusReportingConfig: { min: "MIN", max: "MAX", change: 0 },
1661
1664
  }),
1662
1665
  illuminance: () => m.illuminance({ reporting: { min: "1_SECOND", max: 600, change: 3522 } }),
1663
1666
  // The temperature sensor isn't used at all by Bosch on the BSEN-M.
@@ -2013,528 +2016,5 @@ exports.boschSmartPlugExtend = {
2013
2016
  ...args,
2014
2017
  }),
2015
2018
  };
2016
- const boschThermostatLookup = {
2017
- heaterType: {
2018
- underfloor_heating: 0x00,
2019
- central_heating: 0x03,
2020
- radiator: 0x02,
2021
- },
2022
- };
2023
- exports.boschThermostatExtend = {
2024
- customThermostatCluster: () => m.deviceAddCustomCluster("hvacThermostat", {
2025
- ID: zigbee_herdsman_1.Zcl.Clusters.hvacThermostat.ID,
2026
- attributes: {
2027
- operatingMode: { ID: 0x4007, type: zigbee_herdsman_1.Zcl.DataType.ENUM8, manufacturerCode: exports.manufacturerOptions.manufacturerCode },
2028
- heatingDemand: { ID: 0x4020, type: zigbee_herdsman_1.Zcl.DataType.ENUM8, manufacturerCode: exports.manufacturerOptions.manufacturerCode },
2029
- valveAdaptStatus: { ID: 0x4022, type: zigbee_herdsman_1.Zcl.DataType.ENUM8, manufacturerCode: exports.manufacturerOptions.manufacturerCode },
2030
- unknownAttribute0: { ID: 0x4025, type: zigbee_herdsman_1.Zcl.DataType.ENUM8, manufacturerCode: exports.manufacturerOptions.manufacturerCode },
2031
- remoteTemperature: { ID: 0x4040, type: zigbee_herdsman_1.Zcl.DataType.INT16, manufacturerCode: exports.manufacturerOptions.manufacturerCode },
2032
- unknownAttribute1: { ID: 0x4041, type: zigbee_herdsman_1.Zcl.DataType.ENUM8, manufacturerCode: exports.manufacturerOptions.manufacturerCode },
2033
- windowOpenMode: { ID: 0x4042, type: zigbee_herdsman_1.Zcl.DataType.ENUM8, manufacturerCode: exports.manufacturerOptions.manufacturerCode },
2034
- boostHeating: { ID: 0x4043, type: zigbee_herdsman_1.Zcl.DataType.ENUM8, manufacturerCode: exports.manufacturerOptions.manufacturerCode },
2035
- cableSensorTemperature: { ID: 0x4052, type: zigbee_herdsman_1.Zcl.DataType.INT16, manufacturerCode: exports.manufacturerOptions.manufacturerCode },
2036
- valveType: { ID: 0x4060, type: zigbee_herdsman_1.Zcl.DataType.ENUM8, manufacturerCode: exports.manufacturerOptions.manufacturerCode },
2037
- unknownAttribute2: { ID: 0x4061, type: zigbee_herdsman_1.Zcl.DataType.ENUM8, manufacturerCode: exports.manufacturerOptions.manufacturerCode },
2038
- cableSensorMode: { ID: 0x4062, type: zigbee_herdsman_1.Zcl.DataType.ENUM8, manufacturerCode: exports.manufacturerOptions.manufacturerCode },
2039
- heaterType: { ID: 0x4063, type: zigbee_herdsman_1.Zcl.DataType.ENUM8, manufacturerCode: exports.manufacturerOptions.manufacturerCode },
2040
- errorState: { ID: 0x5000, type: zigbee_herdsman_1.Zcl.DataType.BITMAP8, manufacturerCode: exports.manufacturerOptions.manufacturerCode },
2041
- },
2042
- commands: {
2043
- calibrateValve: { ID: 0x41, parameters: [] },
2044
- },
2045
- commandsResponse: {},
2046
- }),
2047
- customUserInterfaceCfgCluster: () => m.deviceAddCustomCluster("hvacUserInterfaceCfg", {
2048
- ID: zigbee_herdsman_1.Zcl.Clusters.hvacUserInterfaceCfg.ID,
2049
- attributes: {
2050
- displayOrientation: { ID: 0x400b, type: zigbee_herdsman_1.Zcl.DataType.UINT8, manufacturerCode: exports.manufacturerOptions.manufacturerCode },
2051
- displayedTemperature: { ID: 0x4039, type: zigbee_herdsman_1.Zcl.DataType.ENUM8, manufacturerCode: exports.manufacturerOptions.manufacturerCode },
2052
- displaySwitchOnDuration: { ID: 0x403a, type: zigbee_herdsman_1.Zcl.DataType.ENUM8, manufacturerCode: exports.manufacturerOptions.manufacturerCode },
2053
- displayBrightness: { ID: 0x403b, type: zigbee_herdsman_1.Zcl.DataType.ENUM8, manufacturerCode: exports.manufacturerOptions.manufacturerCode },
2054
- },
2055
- commands: {},
2056
- commandsResponse: {},
2057
- }),
2058
- rmThermostat: () => m.thermostat({
2059
- setpoints: {
2060
- occupiedHeatingSetpoint: { min: 5, max: 30, step: 0.5 },
2061
- occupiedCoolingSetpoint: { min: 5, max: 30, step: 0.5 },
2062
- },
2063
- localTemperatureCalibration: { min: -5, max: 5, step: 0.1 },
2064
- systemMode: ["off", "heat", "cool"],
2065
- runningState: ["idle", "heat", "cool"],
2066
- }),
2067
- customHeatingDemand: () => m.numeric({
2068
- name: "pi_heating_demand",
2069
- cluster: "hvacThermostat",
2070
- attribute: "heatingDemand",
2071
- label: "PI heating demand",
2072
- description: "Position of the valve (= demanded heat) where 0% is fully closed and 100% is fully open",
2073
- unit: "%",
2074
- valueMin: 0,
2075
- valueMax: 100,
2076
- reporting: { min: "MIN", max: "MAX", change: null },
2077
- access: "ALL",
2078
- }),
2079
- cableSensorMode: () => m.enumLookup({
2080
- name: "cable_sensor_mode",
2081
- cluster: "hvacThermostat",
2082
- attribute: "cableSensorMode",
2083
- description: 'Select a configuration for the sensor connection. If you select "with_regulation", the measured temperature on the cable sensor is used by the heating/cooling algorithm instead of the local temperature.',
2084
- lookup: { not_used: 0x00, cable_sensor_without_regulation: 0xb0, cable_sensor_with_regulation: 0xb1 },
2085
- entityCategory: "config",
2086
- }),
2087
- cableSensorTemperature: () => m.numeric({
2088
- name: "cable_sensor_temperature",
2089
- cluster: "hvacThermostat",
2090
- attribute: "cableSensorTemperature",
2091
- description: "Measured temperature value on the cable sensor (if enabled)",
2092
- unit: "°C",
2093
- scale: 100,
2094
- reporting: { min: 30, max: "MAX", change: 20 },
2095
- access: "STATE_GET",
2096
- }),
2097
- heaterType: () => m.enumLookup({
2098
- name: "heater_type",
2099
- cluster: "hvacThermostat",
2100
- attribute: "heaterType",
2101
- description: "Select the connected heater type",
2102
- lookup: boschThermostatLookup.heaterType,
2103
- entityCategory: "config",
2104
- }),
2105
- valveType: () => m.enumLookup({
2106
- name: "valve_type",
2107
- cluster: "hvacThermostat",
2108
- attribute: "valveType",
2109
- description: "Select the connected valve type",
2110
- lookup: { normally_closed: 0x00, normally_open: 0x01 },
2111
- entityCategory: "config",
2112
- }),
2113
- humidity: () => m.humidity(),
2114
- operatingMode: (args) => m.enumLookup({
2115
- name: "operating_mode",
2116
- cluster: "hvacThermostat",
2117
- attribute: "operatingMode",
2118
- description: "Bosch-specific operating mode",
2119
- lookup: { schedule: 0x00, manual: 0x01, pause: 0x05 },
2120
- reporting: { min: "MIN", max: "MAX", change: null },
2121
- ...args,
2122
- }),
2123
- windowOpenMode: () => m.binary({
2124
- name: "window_open_mode",
2125
- cluster: "hvacThermostat",
2126
- attribute: "windowOpenMode",
2127
- description: "Activates the window open mode, where the thermostat disables any heating/cooling to prevent unnecessary energy consumption. Please keep in mind that the device itself does not detect any open windows!",
2128
- valueOn: ["ON", 0x01],
2129
- valueOff: ["OFF", 0x00],
2130
- reporting: { min: "MIN", max: "MAX", change: null, attribute: "windowOpenMode" },
2131
- }),
2132
- childLock: () => m.binary({
2133
- name: "child_lock",
2134
- cluster: "hvacUserInterfaceCfg",
2135
- attribute: "keypadLockout",
2136
- description: "Enables/disables physical input on the device",
2137
- valueOn: ["LOCK", 0x01],
2138
- valueOff: ["UNLOCK", 0x00],
2139
- reporting: { min: "MIN", max: "MAX", change: null, attribute: "keypadLockout" },
2140
- }),
2141
- displayBrightness: () => m.numeric({
2142
- name: "display_brightness",
2143
- cluster: "hvacUserInterfaceCfg",
2144
- attribute: "displayBrightness",
2145
- description: "Sets brightness of the display",
2146
- valueMin: 0,
2147
- valueMax: 100,
2148
- valueStep: 10,
2149
- unit: "%",
2150
- scale: 0.1,
2151
- entityCategory: "config",
2152
- }),
2153
- displaySwitchOnDuration: () => m.numeric({
2154
- name: "display_switch_on_duration",
2155
- cluster: "hvacUserInterfaceCfg",
2156
- attribute: "displaySwitchOnDuration",
2157
- label: "Display switch-on duration",
2158
- description: "Sets the time before the display is automatically switched off",
2159
- valueMin: 5,
2160
- valueMax: 30,
2161
- unit: "s",
2162
- entityCategory: "config",
2163
- }),
2164
- displayOrientation: () => m.enumLookup({
2165
- name: "display_orientation",
2166
- cluster: "hvacUserInterfaceCfg",
2167
- attribute: "displayOrientation",
2168
- description: "You can rotate the display content by 180° here. This is recommended if your thermostat is fitted vertically, for instance.",
2169
- lookup: { standard_arrangement: 0x00, rotated_by_180_degrees: 0x01 },
2170
- entityCategory: "config",
2171
- }),
2172
- displayedTemperature: () => m.enumLookup({
2173
- name: "displayed_temperature",
2174
- cluster: "hvacUserInterfaceCfg",
2175
- attribute: "displayedTemperature",
2176
- description: "Select which temperature should be displayed on your radiator thermostat display",
2177
- lookup: { set_temperature: 0x00, measured_temperature: 0x01 },
2178
- entityCategory: "config",
2179
- }),
2180
- remoteTemperature: () => m.numeric({
2181
- name: "remote_temperature",
2182
- cluster: "hvacThermostat",
2183
- attribute: "remoteTemperature",
2184
- description: "Input for remote temperature sensor. Required at least every 30 minutes to prevent fallback to the internal sensor!",
2185
- valueMin: 0.0,
2186
- valueMax: 35.0,
2187
- valueStep: 0.2,
2188
- unit: "°C",
2189
- scale: 100,
2190
- }),
2191
- setpointChangeSource: () => m.enumLookup({
2192
- name: "setpoint_change_source",
2193
- cluster: "hvacThermostat",
2194
- attribute: "setpointChangeSource",
2195
- reporting: { min: "10_SECONDS", max: "MAX", change: null },
2196
- description: "Source of the current setpoint temperature",
2197
- lookup: { manual: 0x00, schedule: 0x01, externally: 0x02 },
2198
- access: "STATE_GET",
2199
- }),
2200
- rmBattery: () => m.battery({
2201
- percentage: true,
2202
- percentageReporting: false,
2203
- voltage: true,
2204
- voltageReporting: true,
2205
- voltageToPercentage: { min: 4400, max: 6400 },
2206
- lowStatus: true,
2207
- lowStatusReportingConfig: { min: "MIN", max: "MAX", change: null },
2208
- }),
2209
- raThermostat: () => {
2210
- const thermostat = m.thermostat({
2211
- localTemperature: {
2212
- description: "Temperature used by the heating algorithm. This is the temperature measured on the device (by default) or the remote temperature (if set within the last 30 min).",
2213
- },
2214
- setpoints: {
2215
- occupiedHeatingSetpoint: { min: 5, max: 30, step: 0.5 },
2216
- },
2217
- localTemperatureCalibration: { min: -5, max: 5, step: 0.1 },
2218
- systemMode: ["heat"],
2219
- });
2220
- const exposes = thermostat.exposes;
2221
- const fromZigbee = thermostat.fromZigbee;
2222
- const toZigbee = thermostat.toZigbee;
2223
- const configure = thermostat.configure;
2224
- const meta = {
2225
- overrideHaDiscoveryPayload: (payload) => {
2226
- // Override climate discovery
2227
- // https://github.com/Koenkk/zigbee2mqtt/pull/23075#issue-2355829475
2228
- if (payload.mode_command_topic?.endsWith("/system_mode")) {
2229
- payload.mode_command_topic = payload.mode_command_topic.substring(0, payload.mode_command_topic.lastIndexOf("/system_mode"));
2230
- payload.mode_command_template =
2231
- "{% set values = " +
2232
- `{ 'auto':'schedule','heat':'manual','off':'pause'} %}` +
2233
- `{"operating_mode": "{{ values[value] if value in values.keys() else 'pause' }}"}`;
2234
- payload.mode_state_template =
2235
- "{% set values = " +
2236
- `{'schedule':'auto','manual':'heat','pause':'off'} %}` +
2237
- `{% set value = value_json.operating_mode %}{{ values[value] if value in values.keys() else 'off' }}`;
2238
- payload.modes = ["off", "heat", "auto"];
2239
- }
2240
- },
2241
- };
2242
- return {
2243
- exposes,
2244
- fromZigbee,
2245
- toZigbee,
2246
- configure,
2247
- meta,
2248
- isModernExtend: true,
2249
- };
2250
- },
2251
- customRunningState: () => {
2252
- const runningStates = ["idle", "heat"];
2253
- const exposes = [e.enum("running_state", ea.STATE_GET, runningStates).withDescription("The current running state")];
2254
- const fromZigbee = [
2255
- {
2256
- cluster: "hvacThermostat",
2257
- type: ["attributeReport", "readResponse"],
2258
- convert: (model, msg, publish, options, meta) => {
2259
- const result = {};
2260
- const data = msg.data;
2261
- if (data.heatingDemand !== undefined) {
2262
- result.running_state = utils.toNumber(data.heatingDemand) > 0 ? runningStates[1] : runningStates[0];
2263
- }
2264
- return result;
2265
- },
2266
- },
2267
- ];
2268
- const toZigbee = [
2269
- {
2270
- key: ["running_state"],
2271
- convertGet: async (entity, key, meta) => {
2272
- await entity.read("hvacThermostat", ["heatingDemand"]);
2273
- },
2274
- },
2275
- ];
2276
- return {
2277
- exposes,
2278
- fromZigbee,
2279
- toZigbee,
2280
- isModernExtend: true,
2281
- };
2282
- },
2283
- boostHeating: () => {
2284
- const boostHeatingLookup = {
2285
- OFF: 0x00,
2286
- ON: 0x01,
2287
- };
2288
- const exposes = [
2289
- e
2290
- .binary("boost_heating", ea.ALL, utils.getFromLookupByValue(0x01, boostHeatingLookup), utils.getFromLookupByValue(0x00, boostHeatingLookup))
2291
- .withLabel("Activate boost heating")
2292
- .withDescription("Activate boost heating (opens TRV for 5 minutes)"),
2293
- ];
2294
- const fromZigbee = [
2295
- {
2296
- cluster: "hvacThermostat",
2297
- type: ["attributeReport", "readResponse"],
2298
- convert: (model, msg, publish, options, meta) => {
2299
- const result = {};
2300
- const data = msg.data;
2301
- if (data.boostHeating !== undefined) {
2302
- result.boost_heating = utils.getFromLookupByValue(data.boostHeating, boostHeatingLookup);
2303
- }
2304
- return result;
2305
- },
2306
- },
2307
- ];
2308
- const toZigbee = [
2309
- {
2310
- key: ["boost_heating"],
2311
- convertSet: async (entity, key, value, meta) => {
2312
- const enableBoostHeating = value === utils.getFromLookupByValue(boostHeatingLookup.ON, boostHeatingLookup);
2313
- if (enableBoostHeating) {
2314
- const systemModeNotSetToHeat = "system_mode" in meta.state && meta.state.system_mode !== "heat";
2315
- if (systemModeNotSetToHeat) {
2316
- throw new Error("Boost heating is only possible when system mode is set to 'heat'!");
2317
- }
2318
- const heaterTypeNotSetToRadiator = "heater_type" in meta.state &&
2319
- meta.state.heater_type !==
2320
- utils.getFromLookupByValue(boschThermostatLookup.heaterType.radiator, boschThermostatLookup.heaterType);
2321
- if (heaterTypeNotSetToRadiator) {
2322
- throw new Error("Boost heating is only possible when heater type is set to 'radiator'!");
2323
- }
2324
- }
2325
- await entity.write("hvacThermostat", {
2326
- boostHeating: utils.toNumber(utils.getFromLookup(value, boostHeatingLookup)),
2327
- });
2328
- return { state: { boost_heating: value } };
2329
- },
2330
- convertGet: async (entity, key, meta) => {
2331
- await entity.read("hvacThermostat", ["boostHeating"]);
2332
- },
2333
- },
2334
- ];
2335
- const configure = [
2336
- m.setupConfigureForReporting("hvacThermostat", "boostHeating", {
2337
- config: { min: "MIN", max: "MAX", change: null },
2338
- }),
2339
- m.setupConfigureForReading("hvacThermostat", ["boostHeating"]),
2340
- ];
2341
- return {
2342
- exposes,
2343
- fromZigbee,
2344
- toZigbee,
2345
- configure,
2346
- isModernExtend: true,
2347
- };
2348
- },
2349
- errorState: () => {
2350
- const exposes = [
2351
- e
2352
- .text("error_state", ea.STATE_GET)
2353
- .withDescription("Indicates whether the device encounters any errors or not")
2354
- .withCategory("diagnostic"),
2355
- ];
2356
- const fromZigbee = [
2357
- {
2358
- cluster: "hvacThermostat",
2359
- type: ["attributeReport", "readResponse"],
2360
- convert: (model, msg, publish, options, meta) => {
2361
- const result = {};
2362
- const data = msg.data;
2363
- if (data.errorState !== undefined) {
2364
- const receivedErrorState = data.errorState;
2365
- if (receivedErrorState === 0) {
2366
- result.error_state = "ok";
2367
- }
2368
- else {
2369
- result.error_state = "";
2370
- const bitmapLength = (receivedErrorState >>> 0).toString(2).length;
2371
- for (let errorNumber = 0; errorNumber < bitmapLength; errorNumber++) {
2372
- if ((receivedErrorState >> errorNumber) & 1) {
2373
- if (String(result.error_state).length > 0) {
2374
- result.error_state += " - ";
2375
- }
2376
- result.error_state += `E${String(errorNumber + 1).padStart(2, "0")}`;
2377
- }
2378
- }
2379
- }
2380
- }
2381
- return result;
2382
- },
2383
- },
2384
- ];
2385
- const toZigbee = [
2386
- {
2387
- key: ["error_state"],
2388
- convertGet: async (entity, key, meta) => {
2389
- await entity.read("hvacThermostat", ["errorState"]);
2390
- },
2391
- },
2392
- ];
2393
- const configure = [
2394
- m.setupConfigureForReporting("hvacThermostat", "errorState", {
2395
- config: { min: "MIN", max: "MAX", change: null },
2396
- }),
2397
- m.setupConfigureForReading("hvacThermostat", ["errorState"]),
2398
- ];
2399
- return {
2400
- exposes,
2401
- fromZigbee,
2402
- toZigbee,
2403
- configure,
2404
- isModernExtend: true,
2405
- };
2406
- },
2407
- valveAdaptation: () => {
2408
- const valveAdaptStatusLookup = {
2409
- none: 0x00,
2410
- ready_to_calibrate: 0x01,
2411
- calibration_in_progress: 0x02,
2412
- error: 0x03,
2413
- success: 0x04,
2414
- };
2415
- const exposes = [
2416
- e
2417
- .enum("valve_adapt_status", ea.STATE_GET, Object.keys(valveAdaptStatusLookup))
2418
- .withLabel("Valve adaptation status")
2419
- .withDescription("Specifies the current status of the valve adaptation")
2420
- .withCategory("diagnostic"),
2421
- e
2422
- .enum("valve_adapt_process", ea.SET, ["adapt"])
2423
- .withLabel("Trigger adaptation process")
2424
- .withDescription('Trigger the valve adaptation process. Only possible when adaptation status is "ready_to_calibrate" or "error".')
2425
- .withCategory("config"),
2426
- ];
2427
- const fromZigbee = [
2428
- {
2429
- cluster: "hvacThermostat",
2430
- type: ["attributeReport", "readResponse"],
2431
- convert: (model, msg, publish, options, meta) => {
2432
- const result = {};
2433
- const data = msg.data;
2434
- if (data.valveAdaptStatus !== undefined) {
2435
- result.valve_adapt_status = utils.getFromLookupByValue(data.valveAdaptStatus, valveAdaptStatusLookup);
2436
- }
2437
- return result;
2438
- },
2439
- },
2440
- ];
2441
- const toZigbee = [
2442
- {
2443
- key: ["valve_adapt_status", "valve_adapt_process"],
2444
- convertSet: async (entity, key, value, meta) => {
2445
- if (key === "valve_adapt_process") {
2446
- let adaptStatus;
2447
- try {
2448
- adaptStatus = utils.getFromLookup(meta.state.valve_adapt_status, valveAdaptStatusLookup);
2449
- }
2450
- catch {
2451
- adaptStatus = valveAdaptStatusLookup.none;
2452
- }
2453
- switch (adaptStatus) {
2454
- case valveAdaptStatusLookup.ready_to_calibrate:
2455
- case valveAdaptStatusLookup.error:
2456
- await entity.command("hvacThermostat", "calibrateValve", {}, exports.manufacturerOptions);
2457
- break;
2458
- default:
2459
- throw new Error("Valve adaptation process not possible right now!");
2460
- }
2461
- }
2462
- },
2463
- convertGet: async (entity, key, meta) => {
2464
- if (key === "valve_adapt_status") {
2465
- await entity.read("hvacThermostat", ["valveAdaptStatus"]);
2466
- }
2467
- },
2468
- },
2469
- ];
2470
- const configure = [
2471
- m.setupConfigureForReporting("hvacThermostat", "valveAdaptStatus", {
2472
- config: { min: "MIN", max: "MAX", change: null },
2473
- }),
2474
- ];
2475
- return {
2476
- exposes,
2477
- fromZigbee,
2478
- toZigbee,
2479
- configure,
2480
- isModernExtend: true,
2481
- };
2482
- },
2483
- /** The Bosch thermostats ask the coordinator on several occasions for
2484
- * information about daylight saving time. As we don't support the setup
2485
- * of schedules, we just answer with 0x00 so that the device stops asking.
2486
- *
2487
- * Since Bosch devices don't seem to like it when we offer incomplete
2488
- * answers, we have to use a customReadResponse here and duplicate
2489
- * some code from zigbee-herdsman. */
2490
- handleDaylightSavingTimeReadRequest: () => {
2491
- const onEvent = [
2492
- (event) => {
2493
- if (event.type !== "start") {
2494
- return;
2495
- }
2496
- event.data.device.customReadResponse = (frame, endpoint) => {
2497
- const isTimeClusterRequest = frame.isCluster("genTime");
2498
- if (!isTimeClusterRequest) {
2499
- return false;
2500
- }
2501
- const daylightSavingTimeRequested = frame.payload.find((i) => i.attrId === zigbee_herdsman_1.Zcl.Clusters.genTime.attributes.dstStart.ID) &&
2502
- frame.payload.find((i) => i.attrId === zigbee_herdsman_1.Zcl.Clusters.genTime.attributes.dstEnd.ID) &&
2503
- frame.payload.find((i) => i.attrId === zigbee_herdsman_1.Zcl.Clusters.genTime.attributes.dstShift.ID);
2504
- if (!daylightSavingTimeRequested) {
2505
- return false;
2506
- }
2507
- const payload = {
2508
- dstStart: 0x00,
2509
- dstEnd: 0x00,
2510
- dstShift: 0x00,
2511
- };
2512
- const OneJanuary2000 = new Date("January 01, 2000 00:00:00 UTC+00:00").getTime();
2513
- const time = Math.round((Date.now() - OneJanuary2000) / 1000);
2514
- const timeRequested = frame.payload.find((i) => i.attrId === zigbee_herdsman_1.Zcl.Clusters.genTime.attributes.time.ID);
2515
- if (timeRequested) {
2516
- payload.time = time;
2517
- }
2518
- const timeZoneRequested = frame.payload.find((i) => i.attrId === zigbee_herdsman_1.Zcl.Clusters.genTime.attributes.timeZone.ID);
2519
- if (timeZoneRequested) {
2520
- payload.timeZone = new Date().getTimezoneOffset() * -1 * 60;
2521
- }
2522
- const localTimeRequested = frame.payload.find((i) => i.attrId === zigbee_herdsman_1.Zcl.Clusters.genTime.attributes.localTime.ID);
2523
- if (localTimeRequested) {
2524
- payload.localTime = time - new Date().getTimezoneOffset() * 60;
2525
- }
2526
- endpoint.readResponse(frame.cluster.name, frame.header.transactionSequenceNumber, payload).catch((e) => {
2527
- logger_1.logger.warning(`Custom genTime response failed for '${event.data.device.ieeeAddr}': ${e}`, NS);
2528
- });
2529
- return true;
2530
- };
2531
- },
2532
- ];
2533
- return {
2534
- onEvent,
2535
- isModernExtend: true,
2536
- };
2537
- },
2538
- };
2539
2019
  //endregion
2540
2020
  //# sourceMappingURL=bosch.js.map