zigbee-herdsman-converters 15.0.17 → 15.0.19

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.
@@ -7431,6 +7431,17 @@ const converters = {
7431
7431
  const lookup = {1: 'manual', 2: 'schedule', 3: 'energy_saver', 6: 'holiday'};
7432
7432
  result['zone_mode'] = lookup[msg.data[0xe010]];
7433
7433
  }
7434
+ if (msg.data.hasOwnProperty(0xe011)) {
7435
+ // wiserSmartHactConfig
7436
+ const lookup = {0x00: 'unconfigured', 0x80: 'setpoint_switch', 0x82: 'setpoint_fip', 0x83: 'fip_fip'};
7437
+ result['hact_config'] = lookup[msg.data[0xe011]];
7438
+ }
7439
+ if (msg.data.hasOwnProperty(0xe020)) {
7440
+ // wiserSmartCurrentFilPiloteMode
7441
+ const lookup = {0: 'comfort', 1: 'comfort_-1', 2: 'comfort_-2', 3: 'energy_saving',
7442
+ 4: 'frost_protection', 5: 'off'};
7443
+ result['fip_setting'] = lookup[msg.data[0xe020]];
7444
+ }
7434
7445
  if (msg.data.hasOwnProperty(0xe030)) {
7435
7446
  // wiserSmartValvePosition
7436
7447
  result['pi_heating_demand'] = msg.data[0xe030];
@@ -7651,57 +7662,6 @@ const converters = {
7651
7662
  return result;
7652
7663
  },
7653
7664
  },
7654
- tuya_radar_sensor_fall: {
7655
- cluster: 'manuSpecificTuya',
7656
- type: ['commandDataResponse', 'commandDataReport'],
7657
- convert: (model, msg, publish, options, meta) => {
7658
- const dpValue = tuya.firstDpValue(msg, meta, 'tuya_radar_sensor_fall');
7659
- const dp = dpValue.dp;
7660
- const value = tuya.getDataValue(dpValue);
7661
- let result = null;
7662
- switch (dp) {
7663
- case tuya.dataPoints.trsfPresenceState:
7664
- result = {presence: {0: false, 1: true}[value]};
7665
- break;
7666
- case tuya.dataPoints.trsfMotionState:
7667
- result = {occupancy: {1: false, 2: true}[value]};
7668
- break;
7669
- case tuya.dataPoints.trsfMotionSpeed:
7670
- result = {motion_speed: value};
7671
- break;
7672
- case tuya.dataPoints.trsfMotionDirection:
7673
- result = {motion_direction: tuya.tuyaRadar.motionDirection[value]};
7674
- break;
7675
- case tuya.dataPoints.trsfScene:
7676
- result = {radar_scene: tuya.tuyaRadar.radarScene[value]};
7677
- break;
7678
- case tuya.dataPoints.trsfSensitivity:
7679
- result = {radar_sensitivity: value};
7680
- break;
7681
- case tuya.dataPoints.trsfIlluminanceLux:
7682
- result = {illuminance_lux: value};
7683
- break;
7684
- case tuya.dataPoints.trsfTumbleAlarmTime:
7685
- result = {tumble_alarm_time: value+1};
7686
- break;
7687
- case tuya.dataPoints.trsfTumbleSwitch:
7688
- result = {tumble_switch: {false: 'OFF', true: 'ON'}[value]};
7689
- break;
7690
- case tuya.dataPoints.trsfFallDownStatus:
7691
- result = {fall_down_status: tuya.tuyaRadar.fallDown[value]};
7692
- break;
7693
- case tuya.dataPoints.trsfStaticDwellAlarm:
7694
- result = {static_dwell_alarm: value};
7695
- break;
7696
- case tuya.dataPoints.trsfFallSensitivity:
7697
- result = {fall_sensitivity: value};
7698
- break;
7699
- default:
7700
- meta.logger.warn(`fromZigbee.tuya_radar_sensor_fall: NOT RECOGNIZED DP ${dp} with data ${JSON.stringify(dpValue)}`);
7701
- }
7702
- return result;
7703
- },
7704
- },
7705
7665
  tuya_smart_vibration_sensor: {
7706
7666
  cluster: 'manuSpecificTuya',
7707
7667
  type: ['commandGetData', 'commandDataResponse', 'raw'],
@@ -61,6 +61,12 @@ const converters = {
61
61
  await entity.command('genBasic', 'resetFactDefault', {}, utils.getOptions(meta.mapped, entity));
62
62
  },
63
63
  },
64
+ identify: {
65
+ key: ['identify'],
66
+ convertSet: async (entity, key, value, meta) => {
67
+ await entity.command('genIdentify', 'identify', {identifytime: value}, utils.getOptions(meta.mapped, entity));
68
+ },
69
+ },
64
70
  arm_mode: {
65
71
  key: ['arm_mode'],
66
72
  convertSet: async (entity, key, value, meta) => {
@@ -6485,6 +6491,58 @@ const converters = {
6485
6491
  }
6486
6492
  },
6487
6493
  },
6494
+ wiser_fip_setting: {
6495
+ key: ['fip_setting'],
6496
+ convertSet: async (entity, key, value, meta) => {
6497
+ const zoneLookup = {'manual': 1, 'schedule': 2, 'energy_saver': 3, 'holiday': 6};
6498
+ const zonemodeNum = zoneLookup[meta.state.zone_mode];
6499
+
6500
+ const fipLookup = {'comfort': 0, 'comfort_-1': 1, 'comfort_-2': 2, 'energy_saving': 3,
6501
+ 'frost_protection': 4, 'off': 5};
6502
+ value = value.toLowerCase();
6503
+ utils.validateValue(value, Object.keys(fipLookup));
6504
+ const fipmodeNum = fipLookup[value];
6505
+
6506
+ const payload = {
6507
+ zonemode: zonemodeNum,
6508
+ fipmode: fipmodeNum,
6509
+ reserved: 0xff,
6510
+ };
6511
+ await entity.command('hvacThermostat', 'wiserSmartSetFipMode', payload,
6512
+ {srcEndpoint: 11, disableDefaultResponse: true});
6513
+
6514
+ return {state: {'fip_setting': value}};
6515
+ },
6516
+ convertGet: async (entity, key, meta) => {
6517
+ await entity.read('hvacThermostat', [0xe020]);
6518
+ },
6519
+ },
6520
+ wiser_hact_config: {
6521
+ key: ['hact_config'],
6522
+ convertSet: async (entity, key, value, meta) => {
6523
+ const lookup = {'unconfigured': 0x00, 'setpoint_switch': 0x80, 'setpoint_fip': 0x82, 'fip_fip': 0x83};
6524
+ value = value.toLowerCase();
6525
+ utils.validateValue(value, Object.keys(lookup));
6526
+ const mode = lookup[value];
6527
+ await entity.write('hvacThermostat', {0xe011: {value: mode, type: 0x18}});
6528
+ return {state: {'hact_config': value}};
6529
+ },
6530
+ convertGet: async (entity, key, meta) => {
6531
+ await entity.read('hvacThermostat', [0xe011]);
6532
+ },
6533
+ },
6534
+ wiser_zone_mode: {
6535
+ key: ['zone_mode'],
6536
+ convertSet: async (entity, key, value, meta) => {
6537
+ const lookup = {'manual': 1, 'schedule': 2, 'energy_saver': 3, 'holiday': 6};
6538
+ const zonemodeNum = lookup[value];
6539
+ await entity.write('hvacThermostat', {0xe010: {value: zonemodeNum, type: 0x30}});
6540
+ return {state: {'zone_mode': value}};
6541
+ },
6542
+ convertGet: async (entity, key, meta) => {
6543
+ await entity.read('hvacThermostat', [0xe010]);
6544
+ },
6545
+ },
6488
6546
  wiser_vact_calibrate_valve: {
6489
6547
  key: ['calibrate_valve'],
6490
6548
  convertSet: async (entity, key, value, meta) => {
@@ -6607,30 +6665,6 @@ const converters = {
6607
6665
  }
6608
6666
  },
6609
6667
  },
