zigbee-herdsman-converters 14.0.375 → 14.0.379

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.
@@ -3672,7 +3672,7 @@ const converters = {
3672
3672
  case tuya.dataPoints.moesSboostHeatingCountdown:
3673
3673
  return {boost_heating_countdown: value};
3674
3674
  case tuya.dataPoints.moesSreset:
3675
- break;
3675
+ return {valve_state: value ? 'CLOSED' : 'OPEN'};
3676
3676
  case tuya.dataPoints.moesSwindowDetectionFunktion_A2:
3677
3677
  return {window_detection: value ? 'ON' : 'OFF'};
3678
3678
  case tuya.dataPoints.moesSwindowDetection:
@@ -4136,6 +4136,51 @@ const converters = {
4136
4136
  }
4137
4137
  },
4138
4138
  },
4139
+ evanell_thermostat: {
4140
+ cluster: 'manuSpecificTuya',
4141
+ type: ['commandDataResponse', 'commandDataReport'],
4142
+ convert: (model, msg, publish, options, meta) => {
4143
+ const result = {};
4144
+ for (const dpValue of msg.data.dpValues) {
4145
+ const value = tuya.getDataValue(dpValue);
4146
+ switch (dpValue.dp) {
4147
+ case tuya.dataPoints.evanellChildLock:
4148
+ result.child_lock = value ? 'LOCK' : 'UNLOCK';
4149
+ break;
4150
+ case tuya.dataPoints.evanellBattery:
4151
+ result.battery = value;
4152
+ break;
4153
+ case tuya.dataPoints.evanellHeatingSetpoint:
4154
+ result.current_heating_setpoint = value/10;
4155
+ break;
4156
+ case tuya.dataPoints.evanellLocalTemp:
4157
+ result.local_temperature = value/10;
4158
+ break;
4159
+ case tuya.dataPoints.evanellMode:
4160
+ switch (value) {
4161
+ case 0: // manual
4162
+ result.system_mode = 'auto';
4163
+ break;
4164
+ case 2: // away
4165
+ result.system_mode = 'heat';
4166
+ break;
4167
+ case 3: // auto
4168
+ result.system_mode = 'off';
4169
+ break;
4170
+ default:
4171
+ meta.logger.warn('zigbee-herdsman-converters:evanell_thermostat: ' +
4172
+ `Mode ${value} is not recognized.`);
4173
+ break;
4174
+ }
4175
+ break;
4176
+ default:
4177
+ meta.logger.warn(`zigbee-herdsman-converters:evanell_thermostat: NOT RECOGNIZED ` +
4178
+ `DP #${dpValue.dp} with data ${JSON.stringify(dpValue)}`);
4179
+ }
4180
+ }
4181
+ return result;
4182
+ },
4183
+ },
4139
4184
  etop_thermostat: {
4140
4185
  cluster: 'manuSpecificTuya',
4141
4186
  type: ['commandDataResponse', 'commandDataReport'],
@@ -7516,22 +7561,33 @@ const converters = {
7516
7561
  const dpValue = tuya.firstDpValue(msg, meta, 'tuya_radar_sensor');
7517
7562
  const dp = dpValue.dp;
7518
7563
  const value = tuya.getDataValue(dpValue);
7564
+ let result = null;
7519
7565
  switch (dp) {
7520
7566
  case tuya.dataPoints.trsPresenceState:
7521
- return {presence: {0: false, 1: true}[value]};
7567
+ result = {presence: {0: false, 1: true}[value]};
7568
+ break;
7522
7569
  case tuya.dataPoints.trsMotionState:
7523
- return {motion: {1: false, 2: true}[value]};
7570
+ result = {occupancy: {1: false, 2: true}[value]};
7571
+ break;
7524
7572
  case tuya.dataPoints.trsMotionSpeed:
7525
- return {motion_speed: value};
7573
+ result = {motion_speed: value};
7574
+ break;
7526
7575
  case tuya.dataPoints.trsMotionDirection:
7527
- return {motion_direction: {0: 'standing_still', 1: 'moving_forward', 2: 'moving_backward'}[value]};
7576
+ result = {motion_direction: tuya.tuyaRadar.motionDirection[value]};
7577
+ break;
7528
7578
  case tuya.dataPoints.trsScene:
7529
- return {radar_scene: {'default': 0, 'area': 1, 'toilet': 2, 'bedroom': 3, 'parlour': 4, 'office': 5, 'hotel': 6}[value]};
7579
+ result = {radar_scene: tuya.tuyaRadar.radarScene[value]};
7580
+ break;
7530
7581
  case tuya.dataPoints.trsSensitivity:
7531
- return {radar_sensitivity: value};
7582
+ result = {radar_sensitivity: value};
7583
+ break;
7532
7584
  case tuya.dataPoints.trsIlluminanceLux:
7533
- return {illuminance_lux: value};
7585
+ result = {illuminance_lux: value};
7586
+ break;
7587
+ default:
7588
+ meta.logger.warn(`fromZigbee.tuya_radar_sensor: NOT RECOGNIZED DP ${dp} with data ${JSON.stringify(dpValue)}`);
7534
7589
  }
7590
+ return result;
7535
7591
  },
7536
7592
  },
