zigbee-herdsman-converters 25.9.0 → 25.11.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 (38) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/dist/devices/bosch.d.ts.map +1 -1
  3. package/dist/devices/bosch.js +379 -54
  4. package/dist/devices/bosch.js.map +1 -1
  5. package/dist/devices/custom_devices_diy.d.ts.map +1 -1
  6. package/dist/devices/custom_devices_diy.js +11 -3
  7. package/dist/devices/custom_devices_diy.js.map +1 -1
  8. package/dist/devices/giex.js +2 -2
  9. package/dist/devices/innr.d.ts.map +1 -1
  10. package/dist/devices/innr.js +7 -0
  11. package/dist/devices/innr.js.map +1 -1
  12. package/dist/devices/inovelli.d.ts.map +1 -1
  13. package/dist/devices/inovelli.js +201 -223
  14. package/dist/devices/inovelli.js.map +1 -1
  15. package/dist/devices/lumi.d.ts.map +1 -1
  16. package/dist/devices/lumi.js +7 -2
  17. package/dist/devices/lumi.js.map +1 -1
  18. package/dist/devices/onokom.d.ts.map +1 -1
  19. package/dist/devices/onokom.js +621 -51
  20. package/dist/devices/onokom.js.map +1 -1
  21. package/dist/devices/philips.d.ts.map +1 -1
  22. package/dist/devices/philips.js +17 -2
  23. package/dist/devices/philips.js.map +1 -1
  24. package/dist/devices/seastar_intelligence.js +1 -1
  25. package/dist/devices/seastar_intelligence.js.map +1 -1
  26. package/dist/devices/slacky_diy.d.ts.map +1 -1
  27. package/dist/devices/slacky_diy.js +249 -2
  28. package/dist/devices/slacky_diy.js.map +1 -1
  29. package/dist/devices/sprut.d.ts.map +1 -1
  30. package/dist/devices/sprut.js +124 -0
  31. package/dist/devices/sprut.js.map +1 -1
  32. package/dist/devices/tuya.d.ts.map +1 -1
  33. package/dist/devices/tuya.js +12 -6
  34. package/dist/devices/tuya.js.map +1 -1
  35. package/dist/index.js +2 -2
  36. package/dist/index.js.map +1 -1
  37. package/dist/models-index.json +1 -1
  38. package/package.json +1 -1
@@ -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,138 @@ 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
+ },
384
+ inovelliMMWave: () => {
385
+ return {
386
+ fromZigbee: [],
387
+ toZigbee: [tzLocal.inovelli_mmwave_control_commands],
388
+ exposes: [exposeMMWaveControl()],
389
+ configure: [],
390
+ isModernExtend: true,
391
+ };
392
+ },
264
393
  };
