zigbee-herdsman-converters 14.0.385 → 14.0.389
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 +165 -2
- package/converters/toZigbee.js +122 -5
- package/devices/ikea.js +1 -1
- package/devices/ledvance.js +1 -1
- package/devices/miboxer.js +4 -1
- package/devices/moes.js +21 -0
- package/devices/philips.js +9 -0
- package/devices/tuya.js +30 -5
- package/devices/xiaomi.js +35 -0
- package/devices/zemismart.js +22 -0
- package/lib/ota/common.js +11 -4
- package/lib/tuya.js +62 -0
- package/npm-shrinkwrap.json +386 -402
- package/package.json +2 -2
package/converters/fromZigbee.js
CHANGED
|
@@ -4362,6 +4362,14 @@ const converters = {
|
|
|
4362
4362
|
convert: (model, msg, publis, options, meta) => {
|
|
4363
4363
|
// Don't use in production!
|
|
4364
4364
|
// Used in: https://www.zigbee2mqtt.io/how_tos/how_to_support_new_tuya_devices.html
|
|
4365
|
+
const getType = (datatype) => {
|
|
4366
|
+
const entry = Object.entries(tuya.dataTypes).find(([typeName, typeId]) => typeId === datatype);
|
|
4367
|
+
return (entry ? entry[0] : 'unknown');
|
|
4368
|
+
};
|
|
4369
|
+
const getAllDpIds = (dp) => {
|
|
4370
|
+
const entries = Object.entries(tuya.dataPoints).filter(([dpName, dpId]) => dpId === dp);
|
|
4371
|
+
return entries.map(([dpName, dpId]) => dpName);
|
|
4372
|
+
};
|
|
4365
4373
|
const getHex = (value) => {
|
|
4366
4374
|
let hex = value.toString(16);
|
|
4367
4375
|
if (hex.length < 2) {
|
|
@@ -4372,6 +4380,11 @@ const converters = {
|
|
|
4372
4380
|
const now = Date.now().toString();
|
|
4373
4381
|
let dataStr = '';
|
|
4374
4382
|
for (const [i, dpValue] of msg.data.dpValues.entries()) {
|
|
4383
|
+
const value = tuya.getDataValue(dpValue);
|
|
4384
|
+
meta.logger.info(`zigbee-herdsman-converters:tuya_data_point_dump: Received DP #${
|
|
4385
|
+
dpValue.dp} from ${meta.device.ieeeAddr} with raw data '${JSON.stringify(dpValue)}': type='${msg.type}', datatype='${
|
|
4386
|
+
getType(dpValue.datatype)}', value='${value}', known DP# usage: ${JSON.stringify(getAllDpIds(dpValue.dp))}`);
|
|
4387
|
+
|
|
4375
4388
|
dataStr +=
|
|
4376
4389
|
now + ' ' +
|
|
4377
4390
|
meta.device.ieeeAddr + ' ' +
|
|
@@ -5177,7 +5190,9 @@ const converters = {
|
|
|
5177
5190
|
payload.voltage = value;
|
|
5178
5191
|
payload.battery = batteryVoltageToPercentage(value, '3V_2100');
|
|
5179
5192
|
} else if (index === 3) payload.temperature = calibrateAndPrecisionRoundOptions(value, options, 'temperature'); // 0x03
|
|
5180
|
-
else if (index ===
|
|
5193
|
+
else if (index === 5) {
|
|
5194
|
+
if (['JT-BZ-01AQ/A'].includes(model.model)) payload.power_outage_count = value;
|
|
5195
|
+
} else if (index === 100) {
|
|
5181
5196
|
if (['QBKG19LM', 'QBKG20LM', 'QBKG39LM', 'QBKG41LM', 'QBCZ15LM'].includes(model.model)) {
|
|
5182
5197
|
const mapping = model.model === 'QBCZ15LM' ? 'relay' : 'left';
|
|
5183
5198
|
payload[`state_${mapping}`] = value === 1 ? 'ON' : 'OFF';
|
|
@@ -5198,15 +5213,37 @@ const converters = {
|
|
|
5198
5213
|
} else if (index === 150) payload.voltage = precisionRound(value * 0.1, 1); // 0x96
|
|
5199
5214
|
else if (index === 151) payload.current = precisionRound(value * 0.001, 4); // 0x97
|
|
5200
5215
|
else if (index === 152) payload.power = precisionRound(value, 2); // 0x98
|
|
5216
|
+
else if (index === 159) payload.gas_sensitivity = {1: '15%LEL', 2: '10%LEL'}[value]; // JT-BZ-01AQ/A
|
|
5217
|
+
else if (index === 160) payload.gas = value === 1; // JT-BZ-01AQ/A
|
|
5218
|
+
else if (index === 161) payload.gas_density = value; // JT-BZ-01AQ/A
|
|
5219
|
+
else if (index === 162) payload.test = value === 1; // JT-BZ-01AQ/A
|
|
5220
|
+
else if (index === 163) payload.mute = value === 1; // JT-BZ-01AQ/A
|
|
5221
|
+
else if (index === 164) payload.state = value === 1 ? 'preparation' : 'work'; // JT-BZ-01AQ/A
|
|
5222
|
+
else if (index === 166) payload.linkage_alarm = value === 1; // JT-BZ-01AQ/A
|
|
5201
5223
|
else if (meta.logger) meta.logger.debug(`${model.zigbeeModel}: unknown index ${index} with value ${value}`);
|
|
5202
5224
|
}
|
|
5203
5225
|
}
|
|
5204
5226
|
|
|
5205
5227
|
if (msg.data.hasOwnProperty('0')) payload.detection_period = msg.data['0'];
|
|
5228
|
+
if (msg.data.hasOwnProperty('2')) {
|
|
5229
|
+
if (['JT-BZ-01AQ/A'].includes(model.model)) payload.power_outage_count = msg.data['2'];
|
|
5230
|
+
}
|
|
5206
5231
|
if (msg.data.hasOwnProperty('4')) payload.mode_switch = {4: 'anti_flicker_mode', 1: 'quick_mode'}[msg.data['4']];
|
|
5207
5232
|
if (msg.data.hasOwnProperty('10')) payload.switch_type = {1: 'toggle', 2: 'momentary'}[msg.data['10']];
|
|
5208
5233
|
if (msg.data.hasOwnProperty('258')) payload.detection_interval = msg.data['258'];
|
|
5209
|
-
if (msg.data.hasOwnProperty('268'))
|
|
5234
|
+
if (msg.data.hasOwnProperty('268')) {
|
|
5235
|
+
if (['RTCGQ13LM'].includes(model.model)) {
|
|
5236
|
+
payload.motion_sensitivity = {1: 'low', 2: 'medium', 3: 'high'}[msg.data['268']];
|
|
5237
|
+
} else if (['JT-BZ-01AQ/A'].includes(model.model)) {
|
|
5238
|
+
payload.gas_sensitivity = {1: '15%LEL', 2: '10%LEL'}[msg.data['268']];
|
|
5239
|
+
}
|
|
5240
|
+
}
|
|
5241
|
+
if (msg.data.hasOwnProperty('294')) payload.mute = msg.data['294'] === 1; // JT-BZ-01AQ/A
|
|
5242
|
+
if (msg.data.hasOwnProperty('295')) payload.test = msg.data['295'] === 1; // JT-BZ-01AQ/A
|
|
5243
|
+
if (msg.data.hasOwnProperty('313')) payload.state = msg.data['313'] === 1 ? 'preparation' : 'work'; // JT-BZ-01AQ/A
|
|
5244
|
+
if (msg.data.hasOwnProperty('314')) payload.gas = msg.data['314'] === 1; // JT-BZ-01AQ/A
|
|
5245
|
+
if (msg.data.hasOwnProperty('315')) payload.gas_density = msg.data['315']; // JT-BZ-01AQ/A
|
|
5246
|
+
if (msg.data.hasOwnProperty('331')) payload.linkage_alarm = msg.data['331'] === 1; // JT-BZ-01AQ/A
|
|
5210
5247
|
if (msg.data.hasOwnProperty('512')) {
|
|
5211
5248
|
if (['ZNCZ15LM', 'QBCZ14LM', 'QBCZ15LM'].includes(model.model)) {
|
|
5212
5249
|
payload.button_lock = msg.data['512'] === 1 ? 'OFF' : 'ON';
|
|
@@ -7590,6 +7627,57 @@ const converters = {
|
|
|
7590
7627
|
return result;
|
|
7591
7628
|
},
|
|
7592
7629
|
},
|
|
7630
|
+
tuya_radar_sensor_fall: {
|
|
7631
|
+
cluster: 'manuSpecificTuya',
|
|
7632
|
+
type: ['commandDataResponse', 'commandDataReport'],
|
|
7633
|
+
convert: (model, msg, publish, options, meta) => {
|
|
7634
|
+
const dpValue = tuya.firstDpValue(msg, meta, 'tuya_radar_sensor_fall');
|
|
7635
|
+
const dp = dpValue.dp;
|
|
7636
|
+
const value = tuya.getDataValue(dpValue);
|
|
7637
|
+
let result = null;
|
|
7638
|
+
switch (dp) {
|
|
7639
|
+
case tuya.dataPoints.trsfPresenceState:
|
|
7640
|
+
result = {presence: {0: false, 1: true}[value]};
|
|
7641
|
+
break;
|
|
7642
|
+
case tuya.dataPoints.trsfMotionState:
|
|
7643
|
+
result = {occupancy: {1: false, 2: true}[value]};
|
|
7644
|
+
break;
|
|
7645
|
+
case tuya.dataPoints.trsfMotionSpeed:
|
|
7646
|
+
result = {motion_speed: value};
|
|
7647
|
+
break;
|
|
7648
|
+
case tuya.dataPoints.trsfMotionDirection:
|
|
7649
|
+
result = {motion_direction: tuya.tuyaRadar.motionDirection[value]};
|
|
7650
|
+
break;
|
|
7651
|
+
case tuya.dataPoints.trsfScene:
|
|
7652
|
+
result = {radar_scene: tuya.tuyaRadar.radarScene[value]};
|
|
7653
|
+
break;
|
|
7654
|
+
case tuya.dataPoints.trsfSensitivity:
|
|
7655
|
+
result = {radar_sensitivity: value};
|
|
7656
|
+
break;
|
|
7657
|
+
case tuya.dataPoints.trsfIlluminanceLux:
|
|
7658
|
+
result = {illuminance_lux: value};
|
|
7659
|
+
break;
|
|
7660
|
+
case tuya.dataPoints.trsfTumbleAlarmTime:
|
|
7661
|
+
result = {tumble_alarm_time: value+1};
|
|
7662
|
+
break;
|
|
7663
|
+
case tuya.dataPoints.trsfTumbleSwitch:
|
|
7664
|
+
result = {tumble_switch: {false: 'OFF', true: 'ON'}[value]};
|
|
7665
|
+
break;
|
|
7666
|
+
case tuya.dataPoints.trsfFallDownStatus:
|
|
7667
|
+
result = {fall_down_status: {0: false, 1: true}[value]};
|
|
7668
|
+
break;
|
|
7669
|
+
case tuya.dataPoints.trsfStaticDwellAlarm:
|
|
7670
|
+
result = {static_dwell_alarm: value};
|
|
7671
|
+
break;
|
|
7672
|
+
case tuya.dataPoints.trsfFallSensitivity:
|
|
7673
|
+
result = {fall_sensitivity: value};
|
|
7674
|
+
break;
|
|
7675
|
+
default:
|
|
7676
|
+
meta.logger.warn(`fromZigbee.tuya_radar_sensor_fall: NOT RECOGNIZED DP ${dp} with data ${JSON.stringify(dpValue)}`);
|
|
7677
|
+
}
|
|
7678
|
+
return result;
|
|
7679
|
+
},
|
|
7680
|
+
},
|
|
7593
7681
|
tuya_smart_vibration_sensor: {
|
|
7594
7682
|
cluster: 'manuSpecificTuya',
|
|
7595
7683
|
type: ['commandGetData', 'commandDataResponse', 'raw'],
|
|
@@ -7956,6 +8044,81 @@ const converters = {
|
|
|
7956
8044
|
return {action};
|
|
7957
8045
|
},
|
|
7958
8046
|
},
|
|
8047
|
+
ZMAM02: {
|
|
8048
|
+
cluster: 'manuSpecificTuya',
|
|
8049
|
+
type: ['commandDataResponse', 'commandDataReport', 'commandSetDataresponse'],
|
|
8050
|
+
convert: (model, msg, publish, options, meta) => {
|
|
8051
|
+
const result = {};
|
|
8052
|
+
// let value = tuya.getDataValue(dpValue);
|
|
8053
|
+
// let result = null;
|
|
8054
|
+
for (const dpValue of msg.data.dpValues) {
|
|
8055
|
+
const value = tuya.getDataValue(dpValue);
|
|
8056
|
+
switch (dpValue.dp) {
|
|
8057
|
+
case tuya.dataPoints.AM02Control:
|
|
8058
|
+
result.control = tuya.ZMAM02.AM02Control[value];
|
|
8059
|
+
break;
|
|
8060
|
+
case tuya.dataPoints.AM02PercentControl:
|
|
8061
|
+
result.percent_control = value;
|
|
8062
|
+
break;
|
|
8063
|
+
case tuya.dataPoints.AM02ControlBackMode:
|
|
8064
|
+
result.control_back_mode = tuya.ZMAM02.AM02Direction[value];
|
|
8065
|
+
break;
|
|
8066
|
+
case tuya.dataPoints.AM02MotorWorkingMode:
|
|
8067
|
+
switch (value) {
|
|
8068
|
+
case 0: // continuous 1
|
|
8069
|
+
result.motor_working_mode = 'continuous';
|
|
8070
|
+
break;
|
|
8071
|
+
case 1: // intermittently
|
|
8072
|
+
result.motor_working_mode = 'intermittently';
|
|
8073
|
+
break;
|
|
8074
|
+
default:
|
|
8075
|
+
meta.logger.warn('zigbee-herdsman-converters:ZM_AM_02: ' +
|
|
8076
|
+
`Mode ${value} is not recognized.`);
|
|
8077
|
+
break;
|
|
8078
|
+
}
|
|
8079
|
+
break;
|
|
8080
|
+
case tuya.dataPoints.AM02Border:
|
|
8081
|
+
switch (value) {
|
|
8082
|
+
case 0: // up
|
|
8083
|
+
result.border = 'up';
|
|
8084
|
+
break;
|
|
8085
|
+
case 1: // down
|
|
8086
|
+
result.border = 'down';
|
|
8087
|
+
break;
|
|
8088
|
+
case 2: // down_delete
|
|
8089
|
+
result.border = 'down_delete';
|
|
8090
|
+
break;
|
|
8091
|
+
default:
|
|
8092
|
+
meta.logger.warn('zigbee-herdsman-converters:ZM_AM_02: ' +
|
|
8093
|
+
`Mode ${value} is not recognized.`);
|
|
8094
|
+
break;
|
|
8095
|
+
}
|
|
8096
|
+
break;
|
|
8097
|
+
case tuya.dataPoints.AM02PercentState:
|
|
8098
|
+
result.percent_state = value;
|
|
8099
|
+
break;
|
|
8100
|
+
case tuya.dataPoints.AM02Mode:
|
|
8101
|
+
switch (value) {
|
|
8102
|
+
case 0: // morning
|
|
8103
|
+
result.mode = 'morning';
|
|
8104
|
+
break;
|
|
8105
|
+
case 1: // night
|
|
8106
|
+
result.mode = 'night';
|
|
8107
|
+
break;
|
|
8108
|
+
default:
|
|
8109
|
+
meta.logger.warn('zigbee-herdsman-converters:ZM_AM_02: ' +
|
|
8110
|
+
`Mode ${value} is not recognized.`);
|
|
8111
|
+
break;
|
|
8112
|
+
}
|
|
8113
|
+
break;
|
|
8114
|
+
default:
|
|
8115
|
+
meta.logger.warn(`fromZigbee.Zemismart Shader Konverter (Zm_AM02): NOT RECOGNIZED ` +
|
|
8116
|
+
`DP #${dpValue.dp} with data ${JSON.stringify(dpValue)}`);
|
|
8117
|
+
}
|
|
8118
|
+
}
|
|
8119
|
+
return result;
|
|
8120
|
+
},
|
|
8121
|
+
},
|
|
7959
8122
|
// #endregion
|
|
7960
8123
|
|
|
7961
8124
|
// #region Ignore converters (these message dont need parsing).
|
package/converters/toZigbee.js
CHANGED
|
@@ -1982,7 +1982,7 @@ const converters = {
|
|
|
1982
1982
|
convertSet: async (entity, key, value, meta) => {
|
|
1983
1983
|
const lookup = {'siren_led': 3, 'siren': 2, 'led': 1, 'nothing': 0};
|
|
1984
1984
|
await entity.write('genBasic', {0x400a: {value: lookup[value], type: 32}},
|
|
1985
|
-
{manufacturerCode: 0x1168, disableDefaultResponse: true,
|
|
1985
|
+
{manufacturerCode: 0x1168, disableDefaultResponse: true, sendWhen: 'active'});
|
|
1986
1986
|
return {state: {alert_behaviour: value}};
|
|
1987
1987
|
},
|
|
1988
1988
|
},
|
|
@@ -2419,6 +2419,72 @@ const converters = {
|
|
|
2419
2419
|
await entity.write('ssIasZone', {0xFFF1: {value: 0x03010000, type: 0x23}}, options);
|
|
2420
2420
|
},
|
|
2421
2421
|
},
|
|
2422
|
+
JTBZ01AQA_gas: {
|
|
2423
|
+
key: ['gas'],
|
|
2424
|
+
convertGet: async (entity, key, meta) => {
|
|
2425
|
+
await entity.read('aqaraOpple', [0x013a], manufacturerOptions.xiaomi);
|
|
2426
|
+
},
|
|
2427
|
+
},
|
|
2428
|
+
JTBZ01AQA_gas_density: {
|
|
2429
|
+
key: ['gas_density'],
|
|
2430
|
+
convertGet: async (entity, key, meta) => {
|
|
2431
|
+
await entity.read('aqaraOpple', [0x013b], manufacturerOptions.xiaomi);
|
|
2432
|
+
},
|
|
2433
|
+
},
|
|
2434
|
+
JTBZ01AQA_gas_sensitivity: {
|
|
2435
|
+
key: ['gas_sensitivity'],
|
|
2436
|
+
convertSet: async (entity, key, value, meta) => {
|
|
2437
|
+
value = value.toLowerCase();
|
|
2438
|
+
const lookup = {'15%lel': 1, '10%lel': 2};
|
|
2439
|
+
await entity.write('aqaraOpple', {0x010c: {value: lookup[value], type: 0x20}}, manufacturerOptions.xiaomi);
|
|
2440
|
+
return {state: {gas_sensitivity: value}};
|
|
2441
|
+
},
|
|
2442
|
+
convertGet: async (entity, key, meta) => {
|
|
2443
|
+
await entity.read('aqaraOpple', [0x010c], manufacturerOptions.xiaomi);
|
|
2444
|
+
},
|
|
2445
|
+
},
|
|
2446
|
+
JTBZ01AQA_selftest: {
|
|
2447
|
+
key: ['selftest'],
|
|
2448
|
+
convertSet: async (entity, key, value, meta) => {
|
|
2449
|
+
await entity.write('aqaraOpple', {0x0127: {value: true, type: 0x10}}, manufacturerOptions.xiaomi);
|
|
2450
|
+
},
|
|
2451
|
+
},
|
|
2452
|
+
JTBZ01AQA_mute_buzzer: {
|
|
2453
|
+
key: ['mute_buzzer'],
|
|
2454
|
+
convertSet: async (entity, key, value, meta) => {
|
|
2455
|
+
await entity.write('aqaraOpple', {0x013f: {value: 15360, type: 0x23}}, manufacturerOptions.xiaomi);
|
|
2456
|
+
await entity.write('aqaraOpple', {0x0126: {value: 1, type: 0x20}}, manufacturerOptions.xiaomi);
|
|
2457
|
+
},
|
|
2458
|
+
},
|
|
2459
|
+
JTBZ01AQA_mute: {
|
|
2460
|
+
key: ['mute'],
|
|
2461
|
+
convertGet: async (entity, key, meta) => {
|
|
2462
|
+
await entity.read('aqaraOpple', [0x0126], manufacturerOptions.xiaomi);
|
|
2463
|
+
},
|
|
2464
|
+
},
|
|
2465
|
+
JTBZ01AQA_linkage_alarm: {
|
|
2466
|
+
key: ['linkage_alarm'],
|
|
2467
|
+
convertSet: async (entity, key, value, meta) => {
|
|
2468
|
+
const lookup = {true: 1, false: 0};
|
|
2469
|
+
await entity.write('aqaraOpple', {0x014b: {value: lookup[value], type: 0x20}}, manufacturerOptions.xiaomi);
|
|
2470
|
+
return {state: {linkage_alarm: value}};
|
|
2471
|
+
},
|
|
2472
|
+
convertGet: async (entity, key, meta) => {
|
|
2473
|
+
await entity.read('aqaraOpple', [0x014b], manufacturerOptions.xiaomi);
|
|
2474
|
+
},
|
|
2475
|
+
},
|
|
2476
|
+
JTBZ01AQA_state: {
|
|
2477
|
+
key: ['state'],
|
|
2478
|
+
convertGet: async (entity, key, meta) => {
|
|
2479
|
+
await entity.read('aqaraOpple', [0x0139], manufacturerOptions.xiaomi);
|
|
2480
|
+
},
|
|
2481
|
+
},
|
|
2482
|
+
aqara_power_outage_count: {
|
|
2483
|
+
key: ['power_outage_count'],
|
|
2484
|
+
convertGet: async (entity, key, meta) => {
|
|
2485
|
+
await entity.read('aqaraOpple', [0x0002], manufacturerOptions.xiaomi);
|
|
2486
|
+
},
|
|
2487
|
+
},
|
|
2422
2488
|
LLKZMK11LM_interlock: {
|
|
2423
2489
|
key: ['interlock'],
|
|
2424
2490
|
convertSet: async (entity, key, value, meta) => {
|
|
@@ -6033,7 +6099,7 @@ const converters = {
|
|
|
6033
6099
|
key: ['keypad_lockout'],
|
|
6034
6100
|
convertSet: async (entity, key, value, meta) => {
|
|
6035
6101
|
const keypadLockout = utils.getKey(constants.keypadLockoutMode, value, value, Number);
|
|
6036
|
-
entity.write('hvacUserInterfaceCfg', {keypadLockout}, {
|
|
6102
|
+
entity.write('hvacUserInterfaceCfg', {keypadLockout}, {sendWhen: 'active'});
|
|
6037
6103
|
entity.saveClusterAttributeKeyValue('hvacUserInterfaceCfg', {keypadLockout});
|
|
6038
6104
|
return {state: {keypad_lockout: value}};
|
|
6039
6105
|
},
|
|
@@ -6172,7 +6238,7 @@ const converters = {
|
|
|
6172
6238
|
key: ['calibrate_valve'],
|
|
6173
6239
|
convertSet: async (entity, key, value, meta) => {
|
|
6174
6240
|
await entity.command('hvacThermostat', 'wiserSmartCalibrateValve', {},
|
|
6175
|
-
{srcEndpoint: 11, disableDefaultResponse: true,
|
|
6241
|
+
{srcEndpoint: 11, disableDefaultResponse: true, sendWhen: 'active'});
|
|
6176
6242
|
return {state: {'calibrate_valve': value}};
|
|
6177
6243
|
},
|
|
6178
6244
|
},
|
|
@@ -6194,7 +6260,7 @@ const converters = {
|
|
|
6194
6260
|
key: ['local_temperature_calibration'],
|
|
6195
6261
|
convertSet: (entity, key, value, meta) => {
|
|
6196
6262
|
entity.write('hvacThermostat', {localTemperatureCalibration: Math.round(value * 10)},
|
|
6197
|
-
{srcEndpoint: 11, disableDefaultResponse: true,
|
|
6263
|
+
{srcEndpoint: 11, disableDefaultResponse: true, sendWhen: 'active'});
|
|
6198
6264
|
return {state: {local_temperature_calibration: value}};
|
|
6199
6265
|
},
|
|
6200
6266
|
},
|
|
@@ -6203,7 +6269,7 @@ const converters = {
|
|
|
6203
6269
|
convertSet: async (entity, key, value, meta) => {
|
|
6204
6270
|
const keypadLockout = utils.getKey(constants.keypadLockoutMode, value, value, Number);
|
|
6205
6271
|
await entity.write('hvacUserInterfaceCfg', {keypadLockout},
|
|
6206
|
-
{srcEndpoint: 11, disableDefaultResponse: true,
|
|
6272
|
+
{srcEndpoint: 11, disableDefaultResponse: true, sendWhen: 'active'});
|
|
6207
6273
|
return {state: {keypad_lockout: value}};
|
|
6208
6274
|
},
|
|
6209
6275
|
},
|
|
@@ -6305,6 +6371,30 @@ const converters = {
|
|
|
6305
6371
|
}
|
|
6306
6372
|
},
|
|
6307
6373
|
},
|
|
6374
|
+
tuya_radar_sensor_fall: {
|
|
6375
|
+
key: ['radar_scene', 'radar_sensitivity', 'tumble_alarm_time', 'tumble_switch', 'fall_sensitivity'],
|
|
6376
|
+
convertSet: async (entity, key, value, meta) => {
|
|
6377
|
+
switch (key) {
|
|
6378
|
+
case 'radar_scene':
|
|
6379
|
+
await tuya.sendDataPointEnum(entity, tuya.dataPoints.trsfScene, utils.getKey(tuya.tuyaRadar.radarScene, value));
|
|
6380
|
+
break;
|
|
6381
|
+
case 'radar_sensitivity':
|
|
6382
|
+
await tuya.sendDataPointValue(entity, tuya.dataPoints.trsfSensitivity, value);
|
|
6383
|
+
break;
|
|
6384
|
+
case 'tumble_switch':
|
|
6385
|
+
await tuya.sendDataPointEnum(entity, tuya.dataPoints.trsfTumbleSwitch, {'on': true, 'off': false}[value.toLowerCase()]);
|
|
6386
|
+
break;
|
|
6387
|
+
case 'tumble_alarm_time':
|
|
6388
|
+
await tuya.sendDataPointEnum(entity, tuya.dataPoints.trsfTumbleAlarmTime, value-1);
|
|
6389
|
+
break;
|
|
6390
|
+
case 'fall_sensitivity':
|
|
6391
|
+
await tuya.sendDataPointValue(entity, tuya.dataPoints.trsfFallSensitivity, value);
|
|
6392
|
+
break;
|
|
6393
|
+
default: // Unknown Key
|
|
6394
|
+
meta.logger.warn(`toZigbee.tuya_radar_sensor_fall: Unhandled Key ${key}`);
|
|
6395
|
+
}
|
|
6396
|
+
},
|
|
6397
|
+
},
|
|
6308
6398
|
javis_microwave_sensor: {
|
|
6309
6399
|
key: [
|
|
6310
6400
|
'illuminance_calibration', 'led_enable',
|
|
@@ -6592,6 +6682,33 @@ const converters = {
|
|
|
6592
6682
|
}
|
|
6593
6683
|
},
|
|
6594
6684
|
},
|
|
6685
|
+
ZMAM02: {
|
|
6686
|
+
key: ['control', 'percent_control', 'mode', 'control_back_mode', 'border', 'motor_working_mode'],
|
|
6687
|
+
convertSet: async (entity, key, value, meta) => {
|
|
6688
|
+
switch (key) {
|
|
6689
|
+
case 'control':
|
|
6690
|
+
await tuya.sendDataPointEnum(entity, tuya.dataPoints.AM02Control, utils.getKey(tuya.ZMAM02.AM02Control, value));
|
|
6691
|
+
break;
|
|
6692
|
+
case 'percent_control':
|
|
6693
|
+
await tuya.sendDataPointValue(entity, tuya.dataPoints.AM02PercentState, value);
|
|
6694
|
+
break;
|
|
6695
|
+
case 'mode':
|
|
6696
|
+
await tuya.sendDataPointEnum(entity, tuya.dataPoints.AM02Mode, utils.getKey(tuya.ZMAM02.AM02Mode, value));
|
|
6697
|
+
break;
|
|
6698
|
+
case 'control_back_mode':
|
|
6699
|
+
await tuya.sendDataPointEnum(entity, tuya.dataPoints.AM02ControlBackMode, utils.getKey(tuya.ZMAM02.AM02Direction, value));
|
|
6700
|
+
break;
|
|
6701
|
+
case 'border':
|
|
6702
|
+
await tuya.sendDataPointEnum(entity, tuya.dataPoints.AM02Border, utils.getKey(tuya.ZMAM02.AM02Border, value));
|
|
6703
|
+
break;
|
|
6704
|
+
case 'motor_working_mode':
|
|
6705
|
+
await tuya.sendDataPointEnum(entity, tuya.dataPoints.AM02MotorWorkingMode, utils.getKey(tuya.ZMAM02.AM02MotorMode, value));
|
|
6706
|
+
break;
|
|
6707
|
+
default: // Unknown Key
|
|
6708
|
+
meta.logger.warn(`toZigbee.ZMAM02: Unhandled Key ${key}`);
|
|
6709
|
+
}
|
|
6710
|
+
},
|
|
6711
|
+
},
|
|
6595
6712
|
// #endregion
|
|
6596
6713
|
|
|
6597
6714
|
// #region Ignore converters
|
package/devices/ikea.js
CHANGED
|
@@ -252,7 +252,7 @@ module.exports = [
|
|
|
252
252
|
extend: tradfriExtend.light_onoff_brightness_colortemp(),
|
|
253
253
|
},
|
|
254
254
|
{
|
|
255
|
-
zigbeeModel: ['TRADFRI bulb E27 WS clear 950lm', 'TRADFRI bulb E26 WS clear 950lm'],
|
|
255
|
+
zigbeeModel: ['TRADFRI bulb E27 WS clear 950lm', 'TRADFRI bulb E26 WS clear 950lm', 'TRADFRI bulb E27 WS\uFFFDclear 950lm'],
|
|
256
256
|
model: 'LED1546G12',
|
|
257
257
|
vendor: 'IKEA',
|
|
258
258
|
description: 'TRADFRI LED bulb E26/E27 950 lumen, dimmable, white spectrum, clear',
|
package/devices/ledvance.js
CHANGED
|
@@ -91,7 +91,7 @@ module.exports = [
|
|
|
91
91
|
zigbeeModel: ['LEDVANCE DIM'],
|
|
92
92
|
model: '4058075208421',
|
|
93
93
|
vendor: 'LEDVANCE',
|
|
94
|
-
description: 'SMART+ candle E14
|
|
94
|
+
description: 'SMART+ candle E14 dimmable white',
|
|
95
95
|
extend: extend.ledvance.light_onoff_brightness(),
|
|
96
96
|
ota: ota.ledvance,
|
|
97
97
|
},
|
package/devices/miboxer.js
CHANGED
|
@@ -4,6 +4,7 @@ const tz = require('../converters/toZigbee');
|
|
|
4
4
|
const e = exposes.presets;
|
|
5
5
|
const ea = exposes.access;
|
|
6
6
|
const extend = require('../lib/extend');
|
|
7
|
+
const tuya = require('../lib/tuya');
|
|
7
8
|
|
|
8
9
|
module.exports = [
|
|
9
10
|
{
|
|
@@ -21,11 +22,13 @@ module.exports = [
|
|
|
21
22
|
],
|
|
22
23
|
},
|
|
23
24
|
{
|
|
24
|
-
fingerprint: [{modelID: 'TS0501B', manufacturerName: '_TZ3210_dxroobu3'}
|
|
25
|
+
fingerprint: [{modelID: 'TS0501B', manufacturerName: '_TZ3210_dxroobu3'},
|
|
26
|
+
{modelID: 'TS0501B', manufacturerName: '_TZ3210_dbilpfqk'}],
|
|
25
27
|
model: 'FUT036Z',
|
|
26
28
|
description: 'Single color LED controller',
|
|
27
29
|
vendor: 'Miboxer',
|
|
28
30
|
extend: extend.light_onoff_brightness(),
|
|
31
|
+
onEvent: tuya.onEventSetTime,
|
|
29
32
|
},
|
|
30
33
|
{
|
|
31
34
|
fingerprint: [{modelID: 'TS0502B', manufacturerName: '_TZ3210_frm6149r'}],
|
package/devices/moes.js
CHANGED
|
@@ -9,6 +9,27 @@ const e = exposes.presets;
|
|
|
9
9
|
const ea = exposes.access;
|
|
10
10
|
|
|
11
11
|
module.exports = [
|
|
12
|
+
{
|
|
13
|
+
fingerprint: [{modelID: 'TS011F', manufacturerName: '_TZ3000_cymsnfvf'}],
|
|
14
|
+
model: 'ZP-LZ-FR2U',
|
|
15
|
+
vendor: 'Moes',
|
|
16
|
+
description: 'Zigbee 3.0 dual USB wireless socket plug',
|
|
17
|
+
fromZigbee: [fz.on_off, fz.tuya_switch_power_outage_memory],
|
|
18
|
+
toZigbee: [tz.on_off, tz.tuya_switch_power_outage_memory],
|
|
19
|
+
exposes: [e.switch().withEndpoint('l1'), e.switch().withEndpoint('l2'),
|
|
20
|
+
exposes.enum('power_outage_memory', ea.STATE_SET, ['on', 'off', 'restore'])
|
|
21
|
+
.withDescription('Recover state after power outage')],
|
|
22
|
+
endpoint: (device) => {
|
|
23
|
+
return {'l1': 1, 'l2': 2};
|
|
24
|
+
},
|
|
25
|
+
meta: {multiEndpoint: true},
|
|
26
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
27
|
+
await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
|
|
28
|
+
await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
|
|
29
|
+
await reporting.onOff(device.getEndpoint(1));
|
|
30
|
+
await reporting.onOff(device.getEndpoint(2));
|
|
31
|
+
},
|
|
32
|
+
},
|
|
12
33
|
{
|
|
13
34
|
fingerprint: [{modelID: 'TS0121', manufacturerName: '_TYZB01_iuepbmpv'}, {modelID: 'TS011F', manufacturerName: '_TZ3000_zmy1waw6'},
|
|
14
35
|
{modelID: 'TS011F', manufacturerName: '_TZ3000_bkfe0bab'}],
|
package/devices/philips.js
CHANGED
|
@@ -1543,6 +1543,15 @@ module.exports = [
|
|
|
1543
1543
|
extend: hueExtend.light_onoff_brightness_colortemp_color(),
|
|
1544
1544
|
ota: ota.zigbeeOTA,
|
|
1545
1545
|
},
|
|
1546
|
+
{
|
|
1547
|
+
zigbeeModel: ['LCF003', '4080248P7'],
|
|
1548
|
+
model: '4080248P7',
|
|
1549
|
+
vendor: 'Philips',
|
|
1550
|
+
description: 'Hue Signe floor light',
|
|
1551
|
+
meta: {turnsOffAtBrightness1: true},
|
|
1552
|
+
extend: hueExtend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
|
|
1553
|
+
ota: ota.zigbeeOTA,
|
|
1554
|
+
},
|
|
1546
1555
|
{
|
|
1547
1556
|
zigbeeModel: ['4080248U9'],
|
|
1548
1557
|
model: '4080248U9',
|
package/devices/tuya.js
CHANGED
|
@@ -845,7 +845,6 @@ module.exports = [
|
|
|
845
845
|
{modelID: 'TS0601', manufacturerName: '_TZE200_fzo2pocs'},
|
|
846
846
|
{modelID: 'TS0601', manufacturerName: '_TZE200_5sbebbzs'},
|
|
847
847
|
{modelID: 'TS0601', manufacturerName: '_TZE200_zuz7f94z'},
|
|
848
|
-
{modelID: 'TS0601', manufacturerName: '_TZE200_iossyxra'},
|
|
849
848
|
],
|
|
850
849
|
model: 'TS0601_cover',
|
|
851
850
|
vendor: 'TuYa',
|
|
@@ -1127,7 +1126,6 @@ module.exports = [
|
|
|
1127
1126
|
{
|
|
1128
1127
|
fingerprint: [
|
|
1129
1128
|
{modelID: 'TS011F', manufacturerName: '_TZ3000_hyfvrar3'},
|
|
1130
|
-
{modelID: 'TS011F', manufacturerName: '_TZ3000_cymsnfvf'},
|
|
1131
1129
|
{modelID: 'TS011F', manufacturerName: '_TZ3000_bfn1w0mm'}],
|
|
1132
1130
|
model: 'TS011F_plug_2',
|
|
1133
1131
|
description: 'Smart plug (without power monitoring)',
|
|
@@ -1718,9 +1716,7 @@ module.exports = [
|
|
|
1718
1716
|
],
|
|
1719
1717
|
},
|
|
1720
1718
|
{
|
|
1721
|
-
fingerprint: [
|
|
1722
|
-
{modelID: 'TS0601', manufacturerName: '_TZE200_vrfecyku'},
|
|
1723
|
-
{modelID: 'TS0601', manufacturerName: '_TZE200_lu01t0zl'}],
|
|
1719
|
+
fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_vrfecyku'}],
|
|
1724
1720
|
model: 'MIR-HE200-TY',
|
|
1725
1721
|
vendor: 'TuYa',
|
|
1726
1722
|
description: 'Human presence sensor',
|
|
@@ -1737,6 +1733,35 @@ module.exports = [
|
|
|
1737
1733
|
.withDescription('presets for sensitivity for presence and movement'),
|
|
1738
1734
|
],
|
|
1739
1735
|
},
|
|
1736
|
+
{
|
|
1737
|
+
fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_lu01t0zl'}],
|
|
1738
|
+
model: 'MIR-HE200-TY_fall',
|
|
1739
|
+
vendor: 'TuYa',
|
|
1740
|
+
description: 'Human presence sensor with fall function',
|
|
1741
|
+
fromZigbee: [fz.tuya_radar_sensor_fall],
|
|
1742
|
+
toZigbee: [tz.tuya_radar_sensor_fall],
|
|
1743
|
+
exposes: [
|
|
1744
|
+
e.illuminance_lux(), e.presence(), e.occupancy(),
|
|
1745
|
+
exposes.numeric('motion_speed', ea.STATE).withDescription('Speed of movement'),
|
|
1746
|
+
exposes.enum('motion_direction', ea.STATE, Object.values(tuya.tuyaRadar.motionDirection))
|
|
1747
|
+
.withDescription('direction of movement from the point of view of the radar'),
|
|
1748
|
+
exposes.numeric('radar_sensitivity', ea.STATE_SET).withValueMin(0).withValueMax(10).withValueStep(1)
|
|
1749
|
+
.withDescription('sensitivity of the radar'),
|
|
1750
|
+
exposes.enum('radar_scene', ea.STATE_SET, Object.values(tuya.tuyaRadar.radarScene))
|
|
1751
|
+
.withDescription('presets for sensitivity for presence and movement'),
|
|
1752
|
+
exposes.enum('tumble_switch', ea.STATE_SET, ['ON', 'OFF']).withDescription('Tumble status switch'),
|
|
1753
|
+
exposes.numeric('fall_sensitivity', ea.STATE_SET).withValueMin(1).withValueMax(10).withValueStep(1)
|
|
1754
|
+
.withDescription('fall sensitivity of the radar'),
|
|
1755
|
+
exposes.numeric('tumble_alarm_time', ea.STATE_SET).withValueMin(1).withValueMax(5).withValueStep(1)
|
|
1756
|
+
.withUnit('min').withDescription('tumble alarm time'),
|
|
1757
|
+
exposes.binary('fall_down_status', ea.STATE).withDescription('fall down status'),
|
|
1758
|
+
exposes.text('static_dwell_alarm', ea.STATE).withDescription('static dwell alarm'),
|
|
1759
|
+
],
|
|
1760
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1761
|
+
const endpoint = device.getEndpoint(1);
|
|
1762
|
+
await tuya.sendDataPointEnum(endpoint, tuya.dataPoints.trsfTumbleSwitch, false);
|
|
1763
|
+
},
|
|
1764
|
+
},
|
|
1740
1765
|
{
|
|
1741
1766
|
fingerprint: [{modelID: 'TS004F', manufacturerName: '_TZ3000_pcqjmcud'}],
|
|
1742
1767
|
model: 'YSR-MINI-Z',
|
package/devices/xiaomi.js
CHANGED
|
@@ -1133,6 +1133,41 @@ module.exports = [
|
|
|
1133
1133
|
exposes.numeric('gas_density', ea.STATE), exposes.enum('selftest', ea.SET, ['']),
|
|
1134
1134
|
],
|
|
1135
1135
|
},
|
|
1136
|
+
{
|
|
1137
|
+
zigbeeModel: ['lumi.sensor_gas.acn02'],
|
|
1138
|
+
model: 'JT-BZ-01AQ/A',
|
|
1139
|
+
vendor: 'Xiaomi',
|
|
1140
|
+
description: 'Aqara smart natural gas detector',
|
|
1141
|
+
fromZigbee: [fz.aqara_opple],
|
|
1142
|
+
toZigbee: [tz.JTBZ01AQA_gas, tz.JTBZ01AQA_gas_density, tz.JTBZ01AQA_gas_sensitivity, tz.JTBZ01AQA_selftest,
|
|
1143
|
+
tz.JTBZ01AQA_mute_buzzer, tz.JTBZ01AQA_mute, tz.JTBZ01AQA_linkage_alarm, tz.JTBZ01AQA_state, tz.aqara_power_outage_count],
|
|
1144
|
+
exposes: [e.gas().withAccess(ea.STATE_GET),
|
|
1145
|
+
exposes.numeric('gas_density', ea.STATE_GET).withUnit('%LEL').withDescription('Value of gas concentration'),
|
|
1146
|
+
exposes.enum('gas_sensitivity', ea.ALL, ['10%LEL', '15%LEL']).withDescription('Gas concentration value at which ' +
|
|
1147
|
+
'an alarm is triggered ("10%LEL" is more sensitive than "15%LEL")'),
|
|
1148
|
+
exposes.enum('selftest', ea.SET, ['Test']).withDescription('Starts the self-test process (checking the indicator ' +
|
|
1149
|
+
'light and buzzer work properly)'),
|
|
1150
|
+
exposes.binary('test', ea.STATE, true, false).withDescription('Self-test in progress'),
|
|
1151
|
+
exposes.enum('mute_buzzer', ea.SET, ['Mute']).withDescription('Mute the buzzer for 10 minutes (buzzer cannot be ' +
|
|
1152
|
+
'pre-muted, because this function only works when the alarm is triggered)'),
|
|
1153
|
+
exposes.binary('mute', ea.STATE_GET, true, false).withDescription('Buzzer muted'),
|
|
1154
|
+
exposes.switch().withState('linkage_alarm', true, 'After being turned on, one of the devices triggers the ' +
|
|
1155
|
+
'natural gas leakage alarm, and other devices with linkage turned on', ea.ALL, true, false),
|
|
1156
|
+
exposes.binary('state', ea.STATE_GET, 'preparation', 'work').withDescription('"Preparation" or "work" ' +
|
|
1157
|
+
'(measurement of the gas concentration value and triggering of an alarm are only performed in the "work" state)'),
|
|
1158
|
+
exposes.numeric('power_outage_count', ea.STATE_GET).withDescription('Number of power outages (since last pairing)')],
|
|
1159
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1160
|
+
const endpoint = device.getEndpoint(1);
|
|
1161
|
+
await endpoint.read('aqaraOpple', [0x013a], {manufacturerCode: 0x115f});
|
|
1162
|
+
await endpoint.read('aqaraOpple', [0x013b], {manufacturerCode: 0x115f});
|
|
1163
|
+
await endpoint.read('aqaraOpple', [0x0126], {manufacturerCode: 0x115f});
|
|
1164
|
+
await endpoint.read('aqaraOpple', [0x0139], {manufacturerCode: 0x115f});
|
|
1165
|
+
await endpoint.read('aqaraOpple', [0x010c], {manufacturerCode: 0x115f});
|
|
1166
|
+
await endpoint.read('aqaraOpple', [0x014b], {manufacturerCode: 0x115f});
|
|
1167
|
+
await endpoint.read('aqaraOpple', [0x0002], {manufacturerCode: 0x115f});
|
|
1168
|
+
},
|
|
1169
|
+
ota: ota.zigbeeOTA,
|
|
1170
|
+
},
|
|
1136
1171
|
{
|
|
1137
1172
|
zigbeeModel: ['lumi.lock.v1'],
|
|
1138
1173
|
model: 'A6121',
|
package/devices/zemismart.js
CHANGED
|
@@ -124,4 +124,26 @@ module.exports = [
|
|
|
124
124
|
await reporting.onOff(device.getEndpoint(2));
|
|
125
125
|
},
|
|
126
126
|
},
|
|
127
|
+
{
|
|
128
|
+
fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_iossyxra'}],
|
|
129
|
+
model: 'ZM-AM02',
|
|
130
|
+
vendor: 'Zemismart',
|
|
131
|
+
description: 'Zigbee/RF curtain converter',
|
|
132
|
+
fromZigbee: [fz.ZMAM02],
|
|
133
|
+
toZigbee: [tz.ZMAM02],
|
|
134
|
+
exposes: [exposes.enum('motor_working_mode', ea.STATE_SET, Object.values(tuya.ZMAM02.AM02MotorMode)),
|
|
135
|
+
exposes.enum('control', ea.STATE_SET, Object.values(tuya.ZMAM02.AM02Control)),
|
|
136
|
+
exposes.numeric('percent_state', ea.STATE).withValueMin(0).withValueMax(100).withValueStep(1).withUnit('%'),
|
|
137
|
+
exposes.enum('mode', ea.STATE_SET, Object.values(tuya.ZMAM02.AM02Mode)),
|
|
138
|
+
exposes.enum('control_back_mode', ea.STATE_SET, Object.values(tuya.ZMAM02.AM02Direction)),
|
|
139
|
+
exposes.enum('border', ea.STATE_SET, Object.values(tuya.ZMAM02.AM02Border)),
|
|
140
|
+
// ---------------------------------------------------------------------------------
|
|
141
|
+
// DP exists, but not used at the moment
|
|
142
|
+
// exposes.numeric('percent_control', ea.STATE_SET).withValueMin(0).withValueMax(100).withValueStep(1).withUnit('%'),
|
|
143
|
+
// exposes.enum('work_state', ea.STATE, Object.values(tuya.ZMAM02.AM02WorkState)),
|
|
144
|
+
// exposes.numeric('countdown_left', ea.STATE).withUnit('s'),
|
|
145
|
+
// exposes.numeric('time_total', ea.STATE).withUnit('ms'),
|
|
146
|
+
// exposes.enum('situation_set', ea.STATE, Object.values(tuya.ZMAM02.AM02Situation)),
|
|
147
|
+
],
|
|
148
|
+
},
|
|
127
149
|
];
|
package/lib/ota/common.js
CHANGED
|
@@ -385,11 +385,18 @@ async function updateToLatest(device, logger, onProgress, getNewImage, getImageM
|
|
|
385
385
|
|
|
386
386
|
endpoint.commandResponse('genOta', 'upgradeEndResponse', payload).then(
|
|
387
387
|
() => {
|
|
388
|
-
logger.debug(`Update succeeded, waiting for device
|
|
389
|
-
|
|
390
|
-
|
|
388
|
+
logger.debug(`Update succeeded, waiting for device announce`);
|
|
389
|
+
onProgress(100, null);
|
|
390
|
+
|
|
391
|
+
let timer = null;
|
|
392
|
+
const cb = () => {
|
|
393
|
+
logger.debug('Got device announce or timed out, call resolve');
|
|
394
|
+
clearInterval(timer);
|
|
395
|
+
device.removeListener('deviceAnnounce', cb);
|
|
391
396
|
resolve();
|
|
392
|
-
}
|
|
397
|
+
};
|
|
398
|
+
timer = setTimeout(cb, 120 * 1000); // timeout after 2 minutes
|
|
399
|
+
device.once('deviceAnnounce', cb);
|
|
393
400
|
},
|
|
394
401
|
(e) => {
|
|
395
402
|
const message = `Upgrade end reponse failed (${e.message})`;
|