zigbee-herdsman-converters 14.0.367 → 14.0.371

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.
@@ -1073,7 +1073,6 @@ const converters = {
1073
1073
  cluster: 'ssIasAce',
1074
1074
  type: 'commandArm',
1075
1075
  convert: (model, msg, publish, options, meta) => {
1076
- if (hasAlreadyProcessedMessage(msg)) return;
1077
1076
  const payload = converters.command_arm.convert(model, msg, publish, options, meta);
1078
1077
  if (!payload) return;
1079
1078
  payload.action_transaction = msg.meta.zclTransactionSequenceNumber;
@@ -1165,7 +1164,8 @@ const converters = {
1165
1164
 
1166
1165
  if (options.simulated_brightness) {
1167
1166
  globalStore.putValue(msg.endpoint, 'simulated_brightness_brightness', msg.data.level);
1168
- payload.brightness = msg.data.level;
1167
+ const property = postfixWithEndpointName('brightness', msg, model);
1168
+ payload[property] = msg.data.level;
1169
1169
  }
1170
1170
 
1171
1171
  return payload;
@@ -1196,7 +1196,8 @@ const converters = {
1196
1196
  brightness += delta;
1197
1197
  brightness = numberWithinRange(brightness, 0, 255);
1198
1198
  globalStore.putValue(msg.endpoint, 'simulated_brightness_brightness', brightness);
1199
- publish({brightness});
1199
+ const property = postfixWithEndpointName('brightness', msg, model);
1200
+ publish({[property]: brightness});
1200
1201
  }, intervalOpts);
1201
1202
 
1202
1203
  globalStore.putValue(msg.endpoint, 'simulated_brightness_timer', timer);
@@ -1226,7 +1227,8 @@ const converters = {
1226
1227
  brightness += delta;
1227
1228
  brightness = numberWithinRange(brightness, 0, 255);
1228
1229
  globalStore.putValue(msg.endpoint, 'simulated_brightness_brightness', brightness);
1229
- payload.brightness = brightness;
1230
+ const property = postfixWithEndpointName('brightness', msg, model);
1231
+ payload[property] = brightness;
1230
1232
  }
1231
1233
 
1232
1234
  return payload;
@@ -2575,6 +2577,28 @@ const converters = {
2575
2577
  }
2576
2578
  },
2577
2579
  },
