zigbee-herdsman-converters 25.8.0 → 25.10.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.
@@ -221,7 +221,7 @@ const inovelliExtend = {
221
221
  },
222
222
  ledEffectComplete: {
223
223
  ID: 0x24,
224
- parameters: [{ name: "notificationType", type: zigbee_herdsman_1.Zcl.DataType.UINT8 }],
224
+ parameters: [{ name: "notificationType", type: zigbee_herdsman_1.Zcl.DataType.INT8 }],
225
225
  },
226
226
  },
227
227
  commandsResponse: {},
@@ -261,9 +261,129 @@ const inovelliExtend = {
261
261
  },
262
262
  },
263
263
  }),
264
+ inovelliDevice: ({ attrs, supportsLedEffects, supportsButtonTaps, splitValuesByEndpoint = false, }) => {
265
+ const fromZigbee = [];
266
+ const toZigbee = [];
267
+ const exposes = [];
268
+ if (supportsLedEffects) {
269
+ fromZigbee.push(fzLocal.led_effect_complete);
270
+ toZigbee.push(tzLocal.inovelli_led_effect, tzLocal.inovelli_individual_led_effect);
271
+ exposes.push(exposeLedEffects(), exposeIndividualLedEffects(), exposeLedEffectComplete());
272
+ }
273
+ for (const attr of attrs) {
274
+ fromZigbee.push(fzLocal.inovelli(attr.attributes, attr.clusterName, splitValuesByEndpoint));
275
+ toZigbee.push(tzLocal.inovelli_parameters(attr.attributes, attr.clusterName), tzLocal.inovelli_parameters_readOnly(attr.attributes, attr.clusterName));
276
+ attributesToExposeList(attr.attributes, exposes);
277
+ }
278
+ if (supportsButtonTaps) {
279
+ exposes.push(e.action(BUTTON_TAP_SEQUENCES));
280
+ }
281
+ const configure = [
282
+ async (device, coordinatorEndpoint, definition) => {
283
+ const endpoint = device.getEndpoint(1);
284
+ await reporting.bind(endpoint, coordinatorEndpoint, [INOVELLI_CLUSTER_NAME]);
285
+ // Bind for Button Event Reporting
286
+ const endpoint2 = device.getEndpoint(2);
287
+ await reporting.bind(endpoint2, coordinatorEndpoint, [INOVELLI_CLUSTER_NAME]);
288
+ for (const attr of attrs) {
289
+ if (!splitValuesByEndpoint) {
290
+ await chunkedRead(endpoint, Object.keys(attr.attributes), attr.clusterName);
291
+ }
292
+ else {
293
+ await chunkedRead(endpoint, Object.keys(attr.attributes).flatMap((key) => {
294
+ const keysplit = key.split("_");
295
+ if (keysplit.length === 2) {
296
+ if (Number(keysplit[1]) === 1) {
297
+ return [keysplit[0]];
298
+ }
299
+ return [];
300
+ }
301
+ return [key];
302
+ }), attr.clusterName);
303
+ await chunkedRead(endpoint2, Object.keys(attr.attributes).flatMap((key) => {
304
+ const keysplit = key.split("_");
305
+ if (keysplit.length === 2) {
306
+ if (Number(keysplit[1]) === 2) {
307
+ return [keysplit[0]];
308
+ }
309
+ }
310
+ return [];
311
+ }), attr.clusterName);
312
+ }
313
+ }
314
+ },
315
+ ];
316
+ return {
317
+ fromZigbee,
318
+ toZigbee,
319
+ exposes,
320
+ configure,
321
+ isModernExtend: true,
322
+ };
323
+ },
324
+ inovelliLight: ({ splitValuesByEndpoint = false } = {}) => {
325
+ const fromZigbee = [];
326
+ const bindingList = ["genOnOff"];
327
+ if (!splitValuesByEndpoint) {
328
+ fromZigbee.push(fz.on_off, fz.brightness, fz.level_config, fz.power_on_behavior, fz.ignore_basic_report);
329
+ bindingList.push("genLevelCtrl");
330
+ }
331
+ const configure = [
332
+ async (device, coordinatorEndpoint, definition) => {
333
+ const endpoint = device.getEndpoint(1);
334
+ await reporting.bind(endpoint, coordinatorEndpoint, bindingList);
335
+ await reporting.onOff(endpoint);
336
+ },
337
+ ];
338
+ return {
339
+ fromZigbee,
340
+ toZigbee: [
341
+ tz.on_off,
342
+ tzLocal.light_onoff_brightness_inovelli,
343
+ tz.power_on_behavior,
344
+ tz.ignore_transition,
345
+ tz.light_brightness_move,
346
+ tz.light_brightness_step,
347
+ tz.level_config,
348
+ ],
349
+ exposes: [e.light_brightness()],
350
+ configure,
351
+ isModernExtend: true,
352
+ };
353
+ },
354
+ inovelliFan: ({ endpointId, splitValuesByEndpoint = false }) => {
355
+ const fromZigbee = [fzLocal.fan_mode(endpointId), fzLocal.breeze_mode(endpointId)];
356
+ const toZigbee = [tzLocal.fan_mode(endpointId), tzLocal.breezeMode(endpointId)];
357
+ const exposes = [e.fan().withState("fan_state").withModes(Object.keys(FAN_MODES)), exposeBreezeMode()];
358
+ const bindingList = ["genOnOff"];
359
+ if (!splitValuesByEndpoint) {
360
+ fromZigbee.push(fzLocal.fan_state);
361
+ toZigbee.push(tzLocal.fan_state);
362
+ bindingList.push("genLevelCtrl");
363
+ }
364
+ const configure = [
365
+ async (device, coordinatorEndpoint, definition) => {
366
+ const endpoint = device.getEndpoint(1);
367
+ await reporting.bind(endpoint, coordinatorEndpoint, bindingList);
368
+ await reporting.onOff(endpoint);
369
+ if (splitValuesByEndpoint) {
370
+ const endpoint2 = device.getEndpoint(2);
371
+ await reporting.bind(endpoint2, coordinatorEndpoint, bindingList);
372
+ await reporting.onOff(endpoint2);
373
+ }
374
+ },
375
+ ];
376
+ return {
377
+ fromZigbee,
378
+ toZigbee,
379
+ exposes,
380
+ configure,
381
+ isModernExtend: true,
382
+ };
383
+ },
264
384
  };
