zigbee-herdsman-converters 14.0.613 → 14.0.616
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/converters/fromZigbee.js +1 -1
- package/converters/toZigbee.js +39 -0
- package/devices/atlantic.js +110 -0
- package/devices/custom_devices_diy.js +31 -1
- package/devices/ecodim.js +5 -0
- package/devices/ikea.js +1 -1
- package/devices/kwikset.js +4 -3
- package/devices/ledvance.js +49 -0
- package/devices/legrand.js +17 -9
- package/devices/owon.js +48 -0
- package/devices/philips.js +7 -0
- package/devices/salus_controls.js +6 -1
- package/devices/smartwings.js +1 -1
- package/devices/tuya.js +11 -1
- package/lib/constants.js +1 -0
- package/lib/exposes.js +5 -1
- package/lib/tuya.js +2 -0
- package/package.json +1 -1
package/converters/fromZigbee.js
CHANGED
|
@@ -5119,7 +5119,7 @@ const converters = {
|
|
|
5119
5119
|
'105_14': 'press_2_and_3_and_4', '105_15': 'press_all', '105_16': 'press_energy_bar', '106_0': 'release',
|
|
5120
5120
|
};
|
|
5121
5121
|
|
|
5122
|
-
const ID = `${commandID}_${msg.data.commandFrame.raw.join('_')}`;
|
|
5122
|
+
const ID = `${commandID}_${msg.data.commandFrame.raw.slice(0, 1).join('_')}`;
|
|
5123
5123
|
if (!lookup.hasOwnProperty(ID)) {
|
|
5124
5124
|
meta.logger.error(`PTM 216Z: missing command '${ID}'`);
|
|
5125
5125
|
} else {
|
package/converters/toZigbee.js
CHANGED
|
@@ -1226,6 +1226,7 @@ const converters = {
|
|
|
1226
1226
|
Object.values(constants.thermostatProgrammingOperationModes).join(', '));
|
|
1227
1227
|
}
|
|
1228
1228
|
await entity.write('hvacThermostat', {programingOperMode: val});
|
|
1229
|
+
return {state: {programming_operation_mode: value}};
|
|
1229
1230
|
},
|
|
1230
1231
|
convertGet: async (entity, key, meta) => {
|
|
1231
1232
|
await entity.read('hvacThermostat', ['programingOperMode']);
|
|
@@ -1341,6 +1342,7 @@ const converters = {
|
|
|
1341
1342
|
}
|
|
1342
1343
|
const occupiedHeatingSetpoint = result;
|
|
1343
1344
|
await entity.write('hvacThermostat', {occupiedHeatingSetpoint});
|
|
1345
|
+
return {state: {occupied_heating_setpoint: value}};
|
|
1344
1346
|
},
|
|
1345
1347
|
convertGet: async (entity, key, meta) => {
|
|
1346
1348
|
await entity.read('hvacThermostat', ['occupiedHeatingSetpoint']);
|
|
@@ -1375,6 +1377,7 @@ const converters = {
|
|
|
1375
1377
|
}
|
|
1376
1378
|
const occupiedCoolingSetpoint = result;
|
|
1377
1379
|
await entity.write('hvacThermostat', {occupiedCoolingSetpoint});
|
|
1380
|
+
return {state: {occupied_cooling_setpoint: value}};
|
|
1378
1381
|
},
|
|
1379
1382
|
convertGet: async (entity, key, meta) => {
|
|
1380
1383
|
await entity.read('hvacThermostat', ['occupiedCoolingSetpoint']);
|
|
@@ -1427,6 +1430,7 @@ const converters = {
|
|
|
1427
1430
|
}
|
|
1428
1431
|
const minHeatSetpointLimit = result;
|
|
1429
1432
|
await entity.write('hvacThermostat', {minHeatSetpointLimit});
|
|
1433
|
+
return {state: {min_heat_setpoint_limit: value}};
|
|
1430
1434
|
},
|
|
1431
1435
|
convertGet: async (entity, key, meta) => {
|
|
1432
1436
|
await entity.read('hvacThermostat', ['minHeatSetpointLimit']);
|
|
@@ -1443,11 +1447,46 @@ const converters = {
|
|
|
1443
1447
|
}
|
|
1444
1448
|
const maxHeatSetpointLimit = result;
|
|
1445
1449
|
await entity.write('hvacThermostat', {maxHeatSetpointLimit});
|
|
1450
|
+
return {state: {max_heat_setpoint_limit: value}};
|
|
1446
1451
|
},
|
|
1447
1452
|
convertGet: async (entity, key, meta) => {
|
|
1448
1453
|
await entity.read('hvacThermostat', ['maxHeatSetpointLimit']);
|
|
1449
1454
|
},
|
|
1450
1455
|
},
|
|
1456
|
+
thermostat_min_cool_setpoint_limit: {
|
|
1457
|
+
key: ['min_cool_setpoint_limit'],
|
|
1458
|
+
convertSet: async (entity, key, value, meta) => {
|
|
1459
|
+
let result;
|
|
1460
|
+
if (meta.options.thermostat_unit === 'fahrenheit') {
|
|
1461
|
+
result = Math.round(utils.normalizeCelsiusVersionOfFahrenheit(value) * 100);
|
|
1462
|
+
} else {
|
|
1463
|
+
result = (Math.round((value * 2).toFixed(1)) / 2).toFixed(1) * 100;
|
|
1464
|
+
}
|
|
1465
|
+
const minCoolSetpointLimit = result;
|
|
1466
|
+
await entity.write('hvacThermostat', {minCoolSetpointLimit});
|
|
1467
|
+
return {state: {min_cool_setpoint_limit: value}};
|
|
1468
|
+
},
|
|
1469
|
+
convertGet: async (entity, key, meta) => {
|
|
1470
|
+
await entity.read('hvacThermostat', ['minCoolSetpointLimit']);
|
|
1471
|
+
},
|
|
1472
|
+
},
|
|
1473
|
+
thermostat_max_cool_setpoint_limit: {
|
|
1474
|
+
key: ['max_cool_setpoint_limit'],
|
|
1475
|
+
convertSet: async (entity, key, value, meta) => {
|
|
1476
|
+
let result;
|
|
1477
|
+
if (meta.options.thermostat_unit === 'fahrenheit') {
|
|
1478
|
+
result = Math.round(utils.normalizeCelsiusVersionOfFahrenheit(value) * 100);
|
|
1479
|
+
} else {
|
|
1480
|
+
result = (Math.round((value * 2).toFixed(1)) / 2).toFixed(1) * 100;
|
|
1481
|
+
}
|
|
1482
|
+
const maxCoolSetpointLimit = result;
|
|
1483
|
+
await entity.write('hvacThermostat', {maxCoolSetpointLimit});
|
|
1484
|
+
return {state: {max_cool_setpoint_limit: value}};
|
|
1485
|
+
},
|
|
1486
|
+
convertGet: async (entity, key, meta) => {
|
|
1487
|
+
await entity.read('hvacThermostat', ['maxCoolSetpointLimit']);
|
|
1488
|
+
},
|
|
1489
|
+
},
|
|
1451
1490
|
thermostat_ac_louver_position: {
|
|
1452
1491
|
key: ['ac_louver_position'],
|
|
1453
1492
|
convertSet: async (entity, key, value, meta) => {
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
const fz = require('../converters/fromZigbee');
|
|
2
|
+
const tz = require('../converters/toZigbee');
|
|
3
|
+
const exposes = require('../lib/exposes');
|
|
4
|
+
const reporting = require('../lib/reporting');
|
|
5
|
+
const utils = require('../lib/utils');
|
|
6
|
+
const assert = require('assert');
|
|
7
|
+
const e = exposes.presets;
|
|
8
|
+
const ea = exposes.access;
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
const thermostatPositions = {
|
|
12
|
+
'quarter_open': 1,
|
|
13
|
+
'half_open': 2,
|
|
14
|
+
'three_quarters_open': 3,
|
|
15
|
+
'fully_open': 4,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const tzLocal = {
|
|
19
|
+
quiet_fan: {
|
|
20
|
+
key: ['quiet_fan'],
|
|
21
|
+
convertSet: async (entity, key, value, meta) => {
|
|
22
|
+
assert(typeof value === 'boolean');
|
|
23
|
+
await entity.write('hvacFanCtrl', {0x1000: {value: value ? 1 : 0, type: 0x10}}, {manufacturerCode: 0x125b});
|
|
24
|
+
return {state: {quiet_fan: value}};
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
ac_louver_position: {
|
|
28
|
+
key: ['ac_louver_position'],
|
|
29
|
+
convertSet: async (entity, key, value, meta) => {
|
|
30
|
+
value = value.toLowerCase();
|
|
31
|
+
utils.validateValue(value, Object.keys(thermostatPositions));
|
|
32
|
+
const index = thermostatPositions[value];
|
|
33
|
+
await entity.write('hvacThermostat', {0x4273: {value: index, type: 0x30}}, {manufacturerCode: 0x125b});
|
|
34
|
+
return {state: {ac_louver_position: value}};
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
preset: {
|
|
38
|
+
key: ['preset'],
|
|
39
|
+
convertSet: async (entity, key, value, meta) => {
|
|
40
|
+
value = value.toLowerCase();
|
|
41
|
+
utils.validateValue(value, ['activity', 'boost', 'eco', 'none']);
|
|
42
|
+
const activity = value === 'activity' ? 1 : 0;
|
|
43
|
+
const boost = value === 'boost' ? 1 : 0;
|
|
44
|
+
const eco = value === 'eco' ? 4 : 0;
|
|
45
|
+
|
|
46
|
+
await entity.write('hvacThermostat', {0x4275: {value: activity, type: 0x30}}, {manufacturerCode: 0x125b});
|
|
47
|
+
await entity.write('hvacThermostat', {'programingOperMode': eco});
|
|
48
|
+
await entity.write('hvacThermostat', {0x4270: {value: boost, type: 0x10}}, {manufacturerCode: 0x125b});
|
|
49
|
+
|
|
50
|
+
return {state: {preset: value}};
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
swingMode: {
|
|
54
|
+
key: ['swing_mode'],
|
|
55
|
+
convertSet: async (entity, key, value, meta) => {
|
|
56
|
+
value = value.toLowerCase();
|
|
57
|
+
utils.validateValue(value, ['on', 'off']);
|
|
58
|
+
await entity.write('hvacThermostat', {0x4274: {value: value === 'on' ? 1 : 0, type: 0x10}}, {manufacturerCode: 0x125b});
|
|
59
|
+
return {state: {swing_mode: value}};
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
module.exports = [{
|
|
65
|
+
zigbeeModel: ['Adapter Zigbee FUJITSU'],
|
|
66
|
+
model: 'GW003-AS-IN-TE-FC',
|
|
67
|
+
vendor: 'Atlantic Group',
|
|
68
|
+
description: 'Interface Naviclim for Takao air conditioners',
|
|
69
|
+
fromZigbee: [
|
|
70
|
+
fz.thermostat,
|
|
71
|
+
fz.fan,
|
|
72
|
+
],
|
|
73
|
+
toZigbee: [
|
|
74
|
+
tzLocal.ac_louver_position,
|
|
75
|
+
tzLocal.preset,
|
|
76
|
+
tzLocal.quiet_fan,
|
|
77
|
+
tzLocal.swingMode,
|
|
78
|
+
tz.fan_mode,
|
|
79
|
+
tz.thermostat_local_temperature,
|
|
80
|
+
tz.thermostat_occupied_cooling_setpoint,
|
|
81
|
+
tz.thermostat_occupied_heating_setpoint,
|
|
82
|
+
tz.thermostat_programming_operation_mode,
|
|
83
|
+
tz.thermostat_system_mode,
|
|
84
|
+
],
|
|
85
|
+
exposes: [
|
|
86
|
+
e.programming_operation_mode(),
|
|
87
|
+
exposes.climate()
|
|
88
|
+
.withLocalTemperature()
|
|
89
|
+
.withSetpoint('occupied_cooling_setpoint', 18, 30, 0.5)
|
|
90
|
+
.withSetpoint('occupied_heating_setpoint', 16, 30, 0.5)
|
|
91
|
+
.withSystemMode(['off', 'heat', 'cool', 'auto', 'dry', 'fan_only'])
|
|
92
|
+
.withPreset(['activity', 'boost', 'eco'])
|
|
93
|
+
.withFanMode(['low', 'medium', 'high', 'auto'])
|
|
94
|
+
.withSwingMode(['on', 'off'], ea.STATE_SET),
|
|
95
|
+
exposes.binary('quiet_fan', ea.STATE_SET, true, false).withDescription('Fan quiet mode'),
|
|
96
|
+
exposes.enum('ac_louver_position', ea.STATE_SET, Object.keys(thermostatPositions))
|
|
97
|
+
.withDescription('Ac louver position of this device'),
|
|
98
|
+
],
|
|
99
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
100
|
+
const endpoint1 = device.getEndpoint(1);
|
|
101
|
+
const binds1 = ['hvacFanCtrl', 'genIdentify', 'hvacFanCtrl', 'hvacThermostat', 'manuSpecificPhilips2'];
|
|
102
|
+
await reporting.bind(endpoint1, coordinatorEndpoint, binds1);
|
|
103
|
+
await reporting.thermostatTemperature(endpoint1);
|
|
104
|
+
await reporting.thermostatOccupiedCoolingSetpoint(endpoint1);
|
|
105
|
+
await reporting.thermostatSystemMode(endpoint1);
|
|
106
|
+
|
|
107
|
+
const endpoint232 = device.getEndpoint(232);
|
|
108
|
+
await reporting.bind(endpoint232, coordinatorEndpoint, ['haDiagnostic']);
|
|
109
|
+
},
|
|
110
|
+
}];
|
|
@@ -772,9 +772,39 @@ module.exports = [
|
|
|
772
772
|
exposes.binary('factory_reset_co2', ea.STATE_SET, 'ON', 'OFF').withDescription('Factory Reset CO2 sensor'),
|
|
773
773
|
exposes.binary('enable_gas', ea.STATE_SET, 'ON', 'OFF').withDescription('Enable CO2 Gas Control'),
|
|
774
774
|
exposes.numeric('high_gas', ea.STATE_SET).withUnit('ppm').withDescription('Setting High CO2 Gas Border')
|
|
775
|
-
.withValueMin(
|
|
775
|
+
.withValueMin(400).withValueMax(2000),
|
|
776
776
|
exposes.numeric('low_gas', ea.STATE_SET).withUnit('ppm').withDescription('Setting Low CO2 Gas Border')
|
|
777
|
+
.withValueMin(400).withValueMax(2000),
|
|
778
|
+
exposes.binary('enable_temperature', ea.STATE_SET, 'ON', 'OFF').withDescription('Enable Temperature Control'),
|
|
779
|
+
exposes.numeric('high_temperature', ea.STATE_SET).withUnit('C').withDescription('Setting High Temperature Border')
|
|
780
|
+
.withValueMin(-5).withValueMax(50),
|
|
781
|
+
exposes.numeric('low_temperature', ea.STATE_SET).withUnit('C').withDescription('Setting Low Temperature Border')
|
|
782
|
+
.withValueMin(-5).withValueMax(50),
|
|
783
|
+
exposes.binary('enable_humidity', ea.STATE_SET, 'ON', 'OFF').withDescription('Enable Humidity Control'),
|
|
784
|
+
exposes.numeric('high_humidity', ea.STATE_SET).withUnit('C').withDescription('Setting High Humidity Border')
|
|
777
785
|
.withValueMin(0).withValueMax(99),
|
|
786
|
+
exposes.numeric('low_humidity', ea.STATE_SET).withUnit('C').withDescription('Setting Low Humidity Border')
|
|
787
|
+
.withValueMin(0).withValueMax(99)],
|
|
788
|
+
},
|
|
789
|
+
{
|
|
790
|
+
zigbeeModel: ['SNZB-02_EFEKTA'],
|
|
791
|
+
model: 'SNZB-02_EFEKTA',
|
|
792
|
+
vendor: 'Custom devices (DiY)',
|
|
793
|
+
description: 'Alternative firmware for the SONOFF SNZB-02 sensor from EfektaLab, DIY',
|
|
794
|
+
fromZigbee: [fz.temperature, fz.humidity, fz.battery, fzLocal.termostat_config, fzLocal.hydrostat_config, fzLocal.node_config],
|
|
795
|
+
toZigbee: [tz.factory_reset, tzLocal.termostat_config, tzLocal.hydrostat_config, tzLocal.node_config],
|
|
796
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
797
|
+
const endpoint = device.getEndpoint(1);
|
|
798
|
+
await reporting.bind(endpoint, coordinatorEndpoint, [
|
|
799
|
+
'genPowerCfg', 'msTemperatureMeasurement', 'msRelativeHumidity']);
|
|
800
|
+
const overides = {min: 0, max: 21600, change: 0};
|
|
801
|
+
await reporting.batteryVoltage(endpoint, overides);
|
|
802
|
+
await reporting.batteryPercentageRemaining(endpoint, overides);
|
|
803
|
+
},
|
|
804
|
+
exposes: [e.battery(), e.temperature(), e.humidity(),
|
|
805
|
+
exposes.numeric('report_delay', ea.STATE_SET).withUnit('Minutes')
|
|
806
|
+
.withDescription('Adjust Report Delay. Setting the time in minutes, by default 5 minutes')
|
|
807
|
+
.withValueMin(1).withValueMax(60),
|
|
778
808
|
exposes.binary('enable_temperature', ea.STATE_SET, 'ON', 'OFF').withDescription('Enable Temperature Control'),
|
|
779
809
|
exposes.numeric('high_temperature', ea.STATE_SET).withUnit('C').withDescription('Setting High Temperature Border')
|
|
780
810
|
.withValueMin(-5).withValueMax(50),
|
package/devices/ecodim.js
CHANGED
|
@@ -38,6 +38,11 @@ module.exports = [
|
|
|
38
38
|
{ID: 1, profileID: 260, deviceID: 257, inputClusters: [0, 3, 4, 5, 6, 8, 2821, 4096], outputClusters: [25]},
|
|
39
39
|
{ID: 242, profileID: 41440, deviceID: 97, inputClusters: [], outputClusters: [33]},
|
|
40
40
|
]},
|
|
41
|
+
{type: 'Router', manufacturerName: 'EcoDim BV', modelID: 'EcoDim-Zigbee 3.0', endpoints: [
|
|
42
|
+
{ID: 1, profileID: 260, deviceID: 257, inputClusters: [0, 3, 4, 5, 6, 8, 2821, 4096], outputClusters: [25]},
|
|
43
|
+
{ID: 67, inputClusters: [], outputClusters: []},
|
|
44
|
+
{ID: 242, profileID: 41440, deviceID: 97, inputClusters: [], outputClusters: [33]},
|
|
45
|
+
]},
|
|
41
46
|
],
|
|
42
47
|
zigbeeModel: ['Dimmer-Switch-ZB3.0'],
|
|
43
48
|
model: 'Eco-Dim.07/Eco-Dim.10',
|
package/devices/ikea.js
CHANGED
|
@@ -457,7 +457,7 @@ module.exports = [
|
|
|
457
457
|
meta: {supportsHueAndSaturation: false},
|
|
458
458
|
},
|
|
459
459
|
{
|
|
460
|
-
zigbeeModel: ['TRADFRI bulb E26 CWS 800lm', 'TRADFRI bulb E27 CWS 806lm'],
|
|
460
|
+
zigbeeModel: ['TRADFRI bulb E26 CWS 800lm', 'TRADFRI bulb E27 CWS 806lm', 'TRADFRI bulb E26 CWS 806lm'],
|
|
461
461
|
model: 'LED1924G9',
|
|
462
462
|
vendor: 'IKEA',
|
|
463
463
|
description: 'TRADFRI bulb E26/E27 CWS 800/806 lumen, dimmable, color, opal white',
|
package/devices/kwikset.js
CHANGED
|
@@ -55,15 +55,16 @@ module.exports = [
|
|
|
55
55
|
model: '99140-031',
|
|
56
56
|
vendor: 'Kwikset',
|
|
57
57
|
description: 'SmartCode traditional electronic deadbolt',
|
|
58
|
-
fromZigbee: [fz.lock, fz.lock_operation_event, fz.battery],
|
|
59
|
-
toZigbee: [tz.lock],
|
|
58
|
+
fromZigbee: [fz.lock, fz.lock_operation_event, fz.battery, fz.lock_programming_event, fz.lock_pin_code_response],
|
|
59
|
+
toZigbee: [tz.lock, tz.pincode_lock],
|
|
60
|
+
meta: {pinCodeCount: 30},
|
|
60
61
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
61
62
|
const endpoint = device.getEndpoint(2);
|
|
62
63
|
await reporting.bind(endpoint, coordinatorEndpoint, ['closuresDoorLock', 'genPowerCfg']);
|
|
63
64
|
await reporting.lockState(endpoint);
|
|
64
65
|
await reporting.batteryPercentageRemaining(endpoint);
|
|
65
66
|
},
|
|
66
|
-
exposes: [e.lock(), e.battery(), e.lock_action(), e.lock_action_source_name(), e.lock_action_user()],
|
|
67
|
+
exposes: [e.lock(), e.battery(), e.pincode(), e.lock_action(), e.lock_action_source_name(), e.lock_action_user()],
|
|
67
68
|
},
|
|
68
69
|
{
|
|
69
70
|
zigbeeModel: ['SMARTCODE_DEADBOLT_5'],
|
package/devices/ledvance.js
CHANGED
|
@@ -175,4 +175,53 @@ module.exports = [
|
|
|
175
175
|
extend: extend.ledvance.light_onoff_brightness(),
|
|
176
176
|
ota: ota.ledvance,
|
|
177
177
|
},
|
|
178
|
+
{
|
|
179
|
+
zigbeeModel: ['B40 DIM T'],
|
|
180
|
+
model: '4058075729063',
|
|
181
|
+
vendor: 'LEDVANCE',
|
|
182
|
+
description: 'SMART+ Classic B40 E14 dimmable white',
|
|
183
|
+
extend: extend.ledvance.light_onoff_brightness(),
|
|
184
|
+
ota: ota.ledvance,
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
zigbeeModel: ['PAR16 DIM T'],
|
|
188
|
+
model: '4058075729148',
|
|
189
|
+
vendor: 'LEDVANCE',
|
|
190
|
+
description: 'SMART+ Spot PAR16 50 GU10 dimmable white',
|
|
191
|
+
extend: extend.ledvance.light_onoff_brightness(),
|
|
192
|
+
ota: ota.ledvance,
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
zigbeeModel: ['P40 DIM T'],
|
|
196
|
+
model: '4058075729100',
|
|
197
|
+
vendor: 'LEDVANCE',
|
|
198
|
+
description: 'SMART+ Classic P40 E14 dimmable white',
|
|
199
|
+
extend: extend.ledvance.light_onoff_brightness(),
|
|
200
|
+
ota: ota.ledvance,
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
zigbeeModel: ['A60 FIL DIM T'],
|
|
204
|
+
model: '4058075729209',
|
|
205
|
+
vendor: 'LEDVANCE',
|
|
206
|
+
description: 'SMART+ Filament Classic A 52 E27 Amber dimmable',
|
|
207
|
+
extend: extend.ledvance.light_onoff_brightness(),
|
|
208
|
+
ota: ota.ledvance,
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
zigbeeModel: ['EDISON60 FIL DIM T'],
|
|
212
|
+
model: '4058075729223',
|
|
213
|
+
vendor: 'LEDVANCE',
|
|
214
|
+
description: 'SMART+ Filament Edison 52 E27 Amber dimmable',
|
|
215
|
+
extend: extend.ledvance.light_onoff_brightness(),
|
|
216
|
+
ota: ota.ledvance,
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
zigbeeModel: ['GLOBE60 FIL DIM T'],
|
|
220
|
+
model: '4058075729247',
|
|
221
|
+
vendor: 'LEDVANCE',
|
|
222
|
+
description: 'SMART+ Filament Globe125 52 E27 Amber dimmable',
|
|
223
|
+
extend: extend.ledvance.light_onoff_brightness(),
|
|
224
|
+
ota: ota.ledvance,
|
|
225
|
+
},
|
|
226
|
+
|
|
178
227
|
];
|
package/devices/legrand.js
CHANGED
|
@@ -174,9 +174,10 @@ module.exports = [
|
|
|
174
174
|
vendor: 'Legrand',
|
|
175
175
|
description: 'Wired switch without neutral',
|
|
176
176
|
extend: extend.light_onoff_brightness({noConfigure: true}),
|
|
177
|
-
fromZigbee: [fz.brightness, fz.identify, fz.on_off, fz.lighting_ballast_configuration, fz.legrand_cluster_fc01
|
|
177
|
+
fromZigbee: [fz.brightness, fz.identify, fz.on_off, fz.lighting_ballast_configuration, fz.legrand_cluster_fc01,
|
|
178
|
+
fz.power_on_behavior],
|
|
178
179
|
toZigbee: [tz.light_onoff_brightness, tz.legrand_settingEnableLedInDark, tz.legrand_settingEnableLedIfOn,
|
|
179
|
-
tz.legrand_deviceMode, tz.legrand_identify, tz.ballast_config],
|
|
180
|
+
tz.legrand_deviceMode, tz.legrand_identify, tz.ballast_config, tz.power_on_behavior],
|
|
180
181
|
exposes: [e.light_brightness(),
|
|
181
182
|
exposes.numeric('ballast_minimum_level', ea.ALL).withValueMin(1).withValueMax(254)
|
|
182
183
|
.withDescription('Specifies the minimum brightness value'),
|
|
@@ -185,7 +186,8 @@ module.exports = [
|
|
|
185
186
|
exposes.binary('device_mode', ea.ALL, 'dimmer_on', 'dimmer_off').withDescription('Allow the device to change brightness'),
|
|
186
187
|
exposes.binary('led_in_dark', ea.ALL, 'ON', 'OFF').withDescription(`Enables the LED when the light is turned off, allowing to
|
|
187
188
|
see the switch in the dark`),
|
|
188
|
-
exposes.binary('led_if_on', ea.ALL, 'ON', 'OFF').withDescription('Enables the LED when the light is turned on')
|
|
189
|
+
exposes.binary('led_if_on', ea.ALL, 'ON', 'OFF').withDescription('Enables the LED when the light is turned on'),
|
|
190
|
+
e.power_on_behavior()],
|
|
189
191
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
190
192
|
await extend.light_onoff_brightness().configure(device, coordinatorEndpoint, logger);
|
|
191
193
|
const endpoint = device.getEndpoint(1);
|
|
@@ -201,10 +203,14 @@ module.exports = [
|
|
|
201
203
|
vendor: 'Legrand',
|
|
202
204
|
ota: ota.zigbeeOTA,
|
|
203
205
|
description: 'Power socket with power consumption monitoring',
|
|
204
|
-
fromZigbee: [fz.identify, fz.on_off, fz.electrical_measurement],
|
|
205
|
-
toZigbee: [tz.on_off, tz.legrand_settingEnableLedInDark, tz.legrand_identify, tz.legrand_settingEnableLedIfOn
|
|
206
|
+
fromZigbee: [fz.identify, fz.on_off, fz.electrical_measurement, fz.power_on_behavior],
|
|
207
|
+
toZigbee: [tz.on_off, tz.legrand_settingEnableLedInDark, tz.legrand_identify, tz.legrand_settingEnableLedIfOn,
|
|
208
|
+
tz.power_on_behavior],
|
|
206
209
|
exposes: [e.switch(), e.action(['identify']), e.power(),
|
|
207
|
-
exposes.binary('
|
|
210
|
+
exposes.binary('led_in_dark', ea.ALL, 'ON', 'OFF').withDescription(`Enables the LED when the power socket is turned off,
|
|
211
|
+
allowing to see it in the dark`),
|
|
212
|
+
exposes.binary('led_if_on', ea.ALL, 'ON', 'OFF').withDescription('Enables the LED when the device is turned on'),
|
|
213
|
+
e.power_on_behavior()],
|
|
208
214
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
209
215
|
const endpoint = device.getEndpoint(1);
|
|
210
216
|
await reporting.bind(endpoint, coordinatorEndpoint, ['genIdentify', 'genOnOff', 'haElectricalMeasurement']);
|
|
@@ -326,12 +332,14 @@ module.exports = [
|
|
|
326
332
|
model: '064882',
|
|
327
333
|
vendor: 'Legrand',
|
|
328
334
|
description: 'Cable outlet with pilot wire and consumption measurement',
|
|
329
|
-
fromZigbee: [fz.legrand_cluster_fc01, fz.legrand_cable_outlet_mode, fz.on_off, fz.electrical_measurement],
|
|
330
|
-
toZigbee: [tz.legrand_deviceMode, tz.legrand_cableOutletMode, tz.on_off, tz.electrical_measurement_power],
|
|
335
|
+
fromZigbee: [fz.legrand_cluster_fc01, fz.legrand_cable_outlet_mode, fz.on_off, fz.electrical_measurement, fz.power_on_behavior],
|
|
336
|
+
toZigbee: [tz.legrand_deviceMode, tz.legrand_cableOutletMode, tz.on_off, tz.electrical_measurement_power, tz.power_on_behavior],
|
|
331
337
|
exposes: [exposes.binary('device_mode', ea.ALL, 'pilot_on', 'pilot_off'),
|
|
332
338
|
exposes.enum('cable_outlet_mode', ea.ALL, ['comfort', 'comfort-1', 'comfort-2', 'eco', 'frost_protection', 'off']),
|
|
333
339
|
exposes.switch().withState('state', true, 'Works only when the pilot wire is deactivated'),
|
|
334
|
-
e.power().withAccess(ea.STATE_GET)
|
|
340
|
+
e.power().withAccess(ea.STATE_GET),
|
|
341
|
+
e.power_on_behavior().withDescription(`Controls the behavior when the device is powered on. Works only when the pilot wire is
|
|
342
|
+
deactivated`)],
|
|
335
343
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
336
344
|
const endpoint = device.getEndpoint(1);
|
|
337
345
|
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement', 'manuSpecificLegrandDevices2']);
|
package/devices/owon.js
CHANGED
|
@@ -227,4 +227,52 @@ module.exports = [
|
|
|
227
227
|
exposes.numeric('reactive_power_l3', ea.STATE).withUnit('VAr').withDescription('Phase 3 reactive power'),
|
|
228
228
|
],
|
|
229
229
|
},
|
|
230
|
+
{
|
|
231
|
+
zigbeeModel: ['PCT504'],
|
|
232
|
+
model: 'PCT504',
|
|
233
|
+
vendor: 'OWON',
|
|
234
|
+
description: 'HVAC fan coil',
|
|
235
|
+
fromZigbee: [fz.fan, fz.thermostat, fz.humidity, fz.occupancy, fz.legacy.hvac_user_interface],
|
|
236
|
+
toZigbee: [tz.fan_mode, tz.thermostat_system_mode,
|
|
237
|
+
tz.thermostat_occupied_heating_setpoint, tz.thermostat_unoccupied_heating_setpoint,
|
|
238
|
+
tz.thermostat_occupied_cooling_setpoint, tz.thermostat_unoccupied_cooling_setpoint,
|
|
239
|
+
tz.thermostat_min_heat_setpoint_limit, tz.thermostat_max_heat_setpoint_limit,
|
|
240
|
+
tz.thermostat_min_cool_setpoint_limit, tz.thermostat_max_cool_setpoint_limit,
|
|
241
|
+
tz.thermostat_local_temperature, tz.thermostat_running_state,
|
|
242
|
+
tz.thermostat_keypad_lockout],
|
|
243
|
+
exposes: [e.humidity(), e.occupancy(),
|
|
244
|
+
exposes.climate().withSystemMode(['off', 'heat', 'cool', 'fan_only']).withRunningState(['idle', 'heat', 'cool', 'fan_only'])
|
|
245
|
+
.withSetpoint('occupied_heating_setpoint', 5, 30, 0.5).withSetpoint('unoccupied_heating_setpoint', 5, 30, 0.5)
|
|
246
|
+
.withSetpoint('occupied_cooling_setpoint', 7, 35, 0.5).withSetpoint('unoccupied_cooling_setpoint', 7, 35, 0.5)
|
|
247
|
+
.withLocalTemperature(),
|
|
248
|
+
e.fan().withModes(['low', 'medium', 'high', 'on', 'auto']), e.keypad_lockout(),
|
|
249
|
+
e.max_heat_setpoint_limit(5, 30, 0.5), e.min_heat_setpoint_limit(5, 30, 0.5),
|
|
250
|
+
e.max_cool_setpoint_limit(7, 35, 0.5), e.min_cool_setpoint_limit(7, 35, 0.5)],
|
|
251
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
252
|
+
const endpoint = device.getEndpoint(1);
|
|
253
|
+
const binds = ['genBasic', 'genIdentify', 'genGroups', 'hvacThermostat', 'hvacUserInterfaceCfg', 'hvacFanCtrl',
|
|
254
|
+
'msTemperatureMeasurement', 'msOccupancySensing'];
|
|
255
|
+
await reporting.bind(endpoint, coordinatorEndpoint, binds);
|
|
256
|
+
await reporting.fanMode(endpoint);
|
|
257
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['hvacThermostat']);
|
|
258
|
+
await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
|
|
259
|
+
await reporting.thermostatUnoccupiedHeatingSetpoint(endpoint);
|
|
260
|
+
await reporting.thermostatOccupiedCoolingSetpoint(endpoint);
|
|
261
|
+
await reporting.thermostatUnoccupiedCoolingSetpoint(endpoint);
|
|
262
|
+
await reporting.thermostatTemperature(endpoint, {min: 60, max: 600, change: 0.1});
|
|
263
|
+
await reporting.thermostatSystemMode(endpoint);
|
|
264
|
+
await reporting.humidity(endpoint, {min: 60, max: 600, change: 1});
|
|
265
|
+
await reporting.thermostatKeypadLockMode(endpoint);
|
|
266
|
+
|
|
267
|
+
await endpoint.read('hvacThermostat', ['systemMode', 'runningState', 'occupiedHeatingSetpoint', 'unoccupiedHeatingSetpoint',
|
|
268
|
+
'occupiedCoolingSetpoint', 'unoccupiedCoolingSetpoint', 'localTemp'],
|
|
269
|
+
'minHeatSetpointLimit', 'maxHeatSetpointLimit', 'minCoolSetpointLimit', 'maxCoolSetpointLimit');
|
|
270
|
+
await endpoint.read('msRelativeHumidity', ['measuredValue']);
|
|
271
|
+
|
|
272
|
+
const endpoint2 = device.getEndpoint(2);
|
|
273
|
+
await reporting.bind(endpoint2, coordinatorEndpoint, ['msOccupancySensing']);
|
|
274
|
+
await reporting.occupancy(endpoint2, {min: 1, max: 600, change: 1});
|
|
275
|
+
await endpoint2.read('msOccupancySensing', ['occupancy']);
|
|
276
|
+
},
|
|
277
|
+
},
|
|
230
278
|
];
|
package/devices/philips.js
CHANGED
|
@@ -329,6 +329,13 @@ module.exports = [
|
|
|
329
329
|
description: 'Hue White ambiance Pillar spotlight',
|
|
330
330
|
extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
|
|
331
331
|
},
|
|
332
|
+
{
|
|
333
|
+
zigbeeModel: ['929003046001'],
|
|
334
|
+
model: '5309031P8',
|
|
335
|
+
vendor: 'Philips',
|
|
336
|
+
description: 'Hue White ambiance Runner spot white (1 spot)',
|
|
337
|
+
extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
|
|
338
|
+
},
|
|
332
339
|
{
|
|
333
340
|
zigbeeModel: ['929002376301'],
|
|
334
341
|
model: '929002376301',
|
|
@@ -87,7 +87,12 @@ module.exports = [
|
|
|
87
87
|
ota: ota.salus,
|
|
88
88
|
},
|
|
89
89
|
{
|
|
90
|
-
zigbeeModel: [
|
|
90
|
+
zigbeeModel: [
|
|
91
|
+
'SS909ZB',
|
|
92
|
+
'PS600\u0000\u0000 �\u0001 ��\u0000\u0000\t\u0001@\u0011�u\u0000\u0000\u0018&\n\u0005\u0000B',
|
|
93
|
+
'PS600\u0000\u0000 �\u0001 ��\u0000\u0000\t\u0001@\u0011�u\u0000\u0000\u0018\u0006\n\u0005\u0000',
|
|
94
|
+
'PS600\u0000\u0000 �\u0001 ��\u0000\u0000\t\u0001@\u0011�u\u0000\u0000\u0018\u0006\n\u0005\u0000B',
|
|
95
|
+
],
|
|
91
96
|
model: 'PS600',
|
|
92
97
|
vendor: 'Salus Controls',
|
|
93
98
|
description: 'Pipe temperature sensor',
|
package/devices/smartwings.js
CHANGED
|
@@ -12,7 +12,7 @@ module.exports = [
|
|
|
12
12
|
description: 'Roller shade',
|
|
13
13
|
fromZigbee: [fz.cover_position_tilt, fz.battery],
|
|
14
14
|
toZigbee: [tz.cover_state, tz.cover_position_tilt],
|
|
15
|
-
meta: {battery: {dontDividePercentage: true}},
|
|
15
|
+
meta: {battery: {dontDividePercentage: true}, coverInverted: true},
|
|
16
16
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
17
17
|
const endpoint = device.getEndpoint(1);
|
|
18
18
|
await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'closuresWindowCovering']);
|
package/devices/tuya.js
CHANGED
|
@@ -336,6 +336,16 @@ const fzLocal = {
|
|
|
336
336
|
return fz.battery.convert(model, msg, publish, options, meta);
|
|
337
337
|
},
|
|
338
338
|
},
|
|
339
|
+
TS0201_humidity: {
|
|
340
|
+
...fz.humidity,
|
|
341
|
+
convert: (model, msg, publish, options, meta) => {
|
|
342
|
+
const result = fz.humidity.convert(model, msg, publish, options, meta);
|
|
343
|
+
if (meta.device.manufacturerName === '_TZ3000_ywagc4rj') {
|
|
344
|
+
result.humidity = result.humidity * 10;
|
|
345
|
+
}
|
|
346
|
+
return result;
|
|
347
|
+
},
|
|
348
|
+
},
|
|
339
349
|
TS0222: {
|
|
340
350
|
cluster: 'manuSpecificTuya',
|
|
341
351
|
type: ['commandDataResponse', 'commandDataReport'],
|
|
@@ -1326,7 +1336,7 @@ module.exports = [
|
|
|
1326
1336
|
vendor: 'TuYa',
|
|
1327
1337
|
description: 'Temperature & humidity sensor with display',
|
|
1328
1338
|
whiteLabel: [{vendor: 'BlitzWolf', model: 'BW-IS4'}],
|
|
1329
|
-
fromZigbee: [fzLocal.TS0201_battery, fz.temperature,
|
|
1339
|
+
fromZigbee: [fzLocal.TS0201_battery, fz.temperature, fzLocal.TS0201_humidity],
|
|
1330
1340
|
toZigbee: [],
|
|
1331
1341
|
exposes: [e.battery(), e.temperature(), e.humidity(), e.battery_voltage()],
|
|
1332
1342
|
configure: async (device, coordinatorEndpoint, logger) => {
|
package/lib/constants.js
CHANGED
package/lib/exposes.js
CHANGED
|
@@ -588,6 +588,10 @@ module.exports = {
|
|
|
588
588
|
lock_action: () => new Enum('action', access.STATE, ['unknown', 'lock', 'unlock', 'lock_failure_invalid_pin_or_id', 'lock_failure_invalid_schedule', 'unlock_failure_invalid_pin_or_id', 'unlock_failure_invalid_schedule', 'one_touch_lock', 'key_lock', 'key_unlock', 'auto_lock', 'schedule_lock', 'schedule_unlock', 'manual_lock', 'manual_unlock', 'non_access_user_operational_event']).withDescription('Triggered action on the lock'),
|
|
589
589
|
lock_action_source_name: () => new Enum('action_source_name', access.STATE, ['keypad', 'rfid', 'manual', 'rf']).withDescription('Source of the triggered action on the lock'),
|
|
590
590
|
lock_action_user: () => new Numeric('action_user', access.STATE).withDescription('ID of user that triggered the action on the lock'),
|
|
591
|
+
max_cool_setpoint_limit: (min, max, step) => new Numeric('max_cool_setpoint_limit', access.ALL).withUnit('°C').withDescription('Maximum Cooling set point limit').withValueMin(min).withValueMax(max).withValueStep(step),
|
|
592
|
+
min_cool_setpoint_limit: (min, max, step) => new Numeric('min_cool_setpoint_limit', access.ALL).withUnit('°C').withDescription('Minimum Cooling point limit').withValueMin(min).withValueMax(max).withValueStep(step),
|
|
593
|
+
max_heat_setpoint_limit: (min, max, step) => new Numeric('max_heat_setpoint_limit', access.ALL).withUnit('°C').withDescription('Maximum Heating set point limit').withValueMin(min).withValueMax(max).withValueStep(step),
|
|
594
|
+
min_heat_setpoint_limit: (min, max, step) => new Numeric('min_heat_setpoint_limit', access.ALL).withUnit('°C').withDescription('Minimum Heating set point limit').withValueMin(min).withValueMax(max).withValueStep(step),
|
|
591
595
|
max_temperature: () => new Numeric('max_temperature', access.STATE_SET).withUnit('°C').withDescription('Maximum temperature').withValueMin(15).withValueMax(35),
|
|
592
596
|
max_temperature_limit: () => new Numeric('max_temperature_limit', access.STATE_SET).withUnit('°C').withDescription('Maximum temperature limit').withValueMin(0).withValueMax(35),
|
|
593
597
|
min_temperature: () => new Numeric('min_temperature', access.STATE_SET).withUnit('°C').withDescription('Minimum temperature').withValueMin(1).withValueMax(15),
|
|
@@ -608,7 +612,7 @@ module.exports = {
|
|
|
608
612
|
power_outage_memory: () => new Binary('power_outage_memory', access.ALL, true, false).withDescription('Enable/disable the power outage memory, this recovers the on/off mode after power failure'),
|
|
609
613
|
presence: () => new Binary('presence', access.STATE, true, false).withDescription('Indicates whether the device detected presence'),
|
|
610
614
|
pressure: () => new Numeric('pressure', access.STATE).withUnit('hPa').withDescription('The measured atmospheric pressure'),
|
|
611
|
-
programming_operation_mode: () => new Enum('programming_operation_mode', access.ALL, ['setpoint', 'schedule']).withDescription('Controls how programming affects the thermostat. Possible values: setpoint (only use specified setpoint), schedule (follow programmed setpoint schedule). Changing this value does not clear programmed schedules.'),
|
|
615
|
+
programming_operation_mode: () => new Enum('programming_operation_mode', access.ALL, ['setpoint', 'schedule', 'eco']).withDescription('Controls how programming affects the thermostat. Possible values: setpoint (only use specified setpoint), schedule (follow programmed setpoint schedule). Changing this value does not clear programmed schedules.'),
|
|
612
616
|
smoke: () => new Binary('smoke', access.STATE, true, false).withDescription('Indicates whether the device detected smoke'),
|
|
613
617
|
soil_moisture: () => new Numeric('soil_moisture', access.STATE).withUnit('%').withDescription('Measured soil moisture value'),
|
|
614
618
|
sos: () => new Binary('sos', access.STATE, true, false).withDescription('SOS alarm'),
|
package/lib/tuya.js
CHANGED
|
@@ -595,6 +595,8 @@ const dataPoints = {
|
|
|
595
595
|
dinrailPowerMeterCurrent: 18,
|
|
596
596
|
dinrailPowerMeterPower: 19,
|
|
597
597
|
dinrailPowerMeterVoltage: 20,
|
|
598
|
+
dinrailPowerMeterTotalEnergy2: 101,
|
|
599
|
+
dinrailPowerMeterPower2: 103,
|
|
598
600
|
// tuya smart air box
|
|
599
601
|
tuyaSabCO2: 2,
|
|
600
602
|
tuyaSabTemp: 18,
|