zigbee-herdsman-converters 15.0.5 → 15.0.7

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.
@@ -2304,43 +2304,59 @@ const converters = {
2304
2304
  // Protocol description
2305
2305
  // https://github.com/Koenkk/zigbee-herdsman-converters/issues/1159#issuecomment-614659802
2306
2306
 
2307
- const dpValue = tuya.firstDpValue(msg, meta, 'tuya_cover');
2308
- const dp = dpValue.dp;
2309
- const value = tuya.getDataValue(dpValue);
2307
+ const result = {};
2310
2308
 
2311
- switch (dp) {
2312
- case tuya.dataPoints.coverPosition: // Started moving to position (triggered from Zigbee)
2313
- case tuya.dataPoints.coverArrived: { // Arrived at position
2314
- const invert = tuya.isCoverInverted(meta.device.manufacturerName) ? !options.invert_cover : options.invert_cover;
2315
- const position = invert ? 100 - (value & 0xFF) : (value & 0xFF);
2316
- const running = dp !== tuya.dataPoints.coverArrived;
2309
+ // Iterate through dpValues in case of some zigbee models returning multiple dp values in one message
2310
+ // For example: [TS0601, _TZE200_3ylew7b4]
2311
+ for (const dpValue of msg.data.dpValues) {
2312
+ const dp = dpValue.dp;
2313
+ const value = tuya.getDataValue(dpValue);
2317
2314
 
2318
- // Not all covers report coverArrived, so set running to false if device doesn't report position for a few seconds
2319
- clearTimeout(globalStore.getValue(msg.endpoint, 'running_timer'));
2320
- if (running) {
2321
- const timer = setTimeout(() => publish({running: false}), 3 * 1000);
2322
- globalStore.putValue(msg.endpoint, 'running_timer', timer);
2323
- }
2315
+ switch (dp) {
2316
+ case tuya.dataPoints.coverPosition: // Started moving to position (triggered from Zigbee)
2317
+ case tuya.dataPoints.coverArrived: { // Arrived at position
2318
+ const invert = tuya.isCoverInverted(meta.device.manufacturerName) ? !options.invert_cover : options.invert_cover;
2319
+ const position = invert ? 100 - (value & 0xff) : value & 0xff;
2320
+ const running = dp !== tuya.dataPoints.coverArrived;
2321
+
2322
+ // Not all covers report coverArrived, so set running to false if device doesn't report position
2323
+ // for a few seconds
2324
+ clearTimeout(globalStore.getValue(msg.endpoint, 'running_timer'));
2325
+ if (running) {
2326
+ const timer = setTimeout(() => publish({running: false}), 3 * 1000);
2327
+ globalStore.putValue(msg.endpoint, 'running_timer', timer);
2328
+ }
2324
2329
 
2325
- if (position > 0 && position <= 100) {
2326
- return {running, position, state: 'OPEN'};
2327
- } else if (position == 0) { // Report fully closed
2328
- return {running, position, state: 'CLOSE'};
2329
- } else {
2330
- return {running}; // Not calibrated yet, no position is available
2330
+ if (position > 0 && position <= 100) {
2331
+ result.running = running;
2332
+ result.position = position;
2333
+ result.state = 'OPEN';
2334
+ } else if (position == 0) {
2335
+ // Report fully closed
2336
+ result.running = running;
2337
+ result.position = position;
2338
+ result.state = 'CLOSE';
2339
+ } else {
2340
+ result.running = running; // Not calibrated yet, no position is available
2341
+ }
2342
+ }
2343
+ break;
2344
+ case tuya.dataPoints.coverSpeed: // Cover is reporting its current speed setting
2345
+ result.motor_speed = value;
2346
+ break;
2347
+ case tuya.dataPoints.state: // Ignore the cover state, it's not reliable between different covers!
2348
+ break;
2349
+ case tuya.dataPoints.coverChange: // Ignore manual cover change, it's not reliable between different covers!
2350
+ break;
2351
+ case tuya.dataPoints.config: // Returned by configuration set; ignore
2352
+ break;
2353
+ default: // Unknown code
2354
+ meta.logger.warn(`TuYa_cover_control: Unhandled DP #${dp} for ${meta.device.manufacturerName}:
2355
+ ${JSON.stringify(dpValue)}`);
2331
2356
  }
2332
2357
  }
2333
- case tuya.dataPoints.coverSpeed: // Cover is reporting its current speed setting
2334
- return {motor_speed: value};
2335
- case tuya.dataPoints.state: // Ignore the cover state, it's not reliable between different covers!
2336
- case tuya.dataPoints.coverChange: // Ignore manual cover change, it's not reliable between different covers!
2337
- break;
2338
- case tuya.dataPoints.config: // Returned by configuration set; ignore
2339
- break;
2340
- default: // Unknown code
2341
- meta.logger.warn(`TuYa_cover_control: Unhandled DP #${dp} for ${meta.device.manufacturerName}:
2342
- ${JSON.stringify(dpValue)}`);
2343
- }
2358
+
2359
+ return result;
2344
2360
  },
2345
2361
  },
2346
2362
  wiser_device_info: {
package/devices/bosch.js CHANGED
@@ -11,6 +11,21 @@ const ea = exposes.access;
11
11
  // Radiator Thermostat II
12
12
  const boschManufacturer = {manufacturerCode: 0x1209};
13
13
 
14
+ // Twinguard
15
+ const smokeSensitivity = {
16
+ 'low': 3,
17
+ 'medium': 2,
18
+ 'high': 1,
19
+ };
20
+
21
+ // Twinguard
22
+ const sirenState = {
23
+ 'stop': 0,
24
+ 'pre_alarm': 1,
25
+ 'fire': 2,
26
+ 'burglar': 3,
27
+ };
28
+
14
29
  // Radiator Thermostat II
15
30
  const operatingModes = {
16
31
  'automatic': 0,
@@ -122,6 +137,67 @@ const tzLocal = {
122
137
  }
123
138
  },
124
139
  },
140
+ bosch_twinguard: {
141
+ key: ['sensitivity', 'pre_alarm', 'self_test', 'alarm', 'heartbeat'],
142
+ convertSet: async (entity, key, value, meta) => {
143
+ if (key === 'sensitivity') {
144
+ value = value.toUpperCase();
145
+ const index = smokeSensitivity[value];
146
+ await entity.write('manuSpecificBosch', {0x4003: {value: index, type: 0x21}}, boschManufacturer);
147
+ return {state: {sensitivity: value}};
148
+ }
149
+ if (key === 'pre_alarm') {
150
+ value = value.toUpperCase();
151
+ const index = stateOffOn[value];
152
+ await entity.write('manuSpecificBosch5', {0x4001: {value: index, type: 0x18}}, boschManufacturer);
153
+ return {state: {pre_alarm: value}};
154
+ }
155
+ if (key === 'heartbeat') {
156
+ const endpoint = meta.device.getEndpoint(12);
157
+ value = value.toUpperCase();
158
+ const index = stateOffOn[value];
159
+ await endpoint.write('manuSpecificBosch7', {0x5005: {value: index, type: 0x18}}, boschManufacturer);
160
+ return {state: {heartbeat: value}};
161
+ }
162
+ if (key === 'self_test') {
163
+ if (value) {
164
+ await entity.command('manuSpecificBosch', 'initiateTestMode', boschManufacturer);
165
+ }
166
+ }
167
+ if (key === 'alarm') {
168
+ const endpoint = meta.device.getEndpoint(12);
169
+ const index = sirenState[value];
170
+ if (index == 0) {
171
+ await entity.commandResponse('genAlarms', 'alarm', {alarmcode: 0x16, clusterid: 0xe000}, {direction: 1});
172
+ await entity.commandResponse('genAlarms', 'alarm', {alarmcode: 0x14, clusterid: 0xe000}, {direction: 1});
173
+ await endpoint.command('manuSpecificBosch8', 'burglarAlarm', {data: 0}, boschManufacturer);
174
+ } else if (index == 1) {
175
+ await entity.commandResponse('genAlarms', 'alarm', {alarmcode: 0x11, clusterid: 0xe000}, {direction: 1});
176
+ return {state: {siren_state: 'pre-alarm'}};
177
+ } else if (index == 2) {
178
+ await entity.commandResponse('genAlarms', 'alarm', {alarmcode: 0x10, clusterid: 0xe000}, {direction: 1});
179
+ return {state: {siren_state: 'fire'}};
180
+ } else if (index == 3) {
181
+ await endpoint.command('manuSpecificBosch8', 'burglarAlarm', {data: 1}, boschManufacturer);
182
+ }
183
+ }
184
+ },
185
+ convertGet: async (entity, key, meta) => {
186
+ switch (key) {
187
+ case 'sensitivity':
188
+ await entity.read('manuSpecificBosch', [0x4003], boschManufacturer);
189
+ break;
190
+ case 'pre_alarm':
191
+ await entity.read('manuSpecificBosch5', [0x4001], boschManufacturer);
192
+ break;
193
+ case 'heartbeat':
194
+ await meta.device.getEndpoint(12).read('manuSpecificBosch7', [0x5005], boschManufacturer);
195
+ break;
196
+ default: // Unknown key
197
+ throw new Error(`Unhandled key toZigbee.bosch_twinguard.convertGet ${key}`);
198
+ }
199
+ },
200
+ },
125
201
  };
