zigbee-herdsman-converters 14.0.598 → 14.0.601

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.
@@ -395,8 +395,7 @@ const converters = {
395
395
  illuminance: {
396
396
  cluster: 'msIlluminanceMeasurement',
397
397
  type: ['attributeReport', 'readResponse'],
398
- options: [exposes.options.precision('illuminance'), exposes.options.calibration('illuminance', 'percentual'),
399
- exposes.options.precision('illuminance_lux'), exposes.options.calibration('illuminance_lux', 'percentual')],
398
+ options: [exposes.options.calibration('illuminance', 'percentual'), exposes.options.calibration('illuminance_lux', 'percentual')],
400
399
  convert: (model, msg, publish, options, meta) => {
401
400
  // DEPRECATED: only return lux here (change illuminance_lux -> illuminance)
402
401
  const illuminance = msg.data['measuredValue'];
@@ -5557,13 +5556,13 @@ const converters = {
5557
5556
  result.push(exposes.options.precision('temperature'), exposes.options.calibration('temperature'));
5558
5557
  }
5559
5558
  if (definition.exposes.find((e) => e.name === 'device_temperature')) {
5560
- result.push(exposes.options.precision('device_temperature'), exposes.options.calibration('device_temperature'));
5559
+ result.push(exposes.options.calibration('device_temperature'));
5561
5560
  }
5562
5561
  if (definition.exposes.find((e) => e.name === 'illuminance')) {
5563
- result.push(exposes.options.precision('illuminance'), exposes.options.calibration('illuminance', 'percentual'));
5562
+ result.push(exposes.options.calibration('illuminance', 'percentual'));
5564
5563
  }
5565
5564
  if (definition.exposes.find((e) => e.name === 'illuminance_lux')) {
5566
- result.push(exposes.options.precision('illuminance_lux'), exposes.options.calibration('illuminance_lux', 'percentual'));
5565
+ result.push(exposes.options.calibration('illuminance_lux', 'percentual'));
5567
5566
  }
5568
5567
  return result;
5569
5568
  },
@@ -5581,7 +5580,7 @@ const converters = {
5581
5580
  result.push(exposes.options.precision('temperature'), exposes.options.calibration('temperature'));
5582
5581
  }
5583
5582
  if (definition.exposes.find((e) => e.name === 'device_temperature')) {
5584
- result.push(exposes.options.precision('device_temperature'), exposes.options.calibration('device_temperature'));
5583
+ result.push(exposes.options.calibration('device_temperature'));
5585
5584
  }
5586
5585
  return result;
5587
5586
  },
@@ -5603,10 +5602,10 @@ const converters = {
5603
5602
  result.push(exposes.options.precision('temperature'), exposes.options.calibration('temperature'));
5604
5603
  }
5605
5604
  if (definition.exposes.find((e) => e.name === 'device_temperature')) {
5606
- result.push(exposes.options.precision('device_temperature'), exposes.options.calibration('device_temperature'));
5605
+ result.push(exposes.options.calibration('device_temperature'));
5607
5606
  }
5608
5607
  if (definition.exposes.find((e) => e.name === 'illuminance')) {
5609
- result.push(exposes.options.precision('illuminance'), exposes.options.calibration('illuminance', 'percentual'));
5608
+ result.push(exposes.options.calibration('illuminance', 'percentual'));
5610
5609
  }
5611
5610
  return result;
5612
5611
  },
