zigbee-herdsman-converters 14.0.399 → 14.0.403
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 +83 -47
- package/converters/toZigbee.js +72 -2
- package/devices/casaia.js +8 -0
- package/devices/ikea.js +2 -2
- package/devices/legrand.js +15 -4
- package/devices/lonsonho.js +44 -0
- package/devices/moes.js +1 -1
- package/devices/namron.js +7 -0
- package/devices/perenio.js +0 -1
- package/devices/philips.js +9 -0
- package/devices/schneider_electric.js +31 -0
- package/devices/shinasystem.js +49 -8
- package/devices/tuya.js +33 -7
- package/devices/xiaomi.js +17 -34
- package/lib/exposes.js +1 -0
- package/lib/tuya.js +3 -0
- package/npm-shrinkwrap.json +1 -1
- package/package.json +1 -1
package/converters/fromZigbee.js
CHANGED
|
@@ -719,6 +719,7 @@ const converters = {
|
|
|
719
719
|
{key: 'rmsVoltage', name: 'voltage', factor: 'acVoltage'},
|
|
720
720
|
{key: 'rmsVoltagePhB', name: 'voltage_phase_b', factor: 'acVoltage'},
|
|
721
721
|
{key: 'rmsVoltagePhC', name: 'voltage_phase_c', factor: 'acVoltage'},
|
|
722
|
+
{key: 'acFrequency', name: 'ac_frequency', factor: 'acFrequency'},
|
|
722
723
|
];
|
|
723
724
|
|
|
724
725
|
const payload = {};
|
|
@@ -730,6 +731,9 @@ const converters = {
|
|
|
730
731
|
payload[property] = calibrateAndPrecisionRoundOptions(value, options, entry.name);
|
|
731
732
|
}
|
|
732
733
|
}
|
|
734
|
+
if (msg.data.hasOwnProperty('powerFactor')) {
|
|
735
|
+
payload.power_factor = precisionRound(msg.data['powerFactor'] / 100, 2);
|
|
736
|
+
}
|
|
733
737
|
return payload;
|
|
734
738
|
},
|
|
735
739
|
},
|
|
@@ -1042,7 +1046,7 @@ const converters = {
|
|
|
1042
1046
|
cluster: 'genScenes',
|
|
1043
1047
|
type: 'commandRecall',
|
|
1044
1048
|
convert: (model, msg, publish, options, meta) => {
|
|
1045
|
-
if (
|
|
1049
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1046
1050
|
const payload = {action: postfixWithEndpointName(`recall_${msg.data.sceneid}`, msg, model)};
|
|
1047
1051
|
addActionGroup(payload, msg, model);
|
|
1048
1052
|
return payload;
|
|
@@ -1052,7 +1056,7 @@ const converters = {
|
|
|
1052
1056
|
cluster: 'ssIasAce',
|
|
1053
1057
|
type: 'commandPanic',
|
|
1054
1058
|
convert: (model, msg, publish, options, meta) => {
|
|
1055
|
-
if (
|
|
1059
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1056
1060
|
const payload = {action: postfixWithEndpointName(`panic`, msg, model)};
|
|
1057
1061
|
addActionGroup(payload, msg, model);
|
|
1058
1062
|
return payload;
|
|
@@ -1062,7 +1066,7 @@ const converters = {
|
|
|
1062
1066
|
cluster: 'ssIasAce',
|
|
1063
1067
|
type: 'commandArm',
|
|
1064
1068
|
convert: (model, msg, publish, options, meta) => {
|
|
1065
|
-
if (
|
|
1069
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1066
1070
|
const payload = {
|
|
1067
1071
|
action: postfixWithEndpointName(constants.armMode[msg.data['armmode']], msg, model),
|
|
1068
1072
|
action_code: msg.data.code,
|
|
@@ -1086,7 +1090,7 @@ const converters = {
|
|
|
1086
1090
|
cluster: 'closuresWindowCovering',
|
|
1087
1091
|
type: 'commandStop',
|
|
1088
1092
|
convert: (model, msg, publish, options, meta) => {
|
|
1089
|
-
if (
|
|
1093
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1090
1094
|
const payload = {action: postfixWithEndpointName('stop', msg, model)};
|
|
1091
1095
|
addActionGroup(payload, msg, model);
|
|
1092
1096
|
return payload;
|
|
@@ -1096,7 +1100,7 @@ const converters = {
|
|
|
1096
1100
|
cluster: 'closuresWindowCovering',
|
|
1097
1101
|
type: 'commandUpOpen',
|
|
1098
1102
|
convert: (model, msg, publish, options, meta) => {
|
|
1099
|
-
if (
|
|
1103
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1100
1104
|
const payload = {action: postfixWithEndpointName('open', msg, model)};
|
|
1101
1105
|
addActionGroup(payload, msg, model);
|
|
1102
1106
|
return payload;
|
|
@@ -1106,7 +1110,7 @@ const converters = {
|
|
|
1106
1110
|
cluster: 'closuresWindowCovering',
|
|
1107
1111
|
type: 'commandDownClose',
|
|
1108
1112
|
convert: (model, msg, publish, options, meta) => {
|
|
1109
|
-
if (
|
|
1113
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1110
1114
|
const payload = {action: postfixWithEndpointName('close', msg, model)};
|
|
1111
1115
|
addActionGroup(payload, msg, model);
|
|
1112
1116
|
return payload;
|
|
@@ -1116,7 +1120,7 @@ const converters = {
|
|
|
1116
1120
|
cluster: 'genOnOff',
|
|
1117
1121
|
type: 'commandOn',
|
|
1118
1122
|
convert: (model, msg, publish, options, meta) => {
|
|
1119
|
-
if (
|
|
1123
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1120
1124
|
const payload = {action: postfixWithEndpointName('on', msg, model)};
|
|
1121
1125
|
addActionGroup(payload, msg, model);
|
|
1122
1126
|
return payload;
|
|
@@ -1126,7 +1130,7 @@ const converters = {
|
|
|
1126
1130
|
cluster: 'genOnOff',
|
|
1127
1131
|
type: 'commandOff',
|
|
1128
1132
|
convert: (model, msg, publish, options, meta) => {
|
|
1129
|
-
if (
|
|
1133
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1130
1134
|
const payload = {action: postfixWithEndpointName('off', msg, model)};
|
|
1131
1135
|
addActionGroup(payload, msg, model);
|
|
1132
1136
|
return payload;
|
|
@@ -1136,7 +1140,7 @@ const converters = {
|
|
|
1136
1140
|
cluster: 'genOnOff',
|
|
1137
1141
|
type: 'commandOffWithEffect',
|
|
1138
1142
|
convert: (model, msg, publish, options, meta) => {
|
|
1139
|
-
if (
|
|
1143
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1140
1144
|
const payload = {action: postfixWithEndpointName(`off`, msg, model)};
|
|
1141
1145
|
addActionGroup(payload, msg, model);
|
|
1142
1146
|
return payload;
|
|
@@ -1146,7 +1150,7 @@ const converters = {
|
|
|
1146
1150
|
cluster: 'genOnOff',
|
|
1147
1151
|
type: 'commandToggle',
|
|
1148
1152
|
convert: (model, msg, publish, options, meta) => {
|
|
1149
|
-
if (
|
|
1153
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1150
1154
|
const payload = {action: postfixWithEndpointName('toggle', msg, model)};
|
|
1151
1155
|
addActionGroup(payload, msg, model);
|
|
1152
1156
|
return payload;
|
|
@@ -1157,7 +1161,7 @@ const converters = {
|
|
|
1157
1161
|
type: ['commandMoveToLevel', 'commandMoveToLevelWithOnOff'],
|
|
1158
1162
|
options: [exposes.options.simulated_brightness()],
|
|
1159
1163
|
convert: (model, msg, publish, options, meta) => {
|
|
1160
|
-
if (
|
|
1164
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1161
1165
|
const payload = {
|
|
1162
1166
|
action: postfixWithEndpointName(`brightness_move_to_level`, msg, model),
|
|
1163
1167
|
action_level: msg.data.level,
|
|
@@ -1179,7 +1183,7 @@ const converters = {
|
|
|
1179
1183
|
type: ['commandMove', 'commandMoveWithOnOff'],
|
|
1180
1184
|
options: [exposes.options.simulated_brightness()],
|
|
1181
1185
|
convert: (model, msg, publish, options, meta) => {
|
|
1182
|
-
if (
|
|
1186
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1183
1187
|
const direction = msg.data.movemode === 1 ? 'down' : 'up';
|
|
1184
1188
|
const action = postfixWithEndpointName(`brightness_move_${direction}`, msg, model);
|
|
1185
1189
|
const payload = {action, action_rate: msg.data.rate};
|
|
@@ -1215,7 +1219,7 @@ const converters = {
|
|
|
1215
1219
|
type: ['commandStep', 'commandStepWithOnOff'],
|
|
1216
1220
|
options: [exposes.options.simulated_brightness()],
|
|
1217
1221
|
convert: (model, msg, publish, options, meta) => {
|
|
1218
|
-
if (
|
|
1222
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1219
1223
|
const direction = msg.data.stepmode === 1 ? 'down' : 'up';
|
|
1220
1224
|
const payload = {
|
|
1221
1225
|
action: postfixWithEndpointName(`brightness_step_${direction}`, msg, model),
|
|
@@ -1242,7 +1246,7 @@ const converters = {
|
|
|
1242
1246
|
type: ['commandStop', 'commandStopWithOnOff'],
|
|
1243
1247
|
options: [exposes.options.simulated_brightness()],
|
|
1244
1248
|
convert: (model, msg, publish, options, meta) => {
|
|
1245
|
-
if (
|
|
1249
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1246
1250
|
if (options.simulated_brightness) {
|
|
1247
1251
|
clearInterval(globalStore.getValue(msg.endpoint, 'simulated_brightness_timer'));
|
|
1248
1252
|
globalStore.putValue(msg.endpoint, 'simulated_brightness_timer', undefined);
|
|
@@ -1257,7 +1261,7 @@ const converters = {
|
|
|
1257
1261
|
cluster: 'lightingColorCtrl',
|
|
1258
1262
|
type: ['commandMoveColorTemp'],
|
|
1259
1263
|
convert: (model, msg, publish, options, meta) => {
|
|
1260
|
-
if (
|
|
1264
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1261
1265
|
const direction = msg.data.movemode === 1 ? 'down' : 'up';
|
|
1262
1266
|
const action = postfixWithEndpointName(`color_temperature_move_${direction}`, msg, model);
|
|
1263
1267
|
const payload = {action, action_rate: msg.data.rate, action_minimum: msg.data.minimum, action_maximum: msg.data.maximum};
|
|
@@ -1269,7 +1273,7 @@ const converters = {
|
|
|
1269
1273
|
cluster: 'lightingColorCtrl',
|
|
1270
1274
|
type: 'commandStepColorTemp',
|
|
1271
1275
|
convert: (model, msg, publish, options, meta) => {
|
|
1272
|
-
if (
|
|
1276
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1273
1277
|
const direction = msg.data.stepmode === 1 ? 'up' : 'down';
|
|
1274
1278
|
const payload = {
|
|
1275
1279
|
action: postfixWithEndpointName(`color_temperature_step_${direction}`, msg, model),
|
|
@@ -1288,7 +1292,7 @@ const converters = {
|
|
|
1288
1292
|
cluster: 'lightingColorCtrl',
|
|
1289
1293
|
type: 'commandEnhancedMoveToHueAndSaturation',
|
|
1290
1294
|
convert: (model, msg, publish, options, meta) => {
|
|
1291
|
-
if (
|
|
1295
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1292
1296
|
const payload = {
|
|
1293
1297
|
action: postfixWithEndpointName(`enhanced_move_to_hue_and_saturation`, msg, model),
|
|
1294
1298
|
action_enhanced_hue: msg.data.enhancehue,
|
|
@@ -1305,7 +1309,7 @@ const converters = {
|
|
|
1305
1309
|
cluster: 'lightingColorCtrl',
|
|
1306
1310
|
type: ['commandStepHue'],
|
|
1307
1311
|
convert: (model, msg, publish, options, meta) => {
|
|
1308
|
-
if (
|
|
1312
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1309
1313
|
const direction = msg.data.stepmode === 1 ? 'up' : 'down';
|
|
1310
1314
|
const payload = {
|
|
1311
1315
|
action: postfixWithEndpointName(`color_hue_step_${direction}`, msg, model),
|
|
@@ -1320,7 +1324,7 @@ const converters = {
|
|
|
1320
1324
|
cluster: 'lightingColorCtrl',
|
|
1321
1325
|
type: ['commandStepSaturation'],
|
|
1322
1326
|
convert: (model, msg, publish, options, meta) => {
|
|
1323
|
-
if (
|
|
1327
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1324
1328
|
const direction = msg.data.stepmode === 1 ? 'up' : 'down';
|
|
1325
1329
|
const payload = {
|
|
1326
1330
|
action: postfixWithEndpointName(`color_saturation_step_${direction}`, msg, model),
|
|
@@ -1335,7 +1339,7 @@ const converters = {
|
|
|
1335
1339
|
cluster: 'lightingColorCtrl',
|
|
1336
1340
|
type: 'commandColorLoopSet',
|
|
1337
1341
|
convert: (model, msg, publish, options, meta) => {
|
|
1338
|
-
if (
|
|
1342
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1339
1343
|
const updateFlags = msg.data.updateflags;
|
|
1340
1344
|
const actionLookup = {
|
|
1341
1345
|
0x00: 'deactivate',
|
|
@@ -1365,7 +1369,7 @@ const converters = {
|
|
|
1365
1369
|
cluster: 'lightingColorCtrl',
|
|
1366
1370
|
type: 'commandMoveToColorTemp',
|
|
1367
1371
|
convert: (model, msg, publish, options, meta) => {
|
|
1368
|
-
if (
|
|
1372
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1369
1373
|
const payload = {
|
|
1370
1374
|
action: postfixWithEndpointName(`color_temperature_move`, msg, model),
|
|
1371
1375
|
action_color_temperature: msg.data.colortemp,
|
|
@@ -1379,7 +1383,7 @@ const converters = {
|
|
|
1379
1383
|
cluster: 'lightingColorCtrl',
|
|
1380
1384
|
type: 'commandMoveToColor',
|
|
1381
1385
|
convert: (model, msg, publish, options, meta) => {
|
|
1382
|
-
if (
|
|
1386
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1383
1387
|
const payload = {
|
|
1384
1388
|
action: postfixWithEndpointName(`color_move`, msg, model),
|
|
1385
1389
|
action_color: {
|
|
@@ -1396,7 +1400,7 @@ const converters = {
|
|
|
1396
1400
|
cluster: 'lightingColorCtrl',
|
|
1397
1401
|
type: 'commandMoveHue',
|
|
1398
1402
|
convert: (model, msg, publish, options, meta) => {
|
|
1399
|
-
if (
|
|
1403
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1400
1404
|
const movestop = msg.data.movemode == 1 ? 'move' : 'stop';
|
|
1401
1405
|
const action = postfixWithEndpointName(`hue_${movestop}`, msg, model);
|
|
1402
1406
|
const payload = {action, action_rate: msg.data.rate};
|
|
@@ -1408,7 +1412,7 @@ const converters = {
|
|
|
1408
1412
|
cluster: 'lightingColorCtrl',
|
|
1409
1413
|
type: 'commandMoveToSaturation',
|
|
1410
1414
|
convert: (model, msg, publish, options, meta) => {
|
|
1411
|
-
if (
|
|
1415
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1412
1416
|
const payload = {
|
|
1413
1417
|
action: postfixWithEndpointName('move_to_saturation', msg, model),
|
|
1414
1418
|
action_saturation: msg.data.saturation,
|
|
@@ -1422,7 +1426,7 @@ const converters = {
|
|
|
1422
1426
|
cluster: 'lightingColorCtrl',
|
|
1423
1427
|
type: 'commandMoveToHue',
|
|
1424
1428
|
convert: (model, msg, publish, options, meta) => {
|
|
1425
|
-
if (
|
|
1429
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1426
1430
|
const payload = {
|
|
1427
1431
|
action: postfixWithEndpointName(`move_to_hue`, msg, model),
|
|
1428
1432
|
action_hue: msg.data.hue,
|
|
@@ -1437,7 +1441,7 @@ const converters = {
|
|
|
1437
1441
|
cluster: 'ssIasAce',
|
|
1438
1442
|
type: 'commandEmergency',
|
|
1439
1443
|
convert: (model, msg, publish, options, meta) => {
|
|
1440
|
-
if (
|
|
1444
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1441
1445
|
const payload = {action: postfixWithEndpointName(`emergency`, msg, model)};
|
|
1442
1446
|
addActionGroup(payload, msg, model);
|
|
1443
1447
|
return payload;
|
|
@@ -1447,7 +1451,7 @@ const converters = {
|
|
|
1447
1451
|
cluster: 'genOnOff',
|
|
1448
1452
|
type: 'commandOn',
|
|
1449
1453
|
convert: (model, msg, publish, options, meta) => {
|
|
1450
|
-
if (
|
|
1454
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1451
1455
|
const property = postfixWithEndpointName('state', msg, model);
|
|
1452
1456
|
return {[property]: 'ON'};
|
|
1453
1457
|
},
|
|
@@ -1456,7 +1460,7 @@ const converters = {
|
|
|
1456
1460
|
cluster: 'genOnOff',
|
|
1457
1461
|
type: 'commandOff',
|
|
1458
1462
|
convert: (model, msg, publish, options, meta) => {
|
|
1459
|
-
if (
|
|
1463
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1460
1464
|
const property = postfixWithEndpointName('state', msg, model);
|
|
1461
1465
|
return {[property]: 'OFF'};
|
|
1462
1466
|
},
|
|
@@ -2181,7 +2185,7 @@ const converters = {
|
|
|
2181
2185
|
cluster: 'ssIasZone',
|
|
2182
2186
|
type: 'commandStatusChangeNotification',
|
|
2183
2187
|
convert: (model, msg, publish, options, meta) => {
|
|
2184
|
-
if (
|
|
2188
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
2185
2189
|
const lookup = {1: 'pressed'};
|
|
2186
2190
|
const zoneStatus = msg.data.zonestatus;
|
|
2187
2191
|
return {
|
|
@@ -4045,7 +4049,8 @@ const converters = {
|
|
|
4045
4049
|
exposes.options.precision('humidity'), exposes.options.calibration('humidity'),
|
|
4046
4050
|
exposes.options.precision('co2'), exposes.options.calibration('co2'),
|
|
4047
4051
|
exposes.options.precision('voc'), exposes.options.calibration('voc'),
|
|
4048
|
-
exposes.options.precision('formaldehyd'), exposes.options.calibration('formaldehyd')
|
|
4052
|
+
exposes.options.precision('formaldehyd'), exposes.options.calibration('formaldehyd'),
|
|
4053
|
+
exposes.options.precision('pm25'), exposes.options.calibration('pm25')],
|
|
4049
4054
|
convert: (model, msg, publish, options, meta) => {
|
|
4050
4055
|
const dpValue = tuya.firstDpValue(msg, meta, 'tuya_air_quality');
|
|
4051
4056
|
const dp = dpValue.dp;
|
|
@@ -4062,6 +4067,8 @@ const converters = {
|
|
|
4062
4067
|
case tuya.dataPoints.tuyaSabFormaldehyd:
|
|
4063
4068
|
// Not sure which unit this is, supposedly mg/m³, but the value seems way too high.
|
|
4064
4069
|
return {formaldehyd: calibrateAndPrecisionRoundOptions(value, options, 'formaldehyd')};
|
|
4070
|
+
case tuya.dataPoints.tuyaSahkMP25:
|
|
4071
|
+
return {pm25: calibrateAndPrecisionRoundOptions(value, options, 'pm25')};
|
|
4065
4072
|
default:
|
|
4066
4073
|
meta.logger.warn(`zigbee-herdsman-converters:TuyaSmartAirBox: Unrecognized DP #${
|
|
4067
4074
|
dp} with data ${JSON.stringify(dpValue)}`);
|
|
@@ -4515,7 +4522,7 @@ const converters = {
|
|
|
4515
4522
|
cluster: 'genScenes',
|
|
4516
4523
|
type: 'commandTradfriArrowSingle',
|
|
4517
4524
|
convert: (model, msg, publish, options, meta) => {
|
|
4518
|
-
if (
|
|
4525
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
4519
4526
|
if (msg.data.value === 2) {
|
|
4520
4527
|
// This is send on toggle hold, ignore it as a toggle_hold is already handled above.
|
|
4521
4528
|
return;
|
|
@@ -4529,7 +4536,7 @@ const converters = {
|
|
|
4529
4536
|
cluster: 'genScenes',
|
|
4530
4537
|
type: 'commandTradfriArrowHold',
|
|
4531
4538
|
convert: (model, msg, publish, options, meta) => {
|
|
4532
|
-
if (
|
|
4539
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
4533
4540
|
const direction = msg.data.value === 3329 ? 'left' : 'right';
|
|
4534
4541
|
globalStore.putValue(msg.endpoint, 'direction', direction);
|
|
4535
4542
|
return {action: `arrow_${direction}_hold`};
|
|
@@ -4540,7 +4547,7 @@ const converters = {
|
|
|
4540
4547
|
type: 'commandTradfriArrowRelease',
|
|
4541
4548
|
options: [exposes.options.legacy()],
|
|
4542
4549
|
convert: (model, msg, publish, options, meta) => {
|
|
4543
|
-
if (
|
|
4550
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
4544
4551
|
const direction = globalStore.getValue(msg.endpoint, 'direction');
|
|
4545
4552
|
if (direction) {
|
|
4546
4553
|
globalStore.clearValue(msg.endpoint, 'direction');
|
|
@@ -5250,19 +5257,27 @@ const converters = {
|
|
|
5250
5257
|
else if (index === 5) {
|
|
5251
5258
|
if (['JT-BZ-01AQ/A'].includes(model.model)) payload.power_outage_count = value;
|
|
5252
5259
|
} else if (index === 100) {
|
|
5253
|
-
if (['
|
|
5260
|
+
if (['QBKG20LM', 'QBKG31LM', 'QBKG39LM', 'QBKG41LM', 'QBCZ15LM'].includes(model.model)) {
|
|
5254
5261
|
const mapping = model.model === 'QBCZ15LM' ? 'relay' : 'left';
|
|
5255
5262
|
payload[`state_${mapping}`] = value === 1 ? 'ON' : 'OFF';
|
|
5263
|
+
} else if (['WXKG14LM', 'WXKG16LM', 'WXKG17LM'].includes(model.model)) {
|
|
5264
|
+
payload.click_mode = {1: 'fast', 2: 'multi'}[value];
|
|
5256
5265
|
} else {
|
|
5257
5266
|
payload.state = value === 1 ? 'ON' : 'OFF';
|
|
5258
5267
|
}
|
|
5259
5268
|
} else if (index === 101) {
|
|
5260
|
-
if (['
|
|
5269
|
+
if (['QBKG20LM', 'QBKG31LM', 'QBKG39LM', 'QBKG41LM', 'QBCZ15LM'].includes(model.model)) {
|
|
5261
5270
|
const mapping = model.model === 'QBCZ15LM' ? 'usb' : 'right';
|
|
5262
5271
|
payload[`state_${mapping}`] = value === 1 ? 'ON' : 'OFF';
|
|
5272
|
+
} else if (['QBKG25LM', 'QBKG34LM'].includes(model.model)) {
|
|
5273
|
+
payload.state_center = value === 1 ? 'ON' : 'OFF';
|
|
5263
5274
|
} else if (['RTCGQ12LM'].includes(model.model)) {
|
|
5264
5275
|
payload.illuminance = calibrateAndPrecisionRoundOptions(value, options, 'illuminance');
|
|
5265
5276
|
}
|
|
5277
|
+
} else if (index ===102 ) {
|
|
5278
|
+
if (['QBKG25LM', 'QBKG34LM'].includes(model.model)) {
|
|
5279
|
+
payload.state_right = value === 1 ? 'ON' : 'OFF';
|
|
5280
|
+
}
|
|
5266
5281
|
} else if (index === 105) payload.motion_sensitivity = {1: 'low', 2: 'medium', 3: 'high'}[value]; // RTCGQ13LM
|
|
5267
5282
|
else if (index === 149) {
|
|
5268
5283
|
payload.energy = precisionRound(value, 2); // 0x95
|
|
@@ -5288,6 +5303,7 @@ const converters = {
|
|
|
5288
5303
|
}
|
|
5289
5304
|
if (msg.data.hasOwnProperty('4')) payload.mode_switch = {4: 'anti_flicker_mode', 1: 'quick_mode'}[msg.data['4']];
|
|
5290
5305
|
if (msg.data.hasOwnProperty('10')) payload.switch_type = {1: 'toggle', 2: 'momentary'}[msg.data['10']];
|
|
5306
|
+
if (msg.data.hasOwnProperty('240')) payload.flip_indicator_light = msg.data['240'] === 1 ? 'ON' : 'OFF';
|
|
5291
5307
|
if (msg.data.hasOwnProperty('258')) payload.detection_interval = msg.data['258'];
|
|
5292
5308
|
if (msg.data.hasOwnProperty('268')) {
|
|
5293
5309
|
if (['RTCGQ13LM'].includes(model.model)) {
|
|
@@ -5380,7 +5396,7 @@ const converters = {
|
|
|
5380
5396
|
cluster: 'genMultistateInput',
|
|
5381
5397
|
type: ['attributeReport'],
|
|
5382
5398
|
convert: (model, msg, publish, options, meta) => {
|
|
5383
|
-
if (
|
|
5399
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
5384
5400
|
let actionLookup = {0: 'hold', 1: 'single', 2: 'double', 3: 'triple', 255: 'release'};
|
|
5385
5401
|
if (model.model === 'WXKG12LM') {
|
|
5386
5402
|
actionLookup = {...actionLookup, 16: 'hold', 17: 'release', 18: 'shake'};
|
|
@@ -5526,7 +5542,7 @@ const converters = {
|
|
|
5526
5542
|
`increase it with this option (value is in ms).`),
|
|
5527
5543
|
],
|
|
5528
5544
|
convert: (model, msg, publish, options, meta) => {
|
|
5529
|
-
if (
|
|
5545
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
5530
5546
|
const state = msg.data['onOff'];
|
|
5531
5547
|
|
|
5532
5548
|
// 0 = click down, 1 = click up, else = multiple clicks
|
|
@@ -5832,7 +5848,7 @@ const converters = {
|
|
|
5832
5848
|
cluster: 'genMultistateInput',
|
|
5833
5849
|
type: ['attributeReport', 'readResponse'],
|
|
5834
5850
|
convert: (model, msg, publish, options, meta) => {
|
|
5835
|
-
if (
|
|
5851
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
5836
5852
|
const actionLookup = {0: 'hold', 255: 'release', 1: 'single', 2: 'double', 3: 'triple', 5: 'quintuple', 6: 'many'};
|
|
5837
5853
|
const button = msg.endpoint.ID;
|
|
5838
5854
|
const value = msg.data.presentValue;
|
|
@@ -5855,7 +5871,7 @@ const converters = {
|
|
|
5855
5871
|
cluster: 'genOnOff',
|
|
5856
5872
|
type: 'commandOn',
|
|
5857
5873
|
convert: (model, msg, publish, options, meta) => {
|
|
5858
|
-
if (
|
|
5874
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
5859
5875
|
return {action: 'button_2_single'};
|
|
5860
5876
|
},
|
|
5861
5877
|
},
|
|
@@ -5863,7 +5879,7 @@ const converters = {
|
|
|
5863
5879
|
cluster: 'genOnOff',
|
|
5864
5880
|
type: 'commandOff',
|
|
5865
5881
|
convert: (model, msg, publish, options, meta) => {
|
|
5866
|
-
if (
|
|
5882
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
5867
5883
|
return {action: 'button_1_single'};
|
|
5868
5884
|
},
|
|
5869
5885
|
},
|
|
@@ -5871,7 +5887,7 @@ const converters = {
|
|
|
5871
5887
|
cluster: 'genLevelCtrl',
|
|
5872
5888
|
type: 'commandStep',
|
|
5873
5889
|
convert: (model, msg, publish, options, meta) => {
|
|
5874
|
-
if (
|
|
5890
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
5875
5891
|
const button = msg.data.stepmode === 0 ? '4' : '3';
|
|
5876
5892
|
return {action: `button_${button}_single`};
|
|
5877
5893
|
},
|
|
@@ -5881,7 +5897,7 @@ const converters = {
|
|
|
5881
5897
|
type: 'commandStop',
|
|
5882
5898
|
options: [exposes.options.legacy()],
|
|
5883
5899
|
convert: (model, msg, publish, options, meta) => {
|
|
5884
|
-
if (
|
|
5900
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
5885
5901
|
if (globalStore.hasValue(msg.endpoint, 'button')) {
|
|
5886
5902
|
const value = globalStore.getValue(msg.endpoint, 'button');
|
|
5887
5903
|
const duration = Date.now() - value.start;
|
|
@@ -5895,7 +5911,7 @@ const converters = {
|
|
|
5895
5911
|
cluster: 'genLevelCtrl',
|
|
5896
5912
|
type: 'commandMove',
|
|
5897
5913
|
convert: (model, msg, publish, options, meta) => {
|
|
5898
|
-
if (
|
|
5914
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
5899
5915
|
const button = msg.data.movemode === 0 ? '4' : '3';
|
|
5900
5916
|
globalStore.putValue(msg.endpoint, 'button', {button, start: Date.now()});
|
|
5901
5917
|
return {action: `button_${button}_hold`};
|
|
@@ -5905,7 +5921,7 @@ const converters = {
|
|
|
5905
5921
|
cluster: 'lightingColorCtrl',
|
|
5906
5922
|
type: 'commandStepColorTemp',
|
|
5907
5923
|
convert: (model, msg, publish, options, meta) => {
|
|
5908
|
-
if (
|
|
5924
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
5909
5925
|
let action;
|
|
5910
5926
|
if (model.model === 'WXCJKG12LM') {
|
|
5911
5927
|
// for WXCJKG12LM model it's double click event on buttons 3 and 4
|
|
@@ -5922,7 +5938,7 @@ const converters = {
|
|
|
5922
5938
|
type: 'commandMoveColorTemp',
|
|
5923
5939
|
options: [exposes.options.legacy()],
|
|
5924
5940
|
convert: (model, msg, publish, options, meta) => {
|
|
5925
|
-
if (
|
|
5941
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
5926
5942
|
const stop = msg.data.movemode === 0;
|
|
5927
5943
|
let result = null;
|
|
5928
5944
|
if (stop) {
|
|
@@ -7229,6 +7245,26 @@ const converters = {
|
|
|
7229
7245
|
return {occupancy: (zoneStatus & 1) > 0, tamper: (zoneStatus & 4) > 0};
|
|
7230
7246
|
},
|
|
7231
7247
|
},
|
|
7248
|
+
ZM35HQ_attr: {
|
|
7249
|
+
cluster: 'ssIasZone',
|
|
7250
|
+
type: ['attributeReport', 'readResponse'],
|
|
7251
|
+
convert: (model, msg, publish, options, meta) => {
|
|
7252
|
+
let result = {};
|
|
7253
|
+
const data = msg.data;
|
|
7254
|
+
if (data && data.hasOwnProperty('zoneStatus')) {
|
|
7255
|
+
result = converters.ias_occupancy_alarm_1_report.convert(model, msg, publish, options, meta);
|
|
7256
|
+
}
|
|
7257
|
+
if (data && data.hasOwnProperty('currentZoneSensitivityLevel')) {
|
|
7258
|
+
const senslookup = {'0': 'low', '1': 'medium', '2': 'high'};
|
|
7259
|
+
result.sensitivity = senslookup[data.currentZoneSensitivityLevel];
|
|
7260
|
+
}
|
|
7261
|
+
if (data && data.hasOwnProperty('61441')) {
|
|
7262
|
+
const keeptimelookup = {'0': 30, '1': 60, '2': 120};
|
|
7263
|
+
result.keep_time = keeptimelookup[data['61441']];
|
|
7264
|
+
}
|
|
7265
|
+
return result;
|
|
7266
|
+
},
|
|
7267
|
+
},
|
|
7232
7268
|
tuya_gas: {
|
|
7233
7269
|
cluster: 'manuSpecificTuya',
|
|
7234
7270
|
type: ['commandDataResponse'],
|
|
@@ -7328,7 +7364,7 @@ const converters = {
|
|
|
7328
7364
|
cluster: 'wiserDeviceInfo',
|
|
7329
7365
|
type: 'attributeReport',
|
|
7330
7366
|
convert: (model, msg, publish, options, meta) => {
|
|
7331
|
-
if (
|
|
7367
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
7332
7368
|
|
|
7333
7369
|
const data = msg.data['deviceInfo'].split(',');
|
|
7334
7370
|
if (data[0] === 'UI' && data[1]) {
|
|
@@ -8106,7 +8142,7 @@ const converters = {
|
|
|
8106
8142
|
convert: (model, msg, publish, options, meta) => {
|
|
8107
8143
|
// commandStopMove without params
|
|
8108
8144
|
if (msg.data[2] !== 71) return;
|
|
8109
|
-
if (
|
|
8145
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
8110
8146
|
const movestop = 'stop';
|
|
8111
8147
|
const action = postfixWithEndpointName(`hue_${movestop}`, msg, model);
|
|
8112
8148
|
const payload = {action};
|
package/converters/toZigbee.js
CHANGED
|
@@ -1409,6 +1409,42 @@ const converters = {
|
|
|
1409
1409
|
await entity.read('seMetering', ['instantaneousDemand']);
|
|
1410
1410
|
},
|
|
1411
1411
|
},
|
|
1412
|
+
currentsummdelivered: {
|
|
1413
|
+
key: ['energy'],
|
|
1414
|
+
convertGet: async (entity, key, meta) => {
|
|
1415
|
+
await entity.read('seMetering', ['currentSummDelivered']);
|
|
1416
|
+
},
|
|
1417
|
+
},
|
|
1418
|
+
frequency: {
|
|
1419
|
+
key: ['ac_frequency'],
|
|
1420
|
+
convertGet: async (entity, key, meta) => {
|
|
1421
|
+
await entity.read('haElectricalMeasurement', ['acFrequency']);
|
|
1422
|
+
},
|
|
1423
|
+
},
|
|
1424
|
+
powerfactor: {
|
|
1425
|
+
key: ['power_factor'],
|
|
1426
|
+
convertGet: async (entity, key, meta) => {
|
|
1427
|
+
await entity.read('haElectricalMeasurement', ['powerFactor']);
|
|
1428
|
+
},
|
|
1429
|
+
},
|
|
1430
|
+
acvoltage: {
|
|
1431
|
+
key: ['voltage'],
|
|
1432
|
+
convertGet: async (entity, key, meta) => {
|
|
1433
|
+
await entity.read('haElectricalMeasurement', ['rmsVoltage']);
|
|
1434
|
+
},
|
|
1435
|
+
},
|
|
1436
|
+
accurrent: {
|
|
1437
|
+
key: ['current'],
|
|
1438
|
+
convertGet: async (entity, key, meta) => {
|
|
1439
|
+
await entity.read('haElectricalMeasurement', ['rmsCurrent']);
|
|
1440
|
+
},
|
|
1441
|
+
},
|
|
1442
|
+
temperature: {
|
|
1443
|
+
key: ['temperature'],
|
|
1444
|
+
convertGet: async (entity, key, meta) => {
|
|
1445
|
+
await entity.read('msTemperatureMeasurement', ['measuredValue']);
|
|
1446
|
+
},
|
|
1447
|
+
},
|
|
1412
1448
|
// #endregion
|
|
1413
1449
|
|
|
1414
1450
|
// #region Non-generic converters
|
|
@@ -2137,7 +2173,7 @@ const converters = {
|
|
|
2137
2173
|
key: ['led_disabled_night'],
|
|
2138
2174
|
convertSet: async (entity, key, value, meta) => {
|
|
2139
2175
|
if (['ZNCZ04LM', 'ZNCZ15LM', 'QBCZ14LM', 'QBCZ15LM', 'QBKG19LM', 'QBKG20LM', 'QBKG25LM', 'QBKG26LM',
|
|
2140
|
-
'QBKG34LM', 'DLKZMK11LM'].includes(meta.mapped.model)) {
|
|
2176
|
+
'QBKG31LM', 'QBKG34LM', 'DLKZMK11LM'].includes(meta.mapped.model)) {
|
|
2141
2177
|
await entity.write('aqaraOpple', {0x0203: {value: value ? 1 : 0, type: 0x10}}, manufacturerOptions.xiaomi);
|
|
2142
2178
|
} else if (['ZNCZ11LM'].includes(meta.mapped.model)) {
|
|
2143
2179
|
const payload = value ?
|
|
@@ -2152,13 +2188,24 @@ const converters = {
|
|
|
2152
2188
|
},
|
|
2153
2189
|
convertGet: async (entity, key, meta) => {
|
|
2154
2190
|
if (['ZNCZ04LM', 'ZNCZ15LM', 'QBCZ15LM', 'QBCZ14LM', 'QBKG19LM', 'QBKG20LM', 'QBKG25LM', 'QBKG26LM',
|
|
2155
|
-
'QBKG34LM', 'DLKZMK11LM'].includes(meta.mapped.model)) {
|
|
2191
|
+
'QBKG31LM', 'QBKG34LM', 'DLKZMK11LM'].includes(meta.mapped.model)) {
|
|
2156
2192
|
await entity.read('aqaraOpple', [0x0203], manufacturerOptions.xiaomi);
|
|
2157
2193
|
} else {
|
|
2158
2194
|
throw new Error('Not supported');
|
|
2159
2195
|
}
|
|
2160
2196
|
},
|
|
2161
2197
|
},
|
|
2198
|
+
xiaomi_flip_indicator_light: {
|
|
2199
|
+
key: ['flip_indicator_light'],
|
|
2200
|
+
convertSet: async (entity, key, value, meta) => {
|
|
2201
|
+
const lookup = {'OFF': 0, 'ON': 1};
|
|
2202
|
+
await entity.write('aqaraOpple', {0x00F0: {value: lookup[value], type: 0x20}}, manufacturerOptions.xiaomi);
|
|
2203
|
+
return {state: {flip_indicator_light: value}};
|
|
2204
|
+
},
|
|
2205
|
+
convertGet: async (entity, key, meta) => {
|
|
2206
|
+
await entity.read('aqaraOpple', [0x00F0], manufacturerOptions.xiaomi);
|
|
2207
|
+
},
|
|
2208
|
+
},
|
|
2162
2209
|
xiaomi_switch_operation_mode_basic: {
|
|
2163
2210
|
key: ['operation_mode'],
|
|
2164
2211
|
convertSet: async (entity, key, value, meta) => {
|
|
@@ -5961,6 +6008,29 @@ const converters = {
|
|
|
5961
6008
|
}
|
|
5962
6009
|
},
|
|
5963
6010
|
},
|
|
6011
|
+
ZM35HQ_attr: {
|
|
6012
|
+
key: [
|
|
6013
|
+
'sensitivity', 'keep_time',
|
|
6014
|
+
],
|
|
6015
|
+
convertSet: async (entity, key, value, meta) => {
|
|
6016
|
+
switch (key) {
|
|
6017
|
+
case 'sensitivity':
|
|
6018
|
+
await entity.write('ssIasZone', {currentZoneSensitivityLevel: {'low': 0, 'medium': 1, 'high': 2}[value]},
|
|
6019
|
+
{sendWhen: 'active'});
|
|
6020
|
+
break;
|
|
6021
|
+
case 'keep_time':
|
|
6022
|
+
await entity.write('ssIasZone', {61441: {value: {'30': 0, '60': 1, '120': 2}[value], type: 0x20}}, {sendWhen: 'active'});
|
|
6023
|
+
break;
|
|
6024
|
+
default: // Unknown key
|
|
6025
|
+
throw new Error(`Unhandled key ${key}`);
|
|
6026
|
+
}
|
|
6027
|
+
},
|
|
6028
|
+
convertGet: async (entity, key, meta) => {
|
|
6029
|
+
// Apparently, reading values may interfere with a commandStatusChangeNotification for changed occupancy.
|
|
6030
|
+
// Therefore, read "zoneStatus" as well.
|
|
6031
|
+
await entity.read('ssIasZone', ['currentZoneSensitivityLevel', 61441, 'zoneStatus'], {sendWhen: 'active'});
|
|
6032
|
+
},
|
|
6033
|
+
},
|
|
5964
6034
|
TS0210_sensitivity: {
|
|
5965
6035
|
key: ['sensitivity'],
|
|
5966
6036
|
convertSet: async (entity, key, value, meta) => {
|
package/devices/casaia.js
CHANGED
|
@@ -3,8 +3,16 @@ const fz = {...require('../converters/fromZigbee'), legacy: require('../lib/lega
|
|
|
3
3
|
const reporting = require('../lib/reporting');
|
|
4
4
|
const e = exposes.presets;
|
|
5
5
|
const tz = require('../converters/toZigbee');
|
|
6
|
+
const extend = require('../lib/extend');
|
|
6
7
|
|
|
7
8
|
module.exports = [
|
|
9
|
+
{
|
|
10
|
+
zigbeeModel: ['CSLC601-D-E'],
|
|
11
|
+
model: 'CSLC601-D-E',
|
|
12
|
+
vendor: 'CASAIA',
|
|
13
|
+
description: 'Dry contact relay switch module in 220v AC for gas boiler',
|
|
14
|
+
extend: extend.switch(),
|
|
15
|
+
},
|
|
8
16
|
{
|
|
9
17
|
zigbeeModel: ['CTHS317ET'],
|
|
10
18
|
model: 'CTHS-317-ET',
|
package/devices/ikea.js
CHANGED
|
@@ -746,10 +746,10 @@ module.exports = [
|
|
|
746
746
|
extend: tradfriExtend.light_onoff_brightness_colortemp_color(),
|
|
747
747
|
},
|
|
748
748
|
{
|
|
749
|
-
zigbeeModel: ['TRADFRIbulbE14WWclear250lm'],
|
|
749
|
+
zigbeeModel: ['TRADFRIbulbE14WWclear250lm', 'TRADFRIbulbE12WWclear250lm'],
|
|
750
750
|
model: 'LED1935C3',
|
|
751
751
|
vendor: 'IKEA',
|
|
752
|
-
description: 'TRADFRI LED bulb E14 WW clear 250 lumen, dimmable',
|
|
752
|
+
description: 'TRADFRI LED bulb E12/E14 WW clear 250 lumen, dimmable',
|
|
753
753
|
extend: tradfriExtend.light_onoff_brightness(),
|
|
754
754
|
},
|
|
755
755
|
{
|
package/devices/legrand.js
CHANGED
|
@@ -15,6 +15,16 @@ const readInitialBatteryState = async (type, data, device) => {
|
|
|
15
15
|
}
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
+
const fzLocal = {
|
|
19
|
+
command_off: {
|
|
20
|
+
cluster: 'genOnOff',
|
|
21
|
+
type: 'commandOff',
|
|
22
|
+
convert: (model, msg, publish, options, meta) => {
|
|
23
|
+
return {action: 'off'};
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
|
|
18
28
|
module.exports = [
|
|
19
29
|
{
|
|
20
30
|
zigbeeModel: [' Contactor\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000'+
|
|
@@ -107,11 +117,12 @@ module.exports = [
|
|
|
107
117
|
vendor: 'Legrand',
|
|
108
118
|
// led blink RED when battery is low
|
|
109
119
|
description: 'Wireless remote switch',
|
|
110
|
-
fromZigbee: [fz.identify, fz.command_on,
|
|
120
|
+
fromZigbee: [fz.identify, fz.command_on, fzLocal.command_off, fz.command_toggle, fz.legacy.cmd_move, fz.legacy.cmd_stop,
|
|
121
|
+
fz.battery],
|
|
111
122
|
exposes: [e.battery(), e.action(['identify', 'on', 'off', 'toggle', 'brightness_move_up',
|
|
112
123
|
'brightness_move_down', 'brightness_stop'])],
|
|
113
124
|
toZigbee: [],
|
|
114
|
-
meta: {
|
|
125
|
+
meta: {battery: {voltageToPercentage: '3V_2500'}},
|
|
115
126
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
116
127
|
const endpoint = device.getEndpoint(1);
|
|
117
128
|
await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'genOnOff', 'genLevelCtrl']);
|
|
@@ -123,11 +134,11 @@ module.exports = [
|
|
|
123
134
|
model: '067774',
|
|
124
135
|
vendor: 'Legrand',
|
|
125
136
|
description: 'Wireless double remote switch',
|
|
126
|
-
fromZigbee: [fz.identify, fz.command_on,
|
|
137
|
+
fromZigbee: [fz.identify, fz.command_on, fzLocal.command_off, fz.command_toggle, fz.command_move, fz.command_stop, fz.battery],
|
|
127
138
|
exposes: [e.battery(),
|
|
128
139
|
e.action(['identify', 'on', 'off', 'toggle', 'brightness_move_up', 'brightness_move_down', 'brightness_stop'])],
|
|
129
140
|
toZigbee: [],
|
|
130
|
-
meta: {
|
|
141
|
+
meta: {multiEndpoint: true, battery: {voltageToPercentage: '3V_2500'}},
|
|
131
142
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
132
143
|
const endpoint = device.getEndpoint(1);
|
|
133
144
|
await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'genOnOff', 'genLevelCtrl']);
|
package/devices/lonsonho.js
CHANGED
|
@@ -32,6 +32,26 @@ module.exports = [
|
|
|
32
32
|
exposes.enum('backlight_mode', ea.ALL, ['LOW', 'MEDIUM', 'HIGH']),
|
|
33
33
|
exposes.numeric('calibration_time', ea.STATE).withUnit('S').withDescription('Calibration time')],
|
|
34
34
|
},
|
|
35
|
+
{
|
|
36
|
+
fingerprint: [{modelID: 'TS130F', manufacturerName: '_TZ3000_j1xl73iw'}],
|
|
37
|
+
model: 'TS130F_dual',
|
|
38
|
+
vendor: 'Lonsonho',
|
|
39
|
+
description: 'Dual curtain/blind module',
|
|
40
|
+
fromZigbee: [fz.cover_position_tilt, fz.tuya_cover_options],
|
|
41
|
+
toZigbee: [tz.cover_state, tz.cover_position_tilt, tz.tuya_cover_calibration, tz.tuya_cover_reversal],
|
|
42
|
+
meta: {multiEndpoint: true},
|
|
43
|
+
endpoint: (device) => {
|
|
44
|
+
return {'left': 1, 'right': 2};
|
|
45
|
+
},
|
|
46
|
+
exposes: [
|
|
47
|
+
exposes.enum('moving', ea.STATE, ['UP', 'STOP', 'DOWN']),
|
|
48
|
+
exposes.numeric('calibration_time', ea.STATE).withUnit('S').withDescription('Calibration time'),
|
|
49
|
+
e.cover_position().withEndpoint('left'), exposes.binary('calibration', ea.ALL, 'ON', 'OFF')
|
|
50
|
+
.withEndpoint('left'), exposes.binary('motor_reversal', ea.ALL, 'ON', 'OFF').withEndpoint('left'),
|
|
51
|
+
e.cover_position().withEndpoint('right'), exposes.binary('calibration', ea.ALL, 'ON', 'OFF')
|
|
52
|
+
.withEndpoint('right'), exposes.binary('motor_reversal', ea.ALL, 'ON', 'OFF').withEndpoint('right'),
|
|
53
|
+
],
|
|
54
|
+
},
|
|
35
55
|
{
|
|
36
56
|
fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_8vxj8khv'}, {modelID: 'TS0601', manufacturerName: '_TZE200_7tdtqgwv'}],
|
|
37
57
|
model: 'X711A',
|
|
@@ -177,4 +197,28 @@ module.exports = [
|
|
|
177
197
|
await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
|
|
178
198
|
},
|
|
179
199
|
},
|
|
200
|
+
{
|
|
201
|
+
fingerprint: [{modelID: 'TS110E', manufacturerName: '_TZ3210_zxbtub8r'}],
|
|
202
|
+
model: 'TS110E_1gang',
|
|
203
|
+
vendor: 'Lonsonho',
|
|
204
|
+
description: 'Zigbee smart dimmer module 1 gang with neutral',
|
|
205
|
+
extend: extend.light_onoff_brightness(),
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
fingerprint: [{modelID: 'TS110E', manufacturerName: '_TZ3210_wdexaypg'}],
|
|
209
|
+
model: 'TS110E_2gang',
|
|
210
|
+
vendor: 'Lonsonho',
|
|
211
|
+
description: 'Zigbee smart dimmer module 2 gang with neutral',
|
|
212
|
+
extend: extend.light_onoff_brightness({noConfigure: true}),
|
|
213
|
+
meta: {multiEndpoint: true},
|
|
214
|
+
exposes: [e.light_brightness().withEndpoint('l1'), e.light_brightness().withEndpoint('l2')],
|
|
215
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
216
|
+
await extend.light_onoff_brightness().configure(device, coordinatorEndpoint, logger);
|
|
217
|
+
await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
|
|
218
|
+
await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
|
|
219
|
+
},
|
|
220
|
+
endpoint: (device) => {
|
|
221
|
+
return {l1: 1, l2: 2};
|
|
222
|
+
},
|
|
223
|
+
},
|
|
180
224
|
];
|
package/devices/moes.js
CHANGED
|
@@ -203,7 +203,7 @@ module.exports = [
|
|
|
203
203
|
},
|
|
204
204
|
},
|
|
205
205
|
{
|
|
206
|
-
fingerprint: [{modelID: 'TS0222', manufacturerName: '_TYZB01_kvwjujy9'}],
|
|
206
|
+
fingerprint: [{modelID: 'TS0222', manufacturerName: '_TYZB01_kvwjujy9'}, {modelID: 'TS0222', manufacturerName: '_TYZB01_ftdkanlj'}],
|
|
207
207
|
model: 'ZSS-ZK-THL',
|
|
208
208
|
vendor: 'Moes',
|
|
209
209
|
description: 'Smart temperature and humidity meter with display',
|
package/devices/namron.js
CHANGED
|
@@ -220,6 +220,13 @@ module.exports = [
|
|
|
220
220
|
description: 'LED 5,3W CCT E14',
|
|
221
221
|
extend: extend.light_onoff_brightness_colortemp(),
|
|
222
222
|
},
|
|
223
|
+
{
|
|
224
|
+
zigbeeModel: ['3802965'],
|
|
225
|
+
model: '3802965',
|
|
226
|
+
vendor: 'Namron',
|
|
227
|
+
description: 'LED 4,8W DIM GU10',
|
|
228
|
+
extend: extend.light_onoff_brightness(),
|
|
229
|
+
},
|
|
223
230
|
{
|
|
224
231
|
zigbeeModel: ['3802966'],
|
|
225
232
|
model: '3802966',
|
package/devices/perenio.js
CHANGED
|
@@ -40,7 +40,6 @@ module.exports = [
|
|
|
40
40
|
description: 'Motion sensor',
|
|
41
41
|
fromZigbee: [fz.battery, fz.ias_occupancy_alarm_1],
|
|
42
42
|
toZigbee: [],
|
|
43
|
-
meta: {battery: {dontDividePercentage: true}},
|
|
44
43
|
exposes: [e.occupancy(), e.battery_low(), e.tamper(), e.battery()],
|
|
45
44
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
46
45
|
const endpoint = device.getEndpoint(1);
|
package/devices/philips.js
CHANGED
|
@@ -36,6 +36,15 @@ module.exports = [
|
|
|
36
36
|
description: 'Hue white ambiance bathroom ceiling light Adore with Bluetooth',
|
|
37
37
|
extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
|
|
38
38
|
},
|
|
39
|
+
{
|
|
40
|
+
zigbeeModel: ['929003045301_01', '929003045301_02', '929003045301_03'],
|
|
41
|
+
model: '929003045301',
|
|
42
|
+
vendor: 'Philips',
|
|
43
|
+
description: 'Hue White and Color Ambiance GU10 (Centura)',
|
|
44
|
+
meta: {turnsOffAtBrightness1: true},
|
|
45
|
+
extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
|
|
46
|
+
ota: ota.zigbeeOTA,
|
|
47
|
+
},
|
|
39
48
|
{
|
|
40
49
|
zigbeeModel: ['929003056901'],
|
|
41
50
|
model: '929003056901',
|
|
@@ -642,4 +642,35 @@ module.exports = [
|
|
|
642
642
|
await reporting.currentSummDelivered(endpoint, {min: 60, change: 1});
|
|
643
643
|
},
|
|
644
644
|
},
|
|
645
|
+
{
|
|
646
|
+
zigbeeModel: ['NHMOTION/SWITCH/1'],
|
|
647
|
+
model: '545D6306',
|
|
648
|
+
vendor: 'Schneider Electric',
|
|
649
|
+
description: 'LK FUGA Wiser wireless PIR with relay',
|
|
650
|
+
fromZigbee: [fz.on_off, fz.illuminance, fz.occupancy, fz.occupancy_timeout],
|
|
651
|
+
exposes: [e.switch().withEndpoint('l1'), e.occupancy(), e.illuminance_lux(), e.illuminance(),
|
|
652
|
+
exposes.numeric('occupancy_timeout', ea.ALL).withUnit('second').withValueMin(0).withValueMax(3600)
|
|
653
|
+
.withDescription('Time in seconds after which occupancy is cleared after detecting it')],
|
|
654
|
+
toZigbee: [tz.on_off, tz.occupancy_timeout],
|
|
655
|
+
endpoint: (device) => {
|
|
656
|
+
return {'default': 37, 'l1': 1, 'l2': 37};
|
|
657
|
+
},
|
|
658
|
+
meta: {multiEndpoint: true},
|
|
659
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
660
|
+
const endpoint1 = device.getEndpoint(1);
|
|
661
|
+
const binds1 = ['genBasic', 'genIdentify', 'genOnOff'];
|
|
662
|
+
await reporting.bind(endpoint1, coordinatorEndpoint, binds1);
|
|
663
|
+
await reporting.onOff(endpoint1);
|
|
664
|
+
// read switch state
|
|
665
|
+
await endpoint1.read('genOnOff', ['onOff']);
|
|
666
|
+
|
|
667
|
+
const endpoint37 = device.getEndpoint(37);
|
|
668
|
+
const binds37 = ['msIlluminanceMeasurement', 'msOccupancySensing'];
|
|
669
|
+
await reporting.bind(endpoint37, coordinatorEndpoint, binds37);
|
|
670
|
+
await reporting.occupancy(endpoint37);
|
|
671
|
+
await reporting.illuminance(endpoint37);
|
|
672
|
+
// read occupancy_timeout
|
|
673
|
+
await endpoint37.read('msOccupancySensing', ['pirOToUDelay']);
|
|
674
|
+
},
|
|
675
|
+
},
|
|
645
676
|
];
|
package/devices/shinasystem.js
CHANGED
|
@@ -183,7 +183,7 @@ module.exports = [
|
|
|
183
183
|
toZigbee: [],
|
|
184
184
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
185
185
|
const endpoint = device.getEndpoint(1);
|
|
186
|
-
await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
|
|
186
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'genPowerCfg']);
|
|
187
187
|
await reporting.batteryVoltage(endpoint);
|
|
188
188
|
},
|
|
189
189
|
exposes: [e.battery(), e.battery_voltage(), e.action(['single', 'double', 'long'])],
|
|
@@ -230,11 +230,14 @@ module.exports = [
|
|
|
230
230
|
toZigbee: [],
|
|
231
231
|
exposes: [e.action(['1_single', '1_double', '1_long', '2_single', '2_double', '2_long',
|
|
232
232
|
'3_single', '3_double', '3_long', '4_single', '4_double', '4_long']), e.battery(), e.battery_voltage()],
|
|
233
|
-
meta: {battery: {voltageToPercentage: '3V_2100'}},
|
|
233
|
+
meta: {battery: {voltageToPercentage: '3V_2100'}, multiEndpoint: true},
|
|
234
234
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
235
235
|
const endpoint = device.getEndpoint(1);
|
|
236
|
-
await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
|
|
236
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'genPowerCfg']);
|
|
237
237
|
await reporting.batteryVoltage(endpoint, {min: 30, max: 21600, change: 1});
|
|
238
|
+
await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
|
|
239
|
+
await reporting.bind(device.getEndpoint(3), coordinatorEndpoint, ['genOnOff']);
|
|
240
|
+
await reporting.bind(device.getEndpoint(4), coordinatorEndpoint, ['genOnOff']);
|
|
238
241
|
},
|
|
239
242
|
},
|
|
240
243
|
{
|
|
@@ -247,7 +250,7 @@ module.exports = [
|
|
|
247
250
|
toZigbee: [],
|
|
248
251
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
249
252
|
const endpoint = device.getEndpoint(1);
|
|
250
|
-
await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
|
|
253
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'genPowerCfg']);
|
|
251
254
|
await reporting.batteryVoltage(endpoint);
|
|
252
255
|
},
|
|
253
256
|
exposes: [e.battery(), e.battery_voltage(), e.action(['single', 'double', 'long'])],
|
|
@@ -260,12 +263,14 @@ module.exports = [
|
|
|
260
263
|
fromZigbee: [fz.sihas_action, fz.battery],
|
|
261
264
|
toZigbee: [],
|
|
262
265
|
exposes: [e.action(['1_single', '1_double', '1_long', '2_single', '2_double', '2_long']), e.battery(), e.battery_voltage()],
|
|
263
|
-
meta: {battery: {voltageToPercentage: '3V_2100'}},
|
|
266
|
+
meta: {battery: {voltageToPercentage: '3V_2100'}, multiEndpoint: true},
|
|
264
267
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
265
268
|
const endpoint = device.getEndpoint(1);
|
|
266
|
-
await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
|
|
269
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'genPowerCfg']);
|
|
267
270
|
await reporting.batteryVoltage(endpoint, {min: 30, max: 21600, change: 1});
|
|
271
|
+
await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
|
|
268
272
|
},
|
|
273
|
+
|
|
269
274
|
},
|
|
270
275
|
{
|
|
271
276
|
zigbeeModel: ['SBM300ZB3'],
|
|
@@ -276,11 +281,13 @@ module.exports = [
|
|
|
276
281
|
toZigbee: [],
|
|
277
282
|
exposes: [e.action(['1_single', '1_double', '1_long', '2_single', '2_double', '2_long',
|
|
278
283
|
'3_single', '3_double', '3_long']), e.battery(), e.battery_voltage()],
|
|
279
|
-
meta: {battery: {voltageToPercentage: '3V_2100'}},
|
|
284
|
+
meta: {battery: {voltageToPercentage: '3V_2100'}, multiEndpoint: true},
|
|
280
285
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
281
286
|
const endpoint = device.getEndpoint(1);
|
|
282
|
-
await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
|
|
287
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'genPowerCfg']);
|
|
283
288
|
await reporting.batteryVoltage(endpoint, {min: 30, max: 21600, change: 1});
|
|
289
|
+
await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
|
|
290
|
+
await reporting.bind(device.getEndpoint(3), coordinatorEndpoint, ['genOnOff']);
|
|
284
291
|
},
|
|
285
292
|
},
|
|
286
293
|
{
|
|
@@ -300,4 +307,38 @@ module.exports = [
|
|
|
300
307
|
await reporting.currentSummDelivered(endpoint, {min: 1, max: 600, change: 5});
|
|
301
308
|
},
|
|
302
309
|
},
|
|
310
|
+
{
|
|
311
|
+
zigbeeModel: ['PMM-300Z2'],
|
|
312
|
+
model: 'PMM-300Z2',
|
|
313
|
+
vendor: 'ShinaSystem',
|
|
314
|
+
description: 'SiHAS energy monitor',
|
|
315
|
+
fromZigbee: [fz.electrical_measurement, fz.metering, fz.temperature],
|
|
316
|
+
toZigbee: [tz.metering_power, tz.currentsummdelivered, tz.frequency, tz.powerfactor, tz.acvoltage, tz.accurrent, tz.temperature],
|
|
317
|
+
exposes: [e.power().withAccess(ea.STATE_GET), e.energy().withAccess(ea.STATE_GET),
|
|
318
|
+
e.current().withAccess(ea.STATE_GET), e.voltage().withAccess(ea.STATE_GET),
|
|
319
|
+
e.temperature().withAccess(ea.STATE_GET).withDescription('temperature of device internal mcu'),
|
|
320
|
+
exposes.numeric('power_factor', ea.STATE_GET).withDescription('Measured electrical power factor'),
|
|
321
|
+
exposes.numeric('ac_frequency', ea.STATE_GET).withUnit('Hz').withDescription('Measured electrical ac frequency')],
|
|
322
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
323
|
+
const endpoint = device.getEndpoint(1);
|
|
324
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['haElectricalMeasurement', 'seMetering', 'msTemperatureMeasurement']);
|
|
325
|
+
await endpoint.read('haElectricalMeasurement', ['acVoltageMultiplier', 'acVoltageDivisor', 'acCurrentMultiplier',
|
|
326
|
+
'acCurrentDivisor']);
|
|
327
|
+
await endpoint.read('seMetering', ['multiplier', 'divisor']);
|
|
328
|
+
// await reporting.activePower(endpoint, {min: 1, max: 600, change: 5}); // no need, duplicate for power value.
|
|
329
|
+
await reporting.instantaneousDemand(endpoint, {min: 1, max: 600, change: 5});
|
|
330
|
+
await reporting.powerFactor(endpoint, {min: 10, max: 600, change: 1});
|
|
331
|
+
await reporting.rmsVoltage(endpoint, {min: 5, max: 600, change: 1});
|
|
332
|
+
await reporting.rmsCurrent(endpoint, {min: 5, max: 600, change: 1});
|
|
333
|
+
await reporting.currentSummDelivered(endpoint, {min: 1, max: 600, change: 5});
|
|
334
|
+
await reporting.temperature(endpoint, {min: 20, max: 300, change: 10});
|
|
335
|
+
endpoint.saveClusterAttributeKeyValue('haElectricalMeasurement', {acFrequencyMultiplier: 1, acFrequencyDivisor: 10});
|
|
336
|
+
await endpoint.configureReporting('haElectricalMeasurement', [{
|
|
337
|
+
attribute: 'acFrequency',
|
|
338
|
+
minimumReportInterval: 10,
|
|
339
|
+
maximumReportInterval: 600,
|
|
340
|
+
reportableChange: 3,
|
|
341
|
+
}]);
|
|
342
|
+
},
|
|
343
|
+
},
|
|
303
344
|
];
|
package/devices/tuya.js
CHANGED
|
@@ -12,7 +12,7 @@ const utils = require('../lib/utils');
|
|
|
12
12
|
|
|
13
13
|
const TS011Fplugs = ['_TZ3000_5f43h46b', '_TZ3000_cphmq0q7', '_TZ3000_dpo1ysak', '_TZ3000_ew3ldmgx', '_TZ3000_gjnozsaz',
|
|
14
14
|
'_TZ3000_jvzvulen', '_TZ3000_mraovvmm', '_TZ3000_nfnmi125', '_TZ3000_ps3dmato', '_TZ3000_w0qqde0g', '_TZ3000_u5u4cakc',
|
|
15
|
-
'_TZ3000_rdtixbnu', '_TZ3000_typdpbpg'
|
|
15
|
+
'_TZ3000_rdtixbnu', '_TZ3000_typdpbpg'];
|
|
16
16
|
|
|
17
17
|
const tzLocal = {
|
|
18
18
|
TS0504B_color: {
|
|
@@ -89,6 +89,15 @@ module.exports = [
|
|
|
89
89
|
toZigbee: [],
|
|
90
90
|
exposes: [e.temperature(), e.humidity(), e.co2(), e.voc(), e.formaldehyd()],
|
|
91
91
|
},
|
|
92
|
+
{
|
|
93
|
+
fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_dwcarsat'}],
|
|
94
|
+
model: 'TS0601_smart_air_house_keeper',
|
|
95
|
+
vendor: 'TuYa',
|
|
96
|
+
description: 'Smart air house keeper',
|
|
97
|
+
fromZigbee: [fz.tuya_air_quality],
|
|
98
|
+
toZigbee: [],
|
|
99
|
+
exposes: [e.temperature(), e.humidity(), e.co2(), e.voc(), e.formaldehyd(), e.pm25()],
|
|
100
|
+
},
|
|
92
101
|
{
|
|
93
102
|
fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_ggev5fsl'}],
|
|
94
103
|
model: 'TS0601_gas_sensor',
|
|
@@ -159,6 +168,7 @@ module.exports = [
|
|
|
159
168
|
{modelID: 'TS0505B', manufacturerName: '_TZ3000_1mtktxdk'},
|
|
160
169
|
{modelID: 'TS0505B', manufacturerName: '_TZ3210_remypqqm'},
|
|
161
170
|
{modelID: 'TS0505B', manufacturerName: '_TZ3000_kohbva1f'},
|
|
171
|
+
{modelID: 'TS0505B', manufacturerName: '_TZ3210_wslkvrau'},
|
|
162
172
|
{modelID: 'TS0505B', manufacturerName: '_TZ3210_0rn9qhnu'},
|
|
163
173
|
{modelID: 'TS0505B', manufacturerName: '_TZ3210_bicjqpg4'},
|
|
164
174
|
{modelID: 'TS0505B', manufacturerName: '_TZ3000_cmaky9gq'},
|
|
@@ -212,6 +222,7 @@ module.exports = [
|
|
|
212
222
|
fingerprint: [{modelID: 'TS0501B', manufacturerName: '_TZ3000_4whigl8i'},
|
|
213
223
|
{modelID: 'TS0501B', manufacturerName: '_TZ3210_4whigl8i'},
|
|
214
224
|
{modelID: 'TS0501B', manufacturerName: '_TZ3210_9q49basr'},
|
|
225
|
+
{modelID: 'TS0501B', manufacturerName: '_TZ3210_i680rtja'},
|
|
215
226
|
{modelID: 'TS0501B', manufacturerName: '_TZ3210_grnwgegn'},
|
|
216
227
|
{modelID: 'TS0501B', manufacturerName: '_TZ3210_wuheofsg'},
|
|
217
228
|
{modelID: 'TS0501B', manufacturerName: '_TZ3210_e5t9bfdv'}],
|
|
@@ -230,9 +241,7 @@ module.exports = [
|
|
|
230
241
|
{modelID: 'TS0202', manufacturerName: '_TZ3000_mmtwjmaq'},
|
|
231
242
|
{modelID: 'TS0202', manufacturerName: '_TZ3000_kmh5qpmb'},
|
|
232
243
|
{modelID: 'TS0202', manufacturerName: '_TYZB01_zwvaj5wy'},
|
|
233
|
-
{modelID: 'TS0202', manufacturerName: '_TZ3000_mcxw5ehu'},
|
|
234
244
|
{modelID: 'TS0202', manufacturerName: '_TZ3000_bsvqrxru'},
|
|
235
|
-
{modelID: 'TS0202', manufacturerName: '_TZ3000_msl6wxk9'},
|
|
236
245
|
{modelID: 'TS0202', manufacturerName: '_TYZB01_tv3wxhcz'},
|
|
237
246
|
{modelID: 'TS0202', manufacturerName: '_TYZB01_hqbdru35'},
|
|
238
247
|
{modelID: 'TS0202', manufacturerName: '_TZ3000_tiwq83wk'},
|
|
@@ -245,6 +254,19 @@ module.exports = [
|
|
|
245
254
|
toZigbee: [],
|
|
246
255
|
exposes: [e.occupancy(), e.battery_low(), e.tamper(), e.battery()],
|
|
247
256
|
},
|
|
257
|
+
{
|
|
258
|
+
fingerprint: [{modelID: 'TS0202', manufacturerName: '_TZ3000_mcxw5ehu'},
|
|
259
|
+
{modelID: 'TS0202', manufacturerName: '_TZ3000_msl6wxk9'}],
|
|
260
|
+
model: 'ZM-35H-Q',
|
|
261
|
+
vendor: 'TuYa',
|
|
262
|
+
description: 'Motion Sensor',
|
|
263
|
+
fromZigbee: [fz.ias_occupancy_alarm_1, fz.battery, fz.ignore_basic_report, fz.ZM35HQ_attr],
|
|
264
|
+
toZigbee: [tz.ZM35HQ_attr],
|
|
265
|
+
exposes: [e.occupancy(), e.battery_low(), e.tamper(), e.battery(),
|
|
266
|
+
exposes.enum('sensitivity', ea.ALL, ['low', 'medium', 'high']).withDescription('PIR sensor sensitivity'),
|
|
267
|
+
exposes.enum('keep_time', ea.ALL, ['30', '60', '120']).withDescription('PIR keep time in seconds'),
|
|
268
|
+
],
|
|
269
|
+
},
|
|
248
270
|
{
|
|
249
271
|
fingerprint: [{modelID: 'TS0207', manufacturerName: '_TZ3000_m0vaazab'},
|
|
250
272
|
{modelID: 'TS0207', manufacturerName: '_TZ3000_ufttklsz'},
|
|
@@ -326,8 +348,7 @@ module.exports = [
|
|
|
326
348
|
],
|
|
327
349
|
},
|
|
328
350
|
{
|
|
329
|
-
fingerprint: [{modelID: 'TS011F', manufacturerName: '_TZ3000_oiymh3qu'},
|
|
330
|
-
{modelID: 'TS011F', manufacturerName: '_TZ3000_o1jzcxou'}],
|
|
351
|
+
fingerprint: [{modelID: 'TS011F', manufacturerName: '_TZ3000_oiymh3qu'}],
|
|
331
352
|
model: 'TS011F_socket_module',
|
|
332
353
|
vendor: 'TuYa',
|
|
333
354
|
description: 'Socket module',
|
|
@@ -336,12 +357,15 @@ module.exports = [
|
|
|
336
357
|
},
|
|
337
358
|
{
|
|
338
359
|
fingerprint: [{modelID: 'TS011F', manufacturerName: '_TZ3000_wxtp7c5y'},
|
|
339
|
-
{modelID: 'TS011F', manufacturerName: '_TYZB01_mtunwanm'}
|
|
360
|
+
{modelID: 'TS011F', manufacturerName: '_TYZB01_mtunwanm'},
|
|
361
|
+
{modelID: 'TS011F', manufacturerName: '_TZ3000_o1jzcxou'}],
|
|
340
362
|
model: 'TS011F_wall_outlet',
|
|
341
363
|
vendor: 'TuYa',
|
|
342
364
|
description: 'In-wall outlet',
|
|
343
365
|
extend: extend.switch(),
|
|
344
|
-
whiteLabel: [{vendor: 'Teekar', model: 'SWP86-01OG'},
|
|
366
|
+
whiteLabel: [{vendor: 'Teekar', model: 'SWP86-01OG'},
|
|
367
|
+
{vendor: 'ClickSmart+', model: 'CMA30035'},
|
|
368
|
+
{vendor: 'BSEED', model: 'Zigbee Socket'}],
|
|
345
369
|
},
|
|
346
370
|
{
|
|
347
371
|
fingerprint: [{modelID: 'isltm67\u0000', manufacturerName: '_TYST11_pisltm67'}],
|
|
@@ -1139,6 +1163,7 @@ module.exports = [
|
|
|
1139
1163
|
{
|
|
1140
1164
|
fingerprint: [
|
|
1141
1165
|
{modelID: 'TS011F', manufacturerName: '_TZ3000_hyfvrar3'},
|
|
1166
|
+
{modelID: 'TS011F', manufacturerName: '_TZ3000_v1pdxuqq'},
|
|
1142
1167
|
{modelID: 'TS011F', manufacturerName: '_TZ3000_bfn1w0mm'}],
|
|
1143
1168
|
model: 'TS011F_plug_2',
|
|
1144
1169
|
description: 'Smart plug (without power monitoring)',
|
|
@@ -1590,6 +1615,7 @@ module.exports = [
|
|
|
1590
1615
|
vendor: 'TuYa',
|
|
1591
1616
|
description: 'Multiprise with 4 AC outlets and 2 USB super charging ports (16A)',
|
|
1592
1617
|
extend: extend.switch(),
|
|
1618
|
+
fromZigbee: [fz.on_off_skip_duplicate_transaction],
|
|
1593
1619
|
exposes: [e.switch().withEndpoint('l1'), e.switch().withEndpoint('l2'), e.switch().withEndpoint('l3'),
|
|
1594
1620
|
e.switch().withEndpoint('l4')],
|
|
1595
1621
|
whiteLabel: [{vendor: 'LEELKI', model: 'WP33-EU'}],
|
package/devices/xiaomi.js
CHANGED
|
@@ -312,22 +312,22 @@ module.exports = [
|
|
|
312
312
|
model: 'QBKG31LM',
|
|
313
313
|
vendor: 'Xiaomi',
|
|
314
314
|
description: 'Aqara smart wall switch H1 Pro (with neutral, double rocker)',
|
|
315
|
-
extend: extend.switch(),
|
|
316
|
-
exposes: [e.power_outage_memory(), e.action(['single_left', 'double_left', 'single_right', 'double_right']),
|
|
317
|
-
e.switch().withEndpoint('left'), e.switch().withEndpoint('right'), e.power().withAccess(ea.STATE_GET),
|
|
318
|
-
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
319
|
-
.withDescription('Decoupled mode for left button').withEndpoint('left'),
|
|
320
|
-
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
321
|
-
.withDescription('Decoupled mode for right button').withEndpoint('right')],
|
|
322
|
-
fromZigbee: [fz.on_off, fz.xiaomi_power, fz.aqara_opple, fz.xiaomi_multistate_action],
|
|
323
|
-
toZigbee: [tz.on_off, tz.xiaomi_power, tz.xiaomi_switch_operation_mode_opple, tz.xiaomi_switch_power_outage_memory],
|
|
324
315
|
meta: {multiEndpoint: true},
|
|
325
316
|
endpoint: (device) => {
|
|
326
317
|
return {'left': 1, 'right': 2};
|
|
327
318
|
},
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
319
|
+
fromZigbee: [fz.on_off, fz.xiaomi_power, fz.aqara_opple, fz.xiaomi_multistate_action],
|
|
320
|
+
toZigbee: [tz.on_off, tz.xiaomi_switch_operation_mode_opple, tz.xiaomi_switch_power_outage_memory,
|
|
321
|
+
tz.xiaomi_led_disabled_night, tz.xiaomi_flip_indicator_light],
|
|
322
|
+
exposes: [e.switch().withEndpoint('left'), e.switch().withEndpoint('right'),
|
|
323
|
+
e.power(), e.energy(), e.voltage(), e.temperature(), e.power_outage_memory(), e.led_disabled_night(), e.flip_indicator_light(),
|
|
324
|
+
e.action([
|
|
325
|
+
'single_left', 'single_right', 'single_both',
|
|
326
|
+
'double_left', 'double_right', 'double_both']),
|
|
327
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
328
|
+
.withDescription('Decoupled mode for left button').withEndpoint('left'),
|
|
329
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
330
|
+
.withDescription('Decoupled mode for right button').withEndpoint('right')],
|
|
331
331
|
onEvent: preventReset,
|
|
332
332
|
ota: ota.zigbeeOTA,
|
|
333
333
|
},
|
|
@@ -736,9 +736,6 @@ module.exports = [
|
|
|
736
736
|
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
737
737
|
.withDescription('Decoupled mode for left button'),
|
|
738
738
|
],
|
|
739
|
-
configure: async (device, coordinatorEndpoint, logger) => {
|
|
740
|
-
await device.getEndpoint(1).write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
|
|
741
|
-
},
|
|
742
739
|
onEvent: preventReset,
|
|
743
740
|
ota: ota.zigbeeOTA,
|
|
744
741
|
},
|
|
@@ -767,9 +764,6 @@ module.exports = [
|
|
|
767
764
|
.withDescription('Decoupled mode for right button')
|
|
768
765
|
.withEndpoint('right'),
|
|
769
766
|
],
|
|
770
|
-
configure: async (device, coordinatorEndpoint, logger) => {
|
|
771
|
-
await device.getEndpoint(1).write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
|
|
772
|
-
},
|
|
773
767
|
onEvent: preventReset,
|
|
774
768
|
ota: ota.zigbeeOTA,
|
|
775
769
|
},
|
|
@@ -804,10 +798,8 @@ module.exports = [
|
|
|
804
798
|
.withDescription('Decoupled mode for right button')
|
|
805
799
|
.withEndpoint('right'),
|
|
806
800
|
],
|
|
807
|
-
configure: async (device, coordinatorEndpoint, logger) => {
|
|
808
|
-
await device.getEndpoint(1).write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
|
|
809
|
-
},
|
|
810
801
|
onEvent: preventReset,
|
|
802
|
+
ota: ota.zigbeeOTA,
|
|
811
803
|
},
|
|
812
804
|
{
|
|
813
805
|
zigbeeModel: ['lumi.sens', 'lumi.sensor_ht'],
|
|
@@ -997,7 +989,7 @@ module.exports = [
|
|
|
997
989
|
e.voltage().withAccess(ea.STATE), e.current(), e.consumer_connected(), e.led_disabled_night(),
|
|
998
990
|
e.power_outage_memory(), exposes.binary('auto_off', ea.STATE_SET, true, false)
|
|
999
991
|
.withDescription('Turn the device automatically off when attached device consumes less than 2W for 20 minutes'),
|
|
1000
|
-
exposes.numeric('overload_protection', exposes.access.ALL).withValueMin(100).withValueMax(
|
|
992
|
+
exposes.numeric('overload_protection', exposes.access.ALL).withValueMin(100).withValueMax(2300).withUnit('W')
|
|
1001
993
|
.withDescription('Maximum allowed load, turns off if exceeded')],
|
|
1002
994
|
ota: ota.zigbeeOTA,
|
|
1003
995
|
},
|
|
@@ -1691,7 +1683,7 @@ module.exports = [
|
|
|
1691
1683
|
zigbeeModel: ['lumi.plug.macn01'],
|
|
1692
1684
|
model: 'ZNCZ15LM',
|
|
1693
1685
|
vendor: 'Xiaomi',
|
|
1694
|
-
description: 'Aqara T1
|
|
1686
|
+
description: 'Aqara smart plug T1 (china standard)',
|
|
1695
1687
|
fromZigbee: [fz.on_off, fz.xiaomi_power, fz.aqara_opple],
|
|
1696
1688
|
toZigbee: [tz.on_off, tz.xiaomi_switch_power_outage_memory, tz.xiaomi_led_disabled_night,
|
|
1697
1689
|
tz.xiaomi_overload_protection, tz.xiaomi_socket_button_lock],
|
|
@@ -1700,9 +1692,6 @@ module.exports = [
|
|
|
1700
1692
|
e.power_outage_memory(), e.led_disabled_night(), e.button_lock(),
|
|
1701
1693
|
exposes.numeric('overload_protection', exposes.access.ALL).withValueMin(100).withValueMax(2500).withUnit('W')
|
|
1702
1694
|
.withDescription('Maximum allowed load, turns off if exceeded')],
|
|
1703
|
-
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1704
|
-
await device.getEndpoint(1).write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
|
|
1705
|
-
},
|
|
1706
1695
|
ota: ota.zigbeeOTA,
|
|
1707
1696
|
},
|
|
1708
1697
|
{
|
|
@@ -1755,7 +1744,7 @@ module.exports = [
|
|
|
1755
1744
|
zigbeeModel: ['lumi.plug.sacn03'],
|
|
1756
1745
|
model: 'QBCZ15LM',
|
|
1757
1746
|
vendor: 'Xiaomi',
|
|
1758
|
-
description: 'Aqara smart wall outlet H1
|
|
1747
|
+
description: 'Aqara smart wall outlet H1 (USB)',
|
|
1759
1748
|
fromZigbee: [fz.on_off, fz.xiaomi_power, fz.aqara_opple],
|
|
1760
1749
|
toZigbee: [tz.on_off, tz.xiaomi_switch_power_outage_memory, tz.xiaomi_led_disabled_night,
|
|
1761
1750
|
tz.xiaomi_button_switch_mode, tz.xiaomi_overload_protection, tz.xiaomi_socket_button_lock],
|
|
@@ -1771,9 +1760,6 @@ module.exports = [
|
|
|
1771
1760
|
.withDescription('Control both relay and usb or only the relay with the physical switch button'),
|
|
1772
1761
|
exposes.numeric('overload_protection', exposes.access.ALL).withValueMin(100).withValueMax(2500).withUnit('W')
|
|
1773
1762
|
.withDescription('Maximum allowed load, turns off if exceeded')],
|
|
1774
|
-
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1775
|
-
await device.getEndpoint(1).write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
|
|
1776
|
-
},
|
|
1777
1763
|
ota: ota.zigbeeOTA,
|
|
1778
1764
|
},
|
|
1779
1765
|
{
|
|
@@ -1805,9 +1791,6 @@ module.exports = [
|
|
|
1805
1791
|
e.current(), e.power_outage_memory(), e.led_disabled_night(), e.button_lock(),
|
|
1806
1792
|
exposes.numeric('overload_protection', exposes.access.ALL).withValueMin(100).withValueMax(2500).withUnit('W')
|
|
1807
1793
|
.withDescription('Maximum allowed load, turns off if exceeded')],
|
|
1808
|
-
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1809
|
-
await device.getEndpoint(1).write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
|
|
1810
|
-
},
|
|
1811
1794
|
ota: ota.zigbeeOTA,
|
|
1812
1795
|
},
|
|
1813
1796
|
{
|
|
@@ -1873,7 +1856,7 @@ module.exports = [
|
|
|
1873
1856
|
model: 'WXKG14LM',
|
|
1874
1857
|
vendor: 'Xiaomi',
|
|
1875
1858
|
description: 'Aqara wireless remote switch H1 (single rocker)',
|
|
1876
|
-
fromZigbee: [fz.xiaomi_multistate_action, fz.aqara_opple],
|
|
1859
|
+
fromZigbee: [fz.xiaomi_multistate_action, fz.aqara_opple, fz.command_toggle],
|
|
1877
1860
|
toZigbee: [tz.xiaomi_switch_click_mode, tz.aqara_opple_operation_mode],
|
|
1878
1861
|
exposes: [e.battery(), e.battery_voltage(), e.action(['single', 'double', 'triple', 'hold']),
|
|
1879
1862
|
exposes.enum('click_mode', ea.ALL, ['fast', 'multi'])
|
package/lib/exposes.js
CHANGED
|
@@ -537,6 +537,7 @@ module.exports = {
|
|
|
537
537
|
effect: () => new Enum('effect', access.SET, ['blink', 'breathe', 'okay', 'channel_change', 'finish_effect', 'stop_effect']).withDescription('Triggers an effect on the light (e.g. make light blink for a few seconds)'),
|
|
538
538
|
energy: () => new Numeric('energy', access.STATE).withUnit('kWh').withDescription('Sum of consumed energy'),
|
|
539
539
|
fan: () => new Fan(),
|
|
540
|
+
flip_indicator_light: () => new Binary('flip_indicator_light', access.ALL, 'ON', 'OFF').withDescription('After turn on, the indicator light turns on while switch is off, and vice versa'),
|
|
540
541
|
force: () => new Enum('force', access.STATE_SET, ['normal', 'open', 'close']).withDescription('Force the valve position'),
|
|
541
542
|
formaldehyd: () => new Numeric('formaldehyd', access.STATE).withDescription('The measured formaldehyd value'),
|
|
542
543
|
gas: () => new Binary('gas', access.STATE, true, false).withDescription('Indicates whether the device detected gas'),
|
package/lib/tuya.js
CHANGED
|
@@ -418,6 +418,9 @@ const dataPoints = {
|
|
|
418
418
|
tuyaSabHumidity: 19,
|
|
419
419
|
tuyaSabVOC: 21,
|
|
420
420
|
tuyaSabFormaldehyd: 22,
|
|
421
|
+
// tuya Smart Air House Keeper, Multifunctionale air quality detector.
|
|
422
|
+
// CO2, Temp, Humidity, VOC and Formaldehyd same as Smart Air Box
|
|
423
|
+
tuyaSahkMP25: 20,
|
|
421
424
|
lidlTimer: 5,
|
|
422
425
|
// Moes MS-105 Dimmer
|
|
423
426
|
moes105DimmerState1: 1,
|
package/npm-shrinkwrap.json
CHANGED