zigbee-herdsman-converters 14.0.447 → 14.0.450

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.
@@ -4176,15 +4176,24 @@ const converters = {
4176
4176
  return {temperature: calibrateAndPrecisionRoundOptions(value / 10, options, 'temperature')};
4177
4177
  case tuya.dataPoints.tuyaSabHumidity:
4178
4178
  return {humidity: calibrateAndPrecisionRoundOptions(value / 10, options, 'humidity')};
4179
+ // DP22: Smart Air Box: Formaldehyd, Smart Air Housekeeper: co2
4180
+ case tuya.dataPoints.tuyaSabFormaldehyd:
4181
+ if (meta.device.manufacturerName === '_TZE200_dwcarsat') {
4182
+ return {co2: calibrateAndPrecisionRoundOptions(value, options, 'co2')};
4183
+ } else {
4184
+ return {formaldehyd: calibrateAndPrecisionRoundOptions(value, options, 'formaldehyd')};
4185
+ }
4186
+ // DP2: Smart Air Box: co2, Smart Air Housekeeper: MP25
4179
4187
  case tuya.dataPoints.tuyaSabCO2:
4180
- return {co2: calibrateAndPrecisionRoundOptions(value, options, 'co2')};
4188
+ if (meta.device.manufacturerName === '_TZE200_dwcarsat') {
4189
+ return {pm25: calibrateAndPrecisionRoundOptions(value, options, 'pm25')};
4190
+ } else {
4191
+ return {co2: calibrateAndPrecisionRoundOptions(value, options, 'co2')};
4192
+ }
4181
4193
  case tuya.dataPoints.tuyaSabVOC:
4182
4194
  return {voc: calibrateAndPrecisionRoundOptions(value, options, 'voc')};
4183
- case tuya.dataPoints.tuyaSabFormaldehyd:
4184
- // Not sure which unit this is, supposedly mg/m³, but the value seems way too high.
4195
+ case tuya.dataPoints.tuyaSahkCH2O:
4185
4196
  return {formaldehyd: calibrateAndPrecisionRoundOptions(value, options, 'formaldehyd')};
4186
- case tuya.dataPoints.tuyaSahkMP25:
4187
- return {pm25: calibrateAndPrecisionRoundOptions(value, options, 'pm25')};
4188
4197
  default:
4189
4198
  meta.logger.warn(`zigbee-herdsman-converters:TuyaSmartAirBox: Unrecognized DP #${
4190
4199
  dp} with data ${JSON.stringify(dpValue)}`);
package/devices/awox.js CHANGED
@@ -70,10 +70,28 @@ module.exports = [
70
70
  },
71
71
  {
72
72
  fingerprint: [
73
- {type: 'Router', manufacturerName: 'AwoX', modelID: 'TLSR82xx', endpoints: [
74
- {ID: 1, profileID: 260, deviceID: 2028, inputClusters: [0, 3, 4, 4096], outputClusters: [0, 3, 4, 5, 6, 8, 768, 4096]},
75
- {ID: 3, profileID: 4751, deviceID: 2048, inputClusters: [65360, 65361], outputClusters: [65360, 65361]},
76
- ]},
73
+ {
74
+ type: 'EndDevice',
75
+ manufacturerName: 'AwoX',
76
+ modelID: 'TLSR82xx',
77
+ powerSource: 'Battery',
78
+ endpoints: [
79
+ {
80
+ ID: 1,
81
+ profileID: 260,
82
+ deviceID: 2048,
83
+ inputClusters: [0, 3, 4, 4096],
84
+ outputClusters: [0, 3, 4, 5, 6, 8, 768, 4096],
85
+ },
86
+ {
87
+ ID: 3,
88
+ profileID: 4751,
89
+ deviceID: 2048,
90
+ inputClusters: [65360, 65361],
91
+ outputClusters: [65360, 65361],
92
+ },
93
+ ],
94
+ },
77
95
  ],
78
96
  model: '33952',
79
97
  vendor: 'AwoX',
@@ -87,24 +105,80 @@ module.exports = [
87
105
  },
88
106
  {
89
107
  fingerprint: [
90
- {type: 'Router', manufacturerName: 'AwoX', modelID: 'TLSR82xx', endpoints: [
91
- {ID: 1, profileID: 260, deviceID: 269, inputClusters: [0, 3, 4, 5, 6, 8, 768, 4096, 64599, 10], outputClusters: [6]},
92
- {ID: 3, profileID: 4751, deviceID: 269, inputClusters: [65360, 65361], outputClusters: [65360, 65361]},
93
- {ID: 242, profileID: 41440, deviceID: 97, inputClusters: [], outputClusters: [33]},
94
- ]},
95
- {type: 'Router', manufacturerName: 'AwoX', modelID: 'TLSR82xx', endpoints: [
96
- {ID: 1, profileID: 260, deviceID: 258, inputClusters: [0, 3, 4, 5, 6, 8, 768, 4096], outputClusters: [6, 25]},
97
- {ID: 3, profileID: 49152, deviceID: 258, inputClusters: [65360, 65361], outputClusters: [65360, 65361]},
98
- ]},
99
- {type: 'Router', manufacturerName: 'AwoX', modelID: 'TLSR82xx', endpoints: [
100
- {ID: 1, profileID: 260, deviceID: 269, inputClusters: [0, 3, 4, 5, 6, 8, 768, 4096, 64599], outputClusters: [6]},
101
- {ID: 3, profileID: 4751, deviceID: 269, inputClusters: [65360, 65361], outputClusters: [65360, 65361]},
102
- {ID: 242, profileID: 41440, deviceID: 97, inputClusters: [], outputClusters: [33]},
103
- ]},
104
- {type: 'Router', manufacturerName: 'AwoX', modelID: 'TLSR82xx', endpoints: [
105
- {ID: 1, profileID: 260, deviceID: 269, inputClusters: [0, 3, 4, 5, 6, 8, 768, 4096, 64599], outputClusters: [6]},
106
- {ID: 3, profileID: 4751, deviceID: 269, inputClusters: [65360, 65361], outputClusters: [65360, 65361]},
107
- ]},
108
+ {
109
+ type: 'Router', manufacturerName: 'AwoX', modelID: 'TLSR82xx', endpoints: [
110
+ {
111
+ ID: 1,
112
+ profileID: 260,
113
+ deviceID: 269,
114
+ inputClusters: [0, 3, 4, 5, 6, 8, 768, 4096, 64599, 10],
115
+ outputClusters: [6],
116
+ },
117
+ {
118
+ ID: 3,
119
+ profileID: 4751,
120
+ deviceID: 269,
121
+ inputClusters: [65360, 65361],
122
+ outputClusters: [65360, 65361],
123
+ },
124
+ {ID: 242, profileID: 41440, deviceID: 97, inputClusters: [], outputClusters: [33]},
125
+ ],
126
+ },
127
+ {
128
+ type: 'Router', manufacturerName: 'AwoX', modelID: 'TLSR82xx', endpoints: [
129
+ {
130
+ ID: 1,
131
+ profileID: 260,
132
+ deviceID: 258,
133
+ inputClusters: [0, 3, 4, 5, 6, 8, 768, 4096],
134
+ outputClusters: [6, 25],
135
+ },
136
+ {
137
+ ID: 3,
138
+ profileID: 49152,
139
+ deviceID: 258,
140
+ inputClusters: [65360, 65361],
141
+ outputClusters: [65360, 65361],
142
+ },
143
+ ],
144
+ },
145
+ {
146
+ type: 'Router', manufacturerName: 'AwoX', modelID: 'TLSR82xx', endpoints: [
147
+ {
148
+ ID: 1,
149
+ profileID: 260,
150
+ deviceID: 269,
151
+ inputClusters: [0, 3, 4, 5, 6, 8, 768, 4096, 64599],
152
+ outputClusters: [6],
153
+ },
154
+ {
155
+ ID: 3,
156
+ profileID: 4751,
157
+ deviceID: 269,
158
+ inputClusters: [65360, 65361],
159
+ outputClusters: [65360, 65361],
160
+ },
161
+ {ID: 242, profileID: 41440, deviceID: 97, inputClusters: [], outputClusters: [33]},
162
+ ],
163
+ },
164
+ {
165
+ type: 'Router', manufacturerName: 'AwoX', modelID: 'TLSR82xx', endpoints: [
166
+ {
167
+ ID: 1,
168
+ profileID: 260,
169
+ deviceID: 269,
170
+ inputClusters: [0, 3, 4, 5, 6, 8, 768, 4096, 64599],
171
+ outputClusters: [6],
172
+ },
173
+ {
174
+ ID: 3,
175
+ profileID: 4751,
176
+ deviceID: 269,
177
+ inputClusters: [65360, 65361],
178
+ outputClusters: [65360, 65361],
179
+ },
180
+ ],
181
+ },
108
182
  ],
109
183
  model: '33943/33944/33946',
110
184
  vendor: 'AwoX',
@@ -113,15 +187,43 @@ module.exports = [
113
187
  },
114
188
  {
115
189
  fingerprint: [
116
- {type: 'Router', manufacturerName: 'AwoX', modelID: 'TLSR82xx', endpoints: [
117
- {ID: 1, profileID: 260, deviceID: 268, inputClusters: [0, 3, 4, 5, 6, 8, 768, 4096, 64599], outputClusters: [6]},
118
- {ID: 3, profileID: 4751, deviceID: 268, inputClusters: [65360, 65361], outputClusters: [65360, 65361]},
119
- ]},
120
- {type: 'Router', manufacturerName: 'AwoX', modelID: 'TLSR82xx', endpoints: [
121
- {ID: 1, profileID: 260, deviceID: 268, inputClusters: [0, 3, 4, 5, 6, 8, 768, 4096, 64599], outputClusters: [6]},
122
- {ID: 242, profileID: 41440, deviceID: 97, inputClusters: [], outputClusters: [33]},
123
- {ID: 3, profileID: 4751, deviceID: 268, inputClusters: [65360, 65361], outputClusters: [65360, 65361]},
124
- ]},
190
+ {
191
+ type: 'Router', manufacturerName: 'AwoX', modelID: 'TLSR82xx', endpoints: [
192
+ {
193
+ ID: 1,
194
+ profileID: 260,
195
+ deviceID: 268,
196
+ inputClusters: [0, 3, 4, 5, 6, 8, 768, 4096, 64599],
197
+ outputClusters: [6],
198
+ },
199
+ {
200
+ ID: 3,
201
+ profileID: 4751,
202
+ deviceID: 268,
203
+ inputClusters: [65360, 65361],
204
+ outputClusters: [65360, 65361],
205
+ },
206
+ ],
207
+ },
208
+ {
209
+ type: 'Router', manufacturerName: 'AwoX', modelID: 'TLSR82xx', endpoints: [
210
+ {
211
+ ID: 1,
212
+ profileID: 260,
213
+ deviceID: 268,
214
+ inputClusters: [0, 3, 4, 5, 6, 8, 768, 4096, 64599],
215
+ outputClusters: [6],
216
+ },
217
+ {ID: 242, profileID: 41440, deviceID: 97, inputClusters: [], outputClusters: [33]},
218
+ {
219
+ ID: 3,
220
+ profileID: 4751,
221
+ deviceID: 268,
222
+ inputClusters: [65360, 65361],
223
+ outputClusters: [65360, 65361],
224
+ },
225
+ ],
226
+ },
125
227
  ],
126
228
  model: '33957',
127
229
  vendor: 'AwoX',
@@ -130,10 +232,24 @@ module.exports = [
130
232
  },
131
233
  {
132
234
  fingerprint: [
133
- {type: 'Router', manufacturerName: 'AwoX', modelID: 'TLSR82xx', endpoints: [
134
- {ID: 1, profileID: 260, deviceID: 268, inputClusters: [0, 3, 4, 5, 6, 8, 768, 4096], outputClusters: [6, 25]},
135
- {ID: 3, profileID: 49152, deviceID: 268, inputClusters: [65360, 65361], outputClusters: [65360, 65361]},
136
- ]},
235
+ {
236
+ type: 'Router', manufacturerName: 'AwoX', modelID: 'TLSR82xx', endpoints: [
237
+ {
238
+ ID: 1,
239
+ profileID: 260,
240
+ deviceID: 268,
241
+ inputClusters: [0, 3, 4, 5, 6, 8, 768, 4096],
242
+ outputClusters: [6, 25],
243
+ },
244
+ {
245
+ ID: 3,
246
+ profileID: 49152,
247
+ deviceID: 268,
248
+ inputClusters: [65360, 65361],
249
+ outputClusters: [65360, 65361],
250
+ },
251
+ ],
252
+ },
137
253
  ],
138
254
  model: '33955',
139
255
  vendor: 'Eglo',
package/devices/hive.js CHANGED
@@ -275,6 +275,7 @@ module.exports = [
275
275
  await reporting.thermostatTemperatureSetpointHold(heatEndpoint);
276
276
  await reporting.thermostatTemperatureSetpointHoldDuration(heatEndpoint);
277
277
  await reporting.bind(waterEndpoint, coordinatorEndpoint, binds);
278
+ await reporting.thermostatTemperature(waterEndpoint);
278
279
  await reporting.thermostatRunningState(waterEndpoint);
279
280
  await reporting.thermostatSystemMode(waterEndpoint);
280
281
  await reporting.thermostatOccupiedHeatingSetpoint(waterEndpoint);
@@ -326,6 +327,7 @@ module.exports = [
326
327
  await reporting.thermostatTemperatureSetpointHold(heatEndpoint);
327
328
  await reporting.thermostatTemperatureSetpointHoldDuration(heatEndpoint);
328
329
  await reporting.bind(waterEndpoint, coordinatorEndpoint, binds);
330
+ await reporting.thermostatTemperature(waterEndpoint);
329
331
  await reporting.thermostatRunningState(waterEndpoint);
330
332
  await reporting.thermostatSystemMode(waterEndpoint);
331
333
  await reporting.thermostatOccupiedHeatingSetpoint(waterEndpoint);
@@ -377,6 +379,7 @@ module.exports = [
377
379
  await reporting.thermostatTemperatureSetpointHold(heatEndpoint);
378
380
  await reporting.thermostatTemperatureSetpointHoldDuration(heatEndpoint);
379
381
  await reporting.bind(waterEndpoint, coordinatorEndpoint, binds);
382
+ await reporting.thermostatTemperature(waterEndpoint);
380
383
  await reporting.thermostatRunningState(waterEndpoint);
381
384
  await reporting.thermostatSystemMode(waterEndpoint);
382
385
  await reporting.thermostatOccupiedHeatingSetpoint(waterEndpoint);
@@ -185,4 +185,14 @@ module.exports = [
185
185
  description: 'Zigbee 3.0 LED-controller 1x 8A',
186
186
  extend: extend.light_onoff_brightness(),
187
187
  },
188
+ {
189
+ zigbeeModel: ['ZGRC-TEUR-001'],
190
+ model: '511.544',
191
+ vendor: 'Iluminize',
192
+ description: 'Zigbee 3.0 wall dimmer RGBW 4 zone',
193
+ fromZigbee: [fz.command_move_to_color, fz.command_move_hue, fz.command_on, fz.command_off, fz.command_move],
194
+ toZigbee: [],
195
+ exposes: [e.action(['recall_*', 'on', 'off', 'color_move', 'color_temperature_move',
196
+ 'hue_move', 'brightness_step_down', 'brightness_step_up', 'brightness_move_down', 'brightness_move_up', 'brightness_stop'])],
197
+ },
188
198
  ];
package/devices/orvibo.js CHANGED
@@ -289,6 +289,8 @@ module.exports = [
289
289
  await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'closuresWindowCovering']);
290
290
  await reporting.batteryPercentageRemaining(endpoint);
291
291
  await reporting.currentPositionLiftPercentage(endpoint);
292
+ device.powerSource = 'Battery';
293
+ device.save();
292
294
  },
293
295
  exposes: [e.cover_position(), e.battery()],
294
296
  },
@@ -1181,6 +1181,15 @@ module.exports = [
1181
1181
  extend: hueExtend.light_onoff_brightness_colortemp(),
1182
1182
  ota: ota.zigbeeOTA,
1183
1183
  },
1184
+ {
1185
+ zigbeeModel: ['LTD004'],
1186
+ model: '801480',
1187
+ vendor: 'Philips',
1188
+ description: 'Hue white ambiance 4" retrofit recessed downlight',
1189
+ meta: {turnsOffAtBrightness1: true},
1190
+ extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
1191
+ ota: ota.zigbeeOTA,
1192
+ },
1184
1193
  {
1185
1194
  zigbeeModel: ['LTD009'],
1186
1195
  model: '5996311U5',
@@ -2499,7 +2508,7 @@ module.exports = [
2499
2508
  ota: ota.zigbeeOTA,
2500
2509
  },
2501
2510
  {
2502
- zigbeeModel: ['5309331P6', '5309330P6', '929003046301_03'],
2511
+ zigbeeModel: ['5309331P6', '5309330P6', '929003046301_03', '929003046301_02'],
2503
2512
  model: '5309331P6',
2504
2513
  vendor: 'Philips',
2505
2514
  description: 'Hue White ambiance Runner triple spotlight',
@@ -2553,7 +2562,7 @@ module.exports = [
2553
2562
  ota: ota.zigbeeOTA,
2554
2563
  },
2555
2564
  {
2556
- zigbeeModel: ['5309030P9', '5309031P9', '5309030P6', '5309031P6'],
2565
+ zigbeeModel: ['5309030P9', '5309031P9', '5309030P6', '5309031P6', '929003046101'],
2557
2566
  model: '5309030P9',
2558
2567
  vendor: 'Philips',
2559
2568
  description: 'Hue White ambiance Runner single spotlight',
@@ -2767,7 +2776,7 @@ module.exports = [
2767
2776
  ota: ota.zigbeeOTA,
2768
2777
  },
2769
2778
  {
2770
- zigbeeModel: ['915005997501'],
2779
+ zigbeeModel: ['915005997501', '915005997401'],
2771
2780
  model: '915005997501',
2772
2781
  vendor: 'Philips',
2773
2782
  description: 'Hue Bluetooth white & color ambiance ceiling lamp Infuse large',
@@ -2801,4 +2810,13 @@ module.exports = [
2801
2810
  extend: hueExtend.light_onoff_brightness(),
2802
2811
  ota: ota.zigbeeOTA,
2803
2812
  },
2813
+ {
2814
+ zigbeeModel: ['LTO005', '929002980901'],
2815
+ model: '929002980901',
2816
+ vendor: 'Philips',
2817
+ description: 'Hue white ambiance G40 E26 filament globe with Bluetooth',
2818
+ meta: {turnsOffAtBrightness1: true},
2819
+ extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [222, 454]}),
2820
+ ota: ota.zigbeeOTA,
2821
+ },
2804
2822
  ];
@@ -46,7 +46,8 @@ module.exports = [
46
46
  exposes.climate()
47
47
  .withSetpoint('current_heating_setpoint', 5, 30, 0.5, ea.STATE_SET).withLocalTemperature(ea.STATE)
48
48
  .withSystemMode(['off', 'heat', 'auto'], ea.STATE_SET)
49
- .withLocalTemperatureCalibration(-30, 30, 0.1, ea.STATE_SET)
49
+ // Range is -6 - 6 and step 1: https://github.com/Koenkk/zigbee2mqtt/issues/11777
50
+ .withLocalTemperatureCalibration(-6, 6, 1, ea.STATE_SET)
50
51
  .withAwayMode()],
51
52
  },
52
53
  ];
@@ -20,9 +20,10 @@ module.exports = [
20
20
  model: '3RSS008Z',
21
21
  vendor: 'Third Reality',
22
22
  description: 'RealitySwitch Plus',
23
- fromZigbee: [fz.on_off],
23
+ fromZigbee: [fz.on_off, fz.battery],
24
24
  toZigbee: [tz.on_off, tz.ignore_transition],
25
- exposes: [e.switch()],
25
+ meta: {battery: {voltageToPercentage: '3V_2100'}},
26
+ exposes: [e.switch(), e.battery(), e.battery_voltage()],
26
27
  },
27
28
  {
28
29
  zigbeeModel: ['3RSS007Z'],
package/devices/tuya.js CHANGED
@@ -143,7 +143,7 @@ module.exports = [
143
143
  description: 'Smart air house keeper',
144
144
  fromZigbee: [fz.tuya_air_quality],
145
145
  toZigbee: [],
146
- exposes: [e.temperature(), e.humidity(), e.co2(), e.voc(), e.formaldehyd(), e.pm25()],
146
+ exposes: [e.temperature(), e.humidity(), e.co2(), e.voc(), e.formaldehyd().withUnit('ppm'), e.pm25()],
147
147
  },
148
148
  {
149
149
  fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_7bztmfm1'}],
@@ -235,7 +235,8 @@ module.exports = [
235
235
  {modelID: 'TS0505B', manufacturerName: '_TZ3210_k1pe6ibm'},
236
236
  {modelID: 'TS0505B', manufacturerName: '_TZ3210_bfwvfyx1'},
237
237
  {modelID: 'TS0505B', manufacturerName: '_TZ3210_leyz4rju'},
238
- {modelID: 'TS0505B', manufacturerName: '_TZ3210_jd3z4yig'}],
238
+ {modelID: 'TS0505B', manufacturerName: '_TZ3210_jd3z4yig'},
239
+ {modelID: 'TS0505B', manufacturerName: '_TZ3210_dgdjiw1c'}],
239
240
  model: 'TS0505B',
240
241
  vendor: 'TuYa',
241
242
  description: 'Zigbee RGB+CCT light',
@@ -999,6 +1000,8 @@ module.exports = [
999
1000
  toZigbee: [tz.tuya_cover_control, tz.tuya_cover_options],
1000
1001
  exposes: [
1001
1002
  e.cover_position().setAccess('position', ea.STATE_SET),
1003
+ exposes.binary('running', ea.STATE, true, false)
1004
+ .withDescription('Whether the motor is moving or not'),
1002
1005
  exposes.composite('options', 'options')
1003
1006
  .withFeature(exposes.numeric('motor_speed', ea.STATE_SET)
1004
1007
  .withValueMin(0)
package/devices/xiaomi.js CHANGED
@@ -914,7 +914,7 @@ module.exports = [
914
914
  fromZigbee: [fz.aqara_opple],
915
915
  toZigbee: [tz.RTCZCGQ11LM_presence, tz.RTCZCGQ11LM_monitoring_mode, tz.RTCZCGQ11LM_approach_distance,
916
916
  tz.aqara_motion_sensitivity, tz.RTCZCGQ11LM_reset_nopresence_status],
917
- exposes: [e.presence().withAccess(ea.STATE_GET),
917
+ exposes: [e.presence().withAccess(ea.STATE_GET), e.power_outage_count(), e.temperature(),
918
918
  exposes.enum('presence_event', ea.STATE, ['enter', 'leave', 'left_enter', 'right_leave', 'right_enter', 'left_leave',
919
919
  'approach', 'away']).withDescription('Presence events: "enter", "leave", "left_enter", "right_leave", ' +
920
920
  '"right_enter", "left_leave", "approach", "away"'),
@@ -925,8 +925,7 @@ module.exports = [
925
925
  exposes.enum('motion_sensitivity', ea.ALL, ['low', 'medium', 'high']).withDescription('Different sensitivities ' +
926
926
  'means different static human body recognition rate and response speed of occupied'),
927
927
  exposes.enum('reset_nopresence_status', ea.SET, ['Reset']).withDescription('Reset the status of no presence'),
928
- exposes.numeric('power_outage_count', ea.STATE).withDescription('Number of power outages (since last pairing)'),
929
- e.temperature()],
928
+ ],
930
929
  configure: async (device, coordinatorEndpoint, logger) => {
931
930
  const endpoint = device.getEndpoint(1);
932
931
  await endpoint.read('aqaraOpple', [0x010c], {manufacturerCode: 0x115f});
@@ -1173,7 +1172,7 @@ module.exports = [
1173
1172
  fromZigbee: [fz.aqara_opple],
1174
1173
  toZigbee: [tz.JTBZ01AQA_gas, tz.JTBZ01AQA_gas_density, tz.JTBZ01AQA_gas_sensitivity, tz.JTBZ01AQA_selftest,
1175
1174
  tz.JTBZ01AQA_mute_buzzer, tz.JTBZ01AQA_mute, tz.JTBZ01AQA_linkage_alarm, tz.JTBZ01AQA_state, tz.aqara_power_outage_count],
1176
- exposes: [e.gas().withAccess(ea.STATE_GET),
1175
+ exposes: [e.gas().withAccess(ea.STATE_GET), e.power_outage_count().withAccess(ea.STATE_GET),
1177
1176
  exposes.numeric('gas_density', ea.STATE_GET).withUnit('%LEL').withDescription('Value of gas concentration'),
1178
1177
  exposes.enum('gas_sensitivity', ea.ALL, ['10%LEL', '15%LEL']).withDescription('Gas concentration value at which ' +
1179
1178
  'an alarm is triggered ("10%LEL" is more sensitive than "15%LEL")'),
@@ -1187,7 +1186,7 @@ module.exports = [
1187
1186
  'is detected, other detectors with this option enabled will also sound the alarm buzzer'),
1188
1187
  exposes.binary('state', ea.STATE_GET, 'preparation', 'work').withDescription('"Preparation" or "work" ' +
1189
1188
  '(measurement of the gas concentration value and triggering of an alarm are only performed in the "work" state)'),
1190
- exposes.numeric('power_outage_count', ea.STATE_GET).withDescription('Number of power outages (since last pairing)')],
1189
+ ],
1191
1190
  configure: async (device, coordinatorEndpoint, logger) => {
1192
1191
  const endpoint = device.getEndpoint(1);
1193
1192
  await endpoint.read('aqaraOpple', [0x013a], {manufacturerCode: 0x115f});
@@ -1239,7 +1238,9 @@ module.exports = [
1239
1238
  vendor: 'Xiaomi',
1240
1239
  fromZigbee: [fz.xiaomi_curtain_position, fz.cover_position_tilt, fz.xiaomi_curtain_options],
1241
1240
  toZigbee: [tz.xiaomi_curtain_position_state, tz.xiaomi_curtain_options],
1242
- exposes: [e.cover_position().setAccess('state', ea.ALL)],
1241
+ exposes: [e.cover_position().setAccess('state', ea.ALL),
1242
+ exposes.binary('running', ea.STATE, true, false)
1243
+ .withDescription('Whether the motor is moving or not')],
1243
1244
  ota: ota.zigbeeOTA,
1244
1245
  },
1245
1246
  {
@@ -1249,7 +1250,9 @@ module.exports = [
1249
1250
  vendor: 'Xiaomi',
1250
1251
  fromZigbee: [fz.xiaomi_curtain_position, fz.cover_position_tilt, fz.xiaomi_curtain_options],
1251
1252
  toZigbee: [tz.xiaomi_curtain_position_state, tz.xiaomi_curtain_options],
1252
- exposes: [e.cover_position().setAccess('state', ea.ALL)],
1253
+ exposes: [e.cover_position().setAccess('state', ea.ALL),
1254
+ exposes.binary('running', ea.STATE, true, false)
1255
+ .withDescription('Whether the motor is moving or not')],
1253
1256
  ota: ota.zigbeeOTA,
1254
1257
  },
1255
1258
  {
@@ -1266,7 +1269,9 @@ module.exports = [
1266
1269
  await device.endpoints[0].read('genAnalogOutput', ['presentValue']);
1267
1270
  }
1268
1271
  },
1269
- exposes: [e.cover_position().setAccess('state', ea.ALL), e.battery()],
1272
+ exposes: [e.cover_position().setAccess('state', ea.ALL), e.battery(),
1273
+ exposes.binary('running', ea.STATE, true, false)
1274
+ .withDescription('Whether the motor is moving or not')],
1270
1275
  configure: async (device, coordinatorEndpoint, logger) => {
1271
1276
  const endpoint = device.endpoints[0];
1272
1277
  await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
@@ -1286,7 +1291,7 @@ module.exports = [
1286
1291
  exposes.enum('motor_state', ea.STATE, ['declining', 'rising', 'pause', 'blocked'])
1287
1292
  .withDescription('The current state of the motor.'),
1288
1293
  exposes.binary('running', ea.STATE, true, false)
1289
- .withDescription('Whether the motor is moving or not.')],
1294
+ .withDescription('Whether the motor is moving or not')],
1290
1295
  configure: async (device, coordinatorEndpoint, logger) => {
1291
1296
  device.powerSource = 'Battery';
1292
1297
  device.save();
@@ -1304,10 +1309,11 @@ module.exports = [
1304
1309
  endpoint: (device) => {
1305
1310
  return {'l1': 1, 'l2': 2};
1306
1311
  },
1307
- exposes: [e.power().withAccess(ea.STATE_GET), e.energy(), e.temperature(), e.voltage().withAccess(ea.STATE), e.current(),
1308
- e.switch().withEndpoint('l1'), e.switch().withEndpoint('l2'),
1312
+ exposes: [e.power().withAccess(ea.STATE_GET), e.energy(), e.temperature(), e.voltage(), e.current(),
1313
+ e.switch().withEndpoint('l1'), e.switch().withEndpoint('l2'), e.power_outage_count(false),
1309
1314
  exposes.binary('interlock', ea.STATE_SET, true, false)
1310
- .withDescription('Enabling prevents both relais being on at the same time')],
1315
+ .withDescription('Enabling prevents both relais being on at the same time'),
1316
+ ],
1311
1317
  ota: ota.zigbeeOTA,
1312
1318
  },
1313
1319
  {
@@ -1481,8 +1487,9 @@ module.exports = [
1481
1487
  // Ignore energy metering reports, rely on aqara_opple: https://github.com/Koenkk/zigbee2mqtt/issues/10709
1482
1488
  fromZigbee: [fz.on_off, fz.device_temperature, fz.aqara_opple, fz.ignore_metering, fz.ignore_electrical_measurement,
1483
1489
  fz.xiaomi_power],
1484
- exposes: [e.switch(), e.energy(), e.power(), e.device_temperature(), e.power_outage_memory(), e.switch_type(),
1485
- e.voltage(), e.temperature(), e.current()],
1490
+ exposes: [e.switch(), e.energy(), e.power(), e.device_temperature(), e.power_outage_memory(), e.power_outage_count(),
1491
+ e.switch_type(), e.voltage(), e.temperature(), e.current(),
1492
+ ],
1486
1493
  toZigbee: [tz.xiaomi_switch_type, tz.on_off, tz.xiaomi_switch_power_outage_memory, tz.xiaomi_led_disabled_night],
1487
1494
  configure: async (device, coordinatorEndpoint, logger) => {
1488
1495
  const endpoint = device.getEndpoint(1);
package/lib/exposes.js CHANGED
@@ -582,6 +582,7 @@ module.exports = {
582
582
  position: () => new Numeric('position', access.STATE).withUnit('%').withDescription('Position'),
583
583
  power: () => new Numeric('power', access.STATE).withUnit('W').withDescription('Instantaneous measured power'),
584
584
  power_on_behavior: () => new Enum('power_on_behavior', access.ALL, ['off', 'previous', 'on']).withDescription('Controls the behavior when the device is powered on'),
585
+ power_outage_count: (resetsWhenPairing = true) => new Numeric('power_outage_count', access.STATE).withDescription('Number of power outages' + (resetsWhenPairing ? ' (since last pairing)' : '')),
585
586
  power_outage_memory: () => new Binary('power_outage_memory', access.ALL, true, false).withDescription('Enable/disable the power outage memory, this recovers the on/off mode after power failure'),
586
587
  presence: () => new Binary('presence', access.STATE, true, false).withDescription('Indicates whether the device detected presence'),
587
588
  pressure: () => new Numeric('pressure', access.STATE).withUnit('hPa').withDescription('The measured atmospheric pressure'),
package/lib/tuya.js CHANGED
@@ -420,7 +420,9 @@ const dataPoints = {
420
420
  tuyaSabFormaldehyd: 22,
421
421
  // tuya Smart Air House Keeper, Multifunctionale air quality detector.
422
422
  // CO2, Temp, Humidity, VOC and Formaldehyd same as Smart Air Box
423
- tuyaSahkMP25: 20,
423
+ tuyaSahkMP25: 2,
424
+ tuyaSahkCO2: 22,
425
+ tuyaSahkFormaldehyd: 20,
424
426
  // Tuya CO (carbon monoxide) smart air box
425
427
  tuyaSabCOalarm: 1,
426
428
  tuyaSabCO: 2,
package/lib/xiaomi.js CHANGED
@@ -160,7 +160,7 @@ const numericAttributes2Payload = (msg, meta, model, options, dataObject) => {
160
160
  payload.mode_switch = {4: 'anti_flicker_mode', 1: 'quick_mode'}[value];
161
161
  break;
162
162
  case '5':
163
- if (['JT-BZ-01AQ/A', 'RTCZCGQ11LM'].includes(model.model)) {
163
+ if (['Mains (single phase)', 'DC Source'].includes(meta.device.powerSource)) {
164
164
  payload.power_outage_count = value;
165
165
  }
166
166
  break;