265
- const fanModes = { off: 0, low: 2, smart: 4, medium: 86, high: 170, on: 255 };
266
- const breezemodes = ["off", "low", "medium", "high"];
394
+ const FAN_MODES = { off: 0, low: 2, smart: 4, medium: 86, high: 170, on: 255 };
395
+ const BREEZE_MODES = ["off", "low", "medium", "high"];
267
396
  const LED_NOTIFICATION_TYPES = {
268
397
  0: "LED_1",
269
398
  1: "LED_2",
@@ -273,19 +402,19 @@ const LED_NOTIFICATION_TYPES = {
273
402
  5: "LED_6",
274
403
  6: "LED_7",
275
404
  16: "ALL_LEDS",
276
- 255: "CONFIG_BUTTON_DOUBLE_PRESS",
405
+ "-1": "CONFIG_BUTTON_DOUBLE_PRESS",
277
406
  };
278
407
  const INOVELLI = 0x122f;
279
408
  // Converts brightness level to a fan mode
280
409
  const intToFanMode = (value) => {
281
410
  let selectedMode = "low";
282
- if (value >= fanModes.low) {
411
+ if (value >= FAN_MODES.low) {
283
412
  selectedMode = "low";
284
413
  }
285
- if (value >= fanModes.medium) {
414
+ if (value >= FAN_MODES.medium) {
286
415
  selectedMode = "medium";
287
416
  }
288
- if (value >= fanModes.high) {
417
+ if (value >= FAN_MODES.high) {
289
418
  selectedMode = "high";
290
419
  }
291
420
  if (value === 4) {
@@ -1275,7 +1404,7 @@ const VZM32_MMWAVE_ATTRIBUTES = {
1275
1404
  min: 0,
1276
1405
  max: 600,
1277
1406
  readOnly: false,
1278
- description: "Defines the detection area in front of the switch)",
1407
+ description: "Defines the detection area in front of the switch",
1279
1408
  },
1280
1409
  mmWaveDepthMax: {
1281
1410
  ID: 106,
@@ -1283,7 +1412,7 @@ const VZM32_MMWAVE_ATTRIBUTES = {
1283
1412
  min: 0,
1284
1413
  max: 600,
1285
1414
  readOnly: false,
1286
- description: "Defines the detection area in front of the switch)",
1415
+ description: "Defines the detection area in front of the switch",
1287
1416
  },
1288
1417
  };
1289
1418
  const VZM35_ATTRIBUTES = {
@@ -1587,7 +1716,7 @@ const tzLocal = {
1587
1716
  ...meta,
1588
1717
  message: {
1589
1718
  ...meta.message,
1590
- transition: (!transition.specified ? 0xffff : Math.round(transition.time)) / 10,
1719
+ transition: (!transition.specified ? 0xffff : transition.time) / 10,
1591
1720
  },
1592
1721
  converterOptions: {
1593
1722
  ctrlbits: 0,
@@ -1604,7 +1733,7 @@ const tzLocal = {
1604
1733
  utils.assertString(value);
1605
1734
  const endpoint = meta.device.getEndpoint(endpointId);
1606
1735
  await endpoint.command("genLevelCtrl", "moveToLevelWithOnOff", {
1607
- level: fanModes[value],
1736
+ level: FAN_MODES[value],
1608
1737
  transtime: 0xffff,
1609
1738
  }, utils.getOptions(meta.mapped, entity));
1610
1739
  meta.state[key] = value;
@@ -1828,11 +1957,11 @@ const fzLocal = {
1828
1957
  if (msg.data.breeze_mode !== undefined) {
1829
1958
  const bitmasks = [3, 60, 192, 3840, 12288, 245760, 786432, 15728640, 50331648, 1006632960];
1830
1959
  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];
1960
+ const s1 = BREEZE_MODES[raw & bitmasks[0]];
1961
+ const s2 = BREEZE_MODES[(raw & bitmasks[2]) / 64];
1962
+ const s3 = BREEZE_MODES[(raw & bitmasks[4]) / 4096];
1963
+ const s4 = BREEZE_MODES[(raw & bitmasks[6]) / 262144];
1964
+ const s5 = BREEZE_MODES[(raw & bitmasks[8]) / 16777216];
1836
1965
  const d1 = ((raw & bitmasks[1]) / 4) * 5;
1837
1966
  const d2 = ((raw & bitmasks[3]) / 256) * 5;
1838
1967
  const d3 = ((raw & bitmasks[5]) / 16384) * 5;
@@ -1948,36 +2077,11 @@ const exposeMMWaveControl = () => {
1948
2077
  };
1949
2078
  const exposeLedEffectComplete = () => {
1950
2079
  return e
1951
- .enum("notificationComplete", ea.STATE_GET, Object.values(LED_NOTIFICATION_TYPES))
2080
+ .enum("notificationComplete", ea.STATE, Object.values(LED_NOTIFICATION_TYPES))
1952
2081
  .withDescription("Indication that a specific notification has completed.")
1953
2082
  .withCategory("diagnostic");
1954
2083
  };
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 = [
2084
+ const BUTTON_TAP_SEQUENCES = [
1981
2085
  "down_single",
1982
2086
  "up_single",
1983
2087
  "config_single",
@@ -2000,10 +2104,6 @@ const buttonTapSequences = [
2000
2104
  "up_quintuple",
2001
2105
  "config_quintuple",
2002
2106
  ];
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
2107
  /*
2008
2108
  * Inovelli devices have a huge number of attributes. Calling endpoint.read() in a single call
2009
2109
  * for all attributes causes timeouts even with the timeout set to an absurdly high number (2 minutes)
@@ -2021,62 +2121,43 @@ exports.definitions = [
2021
2121
  model: "VZM30-SN",
2022
2122
  vendor: "Inovelli",
2023
2123
  description: "On/off switch",
2024
- exposes: exposesListVZM30.concat(m.identify().exposes),
2025
2124
  extend: [
2026
2125
  m.deviceEndpoints({
2027
2126
  endpoints: { "1": 1, "2": 2, "3": 3, "4": 4 },
2028
2127
  multiEndpointSkip: ["state", "voltage", "power", "current", "energy", "brightness", "temperature", "humidity"],
2029
2128
  }),
2129
+ inovelliExtend.inovelliLight(),
2130
+ inovelliExtend.inovelliDevice({
2131
+ attrs: [{ attributes: VZM30_ATTRIBUTES, clusterName: INOVELLI_CLUSTER_NAME }],
2132
+ supportsLedEffects: true,
2133
+ supportsButtonTaps: true,
2134
+ }),
2030
2135
  inovelliExtend.addCustomClusterInovelli(),
2136
+ m.identify(),
2031
2137
  m.temperature(),
2032
2138
  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,
2139
+ m.electricityMeter({ energy: { divisor: 1000 } }),
2056
2140
  ],
2057
2141
  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
2142
  },
2068
2143
  {
2069
2144
  zigbeeModel: ["VZM31-SN"],
2070
2145
  model: "VZM31-SN",
2071
2146
  vendor: "Inovelli",
2072
2147
  description: "2-in-1 switch + dimmer",
2073
- exposes: exposesListVZM31.concat(m.identify().exposes),
2074
2148
  extend: [
2075
2149
  m.deviceEndpoints({
2076
2150
  endpoints: { "1": 1, "2": 2, "3": 3 },
2077
2151
  multiEndpointSkip: ["state", "power", "energy", "brightness"],
2078
2152
  }),
2153
+ inovelliExtend.inovelliLight(),
2154
+ inovelliExtend.inovelliDevice({
2155
+ attrs: [{ attributes: VZM31_ATTRIBUTES, clusterName: INOVELLI_CLUSTER_NAME }],
2156
+ supportsLedEffects: true,
2157
+ supportsButtonTaps: true,
2158
+ }),
2079
2159
  inovelliExtend.addCustomClusterInovelli(),
2160
+ m.identify(),
2080
2161
  m.electricityMeter({
2081
2162
  current: false,
2082
2163
  voltage: false,
@@ -2084,184 +2165,81 @@ exports.definitions = [
2084
2165
  energy: { min: 15, max: 3600, change: 0 },
2085
2166
  }),
2086
2167
  ],
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
2168
  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
2169
  },
2120
2170
  {
2121
2171
  zigbeeModel: ["VZM32-SN"],
2122
2172
  model: "VZM32-SN",
2123
2173
  vendor: "Inovelli",
2124
2174
  description: "mmWave Zigbee Dimmer",
2125
- exposes: exposesListVZM32.concat(m.identify().exposes),
2126
2175
  extend: [
2127
2176
  m.deviceEndpoints({
2128
2177
  endpoints: { "1": 1, "2": 2, "3": 3 },
2129
2178
  multiEndpointSkip: ["state", "voltage", "power", "current", "energy", "brightness", "illuminance", "occupancy"],
2130
2179
  }),
2180
+ inovelliExtend.inovelliLight(),
2181
+ inovelliExtend.inovelliDevice({
2182
+ attrs: [
2183
+ { attributes: VZM32_ATTRIBUTES, clusterName: INOVELLI_CLUSTER_NAME },
2184
+ { attributes: VZM32_MMWAVE_ATTRIBUTES, clusterName: INOVELLI_MMWAVE_CLUSTER_NAME },
2185
+ ],
2186
+ supportsLedEffects: true,
2187
+ supportsButtonTaps: true,
2188
+ }),
2189
+ inovelliExtend.inovelliMMWave(),
2131
2190
  inovelliExtend.addCustomClusterInovelli(),
2132
2191
  inovelliExtend.addCustomMMWaveClusterInovelli(),
2133
- m.electricityMeter(),
2192
+ m.identify(),
2193
+ m.electricityMeter({
2194
+ // Current and voltage were removed in version 0.8 of the firmware and expected to be restored in the future
2195
+ current: false,
2196
+ voltage: false,
2197
+ energy: { divisor: 1000 },
2198
+ }),
2134
2199
  m.illuminance(),
2135
2200
  m.occupancy(),
2136
2201
  ],
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
- ],
2163
2202
  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
2203
  },
2175
2204
  {
2176
2205
  zigbeeModel: ["VZM35-SN"],
2177
2206
  model: "VZM35-SN",
2178
2207
  vendor: "Inovelli",
2179
2208
  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),
2209
+ extend: [
2210
+ inovelliExtend.inovelliFan({ endpointId: 1 }),
2211
+ inovelliExtend.inovelliDevice({
2212
+ attrs: [{ attributes: VZM35_ATTRIBUTES, clusterName: INOVELLI_CLUSTER_NAME }],
2213
+ supportsLedEffects: true,
2214
+ supportsButtonTaps: true,
2215
+ }),
2216
+ inovelliExtend.addCustomClusterInovelli(),
2217
+ m.identify(),
2196
2218
  ],
2197
- exposes: exposesListVZM35.concat(m.identify().exposes),
2198
- extend: [inovelliExtend.addCustomClusterInovelli()],
2199
2219
  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
2220
  },
2209
2221
  {
2210
2222
  zigbeeModel: ["VZM36"],
2211
2223
  model: "VZM36",
2212
2224
  vendor: "Inovelli",
2213
2225
  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
- ],
2226
+ fromZigbee: [fzLocal.brightness, fzLocal.vzm36_fan_light_state],
2221
2227
  toZigbee: [
2222
- tz.identify,
2223
2228
  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
2229
  ],
2233
- exposes: exposesListVZM36.concat(m.identify().exposes),
2234
- extend: [inovelliExtend.addCustomClusterInovelli()],
2230
+ extend: [
2231
+ inovelliExtend.inovelliLight({ splitValuesByEndpoint: true }),
2232
+ inovelliExtend.inovelliFan({ endpointId: 2, splitValuesByEndpoint: true }),
2233
+ inovelliExtend.inovelliDevice({
2234
+ attrs: [{ attributes: VZM36_ATTRIBUTES, clusterName: INOVELLI_CLUSTER_NAME }],
2235
+ supportsLedEffects: false,
2236
+ splitValuesByEndpoint: true,
2237
+ supportsButtonTaps: false,
2238
+ }),
2239
+ inovelliExtend.addCustomClusterInovelli(),
2240
+ m.identify(),
2241
+ ],
2235
2242
  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
2243
  },
2266
2244
  ];
2267
2245
  //# sourceMappingURL=inovelli.js.map