zigbee-herdsman-converters 14.0.671 → 14.0.673

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.
@@ -2973,7 +2973,7 @@ const converters = {
2973
2973
  convert: (model, msg, publish, options, meta) => {
2974
2974
  const stateHeader = Buffer.from([122, 209]);
2975
2975
  if (msg.data.indexOf(stateHeader) === 0) {
2976
- if (msg.data[10] === 5) {
2976
+ if (msg.data[10] === 5 || msg.data[10] === 2) {
2977
2977
  const status = msg.data[14];
2978
2978
  return {
2979
2979
  state_left: status === 1 ? 'ON' : 'OFF',
@@ -8120,17 +8120,6 @@ const converters = {
8120
8120
  }
8121
8121
  },
8122
8122
  },
8123
- dawon_card_holder: {
8124
- cluster: 'ssIasZone',
8125
- type: 'commandStatusChangeNotification',
8126
- convert: (model, msg, publish, options, meta) => {
8127
- const zoneStatus = msg.data.zonestatus;
8128
- return {
8129
- card: (zoneStatus & 1) > 0,
8130
- battery_low: (zoneStatus & 1<<3) > 0,
8131
- };
8132
- },
8133
- },
8134
8123
  tuya_light_wz5: {
8135
8124
  cluster: 'manuSpecificTuya',
8136
8125
  type: ['commandDataResponse', 'commandDataReport'],
@@ -6,6 +6,30 @@ const extend = require('../lib/extend');
6
6
  const e = exposes.presets;
7
7
  const ea = exposes.access;
8
8
 
9
+ const fzLocal = {
10
+ dawon_card_holder: {
11
+ cluster: 'ssIasZone',
12
+ type: 'commandStatusChangeNotification',
13
+ convert: (model, msg, publish, options, meta) => {
14
+ const zoneStatus = msg.data.zonestatus;
15
+ return {
16
+ card: (zoneStatus & 1) > 0,
17
+ battery_low: (zoneStatus & 1<<3) > 0,
18
+ };
19
+ },
20
+ },
21
+ };
22
+
23
+
24
+ const tzLocal = {
25
+ dawon_card_holder: {
26
+ key: ['card'],
27
+ convertGet: async (entity, key, meta) => {
28
+ await entity.read('ssIasZone', ['zoneState']);
29
+ },
30
+ },
31
+ };
32
+
9
33
  module.exports = [
10
34
  {
11
35
  zigbeeModel: ['PM-C140-ZB'],
@@ -13,15 +37,16 @@ module.exports = [
13
37
  vendor: 'Dawon DNS',
14
38
  description: 'IOT remote control smart buried-type outlet',
15
39
  fromZigbee: [fz.on_off, fz.metering],
16
- toZigbee: [tz.on_off],
40
+ toZigbee: [tz.on_off, tz.metering_power, tz.currentsummdelivered],
17
41
  configure: async (device, coordinatorEndpoint, logger) => {
18
42
  const endpoint = device.getEndpoint(1);
19
43
  await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'seMetering']);
20
44
  await reporting.onOff(endpoint);
21
45
  await reporting.readMeteringMultiplierDivisor(endpoint);
22
46
  await reporting.instantaneousDemand(endpoint);
47
+ await reporting.currentSummDelivered(endpoint, {min: 10, max: 3600, change: 5});
23
48
  },
24
- exposes: [e.switch(), e.power(), e.energy()],
49
+ exposes: [e.switch(), e.power().withAccess(ea.STATE_GET), e.energy().withAccess(ea.STATE_GET)],
25
50
  },
26
51
  {
27
52
  zigbeeModel: ['PM-B530-ZB'],
@@ -29,15 +54,16 @@ module.exports = [
29
54
  vendor: 'Dawon DNS',
30
55
  description: 'IOT smart plug 16A',
31
56
  fromZigbee: [fz.on_off, fz.metering],
32
- toZigbee: [tz.on_off],
57
+ toZigbee: [tz.on_off, tz.metering_power, tz.currentsummdelivered],
33
58
  configure: async (device, coordinatorEndpoint, logger) => {
34
59
  const endpoint = device.getEndpoint(1);
35
60
  await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'seMetering']);
36
61
  await reporting.onOff(endpoint);
37
62
  await reporting.readMeteringMultiplierDivisor(endpoint);
38
63
  await reporting.instantaneousDemand(endpoint);
64
+ await reporting.currentSummDelivered(endpoint, {min: 10, max: 3600, change: 5});
39
65
  },
40
- exposes: [e.switch(), e.power(), e.energy()],
66
+ exposes: [e.switch(), e.power().withAccess(ea.STATE_GET), e.energy().withAccess(ea.STATE_GET)],
41
67
  },
42
68
  {
43
69
  zigbeeModel: ['PM-B540-ZB'],
@@ -45,13 +71,14 @@ module.exports = [
45
71
  vendor: 'Dawon DNS',
46
72
  description: 'IOT smart plug 16A',
47
73
  fromZigbee: [fz.device_temperature, fz.on_off, fz.metering],
48
- toZigbee: [tz.on_off],
74
+ toZigbee: [tz.on_off, tz.metering_power, tz.currentsummdelivered],
49
75
  configure: async (device, coordinatorEndpoint, logger) => {
50
76
  const endpoint = device.getEndpoint(1);
51
77
  await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'seMetering', 'genDeviceTempCfg']);
52
78
  await reporting.onOff(endpoint);
53
79
  await reporting.readMeteringMultiplierDivisor(endpoint);
54
80
  await reporting.instantaneousDemand(endpoint);
81
+ await reporting.currentSummDelivered(endpoint, {min: 10, max: 3600, change: 5});
55
82
  await reporting.deviceTemperature(endpoint);
56
83
  // some firmware is not defined powersource
57
84
  if (device.powerSource === 'Unknown') {
@@ -59,7 +86,7 @@ module.exports = [
59
86
  device.save();
60
87
  }
61
88
  },
62
- exposes: [e.device_temperature(), e.switch(), e.power(), e.energy()],
89
+ exposes: [e.device_temperature(), e.switch(), e.power().withAccess(ea.STATE_GET), e.energy().withAccess(ea.STATE_GET)],
63
90
  },
64
91
  {
65
92
  zigbeeModel: ['PM-B430-ZB'],
@@ -248,15 +275,16 @@ module.exports = [
248
275
  vendor: 'Dawon DNS',
249
276
  description: 'IOT remote control smart buried-type 16A outlet',
250
277
  fromZigbee: [fz.on_off, fz.metering],
251
- toZigbee: [tz.on_off],
278
+ toZigbee: [tz.on_off, tz.metering_power, tz.currentsummdelivered],
252
279
  configure: async (device, coordinatorEndpoint, logger) => {
253
280
  const endpoint = device.getEndpoint(1);
254
281
  await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'seMetering']);
255
282
  await reporting.onOff(endpoint);
256
283
  await reporting.readMeteringMultiplierDivisor(endpoint);
257
284
  await reporting.instantaneousDemand(endpoint);
285
+ await reporting.currentSummDelivered(endpoint, {min: 10, max: 3600, change: 5});
258
286
  },
259
- exposes: [e.switch(), e.power(), e.energy()],
287
+ exposes: [e.switch(), e.power().withAccess(ea.STATE_GET), e.energy().withAccess(ea.STATE_GET)],
260
288
  },
261
289
  {
262
290
  zigbeeModel: ['SG-V100-ZB'],
@@ -278,8 +306,8 @@ module.exports = [
278
306
  model: 'KB-HD100-ZB',
279
307
  vendor: 'Dawon DNS',
280
308
  description: 'IOT Card holder',
281
- fromZigbee: [fz.dawon_card_holder],
282
- toZigbee: [],
309
+ fromZigbee: [fzLocal.dawon_card_holder],
310
+ toZigbee: [tzLocal.dawon_card_holder],
283
311
  configure: async (device, coordinatorEndpoint, logger) => {
284
312
  const endpoint = device.getEndpoint(1);
285
313
  await reporting.bind(endpoint, coordinatorEndpoint, ['ssIasZone']);
@@ -287,7 +315,7 @@ module.exports = [
287
315
  attribute: 'zoneState', minimumReportInterval: 0, maximumReportInterval: 3600, reportableChange: 0}];
288
316
  await endpoint.configureReporting('ssIasZone', payload);
289
317
  },
290
- exposes: [exposes.binary('card', ea.STATE, true, false)
318
+ exposes: [exposes.binary('card', ea.STATE, true, false).withAccess(ea.STATE_GET)
291
319
  .withDescription('Indicates if the card is inserted (= true) or not (= false)'), e.battery_low()],
292
320
  },
293
321
  {
@@ -296,14 +324,15 @@ module.exports = [
296
324
  vendor: 'Dawon DNS',
297
325
  description: 'IOT smart plug 16A',
298
326
  fromZigbee: [fz.on_off, fz.metering],
299
- toZigbee: [tz.on_off],
327
+ toZigbee: [tz.on_off, tz.metering_power, tz.currentsummdelivered],
300
328
  configure: async (device, coordinatorEndpoint, logger) => {
301
329
  const endpoint = device.getEndpoint(1);
302
330
  await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'seMetering']);
303
331
  await reporting.onOff(endpoint);
304
332
  await reporting.readMeteringMultiplierDivisor(endpoint);
305
333
  await reporting.instantaneousDemand(endpoint);
334
+ await reporting.currentSummDelivered(endpoint, {min: 10, max: 3600, change: 5});
306
335
  },
307
- exposes: [e.switch(), e.power(), e.energy()],
336
+ exposes: [e.switch(), e.power().withAccess(ea.STATE_GET), e.energy().withAccess(ea.STATE_GET)],
308
337
  },
309
338
  ];
@@ -162,6 +162,14 @@ module.exports = [
162
162
  extend: extend.ledvance.light_onoff_brightness_colortemp({colorTempRange: [153, 370]}),
163
163
  ota: ota.ledvance,
164
164
  },
165
+ {
166
+ zigbeeModel: ['A60 TW T'],
167
+ model: '4058075729001',
168
+ vendor: 'LEDVANCE',
169
+ description: 'SMART+ CL A60 E27 Tunable white',
170
+ extend: extend.ledvance.light_onoff_brightness_colortemp({colorTempRange: [153, 370]}),
171
+ ota: ota.ledvance,
172
+ },
165
173
  {
166
174
  zigbeeModel: ['CLA60 RGBW JP'],
167
175
  model: 'SMARTZBA60RGBW',
@@ -132,7 +132,6 @@ module.exports = [
132
132
  // support binary report on moving state (supposed)
133
133
  fz.legrand_binary_input_moving, fz.cover_position_tilt],
134
134
  toZigbee: [tz.cover_state, tz.cover_position_tilt, tz.legrand_identify, tz.legrand_settingEnableLedInDark],
135
- meta: {coverInverted: true},
136
135
  configure: async (device, coordinatorEndpoint, logger) => {
137
136
  const endpoint = device.getEndpoint(1);
138
137
  await reporting.bind(endpoint, coordinatorEndpoint, ['genBinaryInput', 'closuresWindowCovering', 'genIdentify']);
@@ -200,4 +200,20 @@ module.exports = [
200
200
  extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 555]}),
201
201
  toZigbee: extend.light_onoff_brightness_colortemp().toZigbee.concat([tz.tint_scene]),
202
202
  },
203
+ {
204
+ fingerprint: [{manufacturerName: 'MLI', modelID: 'Candle white+color'}],
205
+ model: '45730',
206
+ vendor: 'Müller Licht',
207
+ description: 'Tint candle E14 white+color',
208
+ extend: extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 555]}),
209
+ toZigbee: extend.light_onoff_brightness_colortemp_color().toZigbee.concat([tz.tint_scene]),
210
+ },
211
+ {
212
+ fingerprint: [{manufacturerName: 'MLI', modelID: 'Bulb white+color'}],
213
+ model: '45728',
214
+ vendor: 'Müller Licht',
215
+ description: 'Tint bulb E27 white+color',
216
+ extend: extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 555]}),
217
+ toZigbee: extend.light_onoff_brightness_colortemp_color().toZigbee.concat([tz.tint_scene]),
218
+ },
203
219
  ];
