zigbee-herdsman-converters 14.0.354 → 14.0.358
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 +31 -1
- package/devices/acova.js +1 -0
- package/devices/ikea.js +3 -9
- package/devices/neo.js +2 -1
- package/devices/philips.js +12 -2
- package/devices/salus_controls.js +14 -0
- package/devices/schneider_electric.js +15 -0
- package/devices/tuya.js +9 -1
- package/devices/xiaomi.js +1 -1
- package/devices/zemismart.js +31 -0
- package/index.js +2 -2
- package/lib/exposes.js +7 -7
- package/npm-shrinkwrap.json +1 -1
- package/package.json +1 -1
package/converters/fromZigbee.js
CHANGED
|
@@ -1035,6 +1035,7 @@ const converters = {
|
|
|
1035
1035
|
cluster: 'genScenes',
|
|
1036
1036
|
type: 'commandRecall',
|
|
1037
1037
|
convert: (model, msg, publish, options, meta) => {
|
|
1038
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1038
1039
|
const payload = {action: postfixWithEndpointName(`recall_${msg.data.sceneid}`, msg, model)};
|
|
1039
1040
|
addActionGroup(payload, msg, model);
|
|
1040
1041
|
return payload;
|
|
@@ -1044,6 +1045,7 @@ const converters = {
|
|
|
1044
1045
|
cluster: 'ssIasAce',
|
|
1045
1046
|
type: 'commandPanic',
|
|
1046
1047
|
convert: (model, msg, publish, options, meta) => {
|
|
1048
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1047
1049
|
const payload = {action: postfixWithEndpointName(`panic`, msg, model)};
|
|
1048
1050
|
addActionGroup(payload, msg, model);
|
|
1049
1051
|
return payload;
|
|
@@ -1067,6 +1069,7 @@ const converters = {
|
|
|
1067
1069
|
cluster: 'ssIasAce',
|
|
1068
1070
|
type: 'commandArm',
|
|
1069
1071
|
convert: (model, msg, publish, options, meta) => {
|
|
1072
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1070
1073
|
const payload = converters.command_arm.convert(model, msg, publish, options, meta);
|
|
1071
1074
|
if (!payload) return;
|
|
1072
1075
|
payload.action_transaction = msg.meta.zclTransactionSequenceNumber;
|
|
@@ -1077,6 +1080,7 @@ const converters = {
|
|
|
1077
1080
|
cluster: 'closuresWindowCovering',
|
|
1078
1081
|
type: 'commandStop',
|
|
1079
1082
|
convert: (model, msg, publish, options, meta) => {
|
|
1083
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1080
1084
|
const payload = {action: postfixWithEndpointName('stop', msg, model)};
|
|
1081
1085
|
addActionGroup(payload, msg, model);
|
|
1082
1086
|
return payload;
|
|
@@ -1086,6 +1090,7 @@ const converters = {
|
|
|
1086
1090
|
cluster: 'closuresWindowCovering',
|
|
1087
1091
|
type: 'commandUpOpen',
|
|
1088
1092
|
convert: (model, msg, publish, options, meta) => {
|
|
1093
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1089
1094
|
const payload = {action: postfixWithEndpointName('open', msg, model)};
|
|
1090
1095
|
addActionGroup(payload, msg, model);
|
|
1091
1096
|
return payload;
|
|
@@ -1095,6 +1100,7 @@ const converters = {
|
|
|
1095
1100
|
cluster: 'closuresWindowCovering',
|
|
1096
1101
|
type: 'commandDownClose',
|
|
1097
1102
|
convert: (model, msg, publish, options, meta) => {
|
|
1103
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1098
1104
|
const payload = {action: postfixWithEndpointName('close', msg, model)};
|
|
1099
1105
|
addActionGroup(payload, msg, model);
|
|
1100
1106
|
return payload;
|
|
@@ -1104,6 +1110,7 @@ const converters = {
|
|
|
1104
1110
|
cluster: 'genOnOff',
|
|
1105
1111
|
type: 'commandOn',
|
|
1106
1112
|
convert: (model, msg, publish, options, meta) => {
|
|
1113
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1107
1114
|
const payload = {action: postfixWithEndpointName('on', msg, model)};
|
|
1108
1115
|
addActionGroup(payload, msg, model);
|
|
1109
1116
|
return payload;
|
|
@@ -1113,6 +1120,7 @@ const converters = {
|
|
|
1113
1120
|
cluster: 'genOnOff',
|
|
1114
1121
|
type: 'commandOff',
|
|
1115
1122
|
convert: (model, msg, publish, options, meta) => {
|
|
1123
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1116
1124
|
const payload = {action: postfixWithEndpointName('off', msg, model)};
|
|
1117
1125
|
addActionGroup(payload, msg, model);
|
|
1118
1126
|
return payload;
|
|
@@ -1122,6 +1130,7 @@ const converters = {
|
|
|
1122
1130
|
cluster: 'genOnOff',
|
|
1123
1131
|
type: 'commandOffWithEffect',
|
|
1124
1132
|
convert: (model, msg, publish, options, meta) => {
|
|
1133
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1125
1134
|
const payload = {action: postfixWithEndpointName(`off`, msg, model)};
|
|
1126
1135
|
addActionGroup(payload, msg, model);
|
|
1127
1136
|
return payload;
|
|
@@ -1131,6 +1140,7 @@ const converters = {
|
|
|
1131
1140
|
cluster: 'genOnOff',
|
|
1132
1141
|
type: 'commandToggle',
|
|
1133
1142
|
convert: (model, msg, publish, options, meta) => {
|
|
1143
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1134
1144
|
const payload = {action: postfixWithEndpointName('toggle', msg, model)};
|
|
1135
1145
|
addActionGroup(payload, msg, model);
|
|
1136
1146
|
return payload;
|
|
@@ -1141,6 +1151,7 @@ const converters = {
|
|
|
1141
1151
|
type: ['commandMoveToLevel', 'commandMoveToLevelWithOnOff'],
|
|
1142
1152
|
options: [exposes.options.simulated_brightness()],
|
|
1143
1153
|
convert: (model, msg, publish, options, meta) => {
|
|
1154
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1144
1155
|
const payload = {
|
|
1145
1156
|
action: postfixWithEndpointName(`brightness_move_to_level`, msg, model),
|
|
1146
1157
|
action_level: msg.data.level,
|
|
@@ -1161,6 +1172,7 @@ const converters = {
|
|
|
1161
1172
|
type: ['commandMove', 'commandMoveWithOnOff'],
|
|
1162
1173
|
options: [exposes.options.simulated_brightness()],
|
|
1163
1174
|
convert: (model, msg, publish, options, meta) => {
|
|
1175
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1164
1176
|
const direction = msg.data.movemode === 1 ? 'down' : 'up';
|
|
1165
1177
|
const action = postfixWithEndpointName(`brightness_move_${direction}`, msg, model);
|
|
1166
1178
|
const payload = {action, action_rate: msg.data.rate};
|
|
@@ -1195,6 +1207,7 @@ const converters = {
|
|
|
1195
1207
|
type: ['commandStep', 'commandStepWithOnOff'],
|
|
1196
1208
|
options: [exposes.options.simulated_brightness()],
|
|
1197
1209
|
convert: (model, msg, publish, options, meta) => {
|
|
1210
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1198
1211
|
const direction = msg.data.stepmode === 1 ? 'down' : 'up';
|
|
1199
1212
|
const payload = {
|
|
1200
1213
|
action: postfixWithEndpointName(`brightness_step_${direction}`, msg, model),
|
|
@@ -1220,6 +1233,7 @@ const converters = {
|
|
|
1220
1233
|
type: ['commandStop', 'commandStopWithOnOff'],
|
|
1221
1234
|
options: [exposes.options.simulated_brightness()],
|
|
1222
1235
|
convert: (model, msg, publish, options, meta) => {
|
|
1236
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1223
1237
|
if (options.simulated_brightness) {
|
|
1224
1238
|
clearInterval(globalStore.getValue(msg.endpoint, 'simulated_brightness_timer'));
|
|
1225
1239
|
globalStore.putValue(msg.endpoint, 'simulated_brightness_timer', undefined);
|
|
@@ -1234,6 +1248,7 @@ const converters = {
|
|
|
1234
1248
|
cluster: 'lightingColorCtrl',
|
|
1235
1249
|
type: ['commandMoveColorTemp'],
|
|
1236
1250
|
convert: (model, msg, publish, options, meta) => {
|
|
1251
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1237
1252
|
const direction = msg.data.movemode === 1 ? 'down' : 'up';
|
|
1238
1253
|
const action = postfixWithEndpointName(`color_temperature_move_${direction}`, msg, model);
|
|
1239
1254
|
const payload = {action, action_rate: msg.data.rate, action_minimum: msg.data.minimum, action_maximum: msg.data.maximum};
|
|
@@ -1245,6 +1260,7 @@ const converters = {
|
|
|
1245
1260
|
cluster: 'lightingColorCtrl',
|
|
1246
1261
|
type: 'commandStepColorTemp',
|
|
1247
1262
|
convert: (model, msg, publish, options, meta) => {
|
|
1263
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1248
1264
|
const direction = msg.data.stepmode === 1 ? 'up' : 'down';
|
|
1249
1265
|
const payload = {
|
|
1250
1266
|
action: postfixWithEndpointName(`color_temperature_step_${direction}`, msg, model),
|
|
@@ -1263,6 +1279,7 @@ const converters = {
|
|
|
1263
1279
|
cluster: 'lightingColorCtrl',
|
|
1264
1280
|
type: 'commandEnhancedMoveToHueAndSaturation',
|
|
1265
1281
|
convert: (model, msg, publish, options, meta) => {
|
|
1282
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1266
1283
|
const payload = {
|
|
1267
1284
|
action: postfixWithEndpointName(`enhanced_move_to_hue_and_saturation`, msg, model),
|
|
1268
1285
|
action_enhanced_hue: msg.data.enhancehue,
|
|
@@ -1279,6 +1296,7 @@ const converters = {
|
|
|
1279
1296
|
cluster: 'lightingColorCtrl',
|
|
1280
1297
|
type: ['commandStepHue'],
|
|
1281
1298
|
convert: (model, msg, publish, options, meta) => {
|
|
1299
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1282
1300
|
const direction = msg.data.stepmode === 1 ? 'up' : 'down';
|
|
1283
1301
|
const payload = {
|
|
1284
1302
|
action: postfixWithEndpointName(`color_hue_step_${direction}`, msg, model),
|
|
@@ -1293,6 +1311,7 @@ const converters = {
|
|
|
1293
1311
|
cluster: 'lightingColorCtrl',
|
|
1294
1312
|
type: ['commandStepSaturation'],
|
|
1295
1313
|
convert: (model, msg, publish, options, meta) => {
|
|
1314
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1296
1315
|
const direction = msg.data.stepmode === 1 ? 'up' : 'down';
|
|
1297
1316
|
const payload = {
|
|
1298
1317
|
action: postfixWithEndpointName(`color_saturation_step_${direction}`, msg, model),
|
|
@@ -1307,6 +1326,7 @@ const converters = {
|
|
|
1307
1326
|
cluster: 'lightingColorCtrl',
|
|
1308
1327
|
type: 'commandColorLoopSet',
|
|
1309
1328
|
convert: (model, msg, publish, options, meta) => {
|
|
1329
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1310
1330
|
const updateFlags = msg.data.updateflags;
|
|
1311
1331
|
const actionLookup = {
|
|
1312
1332
|
0x00: 'deactivate',
|
|
@@ -1336,6 +1356,7 @@ const converters = {
|
|
|
1336
1356
|
cluster: 'lightingColorCtrl',
|
|
1337
1357
|
type: 'commandMoveToColorTemp',
|
|
1338
1358
|
convert: (model, msg, publish, options, meta) => {
|
|
1359
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1339
1360
|
const payload = {
|
|
1340
1361
|
action: postfixWithEndpointName(`color_temperature_move`, msg, model),
|
|
1341
1362
|
action_color_temperature: msg.data.colortemp,
|
|
@@ -1349,6 +1370,7 @@ const converters = {
|
|
|
1349
1370
|
cluster: 'lightingColorCtrl',
|
|
1350
1371
|
type: 'commandMoveToColor',
|
|
1351
1372
|
convert: (model, msg, publish, options, meta) => {
|
|
1373
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1352
1374
|
const payload = {
|
|
1353
1375
|
action: postfixWithEndpointName(`color_move`, msg, model),
|
|
1354
1376
|
action_color: {
|
|
@@ -1365,6 +1387,7 @@ const converters = {
|
|
|
1365
1387
|
cluster: 'lightingColorCtrl',
|
|
1366
1388
|
type: 'commandMoveHue',
|
|
1367
1389
|
convert: (model, msg, publish, options, meta) => {
|
|
1390
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1368
1391
|
const movestop = msg.data.movemode == 1 ? 'move' : 'stop';
|
|
1369
1392
|
const action = postfixWithEndpointName(`hue_${movestop}`, msg, model);
|
|
1370
1393
|
const payload = {action, action_rate: msg.data.rate};
|
|
@@ -1376,6 +1399,7 @@ const converters = {
|
|
|
1376
1399
|
cluster: 'lightingColorCtrl',
|
|
1377
1400
|
type: 'commandMoveToSaturation',
|
|
1378
1401
|
convert: (model, msg, publish, options, meta) => {
|
|
1402
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1379
1403
|
const payload = {
|
|
1380
1404
|
action: postfixWithEndpointName('move_to_saturation', msg, model),
|
|
1381
1405
|
action_saturation: msg.data.saturation,
|
|
@@ -1389,6 +1413,7 @@ const converters = {
|
|
|
1389
1413
|
cluster: 'lightingColorCtrl',
|
|
1390
1414
|
type: 'commandMoveToHue',
|
|
1391
1415
|
convert: (model, msg, publish, options, meta) => {
|
|
1416
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1392
1417
|
const payload = {
|
|
1393
1418
|
action: postfixWithEndpointName(`move_to_hue`, msg, model),
|
|
1394
1419
|
action_hue: msg.data.hue,
|
|
@@ -1413,6 +1438,7 @@ const converters = {
|
|
|
1413
1438
|
cluster: 'genOnOff',
|
|
1414
1439
|
type: 'commandOn',
|
|
1415
1440
|
convert: (model, msg, publish, options, meta) => {
|
|
1441
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1416
1442
|
const property = postfixWithEndpointName('state', msg, model);
|
|
1417
1443
|
return {[property]: 'ON'};
|
|
1418
1444
|
},
|
|
@@ -1421,6 +1447,7 @@ const converters = {
|
|
|
1421
1447
|
cluster: 'genOnOff',
|
|
1422
1448
|
type: 'commandOff',
|
|
1423
1449
|
convert: (model, msg, publish, options, meta) => {
|
|
1450
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
1424
1451
|
const property = postfixWithEndpointName('state', msg, model);
|
|
1425
1452
|
return {[property]: 'OFF'};
|
|
1426
1453
|
},
|
|
@@ -1771,7 +1798,7 @@ const converters = {
|
|
|
1771
1798
|
},
|
|
1772
1799
|
nous_lcd_temperature_humidity_sensor: {
|
|
1773
1800
|
cluster: 'manuSpecificTuya',
|
|
1774
|
-
type: ['
|
|
1801
|
+
type: ['commandDataResponse'],
|
|
1775
1802
|
options: [exposes.options.precision('temperature'), exposes.options.calibration('temperature'),
|
|
1776
1803
|
exposes.options.precision('humidity'), exposes.options.calibration('humidity')],
|
|
1777
1804
|
convert: (model, msg, publish, options, meta) => {
|
|
@@ -4317,6 +4344,7 @@ const converters = {
|
|
|
4317
4344
|
cluster: 'genScenes',
|
|
4318
4345
|
type: 'commandTradfriArrowSingle',
|
|
4319
4346
|
convert: (model, msg, publish, options, meta) => {
|
|
4347
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
4320
4348
|
if (msg.data.value === 2) {
|
|
4321
4349
|
// This is send on toggle hold, ignore it as a toggle_hold is already handled above.
|
|
4322
4350
|
return;
|
|
@@ -4330,6 +4358,7 @@ const converters = {
|
|
|
4330
4358
|
cluster: 'genScenes',
|
|
4331
4359
|
type: 'commandTradfriArrowHold',
|
|
4332
4360
|
convert: (model, msg, publish, options, meta) => {
|
|
4361
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
4333
4362
|
const direction = msg.data.value === 3329 ? 'left' : 'right';
|
|
4334
4363
|
globalStore.putValue(msg.endpoint, 'direction', direction);
|
|
4335
4364
|
return {action: `arrow_${direction}_hold`};
|
|
@@ -4340,6 +4369,7 @@ const converters = {
|
|
|
4340
4369
|
type: 'commandTradfriArrowRelease',
|
|
4341
4370
|
options: [exposes.options.legacy()],
|
|
4342
4371
|
convert: (model, msg, publish, options, meta) => {
|
|
4372
|
+
if (hasAlreadyProcessedMessage(msg)) return;
|
|
4343
4373
|
const direction = globalStore.getValue(msg.endpoint, 'direction');
|
|
4344
4374
|
if (direction) {
|
|
4345
4375
|
globalStore.clearValue(msg.endpoint, 'direction');
|
package/devices/acova.js
CHANGED
|
@@ -28,6 +28,7 @@ module.exports = [{
|
|
|
28
28
|
const endpoint = device.getEndpoint(1);
|
|
29
29
|
await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'hvacThermostat']);
|
|
30
30
|
await reporting.thermostatTemperature(endpoint);
|
|
31
|
+
await reporting.thermostatRunningState(endpoint);
|
|
31
32
|
await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
|
|
32
33
|
await reporting.thermostatUnoccupiedHeatingSetpoint(endpoint);
|
|
33
34
|
},
|
package/devices/ikea.js
CHANGED
|
@@ -443,27 +443,21 @@ module.exports = [
|
|
|
443
443
|
model: 'ICPSHC24-10EU-IL-1',
|
|
444
444
|
vendor: 'IKEA',
|
|
445
445
|
description: 'TRADFRI driver for wireless control (10 watt)',
|
|
446
|
-
extend:
|
|
447
|
-
ota: ota.tradfri,
|
|
448
|
-
onEvent: bulbOnEvent,
|
|
446
|
+
extend: tradfriExtend.light_onoff_brightness(),
|
|
449
447
|
},
|
|
450
448
|
{
|
|
451
449
|
zigbeeModel: ['TRADFRI transformer 30W', 'TRADFRI Driver 30W'],
|
|
452
450
|
model: 'ICPSHC24-30EU-IL-1',
|
|
453
451
|
vendor: 'IKEA',
|
|
454
452
|
description: 'TRADFRI driver for wireless control (30 watt)',
|
|
455
|
-
extend:
|
|
456
|
-
ota: ota.tradfri,
|
|
457
|
-
onEvent: bulbOnEvent,
|
|
453
|
+
extend: tradfriExtend.light_onoff_brightness(),
|
|
458
454
|
},
|
|
459
455
|
{
|
|
460
456
|
zigbeeModel: ['SILVERGLANS IP44 LED driver'],
|
|
461
457
|
model: 'ICPSHC24-30-IL44-1',
|
|
462
458
|
vendor: 'IKEA',
|
|
463
459
|
description: 'SILVERGLANS IP44 LED driver for wireless control (30 watt)',
|
|
464
|
-
extend:
|
|
465
|
-
ota: ota.tradfri,
|
|
466
|
-
onEvent: bulbOnEvent,
|
|
460
|
+
extend: tradfriExtend.light_onoff_brightness(),
|
|
467
461
|
},
|
|
468
462
|
{
|
|
469
463
|
zigbeeModel: ['FLOALT panel WS 30x30'],
|
package/devices/neo.js
CHANGED
|
@@ -7,7 +7,8 @@ const tuya = require('../lib/tuya');
|
|
|
7
7
|
|
|
8
8
|
module.exports = [
|
|
9
9
|
{
|
|
10
|
-
fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_d0yu2xgi'}
|
|
10
|
+
fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_d0yu2xgi'},
|
|
11
|
+
{modelID: 'TS0601', manufacturerName: '_TZE200_t1blo2bj'}],
|
|
11
12
|
zigbeeModel: ['0yu2xgi'],
|
|
12
13
|
model: 'NAS-AB02B0',
|
|
13
14
|
vendor: 'Neo',
|
package/devices/philips.js
CHANGED
|
@@ -1525,6 +1525,15 @@ module.exports = [
|
|
|
1525
1525
|
extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
|
|
1526
1526
|
ota: ota.zigbeeOTA,
|
|
1527
1527
|
},
|
|
1528
|
+
{
|
|
1529
|
+
zigbeeModel: ['915005986901'],
|
|
1530
|
+
model: '915005986901',
|
|
1531
|
+
vendor: 'Philips',
|
|
1532
|
+
description: 'Hue White and color ambiance Gradient Signe table lamp (white)',
|
|
1533
|
+
meta: {turnsOffAtBrightness1: true},
|
|
1534
|
+
extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
|
|
1535
|
+
ota: ota.zigbeeOTA,
|
|
1536
|
+
},
|
|
1528
1537
|
{
|
|
1529
1538
|
zigbeeModel: ['5060730P7_01', '5060730P7_02', '5060730P7_03', '5060730P7_04', '5060730P7_05'],
|
|
1530
1539
|
model: '5060730P7',
|
|
@@ -1724,7 +1733,7 @@ module.exports = [
|
|
|
1724
1733
|
ota: ota.zigbeeOTA,
|
|
1725
1734
|
},
|
|
1726
1735
|
{
|
|
1727
|
-
zigbeeModel: ['RDM001'],
|
|
1736
|
+
zigbeeModel: ['RDM001', '9290030171'],
|
|
1728
1737
|
model: '929003017102',
|
|
1729
1738
|
vendor: 'Philips',
|
|
1730
1739
|
description: 'Hue wall switch module',
|
|
@@ -1748,7 +1757,8 @@ module.exports = [
|
|
|
1748
1757
|
fromZigbee: [fz.ignore_command_on, fz.ignore_command_off, fz.ignore_command_step, fz.ignore_command_stop,
|
|
1749
1758
|
fz.legacy.hue_dimmer_switch, fz.battery],
|
|
1750
1759
|
exposes: [e.battery(), e.action(['on-press', 'on-hold', 'on-hold-release', 'up-press', 'up-hold', 'up-hold-release',
|
|
1751
|
-
'down-press', 'down-hold', 'down-hold-release', 'off-press', 'off-hold', 'off-hold-release'])
|
|
1760
|
+
'down-press', 'down-hold', 'down-hold-release', 'off-press', 'off-hold', 'off-hold-release']),
|
|
1761
|
+
exposes.numeric('action_duration', ea.STATE).withUnit('second')],
|
|
1752
1762
|
toZigbee: [],
|
|
1753
1763
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1754
1764
|
const endpoint1 = device.getEndpoint(1);
|
|
@@ -86,6 +86,20 @@ module.exports = [
|
|
|
86
86
|
exposes: [e.contact(), e.battery_low(), e.tamper()],
|
|
87
87
|
ota: ota.salus,
|
|
88
88
|
},
|
|
89
|
+
{
|
|
90
|
+
zigbeeModel: ['SS909ZB'],
|
|
91
|
+
model: 'PS600',
|
|
92
|
+
vendor: 'Salus Controls',
|
|
93
|
+
description: 'Pipe temperature sensor',
|
|
94
|
+
fromZigbee: [fz.temperature],
|
|
95
|
+
toZigbee: [],
|
|
96
|
+
exposes: [e.temperature()],
|
|
97
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
98
|
+
const endpoint = device.getEndpoint(9);
|
|
99
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['msTemperatureMeasurement']);
|
|
100
|
+
},
|
|
101
|
+
ota: ota.salus,
|
|
102
|
+
},
|
|
89
103
|
{
|
|
90
104
|
zigbeeModel: ['RE600'],
|
|
91
105
|
model: 'RE600',
|
|
@@ -8,6 +8,21 @@ const e = exposes.presets;
|
|
|
8
8
|
const ea = exposes.access;
|
|
9
9
|
|
|
10
10
|
module.exports = [
|
|
11
|
+
{
|
|
12
|
+
zigbeeModel: ['PUCK/SHUTTER/1'],
|
|
13
|
+
model: 'CCT5015-0001',
|
|
14
|
+
vendor: 'Schneider Electric',
|
|
15
|
+
description: 'Roller shutter module',
|
|
16
|
+
fromZigbee: [fz.cover_position_tilt],
|
|
17
|
+
toZigbee: [tz.cover_position_tilt, tz.cover_state],
|
|
18
|
+
exposes: [e.cover_position()],
|
|
19
|
+
meta: {coverInverted: true},
|
|
20
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
21
|
+
const endpoint = device.getEndpoint(5);
|
|
22
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['closuresWindowCovering']);
|
|
23
|
+
await reporting.currentPositionLiftPercentage(endpoint);
|
|
24
|
+
},
|
|
25
|
+
},
|
|
11
26
|
{
|
|
12
27
|
zigbeeModel: ['NHPB/SHUTTER/1'],
|
|
13
28
|
model: 'S520567',
|
package/devices/tuya.js
CHANGED
|
@@ -11,7 +11,7 @@ const ea = exposes.access;
|
|
|
11
11
|
|
|
12
12
|
const TS011Fplugs = ['_TZ3000_5f43h46b', '_TZ3000_cphmq0q7', '_TZ3000_dpo1ysak', '_TZ3000_ew3ldmgx', '_TZ3000_gjnozsaz',
|
|
13
13
|
'_TZ3000_jvzvulen', '_TZ3000_mraovvmm', '_TZ3000_nfnmi125', '_TZ3000_ps3dmato', '_TZ3000_w0qqde0g', '_TZ3000_u5u4cakc',
|
|
14
|
-
'_TZ3000_rdtixbnu'];
|
|
14
|
+
'_TZ3000_rdtixbnu', '_TZ3000_typdpbpg', '_TZ3000_v1pdxuqq'];
|
|
15
15
|
|
|
16
16
|
module.exports = [
|
|
17
17
|
{
|
|
@@ -175,6 +175,7 @@ module.exports = [
|
|
|
175
175
|
{modelID: 'TS0202', manufacturerName: '_TYZB01_dl7cejts'},
|
|
176
176
|
{modelID: 'TS0202', manufacturerName: '_TYZB01_qjqgmqxr'},
|
|
177
177
|
{modelID: 'TS0202', manufacturerName: '_TZ3000_mmtwjmaq'},
|
|
178
|
+
{modelID: 'TS0202', manufacturerName: '_TZ3000_kmh5qpmb'},
|
|
178
179
|
{modelID: 'TS0202', manufacturerName: '_TZ3000_mcxw5ehu'},
|
|
179
180
|
{modelID: 'TS0202', manufacturerName: '_TZ3000_msl6wxk9'},
|
|
180
181
|
{modelID: 'TS0202', manufacturerName: '_TYZB01_hqbdru35'},
|
|
@@ -570,6 +571,13 @@ module.exports = [
|
|
|
570
571
|
exposes: [e.battery(), e.action(['1_single', '1_double', '1_hold', '2_single', '2_double', '2_hold',
|
|
571
572
|
'3_single', '3_double', '3_hold', '4_single', '4_double', '4_hold'])],
|
|
572
573
|
toZigbee: [],
|
|
574
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
575
|
+
const endpoint = device.getEndpoint(1);
|
|
576
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
|
|
577
|
+
try {
|
|
578
|
+
await reporting.batteryPercentageRemaining(endpoint);
|
|
579
|
+
} catch (error) {/* Fails for some*/}
|
|
580
|
+
},
|
|
573
581
|
},
|
|
574
582
|
{
|
|
575
583
|
fingerprint: [{modelID: 'TS004F', manufacturerName: '_TZ3000_xabckq1v'}],
|
package/devices/xiaomi.js
CHANGED
|
@@ -1724,7 +1724,7 @@ module.exports = [
|
|
|
1724
1724
|
model: 'MCCGQ12LM',
|
|
1725
1725
|
vendor: 'Xiaomi',
|
|
1726
1726
|
description: 'Aqara T1 door & window contact sensor',
|
|
1727
|
-
fromZigbee: [fz.
|
|
1727
|
+
fromZigbee: [fz.xiaomi_contact, fz.battery],
|
|
1728
1728
|
toZigbee: [],
|
|
1729
1729
|
meta: {battery: {voltageToPercentage: '3V_2100'}},
|
|
1730
1730
|
exposes: [e.contact(), e.battery(), e.battery_voltage()],
|
package/devices/zemismart.js
CHANGED
|
@@ -4,6 +4,21 @@ const tz = require('../converters/toZigbee');
|
|
|
4
4
|
const reporting = require('../lib/reporting');
|
|
5
5
|
const extend = require('../lib/extend');
|
|
6
6
|
const e = exposes.presets;
|
|
7
|
+
const tuya = require('../lib/tuya');
|
|
8
|
+
|
|
9
|
+
const fzLocal = {
|
|
10
|
+
ZMRM02: {
|
|
11
|
+
cluster: 'manuSpecificTuya',
|
|
12
|
+
type: ['commandGetData', 'commandSetDataResponse'],
|
|
13
|
+
convert: (model, msg, publish, options, meta) => {
|
|
14
|
+
const button = msg.data.dp;
|
|
15
|
+
const actionValue = tuya.getDataValue(msg.data.datatype, msg.data.data);
|
|
16
|
+
const lookup = {0: 'single', 1: 'double', 2: 'hold'};
|
|
17
|
+
const action = lookup[actionValue];
|
|
18
|
+
return {action: `button_${button}_${action}`};
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
};
|
|
7
22
|
|
|
8
23
|
module.exports = [
|
|
9
24
|
{
|
|
@@ -66,4 +81,20 @@ module.exports = [
|
|
|
66
81
|
await reporting.onOff(endpoint);
|
|
67
82
|
},
|
|
68
83
|
},
|
|
84
|
+
{
|
|
85
|
+
fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_zqtiam4u'}],
|
|
86
|
+
model: 'ZM-RM02',
|
|
87
|
+
vendor: 'Zemismart',
|
|
88
|
+
description: 'Smart 6 key scene switch',
|
|
89
|
+
fromZigbee: [fzLocal.ZMRM02],
|
|
90
|
+
toZigbee: [],
|
|
91
|
+
onEvent: tuya.onEventSetTime,
|
|
92
|
+
exposes: [e.battery(), e.action([
|
|
93
|
+
'button_1_hold', 'button_1_single', 'button_1_double',
|
|
94
|
+
'button_2_hold', 'button_2_single', 'button_2_double',
|
|
95
|
+
'button_3_hold', 'button_3_single', 'button_3_double',
|
|
96
|
+
'button_4_hold', 'button_4_single', 'button_4_double',
|
|
97
|
+
'button_5_hold', 'button_5_single', 'button_5_double',
|
|
98
|
+
'button_6_hold', 'button_6_single', 'button_6_double'])],
|
|
99
|
+
},
|
|
69
100
|
];
|
package/index.js
CHANGED
|
@@ -46,7 +46,6 @@ const converterRequiredFields = {
|
|
|
46
46
|
description: 'String',
|
|
47
47
|
fromZigbee: 'Array',
|
|
48
48
|
toZigbee: 'Array',
|
|
49
|
-
exposes: 'Array',
|
|
50
49
|
};
|
|
51
50
|
|
|
52
51
|
function validateDefinition(definition) {
|
|
@@ -56,6 +55,7 @@ function validateDefinition(definition) {
|
|
|
56
55
|
const msg = `Converter field ${field} expected type doenst match to ${definition[field]}`;
|
|
57
56
|
assert.strictEqual(definition[field].constructor.name, expectedType, msg);
|
|
58
57
|
}
|
|
58
|
+
assert.ok(Array.isArray(definition.exposes) || typeof definition.exposes === 'function', 'Exposes incorrect');
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
function addDefinition(definition) {
|
|
@@ -77,7 +77,7 @@ function addDefinition(definition) {
|
|
|
77
77
|
|
|
78
78
|
definition.toZigbee.push(tz.scene_store, tz.scene_recall, tz.scene_add, tz.scene_remove, tz.scene_remove_all, tz.read, tz.write);
|
|
79
79
|
|
|
80
|
-
if (definition.exposes) {
|
|
80
|
+
if (definition.exposes && Array.isArray(definition.exposes)) {
|
|
81
81
|
definition.exposes = definition.exposes.concat([exposes.presets.linkquality()]);
|
|
82
82
|
}
|
|
83
83
|
|
package/lib/exposes.js
CHANGED
|
@@ -516,7 +516,7 @@ module.exports = {
|
|
|
516
516
|
carbon_monoxide: () => new Binary('carbon_monoxide', access.STATE, true, false).withDescription('Indicates if CO (carbon monoxide) is detected'),
|
|
517
517
|
child_lock: () => new Lock().withState('child_lock', 'LOCK', 'UNLOCK', 'Enables/disables physical input on the device', access.STATE_SET),
|
|
518
518
|
co2: () => new Numeric('co2', access.STATE).withUnit('ppm').withDescription('The measured CO2 (carbon dioxide) value'),
|
|
519
|
-
comfort_temperature: () => new Numeric('comfort_temperature', access.STATE_SET).withUnit('°C').withDescription('Comfort temperature').withValueMin(
|
|
519
|
+
comfort_temperature: () => new Numeric('comfort_temperature', access.STATE_SET).withUnit('°C').withDescription('Comfort temperature').withValueMin(0).withValueMax(30),
|
|
520
520
|
consumer_connected: () => new Binary('consumer_connected', access.STATE, true, false).withDescription('Indicates whether a plug is physically attached. Device does not have to pull power or even be connected electrically (state of this binary switch can be ON even if main power switch is OFF)'),
|
|
521
521
|
contact: () => new Binary('contact', access.STATE, false, true).withDescription('Indicates if the contact is closed (= true) or open (= false)'),
|
|
522
522
|
cover_position: () => new Cover().withPosition(),
|
|
@@ -531,7 +531,7 @@ module.exports = {
|
|
|
531
531
|
device_temperature: () => new Numeric('device_temperature', access.STATE).withUnit('°C').withDescription('Temperature of the device'),
|
|
532
532
|
eco2: () => new Numeric('eco2', access.STATE).withUnit('ppm').withDescription('Measured eCO2 value'),
|
|
533
533
|
eco_mode: () => new Binary('eco_mode', access.STATE_SET, 'ON', 'OFF').withDescription('ECO mode (energy saving mode)'),
|
|
534
|
-
eco_temperature: () => new Numeric('eco_temperature', access.STATE_SET).withUnit('°C').withDescription('Eco temperature').withValueMin(
|
|
534
|
+
eco_temperature: () => new Numeric('eco_temperature', access.STATE_SET).withUnit('°C').withDescription('Eco temperature').withValueMin(0).withValueMax(35),
|
|
535
535
|
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)'),
|
|
536
536
|
energy: () => new Numeric('energy', access.STATE).withUnit('kWh').withDescription('Sum of consumed energy'),
|
|
537
537
|
fan: () => new Fan(),
|
|
@@ -539,7 +539,7 @@ module.exports = {
|
|
|
539
539
|
formaldehyd: () => new Numeric('formaldehyd', access.STATE).withDescription('The measured formaldehyd value'),
|
|
540
540
|
gas: () => new Binary('gas', access.STATE, true, false).withDescription('Indicates whether the device detected gas'),
|
|
541
541
|
hcho: () => new Numeric('hcho', access.STATE).withUnit('mg/m³').withDescription('Measured Hcho value'),
|
|
542
|
-
holiday_temperature: () => new Numeric('holiday_temperature', access.STATE_SET).withUnit('°C').withDescription('Holiday temperature').withValueMin(
|
|
542
|
+
holiday_temperature: () => new Numeric('holiday_temperature', access.STATE_SET).withUnit('°C').withDescription('Holiday temperature').withValueMin(0).withValueMax(30),
|
|
543
543
|
humidity: () => new Numeric('humidity', access.STATE).withUnit('%').withDescription('Measured relative humidity'),
|
|
544
544
|
illuminance: () => new Numeric('illuminance', access.STATE).withDescription('Raw measured illuminance'),
|
|
545
545
|
illuminance_lux: () => new Numeric('illuminance_lux', access.STATE).withUnit('lx').withDescription('Measured illuminance in lux'),
|
|
@@ -557,15 +557,15 @@ module.exports = {
|
|
|
557
557
|
linkquality: () => new Numeric('linkquality', access.STATE).withUnit('lqi').withDescription('Link quality (signal strength)').withValueMin(0).withValueMax(255),
|
|
558
558
|
local_temperature: () => new Numeric('local_temperature', access.STATE_GET).withUnit('°C').withDescription('Current temperature measured on the device'),
|
|
559
559
|
lock: () => new Lock().withState('state', 'LOCK', 'UNLOCK', 'State of the lock').withLockState('lock_state', 'Actual state of the lock'),
|
|
560
|
-
max_temperature: () => new Numeric('max_temperature', access.STATE_SET).withUnit('°C').withDescription('Maximum temperature').withValueMin(
|
|
561
|
-
max_temperature_limit: () => new Numeric('max_temperature_limit', access.STATE_SET).withUnit('°C').withDescription('Maximum temperature limit').withValueMin(
|
|
562
|
-
min_temperature: () => new Numeric('min_temperature', access.STATE_SET).withUnit('°C').withDescription('Minimum temperature').withValueMin(
|
|
560
|
+
max_temperature: () => new Numeric('max_temperature', access.STATE_SET).withUnit('°C').withDescription('Maximum temperature').withValueMin(15).withValueMax(35),
|
|
561
|
+
max_temperature_limit: () => new Numeric('max_temperature_limit', access.STATE_SET).withUnit('°C').withDescription('Maximum temperature limit').withValueMin(0).withValueMax(35),
|
|
562
|
+
min_temperature: () => new Numeric('min_temperature', access.STATE_SET).withUnit('°C').withDescription('Minimum temperature').withValueMin(5).withValueMax(15),
|
|
563
563
|
noise: () => new Numeric('noise', access.STATE).withUnit('dBA').withDescription('The measured noise value'),
|
|
564
564
|
noise_detected: () => new Binary('noise_detected', access.STATE, true, false).withDescription('Indicates whether the device detected noise'),
|
|
565
565
|
occupancy: () => new Binary('occupancy', access.STATE, true, false).withDescription('Indicates whether the device detected occupancy'),
|
|
566
566
|
occupancy_level: () => new Numeric('occupancy_level', access.STATE).withDescription('The measured occupancy value'),
|
|
567
567
|
open_window: () => new Binary('open_window', access.STATE_SET, 'ON', 'OFF').withDescription('Enables/disables the status on the device'),
|
|
568
|
-
open_window_temperature: () => new Numeric('open_window_temperature', access.STATE_SET).withUnit('°C').withDescription('Open window temperature').withValueMin(
|
|
568
|
+
open_window_temperature: () => new Numeric('open_window_temperature', access.STATE_SET).withUnit('°C').withDescription('Open window temperature').withValueMin(0).withValueMax(35),
|
|
569
569
|
pm10: () => new Numeric('pm10', access.STATE).withUnit('µg/m³').withDescription('Measured PM10 (particulate matter) concentration'),
|
|
570
570
|
pm25: () => new Numeric('pm25', access.STATE).withUnit('µg/m³').withDescription('Measured PM2.5 (particulate matter) concentration'),
|
|
571
571
|
position: () => new Numeric('position', access.STATE).withUnit('%').withDescription('Position'),
|
package/npm-shrinkwrap.json
CHANGED