zigbee-herdsman-converters 14.0.402 → 14.0.406
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 +145 -60
- package/converters/toZigbee.js +121 -26
- package/devices/acova.js +60 -29
- package/devices/casaia.js +8 -0
- package/devices/gledopto.js +8 -0
- package/devices/jasco.js +17 -0
- package/devices/kwikset.js +1 -1
- package/devices/legrand.js +22 -2
- package/devices/moes.js +1 -1
- package/devices/namron.js +13 -0
- package/devices/orvibo.js +20 -0
- package/devices/philips.js +18 -0
- package/devices/sinope.js +19 -5
- package/devices/tplink.js +26 -0
- package/devices/tuya.js +40 -21
- package/devices/woox.js +19 -0
- package/devices/xiaomi.js +102 -59
- package/index.js +2 -1
- package/lib/exposes.js +1 -0
- package/npm-shrinkwrap.json +186 -221
- package/package.json +2 -2
package/converters/fromZigbee.js
CHANGED
|
@@ -1046,7 +1046,7 @@ const converters = {
|
|
|
1046
1046
|
cluster: 'genScenes',
|
|
1047
1047
|
type: 'commandRecall',
|
|
1048
1048
|
convert: (model, msg, publish, options, meta) => {
|
|
1049
|
-
if (
|
|
1049
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1050
1050
|
const payload = {action: postfixWithEndpointName(`recall_${msg.data.sceneid}`, msg, model)};
|
|
1051
1051
|
addActionGroup(payload, msg, model);
|
|
1052
1052
|
return payload;
|
|
@@ -1056,7 +1056,7 @@ const converters = {
|
|
|
1056
1056
|
cluster: 'ssIasAce',
|
|
1057
1057
|
type: 'commandPanic',
|
|
1058
1058
|
convert: (model, msg, publish, options, meta) => {
|
|
1059
|
-
if (
|
|
1059
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1060
1060
|
const payload = {action: postfixWithEndpointName(`panic`, msg, model)};
|
|
1061
1061
|
addActionGroup(payload, msg, model);
|
|
1062
1062
|
return payload;
|
|
@@ -1066,7 +1066,7 @@ const converters = {
|
|
|
1066
1066
|
cluster: 'ssIasAce',
|
|
1067
1067
|
type: 'commandArm',
|
|
1068
1068
|
convert: (model, msg, publish, options, meta) => {
|
|
1069
|
-
if (
|
|
1069
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1070
1070
|
const payload = {
|
|
1071
1071
|
action: postfixWithEndpointName(constants.armMode[msg.data['armmode']], msg, model),
|
|
1072
1072
|
action_code: msg.data.code,
|
|
@@ -1090,7 +1090,7 @@ const converters = {
|
|
|
1090
1090
|
cluster: 'closuresWindowCovering',
|
|
1091
1091
|
type: 'commandStop',
|
|
1092
1092
|
convert: (model, msg, publish, options, meta) => {
|
|
1093
|
-
if (
|
|
1093
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1094
1094
|
const payload = {action: postfixWithEndpointName('stop', msg, model)};
|
|
1095
1095
|
addActionGroup(payload, msg, model);
|
|
1096
1096
|
return payload;
|
|
@@ -1100,7 +1100,7 @@ const converters = {
|
|
|
1100
1100
|
cluster: 'closuresWindowCovering',
|
|
1101
1101
|
type: 'commandUpOpen',
|
|
1102
1102
|
convert: (model, msg, publish, options, meta) => {
|
|
1103
|
-
if (
|
|
1103
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1104
1104
|
const payload = {action: postfixWithEndpointName('open', msg, model)};
|
|
1105
1105
|
addActionGroup(payload, msg, model);
|
|
1106
1106
|
return payload;
|
|
@@ -1110,7 +1110,7 @@ const converters = {
|
|
|
1110
1110
|
cluster: 'closuresWindowCovering',
|
|
1111
1111
|
type: 'commandDownClose',
|
|
1112
1112
|
convert: (model, msg, publish, options, meta) => {
|
|
1113
|
-
if (
|
|
1113
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1114
1114
|
const payload = {action: postfixWithEndpointName('close', msg, model)};
|
|
1115
1115
|
addActionGroup(payload, msg, model);
|
|
1116
1116
|
return payload;
|
|
@@ -1120,7 +1120,7 @@ const converters = {
|
|
|
1120
1120
|
cluster: 'genOnOff',
|
|
1121
1121
|
type: 'commandOn',
|
|
1122
1122
|
convert: (model, msg, publish, options, meta) => {
|
|
1123
|
-
if (
|
|
1123
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1124
1124
|
const payload = {action: postfixWithEndpointName('on', msg, model)};
|
|
1125
1125
|
addActionGroup(payload, msg, model);
|
|
1126
1126
|
return payload;
|
|
@@ -1130,7 +1130,7 @@ const converters = {
|
|
|
1130
1130
|
cluster: 'genOnOff',
|
|
1131
1131
|
type: 'commandOff',
|
|
1132
1132
|
convert: (model, msg, publish, options, meta) => {
|
|
1133
|
-
if (
|
|
1133
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1134
1134
|
const payload = {action: postfixWithEndpointName('off', msg, model)};
|
|
1135
1135
|
addActionGroup(payload, msg, model);
|
|
1136
1136
|
return payload;
|
|
@@ -1140,7 +1140,7 @@ const converters = {
|
|
|
1140
1140
|
cluster: 'genOnOff',
|
|
1141
1141
|
type: 'commandOffWithEffect',
|
|
1142
1142
|
convert: (model, msg, publish, options, meta) => {
|
|
1143
|
-
if (
|
|
1143
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1144
1144
|
const payload = {action: postfixWithEndpointName(`off`, msg, model)};
|
|
1145
1145
|
addActionGroup(payload, msg, model);
|
|
1146
1146
|
return payload;
|
|
@@ -1150,7 +1150,7 @@ const converters = {
|
|
|
1150
1150
|
cluster: 'genOnOff',
|
|
1151
1151
|
type: 'commandToggle',
|
|
1152
1152
|
convert: (model, msg, publish, options, meta) => {
|
|
1153
|
-
if (
|
|
1153
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1154
1154
|
const payload = {action: postfixWithEndpointName('toggle', msg, model)};
|
|
1155
1155
|
addActionGroup(payload, msg, model);
|
|
1156
1156
|
return payload;
|
|
@@ -1161,7 +1161,7 @@ const converters = {
|
|
|
1161
1161
|
type: ['commandMoveToLevel', 'commandMoveToLevelWithOnOff'],
|
|
1162
1162
|
options: [exposes.options.simulated_brightness()],
|
|
1163
1163
|
convert: (model, msg, publish, options, meta) => {
|
|
1164
|
-
if (
|
|
1164
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1165
1165
|
const payload = {
|
|
1166
1166
|
action: postfixWithEndpointName(`brightness_move_to_level`, msg, model),
|
|
1167
1167
|
action_level: msg.data.level,
|
|
@@ -1183,7 +1183,7 @@ const converters = {
|
|
|
1183
1183
|
type: ['commandMove', 'commandMoveWithOnOff'],
|
|
1184
1184
|
options: [exposes.options.simulated_brightness()],
|
|
1185
1185
|
convert: (model, msg, publish, options, meta) => {
|
|
1186
|
-
if (
|
|
1186
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1187
1187
|
const direction = msg.data.movemode === 1 ? 'down' : 'up';
|
|
1188
1188
|
const action = postfixWithEndpointName(`brightness_move_${direction}`, msg, model);
|
|
1189
1189
|
const payload = {action, action_rate: msg.data.rate};
|
|
@@ -1219,7 +1219,7 @@ const converters = {
|
|
|
1219
1219
|
type: ['commandStep', 'commandStepWithOnOff'],
|
|
1220
1220
|
options: [exposes.options.simulated_brightness()],
|
|
1221
1221
|
convert: (model, msg, publish, options, meta) => {
|
|
1222
|
-
if (
|
|
1222
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1223
1223
|
const direction = msg.data.stepmode === 1 ? 'down' : 'up';
|
|
1224
1224
|
const payload = {
|
|
1225
1225
|
action: postfixWithEndpointName(`brightness_step_${direction}`, msg, model),
|
|
@@ -1246,7 +1246,7 @@ const converters = {
|
|
|
1246
1246
|
type: ['commandStop', 'commandStopWithOnOff'],
|
|
1247
1247
|
options: [exposes.options.simulated_brightness()],
|
|
1248
1248
|
convert: (model, msg, publish, options, meta) => {
|
|
1249
|
-
if (
|
|
1249
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1250
1250
|
if (options.simulated_brightness) {
|
|
1251
1251
|
clearInterval(globalStore.getValue(msg.endpoint, 'simulated_brightness_timer'));
|
|
1252
1252
|
globalStore.putValue(msg.endpoint, 'simulated_brightness_timer', undefined);
|
|
@@ -1261,7 +1261,7 @@ const converters = {
|
|
|
1261
1261
|
cluster: 'lightingColorCtrl',
|
|
1262
1262
|
type: ['commandMoveColorTemp'],
|
|
1263
1263
|
convert: (model, msg, publish, options, meta) => {
|
|
1264
|
-
if (
|
|
1264
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1265
1265
|
const direction = msg.data.movemode === 1 ? 'down' : 'up';
|
|
1266
1266
|
const action = postfixWithEndpointName(`color_temperature_move_${direction}`, msg, model);
|
|
1267
1267
|
const payload = {action, action_rate: msg.data.rate, action_minimum: msg.data.minimum, action_maximum: msg.data.maximum};
|
|
@@ -1273,7 +1273,7 @@ const converters = {
|
|
|
1273
1273
|
cluster: 'lightingColorCtrl',
|
|
1274
1274
|
type: 'commandStepColorTemp',
|
|
1275
1275
|
convert: (model, msg, publish, options, meta) => {
|
|
1276
|
-
if (
|
|
1276
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1277
1277
|
const direction = msg.data.stepmode === 1 ? 'up' : 'down';
|
|
1278
1278
|
const payload = {
|
|
1279
1279
|
action: postfixWithEndpointName(`color_temperature_step_${direction}`, msg, model),
|
|
@@ -1292,7 +1292,7 @@ const converters = {
|
|
|
1292
1292
|
cluster: 'lightingColorCtrl',
|
|
1293
1293
|
type: 'commandEnhancedMoveToHueAndSaturation',
|
|
1294
1294
|
convert: (model, msg, publish, options, meta) => {
|
|
1295
|
-
if (
|
|
1295
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1296
1296
|
const payload = {
|
|
1297
1297
|
action: postfixWithEndpointName(`enhanced_move_to_hue_and_saturation`, msg, model),
|
|
1298
1298
|
action_enhanced_hue: msg.data.enhancehue,
|
|
@@ -1309,7 +1309,7 @@ const converters = {
|
|
|
1309
1309
|
cluster: 'lightingColorCtrl',
|
|
1310
1310
|
type: ['commandStepHue'],
|
|
1311
1311
|
convert: (model, msg, publish, options, meta) => {
|
|
1312
|
-
if (
|
|
1312
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1313
1313
|
const direction = msg.data.stepmode === 1 ? 'up' : 'down';
|
|
1314
1314
|
const payload = {
|
|
1315
1315
|
action: postfixWithEndpointName(`color_hue_step_${direction}`, msg, model),
|
|
@@ -1324,7 +1324,7 @@ const converters = {
|
|
|
1324
1324
|
cluster: 'lightingColorCtrl',
|
|
1325
1325
|
type: ['commandStepSaturation'],
|
|
1326
1326
|
convert: (model, msg, publish, options, meta) => {
|
|
1327
|
-
if (
|
|
1327
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1328
1328
|
const direction = msg.data.stepmode === 1 ? 'up' : 'down';
|
|
1329
1329
|
const payload = {
|
|
1330
1330
|
action: postfixWithEndpointName(`color_saturation_step_${direction}`, msg, model),
|
|
@@ -1339,7 +1339,7 @@ const converters = {
|
|
|
1339
1339
|
cluster: 'lightingColorCtrl',
|
|
1340
1340
|
type: 'commandColorLoopSet',
|
|
1341
1341
|
convert: (model, msg, publish, options, meta) => {
|
|
1342
|
-
if (
|
|
1342
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1343
1343
|
const updateFlags = msg.data.updateflags;
|
|
1344
1344
|
const actionLookup = {
|
|
1345
1345
|
0x00: 'deactivate',
|
|
@@ -1369,7 +1369,7 @@ const converters = {
|
|
|
1369
1369
|
cluster: 'lightingColorCtrl',
|
|
1370
1370
|
type: 'commandMoveToColorTemp',
|
|
1371
1371
|
convert: (model, msg, publish, options, meta) => {
|
|
1372
|
-
if (
|
|
1372
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1373
1373
|
const payload = {
|
|
1374
1374
|
action: postfixWithEndpointName(`color_temperature_move`, msg, model),
|
|
1375
1375
|
action_color_temperature: msg.data.colortemp,
|
|
@@ -1383,7 +1383,7 @@ const converters = {
|
|
|
1383
1383
|
cluster: 'lightingColorCtrl',
|
|
1384
1384
|
type: 'commandMoveToColor',
|
|
1385
1385
|
convert: (model, msg, publish, options, meta) => {
|
|
1386
|
-
if (
|
|
1386
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1387
1387
|
const payload = {
|
|
1388
1388
|
action: postfixWithEndpointName(`color_move`, msg, model),
|
|
1389
1389
|
action_color: {
|
|
@@ -1400,7 +1400,7 @@ const converters = {
|
|
|
1400
1400
|
cluster: 'lightingColorCtrl',
|
|
1401
1401
|
type: 'commandMoveHue',
|
|
1402
1402
|
convert: (model, msg, publish, options, meta) => {
|
|
1403
|
-
if (
|
|
1403
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1404
1404
|
const movestop = msg.data.movemode == 1 ? 'move' : 'stop';
|
|
1405
1405
|
const action = postfixWithEndpointName(`hue_${movestop}`, msg, model);
|
|
1406
1406
|
const payload = {action, action_rate: msg.data.rate};
|
|
@@ -1412,7 +1412,7 @@ const converters = {
|
|
|
1412
1412
|
cluster: 'lightingColorCtrl',
|
|
1413
1413
|
type: 'commandMoveToSaturation',
|
|
1414
1414
|
convert: (model, msg, publish, options, meta) => {
|
|
1415
|
-
if (
|
|
1415
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1416
1416
|
const payload = {
|
|
1417
1417
|
action: postfixWithEndpointName('move_to_saturation', msg, model),
|
|
1418
1418
|
action_saturation: msg.data.saturation,
|
|
@@ -1426,7 +1426,7 @@ const converters = {
|
|
|
1426
1426
|
cluster: 'lightingColorCtrl',
|
|
1427
1427
|
type: 'commandMoveToHue',
|
|
1428
1428
|
convert: (model, msg, publish, options, meta) => {
|
|
1429
|
-
if (
|
|
1429
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1430
1430
|
const payload = {
|
|
1431
1431
|
action: postfixWithEndpointName(`move_to_hue`, msg, model),
|
|
1432
1432
|
action_hue: msg.data.hue,
|
|
@@ -1441,7 +1441,7 @@ const converters = {
|
|
|
1441
1441
|
cluster: 'ssIasAce',
|
|
1442
1442
|
type: 'commandEmergency',
|
|
1443
1443
|
convert: (model, msg, publish, options, meta) => {
|
|
1444
|
-
if (
|
|
1444
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1445
1445
|
const payload = {action: postfixWithEndpointName(`emergency`, msg, model)};
|
|
1446
1446
|
addActionGroup(payload, msg, model);
|
|
1447
1447
|
return payload;
|
|
@@ -1451,7 +1451,7 @@ const converters = {
|
|
|
1451
1451
|
cluster: 'genOnOff',
|
|
1452
1452
|
type: 'commandOn',
|
|
1453
1453
|
convert: (model, msg, publish, options, meta) => {
|
|
1454
|
-
if (
|
|
1454
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1455
1455
|
const property = postfixWithEndpointName('state', msg, model);
|
|
1456
1456
|
return {[property]: 'ON'};
|
|
1457
1457
|
},
|
|
@@ -1460,7 +1460,7 @@ const converters = {
|
|
|
1460
1460
|
cluster: 'genOnOff',
|
|
1461
1461
|
type: 'commandOff',
|
|
1462
1462
|
convert: (model, msg, publish, options, meta) => {
|
|
1463
|
-
if (
|
|
1463
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1464
1464
|
const property = postfixWithEndpointName('state', msg, model);
|
|
1465
1465
|
return {[property]: 'OFF'};
|
|
1466
1466
|
},
|
|
@@ -2185,7 +2185,7 @@ const converters = {
|
|
|
2185
2185
|
cluster: 'ssIasZone',
|
|
2186
2186
|
type: 'commandStatusChangeNotification',
|
|
2187
2187
|
convert: (model, msg, publish, options, meta) => {
|
|
2188
|
-
if (
|
|
2188
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
2189
2189
|
const lookup = {1: 'pressed'};
|
|
2190
2190
|
const zoneStatus = msg.data.zonestatus;
|
|
2191
2191
|
return {
|
|
@@ -3815,19 +3815,21 @@ const converters = {
|
|
|
3815
3815
|
return {open_window_temperature: (value / 10).toFixed(1)};
|
|
3816
3816
|
case tuya.dataPoints.tvErrorStatus:
|
|
3817
3817
|
return {fault_alarm: value};
|
|
3818
|
-
case tuya.dataPoints.tvHolidayMode:
|
|
3819
|
-
|
|
3820
|
-
|
|
3818
|
+
case tuya.dataPoints.tvHolidayMode: {
|
|
3819
|
+
const sy = value.slice(0, 4); const sm = value.slice(4, 6); const sd = value.slice(6, 8);
|
|
3820
|
+
const sh = value.slice(8, 10); const smi = value.slice(10, 12); const ey = value.slice(12, 16);
|
|
3821
|
+
const em = value.slice(16, 18); const ed = value.slice(18, 20); const eh = value.slice(20, 22);
|
|
3822
|
+
const emi = value.slice(22, 24);
|
|
3823
|
+
const hMode = 'start --> ' + sy + ' - ' + sm + ' - ' + sd + ' ' + sh + ' : ' + smi +
|
|
3824
|
+
' stop --> ' + ey + ' - ' + em + ' - ' + ed + ' ' + eh + ' : ' + emi;
|
|
3825
|
+
return {holiday_start_stop: hMode};
|
|
3826
|
+
}
|
|
3821
3827
|
case tuya.dataPoints.tvBoostMode:
|
|
3822
|
-
//
|
|
3828
|
+
// 115 online / Is the device online
|
|
3823
3829
|
return {online: value ? 'ON' : 'OFF'};
|
|
3824
3830
|
case tuya.dataPoints.tvWorkingDay:
|
|
3825
|
-
//
|
|
3831
|
+
// DP-31, Send and Report, ENUM, Week select 0 - 5 days, 1 - 6 days, 2 - 7 days
|
|
3826
3832
|
return {working_day: value};
|
|
3827
|
-
case tuya.dataPoints.tvWeekSchedule:
|
|
3828
|
-
// tvWeekSchedule: 106, Week select 0 - 5 days, 1 - 6 days, 2 - 7 days
|
|
3829
|
-
return {week_schedule: value};
|
|
3830
|
-
|
|
3831
3833
|
case tuya.dataPoints.tvMondaySchedule:
|
|
3832
3834
|
return {schedule_monday:
|
|
3833
3835
|
' ' + value[0] / 6 + 'h:' + value[1] + 'm ' + value[2] / 10 + '°C' +
|
|
@@ -4522,7 +4524,7 @@ const converters = {
|
|
|
4522
4524
|
cluster: 'genScenes',
|
|
4523
4525
|
type: 'commandTradfriArrowSingle',
|
|
4524
4526
|
convert: (model, msg, publish, options, meta) => {
|
|
4525
|
-
if (
|
|
4527
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
4526
4528
|
if (msg.data.value === 2) {
|
|
4527
4529
|
// This is send on toggle hold, ignore it as a toggle_hold is already handled above.
|
|
4528
4530
|
return;
|
|
@@ -4536,7 +4538,7 @@ const converters = {
|
|
|
4536
4538
|
cluster: 'genScenes',
|
|
4537
4539
|
type: 'commandTradfriArrowHold',
|
|
4538
4540
|
convert: (model, msg, publish, options, meta) => {
|
|
4539
|
-
if (
|
|
4541
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
4540
4542
|
const direction = msg.data.value === 3329 ? 'left' : 'right';
|
|
4541
4543
|
globalStore.putValue(msg.endpoint, 'direction', direction);
|
|
4542
4544
|
return {action: `arrow_${direction}_hold`};
|
|
@@ -4547,7 +4549,7 @@ const converters = {
|
|
|
4547
4549
|
type: 'commandTradfriArrowRelease',
|
|
4548
4550
|
options: [exposes.options.legacy()],
|
|
4549
4551
|
convert: (model, msg, publish, options, meta) => {
|
|
4550
|
-
if (
|
|
4552
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
4551
4553
|
const direction = globalStore.getValue(msg.endpoint, 'direction');
|
|
4552
4554
|
if (direction) {
|
|
4553
4555
|
globalStore.clearValue(msg.endpoint, 'direction');
|
|
@@ -5027,6 +5029,9 @@ const converters = {
|
|
|
5027
5029
|
// dimmer
|
|
5028
5030
|
else if (option0 === 0x0101) payload.device_mode = 'dimmer_on';
|
|
5029
5031
|
else if (option0 === 0x0100) payload.device_mode = 'dimmer_off';
|
|
5032
|
+
// pilot wire
|
|
5033
|
+
else if (option0 === 0x0002) payload.device_mode = 'pilot_on';
|
|
5034
|
+
else if (option0 === 0x0001) payload.device_mode = 'pilot_off';
|
|
5030
5035
|
// unknown case
|
|
5031
5036
|
else {
|
|
5032
5037
|
meta.logger.warn(`device_mode ${option0} not recognized, please fix me`);
|
|
@@ -5035,6 +5040,26 @@ const converters = {
|
|
|
5035
5040
|
return payload;
|
|
5036
5041
|
},
|
|
5037
5042
|
},
|
|
5043
|
+
legrand_cable_outlet_mode: {
|
|
5044
|
+
cluster: '64576',
|
|
5045
|
+
type: ['readResponse'],
|
|
5046
|
+
convert: (model, msg, publish, options, meta) => {
|
|
5047
|
+
const payload = {};
|
|
5048
|
+
const mode = msg.data['0'];
|
|
5049
|
+
|
|
5050
|
+
if (mode === 0x00) payload.cable_outlet_mode = 'comfort';
|
|
5051
|
+
else if (mode === 0x01) payload.cable_outlet_mode = 'comfort-1';
|
|
5052
|
+
else if (mode === 0x02) payload.cable_outlet_mode = 'comfort-2';
|
|
5053
|
+
else if (mode === 0x03) payload.cable_outlet_mode = 'eco';
|
|
5054
|
+
else if (mode === 0x04) payload.cable_outlet_mode = 'frost_protection';
|
|
5055
|
+
else if (mode === 0x05) payload.cable_outlet_mode = 'off';
|
|
5056
|
+
else {
|
|
5057
|
+
meta.logger.warn(`Bad mode : ${mode}`);
|
|
5058
|
+
payload.cable_outlet_mode = 'unknown';
|
|
5059
|
+
}
|
|
5060
|
+
return payload;
|
|
5061
|
+
},
|
|
5062
|
+
},
|
|
5038
5063
|
legrand_power_alarm: {
|
|
5039
5064
|
cluster: 'haElectricalMeasurement',
|
|
5040
5065
|
type: ['attributeReport', 'readResponse'],
|
|
@@ -5255,31 +5280,45 @@ const converters = {
|
|
|
5255
5280
|
payload.battery = batteryVoltageToPercentage(value, '3V_2100');
|
|
5256
5281
|
} else if (index === 3) payload.temperature = calibrateAndPrecisionRoundOptions(value, options, 'temperature'); // 0x03
|
|
5257
5282
|
else if (index === 5) {
|
|
5258
|
-
if (['JT-BZ-01AQ/A'].includes(model.model)) payload.power_outage_count = value;
|
|
5283
|
+
if (['JT-BZ-01AQ/A', 'RTCZCGQ11LM'].includes(model.model)) payload.power_outage_count = value;
|
|
5259
5284
|
} else if (index === 100) {
|
|
5260
|
-
if (['QBKG20LM', 'QBKG39LM', 'QBKG41LM', 'QBCZ15LM'].includes(model.model)) {
|
|
5285
|
+
if (['QBKG20LM', 'QBKG31LM', 'QBKG39LM', 'QBKG41LM', 'QBCZ15LM'].includes(model.model)) {
|
|
5261
5286
|
const mapping = model.model === 'QBCZ15LM' ? 'relay' : 'left';
|
|
5262
5287
|
payload[`state_${mapping}`] = value === 1 ? 'ON' : 'OFF';
|
|
5263
5288
|
} else if (['WXKG14LM', 'WXKG16LM', 'WXKG17LM'].includes(model.model)) {
|
|
5264
5289
|
payload.click_mode = {1: 'fast', 2: 'multi'}[value];
|
|
5290
|
+
} else if (['WXCJKG11LM ', 'WXCJKG12LM', 'WXCJKG13LM'].includes(model.model)) {
|
|
5291
|
+
// We don't know what the value means for these devices.
|
|
5292
|
+
// https://github.com/Koenkk/zigbee2mqtt/issues/11126
|
|
5265
5293
|
} else {
|
|
5266
5294
|
payload.state = value === 1 ? 'ON' : 'OFF';
|
|
5267
5295
|
}
|
|
5268
5296
|
} else if (index === 101) {
|
|
5269
|
-
if (['
|
|
5297
|
+
if (['QBKG20LM', 'QBKG31LM', 'QBKG39LM', 'QBKG41LM', 'QBCZ15LM'].includes(model.model)) {
|
|
5270
5298
|
const mapping = model.model === 'QBCZ15LM' ? 'usb' : 'right';
|
|
5271
5299
|
payload[`state_${mapping}`] = value === 1 ? 'ON' : 'OFF';
|
|
5272
5300
|
} else if (['QBKG25LM', 'QBKG34LM'].includes(model.model)) {
|
|
5273
5301
|
payload.state_center = value === 1 ? 'ON' : 'OFF';
|
|
5274
5302
|
} else if (['RTCGQ12LM'].includes(model.model)) {
|
|
5275
5303
|
payload.illuminance = calibrateAndPrecisionRoundOptions(value, options, 'illuminance');
|
|
5304
|
+
} else if (['ZNJLBL01LM'].includes(model.model)) {
|
|
5305
|
+
payload.battery = value;
|
|
5276
5306
|
}
|
|
5277
5307
|
} else if (index ===102 ) {
|
|
5278
5308
|
if (['QBKG25LM', 'QBKG34LM'].includes(model.model)) {
|
|
5279
5309
|
payload.state_right = value === 1 ? 'ON' : 'OFF';
|
|
5310
|
+
} else if (['RTCZCGQ11LM'].includes(model.model)) {
|
|
5311
|
+
payload.presence_event = {0: 'enter', 1: 'leave', 2: 'left_enter', 3: 'right_leave', 4: 'right_enter',
|
|
5312
|
+
5: 'left_leave', 6: 'approach', 7: 'away', 255: null}[value];
|
|
5313
|
+
}
|
|
5314
|
+
} else if (index ===103) payload.monitoring_mode = value === 1 ? 'left_right' : 'undirected'; // RTCZCGQ11LM
|
|
5315
|
+
else if (index === 105) {
|
|
5316
|
+
if (['RTCGQ13LM'].includes(model.model)) {
|
|
5317
|
+
payload.motion_sensitivity = {1: 'low', 2: 'medium', 3: 'high'}[value];
|
|
5318
|
+
} else if (['RTCZCGQ11LM'].includes(model.model)) {
|
|
5319
|
+
payload.approach_distance = {0: 'far', 1: 'medium', 2: 'near'}[value];
|
|
5280
5320
|
}
|
|
5281
|
-
} else if (index ===
|
|
5282
|
-
else if (index === 149) {
|
|
5321
|
+
} else if (index === 149) {
|
|
5283
5322
|
payload.energy = precisionRound(value, 2); // 0x95
|
|
5284
5323
|
// Consumption is deprecated
|
|
5285
5324
|
payload.consumption = payload.energy;
|
|
@@ -5303,6 +5342,7 @@ const converters = {
|
|
|
5303
5342
|
}
|
|
5304
5343
|
if (msg.data.hasOwnProperty('4')) payload.mode_switch = {4: 'anti_flicker_mode', 1: 'quick_mode'}[msg.data['4']];
|
|
5305
5344
|
if (msg.data.hasOwnProperty('10')) payload.switch_type = {1: 'toggle', 2: 'momentary'}[msg.data['10']];
|
|
5345
|
+
if (msg.data.hasOwnProperty('240')) payload.flip_indicator_light = msg.data['240'] === 1 ? 'ON' : 'OFF';
|
|
5306
5346
|
if (msg.data.hasOwnProperty('258')) payload.detection_interval = msg.data['258'];
|
|
5307
5347
|
if (msg.data.hasOwnProperty('268')) {
|
|
5308
5348
|
if (['RTCGQ13LM'].includes(model.model)) {
|
|
@@ -5317,6 +5357,15 @@ const converters = {
|
|
|
5317
5357
|
if (msg.data.hasOwnProperty('313')) payload.state = msg.data['313'] === 1 ? 'preparation' : 'work'; // JT-BZ-01AQ/A
|
|
5318
5358
|
if (msg.data.hasOwnProperty('314')) payload.gas = msg.data['314'] === 1; // JT-BZ-01AQ/A
|
|
5319
5359
|
if (msg.data.hasOwnProperty('315')) payload.gas_density = msg.data['315']; // JT-BZ-01AQ/A
|
|
5360
|
+
if (msg.data.hasOwnProperty('322')) payload.presence = msg.data['322'] === 1; // RTCZCGQ11LM
|
|
5361
|
+
if (msg.data.hasOwnProperty('323')) {
|
|
5362
|
+
payload.presence_event = {0: 'enter', 1: 'leave', 2: 'left_enter', 3: 'right_leave', 4: 'right_enter',
|
|
5363
|
+
5: 'left_leave', 6: 'approach', 7: 'away'}[msg.data['323']]; // RTCZCGQ11LM
|
|
5364
|
+
}
|
|
5365
|
+
// RTCZCGQ11LM
|
|
5366
|
+
if (msg.data.hasOwnProperty('324')) payload.monitoring_mode = msg.data['324'] === 1 ? 'left_right' : 'undirected';
|
|
5367
|
+
// RTCZCGQ11LM
|
|
5368
|
+
if (msg.data.hasOwnProperty('326')) payload.approach_distance = {0: 'far', 1: 'medium', 2: 'near'}[msg.data['326']];
|
|
5320
5369
|
if (msg.data.hasOwnProperty('331')) payload.linkage_alarm = msg.data['331'] === 1; // JT-BZ-01AQ/A
|
|
5321
5370
|
if (msg.data.hasOwnProperty('512')) {
|
|
5322
5371
|
if (['ZNCZ15LM', 'QBCZ14LM', 'QBCZ15LM'].includes(model.model)) {
|
|
@@ -5333,6 +5382,7 @@ const converters = {
|
|
|
5333
5382
|
if (msg.data.hasOwnProperty('523')) payload.overload_protection = precisionRound(msg.data['523'], 2);
|
|
5334
5383
|
if (msg.data.hasOwnProperty('550')) payload.button_switch_mode = msg.data['550'] === 1 ? 'relay_and_usb' : 'relay';
|
|
5335
5384
|
if (msg.data['mode'] !== undefined) payload.operation_mode = ['command', 'event'][msg.data['mode']];
|
|
5385
|
+
if (msg.data.hasOwnProperty('1289')) payload.dimmer_mode = {3: 'rgbw', 1: 'dual_ct'}[msg.data['1289']];
|
|
5336
5386
|
return payload;
|
|
5337
5387
|
},
|
|
5338
5388
|
},
|
|
@@ -5395,14 +5445,15 @@ const converters = {
|
|
|
5395
5445
|
cluster: 'genMultistateInput',
|
|
5396
5446
|
type: ['attributeReport'],
|
|
5397
5447
|
convert: (model, msg, publish, options, meta) => {
|
|
5398
|
-
if (
|
|
5448
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
5399
5449
|
let actionLookup = {0: 'hold', 1: 'single', 2: 'double', 3: 'triple', 255: 'release'};
|
|
5400
5450
|
if (model.model === 'WXKG12LM') {
|
|
5401
5451
|
actionLookup = {...actionLookup, 16: 'hold', 17: 'release', 18: 'shake'};
|
|
5402
5452
|
}
|
|
5403
5453
|
|
|
5404
5454
|
let buttonLookup = null;
|
|
5405
|
-
if (['WXKG02LM_rev2', 'WXKG07LM', '
|
|
5455
|
+
if (['WXKG02LM_rev2', 'WXKG07LM', 'WXKG15LM', 'WXKG17LM',
|
|
5456
|
+
'WRS-R02'].includes(model.model)) buttonLookup = {1: 'left', 2: 'right', 3: 'both'};
|
|
5406
5457
|
if (['QBKG12LM', 'QBKG24LM'].includes(model.model)) buttonLookup = {5: 'left', 6: 'right', 7: 'both'};
|
|
5407
5458
|
if (['QBKG39LM', 'QBKG41LM', 'WS-EUK02', 'WS-EUK04', 'QBKG20LM', 'QBKG31LM'].includes(model.model)) {
|
|
5408
5459
|
buttonLookup = {41: 'left', 42: 'right', 51: 'both'};
|
|
@@ -5541,7 +5592,7 @@ const converters = {
|
|
|
5541
5592
|
`increase it with this option (value is in ms).`),
|
|
5542
5593
|
],
|
|
5543
5594
|
convert: (model, msg, publish, options, meta) => {
|
|
5544
|
-
if (
|
|
5595
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
5545
5596
|
const state = msg.data['onOff'];
|
|
5546
5597
|
|
|
5547
5598
|
// 0 = click down, 1 = click up, else = multiple clicks
|
|
@@ -5805,6 +5856,40 @@ const converters = {
|
|
|
5805
5856
|
}
|
|
5806
5857
|
},
|
|
5807
5858
|
},
|
|
5859
|
+
xiaomi_curtain_acn002_position: {
|
|
5860
|
+
cluster: 'genAnalogOutput',
|
|
5861
|
+
type: ['attributeReport', 'readResponse'],
|
|
5862
|
+
options: [exposes.options.invert_cover()],
|
|
5863
|
+
convert: (model, msg, publish, options, meta) => {
|
|
5864
|
+
let position = precisionRound(msg.data['presentValue'], 2);
|
|
5865
|
+
position = options.invert_cover ? 100 - position : position;
|
|
5866
|
+
return {position: position};
|
|
5867
|
+
},
|
|
5868
|
+
},
|
|
5869
|
+
xiaomi_curtain_acn002_status: {
|
|
5870
|
+
cluster: 'genMultistateOutput',
|
|
5871
|
+
type: ['attributeReport', 'readResponse'],
|
|
5872
|
+
convert: (model, msg, publish, options, meta) => {
|
|
5873
|
+
let running = false;
|
|
5874
|
+
const data = msg.data;
|
|
5875
|
+
const lookup = {
|
|
5876
|
+
0: 'declining',
|
|
5877
|
+
1: 'rising',
|
|
5878
|
+
2: 'pause',
|
|
5879
|
+
3: 'blocked',
|
|
5880
|
+
};
|
|
5881
|
+
if (data && data.hasOwnProperty('presentValue')) {
|
|
5882
|
+
const value = data['presentValue'];
|
|
5883
|
+
if (value < 2) {
|
|
5884
|
+
running = true;
|
|
5885
|
+
}
|
|
5886
|
+
return {
|
|
5887
|
+
motor_state: lookup[value],
|
|
5888
|
+
running: running,
|
|
5889
|
+
};
|
|
5890
|
+
}
|
|
5891
|
+
},
|
|
5892
|
+
},
|
|
5808
5893
|
xiaomi_operation_mode_basic: {
|
|
5809
5894
|
cluster: 'genBasic',
|
|
5810
5895
|
type: ['attributeReport', 'readResponse'],
|
|
@@ -5847,7 +5932,7 @@ const converters = {
|
|
|
5847
5932
|
cluster: 'genMultistateInput',
|
|
5848
5933
|
type: ['attributeReport', 'readResponse'],
|
|
5849
5934
|
convert: (model, msg, publish, options, meta) => {
|
|
5850
|
-
if (
|
|
5935
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
5851
5936
|
const actionLookup = {0: 'hold', 255: 'release', 1: 'single', 2: 'double', 3: 'triple', 5: 'quintuple', 6: 'many'};
|
|
5852
5937
|
const button = msg.endpoint.ID;
|
|
5853
5938
|
const value = msg.data.presentValue;
|
|
@@ -5870,7 +5955,7 @@ const converters = {
|
|
|
5870
5955
|
cluster: 'genOnOff',
|
|
5871
5956
|
type: 'commandOn',
|
|
5872
5957
|
convert: (model, msg, publish, options, meta) => {
|
|
5873
|
-
if (
|
|
5958
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
5874
5959
|
return {action: 'button_2_single'};
|
|
5875
5960
|
},
|
|
5876
5961
|
},
|
|
@@ -5878,7 +5963,7 @@ const converters = {
|
|
|
5878
5963
|
cluster: 'genOnOff',
|
|
5879
5964
|
type: 'commandOff',
|
|
5880
5965
|
convert: (model, msg, publish, options, meta) => {
|
|
5881
|
-
if (
|
|
5966
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
5882
5967
|
return {action: 'button_1_single'};
|
|
5883
5968
|
},
|
|
5884
5969
|
},
|
|
@@ -5886,7 +5971,7 @@ const converters = {
|
|
|
5886
5971
|
cluster: 'genLevelCtrl',
|
|
5887
5972
|
type: 'commandStep',
|
|
5888
5973
|
convert: (model, msg, publish, options, meta) => {
|
|
5889
|
-
if (
|
|
5974
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
5890
5975
|
const button = msg.data.stepmode === 0 ? '4' : '3';
|
|
5891
5976
|
return {action: `button_${button}_single`};
|
|
5892
5977
|
},
|
|
@@ -5896,7 +5981,7 @@ const converters = {
|
|
|
5896
5981
|
type: 'commandStop',
|
|
5897
5982
|
options: [exposes.options.legacy()],
|
|
5898
5983
|
convert: (model, msg, publish, options, meta) => {
|
|
5899
|
-
if (
|
|
5984
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
5900
5985
|
if (globalStore.hasValue(msg.endpoint, 'button')) {
|
|
5901
5986
|
const value = globalStore.getValue(msg.endpoint, 'button');
|
|
5902
5987
|
const duration = Date.now() - value.start;
|
|
@@ -5910,7 +5995,7 @@ const converters = {
|
|
|
5910
5995
|
cluster: 'genLevelCtrl',
|
|
5911
5996
|
type: 'commandMove',
|
|
5912
5997
|
convert: (model, msg, publish, options, meta) => {
|
|
5913
|
-
if (
|
|
5998
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
5914
5999
|
const button = msg.data.movemode === 0 ? '4' : '3';
|
|
5915
6000
|
globalStore.putValue(msg.endpoint, 'button', {button, start: Date.now()});
|
|
5916
6001
|
return {action: `button_${button}_hold`};
|
|
@@ -5920,7 +6005,7 @@ const converters = {
|
|
|
5920
6005
|
cluster: 'lightingColorCtrl',
|
|
5921
6006
|
type: 'commandStepColorTemp',
|
|
5922
6007
|
convert: (model, msg, publish, options, meta) => {
|
|
5923
|
-
if (
|
|
6008
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
5924
6009
|
let action;
|
|
5925
6010
|
if (model.model === 'WXCJKG12LM') {
|
|
5926
6011
|
// for WXCJKG12LM model it's double click event on buttons 3 and 4
|
|
@@ -5937,7 +6022,7 @@ const converters = {
|
|
|
5937
6022
|
type: 'commandMoveColorTemp',
|
|
5938
6023
|
options: [exposes.options.legacy()],
|
|
5939
6024
|
convert: (model, msg, publish, options, meta) => {
|
|
5940
|
-
if (
|
|
6025
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
5941
6026
|
const stop = msg.data.movemode === 0;
|
|
5942
6027
|
let result = null;
|
|
5943
6028
|
if (stop) {
|
|
@@ -7363,7 +7448,7 @@ const converters = {
|
|
|
7363
7448
|
cluster: 'wiserDeviceInfo',
|
|
7364
7449
|
type: 'attributeReport',
|
|
7365
7450
|
convert: (model, msg, publish, options, meta) => {
|
|
7366
|
-
if (
|
|
7451
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
7367
7452
|
|
|
7368
7453
|
const data = msg.data['deviceInfo'].split(',');
|
|
7369
7454
|
if (data[0] === 'UI' && data[1]) {
|
|
@@ -8141,7 +8226,7 @@ const converters = {
|
|
|
8141
8226
|
convert: (model, msg, publish, options, meta) => {
|
|
8142
8227
|
// commandStopMove without params
|
|
8143
8228
|
if (msg.data[2] !== 71) return;
|
|
8144
|
-
if (
|
|
8229
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
8145
8230
|
const movestop = 'stop';
|
|
8146
8231
|
const action = postfixWithEndpointName(`hue_${movestop}`, msg, model);
|
|
8147
8232
|
const payload = {action};
|
|
@@ -8153,7 +8238,7 @@ const converters = {
|
|
|
8153
8238
|
cluster: 'genOnOff',
|
|
8154
8239
|
type: 'raw',
|
|
8155
8240
|
convert: (model, msg, publish, options, meta) => {
|
|
8156
|
-
if (hasAlreadyProcessedMessage(msg, msg.data[
|
|
8241
|
+
if (hasAlreadyProcessedMessage(msg, msg.data[1])) return;
|
|
8157
8242
|
let action;
|
|
8158
8243
|
if (msg.data[2] == 253) {
|
|
8159
8244
|
action = {0: 'single', 1: 'double', 2: 'hold'}[msg.data[3]];
|