zigbee-herdsman-converters 14.0.628 → 14.0.630

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.
@@ -785,6 +785,20 @@ const converters = {
785
785
  }
786
786
  },
787
787
  },
788
+ on_off_force_multiendpoint: {
789
+ cluster: 'genOnOff',
790
+ type: ['attributeReport', 'readResponse'],
791
+ convert: (model, msg, publish, options, meta) => {
792
+ // This converted is need instead of `fz.on_off` when no meta: {multiEndpoint: true} can be defined for this device
793
+ // but it is needed for the `state`. E.g. when a switch has 3 channels (state_l1, state_l2, state_l3) but
794
+ // has combined power measurements (power, energy))
795
+ if (msg.data.hasOwnProperty('onOff')) {
796
+ const endpointName = model.hasOwnProperty('endpoint') ?
797
+ utils.getKey(model.endpoint(meta.device), msg.endpoint.ID) : msg.endpoint.ID;
798
+ return {[`state_${endpointName}`]: msg.data['onOff'] === 1 ? 'ON' : 'OFF'};
799
+ }
800
+ },
801
+ },
788
802
  on_off_skip_duplicate_transaction: {
789
803
  cluster: 'genOnOff',
790
804
  type: ['attributeReport', 'readResponse'],
@@ -582,7 +582,8 @@ const converters = {
582
582
  'ballast_physical_minimum_level',
583
583
  'ballast_physical_maximum_level',
584
584
  'ballast_minimum_level',
585
- 'ballast_maximum_level'],
585
+ 'ballast_maximum_level',
586
+ 'ballast_power_on_level'],
586
587
  // zcl attribute names are camel case, but we want to use snake case in the outside communication