@@ -2359,10 +2359,10 @@ module.exports = [
2359
2359
  },
2360
2360
  {
2361
2361
  zigbeeModel: ['LLM001'],
2362
- model: '7121131PU',
2362
+ model: '7121131PU/7120031PH/7120131PH/7120231PU',
2363
2363
  vendor: 'Philips',
2364
- description: 'Hue Beyond white and color ambiance suspension light',
2365
- extend: hueExtend.light_onoff_brightness_colortemp_color(),
2364
+ description: 'Hue Beyond white and color ambiance suspension/ceiling/table lamp',
2365
+ extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
2366
2366
  },
2367
2367
  {
2368
2368
  zigbeeModel: ['5041131P9', '5041148P9'],
@@ -2918,7 +2918,7 @@ module.exports = [
2918
2918
  zigbeeModel: ['LCX012'],
2919
2919
  model: '929003535301',
2920
2920
  vendor: 'Philips',
2921
- description: 'Hue Festivia gradient light string 250',
2921
+ description: 'Hue Festavia gradient light string 250',
2922
2922
  extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
2923
2923
  },
2924
2924
  ];
@@ -464,6 +464,18 @@ module.exports = [
464
464
  await reporting.currentPositionLiftPercentage(endpoint);
465
465
  },
466
466
  },
