zigbee-herdsman-converters 14.0.418 → 14.0.422

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.
@@ -4141,6 +4141,25 @@ const converters = {
4141
4141
  }
4142
4142
  },
4143
4143
  },
4144
+ tuya_CO: {
4145
+ cluster: 'manuSpecificTuya',
4146
+ type: ['commandDataReport', 'commandDataResponse'],
4147
+ options: [exposes.options.precision('co'), exposes.options.calibration('co')],
4148
+ convert: (model, msg, publish, options, meta) => {
4149
+ const dpValue = tuya.firstDpValue(msg, meta, 'tuya_CO');
4150
+ const dp = dpValue.dp;
4151
+ const value = tuya.getDataValue(dpValue);
4152
+ switch (dp) {
4153
+ case tuya.dataPoints.tuyaSabCO:
4154
+ return {co: calibrateAndPrecisionRoundOptions(value / 100, options, 'co')};
4155
+ case tuya.dataPoints.tuyaSabCOalarm:
4156
+ return {carbon_monoxide: value ? 'OFF' : 'ON'};
4157
+ default:
4158
+ meta.logger.warn(`zigbee-herdsman-converters:TuyaSmartAirBox: Unrecognized DP #${
4159
+ dp} with data ${JSON.stringify(dpValue)}`);
4160
+ }
4161
+ },
4162
+ },
4144
4163
  saswell_thermostat: {
4145
4164
  cluster: 'manuSpecificTuya',
4146
4165
  type: ['commandDataResponse', 'commandDataReport'],
@@ -4434,7 +4453,7 @@ const converters = {
4434
4453
  case tuya.dataPoints.ecoTemp:
4435
4454
  return {eco_temperature: value};
4436
4455
  case tuya.dataPoints.valvePos:
4437
- return {position: value};
4456
+ return {position: value, running_state: value ? 'heat' : 'idle'};
4438
4457
  case tuya.dataPoints.awayTemp:
4439
4458
  return {away_preset_temperature: value};
4440
4459
  case tuya.dataPoints.awayDays:
@@ -8150,7 +8169,7 @@ const converters = {
8150
8169
  1: 'on',
8151
8170
  2: 'previous',
8152
8171
  };
8153
- result.power_on_behaviour = lookup[value];
8172
+ result.power_on_behavior = lookup[value];
8154
8173
  }
8155
8174
  if (dp === tuya.dataPoints.hochFaultCode) {
8156
8175
  const lookup = {
@@ -8410,6 +8429,20 @@ const converters = {
8410
8429
  }
8411
8430
  },
8412
8431
  },
8432
+ tm081: {
8433
+ cluster: 'manuSpecificTuya',
8434
+ type: ['commandDataReport'],
8435
+ convert: (model, msg, publish, options, meta) => {
8436
+ const dpValue = tuya.firstDpValue(msg, meta, 'tm0801');
8437
+ const dp = dpValue.dp;
8438
+ const value = tuya.getDataValue(dpValue);
8439
+ if (dp === 1) return {contact: value === true ? false : true};
8440
+ if (dp === 2) return {battery: value};
8441
+ else {
8442
+ meta.logger.warn(`zigbee-herdsman-converters:TM081: NOT RECOGNIZED DP #${dp} with data ${JSON.stringify(dpValue)}`);
8443
+ }
8444
+ },
8445
+ },
8413
8446
  // #endregion
8414
8447
 
8415
8448
  // #region Ignore converters (these message dont need parsing).
@@ -299,6 +299,10 @@ const converters = {
299
299
  convertSet: async (entity, key, value, meta) => {
300
300
  if (typeof value !== 'number') {
301
301
  value = value.toLowerCase();
302
+ if (value === 'stop') {
303
+ await entity.command('genLevelCtrl', 'stop', {}, utils.getOptions(meta.mapped, entity));
304
+ return;
305
+ }
302
306
  const lookup = {'open': 100, 'close': 0};
303
307
  utils.validateValue(value, Object.keys(lookup));
304
308
  value = lookup[value];
@@ -7002,7 +7006,7 @@ const converters = {
7002
7006
  key: ['state',
7003
7007
  'child_lock',
7004
7008
  'countdown_timer',
7005
- 'power_on_behaviour',
7009
+ 'power_on_behavior',
7006
7010
  'trip',
7007
7011
  'clear_device_data',
7008
7012
  /* TODO: Add the below keys when toZigbee converter work has been completed
@@ -7021,10 +7025,10 @@ const converters = {
7021
7025
  } else if (key === 'countdown_timer') {
7022
7026
  await tuya.sendDataPointValue(entity, tuya.dataPoints.hochCountdownTimer, value);
7023
7027
  return {state: {countdown_timer: value}};
7024
- } else if (key === 'power_on_behaviour') {
7028
+ } else if (key === 'power_on_behavior') {
7025
7029
  const lookup = {'off': 0, 'on': 1, 'previous': 2};
7026
7030
  await tuya.sendDataPointEnum(entity, tuya.dataPoints.hochRelayStatus, lookup[value], 'sendData');
7027
- return {state: {power_on_behaviour: value}};
7031
+ return {state: {power_on_behavior: value}};
7028
7032
  } else if (key === 'trip') {
7029
7033
  if (value === 'clear') {
7030
7034
  await tuya.sendDataPointBool(entity, tuya.dataPoints.hochLocking, true, 'sendData');
package/devices/adeo.js CHANGED
@@ -26,7 +26,7 @@ module.exports = [
26
26
  },
27
27
  },
28
28
  {
29
- zigbeeModel: ['LXEK-5'],
29
+ zigbeeModel: ['LXEK-5', 'ZBEK-26'],
30
30
  model: 'HR-C99C-Z-C045',
31
31
  vendor: 'ADEO',
32
32
  description: 'RGB CTT LEXMAN ENKI remote control',
@@ -71,6 +71,13 @@ module.exports = [
71
71
  description: 'ENKI Lexman E27 14W to 100W LED RGBW',
72
72
  extend: extend.light_onoff_brightness_colortemp_color(),
73
73
  },
74
+ {
75
+ zigbeeModel: ['ZBEK-2'],
76
+ model: 'IG-CDZOTAAG014RA-MAN',
77
+ vendor: 'ADEO',
78
+ description: 'ENKI Lexman E27 14W to 100W LED RGBW v2',
79
+ extend: extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 370]}),
80
+ },
74
81
  {
75
82
  zigbeeModel: ['LXEK-7'],
76
83
  model: '9CZA-A806ST-Q1Z',
@@ -0,0 +1,11 @@
1
+ const extend = require('../lib/extend');
2
+
3
+ module.exports = [
4
+ {
5
+ zigbeeModel: ['AL8TC13W-AP'],
6
+ model: 'AL8TC13W-AP',
7
+ vendor: 'Alchemy',
8
+ description: 'Downlight with tuneable white',
9
+ extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 370]}),
10
+ },
11
+ ];
@@ -4,6 +4,21 @@ const tz = require('../converters/toZigbee');
4
4
  const reporting = require('../lib/reporting');
5
5
  const extend = require('../lib/extend');
6
6
  const e = exposes.presets;
7
+ const utils = require('zigbee-herdsman-converters/lib/utils');
8
+ const ea = exposes.access;
9
+
10
+ const tzLocal = {
11
+ aOneBacklight: {
12
+ key: ['backlight_led'],
13
+ convertSet: async (entity, key, value, meta) => {
14
+ const state = value.toLowerCase();
15
+ utils.validateValue(state, ['toggle', 'off', 'on']);
16
+ const endpoint = meta.device.getEndpoint(3);
17
+ await endpoint.command('genOnOff', state, {});
18
+ return {state: {backlight_led: state.toUpperCase()}};
19
+ },
20
+ },
21
+ };
7
22
 
8
23
  const batteryRotaryDimmer = (...endpointsIds) => ({
9
24
  fromZigbee: [fz.battery, fz.command_on, fz.command_off, fz.command_step, fz.command_step_color_temperature],
@@ -129,6 +144,9 @@ module.exports = [
129
144
  model: 'AU-A1ZB2WDM',
130
145
  vendor: 'Aurora Lighting',
131
146
  description: 'AOne 250W smart rotary dimmer module',
147
+ exposes: [...extend.light_onoff_brightness({noConfigure: true}).exposes,
148
+ exposes.binary('backlight_led', ea.STATE_SET, 'ON', 'OFF').withDescription('Enable or disable the blue backlight LED')],
149
+ toZigbee: [...extend.light_onoff_brightness({noConfigure: true}).toZigbee, tzLocal.aOneBacklight],
132
150
  extend: extend.light_onoff_brightness({noConfigure: true}),
133
151
  configure: async (device, coordinatorEndpoint, logger) => {
134
152
  await extend.light_onoff_brightness().configure(device, coordinatorEndpoint, logger);
package/devices/awox.js CHANGED
@@ -1,4 +1,64 @@
1
1
  const extend = require('../lib/extend');
2
+ const fz = require('../converters/fromZigbee');
3
+ const exposes = require('../lib/exposes');
4
+ const e = exposes.presets;
5
+
6
+ const awoxRemoteHelper = {
7
+ convertToColorName: (buffer) => {
8
+ const commonForColors = buffer[0] === 17 && buffer[2] === 48 && buffer[3] === 0 && buffer[5] === 8 && buffer[6] === 0;
9
+
10
+ if (commonForColors && buffer[4] === 255) {
11
+ return 'red';
12
+ } else if (commonForColors && buffer[4] === 42) {
13
+ return 'yellow';
14
+ } else if (commonForColors && buffer[4] === 85) {
15
+ return 'green';
16
+ } else if (commonForColors && buffer[4] === 170) {
17
+ return 'blue';
18
+ }
19
+ return null;
20
+ },
21
+ isRefresh: (buffer) => {
22
+ return buffer[0] === 17 && buffer[2] === 16 && buffer[3] === 1 && buffer[4] === 1;
23
+ },
24
+ };
25
+
26
+ const fzLocal = {
27
+ colors: {
28
+ cluster: 'lightingColorCtrl',
29
+ type: ['raw'],
30
+ convert: (model, msg, publish, options, meta) => {
31
+ const color = awoxRemoteHelper.convertToColorName(msg.data);
32
+ if (color != null) {
33
+ return {
34
+ action: color,
35
+ };
36
+ }
37
+ },
38
+ },
39
+ refreshColored: {
40
+ cluster: 'lightingColorCtrl',
41
+ type: ['commandMoveHue'],
42
+ convert: (model, msg, publish, options, meta) => {
43
+ if (msg.data.movemode === 1 && msg.data.rate === 12) {
44
+ return {
45
+ action: 'refresh_colored',
46
+ };
47
+ }
48
+ },
49
+ },
50
+ refresh: {
51
+ cluster: 'genLevelCtrl',
52
+ type: ['raw'],
53
+ convert: (model, msg, publish, options, meta) => {
54
+ if (awoxRemoteHelper.isRefresh(msg.data)) {
55
+ return {
56
+ action: 'refresh',
57
+ };
58
+ }
59
+ },
60
+ },
61
+ };
2
62
 
3
63
  module.exports = [
4
64
  {
@@ -8,6 +68,23 @@ module.exports = [
8
68
  description: 'LED white',
9
69
  extend: extend.light_onoff_brightness(),
10
70
  },
71
+ {
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
+ ]},
77
+ ],
78
+ model: '33952',
79
+ vendor: 'AwoX',
80
+ description: 'Remote controller',
81
+ fromZigbee: [fz.command_on, fzLocal.colors, fzLocal.refresh, fzLocal.refreshColored, fz.command_off,
82
+ fz.command_step, fz.command_move, fz.command_stop, fz.command_recall, fz.command_step_color_temperature],
83
+ toZigbee: [],
84
+ exposes: [e.action(['on', 'off', 'red', 'refresh', 'refresh_colored', 'blue', 'yellow',
85
+ 'green', 'brightness_step_up', 'brightness_step_down', 'brightness_move_up', 'brightness_move_down', 'brightness_stop',
86
+ 'recall_1', 'color_temperature_step_up', 'color_temperature_step_down'])],
87
+ },
11
88
  {
12
89
  fingerprint: [
13
90
  {type: 'Router', manufacturerName: 'AwoX', modelID: 'TLSR82xx', endpoints: [
@@ -15,6 +15,18 @@ module.exports = [
15
15
  await reporting.onOff(endpoint);
16
16
  },
17
17
  },
18
+ {
19
+ zigbeeModel: ['43078'],
20
+ model: '43078',
21
+ vendor: 'Enbrighten',
22
+ description: 'Zigbee in-wall smart switch',
23
+ extend: extend.switch(),
24
+ configure: async (device, coordinatorEndpoint, logger) => {
25
+ const endpoint = device.getEndpoint(1);
26
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
27
+ await reporting.onOff(endpoint);
28
+ },
29
+ },
18
30
  {
19
31
  zigbeeModel: ['43080'],
20
32
  model: '43080',
package/devices/ikea.js CHANGED
@@ -285,6 +285,13 @@ module.exports = [
285
285
  description: 'TRADFRI LED bulb E27 1055 lumen, dimmable, white spectrum, opal white',
286
286
  extend: tradfriExtend.light_onoff_brightness_colortemp(),
287
287
  },
288
+ {
289
+ zigbeeModel: ['TRADFRIbulbE27WSglobeclear806lm'],
290
+ model: 'LED2004G8',
291
+ vendor: 'IKEA',
292
+ description: 'TRADFRI LED bulb E27 806 lumen, dimmable, white spectrum, clear',
293
+ extend: tradfriExtend.light_onoff_brightness_colortemp(),
294
+ },
288
295
  {
289
296
  zigbeeModel: ['TRADFRI bulb E27 opal 470lm', 'TRADFRI bulb E27 W opal 470lm', 'TRADFRIbulbT120E27WSopal470lm'],
290
297
  model: 'LED1937T5_E27',
package/devices/lds.js ADDED
@@ -0,0 +1,11 @@
1
+ const extend = require('../lib/extend');
2
+
3
+ module.exports = [
4
+ {
5
+ zigbeeModel: ['ZBT-RGBWLight-A0000'],
6
+ model: 'ZBT-RGBWLight-A0000',
7
+ vendor: 'LDS',
8
+ description: 'Ynoa smart LED E27',
9
+ extend: extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 555]}),
10
+ },
11
+ ];
package/devices/lixee.js CHANGED
@@ -443,19 +443,21 @@ function getCurrentConfig(device, options, logger=console) {
443
443
  .filter((e) => e.linkyMode == linkyMode && (e.linkyPhase == linkyPhase || e.linkyPhase == linkyPhaseDef.all) && (linkyProduction || !e.onlyProducer));
444
444
 
445
445
  // Filter even more, based on our current tarif
446
- let currentTarf;
446
+ let currentTarf = '';
447
447
 
448
- try {
449
- // Try to remove atributes which doesn't match current tarif
450
- currentTarf = endpoint.clusters.liXeePrivate.attributes.currentTarif.replace(/\0/g, '');
451
- } catch (error) {
452
- currentTarf = '';
453
- if (options && options.hasOwnProperty('tarif') && options['tarif'] != 'auto') {
454
- currentTarf = Object.entries(tarifsDef).find(( [k, v] ) => (v.fname == options['tarif']))[1].currentTarf;
448
+ if (options && options.hasOwnProperty('tarif') && options['tarif'] != 'auto') {
449
+ currentTarf = Object.entries(tarifsDef).find(( [k, v] ) => (v.fname == options['tarif']))[1].currentTarf;
450
+ } else {
451
+ try {
452
+ const lixAtts = endpoint.clusters[clustersDef._0xFF66].attributes;
453
+ lixAtts.raiseIfEmpty;
454
+ currentTarf = fzLocal.lixee_private_fz.convert({}, {data: lixAtts}).current_tarif;
455
+ } catch (error) {
456
+ logger.warn(`Not able to detect the current tarif. Not filtering any expose...`);
455
457
  }
456
458
  }
457
459
 
458
- // logger.debug(`zlinky config: ` + linkyMode + `, `+ linkyPhase + `, `+ linkyProduction.toString() +`, `+ currentTarf);
460
+ logger.debug(`zlinky config: ` + linkyMode + `, `+ linkyPhase + `, `+ linkyProduction.toString() +`, `+ currentTarf);
459
461
 
460
462
  switch (currentTarf) {
461
463
  case linkyMode == linkyModeDef.legacy && tarifsDef.histo_BASE.currentTarf:
@@ -481,7 +483,7 @@ function getCurrentConfig(device, options, logger=console) {
481
483
  return myExpose;
482
484
  }
483
485
  const definition = {
484
- zigbeeModel: ['ZLinky_TIC'],
486
+ zigbeeModel: ['ZLinky_TIC', 'ZLinky_TIC\u0000'],
485
487
  model: 'ZLinky_TIC',
486
488
  vendor: 'LiXee',
487
489
  description: 'Lixee ZLinky',
@@ -525,13 +527,15 @@ const definition = {
525
527
  clustersDef._0xFF66, /* liXeePrivate */
526
528
  ]);
527
529
 
530
+ await endpoint.read('liXeePrivate', ['linkyMode', 'currentTarif'], {manufacturerCode: null});
531
+
528
532
  const configReportings = [];
529
533
  const suscribeNew = getCurrentConfig(device, options, logger).filter((e) => e.reportable);
530
534
 
531
535
  const unsuscribe = endpoint.configuredReportings
532
536
  .filter((e) => !suscribeNew.some((r) => e.cluster.name == r.cluster && e.attribute.name == r.att));
533
537
  // Unsuscribe reports that doesn't correspond with the current config
534
- (await Promise.allSettled(unsuscribe.map((e) => endpoint.configureReporting(e.cluster.name, reporting.payload(e.attribute.name, e.minimumReportInterval, 65535, e.reportableChange)))))
538
+ (await Promise.allSettled(unsuscribe.map((e) => endpoint.configureReporting(e.cluster.name, reporting.payload(e.attribute.name, e.minimumReportInterval, 65535, e.reportableChange), {manufacturerCode: null}))))
535
539
  .filter((e) => e.status == 'rejected')
536
540
  .forEach((e) => {
537
541
  throw e.reason;
@@ -550,7 +554,8 @@ const definition = {
550
554
  }
551
555
  configReportings.push(endpoint
552
556
  .configureReporting(
553
- e.cluster, reporting.payload(params.att, params.min, params.max, params.change)),
557
+ e.cluster, reporting.payload(params.att, params.min, params.max, params.change),
558
+ {manufacturerCode: null}),
554
559
  );
555
560
  }
556
561
  (await Promise.allSettled(configReportings))
@@ -573,8 +578,7 @@ const definition = {
573
578
  .filter((e) => !endpoint.configuredReportings.some((r) => r.cluster.name == e.cluster && r.attribute.name == e.att));
574
579
  for (const e of currentExposes) {
575
580
  await endpoint
576
- .read(e.cluster, [e.att])
577
- .catch((err) => { }); // TODO: Ignore reads error?
581
+ .read(e.cluster, [e.att], {manufacturerCode: null});
578
582
  }
579
583
  }, seconds * 1000);
580
584
  globalStore.putValue(device, 'interval', interval);
@@ -45,7 +45,7 @@ module.exports = [
45
45
  },
46
46
  {
47
47
  zigbeeModel: ['ZBT-ExtendedColor'],
48
- model: '404000/404005/404012',
48
+ model: '404000/404005/404012/404019',
49
49
  vendor: 'Müller Licht',
50
50
  description: 'Tint LED bulb GU10/E14/E27 350/470/806 lumen, dimmable, color, opal white',
51
51
  extend: extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 556], supportsHS: true}),
package/devices/nous.js CHANGED
@@ -16,6 +16,31 @@ module.exports = [
16
16
  toZigbee: [],
17
17
  exposes: [e.temperature(), e.humidity(), e.battery()],
18
18
  },
19
+ {
20
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_lve3dvpy'}],
21
+ model: 'SZ-T04',
22
+ vendor: 'Nous',
23
+ description: 'Temperature and humidity sensor with clock',
24
+ fromZigbee: [fz.nous_lcd_temperature_humidity_sensor, fz.ignore_tuya_set_time],
25
+ toZigbee: [tz.nous_lcd_temperature_humidity_sensor],
26
+ onEvent: tuya.onEventSetLocalTime,
27
+ configure: async (device, coordinatorEndpoint, logger) => {
28
+ const endpoint = device.getEndpoint(1);
29
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genBasic']);
30
+ },
31
+ exposes: [
32
+ e.temperature(), e.humidity(), e.battery(),
33
+ exposes.enum('temperature_unit_convert', ea.STATE_SET, ['celsius', 'fahrenheit']).withDescription('Current display unit'),
34
+ exposes.enum('temperature_alarm', ea.STATE, ['canceled', 'lower_alarm', 'upper_alarm'])
35
+ .withDescription('Temperature alarm status'),
36
+ exposes.numeric('max_temperature', ea.STATE_SET).withUnit('°C').withValueMin(-20).withValueMax(60)
37
+ .withDescription('Alarm temperature max'),
38
+ exposes.numeric('min_temperature', ea.STATE_SET).withUnit('°C').withValueMin(-20).withValueMax(60)
39
+ .withDescription('Alarm temperature min'),
40
+ exposes.numeric('temperature_sensitivity', ea.STATE_SET).withUnit('°C').withValueMin(0.1).withValueMax(50).withValueStep(0.1)
41
+ .withDescription('Temperature sensitivity'),
42
+ ],
43
+ },
19
44
  {
20
45
  fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_nnrfa68v'}],
21
46
  model: 'E6',
@@ -2465,7 +2465,7 @@ module.exports = [
2465
2465
  ota: ota.zigbeeOTA,
2466
2466
  },
2467
2467
  {
2468
- zigbeeModel: ['5309230P6', '5309231P6'],
2468
+ zigbeeModel: ['5309230P6', '5309231P6', '929003045701_01', '929003045701_02'],
2469
2469
  model: '5309230P6',
2470
2470
  vendor: 'Philips',
2471
2471
  description: 'Hue White ambiance Runner double spotlight',
@@ -2706,6 +2706,14 @@ module.exports = [
2706
2706
  extend: hueExtend.light_onoff_brightness(),
2707
2707
  ota: ota.zigbeeOTA,
2708
2708
  },
2709
+ {
2710
+ zigbeeModel: ['915005997301'],
2711
+ model: '915005997301',
2712
+ vendor: 'Philips',
2713
+ description: 'Hue Bluetooth white & color ambiance ceiling lamp Infuse medium',
2714
+ extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
2715
+ ota: ota.zigbeeOTA,
2716
+ },
2709
2717
  {
2710
2718
  zigbeeModel: ['915005997501'],
2711
2719
  model: '915005997501',
@@ -0,0 +1,34 @@
1
+ const fz = require('../converters/fromZigbee');
2
+ const tz = require('../converters/toZigbee');
3
+ const exposes = require('../lib/exposes');
4
+ const reporting = require('../lib/reporting');
5
+ const e = exposes.presets;
6
+ const ea = exposes.access;
7
+
8
+ module.exports = [
9
+ {
10
+ fingerprint: [{manufId: 4368, endpoints: [{ID: 1, profileID: 260, deviceID: 513, inputClusters: [0, 3, 21],
11
+ outputClusters: [3, 4, 5, 6, 8, 256, 64544, 64545]}]}],
12
+ model: 'NB102',
13
+ vendor: 'Profalux',
14
+ description: 'Cover remote',
15
+ fromZigbee: [],
16
+ toZigbee: [],
17
+ exposes: [],
18
+ },
19
+ {
20
+ fingerprint: [{manufId: 4368, endpoints: [{ID: 1, profileID: 260, deviceID: 512,
21
+ inputClusters: [0, 3, 4, 5, 6, 8, 10, 21, 256, 64544, 64545], outputClusters: [3, 64544]}]}],
22
+ model: 'NSAV061',
23
+ vendor: 'Profalux',
24
+ description: 'Cover',
25
+ fromZigbee: [fz.cover_position_via_brightness, fz.cover_state_via_onoff],
26
+ toZigbee: [tz.cover_via_brightness],
27
+ exposes: [e.cover_position().setAccess('state', ea.ALL)],
28
+ configure: async (device, coordinatorEndpoint, logger) => {
29
+ const endpoint = device.getEndpoint(1);
30
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genLevelCtrl']);
31
+ await reporting.brightness(endpoint);
32
+ },
33
+ },
34
+ ];
package/devices/slv.js ADDED
@@ -0,0 +1,20 @@
1
+ const extend = require('../lib/extend');
2
+
3
+ module.exports = [
4
+ {
5
+ zigbeeModel: ['1001248', 'ZBT-ColorTemperature-Panel'],
6
+ model: '1001248',
7
+ vendor: 'SLV',
8
+ description: 'VALETO CCT LED driver',
9
+ extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 370]}),
10
+ },
11
+ {
12
+ zigbeeModel: ['1002994'],
13
+ model: '1002994',
14
+ vendor: 'SLV',
15
+ description: 'VALETO remote (binds to device)',
16
+ fromZigbee: [],
17
+ toZigbee: [],
18
+ exposes: [],
19
+ },
20
+ ];
package/devices/tuya.js CHANGED
@@ -98,6 +98,15 @@ module.exports = [
98
98
  toZigbee: [],
99
99
  exposes: [e.temperature(), e.humidity(), e.co2(), e.voc(), e.formaldehyd(), e.pm25()],
100
100
  },
101
+ {
102
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_7bztmfm1'}],
103
+ model: 'TS0601_smart_CO_air_box',
104
+ vendor: 'TuYa',
105
+ description: 'Smart air box (carbon monoxide)',
106
+ fromZigbee: [fz.tuya_CO],
107
+ toZigbee: [],
108
+ exposes: [e.carbon_monoxide(), e.co()],
109
+ },
101
110
  {
102
111
  fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_ggev5fsl'}],
103
112
  model: 'TS0601_gas_sensor',
@@ -331,6 +340,7 @@ module.exports = [
331
340
  {modelID: 'TS0601', manufacturerName: '_TZE200_dfxkcots'},
332
341
  {modelID: 'TS0601', manufacturerName: '_TZE200_ojzhk75b'},
333
342
  {modelID: 'TS0601', manufacturerName: '_TZE200_swaamsoy'},
343
+ {modelID: 'TS0601', manufacturerName: '_TZE200_3p5ydos3'},
334
344
  ],
335
345
  model: 'TS0601_dimmer',
336
346
  vendor: 'TuYa',
@@ -961,7 +971,8 @@ module.exports = [
961
971
  'to the desired temperature. If you want TRV to properly regulate the temperature you need to use mode `auto` ' +
962
972
  'instead setting the desired temperature.')
963
973
  .withLocalTemperatureCalibration(-9, 9, 1, ea.STATE_SET)
964
- .withAwayMode().withPreset(['schedule', 'manual', 'boost', 'complex', 'comfort', 'eco']),
974
+ .withAwayMode().withPreset(['schedule', 'manual', 'boost', 'complex', 'comfort', 'eco'])
975
+ .withRunningState(['idle', 'heat'], ea.STATE),
965
976
  e.auto_lock(), e.away_mode(), e.away_preset_days(), e.boost_time(), e.comfort_temperature(), e.eco_temperature(), e.force(),
966
977
  e.max_temperature(), e.min_temperature(), e.away_preset_temperature(),
967
978
  exposes.composite('programming_mode').withDescription('Schedule MODE ⏱ - In this mode, ' +
@@ -1158,6 +1169,7 @@ module.exports = [
1158
1169
  vendor: 'TuYa',
1159
1170
  whiteLabel: [{vendor: 'LELLKI', model: 'TS011F_plug'}, {vendor: 'NEO', model: 'NAS-WR01B'},
1160
1171
  {vendor: 'BlitzWolf', model: 'BW-SHP15'}],
1172
+ ota: ota.zigbeeOTA,
1161
1173
  fromZigbee: [fz.on_off, fz.electrical_measurement, fz.metering, fz.ignore_basic_report, fz.tuya_switch_power_outage_memory,
1162
1174
  fz.ts011f_plug_indicator_mode, fz.ts011f_plug_child_mode],
1163
1175
  toZigbee: [tz.on_off, tz.tuya_switch_power_outage_memory, tz.ts011f_plug_indicator_mode, tz.ts011f_plug_child_mode],
@@ -1207,6 +1219,7 @@ module.exports = [
1207
1219
  description: 'Smart plug (with power monitoring by polling)',
1208
1220
  vendor: 'TuYa',
1209
1221
  whiteLabel: [{vendor: 'VIKEFON', model: 'TS011F'}, {vendor: 'BlitzWolf', model: 'BW-SHP15'}],
1222
+ ota: ota.zigbeeOTA,
1210
1223
  fromZigbee: [fz.on_off, fz.electrical_measurement, fz.metering, fz.ignore_basic_report, fz.tuya_switch_power_outage_memory,
1211
1224
  fz.ts011f_plug_indicator_mode, fz.ts011f_plug_child_mode],
1212
1225
  toZigbee: [tz.on_off, tz.tuya_switch_power_outage_memory, tz.ts011f_plug_indicator_mode, tz.ts011f_plug_child_mode],
@@ -1892,7 +1905,7 @@ module.exports = [
1892
1905
  exposes.text('alarm', ea.STATE),
1893
1906
  exposes.binary('trip', ea.STATE_SET, 'trip', 'clear'),
1894
1907
  exposes.binary('child_lock', ea.STATE_SET, 'ON', 'OFF'),
1895
- exposes.enum('power_on_behaviour', ea.STATE_SET, ['off', 'on', 'previous']),
1908
+ exposes.enum('power_on_behavior', ea.STATE_SET, ['off', 'on', 'previous']),
1896
1909
  exposes.numeric('countdown_timer', ea.STATE_SET).withValueMin(0).withValueMax(86400).withUnit('s'),
1897
1910
  exposes.numeric('voltage', ea.STATE).withUnit('V'),
1898
1911
  exposes.numeric('voltage_rms', ea.STATE).withUnit('V'),
@@ -2003,4 +2016,13 @@ module.exports = [
2003
2016
  toZigbee: [],
2004
2017
  exposes: [e.illuminance_lux(), e.brightness_state()],
2005
2018
  },
2019
+ {
2020
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_kltffuzl'}, {modelID: 'TS0601', manufacturerName: '_TZE200_fwoorn8y'}],
2021
+ model: 'TM001-ZA/TM081',
2022
+ vendor: 'TuYa',
2023
+ description: 'Door and window sensor',
2024
+ fromZigbee: [fz.tm081],
2025
+ toZigbee: [],
2026
+ exposes: [e.contact(), e.battery()],
2027
+ },
2006
2028
  ];
package/devices/xiaomi.js CHANGED
@@ -54,9 +54,15 @@ module.exports = [
54
54
  model: 'MCCGQ13LM',
55
55
  vendor: 'Xiaomi',
56
56
  description: 'Aqara P1 door & window contact sensor',
57
- fromZigbee: [fz.ias_contact_alarm_1, fz.aqara_opple],
57
+ fromZigbee: [fz. xiaomi_contact, fz.ias_contact_alarm_1, fz.aqara_opple, fz.battery],
58
58
  toZigbee: [],
59
+ meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
59
60
  exposes: [e.contact(), e.battery(), e.battery_voltage()],
61
+ configure: async (device, coordinatorEndpoint, logger) => {
62
+ const endpoint = device.getEndpoint(1);
63
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
64
+ await reporting.batteryVoltage(endpoint);
65
+ },
60
66
  },
61
67
  {
62
68
  zigbeeModel: ['lumi.dimmer.rcbac1'],
@@ -1472,7 +1478,8 @@ module.exports = [
1472
1478
  // Ignore energy metering reports, rely on aqara_opple: https://github.com/Koenkk/zigbee2mqtt/issues/10709
1473
1479
  fromZigbee: [fz.on_off, fz.device_temperature, fz.aqara_opple, fz.ignore_metering, fz.ignore_electrical_measurement,
1474
1480
  fz.xiaomi_power],
1475
- exposes: [e.switch(), e.energy(), e.power(), e.device_temperature(), e.power_outage_memory(), e.switch_type()],
1481
+ exposes: [e.switch(), e.energy(), e.power(), e.device_temperature(), e.power_outage_memory(), e.switch_type(),
1482
+ e.voltage(), e.temperature(), e.current()],
1476
1483
  toZigbee: [tz.xiaomi_switch_type, tz.on_off, tz.xiaomi_switch_power_outage_memory, tz.xiaomi_led_disabled_night],
1477
1484
  configure: async (device, coordinatorEndpoint, logger) => {
1478
1485
  const endpoint = device.getEndpoint(1);
package/lib/exposes.js CHANGED
@@ -519,6 +519,7 @@ module.exports = {
519
519
  carbon_monoxide: () => new Binary('carbon_monoxide', access.STATE, true, false).withDescription('Indicates if CO (carbon monoxide) is detected'),
520
520
  child_lock: () => new Lock().withState('child_lock', 'LOCK', 'UNLOCK', 'Enables/disables physical input on the device', access.STATE_SET),
521
521
  co2: () => new Numeric('co2', access.STATE).withUnit('ppm').withDescription('The measured CO2 (carbon dioxide) value'),
522
+ co: () => new Numeric('co', access.STATE).withUnit('ppm').withDescription('The measured CO (carbon monoxide) value'),
522
523
  comfort_temperature: () => new Numeric('comfort_temperature', access.STATE_SET).withUnit('°C').withDescription('Comfort temperature').withValueMin(0).withValueMax(30),
523
524
  consumer_connected: () => new Binary('consumer_connected', access.STATE, true, false).withDescription('Indicates whether a plug is physically attached. Device does not have to pull power or even be connected electrically (state of this binary switch can be ON even if main power switch is OFF)'),
524
525
  contact: () => new Binary('contact', access.STATE, false, true).withDescription('Indicates if the contact is closed (= true) or open (= false)'),
package/lib/tuya.js CHANGED
@@ -421,6 +421,9 @@ const dataPoints = {
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
423
  tuyaSahkMP25: 20,
424
+ // Tuya CO (carbon monoxide) smart air box
425
+ tuyaSabCOalarm: 1,
426
+ tuyaSabCO: 2,
424
427
  lidlTimer: 5,
425
428
  // Moes MS-105 Dimmer
426
429
  moes105DimmerState1: 1,