zigbee-herdsman-converters 15.0.71 → 15.0.72

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.
package/devices/gs.js CHANGED
@@ -24,6 +24,6 @@ module.exports = [
24
24
  model: 'BRHM8E27W70-I1',
25
25
  vendor: 'GS',
26
26
  description: 'Smart dimmable, RGB + white (E27 & B22)',
27
- extend: extend.light_onoff_brightness_color(),
27
+ extend: extend.light_onoff_brightness_colortemp_color(),
28
28
  },
29
29
  ];
package/devices/heiman.js CHANGED
@@ -395,9 +395,9 @@ module.exports = [
395
395
  model: 'SGMHM-I1',
396
396
  vendor: 'HEIMAN',
397
397
  description: 'Combustible gas sensor',
398
- fromZigbee: [fz.ias_gas_alarm_1],
398
+ fromZigbee: [fz.ias_gas_alarm_2],
399
399
  toZigbee: [],
400
- exposes: [e.gas(), e.battery_low(), e.tamper()],
400
+ exposes: [e.gas()],
401
401
  },
402
402
  {
403
403
  zigbeeModel: ['STHM-I1H'],
package/devices/lidl.js CHANGED
@@ -193,8 +193,8 @@ const tzLocal = {
193
193
  // Load current state or defaults
194
194
  const newSettings = {
195
195
  brightness: meta.state.brightness ?? 254, // full brightness
196
- hue: (meta.state.color ?? {}).h ?? 0, // red
197
- saturation: (meta.state.color ?? {}).s ?? 100, // full saturation
196
+ hue: (meta.state.color ?? {}).hue ?? 0, // red
197
+ saturation: (meta.state.color ?? {}).saturation ?? 100, // full saturation
198
198
  };
199
199
 
200
200
  // Apply changes
@@ -217,8 +217,8 @@ const tzLocal = {
217
217
  newSettings.saturation = color.saturation;
218
218
 
219
219
  newState.color = {
220
- h: color.hue,
221
- s: color.saturation,
220
+ hue: color.hue,
221
+ saturation: color.saturation,
222
222
  };
223
223
  }
224
224
 
@@ -234,6 +234,10 @@ const tzLocal = {
234
234
  }
235
235
  }
236
236
 
237
+ // If we're in white mode, calculate a matching display color for the set color temperature. This also kind
238
+ // of works in the other direction.
239
+ Object.assign(newState, libColor.syncColorState(newState, meta.state, entity, meta.options, meta.logger));
240
+
237
241
  return {state: newState};
238
242
  },
