zigbee-herdsman-converters 14.0.625 → 14.0.627

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.
@@ -3484,8 +3484,6 @@ const converters = {
3484
3484
  if (value == 'ON') {
3485
3485
  await tuya.sendDataPointBool(entity, tuya.dataPoints.tvHeatingStop, 1);
3486
3486
  } else {
3487
- await tuya.sendDataPointBool(entity, tuya.dataPoints.tvHeatingStop, 0);
3488
- await utils.sleep(500);
3489
3487
  await tuya.sendDataPointEnum(entity, tuya.dataPoints.tvMode, 1 /* manual */);
3490
3488
  }
3491
3489
  break;
@@ -3493,8 +3491,6 @@ const converters = {
3493
3491
  if (value == 'ON') {
3494
3492
  await tuya.sendDataPointBool(entity, tuya.dataPoints.tvFrostDetection, 1);
3495
3493
  } else {
3496
- await tuya.sendDataPointBool(entity, tuya.dataPoints.tvFrostDetection, 0);
3497
- await utils.sleep(500);
3498
3494
  await tuya.sendDataPointEnum(entity, tuya.dataPoints.tvMode, 1 /* manual */);
3499
3495
  }
3500
3496
  break;
package/devices/acova.js CHANGED
@@ -5,7 +5,7 @@ const reporting = require('../lib/reporting');
5
5
 
6
6
  module.exports = [
7
7
  {
8
- zigbeeModel: ['PERCALE2 D1.00P1.01Z1.00'],
8
+ zigbeeModel: ['PERCALE2 D1.00P1.01Z1.00', 'PERCALE2 D1.00P1.02Z1.00'],
9
9
  model: 'PERCALE2',
10
10
  vendor: 'Acova',
11
11
  description: 'Percale 2 heater',
@@ -3,13 +3,29 @@ const fz = {...require('../converters/fromZigbee'), legacy: require('../lib/lega
3
3
  const tz = require('../converters/toZigbee');
4
4
  const extend = require('../lib/extend');
5
5
  const ea = exposes.access;
6
+ const e = exposes.presets;
7
+
8
+ const fzLocal = {
9
+ DTB2011014: {
10
+ cluster: 'genOnOff',
11
+ type: ['attributeReport', 'readResponse'],
12
+ convert: (model, msg, publish, options, meta) => {
13
+ return {
14
+ key_1: msg.data['41361'] === 1 ? 'ON' : 'OFF',
15
+ key_2: msg.data['41362'] === 1 ? 'ON' : 'OFF',
16
+ key_3: msg.data['41363'] === 1 ? 'ON' : 'OFF',
17
+ key_4: msg.data['41364'] === 1 ? 'ON' : 'OFF',
18
+ };
19
+ },
20
+ },
21
+ };
6
22
 
7
23
  module.exports = [
8
24
  {
9
25
  zigbeeModel: ['DTB190502A1'],
10
26
  model: 'DTB190502A1',
11
27
  vendor: 'databyte.ch',
12
- description: '[CC2530 based IO Board](https://databyte.ch/zigbee-dev-board-dtb190502a)',
28
+ description: 'CC2530 based IO Board',
13
29
  fromZigbee: [fz.DTB190502A1],
14
30
  toZigbee: [tz.DTB190502A1_LED],
15
31
  exposes: [exposes.binary('led_state', ea.STATE, 'ON', 'OFF'),
@@ -19,7 +35,21 @@ module.exports = [
19
35
  zigbeeModel: ['DTB-ED2004-012'],
20
36
  model: 'ED2004-012',
21
37
  vendor: 'databyte.ch',
22
- description: 'Panda 1 - wall switch (https://databyte.ch/panda1-wallswitch-zigbee)',
38
+ description: 'Panda 1 - wall switch',
23
39
  extend: extend.switch(),
24
40
  },
41
+ {
42
+ zigbeeModel: ['DTB-ED2011-014'],
43
+ model: 'Touch4',
44
+ vendor: 'databyte.ch',
45
+ description: 'Wall touchsensor with 4 keys',
46
+ fromZigbee: [fzLocal.DTB2011014, fz.battery],
47
+ toZigbee: [],
48
+ exposes: [e.battery(), e.linkquality(),
49
+ exposes.binary('key_1', ea.STATE, 'ON', 'OFF'),
50
+ exposes.binary('key_2', ea.STATE, 'ON', 'OFF'),
51
+ exposes.binary('key_3', ea.STATE, 'ON', 'OFF'),
52
+ exposes.binary('key_4', ea.STATE, 'ON', 'OFF'),
53
+ ],
54
+ },
25
55
  ];
@@ -9,9 +9,9 @@ const e = exposes.presets;
9
9
  const ea = exposes.access;
10
10
 
11
11
  const fzLocal = {
12
- // SPLZB-134 reports strange values sometimes
12
+ // SPLZB-134 and SPLZB-131 reports strange values sometimes
13
13
  // https://github.com/Koenkk/zigbee2mqtt/issues/13329
14
- SPLZB134_electrical_measurement: {
14
+ develco_electrical_measurement: {
15
15
  ...fz.electrical_measurement,
16
16
  convert: (model, msg, publish, options, meta) => {
17
17
  if (msg.data.rmsVoltage !== 0xFFFF && msg.data.rmsCurrent !== 0xFFFF && msg.data.activePower !== -0x8000) {
@@ -19,7 +19,7 @@ const fzLocal = {
19
19
  }
20
20
  },
21
21
  },
22
- SPLZB134_device_temperature: {
22
+ develco_device_temperature: {
23
23
  ...fz.device_temperature,
24
24
  convert: (model, msg, publish, options, meta) => {
25
25
  if (msg.data.currentTemperature !== -0x8000) {
@@ -27,7 +27,7 @@ const fzLocal = {
27
27
  }
28
28
  },
29
29
  },
30
- SPLZB134_metering: {
30
+ develco_metering: {
31
31
  ...fz.metering,
32
32
  convert: (model, msg, publish, options, meta) => {
33
33
  if (msg.data.instantaneousDemand !== -0x800000) {
@@ -43,7 +43,7 @@ module.exports = [
43
43
  model: 'SPLZB-131',
44
44
  vendor: 'Develco',
45
45
  description: 'Power plug',
46
- fromZigbee: [fz.on_off, fz.electrical_measurement, fz.metering],
46
+ fromZigbee: [fz.on_off, fzLocal.develco_electrical_measurement, fzLocal.develco_metering],
47
47
  toZigbee: [tz.on_off],
48
48
  exposes: [e.switch(), e.power(), e.current(), e.voltage(), e.energy()],
49
49
  configure: async (device, coordinatorEndpoint, logger) => {
@@ -94,7 +94,7 @@ module.exports = [
94
94
  model: 'SPLZB-134',
95
95
  vendor: 'Develco',
96
96
  description: 'Power plug (type G)',
97
- fromZigbee: [fz.on_off, fzLocal.SPLZB134_electrical_measurement, fzLocal.SPLZB134_metering, fzLocal.SPLZB134_device_temperature],
97
+ fromZigbee: [fz.on_off, fzLocal.develco_electrical_measurement, fzLocal.develco_metering, fzLocal.develco_device_temperature],
98
98
  toZigbee: [tz.on_off],
99
99
  exposes: [e.switch(), e.power(), e.current(), e.voltage(), e.energy(), e.device_temperature()],
100
100
  configure: async (device, coordinatorEndpoint, logger) => {
@@ -144,7 +144,7 @@ module.exports = [
144
144
  model: 'EMIZB-132',
145
145
  vendor: 'Develco',
146
146
  description: 'Wattle AMS HAN power-meter sensor',
147
- fromZigbee: [fzLocal.SPLZB134_metering, fzLocal.SPLZB134_electrical_measurement, fz.develco_fw],
147
+ fromZigbee: [fzLocal.develco_metering, fzLocal.develco_electrical_measurement, fz.develco_fw],
148
148
  toZigbee: [tz.EMIZB_132_mode],
149
149
  ota: ota.zigbeeOTA,
150
150
  configure: async (device, coordinatorEndpoint, logger) => {
package/devices/ikea.js CHANGED
@@ -6,6 +6,7 @@ const constants = require('../lib/constants');
6
6
  const reporting = require('../lib/reporting');
7
7
  const {repInterval} = require('../lib/constants');
8
8
  const utils = require('../lib/utils');
9
+ const libColor = require('../lib/color');
9
10
  const extend = require('../lib/extend');
10
11
  const globalStore = require('../lib/store');
11
12
  const e = exposes.presets;
@@ -60,6 +61,30 @@ const configureRemote = async (device, coordinatorEndpoint, logger) => {
60
61
  await reporting.batteryPercentageRemaining(endpoint);
61
62
  };
62
63
 
64
+ const tzLocal = {
65
+ LED1624G9_color_colortemp: {
66
+ ...tz.light_color_colortemp,
67
+ convertSet: async (entity, key, value, meta) => {
68
+ if (key == 'color') {
69
+ const result = await tz.light_color.convertSet(entity, key, value, meta);
70
+ return result;
71
+ } else if (key == 'color_temp' || key == 'color_temp_percent') {
72
+ const xy = libColor.ColorXY.fromMireds(value);
73
+ const payload = {
74
+ transtime: utils.getTransition(entity, key, meta).time,
75
+ colorx: utils.mapNumberRange(xy.x, 0, 1, 0, 65535),
76
+ colory: utils.mapNumberRange(xy.y, 0, 1, 0, 65535),
77
+ };
78
+ await entity.command('lightingColorCtrl', 'moveToColor', payload, utils.getOptions(meta.mapped, entity));
79
+ return {
80
+ state: libColor.syncColorState({'color_mode': constants.colorMode[2], 'color_temp': value}, meta.state,
81
+ entity, meta.options, meta.logger), readAfterWriteTime: payload.transtime * 100,
82
+ };
83
+ }
84
+ },
85
+ },
86
+ };
87
+
63
88
  const fzLocal = {
64
89
  // The STYRBAR sends an on +- 500ms after the arrow release. We don't want to send the ON action in this case.
65
90
  // https://github.com/Koenkk/zigbee2mqtt/issues/13335
@@ -453,7 +478,12 @@ module.exports = [
453
478
  model: 'LED1624G9',
454
479
  vendor: 'IKEA',
455
480
  description: 'TRADFRI LED bulb E14/E26/E27 600 lumen, dimmable, color, opal white',
456
- extend: tradfriExtend.light_onoff_brightness_color(),
481
+ extend: tradfriExtend.light_onoff_brightness_colortemp_color(),
482
+ toZigbee: utils.replaceInArray(
483
+ tradfriExtend.light_onoff_brightness_colortemp_color().toZigbee,
484
+ [tz.light_color_colortemp],
485
+ [tzLocal.LED1624G9_color_colortemp],
486
+ ),
457
487
  meta: {supportsHueAndSaturation: false},
458
488
  },
459
489
  {
@@ -223,5 +223,30 @@ module.exports = [
223
223
  extend: extend.ledvance.light_onoff_brightness(),
224
224
  ota: ota.ledvance,
225
225
  },
226
-
226
+ {
227
+ zigbeeModel: ['PLUG COMPACT EU T'],
228
+ model: '4058075729322',
229
+ vendor: 'LEDVANCE',
230
+ description: 'SMART+ Compact Outdoor Plug EU',
231
+ extend: extend.switch(),
232
+ ota: ota.ledvance,
233
+ configure: async (device, coordinatorEndpoint, logger) => {
234
+ const endpoint = device.getEndpoint(1);
235
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
236
+ await reporting.onOff(endpoint);
237
+ },
238
+ },
239
+ {
240
+ zigbeeModel: ['PLUG OUTDOOR EU T'],
241
+ model: '4058075729308',
242
+ vendor: 'LEDVANCE',
243
+ description: 'SMART+ Outdoor Plug EU',
244
+ extend: extend.switch(),
245
+ ota: ota.ledvance,
246
+ configure: async (device, coordinatorEndpoint, logger) => {
247
+ const endpoint = device.getEndpoint(1);
248
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
249
+ await reporting.onOff(endpoint);
250
+ },
251
+ },
227
252
  ];
@@ -38,13 +38,15 @@ module.exports = [
38
38
  model: 'MCLH-03',
39
39
  vendor: 'LifeControl',
40
40
  description: 'Power plug',
41
- fromZigbee: [fz.on_off, fz.electrical_measurement],
41
+ fromZigbee: [fz.on_off, fz.electrical_measurement, fz.metering],
42
42
  toZigbee: [tz.on_off],
43
43
  configure: async (device, coordinatorEndpoint, logger) => {
44
44
  const endpoint = device.getEndpoint(1);
45
- await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement']);
45
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement', 'seMetering']);
46
46
  await reporting.onOff(endpoint);
47
47
  await reporting.readEletricalMeasurementMultiplierDivisors(endpoint);
48
+ await reporting.readMeteringMultiplierDivisor(endpoint);
49
+ await reporting.currentSummDelivered(endpoint);
48
50
  },
49
51
  onEvent: async (type, data, device) => {
50
52
  // This device doesn't support reporting correctly.
@@ -57,6 +59,7 @@ module.exports = [
57
59
  const interval = setInterval(async () => {
58
60
  try {
59
61
  await endpoint.read('haElectricalMeasurement', ['rmsVoltage', 'rmsCurrent', 'activePower']);
62
+ await endpoint.read('seMetering', ['currentSummDelivered', 'multiplier', 'divisor']);
60
63
  } catch (error) {
61
64
  // Do nothing
62
65
  }
@@ -64,7 +67,7 @@ module.exports = [
64
67
  globalStore.putValue(device, 'interval', interval);
65
68
  }
66
69
  },
67
- exposes: [e.switch(), e.power(), e.current(), e.voltage()],
70
+ exposes: [e.switch(), e.power(), e.current(), e.voltage(), e.energy()],
68
71
  },
69
72
  {
70
73
  zigbeeModel: ['Motion_Sensor'],
@@ -145,15 +145,22 @@ module.exports = [
145
145
  model: 'QS-Zigbee-D02-TRIAC-LN',
146
146
  vendor: 'Lonsonho',
147
147
  description: '1 gang smart dimmer switch module with neutral',
148
- extend: extend.light_onoff_brightness(),
148
+ fromZigbee: extend.light_onoff_brightness().fromZigbee.concat([fz.tuya_min_brightness]),
149
+ toZigbee: extend.light_onoff_brightness().toZigbee.concat([tz.tuya_min_brightness]),
150
+ exposes: [e.light_brightness().withMinBrightness()],
149
151
  },
150
152
  {
151
153
  fingerprint: [{modelID: 'TS110F', manufacturerName: '_TYZB01_v8gtiaed'}, {modelID: 'TS110E', manufacturerName: '_TZ3210_pagajpog'}],
152
154
  model: 'QS-Zigbee-D02-TRIAC-2C-LN',
153
155
  vendor: 'Lonsonho',
154
156
  description: '2 gang smart dimmer switch module with neutral',
155
- extend: extend.light_onoff_brightness({noConfigure: true}),
156
- exposes: [e.light_brightness().withEndpoint('l1'), e.light_brightness().withEndpoint('l2')],
157
+ fromZigbee: extend.light_onoff_brightness().fromZigbee.concat([fz.tuya_min_brightness]),
158
+ toZigbee: extend.light_onoff_brightness().toZigbee.concat([tz.tuya_min_brightness]),
159
+ exposes: [e.light_brightness().withMinBrightness().withEndpoint('l1'),
160
+ e.light_brightness().withMinBrightness().withEndpoint('l2')],
161
+ endpoint: (device) => {
162
+ return {'l1': 1, 'l2': 2};
163
+ },
157
164
  meta: {multiEndpoint: true},
158
165
  configure: async (device, coordinatorEndpoint, logger) => {
159
166
  await extend.light_onoff_brightness().configure(device, coordinatorEndpoint, logger);
@@ -161,9 +168,6 @@ module.exports = [
161
168
  await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
162
169
  // Don't do: await reporting.onOff(endpoint); https://github.com/Koenkk/zigbee2mqtt/issues/6041
163
170
  },
164
- endpoint: (device) => {
165
- return {l1: 1, l2: 2};
166
- },
167
171
  },
168
172
  {
169
173
  fingerprint: [{modelID: 'TS110F', manufacturerName: '_TZ3000_92chsky7'}, {modelID: 'TS110E', manufacturerName: '_TZ3210_4ubylghk'}],
@@ -2580,6 +2580,13 @@ module.exports = [
2580
2580
  description: 'Hue White & Color Ambiance Xamento M',
2581
2581
  extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
2582
2582
  },
2583
+ {
2584
+ zigbeeModel: ['915005997901'],
2585
+ model: '915005997901',
2586
+ vendor: 'Philips',
2587
+ description: 'Hue White & Color Ambiance Xamento L',
2588
+ extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
2589
+ },
2583
2590
  {
2584
2591
  zigbeeModel: ['929002966401'],
2585
2592
  model: '929002966401',
@@ -2756,10 +2763,17 @@ module.exports = [
2756
2763
  extend: hueExtend.light_onoff_brightness(),
2757
2764
  },
2758
2765
  {
2759
- zigbeeModel: ['3402931P7'],
2760
- model: '3402931P7',
2766
+ zigbeeModel: ['3402931P7', '3418231P6'],
2767
+ model: '8718696175798',
2761
2768
  vendor: 'Philips',
2762
2769
  description: 'Philips Hue Adore Bathroom Mirror Light',
2763
2770
  extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
2764
2771
  },
2772
+ {
2773
+ zigbeeModel: ['929003045901'],
2774
+ model: '929003045901',
2775
+ vendor: 'Philips',
2776
+ description: 'Hue White ambiance Runner spot white (1 spot)',
2777
+ extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
2778
+ },
2765
2779
  ];
package/devices/robb.js CHANGED
@@ -105,12 +105,22 @@ module.exports = [
105
105
  model: 'ROB_200-014-0',
106
106
  vendor: 'ROBB',
107
107
  description: 'ZigBee AC phase-cut rotary dimmer',
108
- extend: extend.light_onoff_brightness({noConfigure: true}),
108
+ fromZigbee: extend.light_onoff_brightness().fromZigbee.concat([fz.electrical_measurement, fz.metering, fz.ignore_genOta]),
109
+ toZigbee: extend.light_onoff_brightness().toZigbee,
110
+ exposes: [e.light_brightness(), e.power(), e.voltage(), e.current(), e.energy()],
111
+ whiteLabel: [{vendor: 'YPHIX', model: '50208695'}, {vendor: 'Samotech', model: 'SM311'}],
109
112
  configure: async (device, coordinatorEndpoint, logger) => {
110
- await extend.light_onoff_brightness().configure(device, coordinatorEndpoint, logger);
111
113
  const endpoint = device.getEndpoint(1);
112
- await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
114
+ const binds = ['genOnOff', 'genLevelCtrl', 'haElectricalMeasurement', 'seMetering'];
115
+ await reporting.bind(endpoint, coordinatorEndpoint, binds);
113
116
  await reporting.onOff(endpoint);
117
+ await reporting.brightness(endpoint);
118
+ await reporting.readEletricalMeasurementMultiplierDivisors(endpoint);
119
+ await reporting.activePower(endpoint);
120
+ await reporting.rmsCurrent(endpoint, {min: 10, change: 10});
121
+ await reporting.rmsVoltage(endpoint, {min: 10});
122
+ await reporting.readMeteringMultiplierDivisor(endpoint);
123
+ await reporting.currentSummDelivered(endpoint);
114
124
  },
115
125
  },
116
126
  {
@@ -1,4 +1,5 @@
1
1
  const exposes = require('../lib/exposes');
2
+ const utils = require('../lib/utils');
2
3
  const fz = {...require('../converters/fromZigbee'), legacy: require('../lib/legacy').fromZigbee};
3
4
  const tz = require('../converters/toZigbee');
4
5
  const reporting = require('../lib/reporting');
@@ -16,10 +17,12 @@ const fzLocal = {
16
17
  convert: (model, msg, publish, options, meta) => {
17
18
  const occupancyIn = msg.data.occupancy;
18
19
  globalStore.putValue(msg.endpoint, 'occupancy_in', occupancyIn);
19
- const occupancy = occupancyIn | globalStore.getValue(msg.endpoint, 'occupancy_out', 0);
20
+ const occupancyOr = occupancyIn | globalStore.getValue(msg.endpoint, 'occupancy_out', 0);
21
+ const occupancyAnd = occupancyIn & globalStore.getValue(msg.endpoint, 'occupancy_out', 0);
20
22
  return {
21
23
  occupancy_in: (occupancyIn & 1) > 0,
22
- occupancy: (occupancy & 1) > 0,
24
+ occupancy_or: (occupancyOr & 1) > 0,
25
+ occupancy_and: (occupancyAnd & 1) > 0,
23
26
  };
24
27
  },
25
28
  },
@@ -29,15 +32,137 @@ const fzLocal = {
29
32
  convert: (model, msg, publish, options, meta) => {
30
33
  const occupancyOut = msg.data.zonestatus;
31
34
  globalStore.putValue(msg.endpoint, 'occupancy_out', occupancyOut);
32
- const occupancy = occupancyOut | globalStore.getValue(msg.endpoint, 'occupancy_in', 0);
35
+ const occupancyOr = occupancyOut | globalStore.getValue(msg.endpoint, 'occupancy_in', 0);
36
+ const occupancyAnd = occupancyOut & globalStore.getValue(msg.endpoint, 'occupancy_in', 0);
33
37
  return {
34
38
  occupancy_out: (occupancyOut & 1) > 0,
35
- occupancy: (occupancy & 1) > 0,
39
+ occupancy_or: (occupancyOr & 1) > 0,
40
+ occupancy_and: (occupancyAnd & 1) > 0,
36
41
  };
37
42
  },
38
43
  },
44
+ ISM300Z3_on_off: {
45
+ cluster: 'genOnOff',
46
+ type: ['attributeReport', 'readResponse'],
47
+ convert: (model, msg, publish, options, meta) => {
48
+ if (msg.data.hasOwnProperty('onOff')) {
49
+ const property = utils.postfixWithEndpointName('state', msg, model, meta);
50
+ return {[property]: msg.data['onOff'] === 1 ? 'ON' : 'OFF'};
51
+ } else if (msg.data.hasOwnProperty(0x9000)) {
52
+ const value = msg.data[0x9000];
53
+ const lookup = {0: 'auto', 1: 'push', 2: 'latch'};
54
+ return {operation_mode: lookup[value]};
55
+ }
56
+ },
57
+ },
39
58
  };
40
59
 
60
+ const tzLocal = {
61
+ CSM300_SETUP: {
62
+ key: ['rf_pairing_on', 'counting_freeze', 'tof_init', 'led_state', 'rf_state', 'transation', 'fast_in', 'fast_out'],
63
+ convertSet: async (entity, key, value, meta) => {
64
+ let payload = null;
65
+ const endpoint = meta.device.endpoints.find((e) => e.supportsInputCluster('genAnalogInput'));
66
+ switch (key) {
67
+ case 'rf_pairing_on':
68
+ payload = {'presentValue': 81};
69
+ break;
70
+ case 'counting_freeze':
71
+ if (value.toLowerCase() === 'on') {
72
+ payload = {'presentValue': 82};
73
+ } else if (value.toLowerCase() === 'off') {
74
+ payload = {'presentValue': 84};
75
+ }
76
+ break;
77
+ case 'tof_init':
78
+ payload = {'presentValue': 83};
79
+ break;
80
+ case 'led_state':
81
+ if (value === 'enable') {
82
+ payload = {'presentValue': 86};
83
+ } else if (value === 'disable') {
84
+ payload = {'presentValue': 87};
85
+ }
86
+ break;
87
+ case 'rf_state':
88
+ if (value === 'enable') {
89
+ payload = {'presentValue': 88};
90
+ } else if (value === 'disable') {
91
+ payload = {'presentValue': 89};
92
+ }
93
+ break;
94
+ case 'transation':
95
+ if (value === '0ms') {
96
+ payload = {'presentValue': 90};
97
+ } else if (value === '200ms') {
98
+ payload = {'presentValue': 91};
99
+ } else if (value === '400ms') {
100
+ payload = {'presentValue': 92};
101
+ } else if (value === '600ms') {
102
+ payload = {'presentValue': 93};
103
+ } else if (value === '800ms') {
104
+ payload = {'presentValue': 94};
105
+ } else if (value === '1,000ms') {
106
+ payload = {'presentValue': 95};
107
+ }
108
+ break;
109
+ case 'fast_in':
110
+ if (value === 'enable') {
111
+ payload = {'presentValue': 96};
112
+ } else if (value === 'disable') {
113
+ payload = {'presentValue': 97};
114
+ }
115
+ break;
116
+ case 'fast_out':
117
+ if (value === 'enable') {
118
+ payload = {'presentValue': 98};
119
+ } else if (value === 'disable') {
120
+ payload = {'presentValue': 99};
121
+ }
122
+ break;
123
+ }
124
+ await endpoint.write('genAnalogInput', payload);
125
+ },
126
+ },
127
+ ISM300Z3_on_off: {
128
+ key: ['state', 'operation_mode'],
129
+ convertSet: async (entity, key, value, meta) => {
130
+ const endpoint = meta.device.getEndpoint(1);
131
+ if (key === 'state') {
132
+ const state = meta.message.hasOwnProperty('state') ? meta.message.state.toLowerCase() : null;
133
+ utils.validateValue(state, ['toggle', 'off', 'on']);
134
+ await entity.command('genOnOff', state, {}, utils.getOptions(meta.mapped, entity));
135
+ if (state === 'toggle') {
136
+ const currentState = meta.state[`state${meta.endpoint_name ? `_${meta.endpoint_name}` : ''}`];
137
+ return currentState ? {state: {state: currentState === 'OFF' ? 'ON' : 'OFF'}} : {};
138
+ } else {
139
+ return {state: {state: state.toUpperCase()}};
140
+ }
141
+ } else if (key === 'operation_mode') {
142
+ const lookup = {'auto': 0, 'push': 1, 'latch': 2};
143
+ const payload = {0x9000: {value: lookup[value], type: 0x20}}; // INT8U
144
+ await entity.write('genOnOff', payload);
145
+ await endpoint.read('genOnOff', [0x9000]);
146
+ }
147
+ },
148
+ convertGet: async (entity, key, meta) => {
149
+ if (key === 'operation_mode') {
150
+ const endpoint = meta.device.getEndpoint(1);
151
+ await endpoint.read('genOnOff', [0x9000]);
152
+ } else {
153
+ await entity.read('genOnOff', ['onOff']);
154
+ }
155
+ },
156
+ },
157
+ ISM300Z3_rf_pairing: {
158
+ key: ['rf_pairing'],
159
+ convertSet: async (entity, key, value, meta) => {
160
+ const lookup = {'l1': 1, 'l2': 2, 'l3': 3};
161
+ const payload = {0x9001: {value: lookup[value], type: 0x20}}; // INT8U
162
+ await entity.write('genOnOff', payload);
163
+ },
164
+ },
165
+ };
41
166
 
42
167
  module.exports = [
43
168
  {
@@ -73,7 +198,7 @@ module.exports = [
73
198
  description: 'SiHAS multipurpose ToF sensor',
74
199
  meta: {battery: {voltageToPercentage: 'Add_1V_42V_CSM300z2v2'}},
75
200
  fromZigbee: [fz.battery, fz.sihas_people_cnt],
76
- toZigbee: [tz.sihas_set_people],
201
+ toZigbee: [tz.sihas_set_people, tzLocal.CSM300_SETUP],
77
202
  configure: async (device, coordinatorEndpoint, logger) => {
78
203
  const endpoint = device.getEndpoint(1);
79
204
  const binds = ['genPowerCfg', 'genAnalogInput'];
@@ -84,7 +209,19 @@ module.exports = [
84
209
  },
85
210
  exposes: [e.battery(), e.battery_voltage(),
86
211
  exposes.enum('status', ea.STATE, ['idle', 'in', 'out']).withDescription('Currently status'),
87
- exposes.numeric('people', ea.ALL).withValueMin(0).withValueMax(100).withDescription('People count')],
212
+ exposes.numeric('people', ea.ALL).withValueMin(0).withValueMax(100).withDescription('People count'),
213
+ exposes.enum('rf_pairing_on', ea.SET, ['run']).withDescription('Run RF pairing mode'),
214
+ exposes.binary('counting_freeze', ea.SET, 'ON', 'OFF')
215
+ .withDescription('Counting Freeze ON/OFF, not reporting people value when is ON'),
216
+ exposes.enum('tof_init', ea.SET, ['initial']).withDescription('ToF sensor initial'),
217
+ exposes.binary('led_state', ea.SET, 'enable', 'disable').withDescription('Indicate LED enable/disable, default : enable'),
218
+ exposes.binary('rf_state', ea.SET, 'enable', 'disable').withDescription('RF function enable/disable, default : disable'),
219
+ exposes.enum('transation', ea.SET, ['0ms', '200ms', '400ms', '600ms', '800ms', '1,000ms'])
220
+ .withDescription('Transation interval, default : 400ms'),
221
+ exposes.binary('fast_in', ea.SET, 'enable', 'disable')
222
+ .withDescription('Fast process enable/disable when people 0 to 1. default : enable'),
223
+ exposes.binary('fast_out', ea.SET, 'enable', 'disable')
224
+ .withDescription('Fast process enable/disable when people 1 to 0. default : enable')],
88
225
  },
89
226
  {
90
227
  zigbeeModel: ['USM-300Z'],
@@ -447,8 +584,10 @@ module.exports = [
447
584
  .withDescription('Indicates whether "IN" Sensor of the device detected occupancy'),
448
585
  exposes.binary('occupancy_out', ea.STATE, true, false)
449
586
  .withDescription('Indicates whether "OUT" Sensor of the device detected occupancy'),
450
- exposes.binary('occupancy', ea.STATE, true, false)
587
+ exposes.binary('occupancy_or', ea.STATE, true, false)
451
588
  .withDescription('Indicates whether "IN or OUT" Sensor of the device detected occupancy'),
589
+ exposes.binary('occupancy_and', ea.STATE, true, false)
590
+ .withDescription('Indicates whether "IN and OUT" Sensor of the device detected occupancy'),
452
591
  exposes.numeric('occupancy_timeout', ea.ALL).withUnit('second').withValueMin(0).withValueMax(3600)],
453
592
  },
454
593
  {
@@ -457,13 +596,19 @@ module.exports = [
457
596
  vendor: 'ShinaSystem',
458
597
  ota: ota.zigbeeOTA,
459
598
  description: 'SiHAS IOT smart inner switch 3 gang',
460
- extend: extend.switch(),
461
- exposes: [e.switch().withEndpoint('l1'), e.switch().withEndpoint('l2'), e.switch().withEndpoint('l3')],
599
+ fromZigbee: [fzLocal.ISM300Z3_on_off],
600
+ toZigbee: [tzLocal.ISM300Z3_on_off, tzLocal.ISM300Z3_rf_pairing],
601
+ exposes: [e.switch().withEndpoint('l1'), e.switch().withEndpoint('l2'), e.switch().withEndpoint('l3'),
602
+ exposes.enum('operation_mode', ea.ALL, ['auto', 'push', 'latch'])
603
+ .withDescription('Operation mode: "auto" - toggle by S/W, "push" - for momentary S/W, "latch" - sync S/W'),
604
+ exposes.enum('rf_pairing', ea.SET, ['l1', 'l2', 'l3'])
605
+ .withDescription('Enable RF pairing mode each button l1, l2, l3')],
462
606
  endpoint: (device) => {
463
607
  return {l1: 1, l2: 2, l3: 3};
464
608
  },
465
609
  meta: {multiEndpoint: true},
466
610
  configure: async (device, coordinatorEndpoint, logger) => {
611
+ await device.getEndpoint(1).read('genOnOff', [0x9000]);
467
612
  await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
468
613
  await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
469
614
  await reporting.bind(device.getEndpoint(3), coordinatorEndpoint, ['genOnOff']);
package/devices/tuya.js CHANGED
@@ -21,7 +21,7 @@ const TS011Fplugs = ['_TZ3000_5f43h46b', '_TZ3000_cphmq0q7', '_TZ3000_dpo1ysak',
21
21
  '_TZ3000_1h2x4akh', '_TZ3000_9vo5icau', '_TZ3000_cehuw1lw', '_TZ3000_ko6v90pg', '_TZ3000_f1bapcit', '_TZ3000_cjrngdr3',
22
22
  '_TZ3000_zloso4jk', '_TZ3000_r6buo8ba', '_TZ3000_iksasdbv', '_TZ3000_idrffznf', '_TZ3000_okaz9tjs', '_TZ3210_q7oryllx',
23
23
  '_TZ3000_ss98ec5d', '_TZ3000_gznh2xla', '_TZ3000_hdopuwv6', '_TZ3000_gvn91tmx', '_TZ3000_dksbtrzs', '_TZ3000_b28wrpvx',
24
- '_TZ3000_aim0ztek'];
24
+ '_TZ3000_aim0ztek', '_TZ3000_mlswgkc3'];
25
25
 
26
26
  const tzLocal = {
27
27
  SA12IZL_silence_siren: {
@@ -796,6 +796,7 @@ module.exports = [
796
796
  {modelID: 'TS0001', manufacturerName: '_TZ3000_5ng23zjs'},
797
797
  {modelID: 'TS0001', manufacturerName: '_TZ3000_rmjr4ufz'},
798
798
  {modelID: 'TS0001', manufacturerName: '_TZ3000_v7gnj3ad'},
799
+ {modelID: 'TS0001', manufacturerName: '_TZ3000_ark8nv4y'},
799
800
  {modelID: 'TS0001', manufacturerName: '_TZ3000_mx3vgyea'},
800
801
  {modelID: 'TS0001', manufacturerName: '_TZ3000_qsp2pwtf'},
801
802
  {modelID: 'TS0001', manufacturerName: '_TZ3000_46t1rvdu'}],
@@ -1939,9 +1940,9 @@ module.exports = [
1939
1940
  exposes.binary('heating_stop', ea.STATE_SET, 'ON', 'OFF').withDescription('Battery life can be prolonged'+
1940
1941
  ' by switching the heating off. To achieve this, the valve is closed fully. To activate the '+
1941
1942
  'heating stop, the device display "HS", press the pair button to cancel.'),
1942
- e.holiday_temperature(), exposes.composite('holiday_mode_date').withDescription('The holiday mode( ⛱ ) will '+
1943
- 'automatically start at the set time starting point and run the holiday temperature.')
1944
- .withFeature(exposes.text('holiday_start_stop', ea.STATE_SET)),
1943
+ e.holiday_temperature(),
1944
+ exposes.text('holiday_start_stop', ea.STATE_SET).withDescription('The holiday mode( ) will '+
1945
+ 'automatically start at the set time starting point and run the holiday temperature.'),
1945
1946
  // exposes.enum('working_day', ea.STATE_SET, ['0', '1', '2', '3']),
1946
1947
  exposes.composite('schedule')/* .withFeature(exposes.text('week_schedule_programming', ea.STATE_SET)) */
1947
1948
  .withDescription('week_schedule').withDescription('Auto Mode ⏱ - In this mode, '+
@@ -3270,6 +3271,8 @@ module.exports = [
3270
3271
  configure: async (device, coordinatorEndpoint, logger) => {
3271
3272
  const endpoint = device.getEndpoint(1);
3272
3273
  await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'msTemperatureMeasurement', 'msRelativeHumidity']);
3274
+ await endpoint.read('genPowerCfg', ['batteryVoltage', 'batteryPercentageRemaining']);
3275
+ await reporting.batteryPercentageRemaining(endpoint);
3273
3276
  },
3274
3277
  },
3275
3278
  {
package/devices/xiaomi.js CHANGED
@@ -8,6 +8,7 @@ const extend = require('../lib/extend');
8
8
  const e = exposes.presets;
9
9
  const ea = exposes.access;
10
10
  const globalStore = require('../lib/store');
11
+ const xiaomi = require('../lib/xiaomi');
11
12
 
12
13
  const xiaomiExtend = {
13
14
  light_onoff_brightness_colortemp: (options={disableColorTempStartup: true}) => ({
@@ -125,6 +126,17 @@ const tzLocal = {
125
126
  }
126
127
  },
127
128
  },
129
+ VOCKQJK11LM_display_unit: {
130
+ key: ['display_unit'],
131
+ convertSet: async (entity, key, value, meta) => {
132
+ await entity.write('aqaraOpple',
133
+ {0x0114: {value: xiaomi.VOCKQJK11LMDisplayUnit[value], type: 0x20}}, {manufacturerCode: 0x115F});
134
+ return {state: {display_unit: value}};
135
+ },
136
+ convertGet: async (entity, key, meta) => {
137
+ await entity.read('aqaraOpple', [0x0114], {manufacturerCode: 0x115F, disableDefaultResponse: true});
138
+ },
139
+ },
128
140
  };
129
141
 
130
142
  module.exports = [
@@ -550,6 +562,7 @@ module.exports = [
550
562
  // set "event" mode
551
563
  await endpoint1.write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
552
564
  },
565
+ ota: ota.zigbeeOTA,
553
566
  },
554
567
  {
555
568
  zigbeeModel: ['lumi.switch.n2aeu1'],
@@ -1594,7 +1607,7 @@ module.exports = [
1594
1607
  e.battery_voltage().withAccess(ea.STATE_GET),
1595
1608
  e.device_temperature(),
1596
1609
  e.action(['manual_open', 'manual_close']),
1597
- exposes.enum('motor_state', ea.STATE, ['stopped', 'opening', 'closing'])
1610
+ exposes.enum('motor_state', ea.STATE, ['stopped', 'opening', 'closing', 'pause'])
1598
1611
  .withDescription('Motor state'),
1599
1612
  exposes.binary('running', ea.STATE, true, false)
1600
1613
  .withDescription('Whether the motor is moving or not'),
@@ -2020,9 +2033,11 @@ module.exports = [
2020
2033
  whiteLabel: [{vendor: 'Xiaomi', model: 'AAQS-S01'}],
2021
2034
  description: 'Aqara TVOC air quality monitor',
2022
2035
  fromZigbee: [fz.xiaomi_tvoc, fz.battery, fz.temperature, fz.humidity, fz.aqara_opple],
2023
- toZigbee: [],
2036
+ toZigbee: [tzLocal.VOCKQJK11LM_display_unit],
2024
2037
  meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
2025
- exposes: [e.temperature(), e.humidity(), e.voc(), e.device_temperature(), e.battery(), e.battery_voltage()],
2038
+ exposes: [e.temperature(), e.humidity(), e.voc(), e.device_temperature(), e.battery(), e.battery_voltage(),
2039
+ exposes.enum('display_unit', ea.ALL, ['mgm3_celsius', 'ppb_celsius', 'mgm3_fahrenheit', 'ppb_fahrenheit'])
2040
+ .withDescription('Units to show on the display')],
2026
2041
  configure: async (device, coordinatorEndpoint, logger) => {
2027
2042
  const endpoint = device.getEndpoint(1);
2028
2043
  const binds = ['msTemperatureMeasurement', 'msRelativeHumidity', 'genAnalogInput'];
@@ -2258,13 +2273,18 @@ module.exports = [
2258
2273
  model: 'SRTS-A01',
2259
2274
  vendor: 'Xiaomi',
2260
2275
  description: 'Aqara Smart Radiator Thermostat E1',
2261
- fromZigbee: [fzLocal.aqara_trv, fz.thermostat],
2276
+ fromZigbee: [fzLocal.aqara_trv, fz.thermostat, fz.battery],
2262
2277
  toZigbee: [tzLocal.aqara_trv, tz.thermostat_occupied_heating_setpoint],
2263
2278
  exposes: [e.switch().setAccess('state', ea.STATE_SET),
2264
2279
  exposes.climate().withSetpoint('occupied_heating_setpoint', 5, 30, 0.5)
2265
2280
  .withLocalTemperature(ea.STATE).withPreset(['manual', 'away', 'auto'], ea.STATE_SET),
2266
2281
  e.child_lock(), e.window_detection(), e.valve_detection(),
2267
- e.away_preset_temperature(),
2282
+ e.away_preset_temperature(), e.battery_voltage(), e.battery(),
2268
2283
  ],
2284
+ meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
2285
+ configure: async (device, coordinatorEndpoint, logger) => {
2286
+ const endpoint = device.getEndpoint(1);
2287
+ await endpoint.read('genPowerCfg', ['batteryVoltage']);
2288
+ },
2269
2289
  },
2270
2290
  ];
package/lib/xiaomi.js CHANGED
@@ -5,6 +5,7 @@ const {
5
5
  calibrateAndPrecisionRoundOptions,
6
6
  postfixWithEndpointName,
7
7
  precisionRound,
8
+ getKey,
8
9
  } = require('./utils');
9
10
 
10
11
  const buffer2DataObject = (meta, model, buffer) => {
@@ -432,6 +433,11 @@ const numericAttributes2Payload = (msg, meta, model, options, dataObject) => {
432
433
  payload.gas_sensitivity = {1: '15%LEL', 2: '10%LEL'}[value];
433
434
  }
434
435
  break;
436
+ case '276':
437
+ if (['VOCKQJK11LM'].includes(model.model)) {
438
+ payload.display_unit = getKey(VOCKQJK11LMDisplayUnit, value);
439
+ }
440
+ break;
435
441
  case '293':
436
442
  payload.click_mode = {1: 'fast', 2: 'multi'}[value];
437
443
  break;
@@ -637,7 +643,15 @@ const numericAttributes2Payload = (msg, meta, model, options, dataObject) => {
637
643
  return payload;
638
644
  };
639
645
 
646
+ const VOCKQJK11LMDisplayUnit = {
647
+ 'mgm3_celsius': 0x00, // mg/m³, °C (default)
648
+ 'ppb_celsius': 0x01, // ppb, °C
649
+ 'mgm3_fahrenheit': 0x10, // mg/m³, °F
650
+ 'ppb_fahrenheit': 0x11, // ppb, °F
651
+ };
652
+
640
653
  module.exports = {
641
654
  buffer2DataObject,
642
655
  numericAttributes2Payload,
656
+ VOCKQJK11LMDisplayUnit,
643
657
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zigbee-herdsman-converters",
3
- "version": "14.0.625",
3
+ "version": "14.0.627",
4
4
  "description": "Collection of device converters to be used with zigbee-herdsman",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -38,7 +38,7 @@
38
38
  "buffer-crc32": "^0.2.13",
39
39
  "https-proxy-agent": "^5.0.1",
40
40
  "tar-stream": "^2.2.0",
41
- "zigbee-herdsman": "^0.14.54"
41
+ "zigbee-herdsman": "^0.14.55"
42
42
  },
43
43
  "devDependencies": {
44
44
  "eslint": "*",