zigbee-herdsman-converters 15.0.13 → 15.0.15

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.
@@ -5444,7 +5444,7 @@ const converters = {
5444
5444
  61: 'all',
5445
5445
  };
5446
5446
  }
5447
- if (['WS-USC02'].includes(model.model)) {
5447
+ if (['WS-USC02', 'WS-USC04'].includes(model.model)) {
5448
5448
  buttonLookup = {41: 'top', 42: 'bottom', 51: 'both'};
5449
5449
  }
5450
5450
 
@@ -2139,6 +2139,7 @@ const converters = {
2139
2139
  if (['SP-EUC01', 'ZNCZ04LM', 'ZNCZ12LM', 'ZNCZ15LM', 'QBCZ14LM', 'QBCZ15LM', 'SSM-U01', 'SSM-U02', 'DLKZMK11LM', 'DLKZMK12LM',
2140
2140
  'WS-EUK01', 'WS-EUK02', 'WS-EUK03', 'WS-EUK04', 'QBKG19LM', 'QBKG20LM', 'QBKG25LM', 'QBKG26LM',
2141
2141
  'QBKG31LM', 'QBKG34LM', 'QBKG38LM', 'QBKG39LM', 'QBKG40LM', 'QBKG41LM', 'ZNDDMK11LM', 'ZNLDP13LM',
2142
+ 'WS-USC02', 'WS-USC04',
2142
2143
  ].includes(meta.mapped.model)) {
2143
2144
  await entity.write('aqaraOpple', {0x0201: {value: value ? 1 : 0, type: 0x10}}, manufacturerOptions.xiaomi);
2144
2145
  } else if (['ZNCZ02LM', 'QBCZ11LM', 'LLKZMK11LM'].includes(meta.mapped.model)) {
@@ -2163,6 +2164,7 @@ const converters = {
2163
2164
  if (['SP-EUC01', 'ZNCZ04LM', 'ZNCZ12LM', 'ZNCZ15LM', 'QBCZ14LM', 'QBCZ15LM', 'SSM-U01', 'SSM-U02', 'DLKZMK11LM', 'DLKZMK12LM',
2164
2165
  'WS-EUK01', 'WS-EUK02', 'WS-EUK03', 'WS-EUK04', 'QBKG19LM', 'QBKG20LM', 'QBKG25LM', 'QBKG26LM',
2165
2166
  'QBKG31LM', 'QBKG34LM', 'QBKG38LM', 'QBKG39LM', 'QBKG40LM', 'QBKG41LM', 'ZNDDMK11LM', 'ZNLDP13LM',
2167
+ 'WS-USC02', 'WS-USC04',
2166
2168
  ].includes(meta.mapped.model)) {
2167
2169
  await entity.read('aqaraOpple', [0x0201]);
2168
2170
  } else if (['ZNCZ02LM', 'QBCZ11LM', 'ZNCZ11LM'].includes(meta.mapped.model)) {
@@ -22,7 +22,7 @@ module.exports = [
22
22
  vendor: 'BlitzWolf',
23
23
  description: 'Zigbee 3.0 smart light switch module 1 gang',
24
24
  extend: extend.switch(),
25
- toZigbee: [tz.TYZB01_on_off],
25
+ toZigbee: [tz.TYZB01_on_off, tz.power_on_behavior],
26
26
  configure: async (device, coordinatorEndpoint, logger) => {
27
27
  await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
28
28
  },
@@ -340,4 +340,20 @@ module.exports = [
340
340
  await reporting.activePower(endpoint, {change: 2});
341
341
  },
342
342
  },
343
+ {
344
+ zigbeeModel: ['3315-Geu'],
345
+ model: '3315-Geu',
346
+ vendor: 'Centralite',
347
+ description: 'Water sensor',
348
+ fromZigbee: [fz.temperature, fz.ias_water_leak_alarm_1, fz.battery],
349
+ exposes: [e.temperature(), e.water_leak(), e.battery_low(), e.tamper(), e.battery()],
350
+ toZigbee: [],
351
+ meta: {battery: {voltageToPercentage: '3V_2500'}},
352
+ configure: async (device, coordinatorEndpoint, logger) => {
353
+ const endpoint = device.getEndpoint(1);
354
+ await reporting.bind(endpoint, coordinatorEndpoint, ['msTemperatureMeasurement', 'genPowerCfg']);
355
+ await reporting.temperature(endpoint);
356
+ await reporting.batteryVoltage(endpoint);
357
+ },
358
+ },
343
359
  ];
package/devices/heiman.js CHANGED
@@ -476,7 +476,7 @@ module.exports = [
476
476
  },
477
477
  },
478
478
  {
479
- zigbeeModel: ['GASSensor-EM'],
479
+ zigbeeModel: ['GASSensor-EM', '358e4e3e03c644709905034dae81433e'],
480
480
  model: 'HS1CG-E',
481
481
  vendor: 'HEIMAN',
482
482
  description: 'Combustible gas sensor',
package/devices/ikea.js CHANGED
@@ -602,11 +602,6 @@ module.exports = [
602
602
  description: 'TRADFRI control outlet',
603
603
  vendor: 'IKEA',
604
604
  extend: extend.switch(),
605
- toZigbee: extend.switch().toZigbee.concat([tz.power_on_behavior]),
606
- fromZigbee: extend.switch().fromZigbee.concat([fz.power_on_behavior]),
607
- // power_on_behavior 'toggle' does not seem to be supported
608
- exposes: extend.switch().exposes.concat([exposes.enum('power_on_behavior', ea.ALL, ['off', 'previous', 'on'])
609
- .withDescription('Controls the behaviour when the device is powered on')]),
610
605
  configure: async (device, coordinatorEndpoint, logger) => {
611
606
  const endpoint = device.getEndpoint(1);
612
607
  await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
package/devices/iris.js CHANGED
@@ -177,20 +177,4 @@ module.exports = [
177
177
  await reporting.batteryVoltage(endpoint);
178
178
  },
179
179
  },
180
- {
181
- zigbeeModel: ['3315-Geu'],
182
- model: '3315-Geu',
183
- vendor: 'Iris',
184
- description: 'Water sensor',
185
- fromZigbee: [fz.temperature, fz.ias_water_leak_alarm_1, fz.battery],
186
- exposes: [e.temperature(), e.water_leak(), e.battery_low(), e.tamper(), e.battery()],
187
- toZigbee: [],
188
- meta: {battery: {voltageToPercentage: '3V_2500'}},
189
- configure: async (device, coordinatorEndpoint, logger) => {
190
- const endpoint = device.getEndpoint(1);
191
- await reporting.bind(endpoint, coordinatorEndpoint, ['msTemperatureMeasurement', 'genPowerCfg']);
192
- await reporting.temperature(endpoint);
193
- await reporting.batteryVoltage(endpoint);
194
- },
195
- },
196
180
  ];
@@ -130,7 +130,9 @@ module.exports = [
130
130
  await reporting.bind(endpoint, coordinatorEndpoint, ['genBinaryInput', 'closuresWindowCovering', 'genIdentify']);
131
131
  await reporting.currentPositionLiftPercentage(endpoint);
132
132
  },
133
- exposes: [e.cover_position()],
133
+ exposes: [e.cover_position(),
134
+ exposes.binary('led_in_dark', ea.ALL, 'ON', 'OFF').withDescription(`Enables the LED when the power socket is turned off,
135
+ allowing to see it in the dark`)],
134
136
  },
135
137
  {
136
138
  // swbuildid 001a requires coverInverted: https://github.com/Koenkk/zigbee2mqtt/issues/15101#issuecomment-1356787490
@@ -260,8 +262,8 @@ module.exports = [
260
262
  description: 'Wired micromodule switch',
261
263
  extend: extend.switch(),
262
264
  ota: ota.zigbeeOTA,
263
- fromZigbee: [fz.identify, fz.on_off],
264
- toZigbee: [tz.on_off, tz.legrand_identify],
265
+ fromZigbee: [...extend.switch().fromZigbee, fz.identify],
266
+ toZigbee: [...extend.switch().toZigbee, tz.legrand_identify],
265
267
  whiteLabel: [{vendor: 'BTicino', model: '3584C'}],
266
268
  configure: async (device, coordinatorEndpoint, logger) => {
267
269
  const endpoint = device.getEndpoint(1);
@@ -426,4 +428,23 @@ module.exports = [
426
428
  await reporting.activePower(endpoint);
427
429
  },
428
430
  },
431
+ {
432
+ zigbeeModel: ['Remote dimmer switch'],
433
+ model: 'WNAL63',
434
+ vendor: 'Legrand',
435
+ // led blink RED when battery is low
436
+ description: 'Remote dimmer switch',
437
+ fromZigbee: [fz.identify, fz.command_on, fz.command_off, fz.command_toggle, fz.legacy.cmd_move, fz.legacy.cmd_stop,
438
+ fz.battery],
439
+ exposes: [e.battery(), e.action(['identify', 'on', 'off', 'toggle', 'brightness_move_up',
440
+ 'brightness_move_down', 'brightness_stop'])],
441
+ toZigbee: [],
442
+ meta: {battery: {voltageToPercentage: '3V_2500'}, publishDuplicateTransaction: true},
443
+ onEvent: readInitialBatteryState,
444
+ configure: async (device, coordinatorEndpoint, logger) => {
445
+ await extend.light_onoff_brightness().configure(device, coordinatorEndpoint, logger);
446
+ const endpoint = device.getEndpoint(1);
447
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genIdentify', 'genOnOff', 'genLevelCtrl']);
448
+ },
449
+ },
429
450
  ];
@@ -157,10 +157,6 @@ module.exports = [
157
157
  vendor: 'Linkind',
158
158
  description: 'Control outlet',
159
159
  extend: extend.switch(),
160
- toZigbee: extend.switch().toZigbee.concat([tz.power_on_behavior]),
161
- fromZigbee: extend.switch().fromZigbee.concat([fz.power_on_behavior]),
162
- exposes: extend.switch().exposes.concat([exposes.enum('power_on_behavior', ea.ALL, ['off', 'previous', 'on', 'toggle'])
163
- .withDescription('Controls the behaviour when the device is powered on')]),
164
160
  configure: async (device, coordinatorEndpoint, logger) => {
165
161
  const endpoint = device.getEndpoint(1);
166
162
  await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
package/devices/livolo.js CHANGED
@@ -65,8 +65,8 @@ module.exports = [
65
65
  model: 'TI0001-switch',
66
66
  description: 'Zigbee switch 1 gang',
67
67
  vendor: 'Livolo',
68
- fromZigbee: [fz.livolo_new_switch_state],
69
- toZigbee: [tz.livolo_socket_switch_on_off],
68
+ fromZigbee: [fz.livolo_new_switch_state, fz.power_on_behavior],
69
+ toZigbee: [tz.livolo_socket_switch_on_off, tz.power_on_behavior],
70
70
  extend: extend.switch(),
71
71
  configure: poll,
72
72
  endpoint: (device) => {
@@ -151,8 +151,8 @@ module.exports = [
151
151
  description: 'Zigbee socket',
152
152
  vendor: 'Livolo',
153
153
  extend: extend.switch(),
154
- fromZigbee: [fz.livolo_socket_state],
155
- toZigbee: [tz.livolo_socket_switch_on_off],
154
+ fromZigbee: [fz.livolo_socket_state, fz.power_on_behavior],
155
+ toZigbee: [tz.livolo_socket_switch_on_off, tz.power_on_behavior],
156
156
  configure: poll,
157
157
  onEvent: async (type, data, device) => {
158
158
  if (type === 'stop') {
@@ -205,7 +205,7 @@ module.exports = [
205
205
  vendor: 'Lonsonho',
206
206
  description: '1 gang switch module with neutral wire',
207
207
  extend: extend.switch(),
208
- toZigbee: [tz.TYZB01_on_off],
208
+ toZigbee: [tz.power_on_behavior, tz.TYZB01_on_off],
209
209
  configure: async (device, coordinatorEndpoint, logger) => {
210
210
  await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
211
211
  },
@@ -75,8 +75,8 @@ const hueExtend = {
75
75
  return result;
76
76
  },
77
77
  light_onoff_brightness_colortemp_color_gradient: (options={}) => {
78
- options = {supportsHS: true, disableEffect: true, noConfigure: true, extraEffects: [], ...options};
79
- const result = extendDontUse.light_onoff_brightness_colortemp_color({supportsHS: true, ...options});
78
+ options = {supportsHS: true, disableEffect: true, extraEffects: [], ...options};
79
+ const result = extendDontUse.light_onoff_brightness_colortemp_color({noConfigure: true, ...options});
80
80
  result['ota'] = ota.zigbeeOTA;
81
81
  result['meta'] = {turnsOffAtBrightness1: true};
82
82
  result['toZigbee'] = result['toZigbee'].concat([
@@ -458,7 +458,7 @@ module.exports = [
458
458
  model: '929002994901',
459
459
  vendor: 'Philips',
460
460
  description: 'Hue gradient lightstrip',
461
- extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
461
+ extend: hueExtend.light_onoff_brightness_colortemp_color_gradient({colorTempRange: [153, 500]}),
462
462
  },
463
463
  {
464
464
  zigbeeModel: ['929003045401'],
@@ -642,6 +642,13 @@ module.exports = [
642
642
  description: 'Hue white E27 LED bulb filament giant globe',
643
643
  extend: hueExtend.light_onoff_brightness(),
644
644
  },
645
+ {
646
+ zigbeeModel: ['LWO004'],
647
+ model: '8719514279155',
648
+ vendor: 'Philips',
649
+ description: 'Hue white G125 B22 LED bulb filament giant globe',
650
+ extend: hueExtend.light_onoff_brightness(),
651
+ },
645
652
  {
646
653
  zigbeeModel: ['LTD011'],
647
654
  model: '5110131H5',
@@ -789,6 +796,13 @@ module.exports = [
789
796
  description: 'Hue white E12',
790
797
  extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
791
798
  },
799
+ {
800
+ zigbeeModel: ['LTE004'],
801
+ model: '9290031451',
802
+ vendor: 'Philips',
803
+ description: 'Hue white ambiance filament E12 with Bluetooth',
804
+ extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
805
+ },
792
806
  {
793
807
  zigbeeModel: ['LWA007'],
794
808
  model: '929002277501',
@@ -1071,6 +1085,13 @@ module.exports = [
1071
1085
  description: 'Hue white A60 bulb B22 bluetooth',
1072
1086
  extend: hueExtend.light_onoff_brightness(),
1073
1087
  },
1088
+ {
1089
+ zigbeeModel: ['929003047001'],
1090
+ model: '929003047001',
1091
+ vendor: 'Philips',
1092
+ description: 'Hue White ambiance Milliskin (round)',
1093
+ extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
1094
+ },
1074
1095
  {
1075
1096
  zigbeeModel: ['LWA017'],
1076
1097
  model: '929002469202',
@@ -1209,7 +1230,7 @@ module.exports = [
1209
1230
  model: '8718699703424',
1210
1231
  vendor: 'Philips',
1211
1232
  description: 'Hue white and color ambiance LightStrip plus',
1212
- extend: hueExtend.light_onoff_brightness_colortemp_color(),
1233
+ extend: hueExtend.light_onoff_brightness_colortemp_color({disableHueEffects: false}),
1213
1234
  },
1214
1235
  {
1215
1236
  zigbeeModel: ['LCL002'],
@@ -1960,14 +1981,14 @@ module.exports = [
1960
1981
  model: '915005986901',
1961
1982
  vendor: 'Philips',
1962
1983
  description: 'Hue White and color ambiance Gradient Signe table lamp (white)',
1963
- extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
1984
+ extend: hueExtend.light_onoff_brightness_colortemp_color_gradient({colorTempRange: [153, 500]}),
1964
1985
  },
1965
1986
  {
1966
1987
  zigbeeModel: ['915005987001'],
1967
1988
  model: '915005987001',
1968
1989
  vendor: 'Philips',
1969
1990
  description: 'Hue White and color ambiance Gradient Signe table lamp (black)',
1970
- extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
1991
+ extend: hueExtend.light_onoff_brightness_colortemp_color_gradient({colorTempRange: [153, 500]}),
1971
1992
  },
1972
1993
  {
1973
1994
  zigbeeModel: ['5060730P7_01', '5060730P7_02', '5060730P7_03', '5060730P7_04', '5060730P7_05'],
@@ -2336,7 +2357,7 @@ module.exports = [
2336
2357
  model: '929002240401',
2337
2358
  vendor: 'Philips',
2338
2359
  description: 'Hue smart plug - EU',
2339
- extend: extend.switch(),
2360
+ extend: extend.switch({disablePowerOnBehavior: true}),
2340
2361
  toZigbee: [tz.on_off].concat([tzLocal.hue_power_on_behavior, tzLocal.hue_power_on_error]),
2341
2362
  configure: async (device, coordinatorEndpoint, logger) => {
2342
2363
  const endpoint = device.getEndpoint(11);
@@ -2350,7 +2371,7 @@ module.exports = [
2350
2371
  model: '046677552343',
2351
2372
  vendor: 'Philips',
2352
2373
  description: 'Hue smart plug bluetooth',
2353
- extend: extend.switch(),
2374
+ extend: extend.switch({disablePowerOnBehavior: true}),
2354
2375
  toZigbee: [tz.on_off].concat([tzLocal.hue_power_on_behavior, tzLocal.hue_power_on_error]),
2355
2376
  configure: async (device, coordinatorEndpoint, logger) => {
2356
2377
  const endpoint = device.getEndpoint(11);
@@ -2364,7 +2385,7 @@ module.exports = [
2364
2385
  model: '8718699689308',
2365
2386
  vendor: 'Philips',
2366
2387
  description: 'Hue smart plug - UK',
2367
- extend: extend.switch(),
2388
+ extend: extend.switch({disablePowerOnBehavior: true}),
2368
2389
  toZigbee: [tz.on_off].concat([tzLocal.hue_power_on_behavior, tzLocal.hue_power_on_error]),
2369
2390
  configure: async (device, coordinatorEndpoint, logger) => {
2370
2391
  const endpoint = device.getEndpoint(11);
@@ -2378,7 +2399,7 @@ module.exports = [
2378
2399
  model: '9290022408',
2379
2400
  vendor: 'Philips',
2380
2401
  description: 'Hue smart plug - AU',
2381
- extend: extend.switch(),
2402
+ extend: extend.switch({disablePowerOnBehavior: true}),
2382
2403
  toZigbee: [tz.on_off].concat([tzLocal.hue_power_on_behavior, tzLocal.hue_power_on_error]),
2383
2404
  configure: async (device, coordinatorEndpoint, logger) => {
2384
2405
  const endpoint = device.getEndpoint(11);
@@ -2392,7 +2413,7 @@ module.exports = [
2392
2413
  model: '8719514342361',
2393
2414
  vendor: 'Philips',
2394
2415
  description: 'Hue smart plug - AU',
2395
- extend: extend.switch(),
2416
+ extend: extend.switch({disablePowerOnBehavior: true}),
2396
2417
  toZigbee: [tz.on_off].concat([tzLocal.hue_power_on_behavior, tzLocal.hue_power_on_error]),
2397
2418
  configure: async (device, coordinatorEndpoint, logger) => {
2398
2419
  const endpoint = device.getEndpoint(11);
@@ -2406,7 +2427,7 @@ module.exports = [
2406
2427
  model: '9290024426',
2407
2428
  vendor: 'Philips',
2408
2429
  description: 'Hue smart plug - CH',
2409
- extend: extend.switch(),
2430
+ extend: extend.switch({disablePowerOnBehavior: true}),
2410
2431
  toZigbee: [tz.on_off].concat([tzLocal.hue_power_on_behavior, tzLocal.hue_power_on_error]),
2411
2432
  configure: async (device, coordinatorEndpoint, logger) => {
2412
2433
  const endpoint = device.getEndpoint(11);
@@ -2420,7 +2441,7 @@ module.exports = [
2420
2441
  model: '929003050601',
2421
2442
  vendor: 'Philips',
2422
2443
  description: 'Hue smart plug',
2423
- extend: extend.switch(),
2444
+ extend: extend.switch({disablePowerOnBehavior: true}),
2424
2445
  toZigbee: [tz.on_off].concat([tzLocal.hue_power_on_behavior, tzLocal.hue_power_on_error]),
2425
2446
  configure: async (device, coordinatorEndpoint, logger) => {
2426
2447
  const endpoint = device.getEndpoint(11);
@@ -2434,7 +2455,7 @@ module.exports = [
2434
2455
  model: '9290030509',
2435
2456
  vendor: 'Philips',
2436
2457
  description: 'Hue smart plug - EU',
2437
- extend: extend.switch(),
2458
+ extend: extend.switch({disablePowerOnBehavior: true}),
2438
2459
  toZigbee: [tz.on_off].concat([tzLocal.hue_power_on_behavior, tzLocal.hue_power_on_error]),
2439
2460
  configure: async (device, coordinatorEndpoint, logger) => {
2440
2461
  const endpoint = device.getEndpoint(11);
@@ -2721,21 +2742,21 @@ module.exports = [
2721
2742
  model: '929002422702',
2722
2743
  vendor: 'Philips',
2723
2744
  description: 'Hue Play gradient lightstrip 55',
2724
- extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
2745
+ extend: hueExtend.light_onoff_brightness_colortemp_color_gradient({colorTempRange: [153, 500]}),
2725
2746
  },
2726
2747
  {
2727
2748
  zigbeeModel: ['LCX002'],
2728
2749
  model: '929002422801',
2729
2750
  vendor: 'Philips',
2730
2751
  description: 'Hue Play gradient lightstrip 65',
2731
- extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
2752
+ extend: hueExtend.light_onoff_brightness_colortemp_color_gradient({colorTempRange: [153, 500]}),
2732
2753
  },
2733
2754
  {
2734
2755
  zigbeeModel: ['LCX003'],
2735
2756
  model: '929002422901',
2736
2757
  vendor: 'Philips',
2737
2758
  description: 'Hue Play gradient lightstrip 75',
2738
- extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
2759
+ extend: hueExtend.light_onoff_brightness_colortemp_color_gradient({colorTempRange: [153, 500]}),
2739
2760
  },
2740
2761
  {
2741
2762
  zigbeeModel: ['929003099301'],
@@ -2935,7 +2956,7 @@ module.exports = [
2935
2956
  model: '929002966501',
2936
2957
  vendor: 'Philips',
2937
2958
  description: 'Hue White and Color Ambiance Surimu rectangle panel',
2938
- extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
2959
+ extend: hueExtend.light_onoff_brightness_colortemp_color({disableHueEffects: false, colorTempRange: [153, 500]}),
2939
2960
  },
2940
2961
  {
2941
2962
  zigbeeModel: ['5060930P7_01', '5060930P7_02', '5060930P7_03', '5060930P7_04'],
@@ -3238,6 +3259,14 @@ module.exports = [
3238
3259
  description: 'Hue White & Color Ambiance Xamento M',
3239
3260
  extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
3240
3261
  },
3262
+ {
3263
+ zigbeeModel: ['929003074801_01', '929003074801_02', '929003074801_03'],
3264
+ model: '929003074801',
3265
+ vendor: 'Philips',
3266
+ description: 'Hue White and Color Ambiance GU10 (Xamento)',
3267
+ extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
3268
+ meta: {turnsOffAtBrightness1: true},
3269
+ },
3241
3270
  {
3242
3271
  zigbeeModel: ['LWE008'],
3243
3272
  model: '929003021301',
package/devices/sinope.js CHANGED
@@ -155,6 +155,18 @@ const fzLocal = {
155
155
  if (msg.data.hasOwnProperty('pumpProtection')) {
156
156
  result.pump_protection = msg.data['pumpProtection'] == 1 ? 'ON' : 'OFF';
157
157
  }
158
+ if (msg.data.hasOwnProperty('dimmerTimmer')) {
159
+ result.timer_seconds = msg.data['dimmerTimmer'];
160
+ }
161
+ if (msg.data.hasOwnProperty('ledIntensityOn')) {
162
+ result.led_intensity_on = msg.data['ledIntensityOn'];
163
+ }
164
+ if (msg.data.hasOwnProperty('ledIntensityOff')) {
165
+ result.led_intensity_off = msg.data['ledIntensityOff'];
166
+ }
167
+ if (msg.data.hasOwnProperty('minimumBrightness')) {
168
+ result.minimum_brightness = msg.data['minimumBrightness'];
169
+ }
158
170
  return result;
159
171
  },
160
172
  },
@@ -380,6 +392,10 @@ const tzLocal = {
380
392
  if (value >= 0 && value <= 100) {
381
393
  await entity.write('manuSpecificSinope', {ledIntensityOn: value});
382
394
  }
395
+ return {readAfterWriteTime: 250, state: {ledIntensityOn: value}};
396
+ },
397
+ convertGet: async (entity, key, meta) => {
398
+ await entity.read('manuSpecificSinope', ['ledIntensityOn']);
383
399
  },
384
400
  },
385
401
  led_intensity_off: {
@@ -389,6 +405,10 @@ const tzLocal = {
389
405
  if (value >= 0 && value <= 100) {
390
406
  await entity.write('manuSpecificSinope', {ledIntensityOff: value});
391
407
  }
408
+ return {readAfterWriteTime: 250, state: {ledIntensityOff: value}};
409
+ },
410
+ convertGet: async (entity, key, meta) => {
411
+ await entity.read('manuSpecificSinope', ['ledIntensityOff']);
392
412
  },
393
413
  },
394
414
  led_color_on: {
@@ -422,6 +442,23 @@ const tzLocal = {
422
442
  if (value >= 0 && value <= 3000) {
423
443
  await entity.write('manuSpecificSinope', {minimumBrightness: value});
424
444
  }
445
+ return {readAfterWriteTime: 250, state: {minimumBrightness: value}};
446
+ },
447
+ convertGet: async (entity, key, meta) => {
448
+ await entity.read('manuSpecificSinope', ['minimumBrightness']);
449
+ },
450
+ },
451
+ timer_seconds: {
452
+ // DM2500ZB and SW2500ZB
453
+ key: ['timer_seconds'],
454
+ convertSet: async (entity, key, value, meta) => {
455
+ if (value >= 0 && value <= 10800) {
456
+ await entity.write('manuSpecificSinope', {dimmerTimmer: value});
457
+ }
458
+ return {readAfterWriteTime: 250, state: {dimmerTimmer: value}};
459
+ },
460
+ convertGet: async (entity, key, meta) => {
461
+ await entity.read('manuSpecificSinope', ['dimmerTimmer']);
425
462
  },
426
463
  },
427
464
  };
@@ -764,7 +801,10 @@ module.exports = [
764
801
  await reporting.thermostatTemperature(endpoint);
765
802
  await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
766
803
  await reporting.thermostatPIHeatingDemand(endpoint);
767
- await reporting.thermostatSystemMode(endpoint);
804
+
805
+ try {
806
+ await reporting.thermostatSystemMode(endpoint);
807
+ } catch (error) {/* Not all support this */}
768
808
 
769
809
  await endpoint.read('hvacThermostat', ['occupiedHeatingSetpoint', 'localTemp', 'systemMode', 'pIHeatingDemand',
770
810
  'SinopeBacklight', 'maxHeatSetpointLimit', 'minHeatSetpointLimit', 'SinopeMainCycleOutput', 'SinopeAuxCycleOutput']);
@@ -819,22 +859,25 @@ module.exports = [
819
859
  model: 'SW2500ZB',
820
860
  vendor: 'Sinopé',
821
861
  description: 'Zigbee smart light switch',
822
- fromZigbee: [fz.on_off, fz.electrical_measurement],
823
- toZigbee: [tz.on_off, tzLocal.led_intensity_on, tzLocal.led_intensity_off, tzLocal.led_color_on, tzLocal.led_color_off],
862
+ fromZigbee: [fz.on_off, fz.electrical_measurement, fzLocal.sinope],
863
+ toZigbee: [tz.on_off, tzLocal.timer_seconds, tzLocal.led_intensity_on, tzLocal.led_intensity_off,
864
+ tzLocal.led_color_on, tzLocal.led_color_off],
824
865
  exposes: [e.switch(),
825
- exposes.numeric('led_intensity_on', ea.SET).withValueMin(0).withValueMax(100)
866
+ exposes.numeric('timer_seconds', ea.ALL).withValueMin(0).withValueMax(10800)
867
+ .withDescription('Automatically turn off load after x seconds'),
868
+ exposes.numeric('led_intensity_on', ea.ALL).withValueMin(0).withValueMax(100)
826
869
  .withDescription('Control status LED intensity when load ON'),
827
- exposes.numeric('led_intensity_off', ea.SET).withValueMin(0).withValueMax(100)
870
+ exposes.numeric('led_intensity_off', ea.ALL).withValueMin(0).withValueMax(100)
828
871
  .withDescription('Control status LED intensity when load OFF'),
829
872
  exposes.composite('led_color_on', 'led_color_on')
830
- .withFeature(exposes.numeric('r', ea.ALL))
831
- .withFeature(exposes.numeric('g', ea.ALL))
832
- .withFeature(exposes.numeric('b', ea.ALL))
873
+ .withFeature(exposes.numeric('r', ea.SET))
874
+ .withFeature(exposes.numeric('g', ea.SET))
875
+ .withFeature(exposes.numeric('b', ea.SET))
833
876
  .withDescription('Control status LED color when load ON'),
834
877
  exposes.composite('led_color_off', 'led_color_off')
835
- .withFeature(exposes.numeric('r', ea.ALL))
836
- .withFeature(exposes.numeric('g', ea.ALL))
837
- .withFeature(exposes.numeric('b', ea.ALL))
878
+ .withFeature(exposes.numeric('r', ea.SET))
879
+ .withFeature(exposes.numeric('g', ea.SET))
880
+ .withFeature(exposes.numeric('b', ea.SET))
838
881
  .withDescription('Control status LED color when load OFF')],
839
882
  configure: async (device, coordinatorEndpoint, logger) => {
840
883
  const endpoint = device.getEndpoint(1);
@@ -848,25 +891,27 @@ module.exports = [
848
891
  model: 'DM2500ZB',
849
892
  vendor: 'Sinopé',
850
893
  description: 'Zigbee smart dimmer',
851
- fromZigbee: [fz.on_off, fz.brightness, fz.electrical_measurement],
852
- toZigbee: [tz.light_onoff_brightness, tzLocal.led_intensity_on, tzLocal.led_intensity_off, tzLocal.minimum_brightness,
853
- tzLocal.led_color_on, tzLocal.led_color_off],
894
+ fromZigbee: [fz.on_off, fz.brightness, fz.electrical_measurement, fzLocal.sinope],
895
+ toZigbee: [tz.light_onoff_brightness, tzLocal.timer_seconds, tzLocal.led_intensity_on, tzLocal.led_intensity_off,
896
+ tzLocal.minimum_brightness, tzLocal.led_color_on, tzLocal.led_color_off],
854
897
  exposes: [e.light_brightness(),
855
- exposes.numeric('led_intensity_on', ea.SET).withValueMin(0).withValueMax(100)
898
+ exposes.numeric('timer_seconds', ea.ALL).withValueMin(0).withValueMax(10800)
899
+ .withDescription('Automatically turn off load after x seconds'),
900
+ exposes.numeric('led_intensity_on', ea.ALL).withValueMin(0).withValueMax(100)
856
901
  .withDescription('Control status LED when load ON'),
857
- exposes.numeric('led_intensity_off', ea.SET).withValueMin(0).withValueMax(100)
902
+ exposes.numeric('led_intensity_off', ea.ALL).withValueMin(0).withValueMax(100)
858
903
  .withDescription('Control status LED when load OFF'),
859
- exposes.numeric('minimum_brightness', ea.SET).withValueMin(0).withValueMax(3000)
904
+ exposes.numeric('minimum_brightness', ea.ALL).withValueMin(0).withValueMax(3000)
860
905
  .withDescription('Control minimum dimmer brightness'),
861
906
  exposes.composite('led_color_on', 'led_color_on')
862
- .withFeature(exposes.numeric('r', ea.ALL))
863
- .withFeature(exposes.numeric('g', ea.ALL))
864
- .withFeature(exposes.numeric('b', ea.ALL))
907
+ .withFeature(exposes.numeric('r', ea.SET))
908
+ .withFeature(exposes.numeric('g', ea.SET))
909
+ .withFeature(exposes.numeric('b', ea.SET))
865
910
  .withDescription('Control status LED color when load ON'),
866
911
  exposes.composite('led_color_off', 'led_color_off')
867
- .withFeature(exposes.numeric('r', ea.ALL))
868
- .withFeature(exposes.numeric('g', ea.ALL))
869
- .withFeature(exposes.numeric('b', ea.ALL))
912
+ .withFeature(exposes.numeric('r', ea.SET))
913
+ .withFeature(exposes.numeric('g', ea.SET))
914
+ .withFeature(exposes.numeric('b', ea.SET))
870
915
  .withDescription('Control status LED color when load OFF')],
871
916
  configure: async (device, coordinatorEndpoint, logger) => {
872
917
  await extend.light_onoff_brightness().configure(device, coordinatorEndpoint, logger);
package/devices/sonoff.js CHANGED
@@ -1,6 +1,5 @@
1
1
  const exposes = require('../lib/exposes');
2
- const fz = {...require('../converters/fromZigbee'), legacy: require('../lib/legacy').fromZigbee};
3
- const tz = require('../converters/toZigbee');
2
+ const fz = require('../converters/fromZigbee');
4
3
  const constants = require('../lib/constants');
5
4
  const reporting = require('../lib/reporting');
6
5
  const extend = require('../lib/extend');
@@ -47,9 +46,6 @@ module.exports = [
47
46
  description: 'Zigbee smart switch (no neutral)',
48
47
  ota: ota.zigbeeOTA,
49
48
  extend: extend.switch(),
50
- toZigbee: extend.switch().toZigbee.concat([tz.power_on_behavior]),
51
- fromZigbee: extend.switch().fromZigbee.concat([fz.power_on_behavior]),
52
- exposes: extend.switch().exposes.concat([e.power_on_behavior()]),
53
49
  configure: async (device, coordinatorEndpoint, logger) => {
54
50
  // Unbind genPollCtrl to prevent device from sending checkin message.
55
51
  // Zigbee-herdsmans responds to the checkin message which causes the device
@@ -67,9 +63,6 @@ module.exports = [
67
63
  description: 'Zigbee smart switch (no neutral)',
68
64
  ota: ota.zigbeeOTA,
69
65
  extend: extend.switch(),
70
- toZigbee: extend.switch().toZigbee.concat([tz.power_on_behavior]),
71
- fromZigbee: extend.switch().fromZigbee.concat([fz.power_on_behavior]),
72
- exposes: extend.switch().exposes.concat([e.power_on_behavior()]),
73
66
  configure: async (device, coordinatorEndpoint, logger) => {
74
67
  // Unbind genPollCtrl to prevent device from sending checkin message.
75
68
  // Zigbee-herdsmans responds to the checkin message which causes the device
@@ -218,8 +211,10 @@ module.exports = [
218
211
  const endpoint = device.getEndpoint(1);
219
212
  const bindClusters = ['genPowerCfg'];
220
213
  await reporting.bind(endpoint, coordinatorEndpoint, bindClusters);
221
- await reporting.batteryVoltage(endpoint);
222
- await reporting.batteryPercentageRemaining(endpoint);
214
+ // 3600/7200 prevents disconnect
215
+ // https://github.com/Koenkk/zigbee2mqtt/issues/13600#issuecomment-1283827935
216
+ await reporting.batteryVoltage(endpoint, {min: 3600, max: 7200});
217
+ await reporting.batteryPercentageRemaining(endpoint, {min: 3600, max: 7200});
223
218
  },
224
219
  exposes: [e.occupancy(), e.battery_low(), e.battery(), e.battery_voltage()],
225
220
  },
package/devices/xiaomi.js CHANGED
@@ -710,7 +710,9 @@ module.exports = [
710
710
  vendor: 'Xiaomi',
711
711
  description: 'Aqara smart wall switch (no neutral, double rocker)',
712
712
  fromZigbee: [fz.on_off, fz.xiaomi_multistate_action, fz.aqara_opple],
713
- toZigbee: [tz.on_off, tz.xiaomi_switch_operation_mode_opple, tz.xiaomi_flip_indicator_light, tz.aqara_switch_mode_switch],
713
+ toZigbee: [
714
+ tz.on_off, tz.xiaomi_switch_operation_mode_opple, tz.xiaomi_flip_indicator_light,
715
+ tz.xiaomi_switch_power_outage_memory, tz.aqara_switch_mode_switch],
714
716
  exposes: [
715
717
  e.switch().withEndpoint('top'),
716
718
  e.switch().withEndpoint('bottom'),
@@ -728,6 +730,7 @@ module.exports = [
728
730
  e.power_outage_count(),
729
731
  e.device_temperature().withAccess(ea.STATE),
730
732
  e.flip_indicator_light(),
733
+ e.power_outage_memory(),
731
734
  e.action(['single_top', 'single_bottom', 'single_both', 'double_top', 'double_bottom', 'double_both'])],
732
735
  meta: {multiEndpoint: true},
733
736
  endpoint: (device) => {
@@ -759,19 +762,36 @@ module.exports = [
759
762
  model: 'WS-USC04',
760
763
  vendor: 'Xiaomi',
761
764
  description: 'Aqara smart wall switch (neutral, double rocker)',
762
- extend: extend.switch(),
763
- exposes: [e.switch().withEndpoint('top'), e.switch().withEndpoint('bottom')],
765
+ fromZigbee: [fz.on_off, fz.xiaomi_power, fz.xiaomi_multistate_action, fz.aqara_opple],
766
+ toZigbee: [
767
+ tz.on_off, tz.xiaomi_power, tz.xiaomi_switch_operation_mode_opple, tz.xiaomi_switch_power_outage_memory,
768
+ tz.xiaomi_flip_indicator_light],
769
+ exposes: [
770
+ e.switch().withEndpoint('top'),
771
+ e.switch().withEndpoint('bottom'),
772
+ exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
773
+ .withDescription('Decoupled mode for top button')
774
+ .withEndpoint('top'),
775
+ exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
776
+ .withDescription('Decoupled mode for bottom button')
777
+ .withEndpoint('bottom'),
778
+ e.power_outage_count(),
779
+ e.device_temperature().withAccess(ea.STATE),
780
+ e.flip_indicator_light(),
781
+ e.power().withAccess(ea.STATE_GET),
782
+ e.energy(),
783
+ e.voltage(),
784
+ e.power_outage_memory(),
785
+ e.action(['single_top', 'single_bottom', 'single_both', 'double_top', 'double_bottom', 'double_both'])],
764
786
  meta: {multiEndpoint: true},
765
787
  endpoint: (device) => {
766
788
  return {'top': 1, 'bottom': 2};
767
789
  },
790
+ onEvent: preventReset,
768
791
  configure: async (device, coordinatorEndpoint, logger) => {
769
- const endpoint1 = device.getEndpoint(1);
770
- await reporting.bind(endpoint1, coordinatorEndpoint, ['genOnOff']);
771
- await reporting.onOff(endpoint1);
772
- const endpoint2 = device.getEndpoint(2);
773
- await reporting.bind(endpoint2, coordinatorEndpoint, ['genOnOff']);
774
- await reporting.onOff(endpoint2);
792
+ await device.getEndpoint(1).write(
793
+ 'aqaraOpple', {mode: 1}, {manufacturerCode: 0x115f, disableResponse: true},
794
+ );
775
795
  },
776
796
  ota: ota.zigbeeOTA,
777
797
  },
package/lib/extend.js CHANGED
@@ -6,9 +6,15 @@ const light = require('./light');
6
6
 
7
7
  const extend = {
8
8
  switch: (options={}) => {
9
+ options = {disablePowerOnBehavior: false, ...options};
9
10
  const exposes = [e.switch()];
10
11
  const fromZigbee = [fz.on_off, fz.ignore_basic_report];
11
12
  const toZigbee = [tz.on_off];
13
+ if (!options.disablePowerOnBehavior) {
14
+ exposes.push(e.power_on_behavior(['off', 'on', 'toggle', 'previous']));
15
+ fromZigbee.push(fz.power_on_behavior);
16
+ toZigbee.push(tz.power_on_behavior);
17
+ }
12
18
  return {exposes, fromZigbee, toZigbee};
13
19
  },
14
20
  light_onoff_brightness: (options={}) => {
package/lib/ota/common.js CHANGED
@@ -248,12 +248,12 @@ async function isUpdateAvailable(device, logger, isNewImageAvailable, requestPay
248
248
  requestPayload = request.payload;
249
249
  }
250
250
 
251
- const available = await isNewImageAvailable(requestPayload, logger, device, getImageMeta);
252
- logger.debug(`Update available for '${device.ieeeAddr}': ${available < 0 ? 'YES' : 'NO'}`);
253
- if (available > 0) {
251
+ const availableResult = await isNewImageAvailable(requestPayload, logger, device, getImageMeta);
252
+ logger.debug(`Update available for '${device.ieeeAddr}': ${availableResult.available < 0 ? 'YES' : 'NO'}`);
253
+ if (availableResult.available > 0) {
254
254
  logger.warn(`Firmware on '${device.ieeeAddr}' is newer than latest firmware online.`);
255
255
  }
256
- return {...available, available: available < 0};
256
+ return {...availableResult, available: availableResult.available < 0};
257
257
  }
258
258
 
259
259
  async function isNewImageAvailable(current, logger, device, getImageMeta) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zigbee-herdsman-converters",
3
- "version": "15.0.13",
3
+ "version": "15.0.15",
4
4
  "description": "Collection of device converters to be used with zigbee-herdsman",
5
5
  "main": "index.js",
6
6
  "files": [