265
- const fanModes = { off: 0, low: 2, smart: 4, medium: 86, high: 170, on: 255 };
266
- const breezemodes = ["off", "low", "medium", "high"];
385
+ const FAN_MODES = { off: 0, low: 2, smart: 4, medium: 86, high: 170, on: 255 };
386
+ const BREEZE_MODES = ["off", "low", "medium", "high"];
267
387
  const LED_NOTIFICATION_TYPES = {
268
388
  0: "LED_1",
269
389
  1: "LED_2",
@@ -273,19 +393,19 @@ const LED_NOTIFICATION_TYPES = {
273
393
  5: "LED_6",
274
394
  6: "LED_7",
275
395
  16: "ALL_LEDS",
276
- 255: "CONFIG_BUTTON_DOUBLE_PRESS",
396
+ "-1": "CONFIG_BUTTON_DOUBLE_PRESS",
277
397
  };
278
398
  const INOVELLI = 0x122f;
279
399
  // Converts brightness level to a fan mode
280
400
  const intToFanMode = (value) => {
281
401
  let selectedMode = "low";
282
- if (value >= fanModes.low) {
402
+ if (value >= FAN_MODES.low) {
283
403
  selectedMode = "low";
284
404
  }
285
- if (value >= fanModes.medium) {
405
+ if (value >= FAN_MODES.medium) {
286
406
  selectedMode = "medium";
287
407
  }
288
- if (value >= fanModes.high) {
408
+ if (value >= FAN_MODES.high) {
289
409
  selectedMode = "high";
290
410
  }
291
411
  if (value === 4) {
@@ -1587,7 +1707,7 @@ const tzLocal = {
1587
1707
  ...meta,
1588
1708
  message: {
1589
1709
  ...meta.message,
1590
- transition: (!transition.specified ? 0xffff : Math.round(transition.time)) / 10,
1710
+ transition: (!transition.specified ? 0xffff : transition.time) / 10,
1591
1711
  },
1592
1712
  converterOptions: {
1593
1713
  ctrlbits: 0,
@@ -1604,7 +1724,7 @@ const tzLocal = {
1604
1724
  utils.assertString(value);
1605
1725
  const endpoint = meta.device.getEndpoint(endpointId);
1606
1726
  await endpoint.command("genLevelCtrl", "moveToLevelWithOnOff", {
1607
- level: fanModes[value],
1727
+ level: FAN_MODES[value],
1608
1728
  transtime: 0xffff,
1609
1729
  }, utils.getOptions(meta.mapped, entity));
1610
1730
  meta.state[key] = value;
@@ -1828,11 +1948,11 @@ const fzLocal = {
1828
1948
  if (msg.data.breeze_mode !== undefined) {
1829
1949
  const bitmasks = [3, 60, 192, 3840, 12288, 245760, 786432, 15728640, 50331648, 1006632960];
1830
1950
  const raw = msg.data.breeze_mode;
1831
- const s1 = breezemodes[raw & bitmasks[0]];
1832
- const s2 = breezemodes[(raw & bitmasks[2]) / 64];
1833
- const s3 = breezemodes[(raw & bitmasks[4]) / 4096];
1834
- const s4 = breezemodes[(raw & bitmasks[6]) / 262144];
1835
- const s5 = breezemodes[(raw & bitmasks[8]) / 16777216];
1951
+ const s1 = BREEZE_MODES[raw & bitmasks[0]];
1952
+ const s2 = BREEZE_MODES[(raw & bitmasks[2]) / 64];
1953
+ const s3 = BREEZE_MODES[(raw & bitmasks[4]) / 4096];
1954
+ const s4 = BREEZE_MODES[(raw & bitmasks[6]) / 262144];
1955
+ const s5 = BREEZE_MODES[(raw & bitmasks[8]) / 16777216];
1836
1956
  const d1 = ((raw & bitmasks[1]) / 4) * 5;
1837
1957
  const d2 = ((raw & bitmasks[3]) / 256) * 5;
1838
1958
  const d3 = ((raw & bitmasks[5]) / 16384) * 5;
@@ -1948,36 +2068,11 @@ const exposeMMWaveControl = () => {
1948
2068
  };
1949
2069
  const exposeLedEffectComplete = () => {
1950
2070
  return e
1951
- .enum("notificationComplete", ea.STATE_GET, Object.values(LED_NOTIFICATION_TYPES))
2071
+ .enum("notificationComplete", ea.STATE, Object.values(LED_NOTIFICATION_TYPES))
1952
2072
  .withDescription("Indication that a specific notification has completed.")
1953
2073
  .withCategory("diagnostic");
1954
2074
  };
1955
- const exposesListVZM30 = [e.light_brightness(), exposeLedEffects(), exposeIndividualLedEffects(), exposeLedEffectComplete()];
1956
- const exposesListVZM31 = [e.light_brightness(), exposeLedEffects(), exposeIndividualLedEffects(), exposeLedEffectComplete()];
1957
- const exposesListVZM32 = [
1958
- e.light_brightness(),
1959
- exposeLedEffects(),
1960
- exposeIndividualLedEffects(),
1961
- exposeMMWaveControl(),
1962
- exposeLedEffectComplete(),
1963
- ];
1964
- const exposesListVZM35 = [
1965
- e.fan().withState("fan_state").withModes(Object.keys(fanModes)),
1966
- exposeLedEffects(),
1967
- exposeIndividualLedEffects(),
1968
- exposeBreezeMode(),
1969
- exposeLedEffectComplete(),
1970
- ];
1971
- const exposesListVZM36 = [e.light_brightness(), e.fan().withState("fan_state").withModes(Object.keys(fanModes)), exposeBreezeMode()];
1972
- // Populate exposes list from the attributes description
1973
- attributesToExposeList(VZM30_ATTRIBUTES, exposesListVZM30);
1974
- attributesToExposeList(VZM31_ATTRIBUTES, exposesListVZM31);
1975
- attributesToExposeList(VZM32_ATTRIBUTES, exposesListVZM32);
1976
- attributesToExposeList(VZM32_MMWAVE_ATTRIBUTES, exposesListVZM32);
1977
- attributesToExposeList(VZM35_ATTRIBUTES, exposesListVZM35);
1978
- attributesToExposeList(VZM36_ATTRIBUTES, exposesListVZM36);
1979
- // Put actions at the bottom of ui
1980
- const buttonTapSequences = [
2075
+ const BUTTON_TAP_SEQUENCES = [
1981
2076
  "down_single",
1982
2077
  "up_single",
1983
2078
  "config_single",
@@ -2000,10 +2095,6 @@ const buttonTapSequences = [
2000
2095
  "up_quintuple",
2001
2096
  "config_quintuple",
2002
2097
  ];
2003
- exposesListVZM30.push(e.action(buttonTapSequences));
2004
- exposesListVZM31.push(e.action(buttonTapSequences));
2005
- exposesListVZM32.push(e.action(buttonTapSequences));
2006
- exposesListVZM35.push(e.action(buttonTapSequences));
2007
2098
  /*
2008
2099
  * Inovelli devices have a huge number of attributes. Calling endpoint.read() in a single call
2009
2100
  * for all attributes causes timeouts even with the timeout set to an absurdly high number (2 minutes)
@@ -2021,62 +2112,43 @@ exports.definitions = [
2021
2112
  model: "VZM30-SN",
2022
2113
  vendor: "Inovelli",
2023
2114
  description: "On/off switch",
2024
- exposes: exposesListVZM30.concat(m.identify().exposes),
2025
2115
  extend: [
2026
2116
  m.deviceEndpoints({
2027
2117
  endpoints: { "1": 1, "2": 2, "3": 3, "4": 4 },
2028
2118
  multiEndpointSkip: ["state", "voltage", "power", "current", "energy", "brightness", "temperature", "humidity"],
2029
2119
  }),
2120
+ inovelliExtend.inovelliLight(),
2121
+ inovelliExtend.inovelliDevice({
2122
+ attrs: [{ attributes: VZM30_ATTRIBUTES, clusterName: INOVELLI_CLUSTER_NAME }],
2123
+ supportsLedEffects: true,
2124
+ supportsButtonTaps: true,
2125
+ }),
2030
2126
  inovelliExtend.addCustomClusterInovelli(),
2127
+ m.identify(),
2031
2128
  m.temperature(),
2032
2129
  m.humidity(),
2033
- m.electricityMeter(),
2034
- ],
2035
- toZigbee: [
2036
- tzLocal.light_onoff_brightness_inovelli,
2037
- tz.power_on_behavior,
2038
- tz.ignore_transition,
2039
- tz.identify,
2040
- tz.light_brightness_move,
2041
- tz.light_brightness_step,
2042
- tz.level_config,
2043
- tzLocal.inovelli_led_effect,
2044
- tzLocal.inovelli_individual_led_effect,
2045
- tzLocal.inovelli_parameters(VZM30_ATTRIBUTES, INOVELLI_CLUSTER_NAME),
2046
- tzLocal.inovelli_parameters_readOnly(VZM30_ATTRIBUTES, INOVELLI_CLUSTER_NAME),
2047
- ],
2048
- fromZigbee: [
2049
- fz.on_off,
2050
- fz.brightness,
2051
- fz.level_config,
2052
- fz.power_on_behavior,
2053
- fz.ignore_basic_report,
2054
- fzLocal.inovelli(VZM30_ATTRIBUTES, INOVELLI_CLUSTER_NAME),
2055
- fzLocal.led_effect_complete,
2130
+ m.electricityMeter({ energy: { divisor: 1000 } }),
2056
2131
  ],
2057
2132
  ota: true,
2058
- configure: async (device, coordinatorEndpoint) => {
2059
- const endpoint = device.getEndpoint(1);
2060
- await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff", "genLevelCtrl"]);
2061
- await reporting.onOff(endpoint);
2062
- await chunkedRead(endpoint, Object.keys(VZM30_ATTRIBUTES), INOVELLI_CLUSTER_NAME);
2063
- // Bind for Button Event Reporting
2064
- const endpoint2 = device.getEndpoint(2);
2065
- await reporting.bind(endpoint2, coordinatorEndpoint, [INOVELLI_CLUSTER_NAME]);
2066
- },
2067
2133
  },
2068
2134
  {
2069
2135
  zigbeeModel: ["VZM31-SN"],
2070
2136
  model: "VZM31-SN",
2071
2137
  vendor: "Inovelli",
2072
2138
  description: "2-in-1 switch + dimmer",
2073
- exposes: exposesListVZM31.concat(m.identify().exposes),
2074
2139
  extend: [
2075
2140
  m.deviceEndpoints({
2076
2141
  endpoints: { "1": 1, "2": 2, "3": 3 },
2077
2142
  multiEndpointSkip: ["state", "power", "energy", "brightness"],
2078
2143
  }),
2144
+ inovelliExtend.inovelliLight(),
2145
+ inovelliExtend.inovelliDevice({
2146
+ attrs: [{ attributes: VZM31_ATTRIBUTES, clusterName: INOVELLI_CLUSTER_NAME }],
2147
+ supportsLedEffects: true,
2148
+ supportsButtonTaps: true,
2149
+ }),
2079
2150
  inovelliExtend.addCustomClusterInovelli(),
2151
+ m.identify(),
2080
2152
  m.electricityMeter({
2081
2153
  current: false,
2082
2154
  voltage: false,
@@ -2084,184 +2156,82 @@ exports.definitions = [
2084
2156
  energy: { min: 15, max: 3600, change: 0 },
2085
2157
  }),
2086
2158
  ],
2087
- toZigbee: [
2088
- tzLocal.light_onoff_brightness_inovelli,
2089
- tz.power_on_behavior,
2090
- tz.ignore_transition,
2091
- tz.identify,
2092
- tz.light_brightness_move,
2093
- tz.light_brightness_step,
2094
- tz.level_config,
2095
- tzLocal.inovelli_led_effect,
2096
- tzLocal.inovelli_individual_led_effect,
2097
- tzLocal.inovelli_parameters(VZM31_ATTRIBUTES, INOVELLI_CLUSTER_NAME),
2098
- tzLocal.inovelli_parameters_readOnly(VZM31_ATTRIBUTES, INOVELLI_CLUSTER_NAME),
2099
- ],
2100
- fromZigbee: [
2101
- fz.on_off,
2102
- fz.brightness,
2103
- fz.level_config,
2104
- fz.power_on_behavior,
2105
- fz.ignore_basic_report,
2106
- fzLocal.inovelli(VZM31_ATTRIBUTES, INOVELLI_CLUSTER_NAME),
2107
- fzLocal.led_effect_complete,
2108
- ],
2109
2159
  ota: true,
2110
- configure: async (device, coordinatorEndpoint) => {
2111
- const endpoint = device.getEndpoint(1);
2112
- await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff", "genLevelCtrl", INOVELLI_CLUSTER_NAME]);
2113
- await reporting.onOff(endpoint);
2114
- await chunkedRead(endpoint, Object.keys(VZM31_ATTRIBUTES), INOVELLI_CLUSTER_NAME);
2115
- // Bind for Button Event Reporting
2116
- const endpoint2 = device.getEndpoint(2);
2117
- await reporting.bind(endpoint2, coordinatorEndpoint, [INOVELLI_CLUSTER_NAME]);
2118
- },
2119
2160
  },
2120
2161
  {
2121
2162
  zigbeeModel: ["VZM32-SN"],
2122
2163
  model: "VZM32-SN",
2123
2164
  vendor: "Inovelli",
2124
2165
  description: "mmWave Zigbee Dimmer",
2125
- exposes: exposesListVZM32.concat(m.identify().exposes),
2166
+ exposes: [exposeMMWaveControl()],
2126
2167
  extend: [
2127
2168
  m.deviceEndpoints({
2128
2169
  endpoints: { "1": 1, "2": 2, "3": 3 },
2129
2170
  multiEndpointSkip: ["state", "voltage", "power", "current", "energy", "brightness", "illuminance", "occupancy"],
2130
2171
  }),
2172
+ inovelliExtend.inovelliLight(),
2173
+ inovelliExtend.inovelliDevice({
2174
+ attrs: [
2175
+ { attributes: VZM32_ATTRIBUTES, clusterName: INOVELLI_CLUSTER_NAME },
2176
+ { attributes: VZM32_MMWAVE_ATTRIBUTES, clusterName: INOVELLI_MMWAVE_CLUSTER_NAME },
2177
+ ],
2178
+ supportsLedEffects: true,
2179
+ supportsButtonTaps: true,
2180
+ }),
2131
2181
  inovelliExtend.addCustomClusterInovelli(),
2132
2182
  inovelliExtend.addCustomMMWaveClusterInovelli(),
2133
- m.electricityMeter(),
2183
+ m.identify(),
2184
+ m.electricityMeter({
2185
+ // Current and voltage were removed in version 0.8 of the firmware and expected to be restored in the future
2186
+ current: false,
2187
+ voltage: false,
2188
+ energy: { divisor: 1000 },
2189
+ }),
2134
2190
  m.illuminance(),
2135
2191
  m.occupancy(),
2136
2192
  ],
2137
- toZigbee: [
2138
- tzLocal.light_onoff_brightness_inovelli,
2139
- tz.power_on_behavior,
2140
- tz.ignore_transition,
2141
- tz.identify,
2142
- tz.light_brightness_move,
2143
- tz.light_brightness_step,
2144
- tz.level_config,
2145
- tzLocal.inovelli_led_effect,
2146
- tzLocal.inovelli_individual_led_effect,
2147
- tzLocal.inovelli_mmwave_control_commands,
2148
- tzLocal.inovelli_parameters(VZM32_ATTRIBUTES, INOVELLI_CLUSTER_NAME),
2149
- tzLocal.inovelli_parameters_readOnly(VZM32_ATTRIBUTES, INOVELLI_CLUSTER_NAME),
2150
- tzLocal.inovelli_parameters(VZM32_MMWAVE_ATTRIBUTES, INOVELLI_MMWAVE_CLUSTER_NAME),
2151
- tzLocal.inovelli_parameters_readOnly(VZM32_MMWAVE_ATTRIBUTES, INOVELLI_MMWAVE_CLUSTER_NAME),
2152
- ],
2153
- fromZigbee: [
2154
- fz.on_off,
2155
- fz.brightness,
2156
- fz.level_config,
2157
- fz.power_on_behavior,
2158
- fz.ignore_basic_report,
2159
- fzLocal.inovelli(VZM32_ATTRIBUTES, INOVELLI_CLUSTER_NAME),
2160
- fzLocal.inovelli(VZM32_MMWAVE_ATTRIBUTES, INOVELLI_MMWAVE_CLUSTER_NAME),
2161
- fzLocal.led_effect_complete,
2162
- ],
2193
+ toZigbee: [tzLocal.inovelli_mmwave_control_commands],
2163
2194
  ota: true,
2164
- configure: async (device, coordinatorEndpoint) => {
2165
- const endpoint = device.getEndpoint(1);
2166
- await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff", "genLevelCtrl", INOVELLI_CLUSTER_NAME]);
2167
- await reporting.onOff(endpoint);
2168
- await chunkedRead(endpoint, Object.keys(VZM32_ATTRIBUTES), INOVELLI_CLUSTER_NAME);
2169
- await chunkedRead(endpoint, Object.keys(VZM32_MMWAVE_ATTRIBUTES), INOVELLI_MMWAVE_CLUSTER_NAME);
2170
- // Bind for Button Event Reporting
2171
- const endpoint2 = device.getEndpoint(2);
2172
- await reporting.bind(endpoint2, coordinatorEndpoint, [INOVELLI_CLUSTER_NAME]);
2173
- },
2174
2195
  },
2175
2196
  {
2176
2197
  zigbeeModel: ["VZM35-SN"],
2177
2198
  model: "VZM35-SN",
2178
2199
  vendor: "Inovelli",
2179
2200
  description: "Fan controller",
2180
- fromZigbee: [
2181
- fzLocal.fan_state,
2182
- fzLocal.fan_mode(1),
2183
- fzLocal.breeze_mode(1),
2184
- fzLocal.inovelli(VZM35_ATTRIBUTES, INOVELLI_CLUSTER_NAME),
2185
- fzLocal.led_effect_complete,
2186
- ],
2187
- toZigbee: [
2188
- tz.identify,
2189
- tzLocal.fan_state,
2190
- tzLocal.fan_mode(1),
2191
- tzLocal.inovelli_led_effect,
2192
- tzLocal.inovelli_individual_led_effect,
2193
- tzLocal.inovelli_parameters(VZM35_ATTRIBUTES, INOVELLI_CLUSTER_NAME),
2194
- tzLocal.inovelli_parameters_readOnly(VZM35_ATTRIBUTES, INOVELLI_CLUSTER_NAME),
2195
- tzLocal.breezeMode(1),
2201
+ extend: [
2202
+ inovelliExtend.inovelliFan({ endpointId: 1 }),
2203
+ inovelliExtend.inovelliDevice({
2204
+ attrs: [{ attributes: VZM35_ATTRIBUTES, clusterName: INOVELLI_CLUSTER_NAME }],
2205
+ supportsLedEffects: true,
2206
+ supportsButtonTaps: true,
2207
+ }),
2208
+ inovelliExtend.addCustomClusterInovelli(),
2209
+ m.identify(),
2196
2210
  ],
2197
- exposes: exposesListVZM35.concat(m.identify().exposes),
2198
- extend: [inovelliExtend.addCustomClusterInovelli()],
2199
2211
  ota: true,
2200
- configure: async (device, coordinatorEndpoint) => {
2201
- const endpoint = device.getEndpoint(1);
2202
- await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff", "genLevelCtrl", INOVELLI_CLUSTER_NAME]);
2203
- await chunkedRead(endpoint, Object.keys(VZM35_ATTRIBUTES), INOVELLI_CLUSTER_NAME);
2204
- // Bind for Button Event Reporting
2205
- const endpoint2 = device.getEndpoint(2);
2206
- await reporting.bind(endpoint2, coordinatorEndpoint, [INOVELLI_CLUSTER_NAME]);
2207
- },
2208
2212
  },
2209
2213
  {
2210
2214
  zigbeeModel: ["VZM36"],
2211
2215
  model: "VZM36",
2212
2216
  vendor: "Inovelli",
2213
2217
  description: "Fan canopy module",
2214
- fromZigbee: [
2215
- fzLocal.brightness,
2216
- fzLocal.vzm36_fan_light_state,
2217
- fzLocal.fan_mode(2),
2218
- fzLocal.breeze_mode(2),
2219
- fzLocal.inovelli(VZM36_ATTRIBUTES, INOVELLI_CLUSTER_NAME, true),
2220
- ],
2218
+ fromZigbee: [fzLocal.brightness, fzLocal.vzm36_fan_light_state],
2221
2219
  toZigbee: [
2222
- tz.identify,
2223
2220
  tzLocal.vzm36_fan_on_off, // Need to use VZM36 specific converter
2224
- tz.light_brightness_move,
2225
- tz.light_brightness_step,
2226
- tz.level_config,
2227
- tzLocal.fan_mode(2),
2228
- tzLocal.light_onoff_brightness_inovelli,
2229
- tzLocal.inovelli_parameters(VZM36_ATTRIBUTES, INOVELLI_CLUSTER_NAME),
2230
- tzLocal.inovelli_parameters_readOnly(VZM36_ATTRIBUTES, INOVELLI_CLUSTER_NAME),
2231
- tzLocal.breezeMode(2),
2232
2221
  ],
2233
- exposes: exposesListVZM36.concat(m.identify().exposes),
2234
- extend: [inovelliExtend.addCustomClusterInovelli()],
2222
+ extend: [
2223
+ inovelliExtend.inovelliLight({ splitValuesByEndpoint: true }),
2224
+ inovelliExtend.inovelliFan({ endpointId: 2, splitValuesByEndpoint: true }),
2225
+ inovelliExtend.inovelliDevice({
2226
+ attrs: [{ attributes: VZM36_ATTRIBUTES, clusterName: INOVELLI_CLUSTER_NAME }],
2227
+ supportsLedEffects: false,
2228
+ splitValuesByEndpoint: true,
2229
+ supportsButtonTaps: false,
2230
+ }),
2231
+ inovelliExtend.addCustomClusterInovelli(),
2232
+ m.identify(),
2233
+ ],
2235
2234
  ota: true,
2236
- // The configure method below is needed to make the device reports on/off state changes
2237
- // when the device is controlled manually through the button on it.
2238
- configure: async (device, coordinatorEndpoint) => {
2239
- const endpoint = device.getEndpoint(1);
2240
- await reporting.bind(endpoint, coordinatorEndpoint, ["genOnOff"]);
2241
- await reporting.onOff(endpoint);
2242
- await chunkedRead(endpoint, Object.keys(VZM36_ATTRIBUTES).flatMap((key) => {
2243
- const keysplit = key.split("_");
2244
- if (keysplit.length === 2) {
2245
- if (Number(keysplit[1]) === 1) {
2246
- return [keysplit[0]];
2247
- }
2248
- return [];
2249
- }
2250
- return [key];
2251
- }), INOVELLI_CLUSTER_NAME);
2252
- const endpoint2 = device.getEndpoint(2);
2253
- await reporting.bind(endpoint2, coordinatorEndpoint, ["genOnOff"]);
2254
- await reporting.onOff(endpoint2);
2255
- await chunkedRead(endpoint2, Object.keys(VZM36_ATTRIBUTES).flatMap((key) => {
2256
- const keysplit = key.split("_");
2257
- if (keysplit.length === 2) {
2258
- if (Number(keysplit[1]) === 2) {
2259
- return [keysplit[0]];
2260
- }
2261
- }
2262
- return [];
2263
- }), INOVELLI_CLUSTER_NAME);
2264
- },
2265
2235
  },
2266
2236
  ];
2267
2237
  //# sourceMappingURL=inovelli.js.map