zigbee-herdsman-converters 14.0.335 → 14.0.339

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.
@@ -2318,20 +2318,20 @@ const converters = {
2318
2318
  exposes.options.precision('humidity'), exposes.options.calibration('humidity')],
2319
2319
  convert: (model, msg, publish, options, meta) => {
2320
2320
  const dp = msg.data.dp;
2321
- if (dp === 101) return {occupancy: msg.data.data[0] > 0};
2321
+ const value = tuya.getDataValue(msg.data.datatype, msg.data.data);
2322
+
2323
+ if (dp === 101) return {occupancy: value > 0 ? true : false};
2322
2324
  else if (dp === 102) {
2323
- const value = msg.data.data[0];
2324
2325
  return {
2325
2326
  power_type: {0: 'battery_full', 1: 'battery_high', 2: 'battery_medium', 3: 'battery_low', 4: 'usb'}[value],
2326
2327
  battery_low: value === 3,
2327
2328
  };
2328
2329
  } else if (dp === 103) {
2329
- return {tamper: msg.data.data[0] > 0 ? true : false};
2330
+ return {tamper: value > 0 ? true : false};
2330
2331
  } else if (dp === 104) {
2331
- const temperature = parseFloat(msg.data.data[3]) / 10.0;
2332
- return {temperature: calibrateAndPrecisionRoundOptions(temperature, options, 'temperature')};
2332
+ return {temperature: calibrateAndPrecisionRoundOptions(value / 10, options, 'temperature')};
2333
2333
  } else if (dp === 105) {
2334
- return {humidity: calibrateAndPrecisionRoundOptions(msg.data.data[3], options, 'humidity')};
2334
+ return {humidity: calibrateAndPrecisionRoundOptions(value, options, 'humidity')};
2335
2335
  } else {
2336
2336
  meta.logger.warn(`zigbee-herdsman-converters:NEO-PD07: NOT RECOGNIZED DP #${dp} with data ${JSON.stringify(msg.data)}`);
2337
2337
  }
@@ -2471,7 +2471,7 @@ const converters = {
2471
2471
  buttonMapping = {1: '1', 2: '2'};
2472
2472
  } else if (model.model === 'TS0043') {
2473
2473
  buttonMapping = {1: '1', 2: '2', 3: '3'};
2474
- } else if (['TS0044', 'YSR-MINI-Z'].includes(model.model)) {
2474
+ } else if (['TS0044', 'YSR-MINI-Z', 'TS004F'].includes(model.model)) {
2475
2475
  buttonMapping = {1: '1', 2: '2', 3: '3', 4: '4'};
2476
2476
  }
2477
2477
  const button = buttonMapping ? `${buttonMapping[msg.endpoint.ID]}_` : '';
@@ -7510,6 +7510,44 @@ const converters = {
7510
7510
  }
7511
7511
  },
7512
7512
  },
7513
+ sunricher_switch2801K2: {
7514
+ cluster: 'greenPower',
7515
+ type: ['commandNotification', 'commandCommisioningNotification'],
7516
+ convert: (model, msg, publish, options, meta) => {
7517
+ const commandID = msg.data.commandID;
7518
+ if (hasAlreadyProcessedMessage(msg, msg.data.frameCounter, `${msg.device.ieeeAddr}_${commandID}`)) return;
7519
+ if (commandID === 224) return;
7520
+ const lookup = {0x21: 'press_on', 0x20: 'press_off', 0x34: 'release', 0x35: 'hold_on', 0x36: 'hold_off'};
7521
+ if (!lookup.hasOwnProperty(commandID)) {
7522
+ meta.logger.error(`Sunricher: missing command '${commandID}'`);
7523
+ } else {
7524
+ return {action: lookup[commandID]};
7525
+ }
7526
+ },
7527
+ },
7528
+ sunricher_switch2801K4: {
7529
+ cluster: 'greenPower',
7530
+ type: ['commandNotification', 'commandCommisioningNotification'],
7531
+ convert: (model, msg, publish, options, meta) => {
7532
+ const commandID = msg.data.commandID;
7533
+ if (hasAlreadyProcessedMessage(msg, msg.data.frameCounter, `${msg.device.ieeeAddr}_${commandID}`)) return;
7534
+ if (commandID === 224) return;
7535
+ const lookup = {
7536
+ 0x21: 'press_on',
7537
+ 0x20: 'press_off',
7538
+ 0x37: 'press_high',
7539
+ 0x38: 'press_low',
7540
+ 0x35: 'hold_high',
7541
+ 0x36: 'hold_low',
7542
+ 0x34: 'release',
7543
+ };
7544
+ if (!lookup.hasOwnProperty(commandID)) {
7545
+ meta.logger.error(`Sunricher: missing command '${commandID}'`);
7546
+ } else {
7547
+ return {action: lookup[commandID]};
7548
+ }
7549
+ },
7550
+ },
7513
7551
  // #endregion
7514
7552
 
7515
7553
  // #region Ignore converters (these message dont need parsing).
