zigbee-herdsman-converters 14.0.467 → 14.0.468

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.
@@ -3820,7 +3820,12 @@ const converters = {
3820
3820
  return {deadzone_temperature: value};
3821
3821
  case tuya.dataPoints.moesLocalTemp:
3822
3822
  temperature = value & 1<<15 ? value - (1<<16) + 1 : value;
3823
- return {local_temperature: parseFloat((temperature / 10).toFixed(1))};
3823
+ if (meta.device.manufacturerName === '_TZE200_ye5jkfsb') {
3824
+ // https://github.com/Koenkk/zigbee2mqtt/issues/11980
3825
+ temperature = temperature / 10;
3826
+ }
3827
+
3828
+ return {local_temperature: parseFloat(temperature.toFixed(1))};
3824
3829
  case tuya.dataPoints.moesTempCalibration:
3825
3830
  temperature = value;
3826
3831
  // for negative values produce complimentary hex (equivalent to negative values)
@@ -4193,6 +4198,7 @@ const converters = {
4193
4198
  const dpValue = tuya.firstDpValue(msg, meta, 'tuya_air_quality');
4194
4199
  const dp = dpValue.dp;
4195
4200
  const value = tuya.getDataValue(dpValue);
4201
+ const swapPM25CO2 = ['_TZE200_ryfmq5rl', '_TZE200_dwcarsat'];
4196
4202
  switch (dp) {
4197
4203
  case tuya.dataPoints.tuyaSabTemp:
4198
4204
  return {temperature: calibrateAndPrecisionRoundOptions(value / 10, options, 'temperature')};
@@ -4200,14 +4206,14 @@ const converters = {
4200
4206
  return {humidity: calibrateAndPrecisionRoundOptions(value / 10, options, 'humidity')};
4201
4207
  // DP22: Smart Air Box: Formaldehyd, Smart Air Housekeeper: co2
4202
4208
  case tuya.dataPoints.tuyaSabFormaldehyd:
4203
- if (meta.device.manufacturerName === '_TZE200_dwcarsat') {
4209
+ if (swapPM25CO2.includes(meta.device.manufacturerName)) {
4204
4210
  return {co2: calibrateAndPrecisionRoundOptions(value, options, 'co2')};
4205
4211
  } else {
4206
4212
  return {formaldehyd: calibrateAndPrecisionRoundOptions(value, options, 'formaldehyd')};
4207
4213
  }
4208
4214
  // DP2: Smart Air Box: co2, Smart Air Housekeeper: MP25
4209
4215
  case tuya.dataPoints.tuyaSabCO2:
4210
- if (meta.device.manufacturerName === '_TZE200_dwcarsat') {
4216
+ if (swapPM25CO2.includes(meta.device.manufacturerName)) {
4211
4217
  return {pm25: calibrateAndPrecisionRoundOptions(value, options, 'pm25')};
4212
4218
  } else {
4213
4219
  return {co2: calibrateAndPrecisionRoundOptions(value, options, 'co2')};
@@ -2584,14 +2584,14 @@ const converters = {
2584
2584
  await entity.write('ssIasZone', {0xFFF1: {value: 0x03010000, type: 0x23}}, options);
2585
2585
  },
2586
2586
  },
2587
- JTBZ01AQA_gas: {
2588
- key: ['gas'],
2587
+ aqara_alarm: {
2588
+ key: ['gas', 'smoke'],
2589
2589
  convertGet: async (entity, key, meta) => {
2590
2590
  await entity.read('aqaraOpple', [0x013a], manufacturerOptions.xiaomi);
2591
2591
  },
2592
2592
  },
2593
- JTBZ01AQA_gas_density: {
2594
- key: ['gas_density'],
2593
+ aqara_density: {
2594
+ key: ['gas_density', 'smoke_density'],
2595
2595
  convertGet: async (entity, key, meta) => {
2596
2596
  await entity.read('aqaraOpple', [0x013b], manufacturerOptions.xiaomi);
2597
2597
  },
@@ -2608,26 +2608,39 @@ const converters = {
2608
2608
  await entity.read('aqaraOpple', [0x010c], manufacturerOptions.xiaomi);
2609
2609
  },
2610
2610
  },
2611
- JTBZ01AQA_selftest: {
2611
+ aqara_selftest: {
2612
2612
  key: ['selftest'],
2613
2613
  convertSet: async (entity, key, value, meta) => {
2614
2614
  await entity.write('aqaraOpple', {0x0127: {value: true, type: 0x10}}, manufacturerOptions.xiaomi);
2615
2615
  },
2616
2616
  },
2617
- JTBZ01AQA_mute_buzzer: {
2617
+ aqara_mute_buzzer: {
2618
2618
  key: ['mute_buzzer'],
2619
2619
  convertSet: async (entity, key, value, meta) => {
2620
- await entity.write('aqaraOpple', {0x013f: {value: 15360, type: 0x23}}, manufacturerOptions.xiaomi);
2620
+ let attribute = 0x013f;
2621
+ if (['JY-GZ-01AQ'].includes(meta.mapped.model)) attribute = 0x013e;
2622
+ await entity.write('aqaraOpple', {[`${attribute}`]: {value: 15360, type: 0x23}}, manufacturerOptions.xiaomi);
2621
2623
  await entity.write('aqaraOpple', {0x0126: {value: 1, type: 0x20}}, manufacturerOptions.xiaomi);
2622
2624
  },
2623
2625
  },
2624
- JTBZ01AQA_mute: {
2626
+ aqara_mute: {
2625
2627
  key: ['mute'],
2626
2628
  convertGet: async (entity, key, meta) => {
2627
2629
  await entity.read('aqaraOpple', [0x0126], manufacturerOptions.xiaomi);
2628
2630
  },
2629
2631
  },
2630
- JTBZ01AQA_linkage_alarm: {
2632
+ JYGZ01AQ_heartbeat_indicator: {
2633
+ key: ['heartbeat_indicator'],
2634
+ convertSet: async (entity, key, value, meta) => {
2635
+ const lookup = {true: 1, false: 0};
2636
+ await entity.write('aqaraOpple', {0x013c: {value: lookup[value], type: 0x20}}, manufacturerOptions.xiaomi);
2637
+ return {state: {heartbeat_indicator: value}};
2638
+ },
2639
+ convertGet: async (entity, key, meta) => {
2640
+ await entity.read('aqaraOpple', [0x013c], manufacturerOptions.xiaomi);
2641
+ },
2642
+ },
2643
+ aqara_linkage_alarm: {
2631
2644
  key: ['linkage_alarm'],
2632
2645
  convertSet: async (entity, key, value, meta) => {
2633
2646
  const lookup = {true: 1, false: 0};
package/devices/datek.js CHANGED
@@ -41,39 +41,45 @@ module.exports = [
41
41
  configure: async (device, coordinatorEndpoint, logger) => {
42
42
  const endpoint = device.getEndpoint(1);
43
43
  await reporting.bind(endpoint, coordinatorEndpoint, ['haElectricalMeasurement', 'seMetering', 'msTemperatureMeasurement']);
44
- await reporting.readEletricalMeasurementMultiplierDivisors(endpoint);
45
44
  await reporting.readMeteringMultiplierDivisor(endpoint);
45
+ try {
46
+ await reporting.readEletricalMeasurementMultiplierDivisors(endpoint);
47
+ } catch (error) {
48
+ /* fails for some: https://github.com/Koenkk/zigbee2mqtt/issues/11867 */
49
+ }
46
50
  const payload = [{
47
51
  attribute: 'rmsVoltagePhB',
48
- minimumReportInterval: 10,
52
+ minimumReportInterval: 60,
49
53
  maximumReportInterval: 3600,
50
54
  reportableChange: 0,
51
55
  },
52
56
  {
53
57
  attribute: 'rmsVoltagePhC',
54
- minimumReportInterval: 10,
58
+ minimumReportInterval: 60,
55
59
  maximumReportInterval: 3600,
56
60
  reportableChange: 0,
57
61
  },
58
62
  {
59
63
  attribute: 'rmsCurrentPhB',
60
- minimumReportInterval: 10,
64
+ minimumReportInterval: 60,
61
65
  maximumReportInterval: 3600,
62
66
  reportableChange: 0,
63
67
  },
64
68
  {
65
69
  attribute: 'rmsCurrentPhC',
66
- minimumReportInterval: 10,
70
+ minimumReportInterval: 60,
67
71
  maximumReportInterval: 3600,
68
72
  reportableChange: 0,
69
73
  }];
70
74
  await endpoint.configureReporting('haElectricalMeasurement', payload);
71
- await reporting.rmsVoltage(endpoint, {min: 10, max: 3600, change: 0});
72
- await reporting.rmsCurrent(endpoint, {min: 10, max: 3600, change: 0});
73
- await reporting.instantaneousDemand(endpoint, {min: 10, max: 3600, change: 0});
74
- await reporting.currentSummDelivered(endpoint, {min: 10, max: 3600, change: [1, 1]});
75
+ await reporting.rmsVoltage(endpoint, {min: 60, max: 3600, change: 0});
76
+ await reporting.rmsCurrent(endpoint, {min: 60, max: 3600, change: 0});
77
+ await reporting.instantaneousDemand(endpoint, {min: 60, max: 3600, change: 0});
78
+ await reporting.currentSummDelivered(endpoint, {min: 60, max: 3600, change: [1, 1]});
75
79
  await reporting.currentSummReceived(endpoint);
76
- await reporting.temperature(endpoint);
80
+ await reporting.temperature(endpoint, {min: 60, max: 3600, change: 0});
81
+ device.powerSource = 'DC source';
82
+ device.save();
77
83
  },
78
84
  exposes: [e.power(), e.energy(), e.current(), e.voltage(), e.current_phase_b(), e.voltage_phase_b(), e.current_phase_c(),
79
85
  e.voltage_phase_c(), e.temperature()],
@@ -341,4 +341,22 @@ module.exports = [
341
341
  return {left: 2, right: 1};
342
342
  },
343
343
  },
344
+ {
345
+ zigbeeModel: [' Mobile outlet\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000'+
346
+ '\u0000\u0000\u0000\u0000\u0000\u0000\u0000'],
347
+ model: 'WNRR15/WNRR20',
348
+ vendor: 'Legrand',
349
+ ota: ota.zigbeeOTA,
350
+ description: 'Outlet with power consumption monitoring',
351
+ fromZigbee: [fz.identify, fz.on_off, fz.electrical_measurement],
352
+ toZigbee: [tz.on_off, tz.legrand_settingAlwaysEnableLed, tz.legrand_identify],
353
+ exposes: [e.switch(), e.action(['identify']), e.power()],
354
+ configure: async (device, coordinatorEndpoint, logger) => {
355
+ const endpoint = device.getEndpoint(1);
356
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genIdentify', 'genOnOff', 'haElectricalMeasurement']);
357
+ await reporting.onOff(endpoint);
358
+ await reporting.readEletricalMeasurementMultiplierDivisors(endpoint);
359
+ await reporting.activePower(endpoint);
360
+ },
361
+ },
344
362
  ];
package/devices/moes.js CHANGED
@@ -99,6 +99,7 @@ module.exports = [
99
99
  {
100
100
  fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_aoclfnxz'},
101
101
  {modelID: 'TS0601', manufacturerName: '_TZE200_ztvwu4nk'},
102
+ {modelID: 'TS0601', manufacturerName: '_TZE200_ye5jkfsb'},
102
103
  {modelID: 'TS0601', manufacturerName: '_TZE200_u9bfwha0'}],
103
104
  model: 'BHT-002-GCLZB',
104
105
  vendor: 'Moes',
package/devices/niko.js CHANGED
@@ -5,6 +5,60 @@ const reporting = require('../lib/reporting');
5
5
  const e = exposes.presets;
6
6
  const ea = exposes.access;
7
7
 
8
+ const fzLocal = {
9
+ fz: {
10
+ switch_operation_mode: {
11
+ cluster: 'manuSpecificNikoSwitchSetup',
12
+ type: ['attributeReport', 'readResponse'],
13
+ convert: (model, msg, publish, options, meta) => {
14
+ const state = {};
15
+ if (msg.data.hasOwnProperty('operationMode')) {
16
+ const operationModeProperty = `operation_mode${meta.endpoint_name ? `_${meta.endpoint_name}` : ''}`;
17
+ const operationModeMap = {0x02: 'control_relay', 0x01: 'decoupled', 0x00: 'unknown'};
18
+ state[operationModeProperty] = operationModeMap[msg.data.operationMode];
19
+ }
20
+ return state;
21
+ },
22
+ },
23
+ switch_action: {
24
+ cluster: 'manuSpecificNikoSwitch',
25
+ type: ['attributeReport', 'readResponse'],
26
+ convert: (model, msg, publish, options, meta) => {
27
+ const state = {};
28
+
29
+ if (msg.data.hasOwnProperty('action')) {
30
+ // NOTE: a single press = two seperate values reported, 16 followed by 64
31
+ // a hold/release cyle = three seperate values, 16, 32, and 48
32
+ const actionProperty = `action${meta.endpoint_name ? `_${meta.endpoint_name}` : ''}`;
33
+ const actionMap = {16: null, 64: 'single', 32: 'hold', 48: 'release'};
34
+ state[actionProperty] = actionMap[msg.data.action];
35
+ }
36
+ return state;
37
+ },
38
+ },
39
+ },
40
+ tz: {
41
+ switch_operation_mode: {
42
+ key: ['operation_mode'],
43
+ convertSet: async (entity, key, value, meta) => {
44
+ // WARN: while we can technically write 0x00 to the operationMode attribute
45
+ // this seems to brick the device and it will need to be rejoined
46
+ const operationModeLookup = {control_relay: 0x02, decoupled: 0x01};
47
+ if (!operationModeLookup.hasOwnProperty(value)) {
48
+ throw new Error(`operation_mode was called with an invalid value (${value})`);
49
+ } else {
50
+ const operationModeProperty = `operation_mode${meta.endpoint_name ? `_${meta.endpoint_name}` : ''}`;
51
+ await entity.write('manuSpecificNikoSwitchSetup', {'operationMode': operationModeLookup[value]});
52
+ return {state: {[operationModeProperty]: value.toLowerCase()}};
53
+ }
54
+ },
55
+ convertGet: async (entity, key, meta) => {
56
+ await entity.read('manuSpecificNikoSwitchSetup', ['operationMode']);
57
+ },
58
+ },
59
+ },
60
+ };
61
+
8
62
  module.exports = [
9
63
  {
10
64
  zigbeeModel: ['Connected socket outlet'],
@@ -80,15 +134,18 @@ module.exports = [
80
134
  model: '552-721X1',
81
135
  vendor: 'Niko',
82
136
  description: 'Single connectable switch',
83
- fromZigbee: [fz.on_off],
84
- toZigbee: [tz.on_off],
137
+ fromZigbee: [fz.on_off, fzLocal.fz.switch_operation_mode, fzLocal.fz.switch_action],
138
+ toZigbee: [tz.on_off, fzLocal.tz.switch_operation_mode],
85
139
  configure: async (device, coordinatorEndpoint, logger) => {
86
140
  const endpoint = device.getEndpoint(1);
87
141
  await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
88
142
  await reporting.onOff(endpoint);
143
+ await endpoint.read('manuSpecificNikoSwitchSetup', ['operationMode']);
89
144
  },
90
145
  exposes: [
91
146
  e.switch(),
147
+ e.action(['single', 'hold', 'release']),
148
+ exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled']),
92
149
  ],
93
150
  },
94
151
  {
@@ -96,8 +153,8 @@ module.exports = [
96
153
  model: '552-721X2',
97
154
  vendor: 'Niko',
98
155
  description: 'Double connectable switch',
99
- fromZigbee: [fz.on_off],
100
- toZigbee: [tz.on_off],
156
+ fromZigbee: [fz.on_off, fzLocal.fz.switch_operation_mode, fzLocal.fz.switch_action],
157
+ toZigbee: [tz.on_off, fzLocal.tz.switch_operation_mode],
101
158
  endpoint: (device) => {
102
159
  return {'l1': 1, 'l2': 2};
103
160
  },
@@ -109,9 +166,15 @@ module.exports = [
109
166
  await reporting.bind(ep2, coordinatorEndpoint, ['genOnOff']);
110
167
  await reporting.onOff(ep1);
111
168
  await reporting.onOff(ep2);
169
+ await ep1.read('manuSpecificNikoSwitchSetup', ['operationMode']);
170
+ await ep2.read('manuSpecificNikoSwitchSetup', ['operationMode']);
112
171
  },
113
172
  exposes: [
114
173
  e.switch().withEndpoint('l1'), e.switch().withEndpoint('l2'),
174
+ e.action(['single', 'hold', 'release']).withEndpoint('l1'),
175
+ e.action(['single', 'hold', 'release']).withEndpoint('l2'),
176
+ exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled']).withEndpoint('l1'),
177
+ exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled']).withEndpoint('l2'),
115
178
  ],
116
179
  },
117
180
  ];
@@ -2714,6 +2714,15 @@ module.exports = [
2714
2714
  meta: {turnsOffAtBrightness1: true},
2715
2715
  ota: ota.zigbeeOTA,
2716
2716
  },
2717
+ {
2718
+ zigbeeModel: ['5060930P7_01', '5060930P7_02', '5060930P7_03', '5060930P7_04'],
2719
+ model: '5060930P7',
2720
+ vendor: 'Philips',
2721
+ description: 'Hue White & Color Ambiance Centris ceiling light (3 spots)',
2722
+ extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
2723
+ meta: {turnsOffAtBrightness1: true},
2724
+ ota: ota.zigbeeOTA,
2725
+ },
2717
2726
  {
2718
2727
  zigbeeModel: ['5060931P7_01', '5060931P7_02', '5060931P7_03', '5060931P7_04'],
2719
2728
  model: '5060931P7',
@@ -10,6 +10,9 @@ module.exports = [
10
10
  vendor: 'Spotmau',
11
11
  description: 'Smart wall switch - 1 gang',
12
12
  extend: extend.switch(),
13
+ endpoint: (device) => {
14
+ return {default: 16};
15
+ },
13
16
  configure: async (device, coordinatorEndpoint, logger) => {
14
17
  await reporting.bind(device.getEndpoint(16), coordinatorEndpoint, ['genOnOff', 'genBasic']);
15
18
  },
package/devices/tuya.js CHANGED
@@ -1048,6 +1048,7 @@ module.exports = [
1048
1048
  {modelID: 'TS0601', manufacturerName: '_TZE200_3i3exuay'},
1049
1049
  {modelID: 'TS0601', manufacturerName: '_TZE200_tvrvdj6o'},
1050
1050
  {modelID: 'zo2pocs\u0000', manufacturerName: '_TYST11_fzo2pocs'},
1051
+ {modelID: 'TS0601', manufacturerName: '_TZE200_cf1sl3tj'},
1051
1052
  // Roller blinds:
1052
1053
  {modelID: 'TS0601', manufacturerName: '_TZE200_sbordckq'},
1053
1054
  {modelID: 'TS0601', manufacturerName: '_TZE200_fctwhugx'},
@@ -1076,6 +1077,7 @@ module.exports = [
1076
1077
  {vendor: 'TuYa', model: 'ZD82TN', description: 'Curtain motor'},
1077
1078
  {vendor: 'Moes', model: 'AM43-0.45/40-ES-EB'},
1078
1079
  {vendor: 'Larkkey', model: 'ZSTY-SM-1SRZG-EU'},
1080
+ {vendor: 'Zemismart', model: 'ZM85EL-2Z', description: 'Roman Rod I type curtains track'},
1079
1081
  {vendor: 'Zemismart', model: 'ZM25TQ', description: 'Tubular motor'},
1080
1082
  {vendor: 'Zemismart', model: 'AM43', description: 'Roller blind motor'},
1081
1083
  {vendor: 'Zemismart', model: 'M2805EGBZTN', description: 'Tubular motor'},
@@ -1103,6 +1105,7 @@ module.exports = [
1103
1105
  {modelID: 'TS0601', manufacturerName: '_TZE200_9sfg7gm0'}, // HomeCloud
1104
1106
  {modelID: 'TS0601', manufacturerName: '_TZE200_2atgpdho'}, // HY367
1105
1107
  {modelID: 'TS0601', manufacturerName: '_TZE200_cpmgn2cf'},
1108
+ {modelID: 'TS0601', manufacturerName: '_TZE200_4eeyebrt'}, // Immax 07732B
1106
1109
  ],
1107
1110
  model: 'TS0601_thermostat',
1108
1111
  vendor: 'TuYa',
@@ -1112,6 +1115,7 @@ module.exports = [
1112
1115
  {vendor: 'Moes', model: 'HY369RT'},
1113
1116
  {vendor: 'SHOJZJ', model: '378RT'},
1114
1117
  {vendor: 'Silvercrest', model: 'TVR01'},
1118
+ {vendor: 'Immax', model: '07732B'},
1115
1119
  ],
1116
1120
  meta: {tuyaThermostatPreset: tuya.thermostatPresets, tuyaThermostatSystemMode: tuya.thermostatSystemModes3},
1117
1121
  ota: ota.zigbeeOTA,
@@ -1705,7 +1709,7 @@ module.exports = [
1705
1709
  },
1706
1710
  },
1707
1711
  {
1708
- zigbeeModel: ['HY0017', '005f0c3'],
1712
+ zigbeeModel: ['HY0017', '005f0c3b'],
1709
1713
  model: 'U86KCJ-ZP',
1710
1714
  vendor: 'TuYa',
1711
1715
  description: 'Smart 6 key scene wall switch',
package/devices/xiaomi.js CHANGED
@@ -1170,9 +1170,9 @@ module.exports = [
1170
1170
  vendor: 'Xiaomi',
1171
1171
  description: 'Aqara smart natural gas detector',
1172
1172
  fromZigbee: [fz.aqara_opple],
1173
- toZigbee: [tz.JTBZ01AQA_gas, tz.JTBZ01AQA_gas_density, tz.JTBZ01AQA_gas_sensitivity, tz.JTBZ01AQA_selftest,
1174
- tz.JTBZ01AQA_mute_buzzer, tz.JTBZ01AQA_mute, tz.JTBZ01AQA_linkage_alarm, tz.JTBZ01AQA_state, tz.aqara_power_outage_count],
1175
- exposes: [e.gas().withAccess(ea.STATE_GET), e.power_outage_count().withAccess(ea.STATE_GET),
1173
+ toZigbee: [tz.aqara_alarm, tz.aqara_density, tz.JTBZ01AQA_gas_sensitivity, tz.aqara_selftest, tz.aqara_mute_buzzer,
1174
+ tz.aqara_mute, tz.aqara_linkage_alarm, tz.JTBZ01AQA_state, tz.aqara_power_outage_count],
1175
+ exposes: [e.gas().withAccess(ea.STATE_GET),
1176
1176
  exposes.numeric('gas_density', ea.STATE_GET).withUnit('%LEL').withDescription('Value of gas concentration'),
1177
1177
  exposes.enum('gas_sensitivity', ea.ALL, ['10%LEL', '15%LEL']).withDescription('Gas concentration value at which ' +
1178
1178
  'an alarm is triggered ("10%LEL" is more sensitive than "15%LEL")'),
@@ -1186,7 +1186,7 @@ module.exports = [
1186
1186
  'is detected, other detectors with this option enabled will also sound the alarm buzzer'),
1187
1187
  exposes.binary('state', ea.STATE_GET, 'preparation', 'work').withDescription('"Preparation" or "work" ' +
1188
1188
  '(measurement of the gas concentration value and triggering of an alarm are only performed in the "work" state)'),
1189
- ],
1189
+ e.power_outage_count().withAccess(ea.STATE_GET)],
1190
1190
  configure: async (device, coordinatorEndpoint, logger) => {
1191
1191
  const endpoint = device.getEndpoint(1);
1192
1192
  await endpoint.read('aqaraOpple', [0x013a], {manufacturerCode: 0x115f});
@@ -1199,6 +1199,40 @@ module.exports = [
1199
1199
  },
1200
1200
  ota: ota.zigbeeOTA,
1201
1201
  },
1202
+ {
1203
+ zigbeeModel: ['lumi.sensor_smoke.acn03'],
1204
+ model: 'JY-GZ-01AQ',
1205
+ vendor: 'Xiaomi',
1206
+ description: 'Aqara smart smoke detector',
1207
+ fromZigbee: [fz.aqara_opple, fz.battery],
1208
+ toZigbee: [tz.aqara_alarm, tz.aqara_density, tz.aqara_selftest, tz.aqara_mute_buzzer, tz.aqara_mute,
1209
+ tz.JYGZ01AQ_heartbeat_indicator, tz.aqara_linkage_alarm],
1210
+ exposes: [e.smoke().withAccess(ea.STATE_GET),
1211
+ exposes.numeric('smoke_density', ea.STATE_GET).withDescription('Value of smoke concentration'),
1212
+ exposes.numeric('smoke_density_dbm', ea.STATE).withUnit('dB/m').withDescription('Value of smoke concentration in dB/m'),
1213
+ exposes.enum('selftest', ea.SET, ['Test']).withDescription('Starts the self-test process (checking the indicator ' +
1214
+ 'light and buzzer work properly)'),
1215
+ exposes.binary('test', ea.STATE, true, false).withDescription('Self-test in progress'),
1216
+ exposes.enum('mute_buzzer', ea.SET, ['Mute']).withDescription('Mute the buzzer for 80 seconds (buzzer cannot be ' +
1217
+ 'pre-muted, because this function only works when the alarm is triggered)'),
1218
+ exposes.binary('mute', ea.STATE_GET, true, false).withDescription('Buzzer muted'),
1219
+ exposes.binary('heartbeat_indicator', ea.ALL, true, false).withDescription('When this option is enabled then in ' +
1220
+ 'the normal monitoring state, the green indicator light flashes every 60 seconds'),
1221
+ exposes.binary('linkage_alarm', ea.ALL, true, false).withDescription('When this option is enabled and a smoke ' +
1222
+ 'is detected, other detectors with this option enabled will also sound the alarm buzzer'),
1223
+ e.temperature(), e.battery()],
1224
+ meta: {battery: {voltageToPercentage: '3V_2850_3000_log'}},
1225
+ configure: async (device, coordinatorEndpoint, logger) => {
1226
+ const endpoint = device.getEndpoint(1);
1227
+ await endpoint.read('genPowerCfg', ['batteryVoltage']);
1228
+ await endpoint.read('aqaraOpple', [0x013a], {manufacturerCode: 0x115f});
1229
+ await endpoint.read('aqaraOpple', [0x013b], {manufacturerCode: 0x115f});
1230
+ await endpoint.read('aqaraOpple', [0x013c], {manufacturerCode: 0x115f});
1231
+ await endpoint.read('aqaraOpple', [0x0126], {manufacturerCode: 0x115f});
1232
+ await endpoint.read('aqaraOpple', [0x014b], {manufacturerCode: 0x115f});
1233
+ },
1234
+ ota: ota.zigbeeOTA,
1235
+ },
1202
1236
  {
1203
1237
  zigbeeModel: ['lumi.lock.v1'],
1204
1238
  model: 'A6121',
package/lib/xiaomi.js CHANGED
@@ -174,9 +174,11 @@ const numericAttributes2Payload = (msg, meta, model, options, dataObject) => {
174
174
  payload.switch_type = {1: 'toggle', 2: 'momentary'}[value];
175
175
  break;
176
176
  case '11':
177
- payload.illuminance = calibrateAndPrecisionRoundOptions(value, options, 'illuminance');
178
- // DEPRECATED: remove illuminance_lux here.
179
- payload.illuminance_lux = calibrateAndPrecisionRoundOptions(value, options, 'illuminance_lux');
177
+ if (!['JT-BZ-01AQ/A'].includes(model.model)) {
178
+ payload.illuminance = calibrateAndPrecisionRoundOptions(value, options, 'illuminance');
179
+ // DEPRECATED: remove illuminance_lux here.
180
+ payload.illuminance_lux = calibrateAndPrecisionRoundOptions(value, options, 'illuminance_lux');
181
+ }
180
182
  break;
181
183
  case '100':
182
184
  if (['QBKG20LM', 'QBKG31LM', 'QBKG39LM', 'QBKG41LM', 'QBCZ15LM', 'LLKZMK11LM', 'QBKG12LM', 'QBKG03LM'].includes(model.model)) {
@@ -300,25 +302,52 @@ const numericAttributes2Payload = (msg, meta, model, options, dataObject) => {
300
302
  }
301
303
  break;
302
304
  case '159':
303
- payload.gas_sensitivity = {1: '15%LEL', 2: '10%LEL'}[value]; // JT-BZ-01AQ/A
305
+ if (['JT-BZ-01AQ/A'].includes(model.model)) {
306
+ payload.gas_sensitivity = {1: '15%LEL', 2: '10%LEL'}[value];
307
+ }
304
308
  break;
305
309
  case '160':
306
- payload.gas = value === 1; // JT-BZ-01AQ/A
310
+ if (['JT-BZ-01AQ/A'].includes(model.model)) {
311
+ payload.gas = value === 1;
312
+ } else if (['JY-GZ-01AQ'].includes(model.model)) {
313
+ payload.smoke = value === 1;
314
+ }
307
315
  break;
308
316
  case '161':
309
- payload.gas_density = value; // JT-BZ-01AQ/A
317
+ if (['JT-BZ-01AQ/A'].includes(model.model)) {
318
+ payload.gas_density = value;
319
+ } else if (['JY-GZ-01AQ'].includes(model.model)) {
320
+ payload.smoke_density = value;
321
+ payload.smoke_density_dbm = {0: 0, 1: 0.085, 2: 0.088, 3: 0.093, 4: 0.095, 5: 0.100, 6: 0.105, 7: 0.110,
322
+ 8: 0.115, 9: 0.120, 10: 0.125}[value];
323
+ }
310
324
  break;
311
325
  case '162':
312
- payload.test = value === 1; // JT-BZ-01AQ/A
326
+ if (['JT-BZ-01AQ/A', 'JY-GZ-01AQ'].includes(model.model)) {
327
+ payload.test = value === 1;
328
+ }
313
329
  break;
314
330
  case '163':
315
- payload.mute = value === 1; // JT-BZ-01AQ/A
331
+ if (['JT-BZ-01AQ/A', 'JY-GZ-01AQ'].includes(model.model)) {
332
+ payload.mute = value === 1;
333
+ }
316
334
  break;
317
335
  case '164':
318
- payload.state = value === 1 ? 'preparation' : 'work'; // JT-BZ-01AQ/A
336
+ if (['JT-BZ-01AQ/A'].includes(model.model)) {
337
+ payload.state = {0: 'work', 1: 'preparation'}[value];
338
+ } else if (['JY-GZ-01AQ'].includes(model.model)) {
339
+ payload.heartbeat_indicator = value === 1;
340
+ }
341
+ break;
342
+ case '165':
343
+ if (['JY-GZ-01AQ'].includes(model.model)) {
344
+ payload.linkage_alarm = value === 1;
345
+ }
319
346
  break;
320
347
  case '166':
321
- payload.linkage_alarm = value === 1; // JT-BZ-01AQ/A
348
+ if (['JT-BZ-01AQ/A'].includes(model.model)) {
349
+ payload.linkage_alarm = value === 1;
350
+ }
322
351
  break;
323
352
  case '240':
324
353
  payload.flip_indicator_light = value === 1 ? 'ON' : 'OFF';
@@ -344,19 +373,40 @@ const numericAttributes2Payload = (msg, meta, model, options, dataObject) => {
344
373
  payload.click_mode = {1: 'fast', 2: 'multi'}[value];
345
374
  break;
346
375
  case '294':
347
- payload.mute = value === 1; // JT-BZ-01AQ/A
376
+ if (['JT-BZ-01AQ/A', 'JY-GZ-01AQ'].includes(model.model)) {
377
+ payload.mute = value === 1;
378
+ }
348
379
  break;
349
380
  case '295':
350
- payload.test = value === 1; // JT-BZ-01AQ/A
381
+ if (['JT-BZ-01AQ/A', 'JY-GZ-01AQ'].includes(model.model)) {
382
+ payload.test = value === 1;
383
+ }
351
384
  break;
352
385
  case '313':
353
- payload.state = value === 1 ? 'preparation' : 'work'; // JT-BZ-01AQ/A
386
+ if (['JT-BZ-01AQ/A'].includes(model.model)) {
387
+ payload.state = {0: 'work', 1: 'preparation'}[value];
388
+ }
354
389
  break;
355
390
  case '314':
356
- payload.gas = value === 1; // JT-BZ-01AQ/A
391
+ if (['JT-BZ-01AQ/A'].includes(model.model)) {
392
+ payload.gas = value === 1;
393
+ } else if (['JY-GZ-01AQ'].includes(model.model)) {
394
+ payload.smoke = value === 1;
395
+ }
357
396
  break;
358
397
  case '315':
359
- payload.gas_density = value; // JT-BZ-01AQ/A
398
+ if (['JT-BZ-01AQ/A'].includes(model.model)) {
399
+ payload.gas_density = value;
400
+ } else if (['JY-GZ-01AQ'].includes(model.model)) {
401
+ payload.smoke_density = value;
402
+ payload.smoke_density_dbm = {0: 0, 1: 0.085, 2: 0.088, 3: 0.093, 4: 0.095, 5: 0.100, 6: 0.105, 7: 0.110,
403
+ 8: 0.115, 9: 0.120, 10: 0.125}[value];
404
+ }
405
+ break;
406
+ case '316':
407
+ if (['JY-GZ-01AQ'].includes(model.model)) {
408
+ payload.heartbeat_indicator = value === 1;
409
+ }
360
410
  break;
361
411
  case '322':
362
412
  if (['RTCZCGQ11LM'].includes(model.model)) {
@@ -380,7 +430,9 @@ const numericAttributes2Payload = (msg, meta, model, options, dataObject) => {
380
430
  }
381
431
  break;
382
432
  case '331':
383
- payload.linkage_alarm = value === 1; // JT-BZ-01AQ/A
433
+ if (['JT-BZ-01AQ/A', 'JY-GZ-01AQ'].includes(model.model)) {
434
+ payload.linkage_alarm = value === 1;
435
+ }
384
436
  break;
385
437
  case '512':
386
438
  if (['ZNCZ15LM', 'QBCZ14LM', 'QBCZ15LM'].includes(model.model)) {
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "zigbee-herdsman-converters",
3
- "version": "14.0.467",
3
+ "version": "14.0.468",
4
4
  "lockfileVersion": 2,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "zigbee-herdsman-converters",
9
- "version": "14.0.467",
9
+ "version": "14.0.468",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "axios": "^0.26.1",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zigbee-herdsman-converters",
3
- "version": "14.0.467",
3
+ "version": "14.0.468",
4
4
  "description": "Collection of device converters to be used with zigbee-herdsman",
5
5
  "main": "index.js",
6
6
  "files": [