7537
7593
  tuya_smart_vibration_sensor: {
@@ -5029,6 +5029,28 @@ const converters = {
5029
5029
  }
5030
5030
  },
5031
5031
  },
5032
+ ts0201_temperature_humidity_alarm: {
5033
+ key: ['alarm_humidity_max', 'alarm_humidity_min', 'alarm_temperature_max', 'alarm_temperature_min'],
5034
+ convertSet: async (entity, key, value, meta) => {
5035
+ switch (key) {
5036
+ case 'alarm_temperature_max':
5037
+ case 'alarm_temperature_min':
5038
+ case 'alarm_humidity_max':
5039
+ case 'alarm_humidity_min': {
5040
+ // await entity.write('manuSpecificTuya_2', {[key]: value});
5041
+ // instead write as custom attribute to override incorrect herdsman dataType from uint16 to int16
5042
+ // https://github.com/Koenkk/zigbee-herdsman/blob/v0.13.191/src/zcl/definition/cluster.ts#L4235
5043
+ const keyToAttributeLookup = {'alarm_temperature_max': 0xD00A, 'alarm_temperature_min': 0xD00B,
5044
+ 'alarm_humidity_max': 0xD00D, 'alarm_humidity_min': 0xD00E};
5045
+ const payload = {[keyToAttributeLookup[key]]: {value: value, type: 0x29}};
5046
+ await entity.write('manuSpecificTuya_2', payload);
5047
+ break;
5048
+ }
5049
+ default: // Unknown key
5050
+ meta.logger.warn(`Unhandled key ${key}`);
5051
+ }
5052
+ },
5053
+ },
5032
5054
  heiman_ir_remote: {
5033
5055
  key: ['send_key', 'create', 'learn', 'delete', 'get_list'],
5034
5056
  convertSet: async (entity, key, value, meta) => {
@@ -5066,7 +5088,7 @@ const converters = {
5066
5088
  key: ['scene_store'],
5067
5089
  convertSet: async (entity, key, value, meta) => {
5068
5090
  const isGroup = entity.constructor.name === 'Group';
5069
- const groupid = isGroup ? entity.groupID : 0;
5091
+ const groupid = isGroup ? entity.groupID : value.hasOwnProperty('group_id') ? value.group_id : 0;
5070
5092
  let sceneid = value;
5071
5093
  let scenename = null;
5072
5094
  if (typeof value === 'object') {
@@ -5166,7 +5188,7 @@ const converters = {
5166
5188
  }
5167
5189
 
5168
5190
  const isGroup = entity.constructor.name === 'Group';
5169
- const groupid = isGroup ? entity.groupID : 0;
5191
+ const groupid = isGroup ? entity.groupID : value.hasOwnProperty('group_id') ? value.group_id : 0;
5170
5192
  const sceneid = value.ID;
5171
5193
  const scenename = value.name;
5172
5194
  const transtime = value.hasOwnProperty('transition') ? value.transition : 0;
@@ -5411,6 +5433,35 @@ const converters = {
5411
5433
  await tuya.sendDataPointValue(entity, tuya.dataPoints.saswellTempCalibration, value);
5412
5434
  },
5413
5435
  },
5436
+ evanell_thermostat_current_heating_setpoint: {
5437
+ key: ['current_heating_setpoint'],
5438
+ convertSet: async (entity, key, value, meta) => {
5439
+ const temp = Math.round(value * 10);
5440
+ await tuya.sendDataPointValue(entity, tuya.dataPoints.evanellHeatingSetpoint, temp);
5441
+ },
5442
+ },
5443
+ evanell_thermostat_system_mode: {
5444
+ key: ['system_mode'],
5445
+ convertSet: async (entity, key, value, meta) => {
5446
+ switch (value) {
5447
+ case 'off':
5448
+ await tuya.sendDataPointEnum(entity, tuya.dataPoints.evanellMode, 3 /* off */);
5449
+ break;
5450
+ case 'heat':
5451
+ await tuya.sendDataPointEnum(entity, tuya.dataPoints.evanellMode, 2 /* manual */);
5452
+ break;
5453
+ case 'auto':
5454
+ await tuya.sendDataPointEnum(entity, tuya.dataPoints.evanellMode, 0 /* auto */);
5455
+ break;
5456
+ }
5457
+ },
5458
+ },
5459
+ evanell_thermostat_child_lock: {
5460
+ key: ['child_lock'],
5461
+ convertSet: async (entity, key, value, meta) => {
5462
+ await tuya.sendDataPointBool(entity, tuya.dataPoints.evanellChildLock, value === 'LOCK');
5463
+ },
5464
+ },
5414
5465
  silvercrest_smart_led_string: {
5415
5466
  key: ['color', 'brightness', 'effect'],
5416
5467
  convertSet: async (entity, key, value, meta) => {
@@ -6244,11 +6295,13 @@ const converters = {
6244
6295
  convertSet: async (entity, key, value, meta) => {
6245
6296
  switch (key) {
6246
6297
  case 'radar_scene':
6247
- await tuya.sendDataPointValue(entity, tuya.dataPoints.trsScene, value);
6248
- return {state: {radar_scene: value}};
6298
+ await tuya.sendDataPointEnum(entity, tuya.dataPoints.trsScene, utils.getKey(tuya.tuyaRadar.radarScene, value));
6299
+ break;
6249
6300
  case 'radar_sensitivity':
6250
6301
  await tuya.sendDataPointValue(entity, tuya.dataPoints.trsSensitivity, value);
6251
- return {state: {radar_sensitivity: value}};
6302
+ break;
6303
+ default: // Unknown Key
6304
+ meta.logger.warn(`toZigbee.tuya_radar_sensor: Unhandled Key ${key}`);
6252
6305
  }
6253
6306
  },
6254
6307
  },
@@ -30,19 +30,22 @@ module.exports = [
30
30
  vendor: 'BTicino',
31
31
  description: 'Dimmer switch with neutral',
32
32
  extend: extend.light_onoff_brightness({noConfigure: true}),
33
- exposes: [
34
- e.light_brightness(),
33
+ fromZigbee: [fz.brightness, fz.identify, fz.on_off, fz.lighting_ballast_configuration],
34
+ toZigbee: [tz.light_onoff_brightness, tz.legrand_settingAlwaysEnableLed, tz.legrand_settingEnableLedIfOn,
35
+ tz.legrand_settingEnableDimmer, tz.legrand_identify, tz.ballast_config],
36
+ exposes: [e.light_brightness(),
37
+ exposes.numeric('ballast_minimum_level', ea.ALL).withValueMin(1).withValueMax(254)
38
+ .withDescription('Specifies the minimum brightness value'),
39
+ exposes.numeric('ballast_maximum_level', ea.ALL).withValueMin(1).withValueMax(254)
40
+ .withDescription('Specifies the maximum brightness value'),
35
41
  exposes.binary('dimmer_enabled', ea.STATE_SET, 'ON', 'OFF').withDescription('Allow the device to change brightness'),
36
42
  exposes.binary('permanent_led', ea.STATE_SET, 'ON', 'OFF').withDescription('Enable or disable the permanent blue LED'),
37
- exposes.binary('led_when_on', ea.STATE_SET, 'ON', 'OFF').withDescription('Enables the LED when the light is on'),
38
- ],
39
- fromZigbee: [fz.brightness, fz.identify, fz.on_off],
40
- toZigbee: [tz.light_onoff_brightness, tz.legrand_settingAlwaysEnableLed, tz.legrand_settingEnableLedIfOn,
41
- tz.legrand_settingEnableDimmer, tz.legrand_identify],
43
+ exposes.binary('led_when_on', ea.STATE_SET, 'ON', 'OFF').withDescription('Enables the LED when the light is on')],
42
44
  configure: async (device, coordinatorEndpoint, logger) => {
43
45
  await extend.light_onoff_brightness().configure(device, coordinatorEndpoint, logger);
44
46
  const endpoint = device.getEndpoint(1);
45
- await reporting.bind(endpoint, coordinatorEndpoint, ['genIdentify', 'genOnOff', 'genLevelCtrl', 'genBinaryInput']);
47
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genIdentify', 'genOnOff', 'genLevelCtrl',
48
+ 'genBinaryInput', 'lightingBallastCfg']);
46
49
  await reporting.onOff(endpoint);
47
50
  await reporting.brightness(endpoint);
48
51
  },
@@ -0,0 +1,29 @@
1
+ const exposes = require('../lib/exposes');
2
+ const fz = require('../converters/fromZigbee');
3
+ const tz = require('../converters/toZigbee');
4
+ const tuya = require('../lib/tuya');
5
+ const reporting = require('../lib/reporting');
6
+ const e = exposes.presets;
7
+ const ea = exposes.access;
8
+
9
+ module.exports = [
10
+ {
11
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_dmfguuli'}],
12
+ model: 'EZ200',
13
+ vendor: 'Evanell',
14
+ description: 'Thermostatic radiator valve',
15
+ fromZigbee: [fz.evanell_thermostat],
16
+ toZigbee: [tz.evanell_thermostat_current_heating_setpoint, tz.evanell_thermostat_system_mode,
17
+ tz.evanell_thermostat_child_lock],
18
+ onEvent: tuya.onEventSetTime,
19
+ configure: async (device, coordinatorEndpoint, logger) => {
20
+ const endpoint = device.getEndpoint(1);
21
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genBasic']);
22
+ },
23
+ exposes: [e.child_lock(), e.battery(),
24
+ exposes.climate()
25
+ .withSetpoint('current_heating_setpoint', 5, 30, 0.5, ea.STATE_SET).withLocalTemperature(ea.STATE)
26
+ .withSystemMode(['off', 'heat', 'auto'], ea.STATE_SET),
27
+ ],
28
+ },
29
+ ];
package/devices/hive.js CHANGED
@@ -2,9 +2,9 @@ const exposes = require('../lib/exposes');
2
2
  const fz = {...require('../converters/fromZigbee'), legacy: require('../lib/legacy').fromZigbee};
3
3
  const tz = require('../converters/toZigbee');
4
4
  const globalStore = require('../lib/store');
5
- const constants = require('../lib/constants');
6
5
  const reporting = require('../lib/reporting');
7
6
  const extend = require('../lib/extend');
7
+ const {extendDevice} = require('../lib/utils');
8
8
  const e = exposes.presets;
9
9
  const ea = exposes.access;
10
10
 
@@ -149,130 +149,12 @@ module.exports = [
149
149
  }
150
150
  },
151
151
  },
152
- {
153
- // TRV001 is the same as Danfoss Ally (eTRV0100) and Popp eT093WRO. If implementing anything, please consider
154
- // changing those two too.
152
+ extendDevice(require('./danfoss'), '014G2461', {
155
153
  zigbeeModel: ['TRV001'],
156
154
  model: 'UK7004240',
157
155
  vendor: 'Hive',
158
- description: 'Radiator valve based on Danfos Ally',
159
- fromZigbee: [fz.battery, fz.thermostat, fz.thermostat_weekly_schedule, fz.hvac_user_interface, fz.danfoss_thermostat],
160
- toZigbee: [tz.danfoss_thermostat_occupied_heating_setpoint, tz.thermostat_local_temperature, tz.danfoss_mounted_mode_active,
161
- tz.danfoss_mounted_mode_control, tz.danfoss_thermostat_vertical_orientation, tz.danfoss_algorithm_scale_factor,
162
- tz.danfoss_heat_available, tz.danfoss_heat_required, tz.danfoss_day_of_week, tz.danfoss_trigger_time,
163
- tz.danfoss_window_open_internal, tz.danfoss_window_open_external, tz.danfoss_load_estimate,
164
- tz.danfoss_viewing_direction, tz.danfoss_external_measured_room_sensor, tz.thermostat_keypad_lockout,
165
- tz.thermostat_system_mode, tz.danfoss_load_balancing_enable, tz.danfoss_load_room_mean,
166
- tz.thermostat_weekly_schedule, tz.thermostat_clear_weekly_schedule, tz.thermostat_programming_operation_mode],
167
- exposes: [e.battery(), e.keypad_lockout(), e.programming_operation_mode(),
168
- exposes.binary('mounted_mode_active', ea.STATE_GET, true, false)
169
- .withDescription('Is the unit in mounting mode. This is set to `false` for mounted (already on ' +
170
- 'the radiator) or `true` for not mounted (after factory reset)'),
171
- exposes.binary('mounted_mode_control', ea.ALL, true, false)
172
- .withDescription('Set the unit mounting mode. `false` Go to Mounted Mode or `true` Go to Mounting Mode'),
173
- exposes.binary('thermostat_vertical_orientation', ea.ALL, true, false)
174
- .withDescription('Thermostat Orientation. This is important for the PID in how it assesses temperature. ' +
175
- '`false` Horizontal or `true` Vertical'),
176
- exposes.binary('viewing_direction', ea.ALL, true, false)
177
- .withDescription('Viewing/Display Direction. `false` Horizontal or `true` Vertical'),
178
- exposes.binary('heat_available', ea.ALL, true, false)
179
- .withDescription('Not clear how this affects operation. `false` No Heat Available or `true` Heat Available'),
180
- exposes.binary('heat_required', ea.STATE_GET, true, false)
181
- .withDescription('Whether or not the unit needs warm water. `false` No Heat Request or `true` Heat Request'),
182
- exposes.enum('setpoint_change_source', ea.STATE, ['manual', 'schedule', 'externally'])
183
- .withDescription('Values observed are `0` (manual), `1` (schedule) or `2` (externally)'),
184
- exposes.climate().withSetpoint('occupied_heating_setpoint', 5, 32, 0.5).withLocalTemperature().withPiHeatingDemand()
185
- .withSystemMode(['heat']).withRunningState(['idle', 'heat'], ea.STATE),
186
- exposes.numeric('external_measured_room_sensor', ea.ALL)
187
- .withDescription('Set at maximum 3 hours interval but not more often than every 30 minutes and 0.1 ' +
188
- 'degrees difference. Resets every 3hours to standard. e.g. 21C = 2100 (-8000=undefined).')
189
- .withValueMin(-8000).withValueMax(3500),
190
- exposes.numeric('window_open_internal', ea.STATE_GET).withValueMin(0).withValueMax(4)
191
- .withDescription('0=Quarantine, 1=Windows are closed, 2=Hold - Windows are maybe about to open, ' +
192
- '3=Open window detected, 4=In window open state from external but detected closed locally'),
193
- exposes.binary('window_open_external', ea.ALL, true, false)
194
- .withDescription('Set if the window is open or close. This setting will trigger a change in the internal ' +
195
- 'window and heating demand. `false` (windows are closed) or `true` (windows are open)'),
196
- exposes.enum('day_of_week', ea.ALL,
197
- ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'away_or_vacation'])
198
- .withDescription('Exercise day of week: 0=Sun...6=Sat, 7=undefined'),
199
- exposes.numeric('trigger_time', ea.ALL).withValueMin(0).withValueMax(65535)
200
- .withDescription('Exercise trigger time. Minutes since midnight (65535=undefined). Range 0 to 1439'),
201
- exposes.numeric('algorithm_scale_factor', ea.ALL).withValueMin(1).withValueMax(10)
202
- .withDescription('Scale factor of setpoint filter timeconstant ("aggressiveness" of control algorithm) '+
203
- '1= Quick ... 5=Moderate ... 10=Slow'),
204
- exposes.binary('load_balancing_enable', ea.ALL, true, false)
205
- .withDescription('Whether or not the thermostat acts as standalone thermostat or shares load with other ' +
206
- 'thermostats in the room. The gateway must update load_room_mean if enabled.'),
207
- exposes.numeric('load_room_mean', ea.ALL)
208
- .withDescription('Mean radiator load for room calculated by gateway for load balancing purposes (-8000=undefined)')
209
- .withValueMin(-8000).withValueMax(2000),
210
- exposes.numeric('load_estimate', ea.STATE_GET)
211
- .withDescription('Load estimate on this radiator')],
212
- configure: async (device, coordinatorEndpoint, logger) => {
213
- const endpoint = device.getEndpoint(1);
214
- const options = {manufacturerCode: 0x1246};
215
- await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'hvacThermostat']);
216
-
217
- // standard ZCL attributes
218
- await reporting.batteryPercentageRemaining(endpoint);
219
- await reporting.thermostatTemperature(endpoint);
220
- await reporting.thermostatPIHeatingDemand(endpoint);
221
- await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
222
-
223
- // danfoss attributes
224
- await endpoint.configureReporting('hvacThermostat', [{
225
- attribute: 'danfossMountedModeActive',
226
- minimumReportInterval: constants.repInterval.MINUTE,
227
- maximumReportInterval: constants.repInterval.MAX,
228
- reportableChange: 1,
229
- }], options);
230
- await endpoint.configureReporting('hvacThermostat', [{
231
- attribute: 'danfossWindowOpenInternal',
232
- minimumReportInterval: constants.repInterval.MINUTE,
233
- maximumReportInterval: constants.repInterval.HOUR,
234
- reportableChange: 1,
235
- }], options);
236
- await endpoint.configureReporting('hvacThermostat', [{
237
- attribute: 'danfossHeatRequired',
238
- minimumReportInterval: constants.repInterval.MINUTE,
239
- maximumReportInterval: constants.repInterval.HOUR,
240
- reportableChange: 1,
241
- }], options);
242
- await endpoint.configureReporting('hvacThermostat', [{
243
- attribute: 'danfossExternalMeasuredRoomSensor',
244
- minimumReportInterval: constants.repInterval.MINUTE,
245
- maximumReportInterval: constants.repInterval.MAX,
246
- reportableChange: 1,
247
- }], options);
248
-
249
- await endpoint.read('hvacThermostat', [
250
- 'danfossWindowOpenExternal',
251
- 'danfossDayOfWeek',
252
- 'danfossTriggerTime',
253
- 'danfossAlgorithmScaleFactor',
254
- 'danfossHeatAvailable',
255
- 'danfossMountedModeControl',
256
- 'danfossMountedModeActive',
257
- 'danfossExternalMeasuredRoomSensor',
258
- 'danfossLoadBalancingEnable',
259
- 'danfossLoadRoomMean',
260
- ], options);
261
-
262
- // read systemMode to have an initial value
263
- await endpoint.read('hvacThermostat', ['systemMode']);
264
-
265
- // read keypadLockout, we don't need reporting as it cannot be set physically on the device
266
- await endpoint.read('hvacUserInterfaceCfg', ['keypadLockout']);
267
-
268
- // Seems that it is bug in Danfoss, device does not asks for the time with binding
269
- // So, we need to write time during configure (same as for HEIMAN devices)
270
- const time = Math.round(((new Date()).getTime() - constants.OneJanuary2000) / 1000);
271
- // Time-master + synchronised
272
- const values = {timeStatus: 3, time: time, timeZone: ((new Date()).getTimezoneOffset() * -1) * 60};
273
- endpoint.write('genTime', values);
274
- },
275
- },
156
+ description: 'Radiator valve based on Danfoss Ally (014G2461)',
157
+ }),
276
158
  {
277
159
  zigbeeModel: ['SLR1'],
278
160
  model: 'SLR1',
@@ -0,0 +1,18 @@
1
+ const reporting = require('../lib/reporting');
2
+ const extend = require('../lib/extend');
3
+
4
+ module.exports = [
5
+ {
6
+ zigbeeModel: ['35938'],
7
+ model: 'ZB3102',
8
+ vendor: 'Jasco Products',
9
+ description: 'Zigbee plug-in smart dimmer',
10
+ extend: extend.light_onoff_brightness({noConfigure: true}),
11
+ configure: async (device, coordinatorEndpoint, logger) => {
12
+ await extend.light_onoff_brightness().configure(device, coordinatorEndpoint, logger);
13
+ const endpoint = device.getEndpoint(1);
14
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
15
+ await reporting.onOff(endpoint);
16
+ },
17
+ },
18
+ ];
@@ -3,6 +3,13 @@ const extend = require('../lib/extend');
3
3
  const reporting = require('../lib/reporting');
4
4
 
5
5
  module.exports = [
6
+ {
7
+ zigbeeModel: ['A60S TW'],
8
+ model: 'AC33898',
9
+ vendor: 'LEDVANCE',
10
+ description: ' Smart+ LED classic E27 Zigbee 10W/810lm',
11
+ extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 370]}),
12
+ },
6
13
  {
7
14
  zigbeeModel: ['Outdoor Plug', 'Plug Value'],
8
15
  model: 'AC26940/AC31266',
package/devices/moes.js CHANGED
@@ -206,7 +206,7 @@ module.exports = [
206
206
  tz.moesS_thermostat_system_mode, tz.moesS_thermostat_schedule_programming],
207
207
  exposes: [
208
208
  e.battery(), e.child_lock(), e.eco_mode(), e.eco_temperature(), e.max_temperature(), e.min_temperature(),
209
- e.position(), e.window_detection(),
209
+ e.valve_state(), e.position(), e.window_detection(),
210
210
  exposes.binary('window', ea.STATE, 'CLOSED', 'OPEN').withDescription('Window status closed or open '),
211
211
  exposes.climate()
212
212
  .withLocalTemperature(ea.STATE).withSetpoint('current_heating_setpoint', 5, 35, 0.5, ea.STATE_SET)
@@ -29,6 +29,15 @@ const hueExtend = {
29
29
  };
30
30
 
31
31
  module.exports = [
32
+ {
33
+ zigbeeModel: ['LCX004'],
34
+ model: '929002994901',
35
+ vendor: 'Philips',
36
+ description: 'Hue gradient lightstrip',
37
+ meta: {turnsOffAtBrightness1: true},
38
+ extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
39
+ ota: ota.zigbeeOTA,
40
+ },
32
41
  {
33
42
  zigbeeModel: ['929003047501'],
34
43
  model: '929003047501',
@@ -2574,4 +2583,13 @@ module.exports = [
2574
2583
  extend: hueExtend.light_onoff_brightness(),
2575
2584
  ota: ota.zigbeeOTA,
2576
2585
  },
2586
+ {
2587
+ zigbeeModel: ['LWA019'],
2588
+ model: '9290024691',
2589
+ vendor: 'Philips',
2590
+ description: 'Hue white single filament bulb A19 E26 with Bluetooth (1100 Lumen)',
2591
+ meta: {turnsOffAtBrightness1: true},
2592
+ extend: hueExtend.light_onoff_brightness(),
2593
+ ota: ota.zigbeeOTA,
2594
+ },
2577
2595
  ];
package/devices/popp.js CHANGED
@@ -1,136 +1,10 @@
1
- const exposes = require('../lib/exposes');
2
- const fz = {...require('../converters/fromZigbee'), legacy: require('../lib/legacy').fromZigbee};
3
- const tz = require('../converters/toZigbee');
4
- const ota = require('../lib/ota');
5
- const constants = require('../lib/constants');
6
- const reporting = require('../lib/reporting');
7
- const e = exposes.presets;
8
- const ea = exposes.access;
1
+ const {extendDevice} = require('../lib/utils');
9
2
 
10
3
  module.exports = [
11
- {
12
- // eT093WRO is the same as Hive TRV001 and Danfoss Ally (eTRV0100). If implementing anything, please consider
13
- // changing those two too.
4
+ extendDevice(require('./danfoss'), '014G2461', {
14
5
  zigbeeModel: ['eT093WRO'],
15
6
  model: '701721',
16
7
  vendor: 'Popp',
17
- description: 'Smart thermostat',
18
- fromZigbee: [fz.battery, fz.thermostat, fz.thermostat_weekly_schedule, fz.hvac_user_interface, fz.danfoss_thermostat],
19
- toZigbee: [tz.danfoss_thermostat_occupied_heating_setpoint, tz.thermostat_local_temperature, tz.danfoss_mounted_mode_active,
20
- tz.danfoss_mounted_mode_control, tz.danfoss_thermostat_vertical_orientation, tz.danfoss_algorithm_scale_factor,
21
- tz.danfoss_heat_available, tz.danfoss_heat_required, tz.danfoss_day_of_week, tz.danfoss_trigger_time,
22
- tz.danfoss_window_open_internal, tz.danfoss_window_open_external, tz.danfoss_load_estimate,
23
- tz.danfoss_viewing_direction, tz.danfoss_external_measured_room_sensor, tz.thermostat_keypad_lockout,
24
- tz.thermostat_system_mode, tz.danfoss_load_balancing_enable, tz.danfoss_load_room_mean,
25
- tz.thermostat_weekly_schedule, tz.thermostat_clear_weekly_schedule, tz.thermostat_programming_operation_mode],
26
- exposes: [e.battery(), e.keypad_lockout(), e.programming_operation_mode(),
27
- exposes.binary('mounted_mode_active', ea.STATE_GET, true, false)
28
- .withDescription('Is the unit in mounting mode. This is set to `false` for mounted (already on ' +
29
- 'the radiator) or `true` for not mounted (after factory reset)'),
30
- exposes.binary('mounted_mode_control', ea.ALL, true, false)
31
- .withDescription('Set the unit mounting mode. `false` Go to Mounted Mode or `true` Go to Mounting Mode'),
32
- exposes.binary('thermostat_vertical_orientation', ea.ALL, true, false)
33
- .withDescription('Thermostat Orientation. This is important for the PID in how it assesses temperature. ' +
34
- '`false` Horizontal or `true` Vertical'),
35
- exposes.binary('viewing_direction', ea.ALL, true, false)
36
- .withDescription('Viewing/Display Direction. `false` Horizontal or `true` Vertical'),
37
- exposes.binary('heat_available', ea.ALL, true, false)
38
- .withDescription('Not clear how this affects operation. `false` No Heat Available or `true` Heat Available'),
39
- exposes.binary('heat_required', ea.STATE_GET, true, false)
40
- .withDescription('Whether or not the unit needs warm water. `false` No Heat Request or `true` Heat Request'),
41
- exposes.enum('setpoint_change_source', ea.STATE, ['manual', 'schedule', 'externally'])
42
- .withDescription('Values observed are `0` (manual), `1` (schedule) or `2` (externally)'),
43
- exposes.climate().withSetpoint('occupied_heating_setpoint', 5, 32, 0.5).withLocalTemperature().withPiHeatingDemand()
44
- .withSystemMode(['heat']).withRunningState(['idle', 'heat'], ea.STATE),
45
- exposes.numeric('external_measured_room_sensor', ea.ALL)
46
- .withDescription('Set at maximum 3 hours interval but not more often than every 30 minutes and 0.1 ' +
47
- 'degrees difference. Resets every 3hours to standard. e.g. 21C = 2100 (-8000=undefined).')
48
- .withValueMin(-8000).withValueMax(3500),
49
- exposes.numeric('window_open_internal', ea.STATE_GET).withValueMin(0).withValueMax(4)
50
- .withDescription('0=Quarantine, 1=Windows are closed, 2=Hold - Windows are maybe about to open, ' +
51
- '3=Open window detected, 4=In window open state from external but detected closed locally'),
52
- exposes.binary('window_open_external', ea.ALL, true, false)
53
- .withDescription('Set if the window is open or close. This setting will trigger a change in the internal ' +
54
- 'window and heating demand. `false` (windows are closed) or `true` (windows are open)'),
55
- exposes.enum('day_of_week', ea.ALL,
56
- ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'away_or_vacation'])
57
- .withDescription('Exercise day of week: 0=Sun...6=Sat, 7=undefined'),
58
- exposes.numeric('trigger_time', ea.ALL).withValueMin(0).withValueMax(65535)
59
- .withDescription('Exercise trigger time. Minutes since midnight (65535=undefined). Range 0 to 1439'),
60
- exposes.numeric('algorithm_scale_factor', ea.ALL).withValueMin(1).withValueMax(10)
61
- .withDescription('Scale factor of setpoint filter timeconstant ("aggressiveness" of control algorithm) '+
62
- '1= Quick ... 5=Moderate ... 10=Slow'),
63
- exposes.binary('load_balancing_enable', ea.ALL, true, false)
64
- .withDescription('Whether or not the thermostat acts as standalone thermostat or shares load with other ' +
65
- 'thermostats in the room. The gateway must update load_room_mean if enabled.'),
66
- exposes.numeric('load_room_mean', ea.ALL)
67
- .withDescription('Mean radiator load for room calculated by gateway for load balancing purposes (-8000=undefined)')
68
- .withValueMin(-8000).withValueMax(2000),
69
- exposes.numeric('load_estimate', ea.STATE_GET)
70
- .withDescription('Load estimate on this radiator')],
71
- ota: ota.zigbeeOTA,
72
- configure: async (device, coordinatorEndpoint, logger) => {
73
- const endpoint = device.getEndpoint(1);
74
- const options = {manufacturerCode: 0x1246};
75
- await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'hvacThermostat']);
76
-
77
- // standard ZCL attributes
78
- await reporting.batteryPercentageRemaining(endpoint);
79
- await reporting.thermostatTemperature(endpoint);
80
- await reporting.thermostatPIHeatingDemand(endpoint);
81
- await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
82
-
83
- // danfoss attributes
84
- await endpoint.configureReporting('hvacThermostat', [{
85
- attribute: 'danfossMountedModeActive',
86
- minimumReportInterval: constants.repInterval.MINUTE,
87
- maximumReportInterval: constants.repInterval.MAX,
88
- reportableChange: 1,
89
- }], options);
90
- await endpoint.configureReporting('hvacThermostat', [{
91
- attribute: 'danfossWindowOpenInternal',
92
- minimumReportInterval: constants.repInterval.MINUTE,
93
- maximumReportInterval: constants.repInterval.HOUR,
94
- reportableChange: 1,
95
- }], options);
96
- await endpoint.configureReporting('hvacThermostat', [{
97
- attribute: 'danfossHeatRequired',
98
- minimumReportInterval: constants.repInterval.MINUTE,
99
- maximumReportInterval: constants.repInterval.HOUR,
100
- reportableChange: 1,
101
- }], options);
102
- await endpoint.configureReporting('hvacThermostat', [{
103
- attribute: 'danfossExternalMeasuredRoomSensor',
104
- minimumReportInterval: constants.repInterval.MINUTE,
105
- maximumReportInterval: constants.repInterval.MAX,
106
- reportableChange: 1,
107
- }], options);
108
-
109
- await endpoint.read('hvacThermostat', [
110
- 'danfossWindowOpenExternal',
111
- 'danfossDayOfWeek',
112
- 'danfossTriggerTime',
113
- 'danfossAlgorithmScaleFactor',
114
- 'danfossHeatAvailable',
115
- 'danfossMountedModeControl',
116
- 'danfossMountedModeActive',
117
- 'danfossExternalMeasuredRoomSensor',
118
- 'danfossLoadBalancingEnable',
119
- 'danfossLoadRoomMean',
120
- ], options);
121
-
122
- // read systemMode to have an initial value
123
- await endpoint.read('hvacThermostat', ['systemMode']);
124
-
125
- // read keypadLockout, we don't need reporting as it cannot be set physically on the device
126
- await endpoint.read('hvacUserInterfaceCfg', ['keypadLockout']);
127
-
128
- // Seems that it is bug in Danfoss, device does not asks for the time with binding
129
- // So, we need to write time during configure (same as for HEIMAN devices)
130
- const time = Math.round(((new Date()).getTime() - constants.OneJanuary2000) / 1000);
131
- // Time-master + synchronised
132
- const values = {timeStatus: 3, time: time, timeZone: ((new Date()).getTimezoneOffset() * -1) * 60};
133
- endpoint.write('genTime', values);
134
- },
135
- },
8
+ description: 'Smart thermostat based on Danfoss Ally (014G2461)',
9
+ }),
136
10
  ];