239
243
  convertGet: async (entity, key, meta) => {
package/devices/lixee.js CHANGED
@@ -11,6 +11,73 @@ const e = exposes.presets;
11
11
  const utils = require('../lib/utils');
12
12
  const ota = require('../lib/ota');
13
13
  const {Buffer} = require('buffer');
14
+ const herdsman = require('zigbee-herdsman');
15
+
16
+
17
+ /* Start ZiPulses */
18
+
19
+ const unitsZiPulses = [
20
+ 'kWh',
21
+ 'm3',
22
+ 'ft3',
23
+ 'ccf',
24
+ 'US gl',
25
+ 'IMP gl',
26
+ 'BTUs',
27
+ 'L (litre)',
28
+ 'kPA (jauge)',
29
+ 'kPA (absolu)',
30
+ 'kPA (absolu)',
31
+ 'sans unité',
32
+ 'MJ',
33
+ 'kVar',
34
+ ];
35
+
36
+ const tzSeMetering = {
37
+ key: ['divisor', 'multiplier', 'unitOfMeasure'],
38
+ convertSet: async (entity, key, value, meta) => {
39
+ if (key === 'unitOfMeasure') {
40
+ const val = unitsZiPulses.indexOf(value);
41
+ const payload = {768: {value: val, type: herdsman.Zcl.DataType.enum8}};
42
+ await entity.write('seMetering', payload);
43
+ await entity.read('seMetering', [key]);
44
+ return {state: {'unitOfMeasure': value}};
45
+ } else {
46
+ await entity.write('seMetering', {
47
+ [key]: value,
48
+ });
49
+ }
50
+
51
+ return {state: {[key]: value}};
52
+ },
53
+ // convertGet: async (entity, key, meta) => {
54
+ // await entity.read('seMetering', [key]);
55
+ // },
56
+ };
57
+
58
+
59
+ const fzZiPulses = {
60
+ cluster: 'seMetering',
61
+ type: ['attributeReport', 'readResponse'],
62
+ convert: (model, msg, publish, options, meta) => {
63
+ const payload = {};
64
+ if (msg.data.hasOwnProperty('multiplier')) {
65
+ payload['multiplier'] = msg.data['multiplier'];
66
+ }
67
+ if (msg.data.hasOwnProperty('divisor')) {
68
+ payload['divisor'] = msg.data['divisor'];
69
+ }
70
+ if (msg.data.hasOwnProperty('unitOfMeasure')) {
71
+ const val = msg.data['unitOfMeasure'];
72
+ payload['unitOfMeasure'] = unitsZiPulses[val];
73
+ }
74
+
75
+ return payload;
76
+ },
77
+ };
78
+
79
+
80
+ /* End ZiPulses */
14
81
 
15
82
  const fzLocal = {
16
83
  lixee_ha_electrical_measurement: {
@@ -555,137 +622,158 @@ function getCurrentConfig(device, options, logger=console) {
555
622
 
556
623
  return myExpose;
557
624
  }
558
- const definition = {
559
- zigbeeModel: ['ZLinky_TIC', 'ZLinky_TIC\u0000'],
560
- model: 'ZLinky_TIC',
561
- vendor: 'LiXee',
562
- description: 'Lixee ZLinky',
563
- fromZigbee: [fzLocal.lixee_metering, fz.meter_identification, fzLocal.lixee_ha_electrical_measurement, fzLocal.lixee_private_fz],
564
- toZigbee: [],
565
- exposes: (device, options) => {
566
- // docs generation
567
- let exposes;
568
- if (device == null && options == null) {
569
- exposes = exposedData.map((e) => e.exposes)
570
- .filter((value, index, self) =>
571
- index === self.findIndex((t) => (
572
- t.property === value.property // Remove duplicates
573
- )),
574
- );
575
- } else {
576
- exposes = getCurrentConfig(device, options).map((e) => e.exposes);
577
- }
625
+ module.exports = [
626
+ {
627
+ zigbeeModel: ['ZLinky_TIC', 'ZLinky_TIC\u0000'],
628
+ model: 'ZLinky_TIC',
629
+ vendor: 'LiXee',
630
+ description: 'Lixee ZLinky',
631
+ fromZigbee: [fzLocal.lixee_metering, fz.meter_identification, fzLocal.lixee_ha_electrical_measurement, fzLocal.lixee_private_fz],
632
+ toZigbee: [],
633
+ exposes: (device, options) => {
634
+ // docs generation
635
+ let exposes;
636
+ if (device == null && options == null) {
637
+ exposes = exposedData.map((e) => e.exposes)
638
+ .filter((value, index, self) =>
639
+ index === self.findIndex((t) => (
640
+ t.property === value.property // Remove duplicates
641
+ )),
642
+ );
643
+ } else {
644
+ exposes = getCurrentConfig(device, options).map((e) => e.exposes);
645
+ }
578
646
 
579
- exposes.push(e.linkquality());
580
- return exposes;
581
- },
582
- options: [
583
- exposes.options.measurement_poll_interval(),
584
- exposes.enum(`linky_mode`, ea.SET, ['auto', linkyModeDef.legacy, linkyModeDef.standard])
585
- .withDescription(`Counter with TIC in mode standard or historique. May require restart (default: auto)`),
586
- exposes.enum(`energy_phase`, ea.SET, ['auto', linkyPhaseDef.single, linkyPhaseDef.three])
587
- .withDescription(`Power with single or three phase. May require restart (default: auto)`),
588
- exposes.enum(`production`, ea.SET, ['auto', 'true', 'false']).withDescription(`If you produce energy back to the grid (works ONLY when linky_mode: ${linkyModeDef.standard}, default: auto)`),
589
- exposes.enum(`tarif`, ea.SET, [...Object.entries(tarifsDef).map(( [k, v] ) => (v.fname)), 'auto'])
590
- .withDescription(`Overrides the automatic current tarif. This option will exclude unnecesary attributes. Open a issue to support more of them. Default: auto`),
591
- exposes.options.precision(`kWh`),
592
- exposes.numeric(`measurement_poll_chunk`, ea.SET).withValueMin(1).withDescription(`During the poll, request multiple exposes to the Zlinky at once for reducing Zigbee network overload. Too much request at once could exceed device limit. Requieres Z2M restart. Default: 1`),
593
- exposes.text(`tic_command_whitelist`, ea.SET).withDescription(`List of TIC commands to be exposed (separated by comma). Reconfigure device after change. Default: all`),
594
- ],
595
- configure: async (device, coordinatorEndpoint, logger, options) => {
596
- const endpoint = device.getEndpoint(1);
597
-
598
- await reporting.bind(endpoint, coordinatorEndpoint, [
599
- clustersDef._0x0702, /* seMetering */
600
- clustersDef._0x0B01, /* haMeterIdentification */
601
- clustersDef._0x0B04, /* haElectricalMeasurement */
602
- clustersDef._0xFF66, /* liXeePrivate */
603
- ]);
604
-
605
- await endpoint.read('liXeePrivate', ['linkyMode', 'currentTarif'], {manufacturerCode: null})
606
- .catch((e) => {
607
- // https://github.com/Koenkk/zigbee2mqtt/issues/11674
608
- logger.warn(`Failed to read zigbee attributes: ${e}`);
609
- });
647
+ exposes.push(e.linkquality());
648
+ return exposes;
649
+ },
650
+ options: [
651
+ exposes.options.measurement_poll_interval(),
652
+ exposes.enum(`linky_mode`, ea.SET, ['auto', linkyModeDef.legacy, linkyModeDef.standard])
653
+ .withDescription(`Counter with TIC in mode standard or historique. May require restart (default: auto)`),
654
+ exposes.enum(`energy_phase`, ea.SET, ['auto', linkyPhaseDef.single, linkyPhaseDef.three])
655
+ .withDescription(`Power with single or three phase. May require restart (default: auto)`),
656
+ exposes.enum(`production`, ea.SET, ['auto', 'true', 'false']).withDescription(`If you produce energy back to the grid (works ONLY when linky_mode: ${linkyModeDef.standard}, default: auto)`),
657
+ exposes.enum(`tarif`, ea.SET, [...Object.entries(tarifsDef).map(( [k, v] ) => (v.fname)), 'auto'])
658
+ .withDescription(`Overrides the automatic current tarif. This option will exclude unnecesary attributes. Open a issue to support more of them. Default: auto`),
659
+ exposes.options.precision(`kWh`),
660
+ exposes.numeric(`measurement_poll_chunk`, ea.SET).withValueMin(1).withDescription(`During the poll, request multiple exposes to the Zlinky at once for reducing Zigbee network overload. Too much request at once could exceed device limit. Requieres Z2M restart. Default: 1`),
661
+ exposes.text(`tic_command_whitelist`, ea.SET).withDescription(`List of TIC commands to be exposed (separated by comma). Reconfigure device after change. Default: all`),
662
+ ],
663
+ configure: async (device, coordinatorEndpoint, logger, options) => {
664
+ const endpoint = device.getEndpoint(1);
665
+
666
+ await reporting.bind(endpoint, coordinatorEndpoint, [
667
+ clustersDef._0x0702, /* seMetering */
668
+ clustersDef._0x0B01, /* haMeterIdentification */
669
+ clustersDef._0x0B04, /* haElectricalMeasurement */
670
+ clustersDef._0xFF66, /* liXeePrivate */
671
+ ]);
672
+
673
+ await endpoint.read('liXeePrivate', ['linkyMode', 'currentTarif'], {manufacturerCode: null})
674
+ .catch((e) => {
675
+ // https://github.com/Koenkk/zigbee2mqtt/issues/11674
676
+ logger.warn(`Failed to read zigbee attributes: ${e}`);
677
+ });
610
678
 
611
- const configReportings = [];
612
- const suscribeNew = getCurrentConfig(device, options, logger).filter((e) => e.reportable);
679
+ const configReportings = [];
680
+ const suscribeNew = getCurrentConfig(device, options, logger).filter((e) => e.reportable);
613
681
 
614
- const unsuscribe = endpoint.configuredReportings
615
- .filter((e) => !suscribeNew.some((r) => e.cluster.name == r.cluster && e.attribute.name == r.att));
616
- // Unsuscribe reports that doesn't correspond with the current config
617
- (await Promise.allSettled(unsuscribe.map((e) => endpoint.configureReporting(e.cluster.name, reporting.payload(e.attribute.name, e.minimumReportInterval, 65535, e.reportableChange), {manufacturerCode: null}))))
618
- .filter((e) => e.status == 'rejected')
619
- .forEach((e) => {
620
- throw e.reason;
621
- });
682
+ const unsuscribe = endpoint.configuredReportings
683
+ .filter((e) => !suscribeNew.some((r) => e.cluster.name == r.cluster && e.attribute.name == r.att));
684
+ // Unsuscribe reports that doesn't correspond with the current config
685
+ (await Promise.allSettled(unsuscribe.map((e) => endpoint.configureReporting(e.cluster.name, reporting.payload(e.attribute.name, e.minimumReportInterval, 65535, e.reportableChange), {manufacturerCode: null}))))
686
+ .filter((e) => e.status == 'rejected')
687
+ .forEach((e) => {
688
+ throw e.reason;
689
+ });
622
690
 
623
- for (const e of suscribeNew) {
624
- let params = {
625
- att: e.att,
626
- min: repInterval.MINUTE,
627
- max: repInterval.MINUTES_15,
628
- change: 1,
629
- };
630
- // Override reportings
631
- if (e.hasOwnProperty('report')) {
632
- params = {...params, ...e.report};
691
+ for (const e of suscribeNew) {
692
+ let params = {
693
+ att: e.att,
694
+ min: repInterval.MINUTE,
695
+ max: repInterval.MINUTES_15,
696
+ change: 1,
697
+ };
698
+ // Override reportings
699
+ if (e.hasOwnProperty('report')) {
700
+ params = {...params, ...e.report};
701
+ }
702
+ configReportings.push(endpoint
703
+ .configureReporting(
704
+ e.cluster, reporting.payload(params.att, params.min, params.max, params.change),
705
+ {manufacturerCode: null}),
706
+ );
633
707
  }
634
- configReportings.push(endpoint
635
- .configureReporting(
636
- e.cluster, reporting.payload(params.att, params.min, params.max, params.change),
637
- {manufacturerCode: null}),
638
- );
639
- }
640
- (await Promise.allSettled(configReportings))
641
- .filter((e) => e.status == 'rejected')
642
- .forEach((e) => {
643
- throw e.reason;
644
- });
645
- },
646
- ota: ota.lixee,
647
- onEvent: async (type, data, device, options) => {
648
- const endpoint = device.getEndpoint(1);
649
- if (type === 'start') {
650
- endpoint.read('liXeePrivate', ['linkyMode', 'currentTarif'], {manufacturerCode: null})
651
- .catch((e) => {
652
- // https://github.com/Koenkk/zigbee2mqtt/issues/11674
653
- console.warn(`Failed to read zigbee attributes: ${e}`);
708
+ (await Promise.allSettled(configReportings))
709
+ .filter((e) => e.status == 'rejected')
710
+ .forEach((e) => {
711
+ throw e.reason;
654
712
  });
655
- } else if (type === 'stop') {
656
- clearInterval(globalStore.getValue(device, 'interval'));
657
- globalStore.clearValue(device, 'interval');
658
- } else if (!globalStore.hasValue(device, 'interval')) {
659
- const seconds = options && options.measurement_poll_interval ? options.measurement_poll_interval : 60;
660
- const measurement_poll_chunk = options && options.measurement_poll_chunk ? options.measurement_poll_chunk : 1;
661
-
662
- const interval = setInterval(async () => {
663
- const currentExposes = getCurrentConfig(device, options)
664
- .filter((e) => !endpoint.configuredReportings.some((r) => r.cluster.name == e.cluster && r.attribute.name == e.att));
665
-
666
- for (const key in clustersDef) {
667
- if (Object.hasOwnProperty.call(clustersDef, key)) {
668
- const cluster = clustersDef[key];
669
-
670
- const targ = currentExposes.filter((e)=> e.cluster == cluster).map((e)=> e.att);
671
- if (targ.length) {
672
- let i; let j;
673
- // Split array by chunks
674
- for (i = 0, j = targ.length; i < j; i += measurement_poll_chunk) {
675
- await endpoint
676
- .read(cluster, targ.slice(i, i + measurement_poll_chunk), {manufacturerCode: null})
677
- .catch((e) => {
678
- // https://github.com/Koenkk/zigbee2mqtt/issues/11674
679
- console.warn(`Failed to read zigbee attributes: ${e}`);
680
- });
713
+ },
714
+ ota: ota.lixee,
715
+ onEvent: async (type, data, device, options) => {
716
+ const endpoint = device.getEndpoint(1);
717
+ if (type === 'start') {
718
+ endpoint.read('liXeePrivate', ['linkyMode', 'currentTarif'], {manufacturerCode: null})
719
+ .catch((e) => {
720
+ // https://github.com/Koenkk/zigbee2mqtt/issues/11674
721
+ console.warn(`Failed to read zigbee attributes: ${e}`);
722
+ });
723
+ } else if (type === 'stop') {
724
+ clearInterval(globalStore.getValue(device, 'interval'));
725
+ globalStore.clearValue(device, 'interval');
726
+ } else if (!globalStore.hasValue(device, 'interval')) {
727
+ const seconds = options && options.measurement_poll_interval ? options.measurement_poll_interval : 60;
728
+ const measurement_poll_chunk = options && options.measurement_poll_chunk ? options.measurement_poll_chunk : 1;
729
+
730
+ const interval = setInterval(async () => {
731
+ const currentExposes = getCurrentConfig(device, options)
732
+ .filter((e) => !endpoint.configuredReportings.some((r) => r.cluster.name == e.cluster && r.attribute.name == e.att));
733
+
734
+ for (const key in clustersDef) {
735
+ if (Object.hasOwnProperty.call(clustersDef, key)) {
736
+ const cluster = clustersDef[key];
737
+
738
+ const targ = currentExposes.filter((e)=> e.cluster == cluster).map((e)=> e.att);
739
+ if (targ.length) {
740
+ let i; let j;
741
+ // Split array by chunks
742
+ for (i = 0, j = targ.length; i < j; i += measurement_poll_chunk) {
743
+ await endpoint
744
+ .read(cluster, targ.slice(i, i + measurement_poll_chunk), {manufacturerCode: null})
745
+ .catch((e) => {
746
+ // https://github.com/Koenkk/zigbee2mqtt/issues/11674
747
+ console.warn(`Failed to read zigbee attributes: ${e}`);
748
+ });
749
+ }
681
750
  }
682
751
  }
683
752
  }
684
- }
685
- }, seconds * 1000);
686
- globalStore.putValue(device, 'interval', interval);
687
- }
753
+ }, seconds * 1000);
754
+ globalStore.putValue(device, 'interval', interval);
755
+ }
756
+ },
688
757
  },
689
- };
690
758
 
691
- module.exports = [definition];
759
+ {
760
+ zigbeeModel: ['ZiPulses'],
761
+ model: 'ZiPulses',
762
+ vendor: 'LiXee',
763
+ description: 'Lixee ZiPulses',
764
+ fromZigbee: [fz.battery, fz.temperature, fz.metering, fzZiPulses],
765
+ toZigbee: [tzSeMetering],
766
+ exposes: [e.battery_voltage(), e.temperature(),
767
+ exposes.numeric('multiplier', ea.STATE_SET).withValueMin(1).withValueMax(1000).withDescription('It is necessary to press the link button to update'),
768
+ exposes.numeric('divisor', ea.STATE_SET).withValueMin(1).withValueMax(1000).withDescription('It is necessary to press the link button to update'),
769
+ exposes.enum('unitOfMeasure', ea.STATE_SET, unitsZiPulses).withDescription('It is necessary to press the link button to update'),
770
+ exposes.numeric('energy', ea.STATE),
771
+ ],
772
+ configure: async (device, coordinatorEndpoint, logger) => {
773
+ const endpoint = device.getEndpoint(1);
774
+ const binds = ['genPowerCfg', 'seMetering', 'msTemperatureMeasurement'];
775
+ await reporting.bind(endpoint, coordinatorEndpoint, binds);
776
+ await endpoint.read('seMetering', ['divisor', 'unitOfMeasure', 'multiplier']);
777
+ },
778
+ },
779
+ ];
@@ -2480,7 +2480,7 @@ module.exports = [
2480
2480
  extend: philips.extend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
2481
2481
  },
2482
2482
  {
2483
- zigbeeModel: ['5309331P6', '5309330P6', '929003046301_03', '929003046301_02'],
2483
+ zigbeeModel: ['5309331P6', '5309330P6', '929003046301_03', '929003046301_02', '929003046301_01'],
2484
2484
  model: '5309331P6',
2485
2485
  vendor: 'Philips',
2486
2486
  description: 'Hue White ambiance Runner triple spotlight',
package/devices/qoto.js CHANGED
@@ -89,7 +89,7 @@ const tzLocal = {
89
89
 
90
90
  module.exports = [
91
91
  {
92
- fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_arge1ptm'}],
92
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE200_arge1ptm', '_TZE200_anv5ujhv']),
93
93
  model: 'QT-05M',
94
94
  vendor: 'QOTO',
95
95
  description: 'Solar powered garden watering timer',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zigbee-herdsman-converters",
3
- "version": "15.0.71",
3
+ "version": "15.0.72",
4
4
  "description": "Collection of device converters to be used with zigbee-herdsman",
5
5
  "main": "index.js",
6
6
  "files": [