126
202
 
127
203
 
@@ -172,6 +248,112 @@ const fzLocal = {
172
248
  return result;
173
249
  },
174
250
  },
251
+ bosch_twinguard_sensitivity: {
252
+ cluster: 'manuSpecificBosch',
253
+ type: ['attributeReport', 'readResponse'],
254
+ options: [],
255
+ convert: (model, msg, publish, options, meta) => {
256
+ const result = {};
257
+ if (msg.data.hasOwnProperty(0x4003)) {
258
+ result.sensitivity = (Object.keys(smokeSensitivity)[msg.data[0x4003]]);
259
+ }
260
+ return result;
261
+ },
262
+ },
263
+ bosch_twinguard_measurements: {
264
+ cluster: 'manuSpecificBosch3',
265
+ type: ['attributeReport', 'readResponse'],
266
+ options: [exposes.options.precision('temperature'), exposes.options.calibration('temperature'),
267
+ exposes.options.precision('humidity'), exposes.options.calibration('humidity'),
268
+ exposes.options.calibration('illuminance_lux', 'percentual')],
269
+ convert: (model, msg, publish, options, meta) => {
270
+ const result = {};
271
+ if (msg.data.hasOwnProperty('humidity')) {
272
+ result.humidity = utils.calibrateAndPrecisionRoundOptions(msg.data['humidity'] / 100.0, options, 'humidity');
273
+ }
274
+ if (msg.data.hasOwnProperty('airpurity')) {
275
+ result.co2 = msg.data['airpurity'] * 10.0 + 500.0;
276
+ }
277
+ if (msg.data.hasOwnProperty('temperature')) {
278
+ result.temperature = utils.calibrateAndPrecisionRoundOptions(msg.data['temperature'] / 100.0, options, 'temperature');
279
+ }
280
+ if (msg.data.hasOwnProperty('illuminance_lux')) {
281
+ result.illuminance_lux = utils.calibrateAndPrecisionRoundOptions(
282
+ msg.data['illuminance_lux'] / 2.0, options, 'illuminance_lux');
283
+ }
284
+ if (msg.data.hasOwnProperty('battery')) {
285
+ result.battery = msg.data['battery'] / 2.0;
286
+ }
287
+ return result;
288
+ },
289
+ },
290
+ bosch_twinguard_pre_alarm: {
291
+ cluster: 'manuSpecificBosch5',
292
+ type: ['attributeReport', 'readResponse'],
293
+ options: [],
294
+ convert: (model, msg, publish, options, meta) => {
295
+ const result = {};
296
+ if (msg.data.hasOwnProperty('pre_alarm')) {
297
+ result.pre_alarm = (Object.keys(stateOffOn)[msg.data['pre_alarm']]);
298
+ }
299
+ return result;
300
+ },
301
+ },
302
+ bosch_twinguard_heartbeat: {
303
+ cluster: 'manuSpecificBosch7',
304
+ type: ['attributeReport', 'readResponse'],
305
+ options: [],
306
+ convert: (model, msg, publish, options, meta) => {
307
+ const result = {};
308
+ if (msg.data.hasOwnProperty('heartbeat')) {
309
+ result.heartbeat = (Object.keys(stateOffOn)[msg.data['heartbeat']]);
310
+ }
311
+ return result;
312
+ },
313
+ },
314
+ bosch_twinguard_alarm_state: {
315
+ cluster: 'manuSpecificBosch8',
316
+ type: ['attributeReport', 'readResponse'],
317
+ options: [],
318
+ convert: (model, msg, publish, options, meta) => {
319
+ const result = {};
320
+ const lookup = {
321
+ 0x00200020: 'clear',
322
+ 0x01200020: 'self_test',
323
+ 0x02200020: 'burglar',
324
+ 0x00200082: 'pre-alarm',
325
+ 0x00200081: 'fire',
326
+ 0x00200040: 'silenced',
327
+ };
328
+
329
+ if (msg.data.hasOwnProperty('alarm_status')) {
330
+ result.self_test = (msg.data['alarm_status'] & 1<<24) > 0;
331
+ result.smoke = (msg.data['alarm_status'] & 1<<7) > 0;
332
+ result.siren_state = lookup[msg.data['alarm_status']];
333
+ }
334
+ return result;
335
+ },
336
+ },
337
+ bosch_twinguard_smoke_alarm_state: {
338
+ cluster: 'genAlarms',
339
+ type: ['commandAlarm', 'readResponse'],
340
+ options: [],
341
+ convert: async (model, msg, publish, options, meta) => {
342
+ const result = {};
343
+ const lookup = {
344
+ 0x10: 'fire',
345
+ 0x11: 'pre-alarm',
346
+ 0x14: 'clear',
347
+ 0x16: 'silenced',
348
+ };
349
+ result.siren_state = lookup[msg.data.alarmcode];
350
+ if (msg.data.alarmcode == 0x10 || msg.data.alarmcode == 0x11) {
351
+ await msg.endpoint.commandResponse('genAlarms', 'alarm',
352
+ {alarmcode: msg.data.alarmcode, clusterid: 0xe000}, {direction: 1});
353
+ }
354
+ return result;
355
+ },
356
+ },
175
357
  };