6610
- tuya_radar_sensor_fall: {
6611
- key: ['radar_scene', 'radar_sensitivity', 'tumble_alarm_time', 'tumble_switch', 'fall_sensitivity'],
6612
- convertSet: async (entity, key, value, meta) => {
6613
- switch (key) {
6614
- case 'radar_scene':
6615
- await tuya.sendDataPointEnum(entity, tuya.dataPoints.trsfScene, utils.getKey(tuya.tuyaRadar.radarScene, value));
6616
- break;
6617
- case 'radar_sensitivity':
6618
- await tuya.sendDataPointValue(entity, tuya.dataPoints.trsfSensitivity, value);
6619
- break;
6620
- case 'tumble_switch':
6621
- await tuya.sendDataPointEnum(entity, tuya.dataPoints.trsfTumbleSwitch, {'on': true, 'off': false}[value.toLowerCase()]);
6622
- break;
6623
- case 'tumble_alarm_time':
6624
- await tuya.sendDataPointEnum(entity, tuya.dataPoints.trsfTumbleAlarmTime, value-1);
6625
- break;
6626
- case 'fall_sensitivity':
6627
- await tuya.sendDataPointValue(entity, tuya.dataPoints.trsfFallSensitivity, value);
6628
- break;
6629
- default: // Unknown Key
6630
- meta.logger.warn(`toZigbee.tuya_radar_sensor_fall: Unhandled Key ${key}`);
6631
- }
6632
- },
6633
- },
6634
6668
  javis_microwave_sensor: {
6635
6669
  key: [
6636
6670
  'illuminance_calibration', 'led_enable',
@@ -8,4 +8,11 @@ module.exports = [
8
8
  description: 'Downlight with tuneable white',
9
9
  extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 370]}),
10
10
  },
11
+ {
12
+ zigbeeModel: ['AL8RGB13W-AP'],
13
+ model: 'AL8RGB13W-AP',
14
+ vendor: 'Alchemy',
15
+ description: 'Downlight RGBW',
16
+ extend: extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 370]}),
17
+ },
11
18
  ];
package/devices/bosch.js CHANGED
@@ -5,6 +5,7 @@ const tz = require('../converters/toZigbee');
5
5
  const reporting = require('../lib/reporting');
6
6
  const utils = require('../lib/utils');
7
7
  const constants = require('../lib/constants');
8
+ const ota = require('../lib/ota');
8
9
  const e = exposes.presets;
9
10
  const ea = exposes.access;
10
11
 
