zigbee-herdsman-converters 14.0.497 → 14.0.500
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 +29 -26
- package/converters/toZigbee.js +22 -6
- package/devices/awox.js +20 -1
- package/devices/danfoss.js +3 -2
- package/devices/fantem.js +17 -3
- package/devices/miboxer.js +25 -0
- package/devices/nue_3a.js +5 -1
- package/devices/philips.js +9 -0
- package/devices/tuya.js +1 -3
- package/devices/xiaomi.js +9 -2
- package/devices/zemismart.js +9 -0
- package/lib/exposes.js +1 -1
- package/lib/tuya.js +7 -0
- package/lib/xiaomi.js +2 -1
- package/package.json +1 -1
package/converters/fromZigbee.js
CHANGED
|
@@ -4294,7 +4294,6 @@ const converters = {
|
|
|
4294
4294
|
const dpValue = tuya.firstDpValue(msg, meta, 'tuya_air_quality');
|
|
4295
4295
|
const dp = dpValue.dp;
|
|
4296
4296
|
const value = tuya.getDataValue(dpValue);
|
|
4297
|
-
const swapPM25CO2 = ['_TZE200_ryfmq5rl', '_TZE200_dwcarsat'];
|
|
4298
4297
|
switch (dp) {
|
|
4299
4298
|
case tuya.dataPoints.tuyaSabTemp:
|
|
4300
4299
|
return {temperature: calibrateAndPrecisionRoundOptions(value / 10, options, 'temperature')};
|
|
@@ -4302,15 +4301,17 @@ const converters = {
|
|
|
4302
4301
|
return {humidity: calibrateAndPrecisionRoundOptions(value / 10, options, 'humidity')};
|
|
4303
4302
|
// DP22: Smart Air Box: Formaldehyd, Smart Air Housekeeper: co2
|
|
4304
4303
|
case tuya.dataPoints.tuyaSabFormaldehyd:
|
|
4305
|
-
if (
|
|
4304
|
+
if (['_TZE200_dwcarsat', '_TZE200_ryfmq5rl'].includes(meta.device.manufacturerName)) {
|
|
4306
4305
|
return {co2: calibrateAndPrecisionRoundOptions(value, options, 'co2')};
|
|
4307
4306
|
} else {
|
|
4308
4307
|
return {formaldehyd: calibrateAndPrecisionRoundOptions(value, options, 'formaldehyd')};
|
|
4309
4308
|
}
|
|
4310
4309
|
// DP2: Smart Air Box: co2, Smart Air Housekeeper: MP25
|
|
4311
4310
|
case tuya.dataPoints.tuyaSabCO2:
|
|
4312
|
-
if (
|
|
4311
|
+
if (meta.device.manufacturerName === '_TZE200_dwcarsat') {
|
|
4313
4312
|
return {pm25: calibrateAndPrecisionRoundOptions(value, options, 'pm25')};
|
|
4313
|
+
} else if (meta.device.manufacturerName === '_TZE200_ryfmq5rl') {
|
|
4314
|
+
return {formaldehyd: calibrateAndPrecisionRoundOptions(value, options, 'formaldehyd')};
|
|
4314
4315
|
} else {
|
|
4315
4316
|
return {co2: calibrateAndPrecisionRoundOptions(value, options, 'co2')};
|
|
4316
4317
|
}
|
|
@@ -4763,7 +4764,7 @@ const converters = {
|
|
|
4763
4764
|
},
|
|
4764
4765
|
tuya_data_point_dump: {
|
|
4765
4766
|
cluster: 'manuSpecificTuya',
|
|
4766
|
-
type: ['commandDataResponse', 'commandDataReport', 'commandActiveStatusReport'],
|
|
4767
|
+
type: ['commandDataResponse', 'commandDataReport', 'commandActiveStatusReport', 'commandActiveStatusReportAlt'],
|
|
4767
4768
|
convert: (model, msg, publis, options, meta) => {
|
|
4768
4769
|
// Don't use in production!
|
|
4769
4770
|
// Used in: https://www.zigbee2mqtt.io/how_tos/how_to_support_new_tuya_devices.html
|
|
@@ -5871,19 +5872,9 @@ const converters = {
|
|
|
5871
5872
|
return result;
|
|
5872
5873
|
},
|
|
5873
5874
|
},
|
|
5874
|
-
xiaomi_curtain_acn002_position: {
|
|
5875
|
-
cluster: 'genAnalogOutput',
|
|
5876
|
-
type: ['attributeReport', 'readResponse'],
|
|
5877
|
-
options: [exposes.options.invert_cover()],
|
|
5878
|
-
convert: (model, msg, publish, options, meta) => {
|
|
5879
|
-
let position = precisionRound(msg.data['presentValue'], 2);
|
|
5880
|
-
position = options.invert_cover ? 100 - position : position;
|
|
5881
|
-
return {position: position};
|
|
5882
|
-
},
|
|
5883
|
-
},
|
|
5884
5875
|
xiaomi_curtain_acn002_status: {
|
|
5885
5876
|
cluster: 'genMultistateOutput',
|
|
5886
|
-
type: ['attributeReport'
|
|
5877
|
+
type: ['attributeReport'],
|
|
5887
5878
|
convert: (model, msg, publish, options, meta) => {
|
|
5888
5879
|
let running = false;
|
|
5889
5880
|
const data = msg.data;
|
|
@@ -7326,22 +7317,34 @@ const converters = {
|
|
|
7326
7317
|
},
|
|
7327
7318
|
ZB006X_settings: {
|
|
7328
7319
|
cluster: 'manuSpecificTuya',
|
|
7329
|
-
type: ['
|
|
7320
|
+
type: ['commandActiveStatusReport', 'commandActiveStatusReportAlt'],
|
|
7330
7321
|
convert: (model, msg, publish, options, meta) => {
|
|
7331
7322
|
const dpValue = tuya.firstDpValue(msg, meta, 'ZB006X_settings');
|
|
7332
7323
|
const dp = dpValue.dp;
|
|
7333
7324
|
const value = tuya.getDataValue(dpValue);
|
|
7334
|
-
|
|
7335
|
-
|
|
7336
|
-
return {
|
|
7337
|
-
|
|
7338
|
-
|
|
7325
|
+
switch (dp) {
|
|
7326
|
+
case tuya.dataPoints.fantemPowerSupplyMode:
|
|
7327
|
+
return {power_supply_mode: {0: 'unknown', 1: 'no_neutral', 2: 'with_neutral'}[value]};
|
|
7328
|
+
case tuya.dataPoints.fantemExtSwitchType:
|
|
7329
|
+
return {ext_switch_type: {0: 'unknown', 1: 'toggle_sw', 2: 'momentary_sw', 3: 'rotary_sw',
|
|
7330
|
+
4: 'auto_config'}[value]};
|
|
7331
|
+
case tuya.dataPoints.fantemLoadDetectionMode:
|
|
7339
7332
|
return {load_detection_mode: {0: 'none', 1: 'first_power_on', 2: 'every_power_on'}[value]};
|
|
7340
|
-
|
|
7341
|
-
|
|
7342
|
-
|
|
7343
|
-
|
|
7344
|
-
|
|
7333
|
+
case tuya.dataPoints.fantemExtSwitchStatus:
|
|
7334
|
+
return {ext_switch_status: value};
|
|
7335
|
+
case tuya.dataPoints.fantemControlMode:
|
|
7336
|
+
return {control_mode: {0: 'ext_switch', 1: 'remote', 2: 'both'}[value]};
|
|
7337
|
+
case 111:
|
|
7338
|
+
// Value 0 is received after each device power-on. No idea what it means.
|
|
7339
|
+
return;
|
|
7340
|
+
case tuya.dataPoints.fantemLoadType:
|
|
7341
|
+
// Not sure if 0 is 'resistive' and 2 is 'resistive_inductive'.
|
|
7342
|
+
// If you see 'unknown', pls. check with Tuya gateway and app and update with label shown in Tuya app.
|
|
7343
|
+
return {load_type: {0: 'unknown', 1: 'resistive_capacitive', 2: 'unknown', 3: 'detecting'}[value]};
|
|
7344
|
+
case tuya.dataPoints.fantemLoadDimmable:
|
|
7345
|
+
return {load_dimmable: {0: 'unknown', 1: 'dimmable', 2: 'not_dimmable'}[value]};
|
|
7346
|
+
default:
|
|
7347
|
+
meta.logger.warn(`fz.ZB006X_settings: Unhandled DP|Value [${dp}|${value}][${JSON.stringify(dpValue)}]`);
|
|
7345
7348
|
}
|
|
7346
7349
|
},
|
|
7347
7350
|
},
|
package/converters/toZigbee.js
CHANGED
|
@@ -792,7 +792,7 @@ const converters = {
|
|
|
792
792
|
},
|
|
793
793
|
},
|
|
794
794
|
light_onoff_brightness: {
|
|
795
|
-
key: ['state', 'brightness', 'brightness_percent'],
|
|
795
|
+
key: ['state', 'brightness', 'brightness_percent', 'on_time'],
|
|
796
796
|
options: [exposes.options.transition()],
|
|
797
797
|
convertSet: async (entity, key, value, meta) => {
|
|
798
798
|
const {message} = meta;
|
|
@@ -2439,6 +2439,20 @@ const converters = {
|
|
|
2439
2439
|
} else {
|
|
2440
2440
|
await entity.command('closuresWindowCovering', 'stop', {}, utils.getOptions(meta.mapped, entity));
|
|
2441
2441
|
}
|
|
2442
|
+
|
|
2443
|
+
if (!['ZNCLDJ11LM', 'ZNJLBL01LM'].includes(meta.mapped.model)) {
|
|
2444
|
+
// The code below is originally added for ZNCLDJ11LM (Koenkk/zigbee2mqtt#4585).
|
|
2445
|
+
// However, in Koenkk/zigbee-herdsman-converters#4039 it was replaced by reading
|
|
2446
|
+
// directly from currentPositionLiftPercentage, so that device is excluded.
|
|
2447
|
+
// For ZNJLBL01LM, in Koenkk/zigbee-herdsman-converters#4163 the position is read
|
|
2448
|
+
// through onEvent each time the motor stops, so it becomes redundant, and the
|
|
2449
|
+
// device is excluded.
|
|
2450
|
+
// The code is left here to avoid breaking compatibility, ideally all devices using
|
|
2451
|
+
// this converter should be tested so the code can be adjusted/deleted.
|
|
2452
|
+
|
|
2453
|
+
// Xiaomi curtain does not send position update on stop, request this.
|
|
2454
|
+
await entity.read('genAnalogOutput', [0x0055]);
|
|
2455
|
+
}
|
|
2442
2456
|
} else {
|
|
2443
2457
|
const lookup = {'open': 100, 'close': 0, 'on': 100, 'off': 0};
|
|
2444
2458
|
|
|
@@ -6495,17 +6509,19 @@ const converters = {
|
|
|
6495
6509
|
convertSet: async (entity, key, value, meta) => {
|
|
6496
6510
|
switch (key) {
|
|
6497
6511
|
case 'ext_switch_type':
|
|
6498
|
-
await tuya.sendDataPointEnum(entity,
|
|
6499
|
-
'momentary_sw': 2, 'rotary_sw': 3, 'auto_config': 4}[value]);
|
|
6512
|
+
await tuya.sendDataPointEnum(entity, tuya.dataPoints.fantemExtSwitchType, {'unknown': 0, 'toggle_sw': 1,
|
|
6513
|
+
'momentary_sw': 2, 'rotary_sw': 3, 'auto_config': 4}[value], 'sendData');
|
|
6500
6514
|
break;
|
|
6501
6515
|
case 'load_detection_mode':
|
|
6502
|
-
await tuya.sendDataPointEnum(entity,
|
|
6516
|
+
await tuya.sendDataPointEnum(entity, tuya.dataPoints.fantemLoadDetectionMode, {'none': 0, 'first_power_on': 1,
|
|
6517
|
+
'every_power_on': 2}[value], 'sendData');
|
|
6503
6518
|
break;
|
|
6504
6519
|
case 'control_mode':
|
|
6505
|
-
await tuya.sendDataPointEnum(entity,
|
|
6520
|
+
await tuya.sendDataPointEnum(entity, tuya.dataPoints.fantemControlMode, {'ext_switch': 0, 'remote': 1,
|
|
6521
|
+
'both': 2}[value], 'sendData');
|
|
6506
6522
|
break;
|
|
6507
6523
|
default: // Unknown key
|
|
6508
|
-
throw new Error(`
|
|
6524
|
+
throw new Error(`tz.ZB006X_settings: Unhandled key ${key}`);
|
|
6509
6525
|
}
|
|
6510
6526
|
},
|
|
6511
6527
|
},
|
package/devices/awox.js
CHANGED
|
@@ -224,11 +224,30 @@ module.exports = [
|
|
|
224
224
|
},
|
|
225
225
|
],
|
|
226
226
|
},
|
|
227
|
+
{
|
|
228
|
+
type: 'Router', manufacturerName: 'AwoX', modelID: 'TLSR82xx', endpoints: [
|
|
229
|
+
{
|
|
230
|
+
ID: 1,
|
|
231
|
+
profileID: 260,
|
|
232
|
+
deviceID: 268,
|
|
233
|
+
inputClusters: [0, 3, 4, 5, 6, 8, 768, 4096, 64599, 10],
|
|
234
|
+
outputClusters: [6],
|
|
235
|
+
},
|
|
236
|
+
{ID: 242, profileID: 41440, deviceID: 97, inputClusters: [], outputClusters: [33]},
|
|
237
|
+
{
|
|
238
|
+
ID: 3,
|
|
239
|
+
profileID: 4751,
|
|
240
|
+
deviceID: 268,
|
|
241
|
+
inputClusters: [65360, 65361],
|
|
242
|
+
outputClusters: [65360, 65361],
|
|
243
|
+
},
|
|
244
|
+
],
|
|
245
|
+
},
|
|
227
246
|
],
|
|
228
247
|
model: '33957',
|
|
229
248
|
vendor: 'AwoX',
|
|
230
249
|
description: 'LED light with color temperature',
|
|
231
|
-
extend: extend.light_onoff_brightness_colortemp(),
|
|
250
|
+
extend: extend.light_onoff_brightness_colortemp({colorTempRange: [153, 370]}),
|
|
232
251
|
},
|
|
233
252
|
{
|
|
234
253
|
fingerprint: [
|
package/devices/danfoss.js
CHANGED
|
@@ -45,7 +45,7 @@ module.exports = [
|
|
|
45
45
|
.withDescription('Whether or not the unit needs warm water. `false` No Heat Request or `true` Heat Request'),
|
|
46
46
|
exposes.enum('setpoint_change_source', ea.STATE, ['manual', 'schedule', 'externally'])
|
|
47
47
|
.withDescription('Values observed are `0` (manual), `1` (schedule) or `2` (externally)'),
|
|
48
|
-
exposes.climate().withSetpoint('occupied_heating_setpoint', 5,
|
|
48
|
+
exposes.climate().withSetpoint('occupied_heating_setpoint', 5, 35, 0.5).withLocalTemperature().withPiHeatingDemand()
|
|
49
49
|
.withSystemMode(['heat']).withRunningState(['idle', 'heat'], ea.STATE),
|
|
50
50
|
exposes.numeric('external_measured_room_sensor', ea.ALL)
|
|
51
51
|
.withDescription('If `radiator_covered` is `true`: Set at maximum 30 minutes interval but not more often than every ' +
|
|
@@ -79,7 +79,8 @@ module.exports = [
|
|
|
79
79
|
.withDescription('Mean radiator load for room calculated by gateway for load balancing purposes (-8000=undefined)')
|
|
80
80
|
.withValueMin(-8000).withValueMax(2000),
|
|
81
81
|
exposes.numeric('load_estimate', ea.STATE_GET)
|
|
82
|
-
.withDescription('Load estimate on this radiator')
|
|
82
|
+
.withDescription('Load estimate on this radiator')
|
|
83
|
+
.withValueMin(-8000).withValueMax(3600),
|
|
83
84
|
exposes.binary('preheat_status', ea.STATE_GET, true, false)
|
|
84
85
|
.withDescription('Specific for pre-heat running in Zigbee Weekly Schedule mode'),
|
|
85
86
|
exposes.enum('adaptation_run_status', ea.STATE_GET, ['none', 'in_progress', 'found', 'lost'])
|
package/devices/fantem.js
CHANGED
|
@@ -5,6 +5,7 @@ const e = exposes.presets;
|
|
|
5
5
|
const ea = exposes.access;
|
|
6
6
|
const extend = require('../lib/extend');
|
|
7
7
|
const reporting = require('../lib/reporting');
|
|
8
|
+
const tuya = require('../lib/tuya');
|
|
8
9
|
|
|
9
10
|
module.exports = [
|
|
10
11
|
{
|
|
@@ -13,21 +14,34 @@ module.exports = [
|
|
|
13
14
|
vendor: 'Fantem',
|
|
14
15
|
description: 'Smart dimmer module without neutral',
|
|
15
16
|
extend: extend.light_onoff_brightness({noConfigure: true}),
|
|
16
|
-
fromZigbee: [...extend.light_onoff_brightness({noConfigure: true}).fromZigbee,
|
|
17
|
-
fz.command_move, fz.command_stop, fz.ZB006X_settings],
|
|
17
|
+
fromZigbee: [...extend.light_onoff_brightness({noConfigure: true}).fromZigbee,
|
|
18
|
+
fz.command_on, fz.command_off, fz.command_move, fz.command_stop, fz.ZB006X_settings],
|
|
18
19
|
toZigbee: [...extend.light_onoff_brightness({noConfigure: true}).toZigbee, tz.ZB006X_settings],
|
|
19
20
|
exposes: [e.light_brightness(),
|
|
20
21
|
e.action(['on', 'off', 'brightness_move_down', 'brightness_move_up', 'brightness_stop']),
|
|
22
|
+
exposes.enum('control_mode', ea.STATE_SET, ['ext_switch', 'remote', 'both']).withDescription('Control mode'),
|
|
21
23
|
exposes.enum('ext_switch_type', ea.STATE_SET, ['unknown', 'toggle_sw', 'momentary_sw', 'rotary_sw', 'auto_config'])
|
|
22
24
|
.withDescription('External switch type'),
|
|
25
|
+
exposes.numeric('ext_switch_status', ea.STATE).withDescription('External switch status')
|
|
26
|
+
.withValueMin(-10000).withValueMax(10000),
|
|
23
27
|
exposes.enum('load_detection_mode', ea.STATE_SET, ['none', 'first_power_on', 'every_power_on'])
|
|
24
28
|
.withDescription('Load detection mode'),
|
|
25
|
-
|
|
29
|
+
// If you see load_type 'unknown', pls. check with Tuya gateway and app and update with label from Tuya app.
|
|
30
|
+
exposes.enum('load_type', ea.STATE, ['unknown', 'resistive_capacitive', 'unknown', 'detecting'])
|
|
31
|
+
.withDescription('Load type'),
|
|
32
|
+
exposes.enum('load_dimmable', ea.STATE, ['unknown', 'dimmable', 'not_dimmable'])
|
|
33
|
+
.withDescription('Load dimmable'),
|
|
34
|
+
exposes.enum('power_supply_mode', ea.STATE, ['unknown', 'no_neutral', 'with_neutral'])
|
|
35
|
+
.withDescription('Power supply mode'),
|
|
26
36
|
],
|
|
27
37
|
meta: {disableActionGroup: true},
|
|
38
|
+
onEvent: tuya.onEventSetLocalTime,
|
|
28
39
|
configure: async (device, coordinatorEndpoint, logger) => {
|
|
29
40
|
await extend.light_onoff_brightness().configure(device, coordinatorEndpoint, logger);
|
|
30
41
|
const endpoint = device.getEndpoint(1);
|
|
42
|
+
// Enables reporting of physical state changes
|
|
43
|
+
// https://github.com/Koenkk/zigbee2mqtt/issues/9057#issuecomment-1007742130
|
|
44
|
+
await endpoint.read('genBasic', ['manufacturerName', 'zclVersion', 'appVersion', 'modelId', 'powerSource', 0xfffe]);
|
|
31
45
|
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
|
|
32
46
|
await reporting.onOff(endpoint);
|
|
33
47
|
},
|
package/devices/miboxer.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const exposes = require('../lib/exposes');
|
|
2
|
+
const fz = require('../converters/fromZigbee');
|
|
2
3
|
const tz = require('../converters/toZigbee');
|
|
3
4
|
const e = exposes.presets;
|
|
4
5
|
const ea = exposes.access;
|
|
@@ -47,4 +48,28 @@ module.exports = [
|
|
|
47
48
|
vendor: 'Miboxer',
|
|
48
49
|
extend: extend.light_onoff_brightness_colortemp_color({disableColorTempStartup: true, colorTempRange: [153, 500]}),
|
|
49
50
|
},
|
|
51
|
+
{
|
|
52
|
+
fingerprint: [{manufacturerName: '_TZ3000_xwh1e22x'}],
|
|
53
|
+
model: 'FUT089Z',
|
|
54
|
+
vendor: 'MiBoxer',
|
|
55
|
+
description: 'RGB+CCT Remote',
|
|
56
|
+
fromZigbee: [fz.battery],
|
|
57
|
+
toZigbee: [],
|
|
58
|
+
exposes: [e.battery(), e.battery_voltage()],
|
|
59
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
60
|
+
const endpoint = device.getEndpoint(1);
|
|
61
|
+
await endpoint.read('genBasic', ['manufacturerName', 'zclVersion', 'appVersion', 'modelId', 'powerSource', 0xfffe]);
|
|
62
|
+
await endpoint.command('genGroups', 'miboxerSetZones', {zones: [
|
|
63
|
+
{zoneNum: 1, groupId: 101},
|
|
64
|
+
{zoneNum: 2, groupId: 102},
|
|
65
|
+
{zoneNum: 3, groupId: 103},
|
|
66
|
+
{zoneNum: 4, groupId: 104},
|
|
67
|
+
{zoneNum: 5, groupId: 105},
|
|
68
|
+
{zoneNum: 6, groupId: 106},
|
|
69
|
+
{zoneNum: 7, groupId: 107},
|
|
70
|
+
{zoneNum: 8, groupId: 108},
|
|
71
|
+
]});
|
|
72
|
+
await endpoint.command('genBasic', 'tuyaSetup', {}, {disableDefaultResponse: true});
|
|
73
|
+
},
|
|
74
|
+
},
|
|
50
75
|
];
|
package/devices/nue_3a.js
CHANGED
|
@@ -137,8 +137,12 @@ module.exports = [
|
|
|
137
137
|
model: 'HGZB-04D / HGZB-4D-UK',
|
|
138
138
|
vendor: 'Nue / 3A',
|
|
139
139
|
description: 'Smart dimmer wall switch',
|
|
140
|
-
extend: extend.light_onoff_brightness({disableEffect: true}),
|
|
140
|
+
extend: extend.light_onoff_brightness({disableEffect: true, noConfigure: true}),
|
|
141
141
|
whiteLabel: [{vendor: 'Sunricher', model: 'SR-ZG9001K8-DIM'}],
|
|
142
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
143
|
+
await extend.light_onoff_brightness().configure(device, coordinatorEndpoint, logger);
|
|
144
|
+
await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
|
|
145
|
+
},
|
|
142
146
|
},
|
|
143
147
|
{
|
|
144
148
|
zigbeeModel: ['FB56+ZSW1HKJ1.7', 'FB56+ZSW1HKJ2.5', 'FB56+ZSW1HKJ2.7'],
|
package/devices/philips.js
CHANGED
|
@@ -108,6 +108,15 @@ module.exports = [
|
|
|
108
108
|
extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
|
|
109
109
|
ota: ota.zigbeeOTA,
|
|
110
110
|
},
|
|
111
|
+
{
|
|
112
|
+
zigbeeModel: ['915005996801', '915005996901'],
|
|
113
|
+
model: '915005996901',
|
|
114
|
+
vendor: 'Philips',
|
|
115
|
+
description: 'Hue white ambiance ceiling light Enrave L with Bluetooth',
|
|
116
|
+
meta: {turnsOffAtBrightness1: true},
|
|
117
|
+
extend: hueExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 454]}),
|
|
118
|
+
ota: ota.zigbeeOTA,
|
|
119
|
+
},
|
|
111
120
|
{
|
|
112
121
|
zigbeeModel: ['915005997001', '915005997101'],
|
|
113
122
|
model: '915005997001',
|
package/devices/tuya.js
CHANGED
|
@@ -167,7 +167,7 @@ module.exports = [
|
|
|
167
167
|
description: 'Air quality sensor',
|
|
168
168
|
fromZigbee: [fz.tuya_air_quality],
|
|
169
169
|
toZigbee: [],
|
|
170
|
-
exposes: [e.temperature(), e.humidity(), e.co2(), e.voc(), e.formaldehyd()],
|
|
170
|
+
exposes: [e.temperature(), e.humidity(), e.co2(), e.voc().withUnit('ppm'), e.formaldehyd()],
|
|
171
171
|
},
|
|
172
172
|
{
|
|
173
173
|
fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_dwcarsat'}],
|
|
@@ -1086,7 +1086,6 @@ module.exports = [
|
|
|
1086
1086
|
// Window pushers:
|
|
1087
1087
|
{modelID: 'TS0601', manufacturerName: '_TZE200_g5wdnuow'},
|
|
1088
1088
|
// Tubular motors:
|
|
1089
|
-
{modelID: 'TS0601', manufacturerName: '_TZE200_fzo2pocs'},
|
|
1090
1089
|
{modelID: 'TS0601', manufacturerName: '_TZE200_5sbebbzs'},
|
|
1091
1090
|
{modelID: 'TS0601', manufacturerName: '_TZE200_zuz7f94z'},
|
|
1092
1091
|
{modelID: 'TS0601', manufacturerName: '_TZE200_zyrdrmno'},
|
|
@@ -1107,7 +1106,6 @@ module.exports = [
|
|
|
1107
1106
|
{vendor: 'Moes', model: 'AM43-0.45/40-ES-EB'},
|
|
1108
1107
|
{vendor: 'Larkkey', model: 'ZSTY-SM-1SRZG-EU'},
|
|
1109
1108
|
{vendor: 'Zemismart', model: 'ZM85EL-2Z', description: 'Roman Rod I type curtains track'},
|
|
1110
|
-
{vendor: 'Zemismart', model: 'ZM25TQ', description: 'Tubular motor'},
|
|
1111
1109
|
{vendor: 'Zemismart', model: 'AM43', description: 'Roller blind motor'},
|
|
1112
1110
|
{vendor: 'Zemismart', model: 'M2805EGBZTN', description: 'Tubular motor'},
|
|
1113
1111
|
{vendor: 'Zemismart', model: 'BCM500DS-TYZ', description: 'Curtain motor'},
|
package/devices/xiaomi.js
CHANGED
|
@@ -1348,9 +1348,16 @@ module.exports = [
|
|
|
1348
1348
|
model: 'ZNJLBL01LM',
|
|
1349
1349
|
description: 'Aqara roller shade companion E1',
|
|
1350
1350
|
vendor: 'Xiaomi',
|
|
1351
|
-
fromZigbee: [fz.
|
|
1352
|
-
fz.ignore_basic_report, fz.aqara_opple],
|
|
1351
|
+
fromZigbee: [fz.xiaomi_curtain_position, fz.xiaomi_curtain_acn002_status, fz.ignore_basic_report, fz.aqara_opple],
|
|
1353
1352
|
toZigbee: [tz.xiaomi_curtain_position_state, tz.xiaomi_curtain_acn002_battery, tz.xiaomi_curtain_acn002_charging_status],
|
|
1353
|
+
onEvent: async (type, data, device) => {
|
|
1354
|
+
if (type === 'message' && data.type === 'attributeReport' && data.cluster === 'genMultistateOutput' &&
|
|
1355
|
+
data.data.hasOwnProperty('presentValue') && data.data['presentValue'] > 1) {
|
|
1356
|
+
// Try to read the position after the motor stops, the device occasionally report wrong data right after stopping
|
|
1357
|
+
// Might need to add delay, seems to be working without one but needs more tests.
|
|
1358
|
+
await device.getEndpoint(1).read('genAnalogOutput', ['presentValue']);
|
|
1359
|
+
}
|
|
1360
|
+
},
|
|
1354
1361
|
exposes: [e.cover_position().setAccess('state', ea.ALL), e.battery().withAccess(ea.STATE_GET),
|
|
1355
1362
|
exposes.binary('charging_status', ea.STATE_GET, true, false)
|
|
1356
1363
|
.withDescription('The current charging status.'),
|
package/devices/zemismart.js
CHANGED
|
@@ -154,4 +154,13 @@ module.exports = [
|
|
|
154
154
|
// exposes.enum('situation_set', ea.STATE, Object.values(tuya.ZMAM02.AM02Situation)),
|
|
155
155
|
],
|
|
156
156
|
},
|
|
157
|
+
{
|
|
158
|
+
fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_fzo2pocs'}],
|
|
159
|
+
model: 'ZM25TQ',
|
|
160
|
+
vendor: 'Zemismart',
|
|
161
|
+
description: 'Tubular motor',
|
|
162
|
+
fromZigbee: [fz.tuya_cover, fz.ignore_basic_report],
|
|
163
|
+
toZigbee: [tz.tuya_cover_control, tz.tuya_cover_options, tz.tuya_data_point_test],
|
|
164
|
+
exposes: [e.cover_position().setAccess('position', ea.STATE_SET)],
|
|
165
|
+
},
|
|
157
166
|
];
|
package/lib/exposes.js
CHANGED
|
@@ -550,7 +550,7 @@ module.exports = {
|
|
|
550
550
|
fan: () => new Fan(),
|
|
551
551
|
flip_indicator_light: () => new Binary('flip_indicator_light', access.ALL, 'ON', 'OFF').withDescription('After turn on, the indicator light turns on while switch is off, and vice versa'),
|
|
552
552
|
force: () => new Enum('force', access.STATE_SET, ['normal', 'open', 'close']).withDescription('Force the valve position'),
|
|
553
|
-
formaldehyd: () => new Numeric('formaldehyd', access.STATE).withDescription('The measured formaldehyd value'),
|
|
553
|
+
formaldehyd: () => new Numeric('formaldehyd', access.STATE).withDescription('The measured formaldehyd value').withUnit('mg/m³'),
|
|
554
554
|
gas: () => new Binary('gas', access.STATE, true, false).withDescription('Indicates whether the device detected gas'),
|
|
555
555
|
hcho: () => new Numeric('hcho', access.STATE).withUnit('mg/m³').withDescription('Measured Hcho value'),
|
|
556
556
|
holiday_temperature: () => new Numeric('holiday_temperature', access.STATE_SET).withUnit('°C').withDescription('Holiday temperature').withValueMin(0).withValueMax(30),
|
package/lib/tuya.js
CHANGED
|
@@ -449,16 +449,23 @@ const dataPoints = {
|
|
|
449
449
|
silvercrestSetColor: 5,
|
|
450
450
|
silvercrestSetEffect: 6,
|
|
451
451
|
// Fantem
|
|
452
|
+
fantemPowerSupplyMode: 101,
|
|
452
453
|
fantemReportingTime: 102,
|
|
454
|
+
fantemExtSwitchType: 103,
|
|
453
455
|
fantemTempCalibration: 104,
|
|
454
456
|
fantemHumidityCalibration: 105,
|
|
457
|
+
fantemLoadDetectionMode: 105,
|
|
455
458
|
fantemLuxCalibration: 106,
|
|
459
|
+
fantemExtSwitchStatus: 106,
|
|
456
460
|
fantemTemp: 107,
|
|
457
461
|
fantemHumidity: 108,
|
|
458
462
|
fantemMotionEnable: 109,
|
|
463
|
+
fantemControlMode: 109,
|
|
459
464
|
fantemBattery: 110,
|
|
460
465
|
fantemLedEnable: 111,
|
|
461
466
|
fantemReportingEnable: 112,
|
|
467
|
+
fantemLoadType: 112,
|
|
468
|
+
fantemLoadDimmable: 113,
|
|
462
469
|
// Woox
|
|
463
470
|
wooxSwitch: 102,
|
|
464
471
|
wooxBattery: 14,
|
package/lib/xiaomi.js
CHANGED
|
@@ -196,9 +196,10 @@ const numericAttributes2Payload = (msg, meta, model, options, dataObject) => {
|
|
|
196
196
|
payload[`state_${mapping}`] = value === 1 ? 'ON' : 'OFF';
|
|
197
197
|
} else if (['WXKG14LM', 'WXKG16LM', 'WXKG17LM'].includes(model.model)) {
|
|
198
198
|
payload.click_mode = {1: 'fast', 2: 'multi'}[value];
|
|
199
|
-
} else if (['WXCJKG11LM', 'WXCJKG12LM', 'WXCJKG13LM'].includes(model.model)) {
|
|
199
|
+
} else if (['WXCJKG11LM', 'WXCJKG12LM', 'WXCJKG13LM', 'ZNMS12LM'].includes(model.model)) {
|
|
200
200
|
// We don't know what the value means for these devices.
|
|
201
201
|
// https://github.com/Koenkk/zigbee2mqtt/issues/11126
|
|
202
|
+
// https://github.com/Koenkk/zigbee2mqtt/issues/12279
|
|
202
203
|
} else if (['WSDCGQ01LM', 'WSDCGQ11LM'].includes(model.model)) {
|
|
203
204
|
// https://github.com/Koenkk/zigbee2mqtt/issues/798
|
|
204
205
|
// Sometimes the sensor publishes non-realistic vales, filter these
|