176
358
 
177
359
  const definition = [
@@ -283,6 +465,47 @@ const definition = [
283
465
  await endpoint.read('hvacUserInterfaceCfg', [0x400b, 0x403a, 0x403b], boschManufacturer);
284
466
  },
285
467
  },
468
+ {
469
+ zigbeeModel: ['Champion'],
470
+ model: '8750001213',
471
+ vendor: 'Bosch',
472
+ description: 'Twinguard',
473
+ fromZigbee: [fzLocal.bosch_twinguard_measurements, fzLocal.bosch_twinguard_sensitivity,
474
+ fzLocal.bosch_twinguard_pre_alarm, fzLocal.bosch_twinguard_alarm_state, fzLocal.bosch_twinguard_smoke_alarm_state,
475
+ fzLocal.bosch_twinguard_heartbeat],
476
+ toZigbee: [tzLocal.bosch_twinguard],
477
+ configure: async (device, coordinatorEndpoint, logger) => {
478
+ const coordinatorEndpointB = coordinatorEndpoint.getDevice().getEndpoint(1);
479
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpointB, [0x0009]);
480
+ await reporting.bind(device.getEndpoint(7), coordinatorEndpointB, [0x0019]);
481
+ await reporting.bind(device.getEndpoint(7), coordinatorEndpointB, [0x0020]);
482
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpointB, [0xe000]);
483
+ await reporting.bind(device.getEndpoint(3), coordinatorEndpointB, [0xe002]);
484
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpointB, [0xe004]);
485
+ await reporting.bind(device.getEndpoint(12), coordinatorEndpointB, [0xe006]);
486
+ await reporting.bind(device.getEndpoint(12), coordinatorEndpointB, [0xe007]);
487
+ await device.getEndpoint(1).read('manuSpecificBosch5', ['unknown_attribute'], boschManufacturer); // Needed for pairing
488
+ await device.getEndpoint(12).command('manuSpecificBosch7', 'pairingCompleted', boschManufacturer); // Needed for pairing
489
+ await device.getEndpoint(1).write('manuSpecificBosch',
490
+ {0x4003: {value: 0x0002, type: 0x21}}, boschManufacturer); // Setting defaults
491
+ await device.getEndpoint(1).write('manuSpecificBosch5',
492
+ {0x4001: {value: 0x01, type: 0x18}}, boschManufacturer); // Setting defaults
493
+ await device.getEndpoint(12).write('manuSpecificBosch7',
494
+ {0x5005: {value: 0x01, type: 0x18}}, boschManufacturer); // Setting defaults
495
+ await device.getEndpoint(1).read('manuSpecificBosch', ['sensitivity'], boschManufacturer);
496
+ await device.getEndpoint(1).read('manuSpecificBosch5', ['pre_alarm'], boschManufacturer);
497
+ await device.getEndpoint(12).read('manuSpecificBosch7', ['heartbeat'], boschManufacturer);
498
+ },
499
+ exposes: [
500
+ e.smoke(), e.temperature(), e.humidity(), e.co2(), e.illuminance_lux(), e.battery(),
501
+ exposes.enum('alarm', ea.ALL, Object.keys(sirenState)).withDescription('Mode of the alarm (sound effect)'),
502
+ exposes.text('siren_state', ea.STATE).withDescription('Siren state'),
503
+ exposes.binary('self_test', ea.ALL, true, false).withDescription('Initiate self-test'),
504
+ exposes.enum('sensitivity', ea.ALL, Object.keys(smokeSensitivity)).withDescription('Sensitivity of the smoke alarm'),
505
+ exposes.enum('pre_alarm', ea.ALL, Object.keys(stateOffOn)).withDescription('Enable/disable pre-alarm'),
506
+ exposes.enum('heartbeat', ea.ALL, Object.keys(stateOffOn)).withDescription('Enable/disable heartbeat'),
507
+ ],
508
+ },
286
509
  ];
