zigbee-herdsman-converters 14.0.313 → 14.0.314

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.
@@ -3705,7 +3705,7 @@ const converters = {
3705
3705
  case tuya.dataPoints.haozeeLocalTemp:
3706
3706
  return {local_temperature: (value / 10).toFixed(1)};
3707
3707
  case tuya.dataPoints.haozeeBoostHeatingCountdown:
3708
- // quick heating countdown
3708
+ // quick heating countdown - not supported by this device
3709
3709
  return {boost_heating_countdown: value};
3710
3710
  case tuya.dataPoints.haozeeWindowDetection:
3711
3711
  // window check
@@ -3782,11 +3782,11 @@ const converters = {
3782
3782
  // working status 0 - pause 1 -working
3783
3783
  return {'heating': value ? 'ON' : 'OFF'};
3784
3784
  case tuya.dataPoints.haozeeBoostHeating:
3785
- // rapid heating -> boolean
3786
- break;
3785
+ // rapid heating -> boolean - not supported by this device
3786
+ return {'boost_heating': value ? 'ON' : 'OFF'};
3787
3787
  case tuya.dataPoints.haozeeTempCalibration:
3788
3788
  // temperature calibration
3789
- break;
3789
+ return {'local_temperature_calibration': ( value/10 ).toFixed(1)};
3790
3790
  case tuya.dataPoints.haozeeValvePosition:
3791
3791
  // valve position
3792
3792
  return {'position': value};
@@ -4020,32 +4020,33 @@ const converters = {
4020
4020
  minutes: value[2],
4021
4021
  },
4022
4022
  };
4023
- case tuya.dataPoints.scheduleWorkday: // set schedule for workdays [6,0,20,8,0,15,11,30,15,12,30,15,17,30,20,22,0,15]
4024
- // 6:00 - 20*, 8:00 - 15*, 11:30 - 15*, 12:30 - 15*, 17:30 - 20*, 22:00 - 15*
4025
- // Top bits in hours have special meaning
4026
- // 8: ??
4027
- // 7: Current schedule indicator
4028
- return {workdays: [
4029
- {hour: value[0] & 0x3F, minute: value[1], temperature: value[2]},
4030
- {hour: value[3] & 0x3F, minute: value[4], temperature: value[5]},
4031
- {hour: value[6] & 0x3F, minute: value[7], temperature: value[8]},
4032
- {hour: value[9] & 0x3F, minute: value[10], temperature: value[11]},
4033
- {hour: value[12] & 0x3F, minute: value[13], temperature: value[14]},
4034
- {hour: value[15] & 0x3F, minute: value[16], temperature: value[17]},
4035
- ]};
4036
- case tuya.dataPoints.scheduleHoliday: // set schedule for holidays [6,0,20,8,0,15,11,30,15,12,30,15,17,30,20,22,0,15]
4023
+ case tuya.dataPoints.scheduleWorkday: // set schedule for workdays/holidays [6,0,20,8,0,15,11,30,15,12,30,15,17,30,20,22,0,15]
4024
+ case tuya.dataPoints.scheduleHoliday: {
4037
4025
  // 6:00 - 20*, 8:00 - 15*, 11:30 - 15*, 12:30 - 15*, 17:30 - 20*, 22:00 - 15*
4038
4026
  // Top bits in hours have special meaning
4039
- // 8: ??
4040
- // 7: Current schedule indicator
4041
- return {holidays: [
4042
- {hour: value[0] & 0x3F, minute: value[1], temperature: value[2]},
4043
- {hour: value[3] & 0x3F, minute: value[4], temperature: value[5]},
4044
- {hour: value[6] & 0x3F, minute: value[7], temperature: value[8]},
4045
- {hour: value[9] & 0x3F, minute: value[10], temperature: value[11]},
4046
- {hour: value[12] & 0x3F, minute: value[13], temperature: value[14]},
4047
- {hour: value[15] & 0x3F, minute: value[16], temperature: value[17]},
4048
- ]};
4027
+ // 6: Current schedule indicator
4028
+ const items = [];
4029
+ const programmingMode = [];
4030
+
4031
+ for (let i = 0; i < 6; i++) {
4032
+ const item = {hour: value[i*3] & 0x3F, minute: value[i*3+1], temperature: value[i*3+2]};
4033
+ if (value[i*3] & 0x40) {
4034
+ item['current'] = true;
4035
+ }
4036
+
4037
+ items[i] = item;
4038
+ programmingMode[i] =
4039
+ item['hour'].toString().padStart(2, '0') + ':' +
4040
+ item['minute'].toString().padStart(2, '0') + '/' +
4041
+ item['temperature'] + '°C';
4042
+ }
4043
+
4044
+ if (dp == tuya.dataPoints.scheduleWorkday) {
4045
+ return {workdays: items, workdays_schedule: programmingMode.join(' ')};
4046
+ } else {
4047
+ return {holidays: items, holidays_schedule: programmingMode.join(' ')};
4048
+ }
4049
+ }
4049
4050
  case tuya.dataPoints.childLock:
4050
4051
  return {child_lock: value ? 'LOCK' : 'UNLOCK'};
4051
4052
  case tuya.dataPoints.siterwellWindowDetection:
@@ -6198,12 +6199,34 @@ const converters = {
6198
6199
  DJT11LM_vibration: {
6199
6200
  cluster: 'closuresDoorLock',
6200
6201
  type: ['attributeReport', 'readResponse'],
6202
+ options: [exposes.options.vibration_timeout()],
6201
6203
  convert: (model, msg, publish, options, meta) => {
6202
6204
  const result = {};
6203
6205
 
6204
6206
  if (msg.data['85']) {
6205
6207
  const vibrationLookup = {1: 'vibration', 2: 'tilt', 3: 'drop'};
6206
6208
  result.action = vibrationLookup[msg.data['85']];
6209
+
6210
+ // Device only sends a message when vibration is detected.
6211
+ // Therefore we need to publish a no_vibration message on our own.
6212
+ if (result.action === 'vibration') {
6213
+ result.vibration = true;
6214
+
6215
+ const timeout = options && options.hasOwnProperty('vibration_timeout') ? options.vibration_timeout : 90;
6216
+
6217
+ // Stop any existing timer cause vibration detected
6218
+ clearTimeout(globalStore.getValue(msg.endpoint, 'vibration_timer', null));
6219
+ globalStore.putValue(msg.endpoint, 'vibration_timer', null);
6220
+
6221
+ // Set new timer to publish no_vibration message
6222
+ if (timeout !== 0) {
6223
+ const timer = setTimeout(() => {
6224
+ publish({vibration: false});
6225
+ }, timeout * 1000);
6226
+
6227
+ globalStore.putValue(msg.endpoint, 'vibration_timer', timer);
6228
+ }
6229
+ }
6207
6230
  }
6208
6231
 
6209
6232
  if (msg.data['1283']) {
@@ -2807,7 +2807,7 @@ const converters = {
2807
2807
  haozee_thermostat_system_mode: {
2808
2808
  key: ['preset'],
2809
2809
  convertSet: async (entity, key, value, meta) => {
2810
- const lookup = {0: 'auto', 1: 'manual', 2: 'off', 3: 'on'};
2810
+ const lookup = {'auto': 0, 'manual': 1, 'off': 2, 'on': 3};
2811
2811
  await tuya.sendDataPointEnum(entity, tuya.dataPoints.haozeeSystemMode, lookup[value]);
2812
2812
  },
2813
2813
  },
@@ -2845,7 +2845,7 @@ const converters = {
2845
2845
  haozee_thermostat_temperature_calibration: {
2846
2846
  key: ['local_temperature_calibration'],
2847
2847
  convertSet: async (entity, key, value, meta) => {
2848
- let temp = Math.round(value * 1);
2848
+ let temp = Math.round(value * 10);
2849
2849
  if (temp < 0) {
2850
2850
  temp = 0xFFFFFFFF + temp + 1;
2851
2851
  }
@@ -4557,6 +4557,34 @@ const converters = {
4557
4557
  }
4558
4558
  },
4559
4559
  },
4560
+ tuya_thermostat_schedule_programming_mode: { // payload example "00:20/5°C 01:20/5°C 6:59/15°C 18:00/5°C 20:00/5°C 23:30/5°C"
4561
+ key: ['workdays_schedule', 'holidays_schedule'],
4562
+ convertSet: async (entity, key, value, meta) => {
4563
+ const dpId =
4564
+ (key === 'workdays_schedule') ?
4565
+ tuya.dataPoints.scheduleWorkday :
4566
+ tuya.dataPoints.scheduleHoliday;
4567
+ const payload = [];
4568
+ const items = value.split(' ');
4569
+
4570
+ for (let i = 0; i < 6; i++) {
4571
+ const hourTemperature = items[i].split('/');
4572
+ const hourMinute = hourTemperature[0].split(':', 2);
4573
+ const hour = parseInt(hourMinute[0]);
4574
+ const minute = parseInt(hourMinute[1]);
4575
+ const temperature = parseInt(hourTemperature[1]);
4576
+
4577
+ if (hour < 0 || hour >= 24 || minute < 0 || minute >= 60 || temperature < 5 || temperature >= 35) {
4578
+ throw new Error('Invalid hour, minute or temperature of:' + items[i]);
4579
+ }
4580
+
4581
+ payload[i*3] = hour;
4582
+ payload[i*3+1] = minute;
4583
+ payload[i*3+2] = temperature;
4584
+ }
4585
+ tuya.sendDataPointRaw(entity, dpId, payload);
4586
+ },
4587
+ },
4560
4588
  tuya_thermostat_week: {
4561
4589
  key: ['week'],
4562
4590
  convertSet: async (entity, key, value, meta) => {
package/devices/candeo.js CHANGED
@@ -13,7 +13,12 @@ module.exports = [
13
13
  const endpoint = device.getEndpoint(1);
14
14
  await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
15
15
  await reporting.onOff(endpoint);
16
- await reporting.brightness(endpoint);
16
+
17
+ // The default reporting from the Candeo dimmer can result in a lot of Zigbee traffic
18
+ // to the extent that reported brighness values can arrive at the endpoint out of order
19
+ // giving the appearance that the values are jumping around.
20
+ // Limit the reporting to once a second to give a smoother reporting of brightness.
21
+ await reporting.brightness(endpoint, {min: 1});
17
22
  },
18
23
  },
19
24
  ];
package/devices/hive.js CHANGED
@@ -332,6 +332,37 @@ module.exports = [
332
332
  await reporting.thermostatTemperatureSetpointHoldDuration(endpoint);
333
333
  },
334
334
  },
335
+ {
336
+ zigbeeModel: ['SLR1c'],
337
+ model: 'SLR1c',
338
+ vendor: 'Hive',
339
+ description: 'Heating thermostat',
340
+ fromZigbee: [fz.thermostat, fz.thermostat_weekly_schedule],
341
+ toZigbee: [tz.thermostat_local_temperature, tz.thermostat_system_mode, tz.thermostat_running_state,
342
+ tz.thermostat_occupied_heating_setpoint, tz.thermostat_control_sequence_of_operation, tz.thermostat_weekly_schedule,
343
+ tz.thermostat_clear_weekly_schedule, tz.thermostat_temperature_setpoint_hold, tz.thermostat_temperature_setpoint_hold_duration],
344
+ exposes: [
345
+ exposes.climate().withSetpoint('occupied_heating_setpoint', 5, 32, 0.5).withLocalTemperature()
346
+ .withSystemMode(['off', 'auto', 'heat']).withRunningState(['idle', 'heat']),
347
+ exposes.binary('temperature_setpoint_hold', ea.ALL, true, false)
348
+ .withDescription('Prevent changes. `false` = run normally. `true` = prevent from making changes.' +
349
+ ' Must be set to `false` when system_mode = off or `true` for heat'),
350
+ exposes.numeric('temperature_setpoint_hold_duration', ea.ALL).withValueMin(0).withValueMax(65535)
351
+ .withDescription('Period in minutes for which the setpoint hold will be active. 65535 = attribute not' +
352
+ ' used. 0 to 360 to match the remote display')],
353
+ meta: {disableDefaultResponse: true},
354
+ configure: async (device, coordinatorEndpoint, logger) => {
355
+ const endpoint = device.getEndpoint(5);
356
+ const binds = ['genBasic', 'genIdentify', 'genAlarms', 'genTime', 'hvacThermostat'];
357
+ await reporting.bind(endpoint, coordinatorEndpoint, binds);
358
+ await reporting.thermostatTemperature(endpoint);
359
+ await reporting.thermostatRunningState(endpoint);
360
+ await reporting.thermostatSystemMode(endpoint);
361
+ await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
362
+ await reporting.thermostatTemperatureSetpointHold(endpoint);
363
+ await reporting.thermostatTemperatureSetpointHoldDuration(endpoint);
364
+ },
365
+ },
335
366
  {
336
367
  zigbeeModel: ['SLR2'],
337
368
  model: 'SLR2',
package/devices/ikea.js CHANGED
@@ -621,7 +621,7 @@ module.exports = [
621
621
  extend: tradfriExtend.light_onoff_brightness_colortemp(),
622
622
  },
623
623
  {
624
- zigbeeModel: ['STARKVIND Air purifier'],
624
+ zigbeeModel: ['STARKVIND Air purifier', 'STARKVIND Air purifier table'],
625
625
  model: 'E2007',
626
626
  vendor: 'IKEA',
627
627
  description: 'STARKVIND air purifier',
package/devices/lidl.js CHANGED
@@ -133,6 +133,17 @@ module.exports = [
133
133
  device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 29});
134
134
  },
135
135
  },
136
+ {
137
+ fingerprint: [{modelID: 'TS0505B', manufacturerName: '_TZ3000_th6zqqy6'}],
138
+ model: 'HG07834B',
139
+ vendor: 'Lidl',
140
+ description: 'Livarno Lux E14 candle RGB',
141
+ ...extend.light_onoff_brightness_colortemp_color({disableColorTempStartup: true, colorTempRange: [153, 500]}),
142
+ meta: {applyRedFix: true, enhancedHue: false},
143
+ configure: async (device, coordinatorEndpoint, logger) => {
144
+ device.getEndpoint(1).saveClusterAttributeKeyValue('lightingColorCtrl', {colorCapabilities: 29});
145
+ },
146
+ },
136
147
  {
137
148
  fingerprint: [{modelID: 'TS0505A', manufacturerName: '_TZ3000_kdpxju99'}],
138
149
  model: 'HG06106A',
@@ -591,6 +591,15 @@ module.exports = [
591
591
  extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
592
592
  ota: ota.zigbeeOTA,
593
593
  },
594
+ {
595
+ zigbeeModel: ['LTA011'],
596
+ model: '929002471901',
597
+ vendor: 'Philips',
598
+ description: 'Hue white ambiance E27 1600lm with Bluetooth',
599
+ meta: {turnsOffAtBrightness1: true},
600
+ extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
601
+ ota: ota.zigbeeOTA,
602
+ },
594
603
  {
595
604
  zigbeeModel: ['LTA008'],
596
605
  model: '9290022267A',
@@ -2233,4 +2242,13 @@ module.exports = [
2233
2242
  extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
2234
2243
  ota: ota.zigbeeOTA,
2235
2244
  },
2245
+ {
2246
+ zigbeeModel: ['1746547P7'],
2247
+ model: '1746547P7',
2248
+ vendor: 'Philips',
2249
+ description: 'Hue White and color ambiance Daylo outdoor wall lamp',
2250
+ meta: {turnsOffAtBrightness1: true},
2251
+ extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
2252
+ ota: ota.zigbeeOTA,
2253
+ },
2236
2254
  ];
package/devices/tuya.js CHANGED
@@ -776,7 +776,8 @@ module.exports = [
776
776
  tz.tuya_thermostat_calibration, tz.tuya_thermostat_min_temp, tz.tuya_thermostat_max_temp,
777
777
  tz.tuya_thermostat_boost_time, tz.tuya_thermostat_comfort_temp, tz.tuya_thermostat_eco_temp,
778
778
  tz.tuya_thermostat_force_to_mode, tz.tuya_thermostat_force, tz.tuya_thermostat_preset, tz.tuya_thermostat_away_mode,
779
- tz.tuya_thermostat_window_detect, tz.tuya_thermostat_schedule, tz.tuya_thermostat_week, tz.tuya_thermostat_away_preset],
779
+ tz.tuya_thermostat_window_detect, tz.tuya_thermostat_schedule, tz.tuya_thermostat_week, tz.tuya_thermostat_away_preset,
780
+ tz.tuya_thermostat_schedule_programming_mode],
780
781
  exposes: [
781
782
  e.child_lock(), e.window_detection(), e.battery_low(), e.valve_detection(), e.position(),
782
783
  exposes.climate().withSetpoint('current_heating_setpoint', 5, 35, 0.5, ea.STATE_SET)
@@ -784,7 +785,12 @@ module.exports = [
784
785
  .withLocalTemperatureCalibration(ea.STATE_SET)
785
786
  .withAwayMode().withPreset(['schedule', 'manual', 'boost', 'complex', 'comfort', 'eco']),
786
787
  e.auto_lock(), e.away_mode(), e.away_preset_days(), e.boost_time(), e.comfort_temperature(), e.eco_temperature(), e.force(),
787
- e.max_temperature(), e.min_temperature(), e.week(), e.away_preset_temperature()],
788
+ e.max_temperature(), e.min_temperature(), e.away_preset_temperature(),
789
+ exposes.composite('programming_mode').withDescription('Schedule MODE ⏱ - In this mode, ' +
790
+ 'the device executes a preset week programming temperature time and temperature.')
791
+ .withFeature(e.week())
792
+ .withFeature(exposes.text('workdays_schedule', ea.STATE_SET))
793
+ .withFeature(exposes.text('holidays_schedule', ea.STATE_SET))],
788
794
  },
789
795
  {
790
796
  fingerprint: [
@@ -1122,9 +1128,11 @@ module.exports = [
1122
1128
  model: 'TS0115',
1123
1129
  vendor: 'TuYa',
1124
1130
  description: 'Multiprise with 4 AC outlets and 2 USB super charging ports (10A or 16A)',
1131
+ toZigbee: extend.switch().toZigbee.concat([tz.moes_power_on_behavior]),
1132
+ fromZigbee: extend.switch().fromZigbee.concat([fz.moes_power_on_behavior]),
1125
1133
  extend: extend.switch(),
1126
1134
  exposes: [e.switch().withEndpoint('l1'), e.switch().withEndpoint('l2'), e.switch().withEndpoint('l3'),
1127
- e.switch().withEndpoint('l4'), e.switch().withEndpoint('l5')],
1135
+ e.switch().withEndpoint('l4'), e.switch().withEndpoint('l5'), e.power_on_behavior()],
1128
1136
  whiteLabel: [{vendor: 'UseeLink', model: 'SM-SO306E/K/M'}],
1129
1137
  endpoint: (device) => {
1130
1138
  return {l1: 1, l2: 2, l3: 3, l4: 4, l5: 7};
@@ -1136,6 +1144,11 @@ module.exports = [
1136
1144
  await reporting.bind(device.getEndpoint(3), coordinatorEndpoint, ['genOnOff']);
1137
1145
  await reporting.bind(device.getEndpoint(4), coordinatorEndpoint, ['genOnOff']);
1138
1146
  await reporting.bind(device.getEndpoint(7), coordinatorEndpoint, ['genOnOff']);
1147
+ await device.getEndpoint(1).read('genOnOff', ['onOff', 'moesStartUpOnOff']);
1148
+ await device.getEndpoint(2).read('genOnOff', ['onOff']);
1149
+ await device.getEndpoint(3).read('genOnOff', ['onOff']);
1150
+ await device.getEndpoint(4).read('genOnOff', ['onOff']);
1151
+ await device.getEndpoint(7).read('genOnOff', ['onOff']);
1139
1152
  },
1140
1153
  },
1141
1154
  {
package/devices/xiaomi.js CHANGED
@@ -1127,7 +1127,7 @@ module.exports = [
1127
1127
  fromZigbee: [fz.xiaomi_battery, fz.DJT11LM_vibration],
1128
1128
  toZigbee: [tz.DJT11LM_vibration_sensitivity],
1129
1129
  exposes: [
1130
- e.battery(), e.action(['vibration', 'tilt', 'drop']),
1130
+ e.battery(), e.vibration(), e.action(['vibration', 'tilt', 'drop']),
1131
1131
  exposes.numeric('strength', ea.STATE), exposes.enum('sensitivity', ea.STATE_SET, ['low', 'medium', 'high']),
1132
1132
  e.angle_axis('angle_x'), e.angle_axis('angle_y'), e.angle_axis('angle_z'), e.battery_voltage(),
1133
1133
  ],
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zigbee-herdsman-converters",
3
- "version": "14.0.313",
3
+ "version": "14.0.314",
4
4
  "lockfileVersion": 1,
5
5
  "requires": true,
6
6
  "dependencies": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zigbee-herdsman-converters",
3
- "version": "14.0.313",
3
+ "version": "14.0.314",
4
4
  "description": "Collection of device converters to be used with zigbee-herdsman",
5
5
  "main": "index.js",
6
6
  "files": [