zigbee-herdsman-converters 14.0.396 → 14.0.397
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 +45 -44
- package/devices/ecodim.js +0 -2
- package/devices/jxuan.js +0 -1
- package/devices/legrand.js +2 -2
- package/devices/moes.js +0 -1
- package/devices/owon.js +0 -1
- package/devices/prolight.js +7 -0
- package/devices/sprut.js +72 -12
- package/devices/technicolor.js +1 -1
- package/npm-shrinkwrap.json +1 -1
- package/package.json +1 -1
package/converters/fromZigbee.js
CHANGED
|
@@ -1042,7 +1042,7 @@ const converters = {
|
|
|
1042
1042
|
cluster: 'genScenes',
|
|
1043
1043
|
type: 'commandRecall',
|
|
1044
1044
|
convert: (model, msg, publish, options, meta) => {
|
|
1045
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1045
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
1046
1046
|
const payload = {action: postfixWithEndpointName(`recall_${msg.data.sceneid}`, msg, model)};
|
|
1047
1047
|
addActionGroup(payload, msg, model);
|
|
1048
1048
|
return payload;
|
|
@@ -1052,7 +1052,7 @@ const converters = {
|
|
|
1052
1052
|
cluster: 'ssIasAce',
|
|
1053
1053
|
type: 'commandPanic',
|
|
1054
1054
|
convert: (model, msg, publish, options, meta) => {
|
|
1055
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1055
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
1056
1056
|
const payload = {action: postfixWithEndpointName(`panic`, msg, model)};
|
|
1057
1057
|
addActionGroup(payload, msg, model);
|
|
1058
1058
|
return payload;
|
|
@@ -1062,7 +1062,7 @@ const converters = {
|
|
|
1062
1062
|
cluster: 'ssIasAce',
|
|
1063
1063
|
type: 'commandArm',
|
|
1064
1064
|
convert: (model, msg, publish, options, meta) => {
|
|
1065
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1065
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
1066
1066
|
const payload = {
|
|
1067
1067
|
action: postfixWithEndpointName(constants.armMode[msg.data['armmode']], msg, model),
|
|
1068
1068
|
action_code: msg.data.code,
|
|
@@ -1076,6 +1076,7 @@ const converters = {
|
|
|
1076
1076
|
cluster: 'ssIasAce',
|
|
1077
1077
|
type: 'commandArm',
|
|
1078
1078
|
convert: (model, msg, publish, options, meta) => {
|
|
1079
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
1079
1080
|
const payload = converters.command_arm.convert(model, msg, publish, options, meta);
|
|
1080
1081
|
if (!payload) return;
|
|
1081
1082
|
payload.action_transaction = msg.meta.zclTransactionSequenceNumber;
|
|
@@ -1086,7 +1087,7 @@ const converters = {
|
|
|
1086
1087
|
cluster: 'closuresWindowCovering',
|
|
1087
1088
|
type: 'commandStop',
|
|
1088
1089
|
convert: (model, msg, publish, options, meta) => {
|
|
1089
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1090
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
1090
1091
|
const payload = {action: postfixWithEndpointName('stop', msg, model)};
|
|
1091
1092
|
addActionGroup(payload, msg, model);
|
|
1092
1093
|
return payload;
|
|
@@ -1096,7 +1097,7 @@ const converters = {
|
|
|
1096
1097
|
cluster: 'closuresWindowCovering',
|
|
1097
1098
|
type: 'commandUpOpen',
|
|
1098
1099
|
convert: (model, msg, publish, options, meta) => {
|
|
1099
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1100
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
1100
1101
|
const payload = {action: postfixWithEndpointName('open', msg, model)};
|
|
1101
1102
|
addActionGroup(payload, msg, model);
|
|
1102
1103
|
return payload;
|
|
@@ -1106,7 +1107,7 @@ const converters = {
|
|
|
1106
1107
|
cluster: 'closuresWindowCovering',
|
|
1107
1108
|
type: 'commandDownClose',
|
|
1108
1109
|
convert: (model, msg, publish, options, meta) => {
|
|
1109
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1110
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
1110
1111
|
const payload = {action: postfixWithEndpointName('close', msg, model)};
|
|
1111
1112
|
addActionGroup(payload, msg, model);
|
|
1112
1113
|
return payload;
|
|
@@ -1116,7 +1117,7 @@ const converters = {
|
|
|
1116
1117
|
cluster: 'genOnOff',
|
|
1117
1118
|
type: 'commandOn',
|
|
1118
1119
|
convert: (model, msg, publish, options, meta) => {
|
|
1119
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1120
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
1120
1121
|
const payload = {action: postfixWithEndpointName('on', msg, model)};
|
|
1121
1122
|
addActionGroup(payload, msg, model);
|
|
1122
1123
|
return payload;
|
|
@@ -1126,7 +1127,7 @@ const converters = {
|
|
|
1126
1127
|
cluster: 'genOnOff',
|
|
1127
1128
|
type: 'commandOff',
|
|
1128
1129
|
convert: (model, msg, publish, options, meta) => {
|
|
1129
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1130
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
1130
1131
|
const payload = {action: postfixWithEndpointName('off', msg, model)};
|
|
1131
1132
|
addActionGroup(payload, msg, model);
|
|
1132
1133
|
return payload;
|
|
@@ -1136,7 +1137,7 @@ const converters = {
|
|
|
1136
1137
|
cluster: 'genOnOff',
|
|
1137
1138
|
type: 'commandOffWithEffect',
|
|
1138
1139
|
convert: (model, msg, publish, options, meta) => {
|
|
1139
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1140
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
1140
1141
|
const payload = {action: postfixWithEndpointName(`off`, msg, model)};
|
|
1141
1142
|
addActionGroup(payload, msg, model);
|
|
1142
1143
|
return payload;
|
|
@@ -1146,7 +1147,7 @@ const converters = {
|
|
|
1146
1147
|
cluster: 'genOnOff',
|
|
1147
1148
|
type: 'commandToggle',
|
|
1148
1149
|
convert: (model, msg, publish, options, meta) => {
|
|
1149
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1150
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
1150
1151
|
const payload = {action: postfixWithEndpointName('toggle', msg, model)};
|
|
1151
1152
|
addActionGroup(payload, msg, model);
|
|
1152
1153
|
return payload;
|
|
@@ -1157,7 +1158,7 @@ const converters = {
|
|
|
1157
1158
|
type: ['commandMoveToLevel', 'commandMoveToLevelWithOnOff'],
|
|
1158
1159
|
options: [exposes.options.simulated_brightness()],
|
|
1159
1160
|
convert: (model, msg, publish, options, meta) => {
|
|
1160
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1161
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
1161
1162
|
const payload = {
|
|
1162
1163
|
action: postfixWithEndpointName(`brightness_move_to_level`, msg, model),
|
|
1163
1164
|
action_level: msg.data.level,
|
|
@@ -1179,7 +1180,7 @@ const converters = {
|
|
|
1179
1180
|
type: ['commandMove', 'commandMoveWithOnOff'],
|
|
1180
1181
|
options: [exposes.options.simulated_brightness()],
|
|
1181
1182
|
convert: (model, msg, publish, options, meta) => {
|
|
1182
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1183
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
1183
1184
|
const direction = msg.data.movemode === 1 ? 'down' : 'up';
|
|
1184
1185
|
const action = postfixWithEndpointName(`brightness_move_${direction}`, msg, model);
|
|
1185
1186
|
const payload = {action, action_rate: msg.data.rate};
|
|
@@ -1215,7 +1216,7 @@ const converters = {
|
|
|
1215
1216
|
type: ['commandStep', 'commandStepWithOnOff'],
|
|
1216
1217
|
options: [exposes.options.simulated_brightness()],
|
|
1217
1218
|
convert: (model, msg, publish, options, meta) => {
|
|
1218
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1219
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
1219
1220
|
const direction = msg.data.stepmode === 1 ? 'down' : 'up';
|
|
1220
1221
|
const payload = {
|
|
1221
1222
|
action: postfixWithEndpointName(`brightness_step_${direction}`, msg, model),
|
|
@@ -1242,7 +1243,7 @@ const converters = {
|
|
|
1242
1243
|
type: ['commandStop', 'commandStopWithOnOff'],
|
|
1243
1244
|
options: [exposes.options.simulated_brightness()],
|
|
1244
1245
|
convert: (model, msg, publish, options, meta) => {
|
|
1245
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1246
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
1246
1247
|
if (options.simulated_brightness) {
|
|
1247
1248
|
clearInterval(globalStore.getValue(msg.endpoint, 'simulated_brightness_timer'));
|
|
1248
1249
|
globalStore.putValue(msg.endpoint, 'simulated_brightness_timer', undefined);
|
|
@@ -1257,7 +1258,7 @@ const converters = {
|
|
|
1257
1258
|
cluster: 'lightingColorCtrl',
|
|
1258
1259
|
type: ['commandMoveColorTemp'],
|
|
1259
1260
|
convert: (model, msg, publish, options, meta) => {
|
|
1260
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1261
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
1261
1262
|
const direction = msg.data.movemode === 1 ? 'down' : 'up';
|
|
1262
1263
|
const action = postfixWithEndpointName(`color_temperature_move_${direction}`, msg, model);
|
|
1263
1264
|
const payload = {action, action_rate: msg.data.rate, action_minimum: msg.data.minimum, action_maximum: msg.data.maximum};
|
|
@@ -1269,7 +1270,7 @@ const converters = {
|
|
|
1269
1270
|
cluster: 'lightingColorCtrl',
|
|
1270
1271
|
type: 'commandStepColorTemp',
|
|
1271
1272
|
convert: (model, msg, publish, options, meta) => {
|
|
1272
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1273
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
1273
1274
|
const direction = msg.data.stepmode === 1 ? 'up' : 'down';
|
|
1274
1275
|
const payload = {
|
|
1275
1276
|
action: postfixWithEndpointName(`color_temperature_step_${direction}`, msg, model),
|
|
@@ -1288,7 +1289,7 @@ const converters = {
|
|
|
1288
1289
|
cluster: 'lightingColorCtrl',
|
|
1289
1290
|
type: 'commandEnhancedMoveToHueAndSaturation',
|
|
1290
1291
|
convert: (model, msg, publish, options, meta) => {
|
|
1291
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1292
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
1292
1293
|
const payload = {
|
|
1293
1294
|
action: postfixWithEndpointName(`enhanced_move_to_hue_and_saturation`, msg, model),
|
|
1294
1295
|
action_enhanced_hue: msg.data.enhancehue,
|
|
@@ -1305,7 +1306,7 @@ const converters = {
|
|
|
1305
1306
|
cluster: 'lightingColorCtrl',
|
|
1306
1307
|
type: ['commandStepHue'],
|
|
1307
1308
|
convert: (model, msg, publish, options, meta) => {
|
|
1308
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1309
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
1309
1310
|
const direction = msg.data.stepmode === 1 ? 'up' : 'down';
|
|
1310
1311
|
const payload = {
|
|
1311
1312
|
action: postfixWithEndpointName(`color_hue_step_${direction}`, msg, model),
|
|
@@ -1320,7 +1321,7 @@ const converters = {
|
|
|
1320
1321
|
cluster: 'lightingColorCtrl',
|
|
1321
1322
|
type: ['commandStepSaturation'],
|
|
1322
1323
|
convert: (model, msg, publish, options, meta) => {
|
|
1323
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1324
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
1324
1325
|
const direction = msg.data.stepmode === 1 ? 'up' : 'down';
|
|
1325
1326
|
const payload = {
|
|
1326
1327
|
action: postfixWithEndpointName(`color_saturation_step_${direction}`, msg, model),
|
|
@@ -1335,7 +1336,7 @@ const converters = {
|
|
|
1335
1336
|
cluster: 'lightingColorCtrl',
|
|
1336
1337
|
type: 'commandColorLoopSet',
|
|
1337
1338
|
convert: (model, msg, publish, options, meta) => {
|
|
1338
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1339
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
1339
1340
|
const updateFlags = msg.data.updateflags;
|
|
1340
1341
|
const actionLookup = {
|
|
1341
1342
|
0x00: 'deactivate',
|
|
@@ -1365,7 +1366,7 @@ const converters = {
|
|
|
1365
1366
|
cluster: 'lightingColorCtrl',
|
|
1366
1367
|
type: 'commandMoveToColorTemp',
|
|
1367
1368
|
convert: (model, msg, publish, options, meta) => {
|
|
1368
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1369
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
1369
1370
|
const payload = {
|
|
1370
1371
|
action: postfixWithEndpointName(`color_temperature_move`, msg, model),
|
|
1371
1372
|
action_color_temperature: msg.data.colortemp,
|
|
@@ -1379,7 +1380,7 @@ const converters = {
|
|
|
1379
1380
|
cluster: 'lightingColorCtrl',
|
|
1380
1381
|
type: 'commandMoveToColor',
|
|
1381
1382
|
convert: (model, msg, publish, options, meta) => {
|
|
1382
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1383
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
1383
1384
|
const payload = {
|
|
1384
1385
|
action: postfixWithEndpointName(`color_move`, msg, model),
|
|
1385
1386
|
action_color: {
|
|
@@ -1396,7 +1397,7 @@ const converters = {
|
|
|
1396
1397
|
cluster: 'lightingColorCtrl',
|
|
1397
1398
|
type: 'commandMoveHue',
|
|
1398
1399
|
convert: (model, msg, publish, options, meta) => {
|
|
1399
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1400
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
1400
1401
|
const movestop = msg.data.movemode == 1 ? 'move' : 'stop';
|
|
1401
1402
|
const action = postfixWithEndpointName(`hue_${movestop}`, msg, model);
|
|
1402
1403
|
const payload = {action, action_rate: msg.data.rate};
|
|
@@ -1408,7 +1409,7 @@ const converters = {
|
|
|
1408
1409
|
cluster: 'lightingColorCtrl',
|
|
1409
1410
|
type: 'commandMoveToSaturation',
|
|
1410
1411
|
convert: (model, msg, publish, options, meta) => {
|
|
1411
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1412
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
1412
1413
|
const payload = {
|
|
1413
1414
|
action: postfixWithEndpointName('move_to_saturation', msg, model),
|
|
1414
1415
|
action_saturation: msg.data.saturation,
|
|
@@ -1422,7 +1423,7 @@ const converters = {
|
|
|
1422
1423
|
cluster: 'lightingColorCtrl',
|
|
1423
1424
|
type: 'commandMoveToHue',
|
|
1424
1425
|
convert: (model, msg, publish, options, meta) => {
|
|
1425
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1426
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
1426
1427
|
const payload = {
|
|
1427
1428
|
action: postfixWithEndpointName(`move_to_hue`, msg, model),
|
|
1428
1429
|
action_hue: msg.data.hue,
|
|
@@ -1437,7 +1438,7 @@ const converters = {
|
|
|
1437
1438
|
cluster: 'ssIasAce',
|
|
1438
1439
|
type: 'commandEmergency',
|
|
1439
1440
|
convert: (model, msg, publish, options, meta) => {
|
|
1440
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1441
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
1441
1442
|
const payload = {action: postfixWithEndpointName(`emergency`, msg, model)};
|
|
1442
1443
|
addActionGroup(payload, msg, model);
|
|
1443
1444
|
return payload;
|
|
@@ -1447,7 +1448,7 @@ const converters = {
|
|
|
1447
1448
|
cluster: 'genOnOff',
|
|
1448
1449
|
type: 'commandOn',
|
|
1449
1450
|
convert: (model, msg, publish, options, meta) => {
|
|
1450
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1451
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
1451
1452
|
const property = postfixWithEndpointName('state', msg, model);
|
|
1452
1453
|
return {[property]: 'ON'};
|
|
1453
1454
|
},
|
|
@@ -1456,7 +1457,7 @@ const converters = {
|
|
|
1456
1457
|
cluster: 'genOnOff',
|
|
1457
1458
|
type: 'commandOff',
|
|
1458
1459
|
convert: (model, msg, publish, options, meta) => {
|
|
1459
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1460
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
1460
1461
|
const property = postfixWithEndpointName('state', msg, model);
|
|
1461
1462
|
return {[property]: 'OFF'};
|
|
1462
1463
|
},
|
|
@@ -2181,7 +2182,7 @@ const converters = {
|
|
|
2181
2182
|
cluster: 'ssIasZone',
|
|
2182
2183
|
type: 'commandStatusChangeNotification',
|
|
2183
2184
|
convert: (model, msg, publish, options, meta) => {
|
|
2184
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
2185
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
2185
2186
|
const lookup = {1: 'pressed'};
|
|
2186
2187
|
const zoneStatus = msg.data.zonestatus;
|
|
2187
2188
|
return {
|
|
@@ -4515,7 +4516,7 @@ const converters = {
|
|
|
4515
4516
|
cluster: 'genScenes',
|
|
4516
4517
|
type: 'commandTradfriArrowSingle',
|
|
4517
4518
|
convert: (model, msg, publish, options, meta) => {
|
|
4518
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
4519
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
4519
4520
|
if (msg.data.value === 2) {
|
|
4520
4521
|
// This is send on toggle hold, ignore it as a toggle_hold is already handled above.
|
|
4521
4522
|
return;
|
|
@@ -4529,7 +4530,7 @@ const converters = {
|
|
|
4529
4530
|
cluster: 'genScenes',
|
|
4530
4531
|
type: 'commandTradfriArrowHold',
|
|
4531
4532
|
convert: (model, msg, publish, options, meta) => {
|
|
4532
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
4533
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
4533
4534
|
const direction = msg.data.value === 3329 ? 'left' : 'right';
|
|
4534
4535
|
globalStore.putValue(msg.endpoint, 'direction', direction);
|
|
4535
4536
|
return {action: `arrow_${direction}_hold`};
|
|
@@ -4540,7 +4541,7 @@ const converters = {
|
|
|
4540
4541
|
type: 'commandTradfriArrowRelease',
|
|
4541
4542
|
options: [exposes.options.legacy()],
|
|
4542
4543
|
convert: (model, msg, publish, options, meta) => {
|
|
4543
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
4544
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
4544
4545
|
const direction = globalStore.getValue(msg.endpoint, 'direction');
|
|
4545
4546
|
if (direction) {
|
|
4546
4547
|
globalStore.clearValue(msg.endpoint, 'direction');
|
|
@@ -5379,7 +5380,7 @@ const converters = {
|
|
|
5379
5380
|
cluster: 'genMultistateInput',
|
|
5380
5381
|
type: ['attributeReport'],
|
|
5381
5382
|
convert: (model, msg, publish, options, meta) => {
|
|
5382
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
5383
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
5383
5384
|
let actionLookup = {0: 'hold', 1: 'single', 2: 'double', 3: 'triple', 255: 'release'};
|
|
5384
5385
|
if (model.model === 'WXKG12LM') {
|
|
5385
5386
|
actionLookup = {...actionLookup, 16: 'hold', 17: 'release', 18: 'shake'};
|
|
@@ -5525,7 +5526,7 @@ const converters = {
|
|
|
5525
5526
|
`increase it with this option (value is in ms).`),
|
|
5526
5527
|
],
|
|
5527
5528
|
convert: (model, msg, publish, options, meta) => {
|
|
5528
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
5529
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
5529
5530
|
const state = msg.data['onOff'];
|
|
5530
5531
|
|
|
5531
5532
|
// 0 = click down, 1 = click up, else = multiple clicks
|
|
@@ -5831,7 +5832,7 @@ const converters = {
|
|
|
5831
5832
|
cluster: 'genMultistateInput',
|
|
5832
5833
|
type: ['attributeReport', 'readResponse'],
|
|
5833
5834
|
convert: (model, msg, publish, options, meta) => {
|
|
5834
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
5835
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
5835
5836
|
const actionLookup = {0: 'hold', 255: 'release', 1: 'single', 2: 'double', 3: 'triple', 5: 'quintuple', 6: 'many'};
|
|
5836
5837
|
const button = msg.endpoint.ID;
|
|
5837
5838
|
const value = msg.data.presentValue;
|
|
@@ -5854,7 +5855,7 @@ const converters = {
|
|
|
5854
5855
|
cluster: 'genOnOff',
|
|
5855
5856
|
type: 'commandOn',
|
|
5856
5857
|
convert: (model, msg, publish, options, meta) => {
|
|
5857
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
5858
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
5858
5859
|
return {action: 'button_2_single'};
|
|
5859
5860
|
},
|
|
5860
5861
|
},
|
|
@@ -5862,7 +5863,7 @@ const converters = {
|
|
|
5862
5863
|
cluster: 'genOnOff',
|
|
5863
5864
|
type: 'commandOff',
|
|
5864
5865
|
convert: (model, msg, publish, options, meta) => {
|
|
5865
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
5866
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
5866
5867
|
return {action: 'button_1_single'};
|
|
5867
5868
|
},
|
|
5868
5869
|
},
|
|
@@ -5870,7 +5871,7 @@ const converters = {
|
|
|
5870
5871
|
cluster: 'genLevelCtrl',
|
|
5871
5872
|
type: 'commandStep',
|
|
5872
5873
|
convert: (model, msg, publish, options, meta) => {
|
|
5873
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
5874
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
5874
5875
|
const button = msg.data.stepmode === 0 ? '4' : '3';
|
|
5875
5876
|
return {action: `button_${button}_single`};
|
|
5876
5877
|
},
|
|
@@ -5880,7 +5881,7 @@ const converters = {
|
|
|
5880
5881
|
type: 'commandStop',
|
|
5881
5882
|
options: [exposes.options.legacy()],
|
|
5882
5883
|
convert: (model, msg, publish, options, meta) => {
|
|
5883
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
5884
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
5884
5885
|
if (globalStore.hasValue(msg.endpoint, 'button')) {
|
|
5885
5886
|
const value = globalStore.getValue(msg.endpoint, 'button');
|
|
5886
5887
|
const duration = Date.now() - value.start;
|
|
@@ -5894,7 +5895,7 @@ const converters = {
|
|
|
5894
5895
|
cluster: 'genLevelCtrl',
|
|
5895
5896
|
type: 'commandMove',
|
|
5896
5897
|
convert: (model, msg, publish, options, meta) => {
|
|
5897
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
5898
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
5898
5899
|
const button = msg.data.movemode === 0 ? '4' : '3';
|
|
5899
5900
|
globalStore.putValue(msg.endpoint, 'button', {button, start: Date.now()});
|
|
5900
5901
|
return {action: `button_${button}_hold`};
|
|
@@ -5904,7 +5905,7 @@ const converters = {
|
|
|
5904
5905
|
cluster: 'lightingColorCtrl',
|
|
5905
5906
|
type: 'commandStepColorTemp',
|
|
5906
5907
|
convert: (model, msg, publish, options, meta) => {
|
|
5907
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
5908
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
5908
5909
|
let action;
|
|
5909
5910
|
if (model.model === 'WXCJKG12LM') {
|
|
5910
5911
|
// for WXCJKG12LM model it's double click event on buttons 3 and 4
|
|
@@ -5921,7 +5922,7 @@ const converters = {
|
|
|
5921
5922
|
type: 'commandMoveColorTemp',
|
|
5922
5923
|
options: [exposes.options.legacy()],
|
|
5923
5924
|
convert: (model, msg, publish, options, meta) => {
|
|
5924
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
5925
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
5925
5926
|
const stop = msg.data.movemode === 0;
|
|
5926
5927
|
let result = null;
|
|
5927
5928
|
if (stop) {
|
|
@@ -7327,7 +7328,7 @@ const converters = {
|
|
|
7327
7328
|
cluster: 'wiserDeviceInfo',
|
|
7328
7329
|
type: 'attributeReport',
|
|
7329
7330
|
convert: (model, msg, publish, options, meta) => {
|
|
7330
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
7331
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
7331
7332
|
|
|
7332
7333
|
const data = msg.data['deviceInfo'].split(',');
|
|
7333
7334
|
if (data[0] === 'UI' && data[1]) {
|
|
@@ -8105,7 +8106,7 @@ const converters = {
|
|
|
8105
8106
|
convert: (model, msg, publish, options, meta) => {
|
|
8106
8107
|
// commandStopMove without params
|
|
8107
8108
|
if (msg.data[2] !== 71) return;
|
|
8108
|
-
if (hasAlreadyProcessedMessage(msg)) return;
|
|
8109
|
+
if ((!model.meta || !model.meta.handleDuplicateTransaction) && hasAlreadyProcessedMessage(msg)) return;
|
|
8109
8110
|
const movestop = 'stop';
|
|
8110
8111
|
const action = postfixWithEndpointName(`hue_${movestop}`, msg, model);
|
|
8111
8112
|
const payload = {action};
|
package/devices/ecodim.js
CHANGED
|
@@ -98,7 +98,6 @@ module.exports = [
|
|
|
98
98
|
model: 'ED-10014',
|
|
99
99
|
vendor: 'EcoDim',
|
|
100
100
|
description: 'Zigbee 8 button wall switch - white',
|
|
101
|
-
supports: '',
|
|
102
101
|
fromZigbee: [fz.command_on, fz.command_off, fz.command_move, fz.command_stop, fz.battery],
|
|
103
102
|
exposes: [e.battery(), e.action(['on_1', 'off_1', 'brightness_move_up_1', 'brightness_move_down_1', 'brightness_stop_1',
|
|
104
103
|
'on_2', 'off_2', 'brightness_move_up_2', 'brightness_move_down_2', 'brightness_stop_2', 'on_3', 'off_3',
|
|
@@ -112,7 +111,6 @@ module.exports = [
|
|
|
112
111
|
model: 'ED-10015',
|
|
113
112
|
vendor: 'EcoDim',
|
|
114
113
|
description: 'Zigbee 8 button wall switch - black',
|
|
115
|
-
supports: '',
|
|
116
114
|
fromZigbee: [fz.command_on, fz.command_off, fz.command_move, fz.command_stop, fz.battery],
|
|
117
115
|
exposes: [e.battery(), e.action(['on_1', 'off_1', 'brightness_move_up_1', 'brightness_move_down_1', 'brightness_stop_1',
|
|
118
116
|
'on_2', 'off_2', 'brightness_move_up_2', 'brightness_move_down_2', 'brightness_stop_2', 'on_3', 'off_3', 'brightness_move_up_3',
|
package/devices/jxuan.js
CHANGED
|
@@ -38,7 +38,6 @@ module.exports = [
|
|
|
38
38
|
model: 'SPZ01',
|
|
39
39
|
vendor: 'J.XUAN',
|
|
40
40
|
description: 'plug',
|
|
41
|
-
supports: 'plug',
|
|
42
41
|
fromZigbee: [fz.on_off, fz.electrical_measurement, fz.metering],
|
|
43
42
|
exposes: [e.switch(), e.power(), e.power_outage_memory().withAccess(ea.STATE_SET)],
|
|
44
43
|
toZigbee: [tz.on_off, tz.SPZ01_power_outage_memory],
|
package/devices/legrand.js
CHANGED
|
@@ -111,7 +111,7 @@ module.exports = [
|
|
|
111
111
|
exposes: [e.battery(), e.action(['identify', 'on', 'off', 'toggle', 'brightness_move_up',
|
|
112
112
|
'brightness_move_down', 'brightness_stop'])],
|
|
113
113
|
toZigbee: [],
|
|
114
|
-
meta: {battery: {voltageToPercentage: '3V_2500'}},
|
|
114
|
+
meta: {handleDuplicateTransaction: true, battery: {voltageToPercentage: '3V_2500'}},
|
|
115
115
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
116
116
|
const endpoint = device.getEndpoint(1);
|
|
117
117
|
await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'genOnOff', 'genLevelCtrl']);
|
|
@@ -127,7 +127,7 @@ module.exports = [
|
|
|
127
127
|
exposes: [e.battery(),
|
|
128
128
|
e.action(['identify', 'on', 'off', 'toggle', 'brightness_move_up', 'brightness_move_down', 'brightness_stop'])],
|
|
129
129
|
toZigbee: [],
|
|
130
|
-
meta: {multiEndpoint: true, battery: {voltageToPercentage: '3V_2500'}},
|
|
130
|
+
meta: {handleDuplicateTransaction: true, multiEndpoint: true, battery: {voltageToPercentage: '3V_2500'}},
|
|
131
131
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
132
132
|
const endpoint = device.getEndpoint(1);
|
|
133
133
|
await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'genOnOff', 'genLevelCtrl']);
|
package/devices/moes.js
CHANGED
|
@@ -303,7 +303,6 @@ module.exports = [
|
|
|
303
303
|
model: 'MS-108ZR',
|
|
304
304
|
vendor: 'Moes',
|
|
305
305
|
description: 'Zigbee + RF curtain switch module',
|
|
306
|
-
supports: 'open, close, stop, position',
|
|
307
306
|
fromZigbee: [fz.tuya_cover_options, fz.cover_position_tilt],
|
|
308
307
|
toZigbee: [tz.cover_state, tz.moes_cover_calibration, tz.cover_position_tilt, tz.tuya_cover_reversal],
|
|
309
308
|
exposes: [e.cover_position(), exposes.numeric('calibration_time', ea.ALL).withValueMin(0).withValueMax(100),
|
package/devices/owon.js
CHANGED
|
@@ -27,7 +27,6 @@ module.exports = [
|
|
|
27
27
|
model: 'CB432',
|
|
28
28
|
vendor: 'OWON',
|
|
29
29
|
description: '32A/63A power circuit breaker',
|
|
30
|
-
supports: 'on/off, power measurement',
|
|
31
30
|
fromZigbee: [fz.on_off, fz.metering, fz.electrical_measurement],
|
|
32
31
|
toZigbee: [tz.on_off],
|
|
33
32
|
exposes: [e.switch(), e.power(), e.energy()],
|
package/devices/prolight.js
CHANGED
|
@@ -15,6 +15,13 @@ module.exports = [
|
|
|
15
15
|
description: 'E27 filament bulb dimmable',
|
|
16
16
|
extend: extend.light_onoff_brightness(),
|
|
17
17
|
},
|
|
18
|
+
{
|
|
19
|
+
zigbeeModel: ['PROLIGHT E27 WARM WHITE'],
|
|
20
|
+
model: '5412748727364',
|
|
21
|
+
vendor: 'Prolight',
|
|
22
|
+
description: 'E27 bulb dimmable',
|
|
23
|
+
extend: extend.light_onoff_brightness(),
|
|
24
|
+
},
|
|
18
25
|
{
|
|
19
26
|
zigbeeModel: ['PROLIGHT GU10 WHITE AND COLOUR'],
|
|
20
27
|
model: '5412748727401',
|
package/devices/sprut.js
CHANGED
|
@@ -2,14 +2,18 @@ const exposes = require('../lib/exposes');
|
|
|
2
2
|
const fz = require('../converters/fromZigbee');
|
|
3
3
|
const tz = require('../converters/toZigbee');
|
|
4
4
|
const reporting = require('../lib/reporting');
|
|
5
|
-
const
|
|
6
|
-
const
|
|
5
|
+
const ota = require('../lib/ota');
|
|
6
|
+
const e = exposes;
|
|
7
|
+
const ep = exposes.presets;
|
|
8
|
+
const eo = exposes.options;
|
|
9
|
+
const ea = exposes.access;
|
|
10
|
+
const {calibrateAndPrecisionRoundOptions, getOptions} = require('../lib/utils');
|
|
7
11
|
|
|
8
12
|
const fzLocal = {
|
|
9
13
|
temperature: {
|
|
10
14
|
cluster: 'msTemperatureMeasurement',
|
|
11
15
|
type: ['attributeReport', 'readResponse'],
|
|
12
|
-
options: [
|
|
16
|
+
options: [eo.precision('temperature'), eo.calibration('temperature')],
|
|
13
17
|
convert: (model, msg, publish, options, meta) => {
|
|
14
18
|
const temperature = parseFloat(msg.data['measuredValue']) / 100.0;
|
|
15
19
|
return {temperature: calibrateAndPrecisionRoundOptions(temperature, options, 'temperature')};
|
|
@@ -46,11 +50,58 @@ const fzLocal = {
|
|
|
46
50
|
cluster: 'sprutNoise',
|
|
47
51
|
type: ['readResponse', 'attributeReport'],
|
|
48
52
|
convert: (model, msg, publish, options, meta) => {
|
|
49
|
-
if (msg.data.hasOwnProperty('
|
|
50
|
-
return {noise_detected: msg.data['
|
|
53
|
+
if (msg.data.hasOwnProperty('noiseDetected')) {
|
|
54
|
+
return {noise_detected: msg.data['noiseDetected'] === 1};
|
|
51
55
|
}
|
|
52
56
|
},
|
|
53
57
|
},
|
|
58
|
+
noise_timeout: {
|
|
59
|
+
cluster: 'sprutNoise',
|
|
60
|
+
type: ['readResponse', 'attributeReport'],
|
|
61
|
+
convert: (model, msg, publish, options, meta) => {
|
|
62
|
+
return {noise_timeout: msg.data.noiseAfterDetectDelay};
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const tzLocal = {
|
|
68
|
+
sprut_ir_remote: {
|
|
69
|
+
key: ['play_store', 'learn_start', 'learn_stop'],
|
|
70
|
+
convertSet: async (entity, key, value, meta) => {
|
|
71
|
+
const options = {
|
|
72
|
+
frameType: 0, manufacturerCode: 26214, disableDefaultResponse: true,
|
|
73
|
+
disableResponse: true, reservedBits: 0, direction: 0, writeUndiv: false,
|
|
74
|
+
transactionSequenceNumber: null,
|
|
75
|
+
};
|
|
76
|
+
switch (key) {
|
|
77
|
+
case 'play_store':
|
|
78
|
+
await entity.command('sprutIrBlaster', 'playStore',
|
|
79
|
+
{param: value['rom']}, options);
|
|
80
|
+
break;
|
|
81
|
+
case 'learn_start':
|
|
82
|
+
await entity.command('sprutIrBlaster', 'learnStart',
|
|
83
|
+
{value: value['rom']}, options);
|
|
84
|
+
break;
|
|
85
|
+
case 'learn_stop':
|
|
86
|
+
await entity.command('sprutIrBlaster', 'learnStop',
|
|
87
|
+
{value: value['rom']}, options);
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
noise_timeout: {
|
|
93
|
+
key: ['noise_timeout'],
|
|
94
|
+
convertSet: async (entity, key, value, meta) => {
|
|
95
|
+
value *= 1;
|
|
96
|
+
const endpoint = meta.device.getEndpoint(1);
|
|
97
|
+
await endpoint.write('sprutNoise', {noiseAfterDetectDelay: value}, getOptions(meta.mapped, entity));
|
|
98
|
+
return {state: {noise_timeout: value}};
|
|
99
|
+
},
|
|
100
|
+
convertGet: async (entity, key, meta) => {
|
|
101
|
+
const endpoint = meta.device.getEndpoint(1);
|
|
102
|
+
await endpoint.read('sprutNoise', ['noiseAfterDetectDelay']);
|
|
103
|
+
},
|
|
104
|
+
},
|
|
54
105
|
};
|
|
55
106
|
|
|
56
107
|
module.exports = [
|
|
@@ -60,15 +111,19 @@ module.exports = [
|
|
|
60
111
|
vendor: 'Sprut.device',
|
|
61
112
|
description: 'Wall-mounted Zigbee sensor',
|
|
62
113
|
fromZigbee: [fzLocal.temperature, fz.illuminance, fz.humidity, fz.occupancy, fzLocal.occupancy, fz.co2, fzLocal.voc,
|
|
63
|
-
fzLocal.noise, fzLocal.noise_detected, fz.on_off],
|
|
64
|
-
toZigbee: [tz.on_off],
|
|
65
|
-
exposes: [
|
|
66
|
-
|
|
67
|
-
|
|
114
|
+
fzLocal.noise, fzLocal.noise_detected, fz.on_off, fz.occupancy_timeout, fzLocal.noise_timeout],
|
|
115
|
+
toZigbee: [tz.on_off, tzLocal.sprut_ir_remote, tz.occupancy_timeout, tzLocal.noise_timeout],
|
|
116
|
+
exposes: [ep.temperature(), ep.illuminance(), ep.illuminance_lux(), ep.humidity(),
|
|
117
|
+
ep.occupancy(), ep.occupancy_level(), ep.co2(), ep.voc(), ep.noise(), ep.noise_detected(ea.STATE_GET),
|
|
118
|
+
ep.switch().withEndpoint('l1'), ep.switch().withEndpoint('l2'), ep.switch().withEndpoint('default'),
|
|
119
|
+
e.numeric('noise_timeout', ea.ALL).withValueMin(0).withValueMax(2000).withUnit('s')
|
|
120
|
+
.withDescription('Time in seconds after which noise is cleared after detecting it (default: 30)'),
|
|
121
|
+
e.numeric('occupancy_timeout', ea.ALL).withValueMin(0).withValueMax(2000).withUnit('s')
|
|
122
|
+
.withDescription('Time in seconds after which occupancy is cleared after detecting it (default: 30)')],
|
|
68
123
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
69
124
|
const endpoint1 = device.getEndpoint(1);
|
|
70
125
|
const binds = ['genBasic', 'msTemperatureMeasurement', 'msIlluminanceMeasurement', 'msRelativeHumidity',
|
|
71
|
-
'msOccupancySensing', 'msCO2', 'sprutVoc', 'sprutNoise'];
|
|
126
|
+
'msOccupancySensing', 'msCO2', 'sprutVoc', 'sprutNoise', 'sprutIrBlaster', 'genOta'];
|
|
72
127
|
await reporting.bind(endpoint1, coordinatorEndpoint, binds);
|
|
73
128
|
|
|
74
129
|
// led_red
|
|
@@ -80,17 +135,22 @@ module.exports = [
|
|
|
80
135
|
// buzzer
|
|
81
136
|
await device.getEndpoint(4).read('genOnOff', ['onOff']);
|
|
82
137
|
|
|
138
|
+
// Read settings at start
|
|
139
|
+
await endpoint1.read('msOccupancySensing', ['pirOToUDelay']);
|
|
140
|
+
await endpoint1.read('sprutNoise', ['noiseAfterDetectDelay']);
|
|
141
|
+
|
|
83
142
|
// Read data at start
|
|
84
143
|
await endpoint1.read('msTemperatureMeasurement', ['measuredValue']);
|
|
85
144
|
await endpoint1.read('msIlluminanceMeasurement', ['measuredValue']);
|
|
86
145
|
await endpoint1.read('msRelativeHumidity', ['measuredValue']);
|
|
87
146
|
await endpoint1.read('msOccupancySensing', ['occupancy']);
|
|
88
147
|
await endpoint1.read('sprutNoise', ['noise']);
|
|
89
|
-
await endpoint1.read('sprutNoise', ['
|
|
148
|
+
await endpoint1.read('sprutNoise', ['noiseDetected']);
|
|
90
149
|
},
|
|
91
150
|
endpoint: (device) => {
|
|
92
151
|
return {'system': 1, 'l1': 2, 'l2': 3, 'default': 4};
|
|
93
152
|
},
|
|
94
153
|
meta: {multiEndpoint: true},
|
|
154
|
+
ota: ota.zigbeeOTA,
|
|
95
155
|
},
|
|
96
156
|
];
|
package/devices/technicolor.js
CHANGED
|
@@ -12,7 +12,7 @@ module.exports = [
|
|
|
12
12
|
model: 'XHK1-TC',
|
|
13
13
|
vendor: 'Technicolor',
|
|
14
14
|
description: 'Xfinity security keypad',
|
|
15
|
-
meta: {battery: {voltageToPercentage: '3V_2100'}},
|
|
15
|
+
meta: {handleDuplicateTransaction: true, battery: {voltageToPercentage: '3V_2100'}},
|
|
16
16
|
fromZigbee: [fz.command_arm_with_transaction, fz.temperature, fz.battery, fz.ias_occupancy_alarm_1, fz.identify,
|
|
17
17
|
fz.ias_contact_alarm_1, fz.ias_ace_occupancy_with_timeout],
|
|
18
18
|
toZigbee: [tz.arm_mode],
|
package/npm-shrinkwrap.json
CHANGED