@@ -0,0 +1,34 @@
1
+ const exposes = require('../lib/exposes');
2
+ const fz = require('../converters/fromZigbee');
3
+ const tz = require('../converters/toZigbee');
4
+ const reporting = require('../lib/reporting');
5
+
6
+ module.exports = [{
7
+ zigbeeModel: ['PERCALE2 D1.00P1.01Z1.00'],
8
+ model: 'PERCALE2',
9
+ vendor: 'Acova',
10
+ description: 'Percale 2 heater',
11
+ fromZigbee: [fz.thermostat, fz.hvac_user_interface],
12
+ toZigbee: [
13
+ tz.thermostat_local_temperature,
14
+ tz.thermostat_system_mode,
15
+ tz.thermostat_occupied_heating_setpoint,
16
+ tz.thermostat_unoccupied_heating_setpoint,
17
+ tz.thermostat_occupied_cooling_setpoint,
18
+ tz.thermostat_running_state,
19
+ ],
20
+ exposes: [
21
+ exposes.climate()
22
+ .withSetpoint('occupied_heating_setpoint', 7, 28, 0.5)
23
+ .withLocalTemperature()
24
+ .withSystemMode(['off', 'heat', 'auto'])
25
+ .withRunningState(['idle', 'heat']),
26
+ ],
27
+ configure: async (device, coordinatorEndpoint, logger) => {
28
+ const endpoint = device.getEndpoint(1);
29
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'hvacThermostat']);
30
+ await reporting.thermostatTemperature(endpoint);
31
+ await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
32
+ await reporting.thermostatUnoccupiedHeatingSetpoint(endpoint);
33
+ },
34
+ }];
@@ -233,4 +233,40 @@ module.exports = [
233
233
  },
234
234
  exposes: [e.soil_moisture(), e.battery(), e.temperature()],
235
235
  },
236
+ {
237
+ zigbeeModel: ['EFEKTA_eON213z'],
238
+ model: 'EFEKTA_eON213z',
239
+ vendor: 'Custom devices (DiY)',
240
+ description: '[Temperature and humidity sensor with e-ink2.13](http://efektalab.com/eON213z)',
241
+ fromZigbee: [fz.temperature, fz.humidity, fz.battery],
242
+ toZigbee: [tz.factory_reset],
243
+ configure: async (device, coordinatorEndpoint, logger) => {
244
+ const endpoint = device.getEndpoint(1);
245
+ await reporting.bind(endpoint, coordinatorEndpoint, [
246
+ 'genPowerCfg', 'msTemperatureMeasurement', 'msRelativeHumidity']);
247
+ const overides = {min: 0, max: 21600, change: 0};
248
+ await reporting.batteryVoltage(endpoint, overides);
249
+ await reporting.batteryPercentageRemaining(endpoint, overides);
250
+ await reporting.temperature(endpoint, overides);
251
+ await reporting.humidity(endpoint, overides);
252
+ },
253
+ exposes: [e.battery(), e.temperature(), e.humidity()],
254
+ },
255
+ {
256
+ zigbeeModel: ['EFEKTA_miniPWS'],
257
+ model: 'EFEKTA_miniPWS',
258
+ vendor: 'Custom devices (DiY)',
259
+ description: '[Mini plant wattering sensor](http://efektalab.com/miniPWS)',
260
+ fromZigbee: [fz.soil_moisture, fz.battery],
261
+ toZigbee: [tz.factory_reset],
262
+ configure: async (device, coordinatorEndpoint, logger) => {
263
+ const firstEndpoint = device.getEndpoint(1);
264
+ await reporting.bind(firstEndpoint, coordinatorEndpoint, ['genPowerCfg', 'msSoilMoisture']);
265
+ const overides = {min: 0, max: 21600, change: 0};
266
+ await reporting.batteryVoltage(firstEndpoint, overides);
267
+ await reporting.batteryPercentageRemaining(firstEndpoint, overides);
268
+ await reporting.soil_moisture(firstEndpoint, overides);
269
+ },
270
+ exposes: [e.soil_moisture(), e.battery()],
271
+ },
236
272
  ];