2580
+ wls100z_water_leak: {
2581
+ cluster: 'manuSpecificTuya',
2582
+ type: ['commandDataResponse', 'commandDataReport'],
2583
+ convert: (model, msg, publish, options, meta) => {
2584
+ const result = {};
2585
+ for (const dpValue of msg.data.dpValues) {
2586
+ const value = tuya.getDataValue(dpValue);
2587
+ switch (dpValue.dp) {
2588
+ case tuya.dataPoints.wlsWaterLeak:
2589
+ result.water_leak = value < 1;
2590
+ break;
2591
+ case tuya.dataPoints.wlsBatteryPercentage:
2592
+ result.battery = value;
2593
+ break;
2594
+ default:
2595
+ meta.logger.warn(`zigbee-herdsman-converters:wls100z_water_leak:` +
2596
+ `NOT RECOGNIZED DP #${dpValue.dp} with data ${JSON.stringify(dpValue)}`);
2597
+ }
2598
+ }
2599
+ return result;
2600
+ },
2601
+ },
2578
2602
  livolo_switch_state: {
2579
2603
  cluster: 'genOnOff',
2580
2604
  type: ['attributeReport', 'readResponse'],
@@ -4680,17 +4704,21 @@ const converters = {
4680
4704
  },
4681
4705
  tuya_smoke: {
4682
4706
  cluster: 'manuSpecificTuya',
4683
- type: ['commandDataResponse'],
4707
+ type: ['commandDataResponse', 'commandDataReport'],
4684
4708
  convert: (model, msg, publish, options, meta) => {
4685
- const dpValue = tuya.firstDpValue(msg, meta, 'tuya_smoke');
4686
- const dp = dpValue.dp;
4687
- const value = tuya.getDataValue(dpValue);
4688
- switch (dp) {
4689
- case tuya.dataPoints.state:
4690
- return {smoke: value === 0};
4691
- default:
4692
- meta.logger.warn(`zigbee-herdsman-converters:tuya_smoke: Unrecognized DP #${ dp} with data ${JSON.stringify(dpValue)}`);
4709
+ const result = {};
4710
+ for (const dpValue of msg.data.dpValues) {
4711
+ const dp = dpValue.dp;
4712
+ const value = tuya.getDataValue(dpValue);
4713
+ switch (dp) {
4714
+ case tuya.dataPoints.state:
4715
+ result.smoke = value === 0;
4716
+ break;
4717
+ default:
4718
+ meta.logger.warn(`zigbee-herdsman-converters:tuya_smoke: Unrecognized DP #${ dp} with data ${JSON.stringify(dpValue)}`);
4719
+ }
4693
4720
  }
4721
+ return result;
4694
4722
  },
4695
4723
  },
4696
4724
  tuya_woox_smoke: {
@@ -5129,6 +5157,7 @@ const converters = {
5129
5157
  if (msg.data.hasOwnProperty('0')) payload.detection_period = msg.data['0'];
5130
5158
  if (msg.data.hasOwnProperty('4')) payload.mode_switch = {4: 'anti_flicker_mode', 1: 'quick_mode'}[msg.data['4']];
5131
5159
  if (msg.data.hasOwnProperty('10')) payload.switch_type = {1: 'toggle', 2: 'momentary'}[msg.data['10']];
5160
+ if (msg.data.hasOwnProperty('258')) payload.detection_interval = msg.data['258'];
5132
5161
  if (msg.data.hasOwnProperty('268')) payload.motion_sensitivity = {1: 'low', 2: 'medium', 3: 'high'}[msg.data['268']];
5133
5162
  if (msg.data.hasOwnProperty('512')) {
5134
5163
  if (['ZNCZ15LM', 'QBCZ14LM', 'QBCZ15LM'].includes(model.model)) {
@@ -5943,7 +5972,13 @@ const converters = {
5943
5972
  ZMCSW032D_cover_position: {
5944
5973
  cluster: 'closuresWindowCovering',
5945
5974
  type: ['attributeReport', 'readResponse'],
5946
- options: [exposes.options.invert_cover()],
5975
+ options: [
5976
+ exposes.options.invert_cover(),
5977
+ exposes.numeric('time_close')
5978
+ .withDescription(`Set the full closing time of the roller shutter (e.g. set it to 20) (value is in s).`),
5979
+ exposes.numeric('time_open')
5980
+ .withDescription(`Set the full opening time of the roller shutter (e.g. set it to 21) (value is in s).`),
5981
+ ],
5947
5982
  convert: (model, msg, publish, options, meta) => {
5948
5983
  const result = {};
5949
5984
  const timeCoverSetMiddle = 60;
@@ -7437,6 +7472,25 @@ const converters = {
7437
7472
  }
7438
7473
  },
7439
7474
  },
7475
+ tuya_smart_vibration_sensor: {
7476
+ cluster: 'manuSpecificTuya',
7477
+ type: ['commandGetData', 'commandDataResponse', 'raw'],
7478
+ convert: (model, msg, publish, options, meta) => {
7479
+ const dp = msg.data.dp;
7480
+ const value = tuya.getDataValue(msg.data.datatype, msg.data.data);
7481
+ switch (dp) {
7482
+ case tuya.dataPoints.state:
7483
+ return {contact: Boolean(value)};
7484
+ case tuya.dataPoints.thitBatteryPercentage:
7485
+ return {battery: value};
7486
+ case tuya.dataPoints.tuyaVibration:
7487
+ return {vibration: Boolean(value)};
7488
+ default:
7489
+ meta.logger.warn(`zigbee-herdsman-converters:tuya_smart_vibration_sensor: NOT RECOGNIZED ` +
7490
+ `DP #${dp} with data ${JSON.stringify(msg.data)}`);
7491
+ }
7492
+ },
7493
+ },
7440
7494
  moes_thermostat_tv: {
7441
7495
  cluster: 'manuSpecificTuya',
7442
7496
  type: ['commandDataResponse', 'commandDataReport', 'raw'],
@@ -7527,7 +7581,11 @@ const converters = {
7527
7581
  cluster: 'genAnalogInput',
7528
7582
  type: ['attributeReport', 'readResponse'],
7529
7583
  convert: (model, msg, publish, options, meta) => {
7530
- return {people: msg.data.presentValue};
7584
+ const lookup = {'0': 'idle', '1': 'in', '2': 'out'};
7585
+ const value = precisionRound(parseFloat(msg.data['presentValue']), 1);
7586
+ let result = null;
7587
+ result = {people: precisionRound(msg.data.presentValue, 0), status: lookup[value*10%10]};
7588
+ return result;
7531
7589
  },
7532
7590
  },
7533
7591
  sihas_action: {
@@ -7865,6 +7923,11 @@ const converters = {
7865
7923
  type: ['commandMcuSyncTime'],
7866
7924
  convert: (model, msg, publish, options, meta) => null,
7867
7925
  },
7926
+ ignore_tuya_raw: {
7927
+ cluster: 'manuSpecificTuya',
7928
+ type: ['raw'],
7929
+ convert: (model, msg, publish, options, meta) => null,
7930
+ },
7868
7931
  // #endregion
7869
7932
  };
7870
7933
 
@@ -2076,6 +2076,17 @@ const converters = {
2076
2076
  await entity.read('aqaraOpple', [0x0000], manufacturerOptions.xiaomi);
2077
2077
  },
2078
2078
  },
2079
+ RTCGQ13LM_detection_interval: {
2080
+ key: ['detection_interval'],
2081
+ convertSet: async (entity, key, value, meta) => {
2082
+ value *= 1;
2083
+ await entity.write('aqaraOpple', {0x0102: {value: [value], type: 0x20}}, manufacturerOptions.xiaomi);
2084
+ return {state: {detection_interval: value}};
2085
+ },
2086
+ convertGet: async (entity, key, meta) => {
2087
+ await entity.read('aqaraOpple', [0x0102], manufacturerOptions.xiaomi);
2088
+ },
2089
+ },
2079
2090
  xiaomi_overload_protection: {
2080
2091
  key: ['overload_protection'],
2081
2092
  convertSet: async (entity, key, value, meta) => {
package/devices/aldi.js CHANGED
@@ -12,14 +12,6 @@ module.exports = [
12
12
  extend: extend.light_onoff_brightness_colortemp_color({disableColorTempStartup: true}),
13
13
  meta: {applyRedFix: true},
14
14
  },
15
- {
16
- fingerprint: [{modelID: 'TS0505B', manufacturerName: '_TZ3000_kohbva1f'}],
17
- model: 'L122CB63H11A9.0W',
18
- vendor: 'Aldi',
19
- description: 'LIGHTWAY smart home LED-lamp - bulb',
20
- extend: extend.light_onoff_brightness_colortemp_color({disableColorTempStartup: true}),
21
- meta: {applyRedFix: true},
22
- },
23
15
  {
24
16
  fingerprint: [{modelID: 'TS0505B', manufacturerName: '_TZ3000_iivsrikg'}],
25
17
  model: 'L122AA63H11A6.5W',
@@ -14,7 +14,11 @@ module.exports = [
14
14
  description: 'Light switch with neutral',
15
15
  fromZigbee: [fz.identify, fz.on_off, fz.K4003C_binary_input],
16
16
  toZigbee: [tz.on_off, tz.legrand_settingAlwaysEnableLed, tz.legrand_settingEnableLedIfOn, tz.legrand_identify],
17
- exposes: [e.switch(), e.action(['identify', 'on', 'off'])],
17
+ exposes: [
18
+ e.switch(), e.action(['identify', 'on', 'off']),
19
+ exposes.binary('permanent_led', ea.STATE_SET, 'ON', 'OFF').withDescription('Enable or disable the permanent blue LED'),
20
+ exposes.binary('led_when_on', ea.STATE_SET, 'ON', 'OFF').withDescription('Enables the LED when the light is on'),
21
+ ],
18
22
  configure: async (device, coordinatorEndpoint, logger) => {
19
23
  const endpoint = device.getEndpoint(1);
20
24
  await reporting.bind(endpoint, coordinatorEndpoint, ['genIdentify', 'genOnOff', 'genBinaryInput']);
@@ -26,7 +30,12 @@ module.exports = [
26
30
  vendor: 'BTicino',
27
31
  description: 'Dimmer switch with neutral',
28
32
  extend: extend.light_onoff_brightness({noConfigure: true}),
29
- exposes: [e.light_brightness()],
33
+ exposes: [
34
+ e.light_brightness(),
35
+ exposes.binary('dimmer_enabled', ea.STATE_SET, 'ON', 'OFF').withDescription('Allow the device to change brightness'),
36
+ exposes.binary('permanent_led', ea.STATE_SET, 'ON', 'OFF').withDescription('Enable or disable the permanent blue LED'),
37
+ exposes.binary('led_when_on', ea.STATE_SET, 'ON', 'OFF').withDescription('Enables the LED when the light is on'),
38
+ ],
30
39
  fromZigbee: [fz.brightness, fz.identify, fz.on_off],
31
40
  toZigbee: [tz.light_onoff_brightness, tz.legrand_settingAlwaysEnableLed, tz.legrand_settingEnableLedIfOn,
32
41
  tz.legrand_settingEnableDimmer, tz.legrand_identify],
package/devices/ecodim.js CHANGED
@@ -121,4 +121,11 @@ module.exports = [
121
121
  toZigbee: [],
122
122
  meta: {multiEndpoint: true, battery: {dontDividePercentage: true}},
123
123
  },
124
+ {
125
+ fingerprint: [{modelID: 'TS0501B', manufacturerName: '_TZ3210_yluvwhjc'}],
126
+ model: 'ED-10042',
127
+ vendor: 'EcoDim',
128
+ description: 'Zigbee LED filament light dimmable E27, globe G125, flame 2200K',
129
+ extend: extend.light_onoff_brightness(),
130
+ },
124
131
  ];
package/devices/iris.js CHANGED
@@ -74,7 +74,7 @@ module.exports = [
74
74
  exposes: [e.contact(), e.battery_low(), e.tamper(), e.temperature(), e.battery()],
75
75
  },
76
76
  {
77
- zigbeeModel: ['3450-L'],
77
+ zigbeeModel: ['3450-L', '3450-L2'],
78
78
  model: '3450-L',
79
79
  vendor: 'Iris',
80
80
  description: 'Smart fob',
package/devices/konke.js CHANGED
@@ -73,4 +73,13 @@ module.exports = [
73
73
  toZigbee: [],
74
74
  exposes: [e.water_leak(), e.battery_low(), e.tamper()],
75
75
  },
76
+ {
77
+ fingerprint: [{modelID: 'TS0222', manufacturerName: '_TYZB01_fi5yftwv'}],
78
+ model: 'KK-ES-J01W',
79
+ vendor: 'Konke',
80
+ description: 'Room temperature, relative humidity and illuminance sensor',
81
+ fromZigbee: [fz.battery, fz.illuminance, fz.humidity, fz.temperature],
82
+ toZigbee: [],
83
+ exposes: [e.battery(), e.illuminance(), e.illuminance_lux().withUnit('lx'), e.humidity(), e.temperature()],
84
+ },
76
85
  ];
package/devices/namron.js CHANGED
@@ -184,6 +184,13 @@ module.exports = [
184
184
  return {l1: 1, l2: 2, l3: 3, l4: 4};
185
185
  },
186
186
  },
187
+ {
188
+ zigbeeModel: ['3802960'],
189
+ model: '3802960',
190
+ vendor: 'Namron',
191
+ description: 'LED 9W DIM E27',
192
+ extend: extend.light_onoff_brightness(),
193
+ },
187
194
  {
188
195
  zigbeeModel: ['3802961'],
189
196
  model: '3802961',
@@ -199,6 +206,13 @@ module.exports = [
199
206
  meta: {turnsOffAtBrightness1: true},
200
207
  extend: extend.light_onoff_brightness_colortemp_color(),
201
208
  },
209
+ {
210
+ zigbeeModel: ['3802963'],
211
+ model: '3802963',
212
+ vendor: 'Namron',
213
+ description: 'LED 5,3W DIM E14',
214
+ extend: extend.light_onoff_brightness(),
215
+ },
202
216
  {
203
217
  zigbeeModel: ['3802964'],
204
218
  model: '3802964',
@@ -206,6 +220,13 @@ module.exports = [
206
220
  description: 'LED 5,3W CCT E14',
207
221
  extend: extend.light_onoff_brightness_colortemp(),
208
222
  },
223
+ {
224
+ zigbeeModel: ['3802966'],
225
+ model: '3802966',
226
+ vendor: 'Namron',
227
+ description: 'LED 4.8W CCT GU10',
228
+ extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 370]}),
229
+ },
209
230
  {
210
231
  zigbeeModel: ['89665'],
211
232
  model: '89665',
package/devices/nodon.js CHANGED
@@ -16,6 +16,8 @@ module.exports = [
16
16
  configure: async (device, coordinatorEndpoint, logger) => {
17
17
  const endpoint = device.getEndpoint(1);
18
18
  await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'closuresWindowCovering']);
19
+ await reporting.currentPositionLiftPercentage(endpoint);
20
+ await reporting.currentPositionTiltPercentage(endpoint);
19
21
  },
20
22
  exposes: [e.cover_position()],
21
23
  },
package/devices/nue_3a.js CHANGED
@@ -157,6 +157,12 @@ module.exports = [
157
157
  },
158
158
  },
159
159
  {
160
+ fingerprint: [
161
+ {type: 'Router', manufacturerName: '3A Smart Home DE', modelID: 'LXN-2S27LX1.0', endpoints: [
162
+ {ID: 11, profileID: 49246, deviceID: 0, inputClusters: [0, 4, 3, 6, 5, 4096, 8], outputClusters: [25]},
163
+ {ID: 12, profileID: 49246, deviceID: 0, inputClusters: [0, 4, 3, 6, 5, 8], outputClusters: [25]},
164
+ ]},
165
+ ],
160
166
  zigbeeModel: ['FNB56-ZSW02LX2.0'],
161
167
  model: 'HGZB-42',
162
168
  vendor: 'Nue / 3A',
@@ -283,7 +289,12 @@ module.exports = [
283
289
  extend: extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 370]}),
284
290
  },
285
291
  {
286
- zigbeeModel: ['LXN-2S27LX1.0'],
292
+ fingerprint: [
293
+ {type: 'Router', manufacturerName: '3A Smart Home DE', modelID: 'LXN-2S27LX1.0', endpoints: [
294
+ {ID: 1, profileID: 49246, deviceID: 0, inputClusters: [0, 4, 3, 6, 5, 4096, 8], outputClusters: [0]},
295
+ {ID: 2, profileID: 49246, deviceID: 0, inputClusters: [0, 4, 3, 6, 5, 4096, 8], outputClusters: [0]},
296
+ ]},
297
+ ],
287
298
  model: 'NUE-AUWZO2',
288
299
  vendor: 'Nue / 3A',
289
300
  description: 'Smart Zigbee double power point',
package/devices/osram.js CHANGED
@@ -178,11 +178,11 @@ module.exports = [
178
178
  ota: ota.ledvance,
179
179
  },
180
180
  {
181
- zigbeeModel: ['Surface Light TW'],
181
+ zigbeeModel: ['Surface Light TW', 'ZLO-CeilingTW-OS'],
182
182
  model: 'AB401130055',
183
183
  vendor: 'OSRAM',
184
184
  description: 'LIGHTIFY Surface Light LED Tunable White',
185
- extend: extend.ledvance.light_onoff_brightness_colortemp(),
185
+ extend: extend.ledvance.light_onoff_brightness_colortemp({colorTempRange: [153, 370]}),
186
186
  ota: ota.ledvance,
187
187
  },
188
188
  {
package/devices/owon.js CHANGED
@@ -106,15 +106,14 @@ module.exports = [
106
106
  zigbeeModel: ['THS317-ET'],
107
107
  model: 'THS317-ET',
108
108
  vendor: 'OWON',
109
- description: 'Temperature and humidity sensor',
110
- fromZigbee: [fz.temperature, fz.humidity, fz.battery],
109
+ description: 'Temperature sensor',
110
+ fromZigbee: [fz.temperature, fz.battery],
111
111
  toZigbee: [],
112
- exposes: [e.battery(), e.temperature(), e.humidity()],
112
+ exposes: [e.battery(), e.temperature()],
113
113
  configure: async (device, coordinatorEndpoint, logger) => {
114
- const endpoint = device.getEndpoint(2);
115
- await reporting.bind(endpoint, coordinatorEndpoint, ['msTemperatureMeasurement', 'msRelativeHumidity', 'genPowerCfg']);
114
+ const endpoint = device.getEndpoint(3);
115
+ await reporting.bind(endpoint, coordinatorEndpoint, ['msTemperatureMeasurement', 'genPowerCfg']);
116
116
  await reporting.temperature(endpoint);
117
- await reporting.humidity(endpoint);
118
117
  await reporting.batteryVoltage(endpoint);
119
118
  await reporting.batteryPercentageRemaining(endpoint);
120
119
  device.powerSource = 'Battery';
@@ -29,6 +29,15 @@ const hueExtend = {
29
29
  };
30
30
 
31
31
  module.exports = [
32
+ {
33
+ zigbeeModel: ['915005996401'],
34
+ model: '915005996401',
35
+ vendor: 'Philips',
36
+ description: 'Hue white ambiance ceiling light Enrave S with Bluetooth',
37
+ meta: {turnsOffAtBrightness1: true},
38
+ extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
39
+ ota: ota.zigbeeOTA,
40
+ },
32
41
  {
33
42
  zigbeeModel: ['929003054001'],
34
43
  model: '929003054001',
@@ -2315,7 +2324,7 @@ module.exports = [
2315
2324
  ota: ota.zigbeeOTA,
2316
2325
  },
2317
2326
  {
2318
- zigbeeModel: ['5309331P6'],
2327
+ zigbeeModel: ['5309331P6', '5309330P6'],
2319
2328
  model: '5309331P6',
2320
2329
  vendor: 'Philips',
2321
2330
  description: 'Hue White ambiance Runner triple spotlight',
@@ -2324,7 +2333,7 @@ module.exports = [
2324
2333
  ota: ota.zigbeeOTA,
2325
2334
  },
2326
2335
  {
2327
- zigbeeModel: ['5309230P6'],
2336
+ zigbeeModel: ['5309230P6', '5309231P6'],
2328
2337
  model: '5309230P6',
2329
2338
  vendor: 'Philips',
2330
2339
  description: 'Hue White ambiance Runner double spotlight',
@@ -2369,7 +2378,7 @@ module.exports = [
2369
2378
  ota: ota.zigbeeOTA,
2370
2379
  },
2371
2380
  {
2372
- zigbeeModel: ['5309030P9'],
2381
+ zigbeeModel: ['5309030P9', '5309031P9', '5309030P6', '5309031P6'],
2373
2382
  model: '5309030P9',
2374
2383
  vendor: 'Philips',
2375
2384
  description: 'Hue White ambiance Runner single spotlight',
@@ -610,4 +610,24 @@ module.exports = [
610
610
  await reporting.readMeteringMultiplierDivisor(endpoint);
611
611
  },
612
612
  },
613
+ {
614
+ zigbeeModel: ['LK/OUTLET/1'],
615
+ model: '545D6115',
616
+ vendor: 'Schneider Electric',
617
+ description: 'LK FUGA wiser wireless socket outlet',
618
+ fromZigbee: [fz.on_off, fz.electrical_measurement, fz.EKO09738_metering, fz.power_on_behavior],
619
+ toZigbee: [tz.on_off, tz.power_on_behavior],
620
+ exposes: [e.switch(), e.power(), e.energy(), e.current(), e.voltage(),
621
+ exposes.enum('power_on_behavior', ea.ALL, ['off', 'previous', 'on'])
622
+ .withDescription('Controls the behaviour when the device is powered on')],
623
+ configure: async (device, coordinatorEndpoint, logger) => {
624
+ const endpoint = device.getEndpoint(6);
625
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement', 'seMetering']);
626
+ await reporting.onOff(endpoint);
627
+ // Unit supports acVoltage and acCurrent, but only acCurrent divisor/multiplier can be read
628
+ await endpoint.read('haElectricalMeasurement', ['acCurrentDivisor', 'acCurrentMultiplier']);
629
+ await reporting.readMeteringMultiplierDivisor(endpoint);
630
+ await reporting.currentSummDelivered(endpoint, {min: 60, change: 1});
631
+ },
632
+ },
613
633
  ];
@@ -24,6 +24,7 @@ module.exports = [
24
24
  await endpoint.configureReporting('genAnalogInput', payload);
25
25
  },
26
26
  exposes: [e.battery(), e.battery_voltage(),
27
+ exposes.enum('status', ea.STATE, ['idle', 'in', 'out']).withDescription('Currently status'),
27
28
  exposes.numeric('people', ea.ALL).withValueMin(0).withValueMax(50).withDescription('People count')],
28
29
  },
29
30
  {
@@ -6,6 +6,22 @@ const extend = require('../lib/extend');
6
6
  const e = exposes.presets;
7
7
 
8
8
  module.exports = [
9
+ {
10
+ zigbeeModel: ['ON/OFF(2CH)'],
11
+ model: 'UP-SA-9127D',
12
+ vendor: 'Sunricher',
13
+ description: 'LED-trading 2 channel AC switch',
14
+ extend: extend.switch(),
15
+ exposes: [e.switch().withEndpoint('l1'), e.switch().withEndpoint('l2')],
16
+ endpoint: (device) => {
17
+ return {'l1': 1, 'l2': 2};
18
+ },
19
+ meta: {multiEndpoint: true},
20
+ configure: async (device, coordinatorEndpoint, logger) => {
21
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
22
+ await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
23
+ },
24
+ },
9
25
  {
10
26
  zigbeeModel: ['HK-ZD-CCT-A'],
11
27
  model: 'HK-ZD-CCT-A',
package/devices/tuya.js CHANGED
@@ -158,6 +158,7 @@ module.exports = [
158
158
  {modelID: 'TS0505B', manufacturerName: '_TZ3000_589kq4ul'},
159
159
  {modelID: 'TS0505B', manufacturerName: '_TZ3000_1mtktxdk'},
160
160
  {modelID: 'TS0505B', manufacturerName: '_TZ3210_remypqqm'},
161
+ {modelID: 'TS0505B', manufacturerName: '_TZ3000_kohbva1f'},
161
162
  {modelID: 'TS0505B', manufacturerName: '_TZ3210_0rn9qhnu'},
162
163
  {modelID: 'TS0505B', manufacturerName: '_TZ3210_bicjqpg4'},
163
164
  {modelID: 'TS0505B', manufacturerName: '_TZ3000_cmaky9gq'},
@@ -166,7 +167,10 @@ module.exports = [
166
167
  vendor: 'TuYa',
167
168
  description: 'Zigbee RGB+CCT light',
168
169
  whiteLabel: [{vendor: 'Mercator Ikuü', model: 'SMD4106W-RGB-ZB'},
169
- {vendor: 'TuYa', model: 'A5C-21F7-01'}, {vendor: 'Mercator Ikuü', model: 'S9E27LED9W-RGB-Z'}],
170
+ {vendor: 'TuYa', model: 'A5C-21F7-01'}, {vendor: 'Mercator Ikuü', model: 'S9E27LED9W-RGB-Z'},
171
+ {vendor: 'Aldi', model: 'L122CB63H11A9.0W', description: 'LIGHTWAY smart home LED-lamp - bulb'},
172
+ {vendor: 'Lidl', model: '14153706L', description: 'Livarno smart LED ceiling light'},
173
+ ],
170
174
  extend: extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
171
175
  meta: {applyRedFix: true, enhancedHue: false},
172
176
  },
@@ -660,6 +664,20 @@ module.exports = [
660
664
  toZigbee: [],
661
665
  whiteLabel: [{vendor: 'Neo', model: 'NAS-WS02B0'}],
662
666
  },
667
+ {
668
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_jthf7vb6'}],
669
+ model: 'WLS-100z',
670
+ vendor: 'TuYa',
671
+ description: 'Water leak sensor',
672
+ fromZigbee: [fz.ignore_basic_report, fz.ignore_tuya_raw, fz.wls100z_water_leak],
673
+ toZigbee: [],
674
+ onEvent: tuya.onEventSetTime,
675
+ configure: async (device, coordinatorEndpoint, logger) => {
676
+ const endpoint = device.getEndpoint(1);
677
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genBasic']);
678
+ },
679
+ exposes: [e.battery(), e.water_leak()],
680
+ },
663
681
  {
664
682
  zigbeeModel: ['TS0001'],
665
683
  model: 'TS0001',
@@ -1151,7 +1169,8 @@ module.exports = [
1151
1169
  },
1152
1170
  {
1153
1171
  fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_byzdayie'},
1154
- {modelID: 'TS0601', manufacturerName: '_TZE200_fsb6zw01'}],
1172
+ {modelID: 'TS0601', manufacturerName: '_TZE200_fsb6zw01'},
1173
+ {modelID: 'TS0601', manufacturerName: '_TZE200_ewxhg6o9'}],
1155
1174
  model: 'TS0601_din',
1156
1175
  vendor: 'TuYa',
1157
1176
  description: 'Zigbee smart energy meter DDS238-2 Zigbee',
@@ -1677,7 +1696,9 @@ module.exports = [
1677
1696
  ],
1678
1697
  },
1679
1698
  {
1680
- fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_vrfecyku'}],
1699
+ fingerprint: [
1700
+ {modelID: 'TS0601', manufacturerName: '_TZE200_vrfecyku'},
1701
+ {modelID: 'TS0601', manufacturerName: '_TZE200_lu01t0zl'}],
1681
1702
  model: 'MIR-HE200-TY',
1682
1703
  vendor: 'TuYa',
1683
1704
  description: 'Human presence sensor',
@@ -1805,4 +1826,13 @@ module.exports = [
1805
1826
  toZigbee: [],
1806
1827
  exposes: [e.action(['toggle', 'brightness_step_up', 'brightness_step_down'])],
1807
1828
  },
1829
+ {
1830
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_kzm5w4iz'}],
1831
+ model: 'TS0601_vibration_sensor',
1832
+ vendor: 'TuYa',
1833
+ description: 'Smart vibration sensor',
1834
+ fromZigbee: [fz.tuya_smart_vibration_sensor],
1835
+ toZigbee: [],
1836
+ exposes: [e.contact(), e.battery(), e.vibration()],
1837
+ },
1808
1838
  ];
package/devices/xiaomi.js CHANGED
@@ -89,6 +89,22 @@ module.exports = [
89
89
  e.power_outage_memory().withAccess(ea.STATE_SET)]),
90
90
  ota: ota.zigbeeOTA,
91
91
  },
92
+ {
93
+ zigbeeModel: ['lumi.light.acn003'],
94
+ model: 'ZNXDD01LM',
95
+ vendor: 'Xiaomi',
96
+ description: 'Aqara ceiling light L1-350',
97
+ extend: xiaomiExtend.light_onoff_brightness_colortemp({disableEffect: true, colorTempRange: [153, 370]}),
98
+ ota: ota.zigbeeOTA,
99
+ },
100
+ {
101
+ zigbeeModel: ['lumi.light.cwac02'],
102
+ model: 'ZNLDP13LM',
103
+ vendor: 'Xiaomi',
104
+ description: 'Aqara T1 smart LED bulb',
105
+ extend: xiaomiExtend.light_onoff_brightness_colortemp({disableEffect: true, colorTempRange: [153, 370]}),
106
+ ota: ota.zigbeeOTA,
107
+ },
92
108
  {
93
109
  zigbeeModel: ['lumi.light.cwopcn01'],
94
110
  model: 'XDD11LM',
@@ -872,18 +888,16 @@ module.exports = [
872
888
  model: 'RTCGQ13LM',
873
889
  vendor: 'Xiaomi',
874
890
  description: 'Aqara high precision motion sensor',
875
- fromZigbee: [fz.occupancy, fz.occupancy_timeout, fz.aqara_opple, fz.battery],
876
- toZigbee: [tz.occupancy_timeout, tz.RTCGQ13LM_motion_sensitivity],
877
- exposes: [e.occupancy(), exposes.enum('motion_sensitivity', exposes.access.ALL, ['low', 'medium', 'high']),
878
- exposes.numeric('occupancy_timeout', exposes.access.ALL).withValueMin(0).withValueMax(65535).withUnit('s')
879
- .withDescription('Time in seconds till occupancy goes to false'), e.battery()],
891
+ fromZigbee: [fz.occupancy_with_timeout, fz.aqara_opple, fz.battery],
892
+ toZigbee: [tz.RTCGQ13LM_detection_interval, tz.RTCGQ13LM_motion_sensitivity],
893
+ exposes: [e.occupancy(), e.battery(),
894
+ exposes.enum('motion_sensitivity', exposes.access.ALL, ['low', 'medium', 'high']),
895
+ exposes.numeric('detection_interval', exposes.access.ALL).withValueMin(2).withValueMax(180).withUnit('s')
896
+ .withDescription('Time interval for detecting actions')],
880
897
  meta: {battery: {voltageToPercentage: '3V_2100'}},
881
898
  configure: async (device, coordinatorEndpoint, logger) => {
882
899
  const endpoint = device.getEndpoint(1);
883
- await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'msOccupancySensing']);
884
- await reporting.occupancy(endpoint);
885
- await reporting.batteryVoltage(endpoint);
886
- await endpoint.read('msOccupancySensing', ['pirOToUDelay']);
900
+ await endpoint.read('aqaraOpple', [0x0102], {manufacturerCode: 0x115f});
887
901
  await endpoint.read('aqaraOpple', [0x010c], {manufacturerCode: 0x115f});
888
902
  },
889
903
  },
package/lib/exposes.js CHANGED
@@ -527,7 +527,7 @@ module.exports = {
527
527
  current: () => new Numeric('current', access.STATE).withUnit('A').withDescription('Instantaneous measured electrical current'),
528
528
  current_phase_b: () => new Numeric('current_phase_b', access.STATE).withUnit('A').withDescription('Instantaneous measured electrical current on phase B'),
529
529
  current_phase_c: () => new Numeric('current_phase_c', access.STATE).withUnit('A').withDescription('Instantaneous measured electrical current on phase C'),
530
- deadzone_temperature: () => new Numeric('deadzone_temperature', access.STATE_SET).withUnit('°C').withDescription('The delta between local_temperature and current_heating_setpoint to trigger Heat').withValueMin(1).withValueMax(5),
530
+ deadzone_temperature: () => new Numeric('deadzone_temperature', access.STATE_SET).withUnit('°C').withDescription('The delta between local_temperature and current_heating_setpoint to trigger Heat').withValueMin(0.1).withValueMax(5),
531
531
  device_temperature: () => new Numeric('device_temperature', access.STATE).withUnit('°C').withDescription('Temperature of the device'),
532
532
  eco2: () => new Numeric('eco2', access.STATE).withUnit('ppm').withDescription('Measured eCO2 value'),
533
533
  eco_mode: () => new Binary('eco_mode', access.STATE_SET, 'ON', 'OFF').withDescription('ECO mode (energy saving mode)'),
@@ -2,17 +2,56 @@ const url = 'https://raw.githubusercontent.com/Koenkk/zigbee-OTA/master/index.js
2
2
  const assert = require('assert');
3
3
  const common = require('./common');
4
4
  const axios = common.getAxios();
5
+ const fs = require('fs');
6
+ const URI = require('uri-js');
7
+
8
+ let overrideFileName = null;
5
9
 
6
10
  /**
7
11
  * Helper functions
8
12
  */
9
13
 
14
+
15
+ function isValidUrl(url) {
16
+ let parsed;
17
+ try {
18
+ parsed = URI.parse(url);
19
+ } catch (_) {
20
+ return false;
21
+ }
22
+ return parsed.scheme === 'http' || parsed.scheme === 'https';
23
+ }
24
+
25
+ async function getFile(urlOrName) {
26
+ if (isValidUrl(urlOrName)) {
27
+ return (await axios.get(urlOrName)).data;
28
+ }
29
+
30
+ return JSON.parse(fs.readFileSync(urlOrName));
31
+ }
32
+
33
+ async function getIndex(logger) {
34
+ const index = (await axios.get(url)).data;
35
+
36
+ logger.debug(`ZigbeeOTA: downloaded main index`);
37
+
38
+ if (overrideFileName) {
39
+ logger.debug(`ZigbeeOTA: Loading override index ${overrideFileName}`);
40
+ const localIndex = await getFile(overrideFileName);
41
+
42
+ // Resulting index will have overriden items first
43
+ return localIndex.concat(index);
44
+ }
45
+
46
+ return index;
47
+ }
48
+
10
49
  async function getImageMeta(current, logger, device) {
11
50
  const modelId = device.modelID;
12
51
  const imageType = current.imageType;
13
52
  const manufacturerCode = current.manufacturerCode;
14
53
  const manufacturerName = device.manufacturerName;
15
- const images = (await axios.get(url)).data;
54
+ const images = await getIndex(logger);
16
55
 
17
56
  // NOTE: Officially an image can be determined with a combination of manufacturerCode and imageType.
18
57
  // However Gledopto pro products use the same imageType (0) for every device while the image is different.
@@ -46,4 +85,7 @@ module.exports = {
46
85
  getImageMeta,
47
86
  isUpdateAvailable,
48
87
  updateToLatest,
88
+ useIndexOverride: (indexFileName) => {
89
+ overrideFileName = indexFileName;
90
+ },
49
91
  };
package/lib/tuya.js CHANGED
@@ -86,6 +86,9 @@ async function onEventMeasurementPoll(type, data, device, options) {
86
86
  try {
87
87
  await endpoint.read('haElectricalMeasurement', ['rmsVoltage', 'rmsCurrent', 'activePower']);
88
88
  await endpoint.read('seMetering', ['currentSummDelivered']);
89
+ if (device.manufacturerName === '_TZ3000_u5u4cakc') {
90
+ await endpoint.read('genOnOff', ['onOff']);
91
+ }
89
92
  } catch (error) {/* Do nothing*/}
90
93
  }, seconds*1000);
91
94
  globalStore.putValue(device, 'interval', interval);
@@ -101,11 +104,14 @@ async function onEventSetTime(type, data, device) {
101
104
  const localTime = utcTime - (new Date()).getTimezoneOffset() * 60;
102
105
  const endpoint = device.getEndpoint(1);
103
106
 
104
- await endpoint.command('manuSpecificTuya', 'mcuSyncTime', {
105
- 'seq': 8, // FIXME: Seems that need to set same seq as in request
106
- 'utc': utcTime,
107
- 'local': localTime,
108
- });
107
+ const payload = {
108
+ payloadSize: 8,
109
+ payload: [
110
+ ...convertDecimalValueTo4ByteHexArray(utcTime),
111
+ ...convertDecimalValueTo4ByteHexArray(localTime),
112
+ ],
113
+ };
114
+ await endpoint.command('manuSpecificTuya', 'mcuSyncTime', payload, {});
109
115
  } catch (error) {
110
116
  // endpoint.command can throw an error which needs to
111
117
  // be caught or the zigbee-herdsman may crash
@@ -134,11 +140,14 @@ async function onEventSetLocalTime(type, data, device) {
134
140
  const localTime = utcTime - (new Date()).getTimezoneOffset() * 60;
135
141
  const endpoint = device.getEndpoint(1);
136
142
 
137
- await endpoint.command('manuSpecificTuya', 'mcuSyncTime', {
138
- 'seq': 8, // FIXME: Seems that need to set same seq as in request
139
- 'utc': utcTime,
140
- 'local': localTime,
141
- });
143
+ const payload = {
144
+ payloadSize: 8,
145
+ payload: [
146
+ ...convertDecimalValueTo4ByteHexArray(utcTime),
147
+ ...convertDecimalValueTo4ByteHexArray(localTime),
148
+ ],
149
+ };
150
+ await endpoint.command('manuSpecificTuya', 'mcuSyncTime', payload, {});
142
151
  } catch (error) {
143
152
  // endpoint.command can throw an error which needs to
144
153
  // be caught or the zigbee-herdsman may crash
@@ -515,12 +524,16 @@ const dataPoints = {
515
524
  nousMinTemp: 11,
516
525
  nousTempAlarm: 14,
517
526
  nousTempSensitivity: 19,
518
-
519
527
  // TUYA / HUMIDITY/ILLUMINANCE/TEMPERATURE SENSOR
520
528
  thitBatteryPercentage: 3,
521
529
  thitIlluminanceLux: 7,
522
530
  thitHumidity: 9,
523
531
  thitTemperature: 8,
532
+ // TUYA SMART VIBRATION SENSOR
533
+ tuyaVibration: 10,
534
+ // TUYA WLS-100z Water Leak Sensor
535
+ wlsWaterLeak: 1,
536
+ wlsBatteryPercentage: 4,
524
537
  };
525
538
 
526
539
  const thermostatWeekFormat = {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zigbee-herdsman-converters",
3
- "version": "14.0.367",
3
+ "version": "14.0.371",
4
4
  "lockfileVersion": 1,
5
5
  "requires": true,
6
6
  "dependencies": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zigbee-herdsman-converters",
3
- "version": "14.0.367",
3
+ "version": "14.0.371",
4
4
  "description": "Collection of device converters to be used with zigbee-herdsman",
5
5
  "main": "index.js",
6
6
  "files": [