587
588
  convertSet: async (entity, key, value, meta) => {
588
589
  if (key === 'ballast_config') {
@@ -599,6 +600,9 @@ const converters = {
599
600
  if (key === 'ballast_maximum_level') {
600
601
  await entity.write('lightingBallastCfg', {'maxLevel': value});
601
602
  }
603
+ if (key === 'ballast_power_on_level') {
604
+ await entity.write('lightingBallastCfg', {'powerOnLevel': value});
605
+ }
602
606
  converters.ballast_config.convertGet(entity, key, meta);
603
607
  },
604
608
  convertGet: async (entity, key, meta) => {
@@ -79,6 +79,13 @@ const batteryRotaryDimmer = (...endpointsIds) => ({
79
79
  });
80
80
 
81
81
  module.exports = [
82
+ {
83
+ zigbeeModel: ['TWBulb51AU'],
84
+ model: 'AU-A1GSZ9CX',
85
+ vendor: 'Aurora',
86
+ description: 'AOne GLS lamp 9w tunable dimmable 2200-5000K',
87
+ extend: extend.light_onoff_brightness_colortemp({colorTempRange: [200, 454]}),
88
+ },
82
89
  {
83
90
  zigbeeModel: ['RGBCXStrip50AU'],
84
91
  model: 'AU-A1ZBSCRGBCX',
package/devices/ctm.js CHANGED
@@ -281,15 +281,6 @@ const fzLocal = {
281
281
 
282
282
 
283
283
  const tzLocal = {
284
- ballast_power_on_level: {
285
- key: ['ballast_power_on_level'],
286
- convertSet: async (entity, key, value, meta) => {
287
- await entity.write('lightingBallastCfg', {'powerOnLevel': value});
288
- },
289
- convertGet: async (entity, key, meta) => {
290
- await entity.read('lightingBallastCfg', ['powerOnLevel']);
291
- },
292
- },
293
284
  ctm_device_mode: {
294
285
  key: ['device_mode'],
295
286
  convertGet: async (entity, key, meta) => {
@@ -577,7 +568,7 @@ module.exports = [
577
568
  vendor: 'CTM Lyng',
578
569
  description: 'mTouch Dim OP, touch dimmer',
579
570
  fromZigbee: [fz.on_off, fz.brightness, fz.lighting_ballast_configuration],
580
- toZigbee: [tz.on_off, tz.light_onoff_brightness, tz.light_brightness_move, tz.ballast_config, tzLocal.ballast_power_on_level],
571
+ toZigbee: [tz.on_off, tz.light_onoff_brightness, tz.light_brightness_move, tz.ballast_config],
581
572
  meta: {disableDefaultResponse: true},
582
573
  configure: async (device, coordinatorEndpoint, logger) => {
583
574
  const endpoint = device.getEndpoint(1);
@@ -13,7 +13,7 @@ module.exports = [
13
13
  extend: extend.light_onoff_brightness(),
14
14
  },
15
15
  {
16
- zigbeeModel: ['ZG50CC-CCT-DRIVER'],
16
+ zigbeeModel: ['ZG50CC-CCT-DRIVER', 'HK-CCT'],
17
17
  model: 'ZG50CC-CCT-DRIVER',
18
18
  vendor: 'Envilar',
19
19
  description: 'Zigbee CCT LED driver',
package/devices/heiman.js CHANGED
@@ -444,6 +444,21 @@ module.exports = [
444
444
  await reporting.batteryPercentageRemaining(endpoint);
445
445
  },
446
446
  },
447
+ {
448
+ zigbeeModel: ['TempDimmerSw-EM-3.0'],
449
+ model: 'HS2WDSC-E',
450
+ vendor: 'HEIMAN',
451
+ description: 'Remote dimmer and temperature control',
452
+ fromZigbee: [fz.battery, fz.command_on, fz.command_off, fz.command_move, fz.command_stop, fz.command_move_to_color,
453
+ fz.command_move_to_color_temp],
454
+ exposes: [e.battery(), e.action(['on', 'off', 'move', 'stop', 'color_move', 'color_temperature_move'])],
455
+ toZigbee: [],
456
+ configure: async (device, coordinatorEndpoint, logger) => {
457
+ const endpoint = device.getEndpoint(1);
458
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'genOnOff', 'genLevelCtrl', 'lightingColorCtrl']);
459
+ await reporting.batteryPercentageRemaining(endpoint, {min: constants.repInterval.MINUTES_5, max: constants.repInterval.HOUR});
460
+ },
461
+ },
447
462
  {
448
463
  fingerprint: [{modelID: 'ColorDimmerSw-EM-3.0', manufacturerName: 'HEIMAN'}],
449
464
  model: 'HS2WDSR-E',
@@ -667,6 +682,13 @@ module.exports = [
667
682
  exposes: [e.switch().withEndpoint('left'), e.switch().withEndpoint('center'), e.switch().withEndpoint('right'),
668
683
  e.device_temperature()],
669
684
  },
685
+ {
686
+ zigbeeModel: ['TemperLight'],
687
+ model: 'HS2WDS',
688
+ vendor: 'HEIMAN',
689
+ description: 'LED 9W CCT E27',
690
+ extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 370]}),
691
+ },
670
692
  {
671
693
  zigbeeModel: ['CurtainMo-EF-3.0', 'CurtainMo-EF'],
672
694
  model: 'HS2CM-N-DC',
package/devices/insta.js CHANGED
@@ -83,7 +83,7 @@ module.exports = [
83
83
  {ID: 242, profileID: 41440, deviceID: 97},
84
84
  ]},
85
85
  ],
86
- zigbeeModel: ['57004000'],
86
+ zigbeeModel: ['NEXENTRO Pushbutton Interface', '57004000'],
87
87
  model: '57004000',
88
88
  vendor: 'Insta',
89
89
  description: 'Pushbutton Interface 2-gang 230V',
package/devices/lellki.js CHANGED
@@ -133,14 +133,16 @@ module.exports = [
133
133
  description: 'Power cord 4 sockets EU (with power monitoring)',
134
134
  vendor: 'LELLKI',
135
135
  extend: extend.switch(),
136
- fromZigbee: [fz.on_off, fz.electrical_measurement, fz.metering, fz.ignore_basic_report, fz.tuya_switch_power_outage_memory],
136
+ fromZigbee: [fz.on_off_force_multiendpoint, fz.electrical_measurement, fz.metering, fz.ignore_basic_report,
137
+ fz.tuya_switch_power_outage_memory],
137
138
  toZigbee: [tz.on_off, tz.tuya_switch_power_outage_memory],
138
139
  configure: async (device, coordinatorEndpoint, logger) => {
139
140
  const endpoint = device.getEndpoint(1);
140
141
  await endpoint.read('genBasic', ['manufacturerName', 'zclVersion', 'appVersion', 'modelId', 'powerSource', 0xfffe]);
141
- await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
142
- await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
143
- await reporting.bind(device.getEndpoint(3), coordinatorEndpoint, ['genOnOff']);
142
+ for (const ep of [1, 2, 3]) {
143
+ await reporting.bind(device.getEndpoint(ep), coordinatorEndpoint, ['genOnOff']);
144
+ await reporting.onOff(device.getEndpoint(ep));
145
+ }
144
146
  endpoint.saveClusterAttributeKeyValue('haElectricalMeasurement', {acCurrentDivisor: 1000, acCurrentMultiplier: 1});
145
147
  endpoint.saveClusterAttributeKeyValue('seMetering', {divisor: 100, multiplier: 1});
146
148
  device.save();
@@ -3,6 +3,8 @@ const fz = {...require('../converters/fromZigbee'), legacy: require('../lib/lega
3
3
  const tz = require('../converters/toZigbee');
4
4
  const reporting = require('../lib/reporting');
5
5
  const extend = require('../lib/extend');
6
+ const e = exposes.presets;
7
+ const ea = exposes.access;
6
8
 
7
9
  module.exports = [
8
10
  {
@@ -83,4 +85,31 @@ module.exports = [
83
85
  .withSetpoint('occupied_cooling_setpoint', 10, 30, 1)
84
86
  .withLocalTemperatureCalibration(-30, 30, 0.1).withPiHeatingDemand()],
85
87
  },
88
+ {
89
+ // Reference from a similar switch: https://gist.github.com/nebhead/dc5a0a827ec14eef6196ded4be6e2dd0
90
+ zigbeeModel: ['ZS057'],
91
+ model: 'ZS057-D0Z',
92
+ vendor: 'Leviton',
93
+ description: 'Wall switch, 0-10V dimmer, 120-277V, Lumina™ RF',
94
+ extend: extend.light_onoff_brightness({disableEffect: true, noConfigure: true}),
95
+ fromZigbee: [fz.brightness, fz.identify, fz.lighting_ballast_configuration, fz.level_config],
96
+ toZigbee: [tz.light_onoff_brightness, tz.ballast_config, tz.level_config],
97
+ exposes: [e.light_brightness(),
98
+ exposes.numeric('ballast_minimum_level', ea.ALL).withValueMin(1).withValueMax(254)
99
+ .withDescription('Specifies the minimum brightness value'),
100
+ exposes.numeric('ballast_maximum_level', ea.ALL).withValueMin(1).withValueMax(254)
101
+ .withDescription('Specifies the maximum brightness value'),
102
+ exposes.numeric('ballast_power_on_level', ea.ALL).withValueMin(1).withValueMax(254)
103
+ .withDescription('Specifies the initialisation light level. Can not be set lower than "ballast_minimum_level"'),
104
+ exposes.numeric('ballast_physical_minimum_level', ea.ALL).withValueMin(1).withValueMax(254)
105
+ .withDescription('Specifies the minimum light output the ballast can achieve.'),
106
+ exposes.numeric('ballast_physical_maximum_level', ea.ALL).withValueMin(1).withValueMax(254)
107
+ .withDescription('Specifies the maximum light output the ballast can achieve.')],
108
+ configure: async (device, coordinatorEndpoint, logger) => {
109
+ await extend.light_onoff_brightness().configure(device, coordinatorEndpoint, logger);
110
+ const endpoint = device.getEndpoint(1);
111
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl', 'lightingBallastCfg']);
112
+ await reporting.onOff(endpoint);
113
+ },
114
+ },
86
115
  ];
package/devices/niko.js CHANGED
@@ -131,6 +131,29 @@ module.exports = [
131
131
  exposes.binary('led_enable', ea.ALL, true, false).withDescription('Enable LED'),
132
132
  ],
133
133
  },
134
+ {
135
+ zigbeeModel: ['Smart plug Zigbee SE'],
136
+ model: '552-80698',
137
+ vendor: 'Niko',
138
+ description: 'Smart plug with side earthing pin',
139
+ fromZigbee: [fz.on_off, fz.electrical_measurement, fz.metering, fz.power_on_behavior],
140
+ toZigbee: [tz.on_off, tz.power_on_behavior, tz.electrical_measurement_power, tz.currentsummdelivered],
141
+ configure: async (device, coordinatorEndpoint, logger) => {
142
+ const endpoint = device.getEndpoint(1);
143
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement', 'seMetering']);
144
+ await reporting.onOff(endpoint);
145
+ // only activePower seems to be support, although compliance document states otherwise
146
+ await endpoint.read('haElectricalMeasurement', ['acPowerMultiplier', 'acPowerDivisor']);
147
+ await reporting.activePower(endpoint);
148
+ await reporting.readMeteringMultiplierDivisor(endpoint);
149
+ await reporting.currentSummDelivered(endpoint, {min: 60, change: 1});
150
+ },
151
+ exposes: [
152
+ e.switch(), e.power().withAccess(ea.STATE_GET), e.energy().withAccess(ea.STATE_GET),
153
+ exposes.enum('power_on_behavior', ea.ALL, ['off', 'previous', 'on'])
154
+ .withDescription('Controls the behaviour when the device is powered on'),
155
+ ],
156
+ },
134
157
  {
135
158
  zigbeeModel: ['Smart plug Zigbee PE'],
136
159
  model: '552-80699',
@@ -2312,6 +2312,13 @@ module.exports = [
2312
2312
  description: 'Hue white filament Edison ST72 E27 LED',
2313
2313
  extend: hueExtend.light_onoff_brightness(),
2314
2314
  },
2315
+ {
2316
+ zigbeeModel: ['LWV004'],
2317
+ model: '8719514279193',
2318
+ vendor: 'Philips',
2319
+ description: 'Hue white filament Edison ST72 B22 LED',
2320
+ extend: hueExtend.light_onoff_brightness(),
2321
+ },
2315
2322
  {
2316
2323
  zigbeeModel: ['HML004'],
2317
2324
  model: '3115331PH',
@@ -2694,6 +2701,13 @@ module.exports = [
2694
2701
  description: 'Akari downlight',
2695
2702
  extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
2696
2703
  },
2704
+ {
2705
+ zigbeeModel: ['LCD005'],
2706
+ model: '9290031345',
2707
+ vendor: 'Philips',
2708
+ description: 'Hue white and color ambiance 4" retrofit recessed downlight',
2709
+ extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
2710
+ },
2697
2711
  {
2698
2712
  zigbeeModel: ['LCD006'],
2699
2713
  model: '9290031346',
@@ -2785,4 +2799,11 @@ module.exports = [
2785
2799
  description: 'Hue White ambiance Runner spot white (1 spot)',
2786
2800
  extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
2787
2801
  },
2802
+ {
2803
+ zigbeeModel: ['915005998101'],
2804
+ model: '915005998101',
2805
+ vendor: 'Philips',
2806
+ description: 'Hue white ambiance ceiling black Enrave',
2807
+ extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
2808
+ },
2788
2809
  ];
package/devices/siglis.js CHANGED
@@ -1,44 +1,41 @@
1
+ /* eslint-disable linebreak-style */
1
2
  const fz = require('../converters/fromZigbee');
2
3
  const tz = require('../converters/toZigbee');
3
4
  const exposes = require('../lib/exposes');
4
5
  const reporting = require('../lib/reporting');
5
6
  const e = exposes.presets;
7
+ const ea = exposes.access;
6
8
 
7
9
 
8
- const siglisManufacturerCode = 0x129C;
9
10
  const zigfredEndpoint = 5;
10
11
 
11
- const zifgredFromZigbee = {
12
- cluster: 'manuSpecificSiglisZigfred',
13
- type: ['attributeReport'],
14
- convert: (model, msg, publish, options, meta) => {
15
- const buttonEvent = msg.data['buttonEvent'];
16
-
17
- if (buttonEvent != null) {
18
- const buttonLookup = {
19
- 0: 'button_1',
20
- 1: 'button_2',
21
- 2: 'button_3',
22
- 3: 'button_4',
23
- };
12
+ const buttonLookup = {
13
+ 0: 'button_1',
14
+ 1: 'button_2',
15
+ 2: 'button_3',
16
+ 3: 'button_4',
17
+ };
24
18
 
25
- const actionLookup = {
26
- 0: 'release',
27
- 1: 'single',
28
- 2: 'double',
29
- 3: 'hold',
30
- };
19
+ const actionLookup = {
20
+ 0: 'release',
21
+ 1: 'single',
22
+ 2: 'double',
23
+ 3: 'hold',
24
+ };
31
25
 
32
- const button = buttonEvent & 0xff;
33
- const state = (buttonEvent >> 8) & 0xff;
26
+ const zifgredFromZigbeeButtonEvent = {
27
+ cluster: 'manuSpecificSiglisZigfred',
28
+ type: ['commandSiglisZigfredButtonEvent'],
29
+ convert: (model, msg, publish, options, meta) => {
30
+ const button = msg.data.button;
31
+ const type = msg.data.type;
34
32
 
35
- const buttonName = buttonLookup[button];
36
- const stateName = actionLookup[state];
33
+ const buttonName = buttonLookup[button];
34
+ const typeName = actionLookup[type];
37
35
 
38
- if (buttonName && stateName) {
39
- const action = `${buttonName}_${stateName}`;
40
- return {action};
41
- }
36
+ if (buttonName && typeName) {
37
+ const action = `${buttonName}_${typeName}`;
38
+ return {action};
42
39
  }
43
40
  },
44
41
  };
@@ -63,6 +60,37 @@ const coverAndLightToZigbee = {
63
60
  },
64
61
  };
65
62
 
63
+ const buttonEventExposes = e.action([
64
+ 'button_1_single', 'button_1_double', 'button_1_hold', 'button_1_release',
65
+ 'button_2_single', 'button_2_double', 'button_2_hold', 'button_2_release',
66
+ 'button_3_single', 'button_3_double', 'button_3_hold', 'button_3_release',
67
+ 'button_4_single', 'button_4_double', 'button_4_hold', 'button_4_release',
68
+ ]);
69
+
70
+ function checkOption(device, options, key) {
71
+ if (options.hasOwnProperty(key)) {
72
+ if (options[key] === 'true') {
73
+ return true;
74
+ } else if (options[key] === 'false') {
75
+ return false;
76
+ }
77
+ }
78
+
79
+ return checkMetaOption(device, key);
80
+ }
81
+
82
+ function checkMetaOption(device, key) {
83
+ const enabled = device.meta[key];
84
+ if (enabled === undefined) {
85
+ return false;
86
+ } else {
87
+ return !!enabled;
88
+ }
89
+ }
90
+
91
+ function setMetaOption(device, key, enabled) {
92
+ device.meta[key] = enabled;
93
+ }
66
94
 
67
95
  module.exports = [
68
96
  {
@@ -70,15 +98,44 @@ module.exports = [
70
98
  model: 'ZFU-1D-CH',
71
99
  vendor: 'Siglis',
72
100
  description: 'zigfred uno smart in-wall switch',
73
- exposes: [e.light_brightness_colorxy().withEndpoint('l1'), e.switch().withEndpoint('l2'), e.light_brightness().withEndpoint('l3'),
74
- e.action([
75
- 'button_1_single', 'button_1_double', 'button_1_hold', 'button_1_release',
76
- 'button_2_single', 'button_2_double', 'button_2_hold', 'button_2_release',
77
- 'button_3_single', 'button_3_double', 'button_3_hold', 'button_3_release',
78
- 'button_4_single', 'button_4_double', 'button_4_hold', 'button_4_release',
79
- ])],
101
+ options: [
102
+ exposes.enum(`front_surface_enabled`, ea.SET, ['auto', 'true', 'false'])
103
+ .withDescription('Front Surface LED enabled'),
104
+ exposes.enum(`relay_enabled`, ea.SET, ['auto', 'true', 'false'])
105
+ .withDescription('Relay enabled'),
106
+ exposes.enum(`dimmer_enabled`, ea.SET, ['auto', 'true', 'false'])
107
+ .withDescription('Dimmer enabled'),
108
+ exposes.enum(`dimmer_dimming_enabled`, ea.SET, ['auto', 'true', 'false'])
109
+ .withDescription('Dimmer dimmable'),
110
+ ],
111
+ exposes: (device, options) => {
112
+ const expose = [];
113
+
114
+ expose.push(buttonEventExposes);
115
+ expose.push(e.linkquality());
116
+
117
+ if (device != null && options != null) {
118
+ if (checkOption(device, options, 'front_surface_enabled')) {
119
+ expose.push(e.light_brightness_colorxy().withEndpoint('l1'));
120
+ }
121
+
122
+ if (checkOption(device, options, 'relay_enabled')) {
123
+ expose.push(e.switch().withEndpoint('l2'));
124
+ }
125
+
126
+ if (checkOption(device, options, 'dimmer_enabled')) {
127
+ if (checkOption(device, options, 'dimmer_dimming_enabled')) {
128
+ expose.push(e.light_brightness().withEndpoint('l3'));
129
+ } else {
130
+ expose.push(e.switch().withEndpoint('l3'));
131
+ }
132
+ }
133
+ }
134
+
135
+ return expose;
136
+ },
80
137
  fromZigbee: [
81
- zifgredFromZigbee,
138
+ zifgredFromZigbeeButtonEvent,
82
139
  fz.color_colortemp,
83
140
  fz.on_off,
84
141
  fz.brightness,
@@ -108,31 +165,38 @@ module.exports = [
108
165
  'l3': 7,
109
166
  };
110
167
  },
111
- configure: async (device, coordinatorEndpoint, logger) => {
112
- const controlEp = device.getEndpoint(zigfredEndpoint);
113
- const relayEp = device.getEndpoint(6);
114
- const dimmerEp = device.getEndpoint(7);
115
-
116
- // Bind Control EP (LED)
117
- await reporting.bind(controlEp, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl', 'manuSpecificSiglisZigfred']);
118
- await reporting.onOff(controlEp);
119
- await reporting.brightness(controlEp);
120
- const payload = [{
121
- attribute: 'buttonEvent',
122
- minimumReportInterval: 0,
123
- maximumReportInterval: 0,
124
- reportableChange: 0,
125
- }];
126
- await controlEp.configureReporting('manuSpecificSiglisZigfred', payload, {manufacturerCode: siglisManufacturerCode});
127
-
128
- // Bind Relay EP
129
- await reporting.bind(relayEp, coordinatorEndpoint, ['genOnOff']);
130
- await reporting.onOff(relayEp);
131
-
132
- // Bind Dimmer EP
133
- await reporting.bind(dimmerEp, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
134
- await reporting.onOff(dimmerEp);
135
- await reporting.brightness(dimmerEp);
168
+ configure: async (device, coordinatorEndpoint, logger, options) => {
169
+ if (device != null) {
170
+ const controlEp = device.getEndpoint(zigfredEndpoint);
171
+ const relayEp = device.getEndpoint(6);
172
+ const dimmerEp = device.getEndpoint(7);
173
+
174
+ // Bind Control EP (LED)
175
+ setMetaOption(device, 'front_surface_enabled', (await controlEp.read('genBasic', ['deviceEnabled'])).deviceEnabled);
176
+ if (checkMetaOption(device, 'front_surface_enabled')) {
177
+ await reporting.bind(controlEp, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl', 'manuSpecificSiglisZigfred']);
178
+ await reporting.onOff(controlEp);
179
+ await reporting.brightness(controlEp);
180
+ }
181
+
182
+ // Bind Relay EP
183
+ setMetaOption(device, 'relay_enabled', (await relayEp.read('genBasic', ['deviceEnabled'])).deviceEnabled);
184
+ if (checkMetaOption(device, 'relay_enabled')) {
185
+ await reporting.bind(relayEp, coordinatorEndpoint, ['genOnOff']);
186
+ await reporting.onOff(relayEp);
187
+ }
188
+
189
+ // Bind Dimmer EP
190
+ setMetaOption(device, 'dimmer_enabled', (await dimmerEp.read('genBasic', ['deviceEnabled'])).deviceEnabled);
191
+ if (checkMetaOption(device, 'dimmer_enabled')) {
192
+ await reporting.bind(dimmerEp, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
193
+ await reporting.onOff(dimmerEp);
194
+ await reporting.brightness(dimmerEp);
195
+ }
196
+ setMetaOption(device, 'dimmer_dimming_enabled', true);
197
+
198
+ device.save();
199
+ }
136
200
  },
137
201
  },
138
202
  {
@@ -140,24 +204,106 @@ module.exports = [
140
204
  model: 'ZFP-1A-CH',
141
205
  vendor: 'Siglis',
142
206
  description: 'zigfred plus smart in-wall switch',
143
- exposes: [
144
- e.light_brightness_colorxy().withEndpoint('l1'),
145
- e.light_brightness().withEndpoint('l2'),
146
- e.light_brightness().withEndpoint('l3'),
147
- e.light_brightness().withEndpoint('l4'),
148
- e.light_brightness().withEndpoint('l5'),
149
- exposes.cover().setAccess('state', exposes.access.STATE_SET | exposes.access.STATE_GET)
150
- .withPosition().withTilt().withEndpoint('l6'),
151
- exposes.cover().setAccess('state', exposes.access.STATE_SET | exposes.access.STATE_GET)
152
- .withPosition().withTilt().withEndpoint('l7'),
153
- e.action([
154
- 'button_1_single', 'button_1_double', 'button_1_hold', 'button_1_release',
155
- 'button_2_single', 'button_2_double', 'button_2_hold', 'button_2_release',
156
- 'button_3_single', 'button_3_double', 'button_3_hold', 'button_3_release',
157
- 'button_4_single', 'button_4_double', 'button_4_hold', 'button_4_release',
158
- ])],
207
+ options: [
208
+ exposes.enum(`front_surface_enabled`, ea.SET, ['auto', 'true', 'false'])
209
+ .withDescription('Front Surface LED enabled'),
210
+ exposes.enum(`dimmer_1_enabled`, ea.SET, ['auto', 'true', 'false'])
211
+ .withDescription('Dimmer 1 enabled'),
212
+ exposes.enum(`dimmer_1_dimming_enabled`, ea.SET, ['auto', 'true', 'false'])
213
+ .withDescription('Dimmer 1 dimmable'),
214
+ exposes.enum(`dimmer_2_enabled`, ea.SET, ['auto', 'true', 'false'])
215
+ .withDescription('Dimmer 2 enabled'),
216
+ exposes.enum(`dimmer_2_dimming_enabled`, ea.SET, ['auto', 'true', 'false'])
217
+ .withDescription('Dimmer 2 dimmable'),
218
+ exposes.enum(`dimmer_3_enabled`, ea.SET, ['auto', 'true', 'false'])
219
+ .withDescription('Dimmer 3 enabled'),
220
+ exposes.enum(`dimmer_3_dimming_enabled`, ea.SET, ['auto', 'true', 'false'])
221
+ .withDescription('Dimmer 3 dimmable'),
222
+ exposes.enum(`dimmer_4_enabled`, ea.SET, ['auto', 'true', 'false'])
223
+ .withDescription('Dimmer 4 enabled'),
224
+ exposes.enum(`dimmer_4_dimming_enabled`, ea.SET, ['auto', 'true', 'false'])
225
+ .withDescription('Dimmer 4 dimmable'),
226
+ exposes.enum(`cover_1_enabled`, ea.SET, ['auto', 'true', 'false'])
227
+ .withDescription('Cover 1 enabled'),
228
+ exposes.enum(`cover_1_tilt_enabled`, ea.SET, ['auto', 'true', 'false'])
229
+ .withDescription('Cover 1 tiltable'),
230
+ exposes.enum(`cover_2_enabled`, ea.SET, ['auto', 'true', 'false'])
231
+ .withDescription('Cover 2 enabled'),
232
+ exposes.enum(`cover_2_tilt_enabled`, ea.SET, ['auto', 'true', 'false'])
233
+ .withDescription('Cover 2 tiltable'),
234
+ ],
235
+ exposes: (device, options) => {
236
+ const expose = [];
237
+
238
+ expose.push(buttonEventExposes);
239
+ expose.push(e.linkquality());
240
+
241
+ if (device != null && options != null) {
242
+ if (checkOption(device, options, 'front_surface_enabled')) {
243
+ expose.push(e.light_brightness_colorxy().withEndpoint('l1'));
244
+ }
245
+
246
+ if (checkOption(device, options, 'dimmer_1_enabled')) {
247
+ if (checkOption(device, options, 'dimmer_1_dimming_enabled')) {
248
+ expose.push(e.light_brightness().withEndpoint('l2'));
249
+ } else {
250
+ expose.push(e.switch().withEndpoint('l2'));
251
+ }
252
+ }
253
+
254
+ if (checkOption(device, options, 'dimmer_2_enabled')) {
255
+ if (checkOption(device, options, 'dimmer_2_dimming_enabled')) {
256
+ expose.push(e.light_brightness().withEndpoint('l3'));
257
+ } else {
258
+ expose.push(e.switch().withEndpoint('l3'));
259
+ }
260
+ }
261
+
262
+ if (checkOption(device, options, 'dimmer_3_enabled')) {
263
+ if (checkOption(device, options, 'dimmer_3_dimming_enabled')) {
264
+ expose.push(e.light_brightness().withEndpoint('l4'));
265
+ } else {
266
+ expose.push(e.switch().withEndpoint('l4'));
267
+ }
268
+ }
269
+
270
+ if (checkOption(device, options, 'dimmer_4_enabled')) {
271
+ if (checkOption(device, options, 'dimmer_4_dimming_enabled')) {
272
+ expose.push(e.light_brightness().withEndpoint('l5'));
273
+ } else {
274
+ expose.push(e.switch().withEndpoint('l5'));
275
+ }
276
+ }
277
+
278
+ if (checkOption(device, options, 'cover_1_enabled')) {
279
+ if (checkOption(device, options, 'cover_1_tilt_enabled')) {
280
+ expose.push(exposes.cover()
281
+ .setAccess('state', exposes.access.STATE_SET | exposes.access.STATE_GET)
282
+ .withPosition().withTilt().withEndpoint('l6'));
283
+ } else {
284
+ expose.push(exposes.cover()
285
+ .setAccess('state', exposes.access.STATE_SET | exposes.access.STATE_GET)
286
+ .withPosition().withEndpoint('l6'));
287
+ }
288
+ }
289
+
290
+ if (checkOption(device, options, 'cover_2_enabled')) {
291
+ if (checkOption(device, options, 'cover_2_tilt_enabled')) {
292
+ expose.push(exposes.cover()
293
+ .setAccess('state', exposes.access.STATE_SET | exposes.access.STATE_GET)
294
+ .withPosition().withTilt().withEndpoint('l7'));
295
+ } else {
296
+ expose.push(exposes.cover()
297
+ .setAccess('state', exposes.access.STATE_SET | exposes.access.STATE_GET)
298
+ .withPosition().withEndpoint('l7'));
299
+ }
300
+ }
301
+ }
302
+
303
+ return expose;
304
+ },
159
305
  fromZigbee: [
160
- zifgredFromZigbee,
306
+ zifgredFromZigbeeButtonEvent,
161
307
  fz.color_colortemp,
162
308
  fz.on_off,
163
309
  fz.brightness,
@@ -196,55 +342,93 @@ module.exports = [
196
342
  'l7': 12,
197
343
  };
198
344
  },
199
- configure: async (device, coordinatorEndpoint, logger) => {
200
- // Bind Control EP (LED)
201
- const controlEp = device.getEndpoint(zigfredEndpoint);
202
- await reporting.bind(controlEp, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl', 'manuSpecificSiglisZigfred']);
203
- await reporting.onOff(controlEp);
204
- await reporting.brightness(controlEp);
205
- const payload = [{
206
- attribute: 'buttonEvent',
207
- minimumReportInterval: 0,
208
- maximumReportInterval: 0,
209
- reportableChange: 0,
210
- }];
211
- await controlEp.configureReporting('manuSpecificSiglisZigfred', payload, {manufacturerCode: siglisManufacturerCode});
212
-
213
- // Bind Dimmer 1 EP
214
- const dimmer1Ep = device.getEndpoint(7);
215
- await reporting.bind(dimmer1Ep, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
216
- await reporting.onOff(dimmer1Ep);
217
- await reporting.brightness(dimmer1Ep);
218
-
219
- // Bind Dimmer 2 EP
220
- const dimmer2Ep = device.getEndpoint(8);
221
- await reporting.bind(dimmer2Ep, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
222
- await reporting.onOff(dimmer2Ep);
223
- await reporting.brightness(dimmer2Ep);
224
-
225
- // Bind Dimmer 3 EP
226
- const dimmer3Ep = device.getEndpoint(9);
227
- await reporting.bind(dimmer3Ep, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
228
- await reporting.onOff(dimmer3Ep);
229
- await reporting.brightness(dimmer3Ep);
230
-
231
- // Bind Dimmer 4 EP
232
- const dimmer4Ep = device.getEndpoint(10);
233
- await reporting.bind(dimmer4Ep, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
234
- await reporting.onOff(dimmer4Ep);
235
- await reporting.brightness(dimmer4Ep);
236
-
237
- // Bind Cover 1 EP
238
- const cover1Ep = device.getEndpoint(11);
239
- await reporting.bind(cover1Ep, coordinatorEndpoint, ['closuresWindowCovering']);
240
- await reporting.currentPositionLiftPercentage(cover1Ep);
241
- await reporting.currentPositionTiltPercentage(cover1Ep);
242
-
243
- // Bind Cover 2 EP
244
- const cover2Ep = device.getEndpoint(12);
245
- await reporting.bind(cover2Ep, coordinatorEndpoint, ['closuresWindowCovering']);
246
- await reporting.currentPositionLiftPercentage(cover2Ep);
247
- await reporting.currentPositionTiltPercentage(cover2Ep);
345
+ configure: async (device, coordinatorEndpoint, logger, options) => {
346
+ if (device != null) {
347
+ // Bind Control EP (LED)
348
+ const controlEp = device.getEndpoint(zigfredEndpoint);
349
+ setMetaOption(device, 'front_surface_enabled', (await controlEp.read('genBasic', ['deviceEnabled'])).deviceEnabled);
350
+ if (checkMetaOption(device, 'front_surface_enabled')) {
351
+ await reporting.bind(controlEp, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl', 'manuSpecificSiglisZigfred']);
352
+ await reporting.onOff(controlEp);
353
+ await reporting.brightness(controlEp);
354
+ }
355
+
356
+ // Bind Dimmer 1 EP
357
+ const dimmer1Ep = device.getEndpoint(7);
358
+ setMetaOption(device, 'dimmer_1_enabled', (await dimmer1Ep.read('genBasic', ['deviceEnabled'])).deviceEnabled);
359
+ if (checkMetaOption(device, 'dimmer_1_enabled')) {
360
+ await reporting.bind(dimmer1Ep, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
361
+ await reporting.onOff(dimmer1Ep);
362
+ await reporting.brightness(dimmer1Ep);
363
+ }
364
+ setMetaOption(device, 'dimmer_1_dimming_enabled', true);
365
+
366
+ // Bind Dimmer 2 EP
367
+ const dimmer2Ep = device.getEndpoint(8);
368
+ setMetaOption(device, 'dimmer_2_enabled', (await dimmer2Ep.read('genBasic', ['deviceEnabled'])).deviceEnabled);
369
+ if (checkMetaOption(device, 'dimmer_2_enabled')) {
370
+ await reporting.bind(dimmer2Ep, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
371
+ await reporting.onOff(dimmer2Ep);
372
+ await reporting.brightness(dimmer2Ep);
373
+ }
374
+ setMetaOption(device, 'dimmer_2_dimming_enabled', true);
375
+
376
+ // Bind Dimmer 3 EP
377
+ const dimmer3Ep = device.getEndpoint(9);
378
+ setMetaOption(device, 'dimmer_3_enabled', (await dimmer3Ep.read('genBasic', ['deviceEnabled'])).deviceEnabled);
379
+ if (checkMetaOption(device, 'dimmer_3_enabled')) {
380
+ await reporting.bind(dimmer3Ep, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
381
+ await reporting.onOff(dimmer3Ep);
382
+ await reporting.brightness(dimmer3Ep);
383
+ }
384
+ setMetaOption(device, 'dimmer_3_dimming_enabled', true);
385
+
386
+ // Bind Dimmer 4 EP
387
+ const dimmer4Ep = device.getEndpoint(10);
388
+ setMetaOption(device, 'dimmer_4_enabled', (await dimmer4Ep.read('genBasic', ['deviceEnabled'])).deviceEnabled);
389
+ if (checkMetaOption(device, 'dimmer_4_enabled')) {
390
+ await reporting.bind(dimmer4Ep, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
391
+ await reporting.onOff(dimmer4Ep);
392
+ await reporting.brightness(dimmer4Ep);
393
+ }
394
+ setMetaOption(device, 'dimmer_4_dimming_enabled', true);
395
+
396
+ // Bind Cover 1 EP
397
+ const cover1Ep = device.getEndpoint(11);
398
+ setMetaOption(device, 'cover_1_enabled', (await cover1Ep.read('genBasic', ['deviceEnabled'])).deviceEnabled);
399
+ if (checkMetaOption(device, 'cover_1_enabled')) {
400
+ await reporting.bind(cover1Ep, coordinatorEndpoint, ['closuresWindowCovering']);
401
+ await reporting.currentPositionLiftPercentage(cover1Ep);
402
+ setMetaOption(
403
+ device,
404
+ 'cover_1_tilt_enabled',
405
+ (await cover1Ep.read('closuresWindowCovering', ['windowCoveringType'])).windowCoveringType === 0x08);
406
+ if (checkMetaOption(device, 'cover_1_tilt_enabled')) {
407
+ await reporting.currentPositionTiltPercentage(cover1Ep);
408
+ }
409
+ } else {
410
+ setMetaOption(device, 'cover_1_tilt_enabled', false);
411
+ }
412
+
413
+ // Bind Cover 2 EP
414
+ const cover2Ep = device.getEndpoint(12);
415
+ setMetaOption(device, 'cover_2_enabled', (await cover2Ep.read('genBasic', ['deviceEnabled'])).deviceEnabled);
416
+ if (checkMetaOption(device, 'cover_2_enabled')) {
417
+ await reporting.bind(cover2Ep, coordinatorEndpoint, ['closuresWindowCovering']);
418
+ await reporting.currentPositionLiftPercentage(cover2Ep);
419
+ setMetaOption(
420
+ device,
421
+ 'cover_2_tilt_enabled',
422
+ (await cover2Ep.read('closuresWindowCovering', ['windowCoveringType'])).windowCoveringType === 0x08);
423
+ if (checkMetaOption(device, 'cover_2_tilt_enabled')) {
424
+ await reporting.currentPositionTiltPercentage(cover2Ep);
425
+ }
426
+ } else {
427
+ setMetaOption(device, 'cover_2_tilt_enabled', false);
428
+ }
429
+
430
+ device.save();
431
+ }
248
432
  },
249
433
  },
250
434
  ];
package/devices/xiaomi.js CHANGED
@@ -886,8 +886,7 @@ module.exports = [
886
886
  e.switch().withEndpoint('right'),
887
887
  e.power().withAccess(ea.STATE_GET),
888
888
  e.action([
889
- 'hold_left', 'single_left', 'double_left', 'release_left', 'hold_right', 'single_right',
890
- 'double_right', 'release_right', 'hold_both', 'single_both', 'double_both', 'release_both',
889
+ 'hold_left', 'single_left', 'double_left', 'single_right', 'double_right', 'single_both', 'double_both',
891
890
  ]),
892
891
  exposes.enum('operation_mode', ea.ALL, ['control_left_relay', 'decoupled'])
893
892
  .withDescription('Decoupled mode for left button')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zigbee-herdsman-converters",
3
- "version": "14.0.628",
3
+ "version": "14.0.630",
4
4
  "description": "Collection of device converters to be used with zigbee-herdsman",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -38,7 +38,7 @@
38
38
  "buffer-crc32": "^0.2.13",
39
39
  "https-proxy-agent": "^5.0.1",
40
40
  "tar-stream": "^2.2.0",
41
- "zigbee-herdsman": "^0.14.55"
41
+ "zigbee-herdsman": "^0.14.59"
42
42
  },
43
43
  "devDependencies": {
44
44
  "eslint": "*",