@@ -34,7 +34,9 @@ module.exports = [
34
34
  exposes.binary('viewing_direction', ea.ALL, true, false)
35
35
  .withDescription('Viewing/Display Direction. `false` Horizontal or `true` Vertical'),
36
36
  exposes.binary('heat_available', ea.ALL, true, false)
37
- .withDescription('Not clear how this affects operation. `false` No Heat Available or `true` Heat Available'),
37
+ .withDescription('Not clear how this affects operation. However, it would appear that the device does not execute any ' +
38
+ 'motor functions if this is set to false. This may be a means to conserve battery during periods that the heating ' +
39
+ 'system is not energized (e.g. during summer). `false` No Heat Available or `true` Heat Available'),
38
40
  exposes.binary('heat_required', ea.STATE_GET, true, false)
39
41
  .withDescription('Whether or not the unit needs warm water. `false` No Heat Request or `true` Heat Request'),
40
42
  exposes.enum('setpoint_change_source', ea.STATE, ['manual', 'schedule', 'externally'])
@@ -42,8 +44,9 @@ module.exports = [
42
44
  exposes.climate().withSetpoint('occupied_heating_setpoint', 5, 32, 0.5).withLocalTemperature().withPiHeatingDemand()
43
45
  .withSystemMode(['heat']).withRunningState(['idle', 'heat'], ea.STATE),
44
46
  exposes.numeric('external_measured_room_sensor', ea.ALL)
45
- .withDescription('Set at maximum 3 hours interval but not more often than every 30 minutes at every 100 ' +
46
- 'value change. Resets every 3hours to standard. e.g. 21C = 2100 (-8000=undefined).'),
47
+ .withDescription('Set at maximum 3 hours interval but not more often than every 30 minutes and 0.1 ' +
48
+ 'degrees difference. Resets every 3hours to standard. e.g. 21C = 2100 (-8000=undefined).')
49
+ .withValueMin(-8000).withValueMax(3500),
47
50
  exposes.numeric('window_open_internal', ea.STATE_GET).withValueMin(0).withValueMax(4)
48
51
  .withDescription('0=Quarantine, 1=Windows are closed, 2=Hold - Windows are maybe about to open, ' +
49
52
  '3=Open window detected, 4=In window open state from external but detected closed locally'),
@@ -62,7 +65,8 @@ module.exports = [
62
65
  .withDescription('Whether or not the thermostat acts as standalone thermostat or shares load with other ' +
63
66
  'thermostats in the room. The gateway must update load_room_mean if enabled.'),
64
67
  exposes.numeric('load_room_mean', ea.ALL)
65
- .withDescription('Mean radiator load for room calculated by gateway for load balancing purposes'),
68
+ .withDescription('Mean radiator load for room calculated by gateway for load balancing purposes (-8000=undefined)')
69
+ .withValueMin(-8000).withValueMax(100),
66
70
  exposes.numeric('load_estimate', ea.STATE_GET)
67
71
  .withDescription('Load estimate on this radiator')],
68
72
  ota: ota.zigbeeOTA,
@@ -318,7 +318,7 @@ module.exports = [
318
318
  ['electricity', 'gas', 'water', 'kamstrup-kmp', 'linky', 'IEC62056-21', 'DSMR-2.3', 'DSMR-4.0'])
319
319
  .withDescription('Operating mode/probe'),
320
320
  exposes.numeric('current_summation', ea.SET)
321
- .withDescription('Current summation value sent to the display. e.g. 570 = 0,570 kWh'),
321
+ .withDescription('Current summation value sent to the display. e.g. 570 = 0,570 kWh').withValueMin(0).withValueMax(10000),
322
322
  exposes.binary('check_meter', ea.STATE, true, false)
323
323
  .withDescription('Is true if communication problem with meter is experienced'),
324
324
  ],
package/devices/diyruz.js CHANGED
@@ -150,11 +150,13 @@ module.exports = [
150
150
  exposes.numeric('radiation_dose_per_hour', ea.STATE).withUnit('μR/h').withDescription('Current radiation level'),
151
151
  exposes.binary('led_feedback', ea.ALL, 'ON', 'OFF').withDescription('Enable LED feedback'),
152
152
  exposes.binary('buzzer_feedback', ea.ALL, 'ON', 'OFF').withDescription('Enable buzzer feedback'),
153
- exposes.numeric('alert_threshold', ea.ALL).withUnit('μR/h').withDescription('Critical radiation level'),
153
+ exposes.numeric('alert_threshold', ea.ALL).withUnit('μR/h').withDescription('Critical radiation level')
154
+ .withValueMin(0).withValueMax(10000),
154
155
  exposes.enum('sensors_type', ea.ALL, ['СБМ-20/СТС-5/BOI-33', 'СБМ-19/СТС-6', 'Others'])
155
156
  .withDescription('Type of installed tubes'),
156
- exposes.numeric('sensors_count', ea.ALL).withDescription('Count of installed tubes'),
157
- exposes.numeric('sensitivity', ea.ALL).withDescription('This is applicable if tubes type is set to other')],
157
+ exposes.numeric('sensors_count', ea.ALL).withDescription('Count of installed tubes').withValueMin(0).withValueMax(50),
158
+ exposes.numeric('sensitivity', ea.ALL).withDescription('This is applicable if tubes type is set to other')
159
+ .withValueMin(0).withValueMax(100)],
158
160
  toZigbee: [tz.diyruz_geiger_config, tz.factory_reset],
159
161
  configure: async (device, coordinatorEndpoint, logger) => {
160
162
  const endpoint = device.getEndpoint(1);
@@ -250,11 +252,16 @@ module.exports = [
250
252
  exposes: [e.co2(), e.temperature(), e.humidity(), e.pressure(),
251
253
  exposes.binary('led_feedback', ea.ALL, 'ON', 'OFF').withDescription('Enable LEDs feedback'),
252
254
  exposes.binary('enable_abc', ea.ALL, 'ON', 'OFF').withDescription('Enable ABC (Automatic Baseline Correction)'),
253
- exposes.numeric('threshold1', ea.ALL).withUnit('ppm').withDescription('Warning (LED2) CO2 level'),
254
- exposes.numeric('threshold2', ea.ALL).withUnit('ppm').withDescription('Critical (LED3) CO2 level'),
255
- exposes.numeric('temperature_offset', ea.ALL).withUnit('°C').withDescription('Adjust temperature'),
256
- exposes.numeric('humidity_offset', ea.ALL).withUnit('%').withDescription('Adjust humidity'),
257
- exposes.numeric('pressure_offset', ea.ALL).withUnit('hPa').withDescription('Adjust pressure')],
255
+ exposes.numeric('threshold1', ea.ALL).withUnit('ppm').withDescription('Warning (LED2) CO2 level')
256
+ .withValueMin(0).withValueMax(50000),
257
+ exposes.numeric('threshold2', ea.ALL).withUnit('ppm').withDescription('Critical (LED3) CO2 level')
258
+ .withValueMin(0).withValueMax(50000),
259
+ exposes.numeric('temperature_offset', ea.ALL).withUnit('°C').withDescription('Adjust temperature')
260
+ .withValueMin(-20).withValueMax(20),
261
+ exposes.numeric('humidity_offset', ea.ALL).withUnit('%').withDescription('Adjust humidity')
262
+ .withValueMin(-50).withValueMax(50),
263
+ exposes.numeric('pressure_offset', ea.ALL).withUnit('hPa').withDescription('Adjust pressure')
264
+ .withValueMin(-1000).withValueMax(1000)],
258
265
  },
