zigbee-herdsman-converters 14.0.535 → 14.0.538
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 +1 -1
- package/devices/centralite.js +27 -1
- package/devices/custom_devices_diy.js +36 -7
- package/devices/danalock.js +4 -3
- package/devices/ecodim.js +2 -1
- package/devices/gledopto.js +1 -1
- package/devices/heiman.js +9 -0
- package/devices/ikea.js +2 -2
- package/devices/m/303/274ller_licht.js +7 -11
- package/devices/niko.js +9 -0
- package/devices/sercomm.js +7 -3
- package/devices/tuya.js +189 -4
- package/devices/xiaomi.js +3 -3
- package/devices/zemismart.js +53 -0
- package/devices/zen.js +2 -1
- package/lib/xiaomi.js +4 -1
- package/package.json +1 -1
package/converters/fromZigbee.js
CHANGED
|
@@ -5267,7 +5267,7 @@ const converters = {
|
|
|
5267
5267
|
const value = tuya.getDataValue(dpValue);
|
|
5268
5268
|
const state = value ? 'ON' : 'OFF';
|
|
5269
5269
|
if (multiEndpoint) {
|
|
5270
|
-
const lookup = {1: 'l1', 2: 'l2', 3: 'l3', 4: 'l4'};
|
|
5270
|
+
const lookup = {1: 'l1', 2: 'l2', 3: 'l3', 4: 'l4', 5: 'l5', 6: 'l6'};
|
|
5271
5271
|
const endpoint = lookup[dp];
|
|
5272
5272
|
if (endpoint in model.endpoint(msg.device)) {
|
|
5273
5273
|
return {[`state_${endpoint}`]: state};
|
package/converters/toZigbee.js
CHANGED
|
@@ -3842,7 +3842,7 @@ const converters = {
|
|
|
3842
3842
|
tuya_switch_state: {
|
|
3843
3843
|
key: ['state'],
|
|
3844
3844
|
convertSet: async (entity, key, value, meta) => {
|
|
3845
|
-
const lookup = {l1: 1, l2: 2, l3: 3, l4: 4};
|
|
3845
|
+
const lookup = {l1: 1, l2: 2, l3: 3, l4: 4, l5: 5, l6: 6};
|
|
3846
3846
|
const multiEndpoint = utils.getMetaValue(entity, meta.mapped, 'multiEndpoint', 'allEqual', false);
|
|
3847
3847
|
const keyid = multiEndpoint ? lookup[meta.endpoint_name] : 1;
|
|
3848
3848
|
await tuya.sendDataPointBool(entity, keyid, value === 'ON');
|
package/devices/centralite.js
CHANGED
|
@@ -8,6 +8,32 @@ const e = exposes.presets;
|
|
|
8
8
|
const ea = exposes.access;
|
|
9
9
|
const constants = require('../lib/constants');
|
|
10
10
|
|
|
11
|
+
const fzLocal = {
|
|
12
|
+
thermostat_3156105: {
|
|
13
|
+
cluster: 'hvacThermostat',
|
|
14
|
+
type: ['attributeReport', 'readResponse'],
|
|
15
|
+
convert: (model, msg, publish, options, meta) => {
|
|
16
|
+
if (msg.data.hasOwnProperty('runningState')) {
|
|
17
|
+
if (msg.data['runningState'] == 1) {
|
|
18
|
+
msg.data['runningState'] = 0;
|
|
19
|
+
} else if (msg.data['runningState'] == 5) {
|
|
20
|
+
msg.data['runningState'] = 4;
|
|
21
|
+
} else if (msg.data['runningState'] == 7) {
|
|
22
|
+
msg.data['runningState'] = 6;
|
|
23
|
+
} else if (msg.data['runningState'] == 13) {
|
|
24
|
+
msg.data['runningState'] = 9;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if (msg.data.hasOwnProperty('ctrlSeqeOfOper')) {
|
|
28
|
+
if (msg.data['ctrlSeqeOfOper'] == 6) {
|
|
29
|
+
msg.data['ctrlSeqeOfOper'] = 4;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return fz.thermostat.convert(model, msg, publish, options, meta);
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
11
37
|
module.exports = [
|
|
12
38
|
{
|
|
13
39
|
zigbeeModel: ['4256251-RZHAC'],
|
|
@@ -195,7 +221,7 @@ module.exports = [
|
|
|
195
221
|
model: '3156105',
|
|
196
222
|
vendor: 'Centralite',
|
|
197
223
|
description: 'HA thermostat',
|
|
198
|
-
fromZigbee: [fz.battery,
|
|
224
|
+
fromZigbee: [fz.battery, fzLocal.thermostat_3156105, fz.fan, fz.ignore_time_read],
|
|
199
225
|
toZigbee: [tz.factory_reset, tz.thermostat_local_temperature,
|
|
200
226
|
tz.thermostat_occupied_heating_setpoint, tz.thermostat_occupied_cooling_setpoint,
|
|
201
227
|
tz.thermostat_setpoint_raise_lower, tz.thermostat_remote_sensing,
|
|
@@ -6,6 +6,37 @@ const extend = require('../lib/extend');
|
|
|
6
6
|
const e = exposes.presets;
|
|
7
7
|
const ea = exposes.access;
|
|
8
8
|
|
|
9
|
+
const tzLocal = {
|
|
10
|
+
node_config: {
|
|
11
|
+
key: ['report_delay'],
|
|
12
|
+
convertSet: async (entity, key, rawValue, meta) => {
|
|
13
|
+
const lookup = {'OFF': 0x00, 'ON': 0x01};
|
|
14
|
+
const value = lookup.hasOwnProperty(rawValue) ? lookup[rawValue] : parseInt(rawValue, 10);
|
|
15
|
+
const payloads = {
|
|
16
|
+
report_delay: ['genPowerCfg', {0x0201: {value, type: 0x21}}],
|
|
17
|
+
};
|
|
18
|
+
await entity.write(payloads[key][0], payloads[key][1]);
|
|
19
|
+
return {
|
|
20
|
+
state: {[key]: rawValue},
|
|
21
|
+
};
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const fzLocal = {
|
|
27
|
+
node_config: {
|
|
28
|
+
cluster: 'genPowerCfg',
|
|
29
|
+
type: ['attributeReport', 'readResponse'],
|
|
30
|
+
convert: (model, msg, publish, options, meta) => {
|
|
31
|
+
const result = {};
|
|
32
|
+
if (msg.data.hasOwnProperty(0x0201)) {
|
|
33
|
+
result.report_delay = msg.data[0x0201];
|
|
34
|
+
}
|
|
35
|
+
return result;
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
9
40
|
module.exports = [
|
|
10
41
|
{
|
|
11
42
|
zigbeeModel: ['ti.router'],
|
|
@@ -257,17 +288,15 @@ module.exports = [
|
|
|
257
288
|
model: 'EFEKTA_miniPWS',
|
|
258
289
|
vendor: 'Custom devices (DiY)',
|
|
259
290
|
description: '[Mini plant wattering sensor](http://efektalab.com/miniPWS)',
|
|
260
|
-
fromZigbee: [fz.soil_moisture, fz.battery],
|
|
261
|
-
toZigbee: [tz.factory_reset],
|
|
291
|
+
fromZigbee: [fz.soil_moisture, fz.battery, fzLocal.node_config],
|
|
292
|
+
toZigbee: [tz.factory_reset, tzLocal.node_config],
|
|
262
293
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
263
294
|
const firstEndpoint = device.getEndpoint(1);
|
|
264
295
|
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
296
|
},
|
|
270
|
-
exposes: [e.soil_moisture(), e.battery()
|
|
297
|
+
exposes: [e.soil_moisture(), e.battery(),
|
|
298
|
+
exposes.numeric('report_delay', ea.STATE_SET).withUnit('min').withDescription('Adjust Report Delay, by default 60 minutes')
|
|
299
|
+
.withValueMin(1).withValueMax(180)],
|
|
271
300
|
},
|
|
272
301
|
{
|
|
273
302
|
zigbeeModel: ['EFEKTA_eON213wz'],
|
package/devices/danalock.js
CHANGED
|
@@ -10,14 +10,15 @@ module.exports = [
|
|
|
10
10
|
model: 'V3-BTZB/V3-BTZBE',
|
|
11
11
|
vendor: 'Danalock',
|
|
12
12
|
description: 'BT/ZB smartlock',
|
|
13
|
-
fromZigbee: [fz.lock, fz.lock_operation_event, fz.battery],
|
|
14
|
-
toZigbee: [tz.lock],
|
|
13
|
+
fromZigbee: [fz.lock, fz.lock_operation_event, fz.battery, fz.lock_programming_event, fz.lock_pin_code_response],
|
|
14
|
+
toZigbee: [tz.lock, tz.pincode_lock, tz.lock_userstatus],
|
|
15
|
+
meta: {pinCodeCount: 20},
|
|
15
16
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
16
17
|
const endpoint = device.getEndpoint(1);
|
|
17
18
|
await reporting.bind(endpoint, coordinatorEndpoint, ['closuresDoorLock', 'genPowerCfg']);
|
|
18
19
|
await reporting.lockState(endpoint);
|
|
19
20
|
await reporting.batteryPercentageRemaining(endpoint);
|
|
20
21
|
},
|
|
21
|
-
exposes: [e.lock(), e.battery(), e.lock_action(), e.lock_action_source_name(), e.lock_action_source_user()],
|
|
22
|
+
exposes: [e.lock(), e.battery(), e.pincode(), e.lock_action(), e.lock_action_source_name(), e.lock_action_source_user()],
|
|
22
23
|
},
|
|
23
24
|
];
|
package/devices/ecodim.js
CHANGED
|
@@ -127,7 +127,8 @@ module.exports = [
|
|
|
127
127
|
extend: extend.light_onoff_brightness(),
|
|
128
128
|
},
|
|
129
129
|
{
|
|
130
|
-
fingerprint: [{modelID: 'CCT Light', manufacturerName: 'ZigBee/CCT', manufacturerID: 4137}
|
|
130
|
+
fingerprint: [{modelID: 'CCT Light', manufacturerName: 'ZigBee/CCT', manufacturerID: 4137},
|
|
131
|
+
{modelID: 'CCT Light', manufacturerName: 'Astuta/ZB-CCT', manufacturerID: 4137}],
|
|
131
132
|
model: 'ED-10041',
|
|
132
133
|
vendor: 'EcoDim',
|
|
133
134
|
description: 'Zigbee LED filament light dimmable E27, edison ST64, flame 2200K',
|
package/devices/gledopto.js
CHANGED
|
@@ -267,7 +267,7 @@ module.exports = [
|
|
|
267
267
|
vendor: 'Gledopto',
|
|
268
268
|
ota: ota.zigbeeOTA,
|
|
269
269
|
description: 'Zigbee LED Controller RGB+CCT (pro)',
|
|
270
|
-
whiteLabel: [{vendor: 'Gledopto', model: 'GL-C-001P'}],
|
|
270
|
+
whiteLabel: [{vendor: 'Gledopto', model: 'GL-C-001P'}, {vendor: 'Gledopto', model: 'GL-C-002P'}],
|
|
271
271
|
extend: gledoptoExtend.light_onoff_brightness_colortemp_color({colorTempRange: [158, 495], noConfigure: true}),
|
|
272
272
|
meta: {disableDefaultResponse: true},
|
|
273
273
|
configure: async (device, coordinatorEndpoint, logger) => {
|
package/devices/heiman.js
CHANGED
|
@@ -117,6 +117,15 @@ module.exports = [
|
|
|
117
117
|
toZigbee: [],
|
|
118
118
|
exposes: [e.gas(), e.battery_low(), e.tamper()],
|
|
119
119
|
},
|
|
120
|
+
{
|
|
121
|
+
zigbeeModel: ['RH3070'],
|
|
122
|
+
model: 'HS1CG',
|
|
123
|
+
vendor: 'Heiman',
|
|
124
|
+
description: 'Smart combustible gas sensor',
|
|
125
|
+
fromZigbee: [fz.ias_gas_alarm_1],
|
|
126
|
+
toZigbee: [],
|
|
127
|
+
exposes: [e.gas(), e.battery_low(), e.tamper()],
|
|
128
|
+
},
|
|
120
129
|
{
|
|
121
130
|
zigbeeModel: ['GAS_V15'],
|
|
122
131
|
model: 'HS1CG_M',
|
package/devices/ikea.js
CHANGED
|
@@ -36,10 +36,10 @@ const bulbOnEvent = async (type, data, device, options, state) => {
|
|
|
36
36
|
|
|
37
37
|
// NOTE: execute_if_off default is false
|
|
38
38
|
// we only restore if true, to save unneeded network writes
|
|
39
|
-
if (state.color_options !== undefined && state.color_options.execute_if_off === true) {
|
|
39
|
+
if (state !== undefined && state.color_options !== undefined && state.color_options.execute_if_off === true) {
|
|
40
40
|
device.endpoints[0].write('lightingColorCtrl', {'options': 1});
|
|
41
41
|
}
|
|
42
|
-
if (state.level_config !== undefined && state.level_config.execute_if_off === true) {
|
|
42
|
+
if (state !== undefined && state.level_config !== undefined && state.level_config.execute_if_off === true) {
|
|
43
43
|
device.endpoints[0].write('genLevelCtrl', {'options': 1});
|
|
44
44
|
}
|
|
45
45
|
}
|
|
@@ -155,20 +155,16 @@ module.exports = [
|
|
|
155
155
|
exposes: [e.action(['on', 'off', 'brightness_step_up', 'brightness_step_down', 'brightness_move_up', 'brightness_move_down',
|
|
156
156
|
'brightness_stop', 'color_temperature_move'])],
|
|
157
157
|
toZigbee: [],
|
|
158
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
159
|
+
device.powerSource = 'Battery';
|
|
160
|
+
device.save();
|
|
161
|
+
},
|
|
158
162
|
},
|
|
159
163
|
{
|
|
160
|
-
zigbeeModel: ['tint-ColorTemperature'],
|
|
161
|
-
model: '404037',
|
|
162
|
-
vendor: 'Müller Licht',
|
|
163
|
-
description: 'Tint retro filament LED-bulb E27, Edison bulb gold, white+ambiance (1800-6500K), dimmable, 5,5W',
|
|
164
|
-
extend: extend.light_onoff_brightness_colortemp(),
|
|
165
|
-
toZigbee: extend.light_onoff_brightness_colortemp().toZigbee.concat([tz.tint_scene]),
|
|
166
|
-
},
|
|
167
|
-
{
|
|
168
|
-
zigbeeModel: ['tint-ColorTemperature2'],
|
|
169
|
-
model: '404038',
|
|
164
|
+
zigbeeModel: ['tint-ColorTemperature', 'tint-ColorTemperature2'],
|
|
165
|
+
model: '404037/404038',
|
|
170
166
|
vendor: 'Müller Licht',
|
|
171
|
-
description: '
|
|
167
|
+
description: 'CCT LED-bulb',
|
|
172
168
|
extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 555]}),
|
|
173
169
|
toZigbee: extend.light_onoff_brightness_colortemp().toZigbee.concat([tz.tint_scene]),
|
|
174
170
|
},
|
package/devices/niko.js
CHANGED
|
@@ -219,4 +219,13 @@ module.exports = [
|
|
|
219
219
|
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled']).withEndpoint('l2'),
|
|
220
220
|
],
|
|
221
221
|
},
|
|
222
|
+
{
|
|
223
|
+
zigbeeModel: ['Connectable dimmer,3-200W,2-wire'],
|
|
224
|
+
model: '552-72201',
|
|
225
|
+
vendor: 'Niko',
|
|
226
|
+
description: 'Connectable dimmer',
|
|
227
|
+
fromZigbee: [fz.on_off, fz.brightness, fz.level_config, fz.command_move, fz.command_stop],
|
|
228
|
+
toZigbee: [tz.light_onoff_brightness, tz.level_config],
|
|
229
|
+
exposes: [e.light_brightness().withLevelConfig()],
|
|
230
|
+
},
|
|
222
231
|
];
|
package/devices/sercomm.js
CHANGED
|
@@ -26,15 +26,19 @@ module.exports = [
|
|
|
26
26
|
model: 'SZ-ESW01-AU',
|
|
27
27
|
vendor: 'Sercomm',
|
|
28
28
|
description: 'Telstra smart plug',
|
|
29
|
-
exposes: [e.switch(), e.power()],
|
|
30
|
-
fromZigbee: [fz.on_off, fz.metering],
|
|
29
|
+
exposes: [e.switch(), e.power(), e.energy(), e.current(), e.voltage()],
|
|
30
|
+
fromZigbee: [fz.on_off, fz.metering, fz.electrical_measurement],
|
|
31
31
|
toZigbee: [tz.on_off],
|
|
32
32
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
33
33
|
const endpoint = device.getEndpoint(1);
|
|
34
|
-
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'seMetering']);
|
|
34
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'seMetering', 'haElectricalMeasurement']);
|
|
35
35
|
await reporting.onOff(endpoint);
|
|
36
36
|
await reporting.instantaneousDemand(endpoint);
|
|
37
|
+
await reporting.currentSummDelivered(endpoint);
|
|
37
38
|
endpoint.saveClusterAttributeKeyValue('seMetering', {divisor: 1000000, multiplier: 1});
|
|
39
|
+
await reporting.readEletricalMeasurementMultiplierDivisors(endpoint);
|
|
40
|
+
await reporting.rmsVoltage(endpoint);
|
|
41
|
+
await reporting.rmsCurrent(endpoint);
|
|
38
42
|
},
|
|
39
43
|
},
|
|
40
44
|
{
|
package/devices/tuya.js
CHANGED
|
@@ -43,6 +43,87 @@ const tzLocal = {
|
|
|
43
43
|
}
|
|
44
44
|
},
|
|
45
45
|
},
|
|
46
|
+
power_on_behavior: {
|
|
47
|
+
key: ['power_on_behavior'],
|
|
48
|
+
convertSet: async (entity, key, value, meta) => {
|
|
49
|
+
value = value.toLowerCase();
|
|
50
|
+
const lookup = {'off': 0, 'on': 1, 'previous': 2};
|
|
51
|
+
utils.validateValue(value, Object.keys(lookup));
|
|
52
|
+
const pState = lookup[value];
|
|
53
|
+
await entity.write('manuSpecificTuya_3', {'powerOnBehavior': pState}, {disableDefaultResponse: true});
|
|
54
|
+
return {state: {power_on_behavior: value}};
|
|
55
|
+
},
|
|
56
|
+
convertGet: async (entity, key, meta) => {
|
|
57
|
+
await entity.read('manuSpecificTuya_3', ['powerOnBehavior']);
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
zb_sm_cover: {
|
|
61
|
+
key: ['state', 'position', 'reverse_direction', 'top_limit', 'bottom_limit', 'favorite_position', 'goto_positon', 'report'],
|
|
62
|
+
convertSet: async (entity, key, value, meta) => {
|
|
63
|
+
switch (key) {
|
|
64
|
+
case 'position': {
|
|
65
|
+
const invert = (meta.state) ? !meta.state.invert_cover : false;
|
|
66
|
+
value = invert ? 100 - value : value;
|
|
67
|
+
if (value >= 0 && value <= 100) {
|
|
68
|
+
await tuya.sendDataPointValue(entity, tuya.dataPoints.coverPosition, value);
|
|
69
|
+
} else {
|
|
70
|
+
throw new Error('TuYa_cover_control: Curtain motor position is out of range');
|
|
71
|
+
}
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
case 'state': {
|
|
75
|
+
const stateEnums = tuya.getCoverStateEnums(meta.device.manufacturerName);
|
|
76
|
+
meta.logger.debug(`TuYa_cover_control: Using state enums for ${meta.device.manufacturerName}:
|
|
77
|
+
${JSON.stringify(stateEnums)}`);
|
|
78
|
+
|
|
79
|
+
value = value.toLowerCase();
|
|
80
|
+
switch (value) {
|
|
81
|
+
case 'close':
|
|
82
|
+
await tuya.sendDataPointEnum(entity, tuya.dataPoints.state, stateEnums.close);
|
|
83
|
+
break;
|
|
84
|
+
case 'open':
|
|
85
|
+
await tuya.sendDataPointEnum(entity, tuya.dataPoints.state, stateEnums.open);
|
|
86
|
+
break;
|
|
87
|
+
case 'stop':
|
|
88
|
+
await tuya.sendDataPointEnum(entity, tuya.dataPoints.state, stateEnums.stop);
|
|
89
|
+
break;
|
|
90
|
+
default:
|
|
91
|
+
throw new Error('TuYa_cover_control: Invalid command received');
|
|
92
|
+
}
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
case 'reverse_direction': {
|
|
96
|
+
meta.logger.info(`Motor direction ${(value) ? 'reverse' : 'forward'}`);
|
|
97
|
+
await tuya.sendDataPointEnum(entity, tuya.dataPoints.motorDirection, (value) ? 1 : 0);
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
case 'top_limit': {
|
|
101
|
+
await tuya.sendDataPointEnum(entity, 104, {'SET': 0, 'CLEAR': 1}[value]);
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
case 'bottom_limit': {
|
|
105
|
+
await tuya.sendDataPointEnum(entity, 103, {'SET': 0, 'CLEAR': 1}[value]);
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
case 'favorite_position': {
|
|
109
|
+
await tuya.sendDataPointValue(entity, 115, value);
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
case 'goto_positon': {
|
|
113
|
+
if (value == 'FAVORITE') {
|
|
114
|
+
value = (meta.state) ? meta.state.favorite_position : null;
|
|
115
|
+
} else {
|
|
116
|
+
value = parseInt(value);
|
|
117
|
+
}
|
|
118
|
+
return tz.tuya_cover_control.convertSet(entity, 'position', value, meta);
|
|
119
|
+
}
|
|
120
|
+
case 'report': {
|
|
121
|
+
await tuya.sendDataPointBool(entity, 116, 0);
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
},
|
|
46
127
|
};
|
|
47
128
|
|
|
48
129
|
const fzLocal = {
|
|
@@ -99,6 +180,84 @@ const fzLocal = {
|
|
|
99
180
|
}
|
|
100
181
|
},
|
|
101
182
|
},
|
|
183
|
+
power_on_behavior: {
|
|
184
|
+
cluster: 'manuSpecificTuya_3',
|
|
185
|
+
type: ['attributeReport', 'readResponse'],
|
|
186
|
+
convert: (model, msg, publish, options, meta) => {
|
|
187
|
+
const attribute = 'powerOnBehavior';
|
|
188
|
+
const lookup = {0: 'off', 1: 'on', 2: 'previous'};
|
|
189
|
+
|
|
190
|
+
if (msg.data.hasOwnProperty(attribute)) {
|
|
191
|
+
const property = utils.postfixWithEndpointName('power_on_behavior', msg, model);
|
|
192
|
+
return {[property]: lookup[msg.data[attribute]]};
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
zb_sm_cover: {
|
|
197
|
+
cluster: 'manuSpecificTuya',
|
|
198
|
+
type: ['commandDataReport', 'commandDataResponse'],
|
|
199
|
+
convert: (model, msg, publish, options, meta) => {
|
|
200
|
+
const result = {};
|
|
201
|
+
for (const dpValue of msg.data.dpValues) {
|
|
202
|
+
const dp = dpValue.dp;
|
|
203
|
+
const value = tuya.getDataValue(dpValue);
|
|
204
|
+
|
|
205
|
+
switch (dp) {
|
|
206
|
+
case tuya.dataPoints.coverPosition: // Started moving to position (triggered from Zigbee)
|
|
207
|
+
case tuya.dataPoints.coverArrived: { // Arrived at position
|
|
208
|
+
const invert = (meta.state) ? !meta.state.invert_cover : false;
|
|
209
|
+
const position = invert ? 100 - (value & 0xFF) : (value & 0xFF);
|
|
210
|
+
if (position > 0 && position <= 100) {
|
|
211
|
+
result.position = position;
|
|
212
|
+
result.state = 'OPEN';
|
|
213
|
+
} else if (position == 0) { // Report fully closed
|
|
214
|
+
result.position = position;
|
|
215
|
+
result.state = 'CLOSE';
|
|
216
|
+
}
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
case 1: // report state
|
|
220
|
+
result.state = {0: 'OPEN', 1: 'STOP', 2: 'CLOSE'}[value];
|
|
221
|
+
break;
|
|
222
|
+
case tuya.dataPoints.motorDirection: // reverse direction
|
|
223
|
+
result.reverse_direction = (value == 1);
|
|
224
|
+
break;
|
|
225
|
+
case 10: // cycle time
|
|
226
|
+
result.cycle_time = value;
|
|
227
|
+
break;
|
|
228
|
+
case 101: // model
|
|
229
|
+
result.motor_type = {0: '', 1: 'AM0/6-28R-Sm', 2: 'AM0/10-19R-Sm',
|
|
230
|
+
3: 'AM1/10-13R-Sm', 4: 'AM1/20-13R-Sm', 5: 'AM1/30-13R-Sm'}[value];
|
|
231
|
+
break;
|
|
232
|
+
case 102: // cycles
|
|
233
|
+
result.cycle_count = value;
|
|
234
|
+
break;
|
|
235
|
+
case 103: // set or clear bottom limit
|
|
236
|
+
result.bottom_limit = {0: 'SET', 1: 'CLEAR'}[value];
|
|
237
|
+
break;
|
|
238
|
+
case 104: // set or clear top limit
|
|
239
|
+
result.top_limit = {0: 'SET', 1: 'CLEAR'}[value];
|
|
240
|
+
break;
|
|
241
|
+
case 109: // active power
|
|
242
|
+
result.active_power = value;
|
|
243
|
+
break;
|
|
244
|
+
case 115: // favorite_position
|
|
245
|
+
result.favorite_position = (value != 101) ? value : null;
|
|
246
|
+
break;
|
|
247
|
+
case 116: // report confirmation
|
|
248
|
+
break;
|
|
249
|
+
case 121: // running state
|
|
250
|
+
result.running_state = {0: 'OPENING', 1: 'STOPPED', 2: 'CLOSING'}[value];
|
|
251
|
+
result.running = (value !== 1) ? true : false;
|
|
252
|
+
break;
|
|
253
|
+
default: // Unknown code
|
|
254
|
+
meta.logger.warn(`zb_sm_tuya_cover: Unhandled DP #${dp} for ${meta.device.manufacturerName}:
|
|
255
|
+
${JSON.stringify(dpValue)}`);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
return result;
|
|
259
|
+
},
|
|
260
|
+
},
|
|
102
261
|
};
|
|
103
262
|
|
|
104
263
|
module.exports = [
|
|
@@ -391,6 +550,7 @@ module.exports = [
|
|
|
391
550
|
{modelID: 'TS0202', manufacturerName: '_TZ3000_otvn3lne'},
|
|
392
551
|
{modelID: 'TS0202', manufacturerName: '_TZ3000_tiwq83wk'},
|
|
393
552
|
{modelID: 'TS0202', manufacturerName: '_TZ3000_ykwcwxmz'},
|
|
553
|
+
{modelID: 'TS0202', manufacturerName: '_TZ3000_hgu1dlak'},
|
|
394
554
|
{modelID: 'WHD02', manufacturerName: '_TZ3000_hktqahrq'}],
|
|
395
555
|
model: 'TS0202',
|
|
396
556
|
vendor: 'TuYa',
|
|
@@ -1128,7 +1288,6 @@ module.exports = [
|
|
|
1128
1288
|
// Tubular motors:
|
|
1129
1289
|
{modelID: 'TS0601', manufacturerName: '_TZE200_5sbebbzs'},
|
|
1130
1290
|
{modelID: 'TS0601', manufacturerName: '_TZE200_zuz7f94z'},
|
|
1131
|
-
{modelID: 'TS0601', manufacturerName: '_TZE200_zyrdrmno'},
|
|
1132
1291
|
{modelID: 'TS0601', manufacturerName: '_TZE200_68nvbio9'},
|
|
1133
1292
|
],
|
|
1134
1293
|
model: 'TS0601_cover',
|
|
@@ -1800,9 +1959,11 @@ module.exports = [
|
|
|
1800
1959
|
model: 'TS0004',
|
|
1801
1960
|
vendor: 'TuYa',
|
|
1802
1961
|
description: 'Smart light switch - 4 gang with neutral wire',
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1962
|
+
fromZigbee: [fz.on_off, fzLocal.power_on_behavior, fz.ignore_basic_report],
|
|
1963
|
+
toZigbee: [tz.on_off, tzLocal.power_on_behavior],
|
|
1964
|
+
exposes: [e.switch().withEndpoint('l1'), e.power_on_behavior().withEndpoint('l1'), e.switch().withEndpoint('l2'),
|
|
1965
|
+
e.power_on_behavior().withEndpoint('l2'), e.switch().withEndpoint('l3'), e.power_on_behavior().withEndpoint('l3'),
|
|
1966
|
+
e.switch().withEndpoint('l4'), e.power_on_behavior().withEndpoint('l4')],
|
|
1806
1967
|
endpoint: (device) => {
|
|
1807
1968
|
return {'l1': 1, 'l2': 2, 'l3': 3, 'l4': 4};
|
|
1808
1969
|
},
|
|
@@ -2426,4 +2587,28 @@ module.exports = [
|
|
|
2426
2587
|
await reporting.batteryPercentageRemaining(endpoint);
|
|
2427
2588
|
},
|
|
2428
2589
|
},
|
|
2590
|
+
{
|
|
2591
|
+
fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_zyrdrmno'}],
|
|
2592
|
+
model: 'ZB-Sm',
|
|
2593
|
+
vendor: 'TuYa',
|
|
2594
|
+
description: 'Tubular motor',
|
|
2595
|
+
fromZigbee: [fzLocal.zb_sm_cover, fz.ignore_basic_report],
|
|
2596
|
+
toZigbee: [tzLocal.zb_sm_cover],
|
|
2597
|
+
onEvent: tuya.onEventSetTime,
|
|
2598
|
+
exposes: [
|
|
2599
|
+
e.cover_position().setAccess('position', ea.STATE_SET),
|
|
2600
|
+
exposes.enum('goto_positon', ea.SET, ['25', '50', '75', 'FAVORITE']),
|
|
2601
|
+
exposes.enum('running_state', ea.STATE, ['OPENING', 'CLOSING', 'STOPPED']),
|
|
2602
|
+
exposes.numeric('active_power', ea.STATE).withDescription('Active power').withUnit('mWt'),
|
|
2603
|
+
exposes.numeric('cycle_count', ea.STATE).withDescription('Cycle count'),
|
|
2604
|
+
exposes.numeric('cycle_time', ea.STATE).withDescription('Cycle time').withUnit('ms'),
|
|
2605
|
+
exposes.enum('top_limit', ea.STATE_SET, ['SET', 'CLEAR']).withDescription('Setup or clear top limit'),
|
|
2606
|
+
exposes.enum('bottom_limit', ea.STATE_SET, ['SET', 'CLEAR']).withDescription('Setup or clear bottom limit'),
|
|
2607
|
+
exposes.numeric('favorite_position', ea.STATE_SET).withValueMin(0).withValueMax(100)
|
|
2608
|
+
.withDescription('Favorite position of this cover'),
|
|
2609
|
+
exposes.binary(`reverse_direction`, ea.STATE_SET, true, false).withDescription(`Inverts the cover direction`),
|
|
2610
|
+
exposes.text('motor_type', ea.STATE),
|
|
2611
|
+
exposes.enum('report', ea.SET, ['REPORT']),
|
|
2612
|
+
],
|
|
2613
|
+
},
|
|
2429
2614
|
];
|
package/devices/xiaomi.js
CHANGED
|
@@ -1538,14 +1538,14 @@ module.exports = [
|
|
|
1538
1538
|
model: 'GZCGQ01LM',
|
|
1539
1539
|
vendor: 'Xiaomi',
|
|
1540
1540
|
description: 'MiJia light intensity sensor',
|
|
1541
|
-
fromZigbee: [fz.battery, fz.illuminance],
|
|
1541
|
+
fromZigbee: [fz.battery, fz.illuminance, fz.aqara_opple],
|
|
1542
1542
|
toZigbee: [],
|
|
1543
1543
|
meta: {battery: {voltageToPercentage: '3V_2850_3000_log'}},
|
|
1544
1544
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1545
1545
|
const endpoint = device.getEndpoint(1);
|
|
1546
|
-
await reporting.bind(endpoint, coordinatorEndpoint, ['
|
|
1547
|
-
await reporting.batteryVoltage(endpoint);
|
|
1546
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['msIlluminanceMeasurement']);
|
|
1548
1547
|
await reporting.illuminance(endpoint, {min: 15, max: constants.repInterval.HOUR, change: 500});
|
|
1548
|
+
await endpoint.read('genPowerCfg', ['batteryVoltage']);
|
|
1549
1549
|
},
|
|
1550
1550
|
exposes: [e.battery(), e.battery_voltage(), e.illuminance(), e.illuminance_lux()],
|
|
1551
1551
|
},
|
package/devices/zemismart.js
CHANGED
|
@@ -189,4 +189,57 @@ module.exports = [
|
|
|
189
189
|
toZigbee: [tz.tuya_cover_control, tz.tuya_cover_options, tz.tuya_data_point_test],
|
|
190
190
|
exposes: [e.cover_position().setAccess('position', ea.STATE_SET)],
|
|
191
191
|
},
|
|
192
|
+
{
|
|
193
|
+
fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_1n2kyphz'}],
|
|
194
|
+
model: 'TB26-4',
|
|
195
|
+
vendor: 'Zemismart',
|
|
196
|
+
description: '4-gang smart wall switch',
|
|
197
|
+
exposes: [e.switch().withEndpoint('l1').setAccess('state', ea.STATE_SET),
|
|
198
|
+
e.switch().withEndpoint('l2').setAccess('state', ea.STATE_SET),
|
|
199
|
+
e.switch().withEndpoint('l3').setAccess('state', ea.STATE_SET),
|
|
200
|
+
e.switch().withEndpoint('l4').setAccess('state', ea.STATE_SET)],
|
|
201
|
+
fromZigbee: [fz.ignore_basic_report, fz.tuya_switch],
|
|
202
|
+
toZigbee: [tz.tuya_switch_state],
|
|
203
|
+
meta: {multiEndpoint: true},
|
|
204
|
+
endpoint: (device) => {
|
|
205
|
+
return {'l1': 1, 'l2': 1, 'l3': 1, 'l4': 1};
|
|
206
|
+
},
|
|
207
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
208
|
+
await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
|
|
209
|
+
if (device.getEndpoint(2)) await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
|
|
210
|
+
if (device.getEndpoint(3)) await reporting.bind(device.getEndpoint(3), coordinatorEndpoint, ['genOnOff']);
|
|
211
|
+
if (device.getEndpoint(4)) await reporting.bind(device.getEndpoint(4), coordinatorEndpoint, ['genOnOff']);
|
|
212
|
+
device.powerSource = 'Mains (single phase)';
|
|
213
|
+
device.save();
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_9mahtqtg'}],
|
|
218
|
+
model: 'TB26-6',
|
|
219
|
+
vendor: 'Zemismart',
|
|
220
|
+
description: '6-gang smart wall switch',
|
|
221
|
+
exposes: [e.switch().withEndpoint('l1').setAccess('state', ea.STATE_SET),
|
|
222
|
+
e.switch().withEndpoint('l2').setAccess('state', ea.STATE_SET),
|
|
223
|
+
e.switch().withEndpoint('l3').setAccess('state', ea.STATE_SET),
|
|
224
|
+
e.switch().withEndpoint('l4').setAccess('state', ea.STATE_SET),
|
|
225
|
+
e.switch().withEndpoint('l5').setAccess('state', ea.STATE_SET),
|
|
226
|
+
e.switch().withEndpoint('l6').setAccess('state', ea.STATE_SET)],
|
|
227
|
+
fromZigbee: [fz.ignore_basic_report, fz.tuya_switch],
|
|
228
|
+
toZigbee: [tz.tuya_switch_state],
|
|
229
|
+
meta: {multiEndpoint: true},
|
|
230
|
+
endpoint: (device) => {
|
|
231
|
+
return {'l1': 1, 'l2': 1, 'l3': 1, 'l4': 1, 'l5': 1, 'l6': 1};
|
|
232
|
+
},
|
|
233
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
234
|
+
await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
|
|
235
|
+
if (device.getEndpoint(2)) await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
|
|
236
|
+
if (device.getEndpoint(3)) await reporting.bind(device.getEndpoint(3), coordinatorEndpoint, ['genOnOff']);
|
|
237
|
+
if (device.getEndpoint(4)) await reporting.bind(device.getEndpoint(4), coordinatorEndpoint, ['genOnOff']);
|
|
238
|
+
if (device.getEndpoint(5)) await reporting.bind(device.getEndpoint(5), coordinatorEndpoint, ['genOnOff']);
|
|
239
|
+
if (device.getEndpoint(6)) await reporting.bind(device.getEndpoint(6), coordinatorEndpoint, ['genOnOff']);
|
|
240
|
+
// Reports itself as battery which is not correct: https://github.com/Koenkk/zigbee2mqtt/issues/6190
|
|
241
|
+
device.powerSource = 'Mains (single phase)';
|
|
242
|
+
device.save();
|
|
243
|
+
},
|
|
244
|
+
},
|
|
192
245
|
];
|
package/devices/zen.js
CHANGED
|
@@ -15,7 +15,8 @@ module.exports = [
|
|
|
15
15
|
tz.thermostat_unoccupied_heating_setpoint, tz.thermostat_setpoint_raise_lower, tz.thermostat_running_state,
|
|
16
16
|
tz.thermostat_remote_sensing, tz.thermostat_control_sequence_of_operation, tz.thermostat_system_mode,
|
|
17
17
|
tz.thermostat_weekly_schedule, tz.thermostat_clear_weekly_schedule, tz.thermostat_relay_status_log],
|
|
18
|
-
exposes: [exposes.climate().withSetpoint('occupied_heating_setpoint', 10, 30, 0.5)
|
|
18
|
+
exposes: [exposes.climate().withSetpoint('occupied_heating_setpoint', 10, 30, 0.5)
|
|
19
|
+
.withSetpoint('occupied_cooling_setpoint', 10, 31, 0.5).withLocalTemperature()
|
|
19
20
|
.withSystemMode(['off', 'auto', 'heat', 'cool']).withRunningState(['idle', 'heat', 'cool'])
|
|
20
21
|
.withLocalTemperatureCalibration(-30, 30, 0.1).withPiHeatingDemand()],
|
|
21
22
|
configure: async (device, coordinatorEndpoint, logger) => {
|
package/lib/xiaomi.js
CHANGED
|
@@ -158,7 +158,7 @@ const numericAttributes2Payload = (msg, meta, model, options, dataObject) => {
|
|
|
158
158
|
}
|
|
159
159
|
break;
|
|
160
160
|
case '3':
|
|
161
|
-
if (['WXCJKG11LM', 'WXCJKG12LM', 'WXCJKG13LM', 'MCCGQ14LM'].includes(model.model)) {
|
|
161
|
+
if (['WXCJKG11LM', 'WXCJKG12LM', 'WXCJKG13LM', 'MCCGQ14LM', 'GZCGQ01LM'].includes(model.model)) {
|
|
162
162
|
// The temperature value is constant 25 °C and does not change, so we ignore it
|
|
163
163
|
// https://github.com/Koenkk/zigbee2mqtt/issues/11126
|
|
164
164
|
// https://github.com/Koenkk/zigbee-herdsman-converters/pull/3585
|
|
@@ -225,6 +225,9 @@ const numericAttributes2Payload = (msg, meta, model, options, dataObject) => {
|
|
|
225
225
|
// payload.water_leak = value === 1;
|
|
226
226
|
} else if (['JTYJ-GD-01LM/BW'].includes(model.model)) {
|
|
227
227
|
payload.smoke_density = value;
|
|
228
|
+
} else if (['GZCGQ01LM'].includes(model.model)) {
|
|
229
|
+
// DEPRECATED: change illuminance_lux -> illuminance
|
|
230
|
+
payload.illuminance_lux = calibrateAndPrecisionRoundOptions(value, options, 'illuminance_lux');
|
|
228
231
|
} else {
|
|
229
232
|
payload.state = value === 1 ? 'ON' : 'OFF';
|
|
230
233
|
}
|