zigbee-herdsman-converters 15.0.21 → 15.0.22

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.
@@ -30,8 +30,10 @@ const converters = {
30
30
  cluster: 'hvacFanCtrl',
31
31
  type: ['attributeReport', 'readResponse'],
32
32
  convert: (model, msg, publish, options, meta) => {
33
- const key = getKey(constants.fanMode, msg.data.fanMode);
34
- return {fan_mode: key, fan_state: key === 'off' ? 'OFF' : 'ON'};
33
+ if (msg.data.hasOwnProperty('fanMode')) {
34
+ const key = getKey(constants.fanMode, msg.data.fanMode);
35
+ return {fan_mode: key, fan_state: key === 'off' ? 'OFF' : 'ON'};
36
+ }
35
37
  },
36
38
  },
37
39
  thermostat: {
@@ -978,9 +980,9 @@ const converters = {
978
980
  },
979
981
  ias_smoke_alarm_1: {
980
982
  cluster: 'ssIasZone',
981
- type: 'commandStatusChangeNotification',
983
+ type: ['commandStatusChangeNotification', 'attributeReport', 'readResponse'],
982
984
  convert: (model, msg, publish, options, meta) => {
983
- const zoneStatus = msg.data.zonestatus;
985
+ const zoneStatus = msg.type === 'commandStatusChangeNotification' ? msg.data.zonestatus : msg.data.zoneStatus;
984
986
  return {
985
987
  smoke: (zoneStatus & 1) > 0,
986
988
  tamper: (zoneStatus & 1<<2) > 0,
@@ -990,6 +992,7 @@ const converters = {
990
992
  trouble: (zoneStatus & 1<<6) > 0,
991
993
  ac_status: (zoneStatus & 1<<7) > 0,
992
994
  test: (zoneStatus & 1<<8) > 0,
995
+ battery_defect: (zoneStatus & 1<<9) > 0,
993
996
  };
994
997
  },
995
998
  },
@@ -4018,7 +4021,7 @@ const converters = {
4018
4021
  return {deadzone_temperature: value};
4019
4022
  case tuya.dataPoints.moesLocalTemp:
4020
4023
  temperature = value & 1<<15 ? value - (1<<16) + 1 : value;
4021
- if (!['_TZE200_ztvwu4nk', '_TZE200_ye5jkfsb'].includes(meta.device.manufacturerName)) {
4024
+ if (!['_TZE200_ztvwu4nk', '_TZE200_ye5jkfsb', '_TZE200_5toc8efa'].includes(meta.device.manufacturerName)) {
4022
4025
  // https://github.com/Koenkk/zigbee2mqtt/issues/11980
4023
4026
  temperature = temperature / 10;
4024
4027
  }
package/devices/awox.js CHANGED
@@ -151,6 +151,13 @@ module.exports = [
151
151
  {ID: 3, profileID: 4751, deviceID: 268, inputClusters: [65360, 65361], outputClusters: [65360, 65361]},
152
152
  ],
153
153
  },
154
+ {
155
+ type: 'Router', manufacturerName: 'AwoX', modelID: 'TLSR82xx', endpoints: [
156
+ {ID: 1, profileID: 260, deviceID: 268, inputClusters: [0, 3, 4, 5, 6, 8, 768, 4096, 64599, 10], outputClusters: [6]},
157
+ {ID: 242, profileID: 41440, deviceID: 97, inputClusters: [], outputClusters: [33]},
158
+ {ID: 3, profileID: 4751, deviceID: 268, inputClusters: [65360, 65361, 4], outputClusters: [65360, 65361]},
159
+ ],
160
+ },
154
161
  ],
155
162
  model: '33957',
156
163
  vendor: 'AwoX',
package/devices/datek.js CHANGED
@@ -15,7 +15,7 @@ module.exports = [
15
15
  vendor: 'Datek',
16
16
  description: 'APEX smart plug 16A',
17
17
  fromZigbee: [fz.on_off, fz.electrical_measurement, fz.temperature],
18
- toZigbee: [tz.on_off],
18
+ toZigbee: [tz.on_off, tz.power_on_behavior],
19
19
  configure: async (device, coordinatorEndpoint, logger) => {
20
20
  const endpoint = device.getEndpoint(1);
21
21
  await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement', 'msTemperatureMeasurement']);
@@ -28,7 +28,7 @@ module.exports = [
28
28
  await reporting.activePower(endpoint);
29
29
  await reporting.temperature(endpoint);
30
30
  },
31
- exposes: [e.power(), e.current(), e.voltage(), e.switch(), e.temperature()],
31
+ exposes: [e.power(), e.current(), e.voltage(), e.switch(), e.temperature(), e.power_on_behavior()],
32
32
  },
33
33
  {
34
34
  fingerprint: [{modelID: 'Meter Reader', manufacturerName: 'Eva'}],
package/devices/hgkg.js CHANGED
@@ -42,7 +42,7 @@ module.exports = [
42
42
  .withPreset(['hold', 'program'])
43
43
  .withFanMode(['off', 'low', 'medium', 'high', 'auto'], ea.STATE_SET),
44
44
  e.temperature_sensor_select(['IN', 'AL', 'OU']),
45
- exposes.composite('programming_mode')
45
+ exposes.composite('programming_mode', 'programming_mode', ea.STATE)
46
46
  .withDescription(
47
47
  'Schedule MODE ⏱ - In this mode, the device executes a preset week programming temperature time and temperature.',
48
48
  )
@@ -162,7 +162,7 @@ module.exports = [
162
162
  exposes: [e.battery(), e.action([
163
163
  'color_move', 'color_temperature_move', 'hue_move', 'hue_stop', 'brightness_step_up', 'brightness_step_down',
164
164
  'recall_*', 'on', 'off']),
165
- exposes.composite('action_color', 'action_color')
165
+ exposes.composite('action_color', 'action_color', ea.STATE)
166
166
  .withFeature(exposes.numeric('x', ea.STATE))
167
167
  .withFeature(exposes.numeric('y', ea.STATE))
168
168
  .withDescription('Only shows the transmitted color in X7Y-Mode. Noch changes possible.'),
@@ -1077,10 +1077,10 @@ const exposesList = [
1077
1077
  e.power(),
1078
1078
  e.energy(),
1079
1079
  exposes
1080
- .composite('led_effect', 'led_effect')
1080
+ .composite('led_effect', 'led_effect', ea.STATE_SET)
1081
1081
  .withFeature(
1082
1082
  exposes
1083
- .enum('effect', ea.SET_STATE, [
1083
+ .enum('effect', ea.STATE_SET, [
1084
1084
  'off',
1085
1085
  'solid',
1086
1086
  'fast_blink',
@@ -1107,7 +1107,7 @@ const exposesList = [
1107
1107
  )
1108
1108
  .withFeature(
1109
1109
  exposes
1110
- .numeric('color', ea.SET_STATE)
1110
+ .numeric('color', ea.STATE_SET)
1111
1111
  .withValueMin(0)
1112
1112
  .withValueMax(255)
1113
1113
  .withDescription(
@@ -1116,14 +1116,14 @@ const exposesList = [
1116
1116
  )
1117
1117
  .withFeature(
1118
1118
  exposes
1119
- .numeric('level', ea.SET_STATE)
1119
+ .numeric('level', ea.STATE_SET)
1120
1120
  .withValueMin(0)
1121
1121
  .withValueMax(100)
1122
1122
  .withDescription('Brightness of the LEDs'),
1123
1123
  )
1124
1124
  .withFeature(
1125
1125
  exposes
1126
- .numeric('duration', ea.SET_STATE)
1126
+ .numeric('duration', ea.STATE_SET)
1127
1127
  .withValueMin(0)
1128
1128
  .withValueMax(255)
1129
1129
  .withDescription(
@@ -1133,15 +1133,15 @@ const exposesList = [
1133
1133
  ),
1134
1134
  ),
1135
1135
  exposes
1136
- .composite('individual_led_effect', 'individual_led_effect')
1136
+ .composite('individual_led_effect', 'individual_led_effect', ea.STATE_SET)
1137
1137
  .withFeature(
1138
1138
  exposes
1139
- .enum('led', ea.SET_STATE, ['1', '2', '3', '4', '5', '6', '7'])
1139
+ .enum('led', ea.STATE_SET, ['1', '2', '3', '4', '5', '6', '7'])
1140
1140
  .withDescription('Individual LED to target.'),
1141
1141
  )
1142
1142
  .withFeature(
1143
1143
  exposes
1144
- .enum('effect', ea.SET_STATE, [
1144
+ .enum('effect', ea.STATE_SET, [
1145
1145
  'off',
1146
1146
  'solid',
1147
1147
  'fast_blink',
@@ -1157,7 +1157,7 @@ const exposesList = [
1157
1157
  )
1158
1158
  .withFeature(
1159
1159
  exposes
1160
- .numeric('color', ea.SET_STATE)
1160
+ .numeric('color', ea.STATE_SET)
1161
1161
  .withValueMin(0)
1162
1162
  .withValueMax(255)
1163
1163
  .withDescription(
@@ -1166,14 +1166,14 @@ const exposesList = [
1166
1166
  )
1167
1167
  .withFeature(
1168
1168
  exposes
1169
- .numeric('level', ea.SET_STATE)
1169
+ .numeric('level', ea.STATE_SET)
1170
1170
  .withValueMin(0)
1171
1171
  .withValueMax(100)
1172
1172
  .withDescription('Brightness of the LED'),
1173
1173
  )
1174
1174
  .withFeature(
1175
1175
  exposes
1176
- .numeric('duration', ea.SET_STATE)
1176
+ .numeric('duration', ea.STATE_SET)
1177
1177
  .withValueMin(0)
1178
1178
  .withValueMax(255)
1179
1179
  .withDescription(
package/devices/lidl.js CHANGED
@@ -524,7 +524,7 @@ module.exports = [
524
524
  description: 'Melinera smart LED string lights',
525
525
  toZigbee: [tz.on_off, tz.silvercrest_smart_led_string],
526
526
  fromZigbee: [fz.on_off, fz.silvercrest_smart_led_string],
527
- exposes: [e.light_brightness_colorhs().setAccess('brightness', ea.STATE_SET)],
527
+ exposes: [e.light_brightness_colorhs().setAccess('brightness', ea.STATE_SET).setAccess('color_hs', ea.STATE_SET)],
528
528
  },
529
529
  {
530
530
  fingerprint: [{modelID: 'TS0505A', manufacturerName: '_TZ3000_odygigth'}],
@@ -874,7 +874,8 @@ module.exports = [
874
874
  exposes.binary('binary_one', ea.STATE_SET, 'ON', 'OFF').withDescription('Unknown binary one'),
875
875
  exposes.binary('binary_two', ea.STATE_SET, 'ON', 'OFF').withDescription('Unknown binary two'),
876
876
  exposes.binary('away_mode', ea.STATE, 'ON', 'OFF').withDescription('Away mode'),
877
- exposes.composite('away_setting', 'away_setting').withFeature(e.away_preset_days()).setAccess('away_preset_days', ea.ALL)
877
+ exposes.composite('away_setting', 'away_setting', ea.STATE_SET)
878
+ .withFeature(e.away_preset_days()).setAccess('away_preset_days', ea.ALL)
878
879
  .withFeature(e.away_preset_temperature()).setAccess('away_preset_temperature', ea.ALL)
879
880
  .withFeature(exposes.numeric('away_preset_year', ea.ALL).withUnit('year').withDescription('Start away year 20xx'))
880
881
  .withFeature(exposes.numeric('away_preset_month', ea.ALL).withUnit('month').withDescription('Start away month'))
@@ -882,7 +883,7 @@ module.exports = [
882
883
  .withFeature(exposes.numeric('away_preset_hour', ea.ALL).withUnit('hour').withDescription('Start away hours'))
883
884
  .withFeature(exposes.numeric('away_preset_minute', ea.ALL).withUnit('min').withDescription('Start away minutes')),
884
885
  ...['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'].map((day) => {
885
- const expose = exposes.composite(day, day);
886
+ const expose = exposes.composite(day, day, ea.STATE_SET);
886
887
  [1, 2, 3, 4, 5, 6, 7, 8, 9].forEach((i) => {
887
888
  expose.withFeature(exposes.numeric(`${day}_temp_${i}`, ea.ALL).withValueMin(0.5)
888
889
  .withValueMax(29.5).withValueStep(0.5).withUnit('°C').withDescription(`Temperature ${i}`));
package/devices/livolo.js CHANGED
@@ -205,7 +205,7 @@ module.exports = [
205
205
  toZigbee: [tz.livolo_cover_state, tz.livolo_cover_position, tz.livolo_cover_options],
206
206
  exposes: [
207
207
  e.cover_position().setAccess('position', ea.STATE_SET),
208
- exposes.composite('options', 'options')
208
+ exposes.composite('options', 'options', ea.STATE_SET)
209
209
  .withDescription('Motor options')
210
210
  .withFeature(exposes.numeric('motor_speed', ea.STATE_SET)
211
211
  .withValueMin(20)
@@ -46,7 +46,7 @@ module.exports = [
46
46
  model: 'FUT036Z',
47
47
  description: 'Single color LED controller',
48
48
  vendor: 'Miboxer',
49
- extend: extend.light_onoff_brightness(),
49
+ extend: extend.light_onoff_brightness({disablePowerOnBehavior: true}),
50
50
  onEvent: tuya.onEventSetTime,
51
51
  },
52
52
  {
package/devices/moes.js CHANGED
@@ -114,7 +114,7 @@ module.exports = [
114
114
  .withSystemMode(['off', 'heat'], ea.STATE_SET).withRunningState(['idle', 'heat', 'cool'], ea.STATE)
115
115
  .withPreset(['hold', 'program']),
116
116
  e.temperature_sensor_select(['IN', 'AL', 'OU']),
117
- exposes.composite('program', 'program').withDescription('Time of day and setpoint to use when in program mode')
117
+ exposes.composite('program', 'program', ea.STATE_SET).withDescription('Time of day and setpoint to use when in program mode')
118
118
  .withFeature(exposesLocal.hour('weekdays_p1_hour'))
119
119
  .withFeature(exposesLocal.minute('weekdays_p1_minute'))
120
120
  .withFeature(exposesLocal.program_temperature('weekdays_p1_temperature'))
@@ -308,9 +308,9 @@ module.exports = [
308
308
  'You can set up to 4 stages of temperature every for WEEKDAY ➀➁➂➃➄, SATURDAY ➅ and SUNDAY ➆.'),
309
309
  exposes.binary('boost_heating', ea.STATE_SET, 'ON', 'OFF').withDescription('Boost Heating: press and hold "+" for 3 seconds, ' +
310
310
  'the device will enter the boost heating mode, and the ▷╵◁ will flash. The countdown will be displayed in the APP'),
311
- exposes.numeric('boost_heating_countdown', ea.STATE).withUnit('Min').withDescription('Countdown in minutes')
311
+ exposes.numeric('boost_heating_countdown', ea.STATE).withUnit('minutes').withDescription('Countdown in minutes')
312
312
  .withValueMin(0).withValueMax(15),
313
- exposes.numeric('boost_heating_countdown_time_set', ea.STATE_SET).withUnit('second')
313
+ exposes.numeric('boost_heating_countdown_time_set', ea.STATE_SET).withUnit('seconds')
314
314
  .withDescription('Boost Time Setting 100 sec - 900 sec, (default = 300 sec)').withValueMin(100)
315
315
  .withValueMax(900).withValueStep(100)],
316
316
  },
package/devices/nue_3a.js CHANGED
@@ -370,4 +370,27 @@ module.exports = [
370
370
  return {left: 1, right: 2};
371
371
  },
372
372
  },
373
+ {
374
+ zigbeeModel: ['LXN56-1S27LX1.2', 'LXX60-FN27LX1.0'],
375
+ model: 'NUE-ZBFLB',
376
+ vendor: 'Nue / 3A',
377
+ description: 'Smart fan light switch',
378
+ extend: extend.switch(),
379
+ exposes: [
380
+ e.switch().withEndpoint('button_light'),
381
+ e.switch().withEndpoint('button_fan_high'),
382
+ e.switch().withEndpoint('button_fan_med'),
383
+ e.switch().withEndpoint('button_fan_low'),
384
+ ],
385
+ endpoint: (device) => {
386
+ return {'button_light': 1, 'button_fan_high': 2, 'button_fan_med': 3, 'button_fan_low': 4};
387
+ },
388
+ meta: {multiEndpoint: true},
389
+ configure: async (device, coordinatorEndpoint, logger) => {
390
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
391
+ await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
392
+ await reporting.bind(device.getEndpoint(3), coordinatorEndpoint, ['genOnOff']);
393
+ await reporting.bind(device.getEndpoint(4), coordinatorEndpoint, ['genOnOff']);
394
+ },
395
+ },
373
396
  ];
@@ -5,6 +5,7 @@ const constants = require('../lib/constants');
5
5
  const reporting = require('../lib/reporting');
6
6
  const extend = require('../lib/extend');
7
7
  const utils = require('../lib/utils');
8
+ const ota = require('../lib/ota');
8
9
  const e = exposes.presets;
9
10
  const ea = exposes.access;
10
11
 
@@ -981,4 +982,28 @@ module.exports = [
981
982
  .withUnit('A').withDescription('Instantaneous measured electrical current on phase C'),
982
983
  ],
983
984
  },
985
+ {
986
+ zigbeeModel: ['W599001'],
987
+ model: 'W599001',
988
+ vendor: 'Schneider Electric',
989
+ description: 'Wiser smoke alarm',
990
+ fromZigbee: [fz.temperature, fz.battery, fz.ias_enroll, fz.ias_smoke_alarm_1],
991
+ toZigbee: [],
992
+ ota: ota.zigbeeOTA, // local OTA updates are untested
993
+ exposes: [e.smoke(), e.battery_low(), e.tamper(), e.battery(), e.battery_voltage(),
994
+ // the temperature readings are unreliable and may need more investigation.
995
+ e.temperature(),
996
+ ],
997
+ configure: async (device, coordinatorEndpoint, logger) => {
998
+ const endpoint = device.getEndpoint(20);
999
+ const binds = ['msTemperatureMeasurement', 'ssIasZone', 'genPowerCfg'];
1000
+ await reporting.bind(endpoint, coordinatorEndpoint, binds);
1001
+ await reporting.batteryPercentageRemaining(endpoint);
1002
+ await reporting.batteryVoltage(endpoint);
1003
+ await reporting.temperature(endpoint);
1004
+ await endpoint.read('msTemperatureMeasurement', ['measuredValue']);
1005
+ await endpoint.read('ssIasZone', ['iasCieAddr', 'zoneState', 'zoneStatus', 'zoneId']);
1006
+ await endpoint.read('genPowerCfg', ['batteryVoltage', 'batteryPercentageRemaining']);
1007
+ },
1008
+ },
984
1009
  ];
@@ -620,7 +620,7 @@ module.exports = [
620
620
  },
621
621
  exposes: [e.battery(), e.lock(), exposes.enum('door_state', ea.STATE, ['open', 'closed']).withDescription('Door status'),
622
622
  e.lock_action(), e.lock_action_source_name(), e.lock_action_user(),
623
- exposes.composite('pin_code', 'pin_code')
623
+ exposes.composite('pin_code', 'pin_code', ea.ALL)
624
624
  .withFeature(exposes.numeric('user', ea.SET).withDescription('User ID can only number 1'))
625
625
  .withFeature(exposes.numeric('pin_code', ea.SET).withDescription('Pincode to set, set pincode(4 digit) to null to clear')),
626
626
  ],
package/devices/sinope.js CHANGED
@@ -860,12 +860,12 @@ module.exports = [
860
860
  .withDescription('Control status LED intensity when load ON'),
861
861
  exposes.numeric('led_intensity_off', ea.ALL).withValueMin(0).withValueMax(100)
862
862
  .withDescription('Control status LED intensity when load OFF'),
863
- exposes.composite('led_color_on', 'led_color_on')
863
+ exposes.composite('led_color_on', 'led_color_on', ea.SET)
864
864
  .withFeature(exposes.numeric('r', ea.SET))
865
865
  .withFeature(exposes.numeric('g', ea.SET))
866
866
  .withFeature(exposes.numeric('b', ea.SET))
867
867
  .withDescription('Control status LED color when load ON'),
868
- exposes.composite('led_color_off', 'led_color_off')
868
+ exposes.composite('led_color_off', 'led_color_off', ea.SET)
869
869
  .withFeature(exposes.numeric('r', ea.SET))
870
870
  .withFeature(exposes.numeric('g', ea.SET))
871
871
  .withFeature(exposes.numeric('b', ea.SET))
@@ -894,12 +894,12 @@ module.exports = [
894
894
  .withDescription('Control status LED when load OFF'),
895
895
  exposes.numeric('minimum_brightness', ea.ALL).withValueMin(0).withValueMax(3000)
896
896
  .withDescription('Control minimum dimmer brightness'),
897
- exposes.composite('led_color_on', 'led_color_on')
897
+ exposes.composite('led_color_on', 'led_color_on', ea.SET)
898
898
  .withFeature(exposes.numeric('r', ea.SET))
899
899
  .withFeature(exposes.numeric('g', ea.SET))
900
900
  .withFeature(exposes.numeric('b', ea.SET))
901
901
  .withDescription('Control status LED color when load ON'),
902
- exposes.composite('led_color_off', 'led_color_off')
902
+ exposes.composite('led_color_off', 'led_color_off', ea.SET)
903
903
  .withFeature(exposes.numeric('r', ea.SET))
904
904
  .withFeature(exposes.numeric('g', ea.SET))
905
905
  .withFeature(exposes.numeric('b', ea.SET))
@@ -930,7 +930,7 @@ module.exports = [
930
930
  await reporting.activePower(endpoint, {min: 10, max: 305, change: 1}); // divider 10 : 0.1W
931
931
  await reporting.rmsCurrent(endpoint, {min: 10, max: 306, change: 10}); // divider 100: 0.1Arms
932
932
  await reporting.rmsVoltage(endpoint, {min: 10, max: 307, change: 10}); // divider 100: 0.1Vrms
933
- await reporting.currentSummDelivered(endpoint, {min: 10, max: 303, change: [1, 1]});
933
+ await reporting.currentSummDelivered(endpoint, {min: 10, max: 303, change: [0, 1]}); // divider 1
934
934
  },
935
935
  },
936
936
  {
@@ -950,7 +950,7 @@ module.exports = [
950
950
  await reporting.activePower(endpoint, {min: 10, max: 305, change: 1}); // divider 10 : 0.1W
951
951
  await reporting.rmsCurrent(endpoint, {min: 10, max: 306, change: 10}); // divider 100: 0.1Arms
952
952
  await reporting.rmsVoltage(endpoint, {min: 10, max: 307, change: 10}); // divider 100: 0.1Vrms
953
- await reporting.currentSummDelivered(endpoint, {min: 10, max: 303, change: [1, 1]});
953
+ await reporting.currentSummDelivered(endpoint, {min: 10, max: 303, change: [0, 1]}); // divider 1
954
954
  },
955
955
  },
956
956
  {
@@ -48,7 +48,7 @@ module.exports = [
48
48
  toZigbee: [tz.tuya_dimmer_state, tz.tuya_light_wz5],
49
49
  exposes: [
50
50
  exposes.light().withBrightness().setAccess('state', ea.STATE_SET).setAccess('brightness',
51
- ea.STATE_SET).withColor(['hs']),
51
+ ea.STATE_SET).withColor(['hs']).setAccess('color_hs', ea.STATE_SET),
52
52
  ],
53
53
  },
54
54
  {
@@ -71,7 +71,7 @@ module.exports = [
71
71
  toZigbee: [tz.tuya_dimmer_state, tz.tuya_light_wz5],
72
72
  exposes: [
73
73
  exposes.light().withBrightness().setAccess('state', ea.STATE_SET).setAccess('brightness',
74
- ea.STATE_SET).withColor(['hs']),
74
+ ea.STATE_SET).withColor(['hs']).setAccess('color_hs', ea.STATE_SET),
75
75
  exposes.numeric('white_brightness', ea.STATE_SET).withValueMin(0).withValueMax(254).withDescription(
76
76
  'White brightness of this light'),
77
77
  ],
@@ -90,7 +90,7 @@ module.exports = [
90
90
  exposes: [
91
91
  exposes.light().withBrightness().setAccess('state', ea.STATE_SET).setAccess('brightness',
92
92
  ea.STATE_SET).withColor(['hs']).withColorTemp([250, 454]).setAccess('color_temp',
93
- ea.STATE_SET),
93
+ ea.STATE_SET).setAccess('color_hs', ea.STATE_SET),
94
94
  exposes.numeric('white_brightness', ea.STATE_SET).withValueMin(0).withValueMax(254).withDescription(
95
95
  'White brightness of this light'),
96
96
  ],
@@ -1,7 +1,4 @@
1
- const exposes = require('../lib/exposes');
2
- const reporting = require('../lib/reporting');
3
1
  const extend = require('../lib/extend');
4
- const e = exposes.presets;
5
2
 
6
3
  module.exports = [
7
4
  {
@@ -18,23 +15,4 @@ module.exports = [
18
15
  description: 'Power plug',
19
16
  extend: extend.switch(),
20
17
  },
21
- {
22
- zigbeeModel: ['LXN56-1S27LX1.2'],
23
- model: 'NUE-ZBFLB',
24
- vendor: 'Nue / 3A',
25
- description: 'Smart fan light switch',
26
- extend: extend.switch(),
27
- exposes: [e.switch().withEndpoint('button_light'), e.switch().withEndpoint('button_fan_high'),
28
- e.switch().withEndpoint('button_fan_med'), e.switch().withEndpoint('button_fan_low')],
29
- endpoint: (device) => {
30
- return {'button_light': 1, 'button_fan_high': 2, 'button_fan_med': 3, 'button_fan_low': 4};
31
- },
32
- meta: {multiEndpoint: true},
33
- configure: async (device, coordinatorEndpoint, logger) => {
34
- await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
35
- await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
36
- await reporting.bind(device.getEndpoint(3), coordinatorEndpoint, ['genOnOff']);
37
- await reporting.bind(device.getEndpoint(4), coordinatorEndpoint, ['genOnOff']);
38
- },
39
- },
40
18
  ];
@@ -126,8 +126,7 @@ module.exports = [
126
126
  model: 'GP-WOU019BBDWG',
127
127
  vendor: 'SmartThings',
128
128
  description: 'Outlet with power meter',
129
- fromZigbee: [fz.on_off, fz.electrical_measurement, fz.metering],
130
- toZigbee: [tz.on_off],
129
+ extend: extend.switch({fromZigbee: [fz.electrical_measurement, fz.metering], exposes: [e.power(), e.energy()]}),
131
130
  configure: async (device, coordinatorEndpoint, logger) => {
132
131
  const endpoint = device.getEndpoint(1);
133
132
  await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement', 'seMetering']);
@@ -139,7 +138,6 @@ module.exports = [
139
138
  await reporting.readMeteringMultiplierDivisor(endpoint);
140
139
  await reporting.currentSummDelivered(endpoint);
141
140
  },
142
- exposes: [e.switch(), e.power(), e.energy()],
143
141
  },
144
142
  {
145
143
  zigbeeModel: ['outlet'],
@@ -271,6 +271,14 @@ module.exports = [
271
271
  description: 'Constant Current Zigbee LED dimmable driver',
272
272
  extend: extend.light_onoff_brightness(),
273
273
  },
274
+ {
275
+ zigbeeModel: ['HK-DIM'],
276
+ model: '50208702',
277
+ vendor: 'Sunricher',
278
+ description: 'LED dimmable driver',
279
+ extend: extend.light_onoff_brightness(),
280
+ whiteLabel: [{vendor: 'Yphix', model: '50208702'}],
281
+ },
274
282
  {
275
283
  zigbeeModel: ['SR-ZG9040A-S'],
276
284
  model: 'SR-ZG9040A-S',
package/devices/tuya.js CHANGED
@@ -1009,6 +1009,8 @@ module.exports = [
1009
1009
  vendor: 'TuYa',
1010
1010
  description: 'Zigbee RGBW light',
1011
1011
  extend: extend.light_onoff_brightness_color({disablePowerOnBehavior: true}),
1012
+ exposes: [e.light_brightness_color({disablePowerOnBehavior: true})
1013
+ .setAccess('color_xy', ea.STATE_SET).setAccess('color_hs', ea.STATE_SET)],
1012
1014
  toZigbee: utils.replaceInArray(extend.light_onoff_brightness_color().toZigbee, [tz.light_color], [tzLocal.TS0504B_color]),
1013
1015
  meta: {applyRedFix: true},
1014
1016
  },
@@ -1153,11 +1155,18 @@ module.exports = [
1153
1155
  exposes.enum('sensitivity', ea.ALL, ['low', 'medium', 'high']).withDescription('PIR sensor sensitivity'),
1154
1156
  exposes.enum('keep_time', ea.ALL, [30, 60, 120]).withDescription('PIR keep time in seconds'),
1155
1157
  ],
1158
+ configure: async (device, coordinatorEndpoint, logger) => {
1159
+ const endpoint = device.getEndpoint(1);
1160
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
1161
+ await reporting.batteryPercentageRemaining(endpoint);
1162
+ await reporting.batteryVoltage(endpoint);
1163
+ },
1156
1164
  },
1157
1165
  {
1158
1166
  fingerprint: [{modelID: 'TS0207', manufacturerName: '_TZ3000_m0vaazab'},
1159
1167
  {modelID: 'TS0207', manufacturerName: '_TZ3000_ufttklsz'},
1160
1168
  {modelID: 'TS0207', manufacturerName: '_TZ3000_nkkl7uzv'},
1169
+ {modelID: 'TS0207', manufacturerName: '_TZ3000_misw04hq'},
1161
1170
  {modelID: 'TS0207', manufacturerName: '_TZ3000_gszjt2xx'},
1162
1171
  {modelID: 'TS0207', manufacturerName: '_TZ3000_5k5vh43t'}],
1163
1172
  model: 'TS0207_repeater',
@@ -2109,7 +2118,7 @@ module.exports = [
2109
2118
  toZigbee: [tz.tuya_cover_control, tz.tuya_cover_options],
2110
2119
  exposes: [
2111
2120
  e.cover_position().setAccess('position', ea.STATE_SET),
2112
- exposes.composite('options', 'options')
2121
+ exposes.composite('options', 'options', ea.STATE_SET)
2113
2122
  .withFeature(exposes.numeric('motor_speed', ea.STATE_SET)
2114
2123
  .withValueMin(0)
2115
2124
  .withValueMax(255)
@@ -2168,7 +2177,7 @@ module.exports = [
2168
2177
  .withRunningState(['idle', 'heat'], ea.STATE),
2169
2178
  e.auto_lock(), e.away_mode(), e.away_preset_days(), e.boost_time(), e.comfort_temperature(), e.eco_temperature(), e.force(),
2170
2179
  e.max_temperature(), e.min_temperature(), e.away_preset_temperature(),
2171
- exposes.composite('programming_mode').withDescription('Schedule MODE ⏱ - In this mode, ' +
2180
+ exposes.composite('programming_mode', 'programming_mode', ea.STATE).withDescription('Schedule MODE ⏱ - In this mode, ' +
2172
2181
  'the device executes a preset week programming temperature time and temperature.')
2173
2182
  .withFeature(e.week())
2174
2183
  .withFeature(exposes.text('workdays_schedule', ea.STATE_SET))
@@ -2224,7 +2233,7 @@ module.exports = [
2224
2233
  '- schedule for Monday used for each day (define it only for Monday). `mon_fri+sat+sun` - schedule for ' +
2225
2234
  'workdays used from Monday (define it only for Monday), Saturday and Sunday are defined separately. `separate` ' +
2226
2235
  '- schedule for each day is defined separately.'),
2227
- exposes.composite('schedule', 'schedule').withFeature(exposes.enum('week_day', ea.SET, ['monday', 'tuesday',
2236
+ exposes.composite('schedule', 'schedule', ea.SET).withFeature(exposes.enum('week_day', ea.SET, ['monday', 'tuesday',
2228
2237
  'wednesday', 'thursday', 'friday', 'saturday', 'sunday'])).withFeature(exposes.text('schedule', ea.SET))
2229
2238
  .withDescription('Schedule will work with "auto" preset. In this mode, the device executes ' +
2230
2239
  'a preset week programming temperature time and temperature. Before using these properties, check `working_day` ' +
@@ -2447,7 +2456,7 @@ module.exports = [
2447
2456
  'ON - In this mode, the thermostat stays open ' +
2448
2457
  'OFF - In this mode, the thermostat stays closed')
2449
2458
  .withSystemMode(['auto', 'heat', 'off'], ea.STATE_SET),
2450
- exposes.composite('programming_mode').withDescription('Auto MODE ⏱ - In this mode, ' +
2459
+ exposes.composite('programming_mode', 'programming_mode', ea.STATE).withDescription('Auto MODE ⏱ - In this mode, ' +
2451
2460
  'the device executes a preset week programming temperature time and temperature. ')
2452
2461
  .withFeature(exposes.text('monday_schedule', ea.STATE))
2453
2462
  .withFeature(exposes.text('tuesday_schedule', ea.STATE))
package/devices/ubisys.js CHANGED
@@ -704,7 +704,7 @@ module.exports = [
704
704
  'brightness_move_up_s2', 'brightness_move_down_s1', 'brightness_move_down_s2', 'brightness_stop_s1',
705
705
  'brightness_stop_s2']),
706
706
  e.light_brightness(),
707
- exposes.composite('level_config', 'level_config')
707
+ exposes.composite('level_config', 'level_config', ea.ALL)
708
708
  .withFeature(exposes.numeric('on_off_transition_time', ea.ALL)
709
709
  .withDescription('Specifies the amount of time, in units of 0.1 seconds, which will be used during a transition to ' +
710
710
  'either the on or off state, when an on/off/toggle command of the on/off cluster is used to turn the light on or off'))
package/devices/xiaomi.js CHANGED
@@ -2311,17 +2311,17 @@ module.exports = [
2311
2311
  .withDescription('Standby LCD brightness'),
2312
2312
  exposes.enum('available_switches', ea.STATE_SET, ['none', '1', '2', '3', '1 and 2', '1 and 3', '2 and 3', 'all'])
2313
2313
  .withDescription('Control which switches are available in the switches screen (none disables switches screen)'),
2314
- exposes.composite('switch_1_text_icon', 'switch_1_text_icon').withDescription('Switch 1 text and icon')
2314
+ exposes.composite('switch_1_text_icon', 'switch_1_text_icon', ea.STATE_SET).withDescription('Switch 1 text and icon')
2315
2315
  .withFeature(exposes.enum('switch_1_icon', ea.STATE_SET, ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11'])
2316
2316
  .withDescription('Icon'))
2317
2317
  .withFeature(exposes.text('switch_1_text', ea.STATE_SET)
2318
2318
  .withDescription('Text')),
2319
- exposes.composite('switch_2_text_icon', 'switch_2_text_icon').withDescription('Switch 2 text and icon')
2319
+ exposes.composite('switch_2_text_icon', 'switch_2_text_icon', ea.STATE_SET).withDescription('Switch 2 text and icon')
2320
2320
  .withFeature(exposes.enum('switch_2_icon', ea.STATE_SET, ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11'])
2321
2321
  .withDescription('Icon'))
2322
2322
  .withFeature(exposes.text('switch_2_text', ea.STATE_SET)
2323
2323
  .withDescription('Text')),
2324
- exposes.composite('switch_3_text_icon', 'switch_3_text_icon').withDescription('Switch 3 text and icon')
2324
+ exposes.composite('switch_3_text_icon', 'switch_3_text_icon', ea.STATE_SET).withDescription('Switch 3 text and icon')
2325
2325
  .withFeature(exposes.enum('switch_3_icon', ea.STATE_SET, ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11'])
2326
2326
  .withDescription('Icon'))
2327
2327
  .withFeature(exposes.text('switch_3_text', ea.STATE_SET)
@@ -2714,7 +2714,7 @@ module.exports = [
2714
2714
  exposes.numeric('weight_per_day', ea.STATE).withDescription('Weight per day').withUnit('g'),
2715
2715
  exposes.binary('error', ea.STATE, true, false)
2716
2716
  .withDescription('Indicates wether there is an error with the feeder'),
2717
- exposes.list('schedule', ea.STATE_SET, exposes.composite('dayTime', exposes.access.STATE_SET)
2717
+ exposes.list('schedule', ea.STATE_SET, exposes.composite('dayTime', 'dayTime', exposes.access.STATE_SET)
2718
2718
  .withFeature(exposes.enum('days', exposes.access.STATE_SET, [
2719
2719
  'everyday', 'workdays', 'weekend', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun',
2720
2720
  'mon-wed-fri-sun', 'tue-thu-sat']))
@@ -149,8 +149,8 @@ module.exports = [
149
149
  fromZigbee: [fz.ZMAM02_cover],
150
150
  toZigbee: [tz.ZMAM02_cover],
151
151
  exposes: [e.cover_position().setAccess('position', ea.STATE_SET),
152
- exposes.composite('options', 'options')
153
- .withFeature(exposes.numeric('motor_speed', ea.STATE_SET)
152
+ exposes.composite('options', 'options', ea.STATE)
153
+ .withFeature(exposes.numeric('motor_speed', ea.STATE)
154
154
  .withValueMin(0)
155
155
  .withValueMax(255)
156
156
  .withDescription('Motor speed')),
package/lib/exposes.js CHANGED
@@ -194,12 +194,13 @@ class Text extends Base {
194
194
  }
195
195
 
196
196
  class Composite extends Base {
197
- constructor(name, property) {
197
+ constructor(name, property, access) {
198
198
  super();
199
199
  this.type = 'composite';
200
200
  this.property = property;
201
201
  this.name = name;
202
202
  this.features = [];
203
+ this.access = access;
203
204
  }
204
205
 
205
206
  withFeature(feature) {
@@ -237,7 +238,7 @@ class Light extends Base {
237
238
 
238
239
  withLevelConfig() {
239
240
  assert(!this.endpoint, 'Cannot add feature after adding endpoint');
240
- const levelConfig = new Composite('level_config', 'level_config')
241
+ const levelConfig = new Composite('level_config', 'level_config', access.ALL)
241
242
  .withFeature(new Numeric('on_off_transition_time', access.ALL)
242
243
  .withDescription('Represents the time taken to move to or from the target level when On of Off commands are received by an On/Off cluster'),
243
244
  )
@@ -313,13 +314,13 @@ class Light extends Base {
313
314
  assert(!this.endpoint, 'Cannot add feature after adding endpoint');
314
315
  for (const type of types) {
315
316
  if (type === 'xy') {
316
- const colorXY = new Composite('color_xy', 'color')
317
+ const colorXY = new Composite('color_xy', 'color', access.ALL)
317
318
  .withFeature(new Numeric('x', access.ALL))
318
319
  .withFeature(new Numeric('y', access.ALL))
319
320
  .withDescription('Color of this light in the CIE 1931 color space (x/y)');
320
321
  this.features.push(colorXY);
321
322
  } else if (type === 'hs') {
322
- const colorHS = new Composite('color_hs', 'color')
323
+ const colorHS = new Composite('color_hs', 'color', access.ALL)
323
324
  .withFeature(new Numeric('hue', access.ALL))
324
325
  .withFeature(new Numeric('saturation', access.ALL))
325
326
  .withDescription('Color of this light expressed as hue/saturation');
@@ -491,7 +492,7 @@ module.exports = {
491
492
  access,
492
493
  binary: (name, access, valueOn, valueOff) => new Binary(name, access, valueOn, valueOff),
493
494
  climate: () => new Climate(),
494
- composite: (name, property) => new Composite(name, property),
495
+ composite: (name, property, access) => new Composite(name, property, access),
495
496
  cover: () => new Cover(),
496
497
  enum: (name, access, values) => new Enum(name, access, values),
497
498
  light: () => new Light(),
@@ -509,7 +510,7 @@ module.exports = {
509
510
  occupancy_timeout: () => new Numeric(`occupancy_timeout`, access.SET).withValueMin(0).withDescription('Time in seconds after which occupancy is cleared after detecting it (default 90 seconds).'),
510
511
  occupancy_timeout_2: () => new Numeric(`occupancy_timeout`, access.SET).withValueMin(0).withValueStep(0.1).withUnit('s').withDescription('Time in seconds after which occupancy is cleared after detecting it (default is "detection_interval" + 2 seconds). The value must be equal to or greater than "detection_interval", and it can also be a fraction.'),
511
512
  vibration_timeout: () => new Numeric(`vibration_timeout`, access.SET).withValueMin(0).withDescription('Time in seconds after which vibration is cleared after detecting it (default 90 seconds).'),
512
- simulated_brightness: (extraNote='') => new Composite('simulated_brightness', 'simulated_brightness')
513
+ simulated_brightness: (extraNote='') => new Composite('simulated_brightness', 'simulated_brightness', access.SET)
513
514
  .withDescription(`Simulate a brightness value. If this device provides a brightness_move_up or brightness_move_down action it is possible to specify the update interval and delta. The action_brightness_delta indicates the delta for each interval. ${extraNote}`)
514
515
  .withFeature(new Numeric('delta', access.SET).withValueMin(0).withDescription('Delta per interval, 20 by default'))
515
516
  .withFeature(new Numeric('interval', access.SET).withValueMin(0).withUnit('ms').withDescription('Interval duration')),
@@ -637,7 +638,7 @@ module.exports = {
637
638
  voltage_phase_b: () => new Numeric('voltage_phase_b', access.STATE).withUnit('V').withDescription('Measured electrical potential value on phase B'),
638
639
  voltage_phase_c: () => new Numeric('voltage_phase_c', access.STATE).withUnit('V').withDescription('Measured electrical potential value on phase C'),
639
640
  water_leak: () => new Binary('water_leak', access.STATE, true, false).withDescription('Indicates whether the device detected a water leak'),
640
- warning: () => new Composite('warning', 'warning')
641
+ warning: () => new Composite('warning', 'warning', access.SET)
641
642
  .withFeature(new Enum('mode', access.SET, ['stop', 'burglar', 'fire', 'emergency', 'police_panic', 'fire_panic', 'emergency_panic']).withDescription('Mode of the warning (sound effect)'))
642
643
  .withFeature(new Enum('level', access.SET, ['low', 'medium', 'high', 'very_high']).withDescription('Sound level'))
643
644
  .withFeature(new Enum('strobe_level', access.SET, ['low', 'medium', 'high', 'very_high']).withDescription('Intensity of the strobe'))
@@ -650,12 +651,12 @@ module.exports = {
650
651
  x_axis: () => new Numeric('x_axis', access.STATE).withDescription('Accelerometer X value'),
651
652
  y_axis: () => new Numeric('y_axis', access.STATE).withDescription('Accelerometer Y value'),
652
653
  z_axis: () => new Numeric('z_axis', access.STATE).withDescription('Accelerometer Z value'),
653
- pincode: () => new Composite('pin_code', 'pin_code')
654
+ pincode: () => new Composite('pin_code', 'pin_code', access.ALL)
654
655
  .withFeature(new Numeric('user', access.SET).withDescription('User ID to set or clear the pincode for'))
655
656
  .withFeature(new Enum('user_type', access.SET, ['unrestricted', 'year_day_schedule', 'week_day_schedule', 'master', 'non_access']).withDescription('Type of user, unrestricted: owner (default), (year|week)_day_schedule: user has ability to open lock based on specific time period, master: user has ability to both program and operate the door lock, non_access: user is recognized by the lock but does not have the ability to open the lock'))
656
657
  .withFeature(new Binary('user_enabled', access.SET, true, false).withDescription('Whether the user is enabled/disabled'))
657
658
  .withFeature(new Numeric('pin_code', access.SET).withDescription('Pincode to set, set pincode to null to clear')),
658
- squawk: () => new Composite('squawk', 'squawk')
659
+ squawk: () => new Composite('squawk', 'squawk', access.SET)
659
660
  .withFeature(new Enum('state', access.SET, ['system_is_armed', 'system_is_disarmed']).withDescription('Set Squawk state'))
660
661
  .withFeature(new Enum('level', access.SET, ['low', 'medium', 'high', 'very_high']).withDescription('Sound level'))
661
662
  .withFeature(new Binary('strobe', access.SET, true, false).withDescription('Turn on/off the strobe (light) for Squawk')),
package/lib/extend.js CHANGED
@@ -6,10 +6,10 @@ const light = require('./light');
6
6
 
7
7
  const extend = {
8
8
  switch: (options={}) => {
9
- options = {disablePowerOnBehavior: false, ...options};
10
- const exposes = [e.switch()];
11
- const fromZigbee = [fz.on_off, fz.ignore_basic_report];
12
- const toZigbee = [tz.on_off];
9
+ options = {disablePowerOnBehavior: false, toZigbee: [], fromZigbee: [], exposes: [], ...options};
10
+ const exposes = [e.switch(), ...options.exposes];
11
+ const fromZigbee = [fz.on_off, fz.ignore_basic_report, ...options.fromZigbee];
12
+ const toZigbee = [tz.on_off, ...options.toZigbee];
13
13
  if (!options.disablePowerOnBehavior) {
14
14
  exposes.push(e.power_on_behavior(['off', 'on', 'toggle', 'previous']));
15
15
  fromZigbee.push(fz.power_on_behavior);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zigbee-herdsman-converters",
3
- "version": "15.0.21",
3
+ "version": "15.0.22",
4
4
  "description": "Collection of device converters to be used with zigbee-herdsman",
5
5
  "main": "index.js",
6
6
  "files": [