259
266
  {
260
267
  zigbeeModel: ['DIY_Zintercom'],
@@ -282,15 +289,15 @@ module.exports = [
282
289
  exposes.binary('sound', ea.ALL, 'ON', 'OFF').withProperty('sound')
283
290
  .withDescription('Enable or disable sound'),
284
291
  exposes.numeric('time_ring', ea.ALL).withUnit('sec')
285
- .withDescription('Time to ring before answer'),
292
+ .withDescription('Time to ring before answer').withValueMin(0).withValueMax(600),
286
293
  exposes.numeric('time_talk', ea.ALL).withUnit('sec')
287
- .withDescription('Time to hold before open'),
294
+ .withDescription('Time to hold before open').withValueMin(0).withValueMax(600),
288
295
  exposes.numeric('time_open', ea.ALL).withUnit('sec')
289
- .withDescription('Time to open before end'),
296
+ .withDescription('Time to open before end').withValueMin(0).withValueMax(600),
290
297
  exposes.numeric('time_bell', ea.ALL).withUnit('sec')
291
- .withDescription('Time after last bell to finish ring'),
298
+ .withDescription('Time after last bell to finish ring').withValueMin(0).withValueMax(600),
292
299
  exposes.numeric('time_report', ea.ALL).withUnit('min')
293
- .withDescription('Reporting interval'),
300
+ .withDescription('Reporting interval').withValueMin(0).withValueMax(1440),
294
301
  e.battery(),
295
302
  ],
296
303
  },
package/devices/fantem.js CHANGED
@@ -29,10 +29,14 @@ module.exports = [
29
29
  fromZigbee: [fz.battery, fz.ignore_basic_report, fz.illuminance, fz.ZB003X, fz.ZB003X_attr, fz.ZB003X_occupancy],
30
30
  toZigbee: [tz.ZB003X],
31
31
  exposes: [e.occupancy(), e.tamper(), e.battery(), e.illuminance(), e.illuminance_lux().withUnit('lx'), e.temperature(),
32
- e.humidity(), exposes.numeric('reporting_time', ea.STATE_SET).withDescription('Reporting interval in minutes'),
33
- exposes.numeric('temperature_calibration', ea.STATE_SET).withDescription('Temperature calibration'),
34
- exposes.numeric('humidity_calibration', ea.STATE_SET).withDescription('Humidity calibration'),
35
- exposes.numeric('illuminance_calibration', ea.STATE_SET).withDescription('Illuminance calibration'),
32
+ e.humidity(), exposes.numeric('reporting_time', ea.STATE_SET).withDescription('Reporting interval in minutes')
33
+ .withValueMin(0).withValueMax(1440),
34
+ exposes.numeric('temperature_calibration', ea.STATE_SET).withDescription('Temperature calibration')
35
+ .withValueMin(-20).withValueMax(20),
36
+ exposes.numeric('humidity_calibration', ea.STATE_SET).withDescription('Humidity calibration')
37
+ .withValueMin(-50).withValueMax(50),
38
+ exposes.numeric('illuminance_calibration', ea.STATE_SET).withDescription('Illuminance calibration')
39
+ .withValueMin(-10000).withValueMax(10000),
36
40
  exposes.binary('pir_enable', ea.STATE_SET, true, false).withDescription('Enable PIR sensor'),
37
41
  exposes.binary('led_enable', ea.STATE_SET, true, false).withDescription('Enabled LED'),
38
42
  exposes.binary('reporting_enable', ea.STATE_SET, true, false).withDescription('Enabled reporting'),
@@ -39,6 +39,27 @@ const gledoptoExtend = {
39
39
  [tz.gledopto_light_onoff_brightness, tz.gledopto_light_color_colortemp],
40
40
  ),
41
41
  }),
42
+ switch: (options={}) => ({
43
+ ...extend.switch(options),
44
+ onEvent: async (type, data, device) => {
45
+ // This device doesn't support reporting.
46
+ // Therefore we read the on/off state every 5 seconds.
47
+ // This is the same way as the Hue bridge does it.
48
+ if (type === 'stop') {
49
+ clearInterval(globalStore.getValue(device, 'interval'));
50
+ globalStore.clearValue(device, 'interval');
51
+ } else if (!globalStore.hasValue(device, 'interval')) {
52
+ const interval = setInterval(async () => {
53
+ try {
54
+ await device.endpoints[0].read('genOnOff', ['onOff']);
55
+ } catch (error) {
56
+ // Do nothing
57
+ }
58
+ }, 5000);
59
+ globalStore.putValue(device, 'interval', interval);
60
+ }
61
+ },
62
+ }),
42
63
  };
43
64
 