467
+ {
468
+ zigbeeModel: ['1GANG/SWITCH/1'],
469
+ model: 'MEG5161-0000',
470
+ vendor: 'Schneider Electric',
471
+ description: 'Merten PlusLink relay insert with Merten Wiser system M push button (1fold)',
472
+ extend: extend.switch(),
473
+ configure: async (device, coordinatorEndpoint, logger) => {
474
+ const endpoint = device.getEndpoint(1);
475
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
476
+ await reporting.onOff(endpoint);
477
+ },
478
+ },
467
479
  {
468
480
  zigbeeModel: ['LK Switch'],
469
481
  model: '545D6514',
@@ -70,8 +70,12 @@ const tzLocal = {
70
70
  case 'counting_freeze':
71
71
  if (value.toLowerCase() === 'on') {
72
72
  payload = {'presentValue': 82};
73
+ await endpoint.write('genAnalogInput', payload);
74
+ return {state: {counting_freeze: 'ON'}};
73
75
  } else if (value.toLowerCase() === 'off') {
74
76
  payload = {'presentValue': 84};
77
+ await endpoint.write('genAnalogInput', payload);
78
+ return {state: {counting_freeze: 'OFF'}};
75
79
  }
76
80
  break;
77
81
  case 'tof_init':
@@ -80,44 +84,72 @@ const tzLocal = {
80
84
  case 'led_state':
81
85
  if (value === 'enable') {
82
86
  payload = {'presentValue': 86};
87
+ await endpoint.write('genAnalogInput', payload);
88
+ return {state: {led_state: 'enable'}};
83
89
  } else if (value === 'disable') {
84
90
  payload = {'presentValue': 87};
91
+ await endpoint.write('genAnalogInput', payload);
92
+ return {state: {led_state: 'disable'}};
85
93
  }
86
94
  break;
87
95
  case 'rf_state':
88
96
  if (value === 'enable') {
89
97
  payload = {'presentValue': 88};
98
+ await endpoint.write('genAnalogInput', payload);
99
+ return {state: {rf_state: 'enable'}};
90
100
  } else if (value === 'disable') {
91
101
  payload = {'presentValue': 89};
102
+ await endpoint.write('genAnalogInput', payload);
103
+ return {state: {rf_state: 'disable'}};
92
104
  }
93
105
  break;
94
106
  case 'transaction':
95
107
  if (value === '0ms') {
96
108
  payload = {'presentValue': 90};
109
+ await endpoint.write('genAnalogInput', payload);
110
+ return {state: {transaction: '0ms'}};
97
111
  } else if (value === '200ms') {
98
112
  payload = {'presentValue': 91};
113
+ await endpoint.write('genAnalogInput', payload);
114
+ return {state: {transaction: '200ms'}};
99
115
  } else if (value === '400ms') {
100
116
  payload = {'presentValue': 92};
117
+ await endpoint.write('genAnalogInput', payload);
118
+ return {state: {transaction: '400ms'}};
101
119
  } else if (value === '600ms') {
102
120
  payload = {'presentValue': 93};
121
+ await endpoint.write('genAnalogInput', payload);
122
+ return {state: {transaction: '600ms'}};
103
123
  } else if (value === '800ms') {
104
124
  payload = {'presentValue': 94};
125
+ await endpoint.write('genAnalogInput', payload);
126
+ return {state: {transaction: '800ms'}};
105
127
  } else if (value === '1,000ms') {
106
128
  payload = {'presentValue': 95};
129
+ await endpoint.write('genAnalogInput', payload);
130
+ return {state: {transaction: '1,000ms'}};
107
131
  }
108
132
  break;
109
133
  case 'fast_in':
110
134
  if (value === 'enable') {
111
135
  payload = {'presentValue': 96};
136
+ await endpoint.write('genAnalogInput', payload);
137
+ return {state: {fast_in: 'enable'}};
112
138
  } else if (value === 'disable') {
113
139
  payload = {'presentValue': 97};
140
+ await endpoint.write('genAnalogInput', payload);
141
+ return {state: {fast_in: 'disable'}};
114
142
  }
115
143
  break;
116
144
  case 'fast_out':
117
145
  if (value === 'enable') {
118
146
  payload = {'presentValue': 98};
147
+ await endpoint.write('genAnalogInput', payload);
148
+ return {state: {fast_out: 'enable'}};
119
149
  } else if (value === 'disable') {
120
150
  payload = {'presentValue': 99};
151
+ await endpoint.write('genAnalogInput', payload);
152
+ return {state: {fast_out: 'disable'}};
121
153
  }
122
154
  break;
123
155
  }
package/devices/sinope.js CHANGED
@@ -14,21 +14,32 @@ module.exports = [
14
14
  vendor: 'Sinopé',
15
15
  description: 'Zigbee line volt thermostat',
16
16
  meta: {thermostat: {dontMapPIHeatingDemand: true}},
17
- fromZigbee: [fz.legacy.sinope_thermostat_att_report, fz.legacy.hvac_user_interface, fz.electrical_measurement, fz.metering,
17
+ fromZigbee: [
18
+ fz.legacy.sinope_thermostat_att_report, fz.legacy.hvac_user_interface, fz.electrical_measurement, fz.metering,
18
19
  fz.ignore_temperature_report, fz.legacy.sinope_thermostat_state, fz.sinope_thermostat],
19
- toZigbee: [tz.thermostat_local_temperature, tz.thermostat_occupied_heating_setpoint, tz.thermostat_unoccupied_heating_setpoint,
20
+ toZigbee: [
21
+ tz.thermostat_local_temperature, tz.thermostat_occupied_heating_setpoint, tz.thermostat_unoccupied_heating_setpoint,
20
22
  tz.thermostat_temperature_display_mode, tz.thermostat_keypad_lockout, tz.thermostat_system_mode, tz.thermostat_running_state,
21
23
  tz.sinope_thermostat_occupancy, tz.sinope_thermostat_backlight_autodim_param, tz.sinope_thermostat_time,
22
24
  tz.sinope_thermostat_enable_outdoor_temperature, tz.sinope_thermostat_outdoor_temperature, tz.sinope_time_format],
23
- exposes: [e.local_temperature(), e.keypad_lockout(), e.power(), e.current(), e.voltage(), e.energy(),
24
- exposes.climate().withSetpoint('occupied_heating_setpoint', 5, 30, 0.5).withLocalTemperature()
25
- .withSystemMode(['off', 'heat']).withRunningState(['idle', 'heat']).withPiHeatingDemand(),
26
- exposes.enum('thermostat_occupancy', ea.SET, ['unoccupied', 'occupied']).withDescription('Occupancy state of the thermostat'),
27
- exposes.enum('backlight_auto_dim', ea.SET, ['on demand', 'sensing']).withDescription('Control backlight dimming behavior')],
25
+ exposes: [
26
+ exposes.climate()
27
+ .withSetpoint('occupied_heating_setpoint', 5, 30, 0.5)
28
+ .withSetpoint('unoccupied_heating_setpoint', 5, 30, 0.5)
29
+ .withLocalTemperature()
30
+ .withSystemMode(['off', 'heat']).withRunningState(['idle', 'heat'])
31
+ .withPiHeatingDemand(),
32
+ exposes.enum('thermostat_occupancy', ea.SET, ['unoccupied', 'occupied'])
33
+ .withDescription('Occupancy state of the thermostat'),
34
+ exposes.enum('backlight_auto_dim', ea.SET, ['on demand', 'sensing'])
35
+ .withDescription('Control backlight dimming behavior'),
36
+ e.keypad_lockout(), e.energy(), e.power(), e.current(), e.voltage()],
28
37
  configure: async (device, coordinatorEndpoint, logger) => {
29
38
  const endpoint = device.getEndpoint(1);
30
- const binds = ['genBasic', 'genIdentify', 'genGroups', 'hvacThermostat', 'hvacUserInterfaceCfg', 'msTemperatureMeasurement',
31
- 'haElectricalMeasurement', 'seMetering', 'manuSpecificSinope'];
39
+ const binds = [
40
+ 'genBasic', 'genIdentify', 'genGroups', 'hvacThermostat', 'hvacUserInterfaceCfg',
41
+ 'msTemperatureMeasurement', 'haElectricalMeasurement', 'seMetering',
42
+ 'manuSpecificSinope'];
32
43
  await reporting.bind(endpoint, coordinatorEndpoint, binds);
33
44
  await reporting.thermostatTemperature(endpoint);
34
45
  await reporting.thermostatPIHeatingDemand(endpoint);
@@ -61,8 +72,8 @@ module.exports = [
61
72
 
62
73
  // Disable default reporting
63
74
  await reporting.temperature(endpoint, {min: 1, max: 0xFFFF});
64
- await endpoint.configureReporting('msTemperatureMeasurement', [{
65
- attribute: 'tolerance', minimumReportInterval: 1, maximumReportInterval: 0xFFFF, reportableChange: 1}]);
75
+ await endpoint.configureReporting('msTemperatureMeasurement', [
76
+ {attribute: 'tolerance', minimumReportInterval: 1, maximumReportInterval: 0xFFFF, reportableChange: 1}]);
66
77
  },
67
78
  },
68
79
  {
@@ -71,21 +82,32 @@ module.exports = [
71
82
  vendor: 'Sinopé',
72
83
  description: 'Zigbee line volt thermostat',
73
84
  meta: {thermostat: {dontMapPIHeatingDemand: true}},
74
- fromZigbee: [fz.legacy.sinope_thermostat_att_report, fz.legacy.hvac_user_interface, fz.electrical_measurement, fz.metering,
85
+ fromZigbee: [
86
+ fz.legacy.sinope_thermostat_att_report, fz.legacy.hvac_user_interface, fz.electrical_measurement, fz.metering,
75
87
  fz.ignore_temperature_report, fz.legacy.sinope_thermostat_state, fz.sinope_thermostat],
76
- toZigbee: [tz.thermostat_local_temperature, tz.thermostat_occupied_heating_setpoint, tz.thermostat_unoccupied_heating_setpoint,
88
+ toZigbee: [
89
+ tz.thermostat_local_temperature, tz.thermostat_occupied_heating_setpoint, tz.thermostat_unoccupied_heating_setpoint,
77
90
  tz.thermostat_temperature_display_mode, tz.thermostat_keypad_lockout, tz.thermostat_system_mode, tz.thermostat_running_state,
78
91
  tz.sinope_thermostat_occupancy, tz.sinope_thermostat_backlight_autodim_param, tz.sinope_thermostat_time,
79
92
  tz.sinope_thermostat_enable_outdoor_temperature, tz.sinope_thermostat_outdoor_temperature, tz.sinope_time_format],
80
- exposes: [e.local_temperature(), e.keypad_lockout(), e.power(), e.current(), e.voltage(), e.energy(),
81
- exposes.climate().withSetpoint('occupied_heating_setpoint', 5, 30, 0.5).withLocalTemperature()
82
- .withSystemMode(['off', 'heat']).withRunningState(['idle', 'heat']).withPiHeatingDemand(),
83
- exposes.enum('thermostat_occupancy', ea.SET, ['unoccupied', 'occupied']).withDescription('Occupancy state of the thermostat'),
84
- exposes.enum('backlight_auto_dim', ea.SET, ['on demand', 'sensing']).withDescription('Control backlight dimming behavior')],
93
+ exposes: [
94
+ exposes.climate()
95
+ .withSetpoint('occupied_heating_setpoint', 5, 30, 0.5)
96
+ .withSetpoint('unoccupied_heating_setpoint', 5, 30, 0.5)
97
+ .withLocalTemperature()
98
+ .withSystemMode(['off', 'heat']).withRunningState(['idle', 'heat'])
99
+ .withPiHeatingDemand(),
100
+ exposes.enum('thermostat_occupancy', ea.SET, ['unoccupied', 'occupied'])
101
+ .withDescription('Occupancy state of the thermostat'),
102
+ exposes.enum('backlight_auto_dim', ea.SET, ['on demand', 'sensing'])
103
+ .withDescription('Control backlight dimming behavior'),
104
+ e.keypad_lockout(), e.energy(), e.power(), e.current(), e.voltage()],
85
105
  configure: async (device, coordinatorEndpoint, logger) => {
86
106
  const endpoint = device.getEndpoint(1);
87
- const binds = ['genBasic', 'genIdentify', 'genGroups', 'hvacThermostat', 'hvacUserInterfaceCfg', 'msTemperatureMeasurement',
88
- 'haElectricalMeasurement', 'seMetering', 'manuSpecificSinope'];
107
+ const binds = [
108
+ 'genBasic', 'genIdentify', 'genGroups', 'hvacThermostat', 'hvacUserInterfaceCfg',
109
+ 'msTemperatureMeasurement', 'haElectricalMeasurement', 'seMetering',
110
+ 'manuSpecificSinope'];
89
111
  await reporting.bind(endpoint, coordinatorEndpoint, binds);
90
112
  await reporting.thermostatTemperature(endpoint);
91
113
  await reporting.thermostatPIHeatingDemand(endpoint);
@@ -101,6 +123,12 @@ module.exports = [
101
123
  await reporting.instantaneousDemand(endpoint, {min: 10, max: 304, change: 1});
102
124
  } catch (error) {/* Do nothing*/}
103
125
 
126
+ await reporting.readMeteringMultiplierDivisor(endpoint);
127
+ await reporting.currentSummDelivered(endpoint, {min: 10, max: 303, change: [1, 1]});
128
+ try {
129
+ await reporting.instantaneousDemand(endpoint, {min: 10, max: 304, change: 1});
130
+ } catch (error) {/* Do nothing*/}
131
+
104
132
  await reporting.readEletricalMeasurementMultiplierDivisors(endpoint);
105
133
  try {
106
134
  await reporting.activePower(endpoint, {min: 10, max: 305, change: 1});
@@ -112,16 +140,10 @@ module.exports = [
112
140
  await reporting.rmsVoltage(endpoint, {min: 10, max: 307, change: 5}); // divider 10: 0.5Vrms
113
141
  } catch (error) {/* Do nothing*/}
114
142
 
115
- try {
116
- await reporting.thermostatKeypadLockMode(endpoint);
117
- } catch (error) {
118
- // Not all support this: https://github.com/Koenkk/zigbee2mqtt/issues/3760
119
- }
120
-
121
143
  // Disable default reporting
122
144
  await reporting.temperature(endpoint, {min: 1, max: 0xFFFF});
123
- await endpoint.configureReporting('msTemperatureMeasurement', [{
124
- attribute: 'tolerance', minimumReportInterval: 1, maximumReportInterval: 0xFFFF, reportableChange: 1}]);
145
+ await endpoint.configureReporting('msTemperatureMeasurement', [
146
+ {attribute: 'tolerance', minimumReportInterval: 1, maximumReportInterval: 0xFFFF, reportableChange: 1}]);
125
147
  },
126
148
  },
127
149
  {
@@ -130,21 +152,30 @@ module.exports = [
130
152
  vendor: 'Sinopé',
131
153
  description: 'Zigbee smart floor heating thermostat',
132
154
  meta: {thermostat: {dontMapPIHeatingDemand: true}},
133
- fromZigbee: [fz.legacy.sinope_thermostat_att_report, fz.legacy.hvac_user_interface, fz.electrical_measurement,
155
+ fromZigbee: [
156
+ fz.legacy.sinope_thermostat_att_report, fz.legacy.hvac_user_interface, fz.electrical_measurement,
134
157
  fz.ignore_temperature_report, fz.legacy.sinope_thermostat_state, fz.sinope_TH1300ZB_specific],
135
- toZigbee: [tz.thermostat_local_temperature, tz.thermostat_occupied_heating_setpoint, tz.thermostat_unoccupied_heating_setpoint,
158
+ toZigbee: [
159
+ tz.thermostat_local_temperature, tz.thermostat_occupied_heating_setpoint, tz.thermostat_unoccupied_heating_setpoint,
136
160
  tz.thermostat_temperature_display_mode, tz.thermostat_keypad_lockout, tz.thermostat_system_mode, tz.thermostat_running_state,
137
161
  tz.sinope_thermostat_occupancy, tz.sinope_thermostat_backlight_autodim_param, tz.sinope_thermostat_time,
138
162
  tz.sinope_thermostat_enable_outdoor_temperature, tz.sinope_thermostat_outdoor_temperature, tz.sinope_floor_control_mode,
139
163
  tz.sinope_ambiant_max_heat_setpoint, tz.sinope_floor_min_heat_setpoint, tz.sinope_floor_max_heat_setpoint,
140
164
  tz.sinope_temperature_sensor, tz.sinope_time_format],
141
- exposes: [e.local_temperature(), e.keypad_lockout(), e.power(), e.current(), e.voltage(),
142
- exposes.climate().withSetpoint('occupied_heating_setpoint', 7, 30, 0.5).withLocalTemperature()
143
- .withSystemMode(['off', 'auto', 'heat']).withRunningState(['idle', 'heat']).withPiHeatingDemand(),
144
- exposes.enum('backlight_auto_dim', ea.SET, ['on demand', 'sensing']).withDescription('Control backlight dimming behavior')],
165
+ exposes: [
166
+ exposes.climate()
167
+ .withSetpoint('occupied_heating_setpoint', 7, 30, 0.5)
168
+ .withLocalTemperature()
169
+ .withSystemMode(['off', 'auto', 'heat'])
170
+ .withRunningState(['idle', 'heat'])
171
+ .withPiHeatingDemand(),
172
+ exposes.enum('backlight_auto_dim', ea.SET, ['on demand', 'sensing'])
173
+ .withDescription('Control backlight dimming behavior'),
174
+ e.keypad_lockout(), e.power(), e.current(), e.voltage()],
145
175
  configure: async (device, coordinatorEndpoint, logger) => {
146
176
  const endpoint = device.getEndpoint(1);
147
- const binds = ['genBasic', 'genIdentify', 'genGroups', 'hvacThermostat', 'hvacUserInterfaceCfg',
177
+ const binds = [
178
+ 'genBasic', 'genIdentify', 'genGroups', 'hvacThermostat', 'hvacUserInterfaceCfg',
148
179
  'haElectricalMeasurement', 'msTemperatureMeasurement', 'manuSpecificSinope'];
149
180
  await reporting.bind(endpoint, coordinatorEndpoint, binds);
150
181
  await reporting.thermostatTemperature(endpoint);
@@ -156,7 +187,7 @@ module.exports = [
156
187
  } catch (error) {/* Not all support this */}
157
188
 
158
189
  try {
159
- await endpoint.read('haElectricalMeasurement', ['acPowerMultiplier', 'acPowerDivisor']);
190
+ await endpoint.read('haElectricalMeasurement', ['acPowerMultiplier']);
160
191
  await reporting.activePower(endpoint, {min: 10, max: 305, change: 1}); // divider 1: 1W
161
192
  } catch (error) {
162
193
  endpoint.saveClusterAttributeKeyValue('haElectricalMeasurement', {'acPowerMultiplier': 1, 'acPowerDivisor': 1});
@@ -178,8 +209,8 @@ module.exports = [
178
209
 
179
210
  await endpoint.configureReporting('manuSpecificSinope', [{attribute: 'GFCiStatus', minimumReportInterval: 1,
180
211
  maximumReportInterval: constants.repInterval.HOUR, reportableChange: 1}]);
181
- await endpoint.configureReporting('manuSpecificSinope', [{attribute: 'floorLimitStatus',
182
- minimumReportInterval: 1, maximumReportInterval: constants.repInterval.HOUR, reportableChange: 1}]);
212
+ await endpoint.configureReporting('manuSpecificSinope', [{attribute: 'floorLimitStatus', minimumReportInterval: 1,
213
+ maximumReportInterval: constants.repInterval.HOUR, reportableChange: 1}]);
183
214
  await reporting.temperature(endpoint, {min: 1, max: 0xFFFF}); // disable reporting
184
215
  },
185
216
  },
@@ -189,17 +220,27 @@ module.exports = [
189
220
  vendor: 'Sinopé',
190
221
  description: 'Zigbee low volt thermostat',
191
222
  meta: {thermostat: {dontMapPIHeatingDemand: true}},
192
- fromZigbee: [fz.legacy.sinope_thermostat_att_report, fz.legacy.sinope_thermostat_state],
193
- toZigbee: [tz.thermostat_local_temperature, tz.thermostat_occupied_heating_setpoint, tz.thermostat_temperature_display_mode,
223
+ fromZigbee: [
224
+ fz.legacy.sinope_thermostat_att_report, fz.legacy.sinope_thermostat_state],
225
+ toZigbee: [
226
+ tz.thermostat_local_temperature, tz.thermostat_occupied_heating_setpoint, tz.thermostat_temperature_display_mode,
194
227
  tz.thermostat_keypad_lockout, tz.thermostat_system_mode, tz.thermostat_running_state,
195
228
  tz.sinope_thermostat_backlight_autodim_param, tz.sinope_thermostat_time, tz.sinope_thermostat_enable_outdoor_temperature,
196
229
  tz.sinope_thermostat_outdoor_temperature],
197
- exposes: [exposes.climate().withSetpoint('occupied_heating_setpoint', 7, 30, 1).withLocalTemperature()
198
- .withSystemMode(['off', 'auto', 'heat']).withRunningState(['idle', 'heat']).withPiHeatingDemand(), exposes.enum(
199
- 'backlight_auto_dim', ea.SET, ['on demand', 'sensing']).withDescription('Control backlight dimming behavior')],
230
+ exposes: [
231
+ exposes.climate()
232
+ .withSetpoint('occupied_heating_setpoint', 7, 30, 1)
233
+ .withLocalTemperature()
234
+ .withSystemMode(['off', 'auto', 'heat'])
235
+ .withRunningState(['idle', 'heat'])
236
+ .withPiHeatingDemand(),
237
+ exposes.enum('backlight_auto_dim', ea.SET, ['on demand', 'sensing'])
238
+ .withDescription('Control backlight dimming behavior')],
200
239
  configure: async (device, coordinatorEndpoint, logger) => {
201
240
  const endpoint = device.getEndpoint(1);
202
- const binds = ['genBasic', 'genIdentify', 'genGroups', 'hvacThermostat', 'hvacUserInterfaceCfg', 'msTemperatureMeasurement'];
241
+ const binds = [
242
+ 'genBasic', 'genIdentify', 'genGroups', 'hvacThermostat',
243
+ 'hvacUserInterfaceCfg', 'msTemperatureMeasurement'];
203
244
  await reporting.bind(endpoint, coordinatorEndpoint, binds);
204
245
  await reporting.thermostatTemperature(endpoint);
205
246
  await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
@@ -215,17 +256,27 @@ module.exports = [
215
256
  model: 'TH1500ZB',
216
257
  vendor: 'Sinopé',
217
258
  description: 'Zigbee dual pole line volt thermostat',
218
- fromZigbee: [fz.legacy.thermostat_att_report],
219
- toZigbee: [tz.thermostat_local_temperature, tz.thermostat_occupied_heating_setpoint, tz.thermostat_unoccupied_heating_setpoint,
259
+ fromZigbee: [
260
+ fz.legacy.thermostat_att_report],
261
+ toZigbee: [
262
+ tz.thermostat_local_temperature, tz.thermostat_occupied_heating_setpoint, tz.thermostat_unoccupied_heating_setpoint,
220
263
  tz.thermostat_temperature_display_mode, tz.thermostat_keypad_lockout, tz.thermostat_system_mode, tz.thermostat_running_state,
221
264
  tz.sinope_thermostat_occupancy, tz.sinope_thermostat_backlight_autodim_param, tz.sinope_thermostat_time,
222
265
  tz.sinope_thermostat_enable_outdoor_temperature, tz.sinope_thermostat_outdoor_temperature],
223
- exposes: [exposes.climate().withSetpoint('occupied_heating_setpoint', 7, 30, 1).withLocalTemperature()
224
- .withSystemMode(['off', 'auto', 'heat']).withRunningState(['idle', 'heat']).withPiHeatingDemand(), exposes.enum(
225
- 'backlight_auto_dim', ea.SET, ['on demand', 'sensing']).withDescription('Control backlight dimming behavior')],
266
+ exposes: [
267
+ exposes.climate()
268
+ .withSetpoint('occupied_heating_setpoint', 7, 30, 1)
269
+ .withLocalTemperature()
270
+ .withSystemMode(['off', 'auto', 'heat'])
271
+ .withRunningState(['idle', 'heat'])
272
+ .withPiHeatingDemand(),
273
+ exposes.enum('backlight_auto_dim', ea.SET, ['on demand', 'sensing'])
274
+ .withDescription('Control backlight dimming behavior')],
226
275
  configure: async (device, coordinatorEndpoint, logger) => {
227
276
  const endpoint = device.getEndpoint(1);
228
- const binds = ['genBasic', 'genIdentify', 'genGroups', 'hvacThermostat', 'hvacUserInterfaceCfg', 'msTemperatureMeasurement'];
277
+ const binds = [
278
+ 'genBasic', 'genIdentify', 'genGroups',
279
+ 'hvacThermostat', 'hvacUserInterfaceCfg', 'msTemperatureMeasurement'];
229
280
  await reporting.bind(endpoint, coordinatorEndpoint, binds);
230
281
  await reporting.thermostatTemperature(endpoint);
231
282
  await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
@@ -304,15 +355,21 @@ module.exports = [
304
355
  model: 'SP2600ZB',
305
356
  vendor: 'Sinopé',
306
357
  description: 'Zigbee smart plug',
307
- fromZigbee: [fz.on_off, fz.electrical_measurement],
358
+ fromZigbee: [fz.on_off, fz.electrical_measurement, fz.metering],
308
359
  toZigbee: [tz.on_off],
309
- exposes: [e.switch(), e.power()],
360
+ exposes: [e.switch(), e.power(), e.current(), e.voltage(), e.ac_frequency(), e.energy()],
310
361
  configure: async (device, coordinatorEndpoint, logger) => {
311
362
  const endpoint = device.getEndpoint(1);
312
- await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement']);
313
- await reporting.readEletricalMeasurementMultiplierDivisors(endpoint);
363
+ const binds = ['genBasic', 'genIdentify', 'genOnOff', 'haElectricalMeasurement', 'seMetering'];
364
+ await reporting.bind(endpoint, coordinatorEndpoint, binds);
365
+ await reporting.readEletricalMeasurementMultiplierDivisors(endpoint, {readFrequencyAttrs: true});
314
366
  await reporting.onOff(endpoint);
315
- await reporting.activePower(endpoint, {min: 10, change: 1});
367
+ await reporting.activePower(endpoint, {min: 10, change: 1}); // divider 10 : 0.1W
368
+ await reporting.rmsCurrent(endpoint, {min: 10, change: 10}); // divider 100: 0.1Arms
369
+ await reporting.rmsVoltage(endpoint, {min: 10, change: 10}); // divider 100: 0.1Vrms
370
+ await reporting.acFrequency(endpoint, {min: 10, change: 100}); // divider 100: 1Hz
371
+ await endpoint.read('haElectricalMeasurement', ['acFrequency']); // get a first read
372
+ await reporting.currentSummDelivered(endpoint, {min: 10, max: 307, change: [1, 1]});
316
373
  },
317
374
  },
318
375
  {
@@ -3,6 +3,7 @@ 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 ota = require('../lib/ota');
6
7
  const e = exposes.presets;
7
8
 
8
9
  module.exports = [
@@ -60,6 +61,7 @@ module.exports = [
60
61
  fromZigbee: [fz.ias_water_leak_alarm_1, fz.battery],
61
62
  meta: {battery: {dontDividePercentage: true}},
62
63
  toZigbee: [],
64
+ ota: ota.zigbeeOTA,
63
65
  exposes: [e.water_leak(), e.battery_low(), e.battery(), e.battery_voltage()],
64
66
  configure: async (device, coordinatorEndpoint, logger) => {
65
67
  device.powerSource = 'Battery';
package/devices/tuya.js CHANGED
@@ -1504,6 +1504,7 @@ module.exports = [
1504
1504
  {modelID: 'TS0201', manufacturerName: '_TZ3000_fllyghyj'},
1505
1505
  {modelID: 'TS0201', manufacturerName: '_TZ3000_yd2e749y'},
1506
1506
  {modelID: 'TS0201', manufacturerName: '_TZ3000_6uzkisv2'},
1507
+ {modelID: 'TS0601', manufacturerName: '_TZE200_9yapgbuv'},
1507
1508
  ],
1508
1509
  model: 'WSD500A',
1509
1510
  vendor: 'TuYa',
@@ -1985,7 +1986,7 @@ module.exports = [
1985
1986
  'to the desired temperature. If you want TRV to properly regulate the temperature you need to use mode `auto` ' +
1986
1987
  'instead setting the desired temperature.')
1987
1988
  .withLocalTemperatureCalibration(-9, 9, 1, ea.STATE_SET)
1988
- .withPreset(['schedule', 'manual', 'boost', 'complex', 'comfort', 'eco'])
1989
+ .withPreset(['schedule', 'manual', 'boost', 'complex', 'comfort', 'eco', 'away'])
1989
1990
  .withRunningState(['idle', 'heat'], ea.STATE),
1990
1991
  e.auto_lock(), e.away_mode(), e.away_preset_days(), e.boost_time(), e.comfort_temperature(), e.eco_temperature(), e.force(),
1991
1992
  e.max_temperature(), e.min_temperature(), e.away_preset_temperature(),
package/devices/xiaomi.js CHANGED
@@ -2604,6 +2604,7 @@ module.exports = [
2604
2604
  exposes.numeric('portion_weight', ea.STATE_SET).withValueMin(1).withValueMax(20).withDescription('Portion weight')
2605
2605
  .withUnit('g'),
2606
2606
  ],
2607
+ ota: ota.zigbeeOTA,
2607
2608
  },
2608
2609
  {
2609
2610
  zigbeeModel: ['lumi.remote.acn007'],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zigbee-herdsman-converters",
3
- "version": "14.0.671",
3
+ "version": "14.0.673",
4
4
  "description": "Collection of device converters to be used with zigbee-herdsman",
5
5
  "main": "index.js",
6
6
  "files": [