@@ -396,6 +397,7 @@ const definition = [
396
397
  model: 'BTH-RA',
397
398
  vendor: 'Bosch',
398
399
  description: 'Radiator thermostat II',
400
+ ota: ota.zigbeeOTA,
399
401
  fromZigbee: [fz.thermostat, fz.battery, fzLocal.bosch_thermostat, fzLocal.bosch_userInterface],
400
402
  toZigbee: [
401
403
  tz.thermostat_occupied_heating_setpoint,
@@ -16,9 +16,10 @@ module.exports = [
16
16
  toZigbee: [tz.on_off, tz.legrand_settingEnableLedInDark, tz.legrand_settingEnableLedIfOn, tz.legrand_identify],
17
17
  exposes: [
18
18
  e.switch(), e.action(['identify', 'on', 'off']),
19
- exposes.binary('led_in_dark', ea.ALL, 'ON', 'OFF').withDescription(`Enables the LED when the light is turned off, allowing to
20
- see the switch in the dark`),
19
+ exposes.binary('led_in_dark', ea.ALL, 'ON', 'OFF').withDescription(`Enables the LED when the light is turned off, allowing ` +
20
+ `to see the switch in the dark`),
21
21
  exposes.binary('led_if_on', ea.ALL, 'ON', 'OFF').withDescription('Enables the LED when the light is turned on'),
22
+ exposes.enum('identify', ea.SET, ['blink']).withDescription(`Blinks the built-in LED to make it easier to find the device`),
22
23
  ],
23
24
  configure: async (device, coordinatorEndpoint, logger) => {
24
25
  const endpoint = device.getEndpoint(1);
@@ -34,15 +35,18 @@ module.exports = [
34
35
  fromZigbee: [fz.brightness, fz.identify, fz.on_off, fz.lighting_ballast_configuration, fz.legrand_cluster_fc01],
35
36
  toZigbee: [tz.light_onoff_brightness, tz.legrand_settingEnableLedInDark, tz.legrand_settingEnableLedIfOn,
36
37
  tz.legrand_deviceMode, tz.legrand_identify, tz.ballast_config],
37
- exposes: [e.light_brightness(),
38
+ exposes: [
39
+ e.light_brightness(),
38
40
  exposes.numeric('ballast_minimum_level', ea.ALL).withValueMin(1).withValueMax(254)
39
41
  .withDescription('Specifies the minimum brightness value'),
40
42
  exposes.numeric('ballast_maximum_level', ea.ALL).withValueMin(1).withValueMax(254)
41
43
  .withDescription('Specifies the maximum brightness value'),
42
44
  exposes.binary('device_mode', ea.ALL, 'dimmer_on', 'dimmer_off').withDescription('Allow the device to change brightness'),
43
- exposes.binary('led_in_dark', ea.ALL, 'ON', 'OFF').withDescription(`Enables the LED when the light is turned off, allowing to
44
- see the switch in the dark`),
45
- exposes.binary('led_if_on', ea.ALL, 'ON', 'OFF').withDescription('Enables the LED when the light is turned on')],
45
+ exposes.binary('led_in_dark', ea.ALL, 'ON', 'OFF').withDescription(`Enables the LED when the light is turned off, allowing ` +
46
+ `to see the switch in the dark`),
47
+ exposes.binary('led_if_on', ea.ALL, 'ON', 'OFF').withDescription('Enables the LED when the light is turned on'),
48
+ exposes.enum('identify', ea.SET, ['blink']).withDescription(`Blinks the built-in LED to make it easier to find the device`),
49
+ ],
46
50
  configure: async (device, coordinatorEndpoint, logger) => {
47
51
  await extend.light_onoff_brightness().configure(device, coordinatorEndpoint, logger);
48
52
  const endpoint = device.getEndpoint(1);
@@ -65,7 +69,12 @@ module.exports = [
65
69
  fz.cover_position_tilt],
66
70
  toZigbee: [tz.bticino_4027C_cover_state, tz.bticino_4027C_cover_position, tz.legrand_identify,
67
71
  tz.legrand_settingEnableLedInDark],
68
- exposes: [e.cover_position()],
72
+ exposes: [
73
+ e.cover_position(), e.action(['moving', 'identify', '']),
74
+ exposes.binary('led_in_dark', ea.ALL, 'ON', 'OFF').withDescription(`Enables the LED when the light is turned off, allowing ` +
75
+ `to see the switch in the dark`),
76
+ exposes.enum('identify', ea.SET, ['blink']).withDescription(`Blinks the built-in LED to make it easier to find the device`),
77
+ ],
69
78
  configure: async (device, coordinatorEndpoint, logger) => {
70
79
  const endpoint = device.getEndpoint(1);
71
80
  await reporting.bind(endpoint, coordinatorEndpoint, ['genBinaryInput', 'closuresWindowCovering', 'genIdentify']);
@@ -311,9 +311,15 @@ module.exports = [
311
311
  await reporting.bind(endpoint, coordinatorEndpoint, ['haElectricalMeasurement', 'genIdentify']);
312
312
  await reporting.readEletricalMeasurementMultiplierDivisors(endpoint);
313
313
  await reporting.activePower(endpoint);
314
- await reporting.apparentPower(endpoint);
315
- // Read configuration values that are not sent periodically as well as current power (activePower).
316
- await endpoint.read('haElectricalMeasurement', ['activePower', 0xf000, 0xf001, 0xf002]);
314
+ await endpoint.read('haElectricalMeasurement', ['activePower']);
315
+ try {
316
+ await reporting.apparentPower(endpoint);
317
+ await endpoint.read('haElectricalMeasurement', ['apparentPower']);
318
+ } catch (e) {
319
+ // Some version/firmware don't seem to support this.
320
+ }
321
+ // Read configuration values that are not sent periodically.
322
+ await endpoint.read('haElectricalMeasurement', [0xf000, 0xf001, 0xf002]);
317
323
  },
318
324
  onEvent: async (type, data, device, options, state) => {
319
325
  /**
@@ -3,6 +3,7 @@ const fz = require('../converters/fromZigbee');
3
3
  const tz = require('../converters/toZigbee');
4
4
  const reporting = require('../lib/reporting');
5
5
  const tuya = require('../lib/tuya');
6
+ const extend = require('../lib/extend');
6
7
  const e = exposes.presets;
7
8
  const ea = exposes.access;
8
9
 
@@ -30,7 +31,97 @@ module.exports = [
30
31
  },
31
32
  },
32
33
  {
33
- fingerprint: tuya.fingerprint('TS011F', ['_TZ3210_7jnk7l3k', '_TZ3210_raqjcxo5']),
34
+ fingerprint: [{modelID: 'TS0202', manufacturerName: '_TYZB01_qjqgmqxr'}],
35
+ model: 'SMA02P',
36
+ vendor: 'Mercator',
37
+ description: 'Ikuü battery motion sensor',
38
+ fromZigbee: [fz.ias_occupancy_alarm_1, fz.battery, fz.ignore_basic_report, fz.ias_occupancy_alarm_1_report],
39
+ toZigbee: [],
40
+ exposes: [e.occupancy(), e.battery_low(), e.tamper(), e.battery(), e.battery_voltage()],
41
+ configure: async (device, coordinatorEndpoint, logger) => {
42
+ const endpoint = device.getEndpoint(1);
43
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
44
+ try {
45
+ await reporting.batteryPercentageRemaining(endpoint);
46
+ } catch (error) {/* Fails for some https://github.com/Koenkk/zigbee2mqtt/issues/13708*/}
47
+ },
48
+ },
49
+ {
50
+ fingerprint: [{modelID: 'TS0201', manufacturerName: '_TZ3000_82ptnsd4'}],
51
+ model: 'SMA03P',
52
+ vendor: 'Mercator',
53
+ description: 'Ikuü temperature & humidity sensor',
54
+ fromZigbee: [fz.battery, fz.temperature, fz.humidity],
55
+ toZigbee: [],
56
+ exposes: [e.battery(), e.temperature(), e.humidity(), e.battery_voltage()],
57
+ configure: tuya.configureMagicPacket,
58
+ },
59
+ {
60
+ fingerprint: [{modelID: 'TS0203', manufacturerName: '_TZ3000_wbrlnkm9'}],
61
+ model: 'SMA04P',
62
+ vendor: 'Mercator',
63
+ description: 'Ikuü battery contact sensor',
64
+ fromZigbee: [fz.ias_contact_alarm_1, fz.battery, fz.ignore_basic_report, fz.ias_contact_alarm_1_report],
65
+ toZigbee: [],
66
+ exposes: [e.contact(), e.battery_low(), e.tamper(), e.battery(), e.battery_voltage()],
67
+ configure: async (device, coordinatorEndpoint, logger) => {
68
+ try {
69
+ const endpoint = device.getEndpoint(1);
70
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
71
+ await reporting.batteryPercentageRemaining(endpoint);
72
+ await reporting.batteryVoltage(endpoint);
73
+ } catch (error) {/* Fails for some*/}
74
+ },
75
+ },
76
+ {
77
+ fingerprint: [{modelID: 'TS0502B', manufacturerName: '_TZ3000_6dwfra5l'}],
78
+ model: 'SMCL01-ZB',
79
+ vendor: 'Mercator',
80
+ description: 'Ikuü Ikon ceiling light CCT',
81
+ extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 500], disablePowerOnBehavior: true}),
82
+ },
83
+ {
84
+ fingerprint: [{modelID: 'TS0505B', manufacturerName: '_TZ3000_xr5m6kfg'}],
85
+ model: 'SMD4109W-RGB-ZB',
86
+ vendor: 'Mercator',
87
+ description: 'Ikuü Walter downlight RGB + CCT',
88
+ extend: extend.light_onoff_brightness_colortemp_color(
89
+ {colorTempRange: [153, 500], disableColorTempStartup: true, disablePowerOnBehavior: true}),
90
+ meta: {applyRedFix: true, enhancedHue: false},
91
+ },
92
+ {
93
+ fingerprint: [{modelID: 'TS011F', manufacturerName: '_TZ3210_raqjcxo5'}],
94
+ model: 'SPP02G',
95
+ vendor: 'Mercator',
96
+ description: 'Ikuü double indoors power point',
97
+ extend: tuya.extend.switch({powerOutageMemory: true, electricalMeasurements: true, endpoints: ['left', 'right']}),
98
+ exposes: [e.switch().withEndpoint('left'), e.switch().withEndpoint('right'),
99
+ e.power().withEndpoint('left'), e.current().withEndpoint('left'),
100
+ e.voltage().withEndpoint('left').withAccess(ea.STATE), e.energy()],
101
+ endpoint: (device) => {
102
+ return {left: 1, right: 2};
103
+ },
104
+ meta: {multiEndpoint: true},
105
+ configure: async (device, coordinatorEndpoint, logger) => {
106
+ const endpoint1 = device.getEndpoint(1);
107
+ const endpoint2 = device.getEndpoint(2);
108
+ await reporting.bind(endpoint1, coordinatorEndpoint, ['genBasic', 'genOnOff', 'haElectricalMeasurement', 'seMetering']);
109
+ await reporting.bind(endpoint2, coordinatorEndpoint, ['genOnOff']);
110
+ await reporting.onOff(endpoint1);
111
+ await reporting.onOff(endpoint1);
112
+ await reporting.onOff(endpoint1);
113
+ await reporting.rmsVoltage(endpoint1, {change: 5});
114
+ await reporting.rmsCurrent(endpoint1, {change: 50});
115
+ await reporting.activePower(endpoint1, {change: 1});
116
+ await reporting.onOff(endpoint1);
117
+ await reporting.onOff(endpoint2);
118
+ endpoint1.saveClusterAttributeKeyValue('haElectricalMeasurement', {acCurrentDivisor: 1000, acCurrentMultiplier: 1});
119
+ endpoint1.saveClusterAttributeKeyValue('seMetering', {divisor: 100, multiplier: 1});
120
+ device.save();
121
+ },
122
+ },
123
+ {
124
+ fingerprint: [{modelID: 'TS011F', manufacturerName: '_TZ3210_7jnk7l3k'}],
34
125
  model: 'SPP02GIP',
35
126
  vendor: 'Mercator',
36
127
  description: 'Ikuü double outdoors power point',
@@ -60,11 +151,31 @@ module.exports = [
60
151
  device.save();
61
152
  },
62
153
  },
154
+ {
155
+ fingerprint: [{modelID: 'TS0013', manufacturerName: '_TZ3000_khtlvdfc'}],
156
+ model: 'SSW03G',
157
+ vendor: 'Mercator',
158
+ description: 'Ikuü triple switch',
159
+ extend: tuya.extend.switch({backlightModeLowMediumHigh: true, endpoints: ['left', 'center', 'right']}),
160
+ endpoint: (device) => {
161
+ return {'left': 1, 'center': 2, 'right': 3};
162
+ },
163
+ meta: {multiEndpoint: true},
164
+ configure: async (device, coordinatorEndpoint, logger) => {
165
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
166
+ for (const ID of [1, 2, 3]) {
167
+ const endpoint = device.getEndpoint(ID);
168
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
169
+ }
170
+ device.powerSource = 'Mains (single phase)';
171
+ device.save();
172
+ },
173
+ },
63
174
  {
64
175
  fingerprint: [{modelID: 'TS0501', manufacturerName: '_TZ3210_lzqq3u4r'},
65
176
  {modelID: 'TS0501', manufacturerName: '_TZ3210_4whigl8i'}],
66
177
  model: 'SSWF01G',
67
- description: 'AC fan controller',
178
+ description: 'Ikuü AC fan controller',
68
179
  vendor: 'Mercator',
69
180
  fromZigbee: [fz.on_off, fz.fan],
70
181
  toZigbee: [tz.fan_mode, tz.on_off],
package/devices/moes.js CHANGED
@@ -97,6 +97,7 @@ module.exports = [
97
97
  {
98
98
  fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_aoclfnxz'},
99
99
  {modelID: 'TS0601', manufacturerName: '_TZE200_ztvwu4nk'},
100
+ {modelID: 'TS0601', manufacturerName: '_TZE200_5toc8efa'},
100
101
  {modelID: 'TS0601', manufacturerName: '_TZE200_ye5jkfsb'},
101
102
  {modelID: 'TS0601', manufacturerName: '_TZE200_u9bfwha0'}],
102
103
  model: 'BHT-002-GCLZB',
package/devices/niko.js CHANGED
@@ -36,6 +36,20 @@ const local = {
36
36
  return state;
37
37
  },
38
38
  },
39
+ switch_status_led: {
40
+ cluster: 'manuSpecificNiko1',
41
+ type: ['attributeReport', 'readResponse'],
42
+ convert: (model, msg, publish, options, meta) => {
43
+ const state = {};
44
+ if (msg.data.hasOwnProperty('outletLedState')) {
45
+ state['led_enable'] = (msg.data['outletLedState'] == 1);
46
+ }
47
+ if (msg.data.hasOwnProperty('outletLedColor')) {
48
+ state['led_state'] = (msg.data['outletLedColor'] == 255 ? 'ON' : 'OFF');
49
+ }
50
+ return state;
51
+ },
52
+ },
39
53
  outlet: {
40
54
  cluster: 'manuSpecificNiko1',
41
55
  type: ['attributeReport', 'readResponse'],
@@ -69,6 +83,27 @@ const local = {
69
83
  await entity.read('manuSpecificNiko1', ['switchOperationMode']);
70
84
  },
71
85
  },
86
+ switch_led_enable: {
87
+ key: ['led_enable'],
88
+ convertSet: async (entity, key, value, meta) => {
89
+ await entity.write('manuSpecificNiko1', {'outletLedState': ((value) ? 1 : 0)});
90
+ await entity.read('manuSpecificNiko1', ['outletLedColor']);
91
+ return {state: {led_enable: ((value) ? true : false)}};
92
+ },
93
+ convertGet: async (entity, key, meta) => {
94
+ await entity.read('manuSpecificNiko1', ['outletLedState']);
95
+ },
96
+ },
97
+ switch_led_state: {
98
+ key: ['led_state'],
99
+ convertSet: async (entity, key, value, meta) => {
100
+ await entity.write('manuSpecificNiko1', {'outletLedColor': ((value.toLowerCase() === 'off') ? 0 : 255)});
101
+ return {state: {led_state: ((value.toLowerCase() === 'off') ? 'OFF' : 'ON')}};
102
+ },
103
+ convertGet: async (entity, key, meta) => {
104
+ await entity.read('manuSpecificNiko1', ['outletLedColor']);
105
+ },
106
+ },
72
107
  outlet_child_lock: {
73
108
  key: ['child_lock'],
74
109
  convertSet: async (entity, key, value, meta) => {
@@ -198,18 +233,20 @@ module.exports = [
198
233
  model: '552-721X1',
199
234
  vendor: 'Niko',
200
235
  description: 'Single connectable switch',
201
- fromZigbee: [fz.on_off, local.fz.switch_operation_mode, local.fz.switch_action],
202
- toZigbee: [tz.on_off, local.tz.switch_operation_mode],
236
+ fromZigbee: [fz.on_off, local.fz.switch_operation_mode, local.fz.switch_action, local.fz.switch_status_led],
237
+ toZigbee: [tz.on_off, local.tz.switch_operation_mode, local.tz.switch_led_enable, local.tz.switch_led_state],
203
238
  configure: async (device, coordinatorEndpoint, logger) => {
204
239
  const endpoint = device.getEndpoint(1);
205
240
  await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
206
241
  await reporting.onOff(endpoint);
207
- await endpoint.read('manuSpecificNiko1', ['switchOperationMode']);
242
+ await endpoint.read('manuSpecificNiko1', ['switchOperationMode', 'outletLedState', 'outletLedColor']);
208
243
  },
209
244
  exposes: [
210
245
  e.switch(),
211
246
  e.action(['single', 'hold', 'release']),
212
247
  exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled']),
248
+ exposes.binary('led_enable', ea.ALL, true, false).withDescription('Enable LED'),
249
+ exposes.binary('led_state', ea.ALL, 'ON', 'OFF').withDescription('LED State'),
213
250
  ],
214
251
  },
215
252
  {
@@ -217,8 +254,8 @@ module.exports = [
217
254
  model: '552-721X2',
218
255
  vendor: 'Niko',
219
256
  description: 'Double connectable switch',
220
- fromZigbee: [fz.on_off, local.fz.switch_operation_mode, local.fz.switch_action],
221
- toZigbee: [tz.on_off, local.tz.switch_operation_mode],
257
+ fromZigbee: [fz.on_off, local.fz.switch_operation_mode, local.fz.switch_action, local.fz.switch_status_led],
258
+ toZigbee: [tz.on_off, local.tz.switch_operation_mode, local.tz.switch_led_enable, local.tz.switch_led_state],
222
259
  endpoint: (device) => {
223
260
  return {'l1': 1, 'l2': 2};
224
261
  },
@@ -230,8 +267,8 @@ module.exports = [
230
267
  await reporting.bind(ep2, coordinatorEndpoint, ['genOnOff']);
231
268
  await reporting.onOff(ep1);
232
269
  await reporting.onOff(ep2);
233
- await ep1.read('manuSpecificNiko1', ['switchOperationMode']);
234
- await ep2.read('manuSpecificNiko1', ['switchOperationMode']);
270
+ await ep1.read('manuSpecificNiko1', ['switchOperationMode', 'outletLedState', 'outletLedColor']);
271
+ await ep2.read('manuSpecificNiko1', ['switchOperationMode', 'outletLedState', 'outletLedColor']);
235
272
  },
236
273
  exposes: [
237
274
  e.switch().withEndpoint('l1'), e.switch().withEndpoint('l2'),
@@ -239,6 +276,10 @@ module.exports = [
239
276
  e.action(['single', 'hold', 'release']).withEndpoint('l2'),
240
277
  exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled']).withEndpoint('l1'),
241
278
  exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled']).withEndpoint('l2'),
279
+ exposes.binary('led_enable', ea.ALL, true, false).withEndpoint('l1').withDescription('Enable LED'),
280
+ exposes.binary('led_enable', ea.ALL, true, false).withEndpoint('l2').withDescription('Enable LED'),
281
+ exposes.binary('led_state', ea.ALL, 'ON', 'OFF').withEndpoint('l1').withDescription('LED State'),
282
+ exposes.binary('led_state', ea.ALL, 'ON', 'OFF').withEndpoint('l2').withDescription('LED State'),
242
283
  ],
243
284
  },
244
285
  {
package/devices/osram.js CHANGED
@@ -205,7 +205,7 @@ module.exports = [
205
205
  model: 'AB3257001NJ',
206
206
  description: 'Smart+ plug',
207
207
  vendor: 'OSRAM',
208
- extend: extend.switch(),
208
+ extend: extend.switch({disablePowerOnBehavior: true}),
209
209
  whiteLabel: [{vendor: 'LEDVANCE', model: 'AB3257001NJ'}, {vendor: 'LEDVANCE', model: 'AC03360'}],
210
210
  ota: ota.ledvance,
211
211
  configure: async (device, coordinatorEndpoint, logger) => {
@@ -226,7 +226,7 @@ module.exports = [
226
226
  model: 'AC10691',
227
227
  description: 'Smart+ plug',
228
228
  vendor: 'OSRAM',
229
- extend: extend.switch(),
229
+ extend: extend.switch({disablePowerOnBehavior: true}),
230
230
  ota: ota.ledvance,
231
231
  whiteLabel: [{vendor: 'LEDVANCE', model: 'AC10691'}],
232
232
  configure: async (device, coordinatorEndpoint, logger) => {
package/devices/owon.js CHANGED
@@ -149,8 +149,13 @@ module.exports = [
149
149
  configure: async (device, coordinatorEndpoint, logger) => {
150
150
  const endpoint2 = device.getEndpoint(2);
151
151
  const endpoint3 = device.getEndpoint(3);
152
- await reporting.bind(endpoint2, coordinatorEndpoint, ['msIlluminanceMeasurement']);
153
- await reporting.bind(endpoint3, coordinatorEndpoint, ['msTemperatureMeasurement', 'msRelativeHumidity']);
152
+ if (device.modelID == 'PIR313') {
153
+ await reporting.bind(endpoint2, coordinatorEndpoint, ['msIlluminanceMeasurement']);
154
+ await reporting.bind(endpoint3, coordinatorEndpoint, ['msTemperatureMeasurement', 'msRelativeHumidity']);
155
+ } else {
156
+ await reporting.bind(endpoint3, coordinatorEndpoint, ['msIlluminanceMeasurement']);
157
+ await reporting.bind(endpoint2, coordinatorEndpoint, ['msTemperatureMeasurement', 'msRelativeHumidity']);
158
+ }
154
159
  device.powerSource = 'Battery';
155
160
  device.save();
156
161
  },
@@ -1561,7 +1561,7 @@ module.exports = [
1561
1561
  model: '4090230P9',
1562
1562
  vendor: 'Philips',
1563
1563
  description: 'Hue Liane (black)',
1564
- extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
1564
+ extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500], disableHueEffects: false}),
1565
1565
  },
1566
1566
  {
1567
1567
  zigbeeModel: ['929003053201'],
@@ -1589,14 +1589,14 @@ module.exports = [
1589
1589
  model: '3261030P6',
1590
1590
  vendor: 'Philips',
1591
1591
  description: 'Hue Being black',
1592
- extend: hueExtend.light_onoff_brightness_colortemp(),
1592
+ extend: hueExtend.light_onoff_brightness_colortemp({disableHueEffects: false}),
1593
1593
  },
1594
1594
  {
1595
1595
  zigbeeModel: ['3261031P6', '929003055001', '929003055101'],
1596
1596
  model: '3261031P6',
1597
1597
  vendor: 'Philips',
1598
1598
  description: 'Hue Being white',
1599
- extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
1599
+ extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 454], disableHueEffects: false}),
1600
1600
  },
1601
1601
  {
1602
1602
  zigbeeModel: ['3261048P6'],
@@ -2560,7 +2560,7 @@ module.exports = [
2560
2560
  model: '1741530P7',
2561
2561
  vendor: 'Philips',
2562
2562
  description: 'Hue Lily outdoor spot light',
2563
- extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
2563
+ extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500], disableHueEffects: false}),
2564
2564
  },
2565
2565
  {
2566
2566
  zigbeeModel: ['1741730V7'],
@@ -51,7 +51,7 @@ module.exports = [
51
51
  },
52
52
  },
53
53
  {
54
- fingerprint: [{modelID: 'Dimmer-Switch-ZB3.0', manufacturerName: 'Samotech'}],
54
+ fingerprint: [{modelID: 'Dimmer-Switch-ZB3.0', manufacturerName: 'Samotech'}, {modelID: 'HK_DIM_A', manufacturerName: 'Samotech'}],
55
55
  model: 'SM323',
56
56
  vendor: 'Samotech',
57
57
  description: 'ZigBee retrofit dimmer 250W',
@@ -766,14 +766,28 @@ module.exports = [
766
766
  model: 'EER50000',
767
767
  vendor: 'Schneider Electric',
768
768
  description: 'Wiser H-Relay (HACT)',
769
- fromZigbee: [fz.ignore_basic_report, fz.ignore_genOta, fz.ignore_zclversion_read, fz.wiser_smart_thermostat],
770
- toZigbee: [tz.thermostat_local_temperature, tz.thermostat_occupied_heating_setpoint],
771
- exposes: [exposes.climate().withSetpoint('occupied_heating_setpoint', 7, 30, 0.5).withLocalTemperature()],
769
+ fromZigbee: [fz.ignore_basic_report, fz.ignore_genOta, fz.ignore_zclversion_read, fz.wiser_smart_thermostat, fz.metering,
770
+ fz.identify],
771
+ toZigbee: [tz.thermostat_local_temperature, tz.thermostat_occupied_heating_setpoint, tz.wiser_fip_setting,
772
+ tz.wiser_hact_config, tz.wiser_zone_mode, tz.identify],
773
+ exposes: [exposes.climate().withSetpoint('occupied_heating_setpoint', 7, 30, 0.5).withLocalTemperature(),
774
+ e.power(), e.energy(),
775
+ exposes.enum('identify', ea.SET, ['0', '30', '60', '600', '900']).withDescription('Flash green tag for x seconds'),
776
+ exposes.enum('zone_mode',
777
+ ea.ALL, ['manual', 'schedule', 'energy_saver', 'holiday']),
778
+ exposes.enum('hact_config',
779
+ ea.ALL, ['unconfigured', 'setpoint_switch', 'setpoint_fip', 'fip_fip'])
780
+ .withDescription('Input (command) and output (control) behavior of actuator'),
781
+ exposes.enum('fip_setting',
782
+ ea.ALL, ['comfort', 'comfort_-1', 'comfort_-2', 'energy_saving', 'frost_protection', 'off'])
783
+ .withDescription('Output signal when operating in fil pilote mode (fip_fip)')],
772
784
  configure: async (device, coordinatorEndpoint, logger) => {
773
785
  const endpoint = device.getEndpoint(11);
774
- const binds = ['genBasic', 'genPowerCfg', 'hvacThermostat', 'msTemperatureMeasurement'];
786
+ const binds = ['genBasic', 'genPowerCfg', 'hvacThermostat', 'msTemperatureMeasurement', 'seMetering'];
775
787
  await reporting.bind(endpoint, coordinatorEndpoint, binds);
776
788
  await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
789
+ await reporting.readMeteringMultiplierDivisor(endpoint);
790
+ await reporting.instantaneousDemand(endpoint);
777
791
  },
778
792
  },
779
793
  {
package/devices/sonoff.js CHANGED
@@ -78,7 +78,7 @@ module.exports = [
78
78
  model: 'ZBMINI',
79
79
  vendor: 'SONOFF',
80
80
  description: 'Zigbee two way smart switch',
81
- extend: extend.switch(),
81
+ extend: extend.switch({disablePowerOnBehavior: true}),
82
82
  configure: async (device, coordinatorEndpoint, logger) => {
83
83
  // Has Unknown power source: https://github.com/Koenkk/zigbee2mqtt/issues/5362, force it here.
84
84
  device.powerSource = 'Mains (single phase)';
@@ -606,7 +606,7 @@ module.exports = [
606
606
  },
607
607
  },
608
608
  {
609
- fingerprint: [{modelID: 'TERNCY-DC01', manufacturer: 'Sunricher'}],
609
+ fingerprint: [{modelID: 'TERNCY-DC01', manufacturerName: 'Sunricher'}],
610
610
  model: 'SR-ZG9010A',
611
611
  vendor: 'Sunricher',
612
612
  description: 'Door windows sensor',
package/devices/tuya.js CHANGED
@@ -1084,7 +1084,6 @@ module.exports = [
1084
1084
  {modelID: 'TS0202', manufacturerName: '_TYZB01_71kfvvma'},
1085
1085
  {modelID: 'TS0202', manufacturerName: '_TZE200_bq5c8xfe'},
1086
1086
  {modelID: 'TS0202', manufacturerName: '_TYZB01_dl7cejts'},
1087
- {modelID: 'TS0202', manufacturerName: '_TYZB01_qjqgmqxr'},
1088
1087
  {modelID: 'TS0202', manufacturerName: '_TZ3000_nss8amz9'},
1089
1088
  {modelID: 'TS0202', manufacturerName: '_TZ3000_mmtwjmaq'},
1090
1089
  {modelID: 'TS0202', manufacturerName: '_TYZB01_zwvaj5wy'},
@@ -1513,6 +1512,7 @@ module.exports = [
1513
1512
  fingerprint: [
1514
1513
  {modelID: 'TS0601', manufacturerName: '_TZE200_nkjintbl'},
1515
1514
  {modelID: 'TS0601', manufacturerName: '_TZE200_ji1gn7rw'},
1515
+ {modelID: 'TS0601', manufacturerName: '_TZE200_3t91nb6k'},
1516
1516
  ],
1517
1517
  model: 'TS0601_switch_2_gang',
1518
1518
  vendor: 'TuYa',
@@ -2126,6 +2126,7 @@ module.exports = [
2126
2126
  {modelID: 'TS0601', manufacturerName: '_TZE200_9sfg7gm0'}, // HomeCloud
2127
2127
  {modelID: 'TS0601', manufacturerName: '_TZE200_2atgpdho'}, // HY367
2128
2128
  {modelID: 'TS0601', manufacturerName: '_TZE200_cpmgn2cf'},
2129
+ {modelID: 'TS0601', manufacturerName: '_TZE200_8thwkzxl'}, // Tervix eva2
2129
2130
  {modelID: 'TS0601', manufacturerName: '_TZE200_4eeyebrt'}, // Immax 07732B
2130
2131
  {modelID: 'TS0601', manufacturerName: '_TZE200_8whxpsiw'}, // EVOLVEO
2131
2132
  {modelID: 'TS0601', manufacturerName: '_TZE200_xby0s3ta'}, // Sandy Beach HY367
@@ -2539,14 +2540,14 @@ module.exports = [
2539
2540
  },
2540
2541
  },
2541
2542
  {
2542
- fingerprint: [160, 69, 68, 65, 64, 66].map((applicationVersion) => {
2543
+ fingerprint: [160, 100, 69, 68, 65, 64, 66].map((applicationVersion) => {
2543
2544
  return {modelID: 'TS011F', applicationVersion, priority: -1};
2544
2545
  }),
2545
2546
  model: 'TS011F_plug_3',
2546
2547
  description: 'Smart plug (with power monitoring by polling)',
2547
2548
  vendor: 'TuYa',
2548
2549
  whiteLabel: [{vendor: 'VIKEFON', model: 'TS011F'}, {vendor: 'BlitzWolf', model: 'BW-SHP15'},
2549
- {vendor: 'Avatto', model: 'MIUCOT10Z'}, {vendor: 'Neo', model: 'NAS-WR01B'}],
2550
+ {vendor: 'Avatto', model: 'MIUCOT10Z'}, {vendor: 'Neo', model: 'NAS-WR01B'}, {vendor: 'Neo', model: 'PLUG-001SPB2'}],
2550
2551
  ota: ota.zigbeeOTA,
2551
2552
  extend: tuya.extend.switch({electricalMeasurements: true, powerOutageMemory: true, indicatorMode: true, childLock: true}),
2552
2553
  configure: async (device, coordinatorEndpoint, logger) => {
@@ -2560,7 +2561,7 @@ module.exports = [
2560
2561
  onEvent: (type, data, device, options) =>
2561
2562
  tuya.onEventMeasurementPoll(type, data, device, options,
2562
2563
  device.applicationVersion !== 66, // polling for voltage, current and power
2563
- device.applicationVersion === 160 || device.applicationVersion === 66, // polling for energy
2564
+ [66, 100, 160].includes(device.applicationVersion), // polling for energy
2564
2565
  ),
2565
2566
  },
2566
2567
  {
@@ -3366,34 +3367,60 @@ module.exports = [
3366
3367
  ],
3367
3368
  },
3368
3369
  {
3369
- fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_lu01t0zl'},
3370
- {modelID: 'TS0601', manufacturerName: '_TZE200_vrfecyku'}],
3370
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE200_lu01t0zl', '_TZE200_vrfecyku']),
3371
3371
  model: 'MIR-HE200-TY',
3372
3372
  vendor: 'TuYa',
3373
3373
  description: 'Human presence sensor with fall function',
3374
- fromZigbee: [fz.tuya_radar_sensor_fall],
3375
- toZigbee: [tz.tuya_radar_sensor_fall],
3374
+ fromZigbee: [tuya.fz.datapoints],
3375
+ toZigbee: [tuya.tz.datapoints],
3376
+ configure: async (device, coordinatorEndpoint, logger) => {
3377
+ const endpoint = device.getEndpoint(1);
3378
+ await tuya.sendDataPointEnum(endpoint, tuya.dataPoints.trsfTumbleSwitch, false);
3379
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
3380
+ },
3376
3381
  exposes: [
3377
3382
  e.illuminance_lux(), e.presence(), e.occupancy(),
3378
3383
  exposes.numeric('motion_speed', ea.STATE).withDescription('Speed of movement'),
3379
- exposes.enum('motion_direction', ea.STATE, Object.values(tuya.tuyaRadar.motionDirection))
3384
+ exposes.enum('motion_direction', ea.STATE, ['standing_still', 'moving_forward', 'moving_backward'])
3380
3385
  .withDescription('direction of movement from the point of view of the radar'),
3381
3386
  exposes.numeric('radar_sensitivity', ea.STATE_SET).withValueMin(0).withValueMax(10).withValueStep(1)
3382
- .withDescription('sensitivity of the radar'),
3383
- exposes.enum('radar_scene', ea.STATE_SET, Object.values(tuya.tuyaRadar.radarScene))
3384
- .withDescription('presets for sensitivity for presence and movement'),
3387
+ .withDescription('Sensitivity of the radar'),
3388
+ exposes.enum('radar_scene', ea.STATE_SET, ['default', 'area', 'toilet', 'bedroom', 'parlour', 'office', 'hotel'])
3389
+ .withDescription('Presets for sensitivity for presence and movement'),
3385
3390
  exposes.enum('tumble_switch', ea.STATE_SET, ['ON', 'OFF']).withDescription('Tumble status switch'),
3386
3391
  exposes.numeric('fall_sensitivity', ea.STATE_SET).withValueMin(1).withValueMax(10).withValueStep(1)
3387
- .withDescription('fall sensitivity of the radar'),
3392
+ .withDescription('Fall sensitivity of the radar'),
3388
3393
  exposes.numeric('tumble_alarm_time', ea.STATE_SET).withValueMin(1).withValueMax(5).withValueStep(1)
3389
- .withUnit('min').withDescription('tumble alarm time'),
3390
- exposes.enum('fall_down_status', ea.STATE, Object.values(tuya.tuyaRadar.fallDown))
3391
- .withDescription('fall down status'),
3392
- exposes.text('static_dwell_alarm', ea.STATE).withDescription('static dwell alarm'),
3394
+ .withUnit('min').withDescription('Tumble alarm time'),
3395
+ exposes.enum('fall_down_status', ea.STATE, ['none', 'maybe_fall', 'fall'])
3396
+ .withDescription('Fall down status'),
3397
+ exposes.text('static_dwell_alarm', ea.STATE).withDescription('Static dwell alarm'),
3393
3398
  ],
3394
- configure: async (device, coordinatorEndpoint, logger) => {
3395
- const endpoint = device.getEndpoint(1);
3396
- await tuya.sendDataPointEnum(endpoint, tuya.dataPoints.trsfTumbleSwitch, false);
3399
+ meta: {
3400
+ tuyaDatapoints: [
3401
+ [1, 'presence', tuya.valueConverter.trueFalse],
3402
+ [2, 'radar_sensitivity', tuya.valueConverter.raw],
3403
+ [102, 'occupancy', tuya.valueConverterBasic.lookup({false: 1, true: 2})],
3404
+ [103, 'illuminance_lux', tuya.valueConverter.raw],
3405
+ [105, 'tumble_switch', tuya.valueConverter.plus1],
3406
+ [106, 'tumble_alarm_time', tuya.valueConverter.raw],
3407
+ [112, 'radar_scene', tuya.valueConverterBasic.lookup(
3408
+ {'default': 0, 'area': 1, 'toilet': 2, 'bedroom': 3, 'parlour': 4, 'office': 5, 'hotel': 6})],
3409
+ [114, 'motion_direction', tuya.valueConverterBasic.lookup(
3410
+ {'standing_still': 0, 'moving_forward': 1, 'moving_backward': 2})],
3411
+ [115, 'motion_speed', tuya.valueConverter.raw],
3412
+ [116, 'fall_down_status', tuya.valueConverterBasic.lookup({'none': 0, 'maybe_fall': 1, 'fall': 2})],
3413
+ [117, 'static_dwell_alarm', tuya.valueConverter.raw],
3414
+ [118, 'fall_sensitivity', tuya.valueConverter.raw],
3415
+ // Below are ignored
3416
+ [101, null, null], // reset_flag_code
3417
+ [104, null, null], // detection_flag_code
3418
+ [107, null, null], // radar_check_end_code
3419
+ [108, null, null], // radar_check_start_code
3420
+ [109, null, null], // hw_version_code
3421
+ [110, null, null], // sw_version_code
3422
+ [111, null, null], // radar_id_code
3423
+ ],
3397
3424
  },
3398
3425
  },
3399
3426
  {
package/devices/ubisys.js CHANGED
@@ -837,13 +837,17 @@ module.exports = [
837
837
  fromZigbee: [fz.legacy.ubisys_c4_scenes, fz.legacy.ubisys_c4_onoff, fz.legacy.ubisys_c4_level, fz.legacy.ubisys_c4_cover,
838
838
  ubisys.fz.configure_device_setup],
839
839
  toZigbee: [ubisys.tz.configure_device_setup],
840
- exposes: [e.action([
841
- '1_scene_*', '1_on', '1_off', '1_toggle', '1_level_move_down', '1_level_move_up',
842
- '2_scene_*', '2_on', '2_off', '2_toggle', '2_level_move_down', '2_level_move_up',
843
- '3_scene_*', '3_on', '3_off', '3_toggle', '3_level_move_down', '3_level_move_up',
844
- '4_scene_*', '4_on', '4_off', '4_toggle', '4_level_move_down', '4_level_move_up',
845
- '5_scene_*', '5_cover_open', '5_cover_close', '5_cover_stop',
846
- '6_scene_*', '6_cover_open', '6_cover_close', '6_cover_stop'])],
840
+ exposes: [
841
+ e.action([
842
+ 'toggle_s1', 'toggle_s2', 'toggle_s3', 'toggle_s4', 'on_s1', 'on_s2', 'on_s3', 'on_s4',
843
+ 'off_s1', 'off_s2', 'off_s3', 'off_s4', 'recall_*_s1', 'recal_*_s2', 'recall_*_s3', 'recal_*_s4',
844
+ 'brightness_move_up_s1', 'brightness_move_up_s2', 'brightness_move_up_s3', 'brightness_move_up_s4',
845
+ 'brightness_move_down_s1', 'brightness_move_down_s2', 'brightness_move_down_s3', 'brightness_move_down_s4',
846
+ 'brightness_stop_s1', 'brightness_stop_s2', 'brightness_stop_s3', 'brightness_stop_s4',
847
+ 'cover_open_s5', 'cover_close_s5', 'cover_stop_s5',
848
+ 'cover_open_s6', 'cover_close_s6', 'cover_stop_s6',
849
+ ]),
850
+ ],
847
851
  configure: async (device, coordinatorEndpoint, logger) => {
848
852
  for (const ep of [1, 2, 3, 4]) {
849
853
  await reporting.bind(device.getEndpoint(ep), coordinatorEndpoint, ['genScenes', 'genOnOff', 'genLevelCtrl']);
@@ -852,6 +856,10 @@ module.exports = [
852
856
  await reporting.bind(device.getEndpoint(ep), coordinatorEndpoint, ['genScenes', 'closuresWindowCovering']);
853
857
  }
854
858
  },
859
+ meta: {multiEndpoint: true},
860
+ endpoint: (device) => {
861
+ return {'s1': 1, 's2': 2, 's3': 3, 's4': 4, 's5': 5, 's6': 6};
862
+ },
855
863
  ota: ota.ubisys,
856
864
  },
857
865
  {
package/lib/ota/common.js CHANGED
@@ -261,12 +261,9 @@ async function isNewImageAvailable(current, logger, device, getImageMeta) {
261
261
  const [currentS, metaS] = [JSON.stringify(current), JSON.stringify(meta)];
262
262
  logger.debug(`Is new image available for '${device.ieeeAddr}', current '${currentS}', latest meta '${metaS}'`);
263
263
 
264
- if (meta.force) {
265
- return -1; // Negative number means the new firmware is 'newer' than current one
266
- }
267
-
264
+ // Negative number means the new firmware is 'newer' than current one
268
265
  return {
269
- available: Math.sign(current.fileVersion - meta.fileVersion),
266
+ available: meta.force ? -1 : Math.sign(current.fileVersion - meta.fileVersion),
270
267
  currentFileVersion: current.fileVersion,
271
268
  otaFileVersion: meta.fileVersion,
272
269
  };
package/lib/tuya.js CHANGED
@@ -1246,7 +1246,7 @@ const valueConverterBasic = {
1246
1246
  };
1247
1247
 
1248
1248
  const valueConverter = {
1249
- trueFalse: valueConverterBasic.lookup({1: true, 0: false}),
1249
+ trueFalse: valueConverterBasic.lookup({true: 1, false: 0}),
1250
1250
  onOff: valueConverterBasic.lookup({'ON': true, 'OFF': false}),
1251
1251
  powerOnBehavior: valueConverterBasic.lookup({'off': 0, 'on': 1, 'previous': 2}),
1252
1252
  lightType: valueConverterBasic.lookup({'led': 0, 'incandescent': 1, 'halogen': 2}),
@@ -1259,6 +1259,10 @@ const valueConverter = {
1259
1259
  divideBy10: valueConverterBasic.divideBy(10),
1260
1260
  divideBy1000: valueConverterBasic.divideBy(1000),
1261
1261
  raw: valueConverterBasic.raw(),
1262
+ plus1: {
1263
+ from: (v) => v + 1,
1264
+ to: (v) => v - 1,
1265
+ },
1262
1266
  static: (value) => {
1263
1267
  return {
1264
1268
  from: (v) => {
@@ -1577,7 +1581,7 @@ const tuyaTz = {
1577
1581
  'holiday_start_stop', 'holiday_temperature', 'comfort_temperature', 'eco_temperature', 'working_day',
1578
1582
  'week_schedule_programming', 'online', 'holiday_mode_date', 'schedule', 'schedule_monday', 'schedule_tuesday',
1579
1583
  'schedule_wednesday', 'schedule_thursday', 'schedule_friday', 'schedule_saturday', 'schedule_sunday', 'clear_fault',
1580
- 'scale_protection', 'error',
1584
+ 'scale_protection', 'error', 'radar_scene', 'radar_sensitivity', 'tumble_alarm_time', 'tumble_switch', 'fall_sensitivity',
1581
1585
  ],
1582
1586
  convertSet: async (entity, key, value, meta) => {
1583
1587
  // A set converter is only called once; therefore we need to loop
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zigbee-herdsman-converters",
3
- "version": "15.0.17",
3
+ "version": "15.0.19",
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": "^3.0.0",
41
- "zigbee-herdsman": "^0.14.83"
41
+ "zigbee-herdsman": "^0.14.84"
42
42
  },
43
43
  "devDependencies": {
44
44
  "eslint": "*",