44
65
  module.exports = [
@@ -580,32 +601,21 @@ module.exports = [
580
601
  zigbeeModel: ['GL-G-007Z'],
581
602
  model: 'GL-G-007Z',
582
603
  vendor: 'Gledopto',
583
- description: 'Zigbee 9W Garden Lamp RGB+CCT',
604
+ description: 'Zigbee 9W garden lamp RGB+CCT',
584
605
  extend: gledoptoExtend.light_onoff_brightness_colortemp_color(),
585
606
  },
586
607
  {
587
608
  zigbeeModel: ['GL-W-001Z'],
588
609
  model: 'GL-W-001Z',
589
610
  vendor: 'Gledopto',
590
- description: 'Zigbee On/Off Wall Switch',
591
- extend: extend.switch(),
592
- onEvent: async (type, data, device) => {
593
- // This device doesn't support reporting.
594
- // Therefore we read the on/off state every 5 seconds.
595
- // This is the same way as the Hue bridge does it.
596
- if (type === 'stop') {
597
- clearInterval(globalStore.getValue(device, 'interval'));
598
- globalStore.clearValue(device, 'interval');
599
- } else if (!globalStore.hasValue(device, 'interval')) {
600
- const interval = setInterval(async () => {
601
- try {
602
- await device.endpoints[0].read('genOnOff', ['onOff']);
603
- } catch (error) {
604
- // Do nothing
605
- }
606
- }, 5000);
607
- globalStore.putValue(device, 'interval', interval);
608
- }
609
- },
611
+ description: 'Zigbee on/off wall switch',
612
+ extend: gledoptoExtend.switch(),
613
+ },
614
+ {
615
+ zigbeeModel: ['GL-SD-002'],
616
+ model: 'GL-SD-002',
617
+ vendor: 'Gledopto',
618
+ description: 'Zigbee 3.0 smart home switch',
619
+ extend: gledoptoExtend.switch(),
610
620
  },
611
621
  ];