@@ -5686,8 +5685,7 @@ const converters = {
5686
5685
  RTCGQ11LM_illuminance: {
5687
5686
  cluster: 'msIlluminanceMeasurement',
5688
5687
  type: ['attributeReport', 'readResponse'],
5689
- options: [exposes.options.precision('illuminance'), exposes.options.calibration('illuminance', 'percentual'),
5690
- exposes.options.precision('illuminance_lux'), exposes.options.calibration('illuminance_lux', 'percentual')],
5688
+ options: [exposes.options.calibration('illuminance', 'percentual'), exposes.options.calibration('illuminance_lux', 'percentual')],
5691
5689
  convert: (model, msg, publish, options, meta) => {
5692
5690
  // also trigger movement, because there is no illuminance without movement
5693
5691
  // https://github.com/Koenkk/zigbee-herdsman-converters/issues/1925
@@ -5707,7 +5705,7 @@ const converters = {
5707
5705
  cluster: 'aqaraOpple',
5708
5706
  type: ['attributeReport', 'readResponse'],
5709
5707
  options: [exposes.options.occupancy_timeout_2(), exposes.options.no_occupancy_since_true(),
5710
- exposes.options.precision('illuminance'), exposes.options.calibration('illuminance', 'percentual')],
5708
+ exposes.options.calibration('illuminance', 'percentual')],
5711
5709
  convert: (model, msg, publish, options, meta) => {
5712
5710
  if (msg.data.hasOwnProperty('illuminance')) {
5713
5711
  // The occupancy sensor only sends a message when motion detected.
@@ -1674,7 +1674,7 @@ const converters = {
1674
1674
  manufacturerCode: 0x1ad2, disableDefaultResponse: true, disableResponse: true,
1675
1675
  reservedBits: 3, direction: 1, transactionSequenceNumber: 0xe9,
1676
1676
  });
1677
- return {state: {state_left: value.toUpperCase()}, readAfterWriteTime: 250};
1677
+ return {state: {state: value.toUpperCase()}, readAfterWriteTime: 250};
1678
1678
  } else if (postfix === 'right') {
1679
1679
  channel = 2.0;
1680
1680
  await entity.command('genLevelCtrl', 'moveToLevelWithOnOff', {level: oldstate, transtime: channel});
@@ -1683,21 +1683,21 @@ const converters = {
1683
1683
  manufacturerCode: 0x1ad2, disableDefaultResponse: true, disableResponse: true,
1684
1684
  reservedBits: 3, direction: 1, transactionSequenceNumber: 0xe9,
1685
1685
  });
1686
- return {state: {state_right: value.toUpperCase()}, readAfterWriteTime: 250};
1686
+ return {state: {state: value.toUpperCase()}, readAfterWriteTime: 250};
1687
1687
  } else if (postfix === 'bottom_right') {
1688
1688
  await entity.write('genPowerCfg', (state === 'on') ? payloadOnBottomRight : payloadOffBottomRight,
1689
1689
  {
1690
1690
  manufacturerCode: 0x1ad2, disableDefaultResponse: true, disableResponse: true,
1691
1691
  reservedBits: 3, direction: 1, transactionSequenceNumber: 0xe9,
1692
1692
  });
1693
- return {state: {state_bottom_right: value.toUpperCase()}, readAfterWriteTime: 250};
1693
+ return {state: {state: value.toUpperCase()}, readAfterWriteTime: 250};
1694
1694
  } else if (postfix === 'bottom_left') {
1695
1695
  await entity.write('genPowerCfg', (state === 'on') ? payloadOnBottomLeft : payloadOffBottomLeft,
1696
1696
  {
1697
1697
  manufacturerCode: 0x1ad2, disableDefaultResponse: true, disableResponse: true,
1698
1698
  reservedBits: 3, direction: 1, transactionSequenceNumber: 0xe9,
1699
1699
  });
1700
- return {state: {state_bottom_left: value.toUpperCase()}, readAfterWriteTime: 250};
1700
+ return {state: {state: value.toUpperCase()}, readAfterWriteTime: 250};
1701
1701
  }
1702
1702
  return {state: {state: value.toUpperCase()}, readAfterWriteTime: 250};
1703
1703
  },
@@ -2669,7 +2669,7 @@ const converters = {
2669
2669
  },
2670
2670
  },
