zigbee-herdsman-converters 15.0.0 → 15.0.2

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/README.md CHANGED
@@ -23,6 +23,8 @@ If any of those commands finish with an error your PR won't pass the tests and w
23
23
 
24
24
  ## Documentation of definition meta property
25
25
  - `multiEndpoint`: enables the multi endpoint functionallity in e.g. fromZigbee.on_off, example: normally this converter would return {"state": "OFF"}, when multiEndpoint is enabled the 'endpoint' method of the device definition will be called to determine the endpoint name which is then used as key e.g. {"state_left": "OFF"}. Only needed when device sends the same attribute from multiple endpoints. (default: false)
26
+ - `multiEndpointSkip`: array of attributes to not suffix with the endpoint name
27
+ - `multiEndpointEnforce`: enforce a certain endpoint for an attribute, e.g. {"power": 4} see utils.enforceEndpoint()
26
28
  - `disableDefaultResponse`: used by toZigbee converters to disable the default response of some devices as they don't provide one. (default: false)
27
29
  - `applyRedFix`: see toZigbee.light_color (default: false)
28
30
  - `enhancedHue`: see toZigbee.light_color (default: true)
@@ -1526,13 +1526,13 @@ const converters = {
1526
1526
  metering_power: {
1527
1527
  key: ['power'],
1528
1528
  convertGet: async (entity, key, meta) => {
1529
- await entity.read('seMetering', ['instantaneousDemand']);
1529
+ await utils.enforceEndpoint(entity, key, meta).read('seMetering', ['instantaneousDemand']);
1530
1530
  },
1531
1531
  },
1532
1532
  currentsummdelivered: {
1533
1533
  key: ['energy'],
1534
1534
  convertGet: async (entity, key, meta) => {
1535
- await entity.read('seMetering', ['currentSummDelivered']);
1535
+ await utils.enforceEndpoint(entity, key, meta).read('seMetering', ['currentSummDelivered']);
1536
1536
  },
1537
1537
  },
1538
1538
  frequency: {
@@ -5515,6 +5515,9 @@ const converters = {
5515
5515
  } else if (attribute === 'brightness') {
5516
5516
  extensionfieldsets.push({'clstId': 8, 'len': 1, 'extField': [val]});
5517
5517
  state['brightness'] = val;
5518
+ } else if (attribute === 'position') {
5519
+ extensionfieldsets.push({'clstId': 258, 'len': 1, 'extField': [val]});
5520
+ state['position'] = val;
5518
5521
  } else if (attribute === 'color_temp') {
5519
5522
  /*
5520
5523
  * ZCL version 7 added support for ColorTemperatureMireds
@@ -56,14 +56,28 @@ module.exports = [
56
56
  'to occupied_heating_setpoint it does not trigger an aggressive response from the actuator. ' +
57
57
  '(more suitable for scheduled changes)'),
58
58
  exposes.numeric('external_measured_room_sensor', ea.ALL)
59
- .withDescription('If `radiator_covered` is `true`: Set at maximum 30 minutes interval but not more often than every ' +
60
- '5 minutes and 0.1 degrees difference. Resets every 35 minutes to standard. If `radiator_covered` is `false`: ' +
61
- 'Set at maximum 3 hours interval but not more often than every 30 minutes and 0.1 degrees difference. ' +
62
- 'Resets every 3 hours to standard. Value 21C = 2100 (-8000=undefined).')
59
+ .withDescription('The temperature sensor of the TRV is due to its design relatively close to the heat source ' +
60
+ '(i.e. the hot water in the radiator). Thus there are situations where the `local_temperature` measured by the ' +
61
+ 'TRV is not accurate enough: If the radiator is covered behind curtains or furniture, if the room is rather big, or ' +
62
+ 'if the radiator itself is big and the flow temperature is high, then the temperature in the room may easily diverge ' +
63
+ 'from the `local_temperature` measured by the TRV by 5°C to 8°C. In this case you might choose to use an external ' +
64
+ 'room sensor and send the measured value of the external room sensor to the `External_measured_room_sensor` property.' +
65
+ 'The way the TRV operates on the `External_measured_room_sensor` depends on the setting of the `Radiator_covered` ' +
66
+ 'property: If `Radiator_covered` is `true` (Auto Offset Mode): You *must* set the `External_measured_room_sensor` ' +
67
+ 'property *at least* every 3 hours. After 3 hours the TRV disables this function and resets the value of the ' +
68
+ '`External_measured_room_sensor` property to -8000 (disabled). You *should* set the `External_measured_room_sensor` ' +
69
+ 'property *at most* every 30 minutes or every 0.1K change in measured room temperature.' +
70
+ 'If `Radiator_covered` is `false` (Room Sensor Mode): You *must* set the `External_measured_room_sensor` property at ' +
71
+ 'least every 30 minutes. After 35 minutes the TRV disables this function and resets the value of the ' +
72
+ '`External_measured_room_sensor` property to -8000 (disabled). You *should* set the `External_measured_room_sensor` ' +
73
+ 'property *at most* every 5 minutes or every 0.1K change in measured room temperature.')
63
74
  .withValueMin(-8000).withValueMax(3500),
64
75
  exposes.binary('radiator_covered', ea.ALL, true, false)
65
- .withDescription('Set if the TRV should solely rely on external_measured_room_sensor or operate in offset mode. ' +
66
- '`false` = Auto Offset Mode or `true` = Room Sensor Mode'),
76
+ .withDescription('Controls whether the TRV should solely rely on an external room sensor or operate in offset mode. ' +
77
+ '`false` = Auto Offset Mode (use this e.g. for exposed radiators) or `true` = Room Sensor Mode (use this e.g. for ' +
78
+ 'covered radiators). Please note that this flag only controls how the TRV operates on the value of ' +
79
+ '`External_measured_room_sensor`; only setting this flag without setting the `External_measured_room_sensor` ' +
80
+ 'has no (noticable?) effect.'),
67
81
  exposes.binary('window_open_feature', ea.ALL, true, false)
68
82
  .withDescription('Whether or not the window open feature is enabled'),
69
83
  exposes.numeric('window_open_internal', ea.STATE_GET).withValueMin(0).withValueMax(4)
@@ -20,6 +20,21 @@ module.exports = [
20
20
  device.skipDefaultResponse = true;
21
21
  },
22
22
  },
23
+ {
24
+ zigbeeModel: ['SA-030-1'],
25
+ model: 'SA-030-1',
26
+ vendor: 'eWeLink',
27
+ description: 'Zigbee 3.0 smart plug 13A (3120W)(UK version)',
28
+ extend: extend.switch(),
29
+ fromZigbee: [fz.on_off_skip_duplicate_transaction],
30
+ configure: async (device, coordinatorEndpoint, logger) => {
31
+ const endpoint = device.getEndpoint(1);
32
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
33
+ },
34
+ onEvent: async (type, data, device) => {
35
+ device.skipDefaultResponse = true;
36
+ },
37
+ },
23
38
  {
24
39
  zigbeeModel: ['SWITCH-ZR02'],
25
40
  model: 'SWITCH-ZR02',
package/devices/nue_3a.js CHANGED
@@ -257,7 +257,7 @@ module.exports = [
257
257
  model: 'HGZB-02A',
258
258
  vendor: 'Nue / 3A',
259
259
  description: 'Smart light controller',
260
- extend: extend.light_onoff_brightness(),
260
+ extend: extend.light_onoff_brightness({disablePowerOnBehavior: true}),
261
261
  },
262
262
  {
263
263
  zigbeeModel: ['FNB56-ZSW01LX2.0'],
@@ -404,6 +404,13 @@ module.exports = [
404
404
  description: 'Hue Iris copper special edition (generation 4) ',
405
405
  extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
406
406
  },
407
+ {
408
+ zigbeeModel: ['929002376803'],
409
+ model: '929002376803',
410
+ vendor: 'Philips',
411
+ description: 'Hue Iris copper special edition (generation 4)',
412
+ extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
413
+ },
407
414
  {
408
415
  zigbeeModel: ['5063130P7'],
409
416
  model: '5063130P7',
@@ -565,6 +572,13 @@ module.exports = [
565
572
  description: 'Hue Go portable light',
566
573
  extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 500]}),
567
574
  },
575
+ {
576
+ zigbeeModel: ['7602031K6'],
577
+ model: '7602031K6',
578
+ vendor: 'Philips',
579
+ description: 'Hue Go portable light',
580
+ extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 500]}),
581
+ },
568
582
  {
569
583
  zigbeeModel: ['LLC020'],
570
584
  model: '7146060PH',
package/devices/tuya.js CHANGED
@@ -2047,6 +2047,8 @@ module.exports = [
2047
2047
  {modelID: 'TS0601', manufacturerName: '_TZE200_cpmgn2cf'},
2048
2048
  {modelID: 'TS0601', manufacturerName: '_TZE200_4eeyebrt'}, // Immax 07732B
2049
2049
  {modelID: 'TS0601', manufacturerName: '_TZE200_8whxpsiw'}, // EVOLVEO
2050
+ {modelID: 'TS0601', manufacturerName: '_TZE200_xby0s3ta'}, // Sandy Beach HY367
2051
+ {modelID: 'TS0601', manufacturerName: '_TZE200_7fqkphoq'}, // AFINTEK
2050
2052
  ],
2051
2053
  model: 'TS0601_thermostat',
2052
2054
  vendor: 'TuYa',
package/devices/ubisys.js CHANGED
@@ -536,18 +536,23 @@ module.exports = [
536
536
  model: 'S1',
537
537
  vendor: 'Ubisys',
538
538
  description: 'Power switch S1',
539
- exposes: [e.switch(), e.power().withAccess(ea.STATE_GET).withEndpoint('meter').withProperty('power'),
539
+ exposes: [
540
+ e.switch(),
540
541
  e.action([
541
542
  'toggle', 'on', 'off', 'recall_*',
542
543
  'brightness_move_up', 'brightness_move_down', 'brightness_stop',
543
544
  ]),
544
- e.power_on_behavior(), e.energy()],
545
+ e.power_on_behavior(),
546
+ e.power().withAccess(ea.STATE_GET),
547
+ e.energy().withAccess(ea.STATE_GET),
548
+ ],
545
549
  fromZigbee: [fz.on_off, fz.metering, fz.command_toggle, fz.command_on, fz.command_off, fz.command_recall, fz.command_move,
546
550
  fz.command_stop, fz.power_on_behavior, ubisys.fz.configure_device_setup],
547
- toZigbee: [tz.on_off, tz.metering_power, ubisys.tz.configure_device_setup, tz.power_on_behavior],
551
+ toZigbee: [tz.on_off, tz.metering_power, tz.currentsummdelivered, ubisys.tz.configure_device_setup, tz.power_on_behavior],
548
552
  endpoint: (device) => {
549
553
  return {'l1': 1, 's1': 2, 'meter': 3};
550
554
  },
555
+ meta: {multiEndpointEnforce: {'power': 3, 'energy': 3}},
551
556
  configure: async (device, coordinatorEndpoint, logger) => {
552
557
  const endpoint = device.getEndpoint(3);
553
558
  await reporting.bind(endpoint, coordinatorEndpoint, ['seMetering']);
@@ -580,15 +585,20 @@ module.exports = [
580
585
  model: 'S1-R',
581
586
  vendor: 'Ubisys',
582
587
  description: 'Power switch S1-R',
583
- exposes: [e.switch(), e.power().withAccess(ea.STATE_GET).withEndpoint('meter').withProperty('power'),
588
+ exposes: [
589
+ e.switch(),
584
590
  e.action([
585
591
  'toggle', 'on', 'off', 'recall_*',
586
592
  'brightness_move_up', 'brightness_move_down', 'brightness_stop',
587
593
  ]),
588
- e.power_on_behavior(), e.energy()],
594
+ e.power_on_behavior(),
595
+ e.power().withAccess(ea.STATE_GET),
596
+ e.energy().withAccess(ea.STATE_GET),
597
+ ],
589
598
  fromZigbee: [fz.on_off, fz.metering, fz.command_toggle, fz.command_on, fz.command_off, fz.command_recall, fz.command_move,
590
599
  fz.command_stop, fz.power_on_behavior, ubisys.fz.configure_device_setup],
591
- toZigbee: [tz.on_off, tz.metering_power, ubisys.tz.configure_device_setup, tz.power_on_behavior],
600
+ toZigbee: [tz.on_off, tz.metering_power, tz.currentsummdelivered, ubisys.tz.configure_device_setup, tz.power_on_behavior],
601
+ meta: {multiEndpointEnforce: {'power': 4, 'energy': 4}},
592
602
  endpoint: (device) => {
593
603
  return {'l1': 1, 's1': 2, 'meter': 4};
594
604
  },
@@ -625,20 +635,23 @@ module.exports = [
625
635
  vendor: 'Ubisys',
626
636
  description: 'Power switch S2',
627
637
  exposes: [
628
- e.switch().withEndpoint('l1'), e.switch().withEndpoint('l2'),
629
- e.power().withAccess(ea.STATE_GET).withEndpoint('meter').withProperty('power'),
630
- e.energy(),
638
+ e.switch().withEndpoint('l1'),
639
+ e.switch().withEndpoint('l2'),
631
640
  e.action(['toggle_s1', 'toggle_s2', 'on_s1', 'on_s2', 'off_s1', 'off_s2', 'recall_*_s1', 'recal_*_s2', 'brightness_move_up_s1',
632
641
  'brightness_move_up_s2', 'brightness_move_down_s1', 'brightness_move_down_s2', 'brightness_stop_s1',
633
642
  'brightness_stop_s2']),
634
- e.power_on_behavior().withEndpoint('l1'), e.power_on_behavior().withEndpoint('l2')],
643
+ e.power_on_behavior().withEndpoint('l1'),
644
+ e.power_on_behavior().withEndpoint('l2'),
645
+ e.power().withAccess(ea.STATE_GET),
646
+ e.energy().withAccess(ea.STATE_GET),
647
+ ],
635
648
  fromZigbee: [fz.on_off, fz.metering, fz.command_toggle, fz.command_on, fz.command_off, fz.command_recall, fz.command_move,
636
649
  fz.command_stop, fz.power_on_behavior, ubisys.fz.configure_device_setup],
637
- toZigbee: [tz.on_off, tz.metering_power, ubisys.tz.configure_device_setup, tz.power_on_behavior],
650
+ toZigbee: [tz.on_off, tz.metering_power, ubisys.tz.configure_device_setup, tz.power_on_behavior, tz.currentsummdelivered],
638
651
  endpoint: (device) => {
639
652
  return {'l1': 1, 'l2': 2, 's1': 3, 's2': 4, 'meter': 5};
640
653
  },
641
- meta: {multiEndpoint: true},
654
+ meta: {multiEndpoint: true, multiEndpointEnforce: {'power': 5, 'energy': 5}},
642
655
  configure: async (device, coordinatorEndpoint, logger) => {
643
656
  const endpoint = device.getEndpoint(5);
644
657
  await reporting.bind(endpoint, coordinatorEndpoint, ['seMetering']);
@@ -684,7 +697,7 @@ module.exports = [
684
697
  ubisys.fz.dimmer_setup_genLevelCtrl, ubisys.fz.configure_device_setup],
685
698
  toZigbee: [tz.light_onoff_brightness, tz.ballast_config, tz.level_config, ubisys.tz.dimmer_setup,
686
699
  ubisys.tz.dimmer_setup_genLevelCtrl, ubisys.tz.configure_device_setup, tz.ignore_transition, tz.light_brightness_move,
687
- tz.light_brightness_step],
700
+ tz.light_brightness_step, tz.metering_power, tz.currentsummdelivered],
688
701
  exposes: [
689
702
  e.action(['toggle_s1', 'toggle_s2', 'on_s1', 'on_s2', 'off_s1', 'off_s2', 'recall_*_s1', 'recal_*_s2', 'brightness_move_up_s1',
690
703
  'brightness_move_up_s2', 'brightness_move_down_s1', 'brightness_move_down_s2', 'brightness_stop_s1',
@@ -704,7 +717,8 @@ module.exports = [
704
717
  .withValueMin(1).withValueMax(254)
705
718
  .withPreset('previous', 255, 'Use previous value')
706
719
  .withDescription('Specifies the initial level to be applied after the device is supplied with power')),
707
- e.power(), e.energy(),
720
+ e.power().withAccess(ea.STATE_GET),
721
+ e.energy().withAccess(ea.STATE_GET),
708
722
  exposes.numeric('ballast_minimum_level', ea.ALL).withValueMin(1).withValueMax(254)
709
723
  .withDescription('Specifies the minimum light output of the ballast'),
710
724
  exposes.numeric('ballast_maximum_level', ea.ALL).withValueMin(1).withValueMax(254)
@@ -748,7 +762,7 @@ module.exports = [
748
762
  await reporting.readMeteringMultiplierDivisor(endpoint);
749
763
  await reporting.instantaneousDemand(endpoint);
750
764
  },
751
- meta: {multiEndpoint: true, multiEndpointSkip: ['state', 'brightness']},
765
+ meta: {multiEndpoint: true, multiEndpointSkip: ['state', 'brightness'], multiEndpointEnforce: {'power': 4, 'energy': 4}},
752
766
  endpoint: (device) => {
753
767
  return {'default': 1, 's1': 2, 's2': 3, 'meter': 4};
754
768
  },
@@ -777,9 +791,13 @@ module.exports = [
777
791
  description: 'Shutter control J1',
778
792
  fromZigbee: [fz.cover_position_tilt, fz.metering, ubisys.fz.configure_device_setup],
779
793
  toZigbee: [tz.cover_state, tz.cover_position_tilt, tz.metering_power,
780
- ubisys.tz.configure_j1, ubisys.tz.configure_device_setup],
781
- exposes: [e.cover_position_tilt(),
782
- e.power().withAccess(ea.STATE_GET).withEndpoint('meter').withProperty('power'), e.energy()],
794
+ ubisys.tz.configure_j1, ubisys.tz.configure_device_setup,
795
+ tz.currentsummdelivered],
796
+ exposes: [
797
+ e.cover_position_tilt(),
798
+ e.power().withAccess(ea.STATE_GET),
799
+ e.energy().withAccess(ea.STATE_GET),
800
+ ],
783
801
  configure: async (device, coordinatorEndpoint, logger) => {
784
802
  const endpoint1 = device.getEndpoint(1);
785
803
  const endpoint3 = device.getEndpoint(3);
@@ -792,6 +810,7 @@ module.exports = [
792
810
  endpoint: (device) => {
793
811
  return {'default': 1, 'meter': 3};
794
812
  },
813
+ meta: {multiEndpointEnforce: {'power': 3, 'energy': 3}},
795
814
  onEvent: async (type, data, device) => {
796
815
  /*
797
816
  * As per technical doc page 21 section 7.3.4
@@ -14,16 +14,4 @@ module.exports = [
14
14
  await reporting.onOff(endpoint);
15
15
  },
16
16
  },
17
- {
18
- zigbeeModel: ['SA-030-1'],
19
- model: 'SA-030',
20
- vendor: 'Woolley',
21
- description: 'Smart plug',
22
- extend: extend.switch(),
23
- configure: async (device, coordinatorEndpoint, logger) => {
24
- const endpoint = device.getEndpoint(1);
25
- await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
26
- await reporting.onOff(endpoint);
27
- },
28
- },
29
17
  ];
package/lib/utils.js CHANGED
@@ -125,6 +125,7 @@ function postfixWithEndpointName(value, msg, definition, meta) {
125
125
  meta.logger.warn(`No meta passed to postfixWithEndpointName, update your external converter!`);
126
126
  meta = {device: null};
127
127
  }
128
+
128
129
  if (definition.meta && definition.meta.multiEndpoint &&
129
130
  (!definition.meta.multiEndpointSkip || !definition.meta.multiEndpointSkip.includes(value))) {
130
131
  const endpointName = definition.hasOwnProperty('endpoint') ?
@@ -137,6 +138,15 @@ function postfixWithEndpointName(value, msg, definition, meta) {
137
138
  return value;
138
139
  }
139
140
 
141
+ function enforceEndpoint(entity, key, meta) {
142
+ const multiEndpointEnforce = getMetaValue(entity, meta.mapped, 'multiEndpointEnforce', 'allEqual', []);
143
+ if (multiEndpointEnforce && multiEndpointEnforce.hasOwnProperty(key)) {
144
+ const endpoint = entity.getDevice().getEndpoint(multiEndpointEnforce[key]);
145
+ if (endpoint) return endpoint;
146
+ }
147
+ return entity;
148
+ }
149
+
140
150
  function getKey(object, value, fallback, convertTo) {
141
151
  for (const key in object) {
142
152
  if (object[key]===value) {
@@ -448,6 +458,7 @@ module.exports = {
448
458
  toPercentage,
449
459
  addActionGroup,
450
460
  postfixWithEndpointName,
461
+ enforceEndpoint,
451
462
  getKey,
452
463
  getObjectProperty,
453
464
  batteryVoltageToPercentage,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zigbee-herdsman-converters",
3
- "version": "15.0.0",
3
+ "version": "15.0.2",
4
4
  "description": "Collection of device converters to be used with zigbee-herdsman",
5
5
  "main": "index.js",
6
6
  "files": [