package/devices/hive.js CHANGED
@@ -183,8 +183,9 @@ module.exports = [
183
183
  exposes.climate().withSetpoint('occupied_heating_setpoint', 5, 32, 0.5).withLocalTemperature().withPiHeatingDemand()
184
184
  .withSystemMode(['heat']).withRunningState(['idle', 'heat'], ea.STATE),
185
185
  exposes.numeric('external_measured_room_sensor', ea.ALL)
186
- .withDescription('Set at maximum 3 hours interval but not more often than every 30 minutes at every 100 ' +
187
- 'value change. Resets every 3hours to standard. e.g. 21C = 2100 (-8000=undefined).'),
186
+ .withDescription('Set at maximum 3 hours interval but not more often than every 30 minutes and 0.1 ' +
187
+ 'degrees difference. Resets every 3hours to standard. e.g. 21C = 2100 (-8000=undefined).')
188
+ .withValueMin(-8000).withValueMax(3500),
188
189
  exposes.numeric('window_open_internal', ea.STATE_GET).withValueMin(0).withValueMax(4)
189
190
  .withDescription('0=Quarantine, 1=Windows are closed, 2=Hold - Windows are maybe about to open, ' +
190
191
  '3=Open window detected, 4=In window open state from external but detected closed locally'),
@@ -203,7 +204,8 @@ module.exports = [
203
204
  .withDescription('Whether or not the thermostat acts as standalone thermostat or shares load with other ' +
204
205
  'thermostats in the room. The gateway must update load_room_mean if enabled.'),
205
206
  exposes.numeric('load_room_mean', ea.ALL)
206
- .withDescription('Mean radiator load for room calculated by gateway for load balancing purposes'),
207
+ .withDescription('Mean radiator load for room calculated by gateway for load balancing purposes (-8000=undefined)')
208
+ .withValueMin(-8000).withValueMax(100),
207
209
  exposes.numeric('load_estimate', ea.STATE_GET)
208
210
  .withDescription('Load estimate on this radiator')],
209
211
  configure: async (device, coordinatorEndpoint, logger) => {
package/devices/immax.js CHANGED
@@ -148,10 +148,14 @@ module.exports = [
148
148
  fromZigbee: [fz.battery, fz.ignore_basic_report, fz.illuminance, fz.ZB003X, fz.ZB003X_attr, fz.ZB003X_occupancy],
149
149
  toZigbee: [tz.ZB003X],
150
150
  exposes: [e.occupancy(), e.tamper(), e.battery(), e.illuminance(), e.illuminance_lux().withUnit('lx'), e.temperature(),
151
- e.humidity(), exposes.numeric('reporting_time', ea.STATE_SET).withDescription('Reporting interval in minutes'),
152
- exposes.numeric('temperature_calibration', ea.STATE_SET).withDescription('Temperature calibration'),
153
- exposes.numeric('humidity_calibration', ea.STATE_SET).withDescription('Humidity calibration'),
154
- exposes.numeric('illuminance_calibration', ea.STATE_SET).withDescription('Illuminance calibration'),
151
+ e.humidity(), exposes.numeric('reporting_time', ea.STATE_SET).withDescription('Reporting interval in minutes')
152
+ .withValueMin(0).withValueMax(1440),
153
+ exposes.numeric('temperature_calibration', ea.STATE_SET).withDescription('Temperature calibration')
154
+ .withValueMin(-20).withValueMax(20),
155
+ exposes.numeric('humidity_calibration', ea.STATE_SET).withDescription('Humidity calibration')
156
+ .withValueMin(-50).withValueMax(50),
157
+ exposes.numeric('illuminance_calibration', ea.STATE_SET).withDescription('Illuminance calibration')
158
+ .withValueMin(-10000).withValueMax(10000),
155
159
  exposes.binary('pir_enable', ea.STATE_SET, true, false).withDescription('Enable PIR sensor'),
156
160
  exposes.binary('led_enable', ea.STATE_SET, true, false).withDescription('Enabled LED'),
157
161
  exposes.binary('reporting_enable', ea.STATE_SET, true, false).withDescription('Enabled reporting'),
package/devices/javis.js CHANGED
@@ -31,6 +31,7 @@ module.exports = [
31
31
  exposes.enum('keep_time', ea.STATE_SET, ['0', '1', '2', '3', '4', '5', '6', '7'])
32
32
  .withDescription('PIR keep time 0:5s|1:30s|2:60s|3:180s|4:300s|5:600s|6:1200s|7:1800s'),
33
33
  exposes.enum('sensitivity', ea.STATE_SET, ['25', '50', '75', '100']),
34
- exposes.numeric('illuminance_calibration', ea.STATE_SET).withDescription('Illuminance calibration')],
34
+ exposes.numeric('illuminance_calibration', ea.STATE_SET).withDescription('Illuminance calibration')
35
+ .withValueMin(-10000).withValueMax(10000)],
35
36
  },
36
37
  ];
package/devices/lidl.js CHANGED
@@ -417,6 +417,7 @@ module.exports = [
417
417
  configure: async (device, coordinatorEndpoint, logger) => {
418
418
  const endpoint = device.getEndpoint(1);
419
419
  await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
420
+ await reporting.batteryPercentageRemaining(endpoint);
420
421
  },
421
422
  },
422
423
  {
@@ -609,7 +610,7 @@ module.exports = [
609
610
  toZigbee: [tz.on_off, tz.lidl_watering_timer],
610
611
  onEvent: tuya.onEventSetTime,
611
612
  configure: async (device, coordinatorEndpoint, logger) => {},
612
- exposes: [e.switch(), exposes.numeric('timer', ea.SET).withValueMin(1)
613
+ exposes: [e.switch(), exposes.numeric('timer', ea.SET).withValueMin(1).withValueMax(10000)
613
614
  .withUnit('min').withDescription('Auto off after specific time.')],
614
615
  },
615
616
  {
@@ -655,8 +656,8 @@ module.exports = [
655
656
  fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_chyvmhay'}],
656
657
  model: '368308_2010',
657
658
  vendor: 'Lidl',
658
- description: 'Silvercrest rdiator valve with thermostat',
659
- fromZigbee: [fz.ignore_tuya_set_time, fzLocal.zs_thermostat, fz.tuya_data_point_dump],
659
+ description: 'Silvercrest radiator valve with thermostat',
660
+ fromZigbee: [fz.ignore_tuya_set_time, fzLocal.zs_thermostat],
660
661
  toZigbee: [tzLocal.zs_thermostat_current_heating_setpoint, tzLocal.zs_thermostat_child_lock,
661
662
  tzLocal.zs_thermostat_comfort_temp, tzLocal.zs_thermostat_eco_temp, tzLocal.zs_thermostat_preset_mode,
662
663
  tzLocal.zs_thermostat_system_mode, tzLocal.zs_thermostat_local_temperature_calibration,
@@ -676,8 +677,10 @@ module.exports = [
676
677
  .withLocalTemperature(ea.STATE).withLocalTemperatureCalibration(-20, 20, 1, ea.STATE_SET)
677
678
  .withSystemMode(['off', 'heat', 'auto'], ea.STATE_SET)
678
679
  .withPreset(['schedule', 'manual', 'holiday', 'boost']),
679
- exposes.numeric('detectwindow_temperature', ea.STATE_SET).withUnit('°C').withDescription('Open window detection temperature'),
680
- exposes.numeric('detectwindow_timeminute', ea.STATE_SET).withUnit('min').withDescription('Open window time in minute'),
680
+ exposes.numeric('detectwindow_temperature', ea.STATE_SET).withUnit('°C').withDescription('Open window detection temperature')
681
+ .withValueMin(-10).withValueMax(35),
682
+ exposes.numeric('detectwindow_timeminute', ea.STATE_SET).withUnit('min').withDescription('Open window time in minute')
683
+ .withValueMin(0).withValueMax(1000),
681
684
  exposes.binary('binary_one', ea.STATE_SET, 'ON', 'OFF').withDescription('Unknown binary one'),
682
685
  exposes.binary('binary_two', ea.STATE_SET, 'ON', 'OFF').withDescription('Unknown binary two'),
683
686
  exposes.binary('away_mode', ea.STATE, 'ON', 'OFF').withDescription('Away mode'),
package/devices/moes.js CHANGED
@@ -225,9 +225,10 @@ module.exports = [
225
225
  'You can set up to 4 stages of temperature every for WEEKDAY ➀➁➂➃➄, SATURDAY ➅ and SUNDAY ➆.'),
226
226
  exposes.binary('boost_heating', ea.STATE_SET, 'ON', 'OFF').withDescription('Boost Heating: press and hold "+" for 3 seconds, ' +
227
227
  'the device will enter the boost heating mode, and the ▷╵◁ will flash. The countdown will be displayed in the APP'),
228
- exposes.numeric('boost_heating_countdown', ea.STATE_SET).withUnit('min').withDescription('Countdown in minutes'),
228
+ exposes.numeric('boost_heating_countdown', ea.STATE_SET).withUnit('min').withDescription('Countdown in minutes')
229
+ .withValueMin(0).withValueMax(15),
229
230
  exposes.numeric('boost_heating_countdown_time_set', ea.STATE_SET).withUnit('second')
230
- .withDescription('Boost Time Setting 100 sec - 900 sec, (default = 300 sec)')],
231
+ .withDescription('Boost Time Setting 100 sec - 900 sec, (default = 300 sec)').withValueMin(100).withValueMax(900)],
231
232
  },
232
233
  {
233
234
  fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_la2c2uo9'}],
@@ -285,34 +286,7 @@ module.exports = [
285
286
  supports: 'open, close, stop, position',
286
287
  fromZigbee: [fz.tuya_cover_options, fz.cover_position_tilt],
287
288
  toZigbee: [tz.cover_state, tz.moes_cover_calibration, tz.cover_position_tilt, tz.tuya_cover_reversal],
288
- exposes: [e.cover_position(), exposes.numeric('calibration_time', ea.ALL), exposes.enum('moving', ea.STATE, ['UP', 'STOP', 'DOWN']),
289
- exposes.binary('motor_reversal', ea.ALL, 'ON', 'OFF')],
290
- },
291
- {
292
- fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_e9ba97vf'},
293
- {modelID: 'TS0601', manufacturerName: '_TZE200_husqqvux'}],
294
- model: 'TV01-ZB',
295
- vendor: 'Moes',
296
- description: 'Thermostat radiator valve',
297
- fromZigbee: [fz.moes_thermostat_tv, fz.ignore_tuya_set_time],
298
- whiteLabel: [{vendor: 'Tesla Smart', model: 'TSL-TRV-TV01ZG'}],
299
- toZigbee: [tz.moes_thermostat_tv],
300
- exposes: [
301
- e.battery(), e.child_lock(), e.window_detection(),
302
- exposes.binary('frost_detection', ea.STATE_SET, true, false).withDescription('Enables/disables frost detection on the device'),
303
- exposes.binary('heating_stop', ea.STATE_SET, true, false).withDescription('Stop heating'),
304
- exposes.numeric('holiday_temperature', ea.STATE_SET).withDescription('Holiday mode temperature'),
305
- exposes.numeric('comfort_temperature', ea.STATE_SET).withDescription('Comfort mode temperature'),
306
- exposes.numeric('eco_temperature', ea.STATE_SET).withDescription('Eco mode temperature'),
307
- exposes.numeric('open_window_temperature', ea.STATE_SET).withDescription('Open window mode temperature'),
308
- exposes.numeric('boost_heating_countdown', ea.STATE).withDescription('Boost heating countdown'),
309
- exposes.numeric('error_status', ea.STATE).withDescription('Error status'),
310
- // exposes.binary('boost_mode', ea.STATE_SET).withDescription('Enables/disables boost mode'),
311
- exposes.climate().withSetpoint('current_heating_setpoint', 5, 29.5, 1, ea.STATE_SET)
312
- .withLocalTemperature(ea.STATE).withLocalTemperatureCalibration(-20, 20, 1, ea.STATE_SET)
313
- .withSystemMode(Object.values(tuya.tvThermostatMode), ea.STATE_SET)
314
- .withPreset(Object.values(tuya.tvThermostatPreset)),
315
- ],
316
- onEvent: tuya.onEventSetLocalTime,
289
+ exposes: [e.cover_position(), exposes.numeric('calibration_time', ea.ALL).withValueMin(0).withValueMax(100),
290
+ exposes.enum('moving', ea.STATE, ['UP', 'STOP', 'DOWN']), exposes.binary('motor_reversal', ea.ALL, 'ON', 'OFF')],
317
291
  },
318
292
  ];
package/devices/neo.js CHANGED
@@ -19,11 +19,11 @@ module.exports = [
19
19
  exposes.binary('temperature_alarm', ea.STATE_SET, true, false),
20
20
  exposes.binary('alarm', ea.STATE_SET, true, false),
21
21
  exposes.enum('melody', ea.STATE_SET, Array.from(Array(18).keys()).map((x)=>(x+1).toString())),
22
- exposes.numeric('duration', ea.STATE_SET).withUnit('second'),
23
- exposes.numeric('temperature_min', ea.STATE_SET).withUnit('°C'),
24
- exposes.numeric('temperature_max', ea.STATE_SET).withUnit('°C'),
25
- exposes.numeric('humidity_min', ea.STATE_SET).withUnit('%'),
26
- exposes.numeric('humidity_max', ea.STATE_SET).withUnit('%'),
22
+ exposes.numeric('duration', ea.STATE_SET).withUnit('second').withValueMin(0).withValueMax(1000),
23
+ exposes.numeric('temperature_min', ea.STATE_SET).withUnit('°C').withValueMin(-10).withValueMax(35),
24
+ exposes.numeric('temperature_max', ea.STATE_SET).withUnit('°C').withValueMin(-10).withValueMax(35),
25
+ exposes.numeric('humidity_min', ea.STATE_SET).withUnit('%').withValueMin(0).withValueMax(100),
26
+ exposes.numeric('humidity_max', ea.STATE_SET).withUnit('%').withValueMin(0).withValueMax(100),
27
27
  exposes.enum('volume', ea.STATE_SET, ['low', 'medium', 'high']),
28
28
  exposes.enum('power_type', ea.STATE, ['battery_full', 'battery_high', 'battery_medium', 'battery_low', 'usb']),
29
29
  ],
@@ -243,12 +243,12 @@ module.exports = [
243
243
  ota: ota.zigbeeOTA,
244
244
  },
245
245
  {
246
- zigbeeModel: ['LCP001', 'LCP002', '4090331P9_01', '4090331P9_02'],
246
+ zigbeeModel: ['LCP001', 'LCP002', '4090331P9_01', '4090331P9_02', '929003053301_01', '929003053301_02'],
247
247
  model: '4090331P9',
248
248
  vendor: 'Philips',
249
- description: 'Hue Ensis',
249
+ description: 'Hue Ensis (white)',
250
250
  meta: {turnsOffAtBrightness1: true},
251
- extend: hueExtend.light_onoff_brightness_colortemp_color(),
251
+ extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
252
252
  ota: ota.zigbeeOTA,
253
253
  },
254
254
  {
package/devices/popp.js CHANGED
@@ -42,8 +42,9 @@ module.exports = [
42
42
  exposes.climate().withSetpoint('occupied_heating_setpoint', 5, 32, 0.5).withLocalTemperature().withPiHeatingDemand()
43
43
  .withSystemMode(['heat']).withRunningState(['idle', 'heat'], ea.STATE),
44
44
  exposes.numeric('external_measured_room_sensor', ea.ALL)
45
- .withDescription('Set at maximum 3 hours interval but not more often than every 30 minutes at every 100 ' +
46
- 'value change. Resets every 3hours to standard. e.g. 21C = 2100 (-8000=undefined).'),
45
+ .withDescription('Set at maximum 3 hours interval but not more often than every 30 minutes and 0.1 ' +
46
+ 'degrees difference. Resets every 3hours to standard. e.g. 21C = 2100 (-8000=undefined).')
47
+ .withValueMin(-8000).withValueMax(3500),
47
48
  exposes.numeric('window_open_internal', ea.STATE_GET).withValueMin(0).withValueMax(4)
48
49
  .withDescription('0=Quarantine, 1=Windows are closed, 2=Hold - Windows are maybe about to open, ' +
49
50
  '3=Open window detected, 4=In window open state from external but detected closed locally'),
@@ -62,7 +63,8 @@ module.exports = [
62
63
  .withDescription('Whether or not the thermostat acts as standalone thermostat or shares load with other ' +
63
64
  'thermostats in the room. The gateway must update load_room_mean if enabled.'),
64
65
  exposes.numeric('load_room_mean', ea.ALL)
65
- .withDescription('Mean radiator load for room calculated by gateway for load balancing purposes'),
66
+ .withDescription('Mean radiator load for room calculated by gateway for load balancing purposes (-8000=undefined)')
67
+ .withValueMin(-8000).withValueMax(100),
66
68
  exposes.numeric('load_estimate', ea.STATE_GET)
67
69
  .withDescription('Load estimate on this radiator')],
68
70
  ota: ota.zigbeeOTA,
@@ -282,4 +282,21 @@ module.exports = [
282
282
  await reporting.batteryVoltage(endpoint, {min: 30, max: 21600, change: 1});
283
283
  },
284
284
  },
285
+ {
286
+ zigbeeModel: ['PMM-300Z1'],
287
+ model: 'PMM-300Z1',
288
+ vendor: 'ShinaSystem',
289
+ description: 'SiHAS energy monitor',
290
+ fromZigbee: [fz.electrical_measurement, fz.metering],
291
+ toZigbee: [tz.electrical_measurement_power],
292
+ exposes: [e.power().withAccess(ea.STATE_GET), e.energy()],
293
+ configure: async (device, coordinatorEndpoint, logger) => {
294
+ const endpoint = device.getEndpoint(1);
295
+ await reporting.bind(endpoint, coordinatorEndpoint, ['haElectricalMeasurement', 'seMetering']);
296
+ await reporting.activePower(endpoint, {min: 1, max: 600, change: 5});
297
+ await reporting.instantaneousDemand(endpoint, {min: 1, max: 600, change: 1});
298
+ endpoint.saveClusterAttributeKeyValue('seMetering', {multiplier: 1, divisor: 1000});
299
+ await reporting.currentSummDelivered(endpoint, {min: 1, max: 600, change: 5});
300
+ },
301
+ },
285
302
  ];
@@ -234,4 +234,22 @@ module.exports = [
234
234
  await reporting.currentPositionLiftPercentage(endpoint);
235
235
  },
236
236
  },
237
+ {
238
+ fingerprint: [{modelID: 'GreenPower_2', ieeeAddr: /^0x00000000010.....$/}],
239
+ model: 'SR-ZGP2801K2-DIM',
240
+ vendor: 'Sunricher',
241
+ description: 'Pushbutton transmitter module',
242
+ fromZigbee: [fz.sunricher_switch2801K2],
243
+ toZigbee: [],
244
+ exposes: [e.action(['press_on', 'press_off', 'hold_on', 'hold_off', 'release'])],
245
+ },
246
+ {
247
+ fingerprint: [{modelID: 'GreenPower_2', ieeeAddr: /^0x000000005d5.....$/}],
248
+ model: 'SR-ZGP2801K4-DIM',
249
+ vendor: 'Sunricher',
250
+ description: 'Pushbutton transmitter module',
251
+ fromZigbee: [fz.sunricher_switch2801K4],
252
+ toZigbee: [],
253
+ exposes: [e.action(['press_on', 'press_off', 'press_high', 'press_low', 'hold_high', 'hold_low', 'release'])],
254
+ },
237
255
  ];
@@ -189,4 +189,12 @@ module.exports = [
189
189
  extend: extend.ledvance.light_onoff_brightness(),
190
190
  ota: ota.ledvance,
191
191
  },
192
+ {
193
+ zigbeeModel: ['A19 G2 RGBW'],
194
+ model: '75564',
195
+ vendor: 'Sylvania',
196
+ description: 'Smart+ adjustable white and full color bulb A19',
197
+ extend: extend.ledvance.light_onoff_brightness_colortemp_color({colorTempRange: [142, 555]}),
198
+ ota: ota.ledvance,
199
+ },
192
200
  ];