zigbee-herdsman-converters 14.0.315 → 14.0.316

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.
@@ -648,6 +648,26 @@ const converters = {
648
648
  return payload;
649
649
  },
650
650
  },
651
+ develco_metering: {
652
+ cluster: 'seMetering',
653
+ type: ['attributeReport', 'readResponse'],
654
+ convert: (model, msg, publish, options, meta) => {
655
+ const result = {};
656
+ if (msg.data.hasOwnProperty('develcoPulseConfiguration')) {
657
+ result[postfixWithEndpointName('pulse_configuration', msg, model)] =
658
+ msg.data['develcoPulseConfiguration'];
659
+ }
660
+
661
+ if (msg.data.hasOwnProperty('develcoInterfaceMode')) {
662
+ result[postfixWithEndpointName('interface_mode', msg, model)] =
663
+ constants.develcoInterfaceMode.hasOwnProperty(msg.data['develcoInterfaceMode']) ?
664
+ constants.develcoInterfaceMode[msg.data['develcoInterfaceMode']] :
665
+ msg.data['develcoInterfaceMode'];
666
+ }
667
+
668
+ return result;
669
+ },
670
+ },
651
671
  electrical_measurement: {
652
672
  /**
653
673
  * When using this converter also add the following to the configure method of the device:
@@ -2485,6 +2505,22 @@ const converters = {
2485
2505
  }
2486
2506
  },
2487
2507
  },
2508
+ livolo_curtain_switch_state: {
2509
+ cluster: 'genPowerCfg',
2510
+ type: ['raw'],
2511
+ convert: (model, msg, publish, options, meta) => {
2512
+ const stateHeader = Buffer.from([122, 209]);
2513
+ if (msg.data.indexOf(stateHeader) === 0) {
2514
+ if (msg.data[10] === 5) {
2515
+ const status = msg.data[14];
2516
+ return {
2517
+ state_left: status === 1 ? 'ON' : 'OFF',
2518
+ state_right: status === 0 ? 'ON' : 'OFF',
2519
+ };
2520
+ }
2521
+ }
2522
+ },
2523
+ },
2488
2524
  livolo_dimmer_state: {
2489
2525
  cluster: 'genPowerCfg',
2490
2526
  type: ['raw'],
@@ -2592,16 +2628,24 @@ const converters = {
2592
2628
  [124,210,21,216,128, 199,147,3,24,0,75,18,0, 19,7,0] after interview
2593
2629
  [122,209, 199,147,3,24,0,75,18,0, 7,1,6,1,0,11] off
2594
2630
  [122,209, 199,147,3,24,0,75,18,0, 7,1,6,1,1,11] on
2631
+
2595
2632
  new switch
2596
2633
  [124,210,21,216,128, 228,41,3,24,0,75,18,0, 19,1,0] after interview
2597
2634
  [122,209, 228,41,3,24,0,75,18,0, 7,1,0,1,0,11] off
2598
2635
  [122,209, 228,41,3,24,0,75,18,0, 7,1,0,1,1,11] on
2636
+
2599
2637
  old switch
2600
2638
  [124,210,21,216,128, 170, 10,2,24,0,75,18,0, 17,0,1] after interview
2601
2639
  [124,210,21,216,0, 18, 15,5,24,0,75,18,0, 34,0,0] left: 0, right: 0
2602
2640
  [124,210,21,216,0, 18, 15,5,24,0,75,18,0, 34,0,1] left: 1, right: 0
2603
2641
  [124,210,21,216,0, 18, 15,5,24,0,75,18,0, 34,0,2] left: 0, right: 1
2604
2642
  [124,210,21,216,0, 18, 15,5,24,0,75,18,0, 34,0,3] left: 1, right: 1
2643
+
2644
+ curtain switch
2645
+ [124,210,21,216,128, 110,74,116,33,0,75,18,0, 19,5,0] after interview
2646
+ [122,209, 110,74,116,33,0,75,18,0, 5,1,5,0,2,11] left: 0, right: 0 (off)
2647
+ [122,209, 110,74,116,33,0,75,18,0, 5,1,5,0,1,11] left: 1, right: 0 (left on)
2648
+ [122,209, 110,74,116,33,0,75,18,0, 5,1,5,0,0,11] left: 0, right: 1 (right on)
2605
2649
  */
2606
2650
  const malformedHeader = Buffer.from([0x7c, 0xd2, 0x15, 0xd8, 0x00]);
2607
2651
  const infoHeader = Buffer.from([0x7c, 0xd2, 0x15, 0xd8, 0x80]);
@@ -2630,6 +2674,12 @@ const converters = {
2630
2674
  meta.device.modelID = 'TI0001-switch-2gang';
2631
2675
  meta.device.save();
2632
2676
  }
2677
+ if (msg.data.includes(Buffer.from([19, 5, 0]), 13)) {
2678
+ if (meta.logger) meta.logger.debug('Detected Livolo Curtain Switch');
2679
+ // curtain switch, hack
2680
+ meta.device.modelID = 'TI0001-curtain-switch';
2681
+ meta.device.save();
2682
+ }
2633
2683
  if (msg.data.includes(Buffer.from([19, 20, 0]), 13)) {
2634
2684
  // new dimmer, hack
2635
2685
  meta.device.modelID = 'TI0001-dimmer';
@@ -15,6 +15,7 @@ const manufacturerOptions = {
15
15
  osram: {manufacturerCode: herdsman.Zcl.ManufacturerCode.OSRAM},
16
16
  eurotronic: {manufacturerCode: herdsman.Zcl.ManufacturerCode.JENNIC},
17
17
  danfoss: {manufacturerCode: herdsman.Zcl.ManufacturerCode.DANFOSS},
18
+ develco: {manufacturerCode: herdsman.Zcl.ManufacturerCode.DEVELCO},
18
19
  hue: {manufacturerCode: herdsman.Zcl.ManufacturerCode.PHILIPS},
19
20
  sinope: {manufacturerCode: herdsman.Zcl.ManufacturerCode.SINOPE_TECH},
20
21
  /*
@@ -2569,6 +2570,34 @@ const converters = {
2569
2570
  await entity.read('haDiagnostic', ['danfossMultimasterRole'], manufacturerOptions.danfoss);
2570
2571
  },
2571
2572
  },
2573
+ develco_pulse_configuration: {
2574
+ key: ['pulse_configuration'],
2575
+ convertSet: async (entity, key, value, meta) => {
2576
+ await entity.write('seMetering', {'develcoPulseConfiguration': value}, manufacturerOptions.develco);
2577
+ return {readAfterWriteTime: 200, state: {'pulse_configuration': value}};
2578
+ },
2579
+ convertGet: async (entity, key, meta) => {
2580
+ await entity.read('seMetering', ['develcoPulseConfiguration'], manufacturerOptions.develco);
2581
+ },
2582
+ },
2583
+ develco_interface_mode: {
2584
+ key: ['interface_mode'],
2585
+ convertSet: async (entity, key, value, meta) => {
2586
+ const payload = {'develcoInterfaceMode': utils.getKey(constants.develcoInterfaceMode, value, undefined, Number)};
2587
+ await entity.write('seMetering', payload, manufacturerOptions.develco);
2588
+ return {readAfterWriteTime: 200, state: {'interface_mode': value}};
2589
+ },
2590
+ convertGet: async (entity, key, meta) => {
2591
+ await entity.read('seMetering', ['develcoInterfaceMode'], manufacturerOptions.develco);
2592
+ },
2593
+ },
2594
+ develco_current_summation: {
2595
+ key: ['current_summation'],
2596
+ convertSet: async (entity, key, value, meta) => {
2597
+ await entity.write('seMetering', {'develcoCurrentSummation': value}, manufacturerOptions.develco);
2598
+ return {state: {'current_summation': value}};
2599
+ },
2600
+ },
2572
2601
  ZMCSW032D_cover_position: {
2573
2602
  key: ['position', 'tilt'],
2574
2603
  convertSet: async (entity, key, value, meta) => {
@@ -2762,9 +2791,9 @@ const converters = {
2762
2791
  await tuya.sendDataPointBool(entity, tuya.dataPoints.tvChildLock, value === 'LOCK');
2763
2792
  break;
2764
2793
  case 'local_temperature_calibration':
2765
- // value = Math.round(value);
2766
- value = (value < 0) ? 0xFFFFFFFF + value + 1 : value;
2767
- await tuya.sendDataPointValue(entity, tuya.dataPoints.tvTempCalibration, value * 10);
2794
+ if (value > 0) value = value*10;
2795
+ if (value < 0) value = value*10 + 0x100000000;
2796
+ await tuya.sendDataPointValue(entity, tuya.dataPoints.tvTempCalibration, value);
2768
2797
  break;
2769
2798
  case 'current_heating_setpoint':
2770
2799
  await tuya.sendDataPointValue(entity, tuya.dataPoints.tvHeatingSetpoint, value * 10);
@@ -5,6 +5,31 @@ const reporting = require('../lib/reporting');
5
5
  const extend = require('../lib/extend');
6
6
  const e = exposes.presets;
7
7
 
8
+ const batteryRotaryDimmer = (...endpointsIds) => ({
9
+ fromZigbee: [fz.battery, fz.command_on, fz.command_off, fz.command_step, fz.command_step_color_temperature],
10
+ toZigbee: [],
11
+ exposes: [e.battery(), e.action([
12
+ 'on', 'off', 'brightness_step_up', 'brightness_step_down', 'color_temperature_step_up', 'color_temperature_step_down'])],
13
+ configure: async (device, coordinatorEndpoint, logger) => {
14
+ const endpoints = endpointsIds.map((endpoint) => device.getEndpoint(endpoint));
15
+
16
+ // Battery level is only reported on first endpoint
17
+ await reporting.batteryVoltage(endpoints[0]);
18
+
19
+ for await (const endpoint of endpoints) {
20
+ logger.debug(`processing endpoint ${endpoint.ID}`);
21
+ await reporting.bind(endpoint, coordinatorEndpoint,
22
+ ['genIdentify', 'genOnOff', 'genLevelCtrl', 'lightingColorCtrl']);
23
+
24
+ // The default is for the device to also report the on/off and
25
+ // brightness at the same time as sending on/off and step commands.
26
+ // Disable the reporting by setting the max interval to 0xFFFF.
27
+ await reporting.brightness(endpoint, {max: 0xFFFF});
28
+ await reporting.onOff(endpoint, {max: 0xFFFF});
29
+ }
30
+ },
31
+ });
32
+
8
33
  module.exports = [
9
34
  {
10
35
  zigbeeModel: ['TWGU10Bulb50AU'],
@@ -167,38 +192,20 @@ module.exports = [
167
192
  model: 'AU-A1ZBR1GW',
168
193
  vendor: 'Aurora Lighting',
169
194
  description: 'AOne one gang wireless battery rotary dimmer',
170
- fromZigbee: [fz.battery, fz.command_on, fz.command_off, fz.command_step, fz.command_step_color_temperature],
171
- toZigbee: [],
172
- exposes: [e.battery(), e.action([
173
- 'on', 'off', 'brightness_step_up', 'brightness_step_down', 'color_temperature_step_up', 'color_temperature_step_down'])],
174
195
  meta: {battery: {voltageToPercentage: '3V_2100'}},
175
- configure: async (device, coordinatorEndpoint, logger) => {
176
- const endpoint1 = device.getEndpoint(1);
177
- await reporting.bind(endpoint1, coordinatorEndpoint,
178
- ['genIdentify', 'genOnOff', 'genLevelCtrl', 'lightingColorCtrl', 'genPowerCfg']);
179
- await reporting.batteryVoltage(endpoint1);
180
- },
196
+ // One gang battery rotary dimmer with endpoint ID 1
197
+ ...batteryRotaryDimmer(1),
181
198
  },
182
199
  {
183
200
  zigbeeModel: ['2GBatteryDimmer50AU'],
184
201
  model: 'AU-A1ZBR2GW',
185
202
  vendor: 'Aurora Lighting',
186
203
  description: 'AOne two gang wireless battery rotary dimmer',
187
- fromZigbee: [fz.battery, fz.command_on, fz.command_off, fz.command_step, fz.command_step_color_temperature],
188
- toZigbee: [],
189
- exposes: [e.battery(), e.action([
190
- 'on', 'off', 'brightness_step_up', 'brightness_step_down', 'color_temperature_step_up', 'color_temperature_step_down'])],
191
204
  meta: {multiEndpoint: true, battery: {voltageToPercentage: '3V_2100'}},
192
205
  endpoint: (device) => {
193
206
  return {'right': 1, 'left': 2};
194
207
  },
195
- configure: async (device, coordinatorEndpoint, logger) => {
196
- const endpoint1 = device.getEndpoint(1);
197
- await reporting.bind(endpoint1, coordinatorEndpoint,
198
- ['genIdentify', 'genOnOff', 'genLevelCtrl', 'lightingColorCtrl', 'genPowerCfg']);
199
- await reporting.batteryVoltage(endpoint1);
200
- const endpoint2 = device.getEndpoint(2);
201
- await reporting.bind(endpoint2, coordinatorEndpoint, ['genIdentify', 'genOnOff', 'genLevelCtrl', 'lightingColorCtrl']);
202
- },
208
+ // Two gang battery rotary dimmer with endpoint IDs 1 and 2
209
+ ...batteryRotaryDimmer(1, 2),
203
210
  },
204
211
  ];
@@ -297,15 +297,28 @@ module.exports = [
297
297
  model: 'ZHEMI101',
298
298
  vendor: 'Develco',
299
299
  description: 'Energy meter',
300
- fromZigbee: [fz.metering],
301
- toZigbee: [],
300
+ fromZigbee: [fz.metering, fz.develco_metering],
301
+ toZigbee: [tz.develco_pulse_configuration, tz.develco_interface_mode, tz.develco_current_summation],
302
+ endpoint: (device) => {
303
+ return {'default': 2};
304
+ },
302
305
  configure: async (device, coordinatorEndpoint, logger) => {
303
306
  const endpoint = device.getEndpoint(2);
304
307
  await reporting.bind(endpoint, coordinatorEndpoint, ['seMetering']);
305
308
  await reporting.instantaneousDemand(endpoint);
306
309
  await reporting.readMeteringMultiplierDivisor(endpoint);
307
310
  },
308
- exposes: [e.power(), e.energy()],
311
+ exposes: [
312
+ e.power(),
313
+ e.energy(),
314
+ exposes.numeric('pulse_configuration', ea.ALL).withValueMin(0).withValueMax(65535)
315
+ .withDescription('Pulses per kwh. Default 1000 imp/kWh. Range 0 to 65535'),
316
+ exposes.enum('interface_mode', ea.ALL,
317
+ ['electricity', 'gas', 'water', 'kamstrup-kmp', 'linky', 'IEC62056-21', 'DSMR-2.3', 'DSMR-4.0'])
318
+ .withDescription('Operating mode/probe'),
319
+ exposes.numeric('current_summation', ea.SET)
320
+ .withDescription('Current summation value sent to the display. e.g. 570 = 0,570 kWh'),
321
+ ],
309
322
  },
310
323
  {
311
324
  zigbeeModel: ['SMRZB-332'],
package/devices/lidl.js CHANGED
@@ -270,10 +270,17 @@ module.exports = [
270
270
  extend: extend.light_onoff_brightness({disableEffect: true}),
271
271
  meta: {turnsOffAtBrightness1: false},
272
272
  },
273
+ {
274
+ fingerprint: [{modelID: 'TS0501A', manufacturerName: '_TZ3000_nosnx7im'}],
275
+ model: 'HG06463B',
276
+ vendor: 'Lidl',
277
+ description: 'Livarno Lux E27 G30 filament bulb',
278
+ extend: extend.light_onoff_brightness({disableEffect: true}),
279
+ meta: {turnsOffAtBrightness1: false},
280
+ },
273
281
  {
274
282
  fingerprint: [
275
283
  {modelID: 'TS0501A', manufacturerName: '_TZ3000_7dcddnye'},
276
- {modelID: 'TS0501A', manufacturerName: '_TZ3000_nosnx7im'},
277
284
  {modelID: 'TS0501A', manufacturerName: '_TZ3000_nbnmw9nc'}, // UK
278
285
  ],
279
286
  model: 'HG06462A',
package/devices/livolo.js CHANGED
@@ -99,6 +99,35 @@ module.exports = [
99
99
  }
100
100
  },
101
101
  },
102
+ {
103
+ zigbeeModel: ['TI0001-curtain-switch'],
104
+ model: 'TI0001-curtain-switch',
105
+ description: 'Zigbee curtain switch (can only read status, control does not work yet)',
106
+ vendor: 'Livolo',
107
+ fromZigbee: [fz.livolo_curtain_switch_state],
108
+ toZigbee: [tz.livolo_socket_switch_on_off],
109
+ // toZigbee: [tz.livolo_curtain_switch_on_off],
110
+ exposes: [e.switch().withEndpoint('left'), e.switch().withEndpoint('right')],
111
+ configure: poll,
112
+ endpoint: (device) => {
113
+ return {'left': 6, 'right': 6};
114
+ },
115
+ onEvent: async (type, data, device) => {
116
+ if (type === 'stop') {
117
+ clearInterval(globalStore.getValue(device, 'interval'));
118
+ globalStore.clearValue(device, 'interval');
119
+ }
120
+ if (['start', 'deviceAnnounce'].includes(type)) {
121
+ await poll(device);
122
+ if (!globalStore.hasValue(device, 'interval')) {
123
+ const interval = setInterval(async () => {
124
+ await poll(device);
125
+ }, 300*1000); // Every 300 seconds
126
+ globalStore.putValue(device, 'interval', interval);
127
+ }
128
+ }
129
+ },
130
+ },
102
131
  {
103
132
  zigbeeModel: ['TI0001-socket'],
104
133
  model: 'TI0001-socket',
@@ -34,4 +34,11 @@ module.exports = [
34
34
  vendor: 'Miboxer',
35
35
  extend: extend.light_onoff_brightness_colortemp({disableColorTempStartup: true, colorTempRange: [153, 500]}),
36
36
  },
37
+ {
38
+ fingerprint: [{modelID: 'TS0504B', manufacturerName: '_TZ3210_ttkgurpb'}],
39
+ model: 'FUT038Z',
40
+ description: 'RGBW LED controller',
41
+ vendor: 'Miboxer',
42
+ extend: extend.light_onoff_brightness_colortemp({disableColorTempStartup: true, colorTempRange: [153, 500]}),
43
+ },
37
44
  ];
@@ -717,6 +717,15 @@ module.exports = [
717
717
  extend: hueExtend.light_onoff_brightness_colortemp_color(),
718
718
  ota: ota.zigbeeOTA,
719
719
  },
720
+ {
721
+ zigbeeModel: ['LCA004'],
722
+ model: '9290024896',
723
+ vendor: 'Philips',
724
+ description: 'Hue white and color ambiance E27',
725
+ meta: {turnsOffAtBrightness1: true},
726
+ extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
727
+ ota: ota.zigbeeOTA,
728
+ },
720
729
  {
721
730
  zigbeeModel: ['LCA008'],
722
731
  model: '929002471601',
@@ -2167,7 +2176,7 @@ module.exports = [
2167
2176
  vendor: 'Philips',
2168
2177
  description: 'Hue Filament Globe XL Ambiance E27',
2169
2178
  meta: {turnsOffAtBrightness1: true},
2170
- extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 500]}),
2179
+ extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [222, 454]}),
2171
2180
  ota: ota.zigbeeOTA,
2172
2181
  },
2173
2182
  {
package/devices/tuya.js CHANGED
@@ -1167,9 +1167,7 @@ module.exports = [
1167
1167
  model: 'TS0011',
1168
1168
  vendor: 'TuYa',
1169
1169
  description: 'Smart light switch - 1 gang',
1170
- toZigbee: extend.switch().toZigbee.concat([tz.tuya_switch_type]),
1171
- fromZigbee: extend.switch().fromZigbee.concat([fz.tuya_switch_type]),
1172
- exposes: [e.switch(), exposes.presets.switch_type_2()],
1170
+ extend: extend.switch(),
1173
1171
  whiteLabel: [
1174
1172
  {vendor: 'Vrey', model: 'VR-X712U-0013'},
1175
1173
  {vendor: 'TUYATEC', model: 'GDKES-01TZXD'},
@@ -1183,6 +1181,25 @@ module.exports = [
1183
1181
  device.save();
1184
1182
  },
1185
1183
  },
1184
+ {
1185
+ fingerprint: [{modelID: 'TS0011', manufacturerName: '_TZ3000_jl7qyupf'}],
1186
+ model: 'TS0011_switch_module',
1187
+ vendor: 'TuYa',
1188
+ description: '1 gang switch module - (without neutral)',
1189
+ toZigbee: extend.switch().toZigbee.concat([tz.moes_power_on_behavior, tz.tuya_switch_type]),
1190
+ fromZigbee: extend.switch().fromZigbee.concat([fz.moes_power_on_behavior, fz.tuya_switch_type]),
1191
+ exposes: [
1192
+ e.switch(),
1193
+ exposes.presets.power_on_behavior(),
1194
+ exposes.presets.switch_type_2(),
1195
+ ],
1196
+ whiteLabel: [{vendor: 'AVATTO', model: '1gang N-ZLWSM01'}],
1197
+ configure: async (device, coordinatorEndpoint, logger) => {
1198
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
1199
+ device.powerSource = 'Mains (single phase)';
1200
+ device.save();
1201
+ },
1202
+ },
1186
1203
  {
1187
1204
  zigbeeModel: ['TS0012'],
1188
1205
  model: 'TS0012',
@@ -1190,9 +1207,33 @@ module.exports = [
1190
1207
  description: 'Smart light switch - 2 gang',
1191
1208
  whiteLabel: [{vendor: 'Vrey', model: 'VR-X712U-0013'}, {vendor: 'TUYATEC', model: 'GDKES-02TZXD'},
1192
1209
  {vendor: 'Earda', model: 'ESW-2ZAA-EU'}],
1193
- toZigbee: extend.switch().toZigbee.concat([tz.tuya_switch_type]),
1194
- fromZigbee: extend.switch().fromZigbee.concat([fz.tuya_switch_type]),
1195
- exposes: [e.switch().withEndpoint('left'), e.switch().withEndpoint('right'), exposes.presets.switch_type_2()],
1210
+ extend: extend.switch(),
1211
+ exposes: [e.switch().withEndpoint('left'), e.switch().withEndpoint('right')],
1212
+ endpoint: (device) => {
1213
+ return {'left': 1, 'right': 2};
1214
+ },
1215
+ meta: {multiEndpoint: true},
1216
+ configure: async (device, coordinatorEndpoint, logger) => {
1217
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
1218
+ await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
1219
+ device.powerSource = 'Mains (single phase)';
1220
+ device.save();
1221
+ },
1222
+ },
1223
+ {
1224
+ fingerprint: [{modelID: 'TS0012', manufacturerName: '_TZ3000_jl7qyupf'}],
1225
+ model: 'TS0012_switch_module',
1226
+ vendor: 'TuYa',
1227
+ description: '2 gang switch module - (without neutral)',
1228
+ whiteLabel: [{vendor: 'AVATTO', model: '2gang N-ZLWSM01'}],
1229
+ toZigbee: extend.switch().toZigbee.concat([tz.moes_power_on_behavior, tz.tuya_switch_type]),
1230
+ fromZigbee: extend.switch().fromZigbee.concat([fz.moes_power_on_behavior, fz.tuya_switch_type]),
1231
+ exposes: [
1232
+ e.switch().withEndpoint('left'),
1233
+ e.switch().withEndpoint('right'),
1234
+ exposes.presets.power_on_behavior(),
1235
+ exposes.presets.switch_type_2(),
1236
+ ],
1196
1237
  endpoint: (device) => {
1197
1238
  return {'left': 1, 'right': 2};
1198
1239
  },
@@ -1209,10 +1250,8 @@ module.exports = [
1209
1250
  model: 'TS0013',
1210
1251
  vendor: 'TuYa',
1211
1252
  description: 'Smart light switch - 3 gang without neutral wire',
1212
- toZigbee: extend.switch().toZigbee.concat([tz.tuya_switch_type]),
1213
- fromZigbee: extend.switch().fromZigbee.concat([fz.tuya_switch_type]),
1214
- exposes: [e.switch().withEndpoint('left'), e.switch().withEndpoint('center'), e.switch().withEndpoint('right'),
1215
- exposes.presets.switch_type_2()],
1253
+ extend: extend.switch(),
1254
+ exposes: [e.switch().withEndpoint('left'), e.switch().withEndpoint('center'), e.switch().withEndpoint('right')],
1216
1255
  endpoint: (device) => {
1217
1256
  return {'left': 1, 'center': 2, 'right': 3};
1218
1257
  },
@@ -1231,6 +1270,38 @@ module.exports = [
1231
1270
  device.save();
1232
1271
  },
1233
1272
  },
1273
+ {
1274
+ fingerprint: [{modelID: 'TS0013', manufacturerName: '_TZ3000_jl7qyupf'}],
1275
+ model: 'TS0013_switch_module',
1276
+ vendor: 'TuYa',
1277
+ description: '3 gang switch module - (without neutral)',
1278
+ whiteLabel: [{vendor: 'AVATTO', model: '3gang N-ZLWSM01'}],
1279
+ toZigbee: extend.switch().toZigbee.concat([tz.moes_power_on_behavior, tz.tuya_switch_type]),
1280
+ fromZigbee: extend.switch().fromZigbee.concat([fz.moes_power_on_behavior, fz.tuya_switch_type]),
1281
+ exposes: [
1282
+ e.switch().withEndpoint('left'),
1283
+ e.switch().withEndpoint('center'),
1284
+ e.switch().withEndpoint('right'),
1285
+ exposes.presets.power_on_behavior(),
1286
+ exposes.presets.switch_type_2(),
1287
+ ],
1288
+ endpoint: (device) => {
1289
+ return {'left': 1, 'center': 2, 'right': 3};
1290
+ },
1291
+ meta: {multiEndpoint: true},
1292
+ configure: async (device, coordinatorEndpoint, logger) => {
1293
+ try {
1294
+ for (const ID of [1, 2, 3]) {
1295
+ const endpoint = device.getEndpoint(ID);
1296
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
1297
+ }
1298
+ } catch (e) {
1299
+ // Fails for some: https://github.com/Koenkk/zigbee2mqtt/issues/4872
1300
+ }
1301
+ device.powerSource = 'Mains (single phase)';
1302
+ device.save();
1303
+ },
1304
+ },
1234
1305
  {
1235
1306
  fingerprint: [{modelID: 'TS0014', manufacturerName: '_TZ3000_jr2atpww'}, {modelID: 'TS0014', manufacturerName: '_TYZB01_dvakyzhd'},
1236
1307
  {modelID: 'TS0014', manufacturerName: '_TZ3210_w3hl6rao'}, {modelID: 'TS0014', manufacturerName: '_TYZB01_bagt1e4o'},
@@ -1238,10 +1309,9 @@ module.exports = [
1238
1309
  model: 'TS0014',
1239
1310
  vendor: 'TuYa',
1240
1311
  description: 'Smart light switch - 4 gang without neutral wire',
1241
- toZigbee: extend.switch().toZigbee.concat([tz.tuya_switch_type]),
1242
- fromZigbee: extend.switch().fromZigbee.concat([fz.tuya_switch_type]),
1312
+ extend: extend.switch(),
1243
1313
  exposes: [e.switch().withEndpoint('l1'), e.switch().withEndpoint('l2'), e.switch().withEndpoint('l3'),
1244
- e.switch().withEndpoint('l4'), exposes.presets.switch_type_2()],
1314
+ e.switch().withEndpoint('l4')],
1245
1315
  endpoint: (device) => {
1246
1316
  return {'l1': 1, 'l2': 2, 'l3': 3, 'l4': 4};
1247
1317
  },
package/lib/constants.js CHANGED
@@ -129,6 +129,17 @@ const danfossMultimasterRole = {
129
129
  3: 'slave_2',
130
130
  };
131
131
 
132
+ const develcoInterfaceMode = {
133
+ 0: 'electricity',
134
+ 1: 'gas',
135
+ 2: 'water',
136
+ 256: 'kamstrup-kmp',
137
+ 257: 'linky',
138
+ 258: 'IEC62056-21',
139
+ 259: 'DSMR-2.3',
140
+ 260: 'DSMR-4.0',
141
+ };
142
+
132
143
  const keypadLockoutMode = {
133
144
  0: 'unlock',
134
145
  1: 'lock1',
@@ -239,6 +250,7 @@ module.exports = {
239
250
  danfossSystemStatusWater,
240
251
  danfossSystemStatusCode,
241
252
  danfossMultimasterRole,
253
+ develcoInterfaceMode,
242
254
  keypadLockoutMode,
243
255
  lockSourceName,
244
256
  armMode,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zigbee-herdsman-converters",
3
- "version": "14.0.315",
3
+ "version": "14.0.316",
4
4
  "lockfileVersion": 1,
5
5
  "requires": true,
6
6
  "dependencies": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zigbee-herdsman-converters",
3
- "version": "14.0.315",
3
+ "version": "14.0.316",
4
4
  "description": "Collection of device converters to be used with zigbee-herdsman",
5
5
  "main": "index.js",
6
6
  "files": [