2671
2671
  aqara_density: {
2672
- key: ['gas_density', 'smoke_density'],
2672
+ key: ['gas_density', 'smoke_density', 'smoke_density_dbm'],
2673
2673
  convertGet: async (entity, key, meta) => {
2674
2674
  await entity.read('aqaraOpple', [0x013b], manufacturerOptions.xiaomi);
2675
2675
  },
@@ -2677,8 +2677,8 @@ const converters = {
2677
2677
  JTBZ01AQA_gas_sensitivity: {
2678
2678
  key: ['gas_sensitivity'],
2679
2679
  convertSet: async (entity, key, value, meta) => {
2680
- value = value.toLowerCase();
2681
- const lookup = {'15%lel': 1, '10%lel': 2};
2680
+ value = value.toUpperCase();
2681
+ const lookup = {'15%LEL': 1, '10%LEL': 2};
2682
2682
  await entity.write('aqaraOpple', {0x010c: {value: lookup[value], type: 0x20}}, manufacturerOptions.xiaomi);
2683
2683
  return {state: {gas_sensitivity: value}};
2684
2684
  },
@@ -2692,19 +2692,24 @@ const converters = {
2692
2692
  await entity.write('aqaraOpple', {0x0127: {value: true, type: 0x10}}, manufacturerOptions.xiaomi);
2693
2693
  },
2694
2694
  },
2695
- aqara_mute_buzzer: {
2696
- key: ['mute_buzzer'],
2695
+ aqara_buzzer: {
2696
+ key: ['buzzer'],
2697
2697
  convertSet: async (entity, key, value, meta) => {
2698
- let attribute = 0x013f;
2699
- if (['JY-GZ-01AQ'].includes(meta.mapped.model)) attribute = 0x013e;
2700
- await entity.write('aqaraOpple', {[`${attribute}`]: {value: 15360, type: 0x23}}, manufacturerOptions.xiaomi);
2701
- await entity.write('aqaraOpple', {0x0126: {value: 1, type: 0x20}}, manufacturerOptions.xiaomi);
2698
+ const attribute = ['JY-GZ-01AQ'].includes(meta.mapped.model) ? 0x013e : 0x013f;
2699
+ value = (value.toLowerCase() === 'alarm') ? 15361 : 15360;
2700
+ await entity.write('aqaraOpple', {[`${attribute}`]: {value: [`${value}`], type: 0x23}}, manufacturerOptions.xiaomi);
2701
+ value = (value === 15361) ? 0 : 1;
2702
+ await entity.write('aqaraOpple', {0x0126: {value: [`${value}`], type: 0x20}}, manufacturerOptions.xiaomi);
2702
2703
  },
2703
2704
  },
2704
- aqara_mute: {
2705
- key: ['mute'],
2705
+ aqara_buzzer_manual: {
2706
+ key: ['buzzer_manual_alarm', 'buzzer_manual_mute'],
2706
2707
  convertGet: async (entity, key, meta) => {
2707
- await entity.read('aqaraOpple', [0x0126], manufacturerOptions.xiaomi);
2708
+ if (key === 'buzzer_manual_mute') {
2709
+ await entity.read('aqaraOpple', [0x0126], manufacturerOptions.xiaomi);
2710
+ } else if (key === 'buzzer_manual_alarm') {
2711
+ await entity.read('aqaraOpple', [0x013d], manufacturerOptions.xiaomi);
2712
+ }
2708
2713
  },
2709
2714
  },
2710
2715
  JYGZ01AQ_heartbeat_indicator: {
package/devices/heiman.js CHANGED
@@ -211,7 +211,7 @@ module.exports = [
211
211
  description: 'Smart remote controller',
212
212
  fromZigbee: [fz.battery, fz.command_arm, fz.command_emergency],
213
213
  toZigbee: [],
214
- exposes: [e.battery(), e.action(['emergency', 'disarm', 'arm_partial_zones', 'arm_all_zones'])],
214
+ exposes: [e.battery(), e.action(['emergency', 'disarm', 'arm_day_zones', 'arm_all_zones'])],
215
215
  configure: async (device, coordinatorEndpoint, logger) => {
216
216
  const endpoint = device.getEndpoint(1);
217
217
  await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
@@ -202,7 +202,7 @@ module.exports = [
202
202
  description: 'Power socket with power consumption monitoring',
203
203
  fromZigbee: [fz.identify, fz.on_off, fz.electrical_measurement],
204
204
  toZigbee: [tz.on_off, tz.legrand_settingAlwaysEnableLed, tz.legrand_identify],
205
- exposes: [e.switch(), e.action(['identify']), e.power(), e.voltage(), e.current()],
205
+ exposes: [e.switch(), e.action(['identify']), e.power()],
206
206
  configure: async (device, coordinatorEndpoint, logger) => {
207
207
  const endpoint = device.getEndpoint(1);
208
208
  await reporting.bind(endpoint, coordinatorEndpoint, ['genIdentify', 'genOnOff', 'haElectricalMeasurement']);
package/devices/namron.js CHANGED
@@ -3,6 +3,7 @@ const fz = {...require('../converters/fromZigbee'), legacy: require('../lib/lega
3
3
  const tz = require('../converters/toZigbee');
4
4
  const constants = require('../lib/constants');
5
5
  const reporting = require('../lib/reporting');
6
+ const globalStore = require('../lib/store');
6
7
  const extend = require('../lib/extend');
7
8
  const ea = exposes.access;
8
9
  const e = exposes.presets;
@@ -340,6 +341,25 @@ module.exports = [
340
341
  .withValueMin(20).withValueMax(60)
341
342
  .withDescription('Room temperature alarm threshold, between 20 and 60 in °C. 0 means disabled. Default: 45.'),
342
343
  ],
344
+ onEvent: async (type, data, device, options) => {
345
+ const endpoint = device.getEndpoint(1);
346
+ if (type === 'stop') {
347
+ clearInterval(globalStore.getValue(device, 'time'));
348
+ globalStore.clearValue(device, 'time');
349
+ } else if (!globalStore.hasValue(device, 'time')) {
350
+ const hours24 = 1000 * 60 * 60 * 24;
351
+ const interval = setInterval(async () => {
352
+ try {
353
+ // Device does not asks for the time with binding, therefore we write the time every 24 hours
354
+ const time = Math.round(((new Date()).getTime() - constants.OneJanuary2000) / 1000 + ((new Date())
355
+ .getTimezoneOffset() * -1) * 60);
356
+ const values = {time: time};
357
+ endpoint.write('genTime', values);
358
+ } catch (error) {/* Do nothing*/}
359
+ }, hours24);
360
+ globalStore.putValue(device, 'time', interval);
361
+ }
362
+ },
343
363
  configure: async (device, coordinatorEndpoint, logger) => {
344
364
  const endpoint = device.getEndpoint(1);
345
365
  const binds = [
@@ -474,11 +494,6 @@ module.exports = [
474
494
  reportableChange: null}],
475
495
  options);
476
496
 
477
- // Device does not asks for the time with binding, we need to write time during configure
478
- const time = Math.round(((new Date()).getTime() - constants.OneJanuary2000) / 1000);
479
- const values = {time: time};
480
- endpoint.write('genTime', values);
481
-
482
497
  // Trigger initial read
483
498
  await endpoint.read('hvacThermostat', ['systemMode', 'runningState', 'occupiedHeatingSetpoint']);
484
499
  await endpoint.read('hvacThermostat', [0x1000, 0x1001, 0x1002, 0x1003], options);
package/devices/nue_3a.js CHANGED
@@ -235,7 +235,7 @@ module.exports = [
235
235
  exposes: [e.switch().withEndpoint('left'), e.switch().withEndpoint('right')],
236
236
  meta: {multiEndpoint: true},
237
237
  endpoint: (device) => {
238
- return {left: 12, right: 11};
238
+ return {left: 11, right: 12};
239
239
  },
240
240
  },
241
241
  {
package/devices/osram.js CHANGED
@@ -107,7 +107,7 @@ module.exports = [
107
107
  model: 'AC03647',
108
108
  vendor: 'OSRAM',
109
109
  description: 'SMART+ LED CLASSIC E27 RGBW',
110
- extend: extend.ledvance.light_onoff_brightness_colortemp_color({colorTempRange: [153, 526], disableColorTempStartup: true}),
110
+ extend: extend.ledvance.light_onoff_brightness_colortemp_color({colorTempRange: [153, 526]}),
111
111
  ota: ota.ledvance,
112
112
  exposes: [e.light_brightness_colortemp_colorhs([153, 526]).removeFeature('color_temp_startup'), e.effect()],
113
113
  },
@@ -260,7 +260,7 @@ module.exports = [
260
260
  model: 'AC0363900NJ',
261
261
  vendor: 'OSRAM',
262
262
  description: 'Smart+ mini gardenpole RGBW',
263
- extend: extend.ledvance.light_onoff_brightness_colortemp_color({colorTempRange: [153, 370], disableColorTempStartup: true}),
263
+ extend: extend.ledvance.light_onoff_brightness_colortemp_color({colorTempRange: [153, 370]}),
264
264
  exposes: [e.light_brightness_colortemp_colorhs([153, 370]).removeFeature('color_temp_startup'), e.effect()],
265
265
  ota: ota.ledvance,
266
266
  },
@@ -285,7 +285,7 @@ module.exports = [
285
285
  model: 'AC08559',
286
286
  vendor: 'OSRAM',
287
287
  description: 'SMART+ Spot GU10 Multicolor',
288
- extend: extend.ledvance.light_onoff_brightness_colortemp_color({colorTempRange: [153, 526], disableColorTempStartup: true}),
288
+ extend: extend.ledvance.light_onoff_brightness_colortemp_color({colorTempRange: [153, 526]}),
289
289
  exposes: [e.light_brightness_colortemp_colorhs([153, 526]).removeFeature('color_temp_startup'), e.effect()],
290
290
  ota: ota.ledvance,
291
291
  },
@@ -255,8 +255,8 @@ module.exports = [
255
255
  model: 'CCT5010-0001',
256
256
  vendor: 'Schneider Electric',
257
257
  description: 'Micro module dimmer',
258
- fromZigbee: [fz.on_off, fz.brightness, fz.level_config, fz.wiser_lighting_ballast_configuration],
259
- toZigbee: [tz.light_onoff_brightness, tz.level_config, tz.ballast_config, tz.wiser_dimmer_mode],
258
+ fromZigbee: [...extend.light_onoff_brightness().fromZigbee, fz.wiser_lighting_ballast_configuration],
259
+ toZigbee: [...extend.light_onoff_brightness().toZigbee, tz.ballast_config, tz.wiser_dimmer_mode],
260
260
  exposes: [e.light_brightness().withLevelConfig(),
261
261
  exposes.numeric('ballast_minimum_level', ea.ALL).withValueMin(1).withValueMax(254)
262
262
  .withDescription('Specifies the minimum light output of the ballast'),
package/devices/tuya.js CHANGED
@@ -271,6 +271,13 @@ const tzLocal = {
271
271
  };
272
272
 
273
273
  const fzLocal = {
274
+ metering_skip_duplicate: {
275
+ ...fz.metering,
276
+ convert: (model, msg, publish, options, meta) => {
277
+ if (utils.hasAlreadyProcessedMessage(msg)) return;
278
+ return fz.metering.convert(model, msg, publish, options, meta);
279
+ },
280
+ },
274
281
  scenes_recall_scene_65029: {
275
282
  cluster: '65029',
276
283
  type: ['raw', 'attributeReport'],
@@ -1928,8 +1935,8 @@ module.exports = [
1928
1935
  {vendor: 'BlitzWolf', model: 'BW-SHP15'}, {vendor: 'Nous', model: 'A1Z'}, {vendor: 'BlitzWolf', model: 'BW-SHP13'},
1929
1936
  {vendor: 'MatSee Plus', model: 'PJ-ZSW01'}],
1930
1937
  ota: ota.zigbeeOTA,
1931
- fromZigbee: [fz.on_off, fz.electrical_measurement, fz.metering, fz.ignore_basic_report, fz.tuya_switch_power_outage_memory,
1932
- fz.ts011f_plug_indicator_mode, fz.ts011f_plug_child_mode],
1938
+ fromZigbee: [fz.on_off, fz.electrical_measurement, fzLocal.metering_skip_duplicate, fz.ignore_basic_report,
1939
+ fz.tuya_switch_power_outage_memory, fz.ts011f_plug_indicator_mode, fz.ts011f_plug_child_mode],
1933
1940
  toZigbee: [tz.on_off, tz.tuya_switch_power_outage_memory, tz.ts011f_plug_indicator_mode, tz.ts011f_plug_child_mode],
1934
1941
  configure: async (device, coordinatorEndpoint, logger) => {
1935
1942
  const endpoint = device.getEndpoint(1);
@@ -1982,8 +1989,8 @@ module.exports = [
1982
1989
  whiteLabel: [{vendor: 'VIKEFON', model: 'TS011F'}, {vendor: 'BlitzWolf', model: 'BW-SHP15'},
1983
1990
  {vendor: 'Avatto', model: 'MIUCOT10Z'}, {vendor: 'Neo', model: 'NAS-WR01B'}],
1984
1991
  ota: ota.zigbeeOTA,
1985
- fromZigbee: [fz.on_off, fz.electrical_measurement, fz.metering, fz.ignore_basic_report, fz.tuya_switch_power_outage_memory,
1986
- fz.ts011f_plug_indicator_mode, fz.ts011f_plug_child_mode],
1992
+ fromZigbee: [fz.on_off, fz.electrical_measurement, fzLocal.metering_skip_duplicate, fz.ignore_basic_report,
1993
+ fz.tuya_switch_power_outage_memory, fz.ts011f_plug_indicator_mode, fz.ts011f_plug_child_mode],
1987
1994
  toZigbee: [tz.on_off, tz.tuya_switch_power_outage_memory, tz.ts011f_plug_indicator_mode, tz.ts011f_plug_child_mode],
1988
1995
  configure: async (device, coordinatorEndpoint, logger) => {
1989
1996
  const endpoint = device.getEndpoint(1);
package/devices/xiaomi.js CHANGED
@@ -1305,8 +1305,8 @@ module.exports = [
1305
1305
  vendor: 'Xiaomi',
1306
1306
  description: 'Aqara smart natural gas detector',
1307
1307
  fromZigbee: [fz.aqara_opple],
1308
- toZigbee: [tz.aqara_alarm, tz.aqara_density, tz.JTBZ01AQA_gas_sensitivity, tz.aqara_selftest, tz.aqara_mute_buzzer,
1309
- tz.aqara_mute, tz.aqara_linkage_alarm, tz.JTBZ01AQA_state, tz.aqara_power_outage_count],
1308
+ toZigbee: [tz.aqara_alarm, tz.aqara_density, tz.JTBZ01AQA_gas_sensitivity, tz.aqara_selftest, tz.aqara_buzzer,
1309
+ tz.aqara_buzzer_manual, tz.aqara_linkage_alarm, tz.JTBZ01AQA_state, tz.aqara_power_outage_count],
1310
1310
  exposes: [e.gas().withAccess(ea.STATE_GET),
1311
1311
  exposes.numeric('gas_density', ea.STATE_GET).withUnit('%LEL').withDescription('Value of gas concentration'),
1312
1312
  exposes.enum('gas_sensitivity', ea.ALL, ['10%LEL', '15%LEL']).withDescription('Gas concentration value at which ' +
@@ -1314,11 +1314,16 @@ module.exports = [
1314
1314
  exposes.enum('selftest', ea.SET, ['']).withDescription('Starts the self-test process (checking the indicator ' +
1315
1315
  'light and buzzer work properly)'),
1316
1316
  exposes.binary('test', ea.STATE, true, false).withDescription('Self-test in progress'),
1317
- exposes.enum('mute_buzzer', ea.SET, ['']).withDescription('Mute the buzzer for 10 minutes (buzzer cannot be ' +
1318
- 'pre-muted, because this function only works when the alarm is triggered)'),
1319
- exposes.binary('mute', ea.STATE_GET, true, false).withDescription('Buzzer muted'),
1320
- exposes.binary('linkage_alarm', ea.ALL, true, false).withDescription('When this option is enabled and a gas leak ' +
1321
- 'is detected, other detectors with this option enabled will also sound the alarm buzzer'),
1317
+ exposes.enum('buzzer', ea.SET, ['mute', 'alarm']).withDescription('The buzzer can be muted and alarmed manually. ' +
1318
+ 'During a gas alarm, the buzzer can be manually muted for 10 minutes ("mute"), but cannot be unmuted manually ' +
1319
+ 'before this timeout expires. The buzzer cannot be pre-muted, as this function only works during a gas alarm. ' +
1320
+ 'During the absence of a gas alarm, the buzzer can be manually alarmed ("alarm") and disalarmed ("mute")'),
1321
+ exposes.binary('buzzer_manual_alarm', ea.STATE_GET, true, false).withDescription('Buzzer alarmed (manually)'),
1322
+ exposes.binary('buzzer_manual_mute', ea.STATE_GET, true, false).withDescription('Buzzer muted (manually)'),
1323
+ exposes.binary('linkage_alarm', ea.ALL, true, false).withDescription('When this option is enabled and a gas ' +
1324
+ 'alarm has occurred, then "linkage_alarm_state"=true, and when the gas alarm has ended or the buzzer has ' +
1325
+ 'been manually muted, then "linkage_alarm_state"=false'),
1326
+ exposes.binary('linkage_alarm_state', ea.STATE, true, false).withDescription('"linkage_alarm" is triggered'),
1322
1327
  exposes.binary('state', ea.STATE_GET, 'preparation', 'work').withDescription('"Preparation" or "work" ' +
1323
1328
  '(measurement of the gas concentration value and triggering of an alarm are only performed in the "work" state)'),
1324
1329
  e.power_outage_count().withAccess(ea.STATE_GET)],
@@ -1326,6 +1331,7 @@ module.exports = [
1326
1331
  const endpoint = device.getEndpoint(1);
1327
1332
  await endpoint.read('aqaraOpple', [0x013a], {manufacturerCode: 0x115f});
1328
1333
  await endpoint.read('aqaraOpple', [0x013b], {manufacturerCode: 0x115f});
1334
+ await endpoint.read('aqaraOpple', [0x013d], {manufacturerCode: 0x115f});
1329
1335
  await endpoint.read('aqaraOpple', [0x0126], {manufacturerCode: 0x115f});
1330
1336
  await endpoint.read('aqaraOpple', [0x0139], {manufacturerCode: 0x115f});
1331
1337
  await endpoint.read('aqaraOpple', [0x010c], {manufacturerCode: 0x115f});
@@ -1340,21 +1346,26 @@ module.exports = [
1340
1346
  vendor: 'Xiaomi',
1341
1347
  description: 'Aqara smart smoke detector',
1342
1348
  fromZigbee: [fz.aqara_opple, fz.battery],
1343
- toZigbee: [tz.aqara_alarm, tz.aqara_density, tz.aqara_selftest, tz.aqara_mute_buzzer, tz.aqara_mute,
1349
+ toZigbee: [tz.aqara_alarm, tz.aqara_density, tz.aqara_selftest, tz.aqara_buzzer, tz.aqara_buzzer_manual,
1344
1350
  tz.JYGZ01AQ_heartbeat_indicator, tz.aqara_linkage_alarm],
1345
1351
  exposes: [e.smoke().withAccess(ea.STATE_GET),
1346
1352
  exposes.numeric('smoke_density', ea.STATE_GET).withDescription('Value of smoke concentration'),
1347
- exposes.numeric('smoke_density_dbm', ea.STATE).withUnit('dB/m').withDescription('Value of smoke concentration in dB/m'),
1353
+ exposes.numeric('smoke_density_dbm', ea.STATE_GET).withUnit('dB/m').withDescription('Value of smoke concentration in dB/m'),
1348
1354
  exposes.enum('selftest', ea.SET, ['']).withDescription('Starts the self-test process (checking the indicator ' +
1349
1355
  'light and buzzer work properly)'),
1350
1356
  exposes.binary('test', ea.STATE, true, false).withDescription('Self-test in progress'),
1351
- exposes.enum('mute_buzzer', ea.SET, ['']).withDescription('Mute the buzzer for 80 seconds (buzzer cannot be ' +
1352
- 'pre-muted, because this function only works when the alarm is triggered)'),
1353
- exposes.binary('mute', ea.STATE_GET, true, false).withDescription('Buzzer muted'),
1357
+ exposes.enum('buzzer', ea.SET, ['mute', 'alarm']).withDescription('The buzzer can be muted and alarmed manually. ' +
1358
+ 'During a smoke alarm, the buzzer can be manually muted for 80 seconds ("mute") and unmuted ("alarm"). ' +
1359
+ 'The buzzer cannot be pre-muted, as this function only works during a smoke alarm. ' +
1360
+ 'During the absence of a smoke alarm, the buzzer can be manually alarmed ("alarm") and disalarmed ("mute")'),
1361
+ exposes.binary('buzzer_manual_alarm', ea.STATE_GET, true, false).withDescription('Buzzer alarmed (manually)'),
1362
+ exposes.binary('buzzer_manual_mute', ea.STATE_GET, true, false).withDescription('Buzzer muted (manually)'),
1354
1363
  exposes.binary('heartbeat_indicator', ea.ALL, true, false).withDescription('When this option is enabled then in ' +
1355
1364
  'the normal monitoring state, the green indicator light flashes every 60 seconds'),
1356
1365
  exposes.binary('linkage_alarm', ea.ALL, true, false).withDescription('When this option is enabled and a smoke ' +
1357
- 'is detected, other detectors with this option enabled will also sound the alarm buzzer'),
1366
+ 'alarm has occurred, then "linkage_alarm_state"=true, and when the smoke alarm has ended or the buzzer has ' +
1367
+ 'been manually muted, then "linkage_alarm_state"=false'),
1368
+ exposes.binary('linkage_alarm_state', ea.STATE, true, false).withDescription('"linkage_alarm" is triggered'),
1358
1369
  e.battery(), e.battery_voltage(), e.power_outage_count(false)],
1359
1370
  meta: {battery: {voltageToPercentage: '3V_2850_3200'}},
1360
1371
  configure: async (device, coordinatorEndpoint, logger) => {
@@ -1363,6 +1374,7 @@ module.exports = [
1363
1374
  await endpoint.read('aqaraOpple', [0x013a], {manufacturerCode: 0x115f});
1364
1375
  await endpoint.read('aqaraOpple', [0x013b], {manufacturerCode: 0x115f});
1365
1376
  await endpoint.read('aqaraOpple', [0x013c], {manufacturerCode: 0x115f});
1377
+ await endpoint.read('aqaraOpple', [0x013d], {manufacturerCode: 0x115f});
1366
1378
  await endpoint.read('aqaraOpple', [0x0126], {manufacturerCode: 0x115f});
1367
1379
  await endpoint.read('aqaraOpple', [0x014b], {manufacturerCode: 0x115f});
1368
1380
  },
package/lib/extend.js CHANGED
@@ -125,17 +125,19 @@ const extend = {
125
125
  ...extend.light_onoff_brightness(options),
126
126
  toZigbee: extend.light_onoff_brightness(options).toZigbee.concat([tz.ledvance_commands]),
127
127
  }),
128
- light_onoff_brightness_colortemp: (options={disableColorTempStartup: true}) => ({
129
- ...extend.light_onoff_brightness_colortemp(options),
130
- toZigbee: extend.light_onoff_brightness_colortemp(options).toZigbee.concat([tz.ledvance_commands]),
128
+ light_onoff_brightness_colortemp: (options={}) => ({
129
+ ...extend.light_onoff_brightness_colortemp({disableColorTempStartup: true, ...options}),
130
+ toZigbee: extend.light_onoff_brightness_colortemp({disableColorTempStartup: true, ...options})
131
+ .toZigbee.concat([tz.ledvance_commands]),
131
132
  }),
132
133
  light_onoff_brightness_color: (options={}) => ({
133
134
  ...extend.light_onoff_brightness_color({supportsHS: true, ...options}),
134
135
  toZigbee: extend.light_onoff_brightness_color({supportsHS: true, ...options}).toZigbee.concat([tz.ledvance_commands]),
135
136
  }),
136
- light_onoff_brightness_colortemp_color: (options={disableColorTempStartup: true}) => ({
137
- ...extend.light_onoff_brightness_colortemp_color({supportsHS: true, ...options}),
138
- toZigbee: extend.light_onoff_brightness_colortemp_color({supportsHS: true, ...options}).toZigbee.concat([tz.ledvance_commands]),
137
+ light_onoff_brightness_colortemp_color: (options={}) => ({
138
+ ...extend.light_onoff_brightness_colortemp_color({supportsHS: true, disableColorTempStartup: true, ...options}),
139
+ toZigbee: extend.light_onoff_brightness_colortemp_color({supportsHS: true, disableColorTempStartup: true, ...options})
140
+ .toZigbee.concat([tz.ledvance_commands]),
139
141
  }),
140
142
  };
141
143
  }
package/lib/xiaomi.js CHANGED
@@ -392,7 +392,7 @@ const numericAttributes2Payload = (msg, meta, model, options, dataObject) => {
392
392
  break;
393
393
  case '163':
394
394
  if (['JT-BZ-01AQ/A', 'JY-GZ-01AQ'].includes(model.model)) {
395
- payload.mute = value === 1;
395
+ payload.buzzer_manual_mute = value === 1;
396
396
  }
397
397
  break;
398
398
  case '164':
@@ -437,7 +437,7 @@ const numericAttributes2Payload = (msg, meta, model, options, dataObject) => {
437
437
  break;
438
438
  case '294':
439
439
  if (['JT-BZ-01AQ/A', 'JY-GZ-01AQ'].includes(model.model)) {
440
- payload.mute = value === 1;
440
+ payload.buzzer_manual_mute = value === 1;
441
441
  }
442
442
  break;
443
443
  case '295':
@@ -471,6 +471,11 @@ const numericAttributes2Payload = (msg, meta, model, options, dataObject) => {
471
471
  payload.heartbeat_indicator = value === 1;
472
472
  }
473
473
  break;
474
+ case '317':
475
+ if (['JT-BZ-01AQ/A', 'JY-GZ-01AQ'].includes(model.model)) {
476
+ payload.buzzer_manual_alarm = value === 1;
477
+ }
478
+ break;
474
479
  case '322':
475
480
  if (['RTCZCGQ11LM'].includes(model.model)) {
476
481
  payload.presence = {0: false, 1: true, 255: null}[value];
@@ -497,6 +502,11 @@ const numericAttributes2Payload = (msg, meta, model, options, dataObject) => {
497
502
  payload.linkage_alarm = value === 1;
498
503
  }
499
504
  break;
505
+ case '332':
506
+ if (['JT-BZ-01AQ/A', 'JY-GZ-01AQ'].includes(model.model)) {
507
+ payload.linkage_alarm_state = value === 1;
508
+ }
509
+ break;
500
510
  case '338':
501
511
  if (['RTCGQ14LM'].includes(model.model)) {
502
512
  payload.trigger_indicator = value === 1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zigbee-herdsman-converters",
3
- "version": "14.0.598",
3
+ "version": "14.0.601",
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.47"
41
+ "zigbee-herdsman": "^0.14.48"
42
42
  },
43
43
  "devDependencies": {
44
44
  "eslint": "*",