287
510
 
288
511
  module.exports = definition;
@@ -212,7 +212,7 @@ module.exports = [
212
212
  vendor: 'Centralite',
213
213
  description: '3-Series pearl touch thermostat',
214
214
  fromZigbee: [fz.battery, fz.thermostat, fz.fan, fz.ignore_time_read],
215
- toZigbee: [tz.factory_reset, tz.thermostat_local_temperature, tz.thermostat_local_temperature_calibration,
215
+ toZigbee: [tz.thermostat_local_temperature, tz.thermostat_local_temperature_calibration,
216
216
  tz.thermostat_occupied_heating_setpoint, tz.thermostat_occupied_cooling_setpoint,
217
217
  tz.thermostat_setpoint_raise_lower, tz.thermostat_remote_sensing,
218
218
  tz.thermostat_control_sequence_of_operation, tz.thermostat_system_mode,
@@ -242,7 +242,7 @@ module.exports = [
242
242
  vendor: 'Centralite',
243
243
  description: 'HA thermostat',
244
244
  fromZigbee: [fz.battery, fzLocal.thermostat_3156105, fz.fan, fz.ignore_time_read],
245
- toZigbee: [tz.factory_reset, tz.thermostat_local_temperature,
245
+ toZigbee: [tz.thermostat_local_temperature,
246
246
  tz.thermostat_occupied_heating_setpoint, tz.thermostat_occupied_cooling_setpoint,
247
247
  tz.thermostat_setpoint_raise_lower, tz.thermostat_remote_sensing,
248
248
  tz.thermostat_control_sequence_of_operation, tz.thermostat_system_mode,
@@ -437,7 +437,7 @@ module.exports = [
437
437
  vendor: 'Custom devices (DiY)',
438
438
  description: 'Flower sensor with rechargeable battery',
439
439
  fromZigbee: [fz.temperature, fz.illuminance, fz.soil_moisture, fz.battery],
440
- toZigbee: [tz.factory_reset],
440
+ toZigbee: [],
441
441
  meta: {multiEndpoint: true},
442
442
  configure: async (device, coordinatorEndpoint, logger) => {
443
443
  const firstEndpoint = device.getEndpoint(1);
@@ -458,7 +458,7 @@ module.exports = [
458
458
  vendor: 'Custom devices (DiY)',
459
459
  description: '[Plant Wattering Sensor, CR2450, CR2477 batteries, temperature ]',
460
460
  fromZigbee: [fz.temperature, fz.humidity, fz.illuminance, fz.soil_moisture, fz.battery, fzLocal.node_config],
461
- toZigbee: [tz.factory_reset, tzLocal.node_config],
461
+ toZigbee: [tzLocal.node_config],
462
462
  configure: async (device, coordinatorEndpoint, logger) => {
463
463
  const firstEndpoint = device.getEndpoint(1);
464
464
  await reporting.bind(firstEndpoint, coordinatorEndpoint, [
@@ -482,7 +482,7 @@ module.exports = [
482
482
  vendor: 'Custom devices (DiY)',
483
483
  description: 'DIY outdoor long-range sensor for temperature, humidity and atmospheric pressure',
484
484
  fromZigbee: [fz.temperature, fz.humidity, fz.pressure, fz.battery],
485
- toZigbee: [tz.factory_reset],
485
+ toZigbee: [],
486
486
  configure: async (device, coordinatorEndpoint, logger) => {
487
487
  const endpoint = device.getEndpoint(1);
488
488
  await reporting.bind(endpoint, coordinatorEndpoint, [
@@ -503,7 +503,7 @@ module.exports = [
503
503
  vendor: 'Custom devices (DiY)',
504
504
  description: '[Plant wattering sensor with e-ink display](https://efektalab.com/epws102)',
505
505
  fromZigbee: [fz.temperature, fz.soil_moisture, fz.battery],
506
- toZigbee: [tz.factory_reset],
506
+ toZigbee: [],
507
507
  configure: async (device, coordinatorEndpoint, logger) => {
508
508
  const firstEndpoint = device.getEndpoint(1);
509
509
  await reporting.bind(firstEndpoint, coordinatorEndpoint, ['genPowerCfg', 'msTemperatureMeasurement', 'msSoilMoisture']);
@@ -521,7 +521,7 @@ module.exports = [
521
521
  vendor: 'Custom devices (DiY)',
522
522
  description: '[Temperature and humidity sensor with e-ink2.13](http://efektalab.com/eON213z)',
523
523
  fromZigbee: [fz.temperature, fz.humidity, fz.battery],
524
- toZigbee: [tz.factory_reset],
524
+ toZigbee: [],
525
525
  configure: async (device, coordinatorEndpoint, logger) => {
526
526
  const endpoint = device.getEndpoint(1);
527
527
  await reporting.bind(endpoint, coordinatorEndpoint, [
@@ -540,7 +540,7 @@ module.exports = [
540
540
  vendor: 'Custom devices (DiY)',
541
541
  description: '[Mini plant wattering sensor](http://efektalab.com/miniPWS)',
542
542
  fromZigbee: [fz.soil_moisture, fz.battery, fzLocal.node_config],
543
- toZigbee: [tz.factory_reset, tzLocal.node_config],
543
+ toZigbee: [tzLocal.node_config],
544
544
  configure: async (device, coordinatorEndpoint, logger) => {
545
545
  const firstEndpoint = device.getEndpoint(1);
546
546
  await reporting.bind(firstEndpoint, coordinatorEndpoint, ['genPowerCfg', 'msSoilMoisture']);
@@ -555,7 +555,7 @@ module.exports = [
555
555
  vendor: 'Custom devices (DiY)',
556
556
  description: '[Mini weather station, digital barometer, forecast, charts, temperature, humidity](http://efektalab.com/eON213wz)',
557
557
  fromZigbee: [fz.temperature, fz.humidity, fz.pressure, fz.battery],
558
- toZigbee: [tz.factory_reset],
558
+ toZigbee: [],
559
559
  configure: async (device, coordinatorEndpoint, logger) => {
560
560
  const endpoint = device.getEndpoint(1);
561
561
  await reporting.bind(endpoint, coordinatorEndpoint, [
@@ -576,7 +576,7 @@ module.exports = [
576
576
  vendor: 'Custom devices (DiY)',
577
577
  description: '[DIY temperature, humidity and atmospheric pressure sensor, long battery life](http://efektalab.com/eON_THP)',
578
578
  fromZigbee: [fz.temperature, fz.humidity, fz.pressure, fz.battery],
579
- toZigbee: [tz.factory_reset],
579
+ toZigbee: [],
580
580
  configure: async (device, coordinatorEndpoint, logger) => {
581
581
  const endpoint = device.getEndpoint(1);
582
582
  await reporting.bind(endpoint, coordinatorEndpoint, [
@@ -597,7 +597,7 @@ module.exports = [
597
597
  vendor: 'Custom devices (DiY)',
598
598
  description: '[Plant watering sensor EFEKTA PWS max](http://efektalab.com/PWS_Max)',
599
599
  fromZigbee: [fz.temperature, fz.humidity, fz.illuminance, fz.soil_moisture, fz.battery],
600
- toZigbee: [tz.factory_reset],
600
+ toZigbee: [],
601
601
  configure: async (device, coordinatorEndpoint, logger) => {
602
602
  const firstEndpoint = device.getEndpoint(1);
603
603
  await reporting.bind(firstEndpoint, coordinatorEndpoint, [
@@ -618,7 +618,7 @@ module.exports = [
618
618
  vendor: 'Custom devices (DiY)',
619
619
  description: '[Plant watering sensor EFEKTA PWS Max Pro, long battery life](http://efektalab.com/PWS_MaxPro)',
620
620
  fromZigbee: [fz.temperature, fz.humidity, fz.illuminance, fz.soil_moisture, fz.battery],
621
- toZigbee: [tz.factory_reset],
621
+ toZigbee: [],
622
622
  configure: async (device, coordinatorEndpoint, logger) => {
623
623
  const firstEndpoint = device.getEndpoint(1);
624
624
  await reporting.bind(firstEndpoint, coordinatorEndpoint, [
@@ -639,7 +639,7 @@ module.exports = [
639
639
  vendor: 'Custom devices (DiY)',
640
640
  description: '[Mini weather station, barometer, forecast, charts, temperature, humidity, light](http://efektalab.com/eON290wz)',
641
641
  fromZigbee: [fz.temperature, fz.humidity, fz.pressure, fz.illuminance, fz.battery],
642
- toZigbee: [tz.factory_reset],
642
+ toZigbee: [],
643
643
  configure: async (device, coordinatorEndpoint, logger) => {
644
644
  const endpoint = device.getEndpoint(1);
645
645
  await reporting.bind(endpoint, coordinatorEndpoint, [
@@ -661,7 +661,7 @@ module.exports = [
661
661
  vendor: 'Custom devices (DiY)',
662
662
  description: '[Plant Wattering Sensor with e-ink display 2.13](https://efektalab.com/eFlowerPro)',
663
663
  fromZigbee: [fz.temperature, fz.humidity, fz.illuminance, fz.soil_moisture, fz.battery],
664
- toZigbee: [tz.factory_reset],
664
+ toZigbee: [],
665
665
  configure: async (device, coordinatorEndpoint, logger) => {
666
666
  const firstEndpoint = device.getEndpoint(1);
667
667
  await reporting.bind(firstEndpoint, coordinatorEndpoint, [
@@ -682,7 +682,7 @@ module.exports = [
682
682
  vendor: 'Custom devices (DiY)',
683
683
  description: '[Mini digital thermometer & hygrometer with e-ink1.02](http://efektalab.com/eTH102)',
684
684
  fromZigbee: [fz.temperature, fz.humidity, fz.battery],
685
- toZigbee: [tz.factory_reset],
685
+ toZigbee: [],
686
686
  configure: async (device, coordinatorEndpoint, logger) => {
687
687
  const endpoint = device.getEndpoint(1);
688
688
  await reporting.bind(endpoint, coordinatorEndpoint, [
@@ -702,7 +702,7 @@ module.exports = [
702
702
  description: '[CO2 Monitor with IPS TFT Display, outdoor temperature and humidity, date and time](http://efektalab.com/iAQ)',
703
703
  fromZigbee: [fz.temperature, fz.humidity, fz.illuminance, fzLocal.co2, fzLocal.co2_config,
704
704
  fzLocal.temperature_config, fzLocal.humidity_config],
705
- toZigbee: [tz.factory_reset, tzLocal.co2_config, tzLocal.temperature_config, tzLocal.humidity_config, tzLocal.local_time],
705
+ toZigbee: [tzLocal.co2_config, tzLocal.temperature_config, tzLocal.humidity_config, tzLocal.local_time],
706
706
  configure: async (device, coordinatorEndpoint, logger) => {
707
707
  const endpoint = device.getEndpoint(1);
708
708
  const clusters = ['msTemperatureMeasurement', 'msRelativeHumidity', 'msIlluminanceMeasurement', 'msCO2'];
@@ -762,7 +762,7 @@ module.exports = [
762
762
  description: '[EFEKTA CO2 Smart Monitor, ws2812b indicator, can control the relay, binding](https://efektalab.com/CO2_Monitor)',
763
763
  fromZigbee: [fz.temperature, fz.humidity, fzLocal.co2, fzLocal.co2_config, fzLocal.temperature_config,
764
764
  fzLocal.humidity_config, fzLocal.termostat_config, fzLocal.hydrostat_config, fzLocal.co2_gasstat_config],
765
- toZigbee: [tz.factory_reset, tzLocal.co2_config, tzLocal.temperature_config, tzLocal.humidity_config,
765
+ toZigbee: [tzLocal.co2_config, tzLocal.temperature_config, tzLocal.humidity_config,
766
766
  tzLocal.termostat_config, tzLocal.hydrostat_config, tzLocal.co2_gasstat_config],
767
767
  configure: async (device, coordinatorEndpoint, logger) => {
768
768
  const endpoint = device.getEndpoint(1);
@@ -813,7 +813,7 @@ module.exports = [
813
813
  vendor: 'Custom devices (DiY)',
814
814
  description: 'Alternative firmware for the SONOFF SNZB-02 sensor from EfektaLab, DIY',
815
815
  fromZigbee: [fz.temperature, fz.humidity, fz.battery, fzLocal.termostat_config, fzLocal.hydrostat_config, fzLocal.node_config],
816
- toZigbee: [tz.factory_reset, tzLocal.termostat_config, tzLocal.hydrostat_config, tzLocal.node_config],
816
+ toZigbee: [tzLocal.termostat_config, tzLocal.hydrostat_config, tzLocal.node_config],
817
817
  configure: async (device, coordinatorEndpoint, logger) => {
818
818
  const endpoint = device.getEndpoint(1);
819
819
  await reporting.bind(endpoint, coordinatorEndpoint, [
package/devices/diyruz.js CHANGED
@@ -73,7 +73,7 @@ module.exports = [
73
73
  }
74
74
  return features;
75
75
  })(20)),
76
- toZigbee: [tz.diyruz_freepad_on_off_config, tz.factory_reset],
76
+ toZigbee: [tz.diyruz_freepad_on_off_config],
77
77
  configure: async (device, coordinatorEndpoint, logger) => {
78
78
  const endpoint = device.getEndpoint(1);
79
79
  await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
@@ -116,7 +116,7 @@ module.exports = [
116
116
  }
117
117
  return features;
118
118
  })(8)),
119
- toZigbee: [tz.diyruz_freepad_on_off_config, tz.factory_reset],
119
+ toZigbee: [tz.diyruz_freepad_on_off_config],
120
120
  configure: async (device, coordinatorEndpoint, logger) => {
121
121
  const endpoint = device.getEndpoint(1);
122
122
  await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
@@ -157,7 +157,7 @@ module.exports = [
157
157
  exposes.numeric('sensors_count', ea.ALL).withDescription('Count of installed tubes').withValueMin(0).withValueMax(50),
158
158
  exposes.numeric('sensitivity', ea.ALL).withDescription('This is applicable if tubes type is set to other')
159
159
  .withValueMin(0).withValueMax(100)],
160
- toZigbee: [tz.diyruz_geiger_config, tz.factory_reset],
160
+ toZigbee: [tz.diyruz_geiger_config],
161
161
  configure: async (device, coordinatorEndpoint, logger) => {
162
162
  const endpoint = device.getEndpoint(1);
163
163
  await reporting.bind(endpoint, coordinatorEndpoint, ['msIlluminanceMeasurement', 'genOnOff']);
@@ -202,7 +202,7 @@ module.exports = [
202
202
  vendor: 'DIYRuZ',
203
203
  description: '[Flower sensor](http://modkam.ru/?p=1700)',
204
204
  fromZigbee: [fz.temperature, fz.humidity, fz.illuminance, fz.soil_moisture, fz.pressure, fz.battery],
205
- toZigbee: [tz.factory_reset],
205
+ toZigbee: [],
206
206
  meta: {multiEndpoint: true},
207
207
  endpoint: (device) => {
208
208
  return {'bme': 1, 'ds': 2};
@@ -237,7 +237,7 @@ module.exports = [
237
237
  description: '[Air quality sensor](https://modkam.ru/?p=1715)',
238
238
  fromZigbee: [fz.temperature, fz.humidity, fz.co2, fz.pressure, fz.diyruz_airsense_config_co2,
239
239
  fz.diyruz_airsense_config_temp, fz.diyruz_airsense_config_pres, fz.diyruz_airsense_config_hum],
240
- toZigbee: [tz.factory_reset, tz.diyruz_airsense_config],
240
+ toZigbee: [tz.diyruz_airsense_config],
241
241
  configure: async (device, coordinatorEndpoint, logger) => {
242
242
  const endpoint = device.getEndpoint(1);
243
243
  const clusters = ['msTemperatureMeasurement', 'msRelativeHumidity', 'msPressureMeasurement', 'msCO2'];
@@ -269,7 +269,7 @@ module.exports = [
269
269
  vendor: 'DIYRuZ',
270
270
  description: '[Matrix intercom auto opener](https://diyruz.github.io/posts/zintercom/)',
271
271
  fromZigbee: [fz.battery, fz.diyruz_zintercom_config],
272
- toZigbee: [tz.factory_reset, tz.diyruz_zintercom_config],
272
+ toZigbee: [tz.diyruz_zintercom_config],
273
273
  configure: async (device, coordinatorEndpoint, logger) => {
274
274
  const firstEndpoint = device.getEndpoint(1);
275
275
  await reporting.bind(firstEndpoint, coordinatorEndpoint, ['closuresDoorLock', 'genPowerCfg']);
package/devices/ecozy.js CHANGED
@@ -12,7 +12,7 @@ module.exports = [
12
12
  vendor: 'eCozy',
13
13
  description: 'Smart heating thermostat',
14
14
  fromZigbee: [fz.battery, fz.legacy.thermostat_att_report],
15
- toZigbee: [tz.factory_reset, tz.thermostat_local_temperature, tz.thermostat_local_temperature_calibration, tz.thermostat_occupancy,
15
+ toZigbee: [tz.thermostat_local_temperature, tz.thermostat_local_temperature_calibration, tz.thermostat_occupancy,
16
16
  tz.thermostat_occupied_heating_setpoint, tz.thermostat_unoccupied_heating_setpoint, tz.thermostat_setpoint_raise_lower,
17
17
  tz.thermostat_remote_sensing, tz.thermostat_control_sequence_of_operation, tz.thermostat_system_mode,
18
18
  tz.thermostat_weekly_schedule, tz.thermostat_clear_weekly_schedule, tz.thermostat_relay_status_log,
@@ -90,7 +90,7 @@ module.exports = [
90
90
  vendor: 'Leviton',
91
91
  description: 'Omnistat2 wireless thermostat',
92
92
  fromZigbee: [fz.legacy.thermostat_att_report, fz.fan],
93
- toZigbee: [tz.factory_reset, tz.thermostat_local_temperature, tz.thermostat_local_temperature_calibration, tz.thermostat_occupancy,
93
+ toZigbee: [tz.thermostat_local_temperature, tz.thermostat_local_temperature_calibration, tz.thermostat_occupancy,
94
94
  tz.thermostat_occupied_heating_setpoint, tz.thermostat_unoccupied_heating_setpoint, tz.thermostat_occupied_cooling_setpoint,
95
95
  tz.thermostat_unoccupied_cooling_setpoint, tz.thermostat_setpoint_raise_lower, tz.thermostat_remote_sensing,
96
96
  tz.thermostat_control_sequence_of_operation, tz.thermostat_system_mode, tz.thermostat_weekly_schedule,
package/devices/lidl.js CHANGED
@@ -8,7 +8,6 @@ const ea = exposes.access;
8
8
  const tuya = require('../lib/tuya');
9
9
  const globalStore = require('../lib/store');
10
10
  const ota = require('../lib/ota');
11
- const utils = require('../lib/utils');
12
11
 
13
12
  const tuyaLocal = {
14
13
  dataPoints: {
@@ -543,11 +542,6 @@ module.exports = [
543
542
  vendor: 'Lidl',
544
543
  description: 'Livarno smart LED ceiling light',
545
544
  ...extend.light_onoff_brightness_colortemp_color({disableColorTempStartup: true, colorTempRange: [153, 500]}),
546
- toZigbee: utils.replaceInArray(
547
- extend.light_onoff_brightness_colortemp_color({disableColorTempStartup: true, colorTempRange: [153, 500]}).toZigbee,
548
- [tz.light_color_colortemp],
549
- [tz.light_color_and_colortemp_via_color],
550
- ),
551
545
  meta: {applyRedFix: true, enhancedHue: false},
552
546
  configure: async (device, coordinatorEndpoint, logger) => {
553
547
  device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 29});
package/devices/lux.js CHANGED
@@ -10,7 +10,7 @@ module.exports = [
10
10
  vendor: 'LUX',
11
11
  description: 'KONOz thermostat',
12
12
  fromZigbee: [fz.battery, fz.thermostat, fz.fan, fz.thermostat_weekly_schedule],
13
- toZigbee: [tz.factory_reset, tz.thermostat_local_temperature,
13
+ toZigbee: [tz.thermostat_local_temperature,
14
14
  tz.thermostat_occupancy, tz.thermostat_occupied_heating_setpoint, tz.thermostat_occupied_cooling_setpoint,
15
15
  tz.thermostat_unoccupied_heating_setpoint, tz.thermostat_setpoint_raise_lower, tz.thermostat_running_state,
16
16
  tz.fan_mode, tz.thermostat_system_mode,
File without changes
package/devices/neo.js CHANGED
@@ -35,7 +35,7 @@ module.exports = [
35
35
  },
36
36
  },
37
37
  {
38
- fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_t1blo2bj'}],
38
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_t1blo2bj'}, {modelID: 'TS0601', manufacturerName: '_TZE204_t1blo2bj'}],
39
39
  zigbeeModel: ['1blo2bj'],
40
40
  model: 'NAS-AB02B2',
41
41
  vendor: 'Neo',
@@ -1693,7 +1693,7 @@ module.exports = [
1693
1693
  extend: hueExtend.light_onoff_brightness_colortemp_color(),
1694
1694
  },
1695
1695
  {
1696
- zigbeeModel: ['1746430P7'],
1696
+ zigbeeModel: ['1746430P7', '929003098701'],
1697
1697
  model: '1746430P7',
1698
1698
  vendor: 'Philips',
1699
1699
  description: 'Hue outdoor Resonate wall lamp (black)',
@@ -2271,6 +2271,13 @@ module.exports = [
2271
2271
  description: 'Hue White Fuzo outdoor floor light',
2272
2272
  extend: hueExtend.light_onoff_brightness(),
2273
2273
  },
2274
+ {
2275
+ zigbeeModel: ['929003098901'],
2276
+ model: '929003098901',
2277
+ vendor: 'Philips',
2278
+ description: 'Hue White Inara outdoor light',
2279
+ extend: hueExtend.light_onoff_brightness(),
2280
+ },
2274
2281
  {
2275
2282
  zigbeeModel: ['1744530P7', '1744630P7', '1744430P7', '1744730P7'],
2276
2283
  model: '8718696170625',