@willieee802/zigbee-herdsman-converters 15.0.8-4.1
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/LICENSE +21 -0
- package/README.md +7 -0
- package/converters/fromZigbee.js +8439 -0
- package/converters/toZigbee.js +7162 -0
- package/devices/ITCommander.js +37 -0
- package/devices/RMC002.js +20 -0
- package/devices/acova.js +101 -0
- package/devices/acuity_brands_lighting.js +11 -0
- package/devices/adeo.js +256 -0
- package/devices/adurosmart.js +130 -0
- package/devices/aeotec.js +13 -0
- package/devices/airam.js +59 -0
- package/devices/ajax_online.js +49 -0
- package/devices/akuvox.js +28 -0
- package/devices/alchemy.js +18 -0
- package/devices/aldi.js +53 -0
- package/devices/alecto.js +98 -0
- package/devices/anchor.js +17 -0
- package/devices/atlantic.js +110 -0
- package/devices/atsmart.js +28 -0
- package/devices/aubess.js +21 -0
- package/devices/aurora_lighting.js +292 -0
- package/devices/automaton.js +44 -0
- package/devices/awox.js +184 -0
- package/devices/axis.js +22 -0
- package/devices/bankamp.js +11 -0
- package/devices/bega.js +22 -0
- package/devices/belkin.js +11 -0
- package/devices/bitron.js +334 -0
- package/devices/blaupunkt.js +27 -0
- package/devices/blitzwolf.js +47 -0
- package/devices/bosch.js +702 -0
- package/devices/brimate.js +15 -0
- package/devices/bseed.js +17 -0
- package/devices/bticino.js +118 -0
- package/devices/busch-jaeger.js +140 -0
- package/devices/byun.js +24 -0
- package/devices/calex.js +37 -0
- package/devices/candeo.js +49 -0
- package/devices/casaia.js +52 -0
- package/devices/centralite.js +359 -0
- package/devices/cleode.js +20 -0
- package/devices/cleverio.js +36 -0
- package/devices/climax.js +138 -0
- package/devices/commercial_electric.js +16 -0
- package/devices/connecte.js +46 -0
- package/devices/cree.js +11 -0
- package/devices/ctm.js +999 -0
- package/devices/current_products_corp.js +24 -0
- package/devices/custom_devices_diy.js +850 -0
- package/devices/cy-lighting.js +11 -0
- package/devices/danalock.js +26 -0
- package/devices/danfoss.js +340 -0
- package/devices/databyte.ch.js +55 -0
- package/devices/datek.js +246 -0
- package/devices/dawon_dns.js +338 -0
- package/devices/develco.js +868 -0
- package/devices/digi.js +14 -0
- package/devices/diyruz.js +305 -0
- package/devices/dlink.js +37 -0
- package/devices/dnake.js +11 -0
- package/devices/dresden_elektronik.js +47 -0
- package/devices/easyaccess.js +27 -0
- package/devices/eatonhalo_led.js +11 -0
- package/devices/echostar.js +25 -0
- package/devices/ecodim.js +145 -0
- package/devices/ecolink.js +21 -0
- package/devices/ecosmart.js +64 -0
- package/devices/ecozy.js +31 -0
- package/devices/edp.js +39 -0
- package/devices/eglo.js +25 -0
- package/devices/elko.js +176 -0
- package/devices/enbrighten.js +163 -0
- package/devices/enocean.js +52 -0
- package/devices/envilar.js +73 -0
- package/devices/essentialb.js +87 -0
- package/devices/eurotronic.js +48 -0
- package/devices/evanell.js +29 -0
- package/devices/evn.js +31 -0
- package/devices/evology.js +24 -0
- package/devices/evvr.js +17 -0
- package/devices/ewelink.js +184 -0
- package/devices/ezex.js +24 -0
- package/devices/fantem.js +77 -0
- package/devices/feibit.js +172 -0
- package/devices/fireangel.js +15 -0
- package/devices/frankever.js +23 -0
- package/devices/garza.js +11 -0
- package/devices/ge.js +111 -0
- package/devices/gewiss.js +48 -0
- package/devices/gidealed.js +11 -0
- package/devices/giderwel.js +11 -0
- package/devices/giex.js +222 -0
- package/devices/girier.js +19 -0
- package/devices/gledopto.js +756 -0
- package/devices/gmy.js +11 -0
- package/devices/gs.js +29 -0
- package/devices/halemeier.js +18 -0
- package/devices/hampton_bay.js +37 -0
- package/devices/heiman.js +805 -0
- package/devices/hej.js +107 -0
- package/devices/hfh.js +11 -0
- package/devices/hgkg.js +54 -0
- package/devices/hilux.js +11 -0
- package/devices/hive.js +524 -0
- package/devices/home_control_as.js +27 -0
- package/devices/hommyn.js +24 -0
- package/devices/honyar.js +29 -0
- package/devices/hornbach.js +53 -0
- package/devices/hzc.js +21 -0
- package/devices/hzc_electric.js +42 -0
- package/devices/icasa.js +121 -0
- package/devices/idinio.js +19 -0
- package/devices/ihorn.js +61 -0
- package/devices/ikea.js +1168 -0
- package/devices/ilightsin.js +11 -0
- package/devices/iluminize.js +262 -0
- package/devices/ilux.js +11 -0
- package/devices/immax.js +203 -0
- package/devices/innr.js +705 -0
- package/devices/inovelli.js +1315 -0
- package/devices/insta.js +110 -0
- package/devices/iolloi.js +20 -0
- package/devices/iotperfect.js +20 -0
- package/devices/iris.js +180 -0
- package/devices/istar.js +20 -0
- package/devices/jasco.js +55 -0
- package/devices/javis.js +37 -0
- package/devices/jethome.js +48 -0
- package/devices/jiawen.js +18 -0
- package/devices/jumitech.js +18 -0
- package/devices/jxuan.js +49 -0
- package/devices/kami.js +15 -0
- package/devices/keen_home.js +80 -0
- package/devices/klikaanklikuit.js +17 -0
- package/devices/kmpcil.js +148 -0
- package/devices/konke.js +141 -0
- package/devices/ksentry.js +17 -0
- package/devices/kurvia.js +17 -0
- package/devices/kwikset.js +120 -0
- package/devices/lanesto.js +11 -0
- package/devices/lds.js +11 -0
- package/devices/led_trading.js +69 -0
- package/devices/ledvance.js +353 -0
- package/devices/leedarson.js +130 -0
- package/devices/legrand.js +554 -0
- package/devices/lellki.js +146 -0
- package/devices/letsled.js +11 -0
- package/devices/letv.js +18 -0
- package/devices/leviton.js +142 -0
- package/devices/lg.js +18 -0
- package/devices/lidl.js +1000 -0
- package/devices/lifecontrol.js +92 -0
- package/devices/lightsolutions.js +37 -0
- package/devices/linkind.js +205 -0
- package/devices/livingwise.js +59 -0
- package/devices/livolo.js +286 -0
- package/devices/lixee.js +779 -0
- package/devices/lonsonho.js +218 -0
- package/devices/lubeez.js +18 -0
- package/devices/lupus.js +74 -0
- package/devices/lutron.js +32 -0
- package/devices/lux.js +40 -0
- package/devices/m-elec.js +18 -0
- package/devices/makegood.js +51 -0
- package/devices/matcall_bv.js +18 -0
- package/devices/meazon.js +47 -0
- package/devices/mercator.js +225 -0
- package/devices/miboxer.js +72 -0
- package/devices/micromatic.js +29 -0
- package/devices/moes.js +400 -0
- package/devices/mycket.js +11 -0
- package/devices/m/303/274ller_licht.js +220 -0
- package/devices/namron.js +774 -0
- package/devices/nanoleaf.js +11 -0
- package/devices/neo.js +86 -0
- package/devices/net2grid.js +29 -0
- package/devices/netvox.js +35 -0
- package/devices/niko.js +314 -0
- package/devices/ninja_blocks.js +24 -0
- package/devices/niviss.js +11 -0
- package/devices/nodon.js +109 -0
- package/devices/nordtronic.js +30 -0
- package/devices/nous.js +88 -0
- package/devices/novo.js +17 -0
- package/devices/nue_3a.js +417 -0
- package/devices/nyce.js +67 -0
- package/devices/onesti.js +59 -0
- package/devices/openlumi.js +22 -0
- package/devices/orvibo.js +515 -0
- package/devices/osram.js +519 -0
- package/devices/oujiabao.js +15 -0
- package/devices/owon.js +352 -0
- package/devices/ozsmartthings.js +11 -0
- package/devices/paul_neuhaus.js +96 -0
- package/devices/paulmann.js +158 -0
- package/devices/peq.js +24 -0
- package/devices/perenio.js +413 -0
- package/devices/philips.js +3118 -0
- package/devices/plaid.js +25 -0
- package/devices/plugwise.js +173 -0
- package/devices/popp.js +10 -0
- package/devices/profalux.js +47 -0
- package/devices/prolight.js +54 -0
- package/devices/qmotion.js +33 -0
- package/devices/qoto.js +113 -0
- package/devices/quotra.js +18 -0
- package/devices/rademacher.js +18 -0
- package/devices/rgb_genie.js +119 -0
- package/devices/robb.js +335 -0
- package/devices/roome.js +15 -0
- package/devices/rtx.js +90 -0
- package/devices/salus_controls.js +137 -0
- package/devices/samotech.js +93 -0
- package/devices/saswell.js +58 -0
- package/devices/scanproducts.js +32 -0
- package/devices/schlage.js +24 -0
- package/devices/schneider_electric.js +1039 -0
- package/devices/schwaiger.js +62 -0
- package/devices/seastar_intelligence.js +16 -0
- package/devices/securifi.js +39 -0
- package/devices/sengled.js +332 -0
- package/devices/sercomm.js +140 -0
- package/devices/shenzhen_homa.js +53 -0
- package/devices/shinasystem.js +686 -0
- package/devices/siglis.js +440 -0
- package/devices/sinope.js +1257 -0
- package/devices/siterwell.js +46 -0
- package/devices/skydance.js +112 -0
- package/devices/slv.js +27 -0
- package/devices/smart9.js +27 -0
- package/devices/smart_home_pty.js +18 -0
- package/devices/smartenit.js +42 -0
- package/devices/smartthings.js +495 -0
- package/devices/smartwings.js +24 -0
- package/devices/sohan_electric.js +13 -0
- package/devices/solaredge.js +11 -0
- package/devices/somgoms.js +47 -0
- package/devices/sonoff.js +262 -0
- package/devices/spotmau.js +36 -0
- package/devices/sprut.js +317 -0
- package/devices/stelpro.js +216 -0
- package/devices/sunricher.js +625 -0
- package/devices/swann.js +33 -0
- package/devices/sylvania.js +200 -0
- package/devices/tci.js +25 -0
- package/devices/technicolor.js +47 -0
- package/devices/terncy.js +64 -0
- package/devices/the_light_group.js +70 -0
- package/devices/third_reality.js +195 -0
- package/devices/titan_products.js +22 -0
- package/devices/tplink.js +42 -0
- package/devices/trust.js +114 -0
- package/devices/tubeszb.js +20 -0
- package/devices/tuya.js +4215 -0
- package/devices/ubisys.js +938 -0
- package/devices/uhome.js +25 -0
- package/devices/universal_electronics_inc.js +119 -0
- package/devices/urlighting.js +12 -0
- package/devices/useelink.js +52 -0
- package/devices/vbled.js +18 -0
- package/devices/vesternet.js +188 -0
- package/devices/viessmann.js +51 -0
- package/devices/villeroy_boch.js +18 -0
- package/devices/vimar.js +78 -0
- package/devices/visonic.js +80 -0
- package/devices/vrey.js +18 -0
- package/devices/wally.js +25 -0
- package/devices/waxman.js +45 -0
- package/devices/weiser.js +67 -0
- package/devices/weten.js +13 -0
- package/devices/wisdom.js +11 -0
- package/devices/woox.js +177 -0
- package/devices/wyze.js +23 -0
- package/devices/xiaomi.js +3223 -0
- package/devices/xinghuoyuan.js +11 -0
- package/devices/yale.js +227 -0
- package/devices/ynoa.js +68 -0
- package/devices/yookee.js +23 -0
- package/devices/ysrsai.js +26 -0
- package/devices/zemismart.js +254 -0
- package/devices/zen.js +34 -0
- package/devices/zipato.js +11 -0
- package/index.js +242 -0
- package/lib/color.js +784 -0
- package/lib/configureKey.js +944 -0
- package/lib/constants.js +316 -0
- package/lib/exposes.js +677 -0
- package/lib/extend.js +180 -0
- package/lib/kelvinToXy.js +1912 -0
- package/lib/legacy.js +2223 -0
- package/lib/light.js +111 -0
- package/lib/ota/OTA_URLs.md +119 -0
- package/lib/ota/common.js +476 -0
- package/lib/ota/index.js +10 -0
- package/lib/ota/inovelli.js +72 -0
- package/lib/ota/ledvance.js +52 -0
- package/lib/ota/lixee.js +57 -0
- package/lib/ota/salus.js +82 -0
- package/lib/ota/securifi.js +25 -0
- package/lib/ota/tradfri.js +45 -0
- package/lib/ota/ubisys.js +61 -0
- package/lib/ota/zigbeeOTA.js +161 -0
- package/lib/philips.js +667 -0
- package/lib/reporting.js +234 -0
- package/lib/store.js +57 -0
- package/lib/tuya.js +2027 -0
- package/lib/utils.js +527 -0
- package/lib/xiaomi.d.ts +11 -0
- package/lib/xiaomi.js +1288 -0
- package/lib/zosung.js +243 -0
- package/package.json +39 -0
|
@@ -0,0 +1,3223 @@
|
|
|
1
|
+
const exposes = require('../lib/exposes');
|
|
2
|
+
const fz = {...require('../converters/fromZigbee'), legacy: require('../lib/legacy').fromZigbee};
|
|
3
|
+
const tz = require('../converters/toZigbee');
|
|
4
|
+
const ota = require('../lib/ota');
|
|
5
|
+
const constants = require('../lib/constants');
|
|
6
|
+
const reporting = require('../lib/reporting');
|
|
7
|
+
const extend = require('../lib/extend');
|
|
8
|
+
const e = exposes.presets;
|
|
9
|
+
const ea = exposes.access;
|
|
10
|
+
const globalStore = require('../lib/store');
|
|
11
|
+
const xiaomi = require('../lib/xiaomi');
|
|
12
|
+
const utils = require('../lib/utils');
|
|
13
|
+
const {printNumberAsHex, printNumbersAsHexSequence} = utils;
|
|
14
|
+
const {fp1, manufacturerCode, trv} = xiaomi;
|
|
15
|
+
|
|
16
|
+
const xiaomiExtend = {
|
|
17
|
+
light_onoff_brightness_colortemp: (options={disableColorTempStartup: true}) => ({
|
|
18
|
+
...extend.light_onoff_brightness_colortemp(options),
|
|
19
|
+
fromZigbee: extend.light_onoff_brightness_colortemp(options).fromZigbee.concat([
|
|
20
|
+
fz.xiaomi_bulb_interval, fz.ignore_occupancy_report, fz.ignore_humidity_report,
|
|
21
|
+
fz.ignore_pressure_report, fz.ignore_temperature_report,
|
|
22
|
+
]),
|
|
23
|
+
}),
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const preventReset = async (type, data, device) => {
|
|
27
|
+
if (
|
|
28
|
+
// options.allow_reset ||
|
|
29
|
+
type !== 'message' ||
|
|
30
|
+
data.type !== 'attributeReport' ||
|
|
31
|
+
data.cluster !== 'genBasic' ||
|
|
32
|
+
!data.data[0xfff0] ||
|
|
33
|
+
// eg: [0xaa, 0x10, 0x05, 0x41, 0x87, 0x01, 0x01, 0x10, 0x00]
|
|
34
|
+
!data.data[0xFFF0].slice(0, 5).equals(Buffer.from([0xaa, 0x10, 0x05, 0x41, 0x87]))
|
|
35
|
+
) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const options = {manufacturerCode: 0x115f};
|
|
39
|
+
const payload = {[0xfff0]: {
|
|
40
|
+
value: [0xaa, 0x10, 0x05, 0x41, 0x47, 0x01, 0x01, 0x10, 0x01],
|
|
41
|
+
type: 0x41,
|
|
42
|
+
}};
|
|
43
|
+
await device.getEndpoint(1).write('genBasic', payload, options);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const daysLookup = {
|
|
47
|
+
0x7f: 'everyday',
|
|
48
|
+
0x1f: 'workdays',
|
|
49
|
+
0x60: 'weekend',
|
|
50
|
+
0x01: 'mon',
|
|
51
|
+
0x02: 'tue',
|
|
52
|
+
0x04: 'wed',
|
|
53
|
+
0x08: 'thu',
|
|
54
|
+
0x10: 'fri',
|
|
55
|
+
0x20: 'sat',
|
|
56
|
+
0x40: 'sun',
|
|
57
|
+
0x55: 'mon-wed-fri-sun',
|
|
58
|
+
0x2a: 'tue-thu-sat',
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
const fzLocal = {
|
|
63
|
+
aqara_s1_co2: {
|
|
64
|
+
cluster: 'msCO2',
|
|
65
|
+
type: ['attributeReport', 'readResponse'],
|
|
66
|
+
convert: (model, msg, publish, options, meta) => {
|
|
67
|
+
return {co2: Math.floor(msg.data.measuredValue)};
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
aqara_s1_pm25: {
|
|
71
|
+
cluster: 'pm25Measurement',
|
|
72
|
+
type: ['attributeReport', 'readResponse'],
|
|
73
|
+
convert: (model, msg, publish, options, meta) => {
|
|
74
|
+
if (msg.data['measuredValue']) {
|
|
75
|
+
return {pm25: msg.data['measuredValue'] / 1000};
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
aqara_trv: {
|
|
80
|
+
cluster: 'aqaraOpple',
|
|
81
|
+
type: ['attributeReport', 'readResponse'],
|
|
82
|
+
convert: (model, msg, publish, options, meta) => {
|
|
83
|
+
const result = {};
|
|
84
|
+
Object.entries(msg.data).forEach(([key, value]) => {
|
|
85
|
+
switch (parseInt(key)) {
|
|
86
|
+
case 0x0271:
|
|
87
|
+
result['system_mode'] = {1: 'heat', 0: 'off'}[value];
|
|
88
|
+
break;
|
|
89
|
+
case 0x0272:
|
|
90
|
+
Object.assign(result, trv.decodePreset(value));
|
|
91
|
+
break;
|
|
92
|
+
case 0x0273:
|
|
93
|
+
result['window_detection'] = {1: 'ON', 0: 'OFF'}[value];
|
|
94
|
+
break;
|
|
95
|
+
case 0x0274:
|
|
96
|
+
result['valve_detection'] = {1: 'ON', 0: 'OFF'}[value];
|
|
97
|
+
break;
|
|
98
|
+
case 0x0277:
|
|
99
|
+
result['child_lock'] = {1: 'LOCK', 0: 'UNLOCK'}[value];
|
|
100
|
+
break;
|
|
101
|
+
case 0x0279:
|
|
102
|
+
result['away_preset_temperature'] = (value / 100).toFixed(1);
|
|
103
|
+
break;
|
|
104
|
+
case 0x027b:
|
|
105
|
+
result['calibrated'] = {1: true, 0: false}[value];
|
|
106
|
+
break;
|
|
107
|
+
case 0x027e:
|
|
108
|
+
result['sensor'] = {1: 'external', 0: 'internal'}[value];
|
|
109
|
+
break;
|
|
110
|
+
case 0x040a:
|
|
111
|
+
result['battery'] = value;
|
|
112
|
+
break;
|
|
113
|
+
case 0x027a:
|
|
114
|
+
result['window_open'] = {1: true, 0: false}[value];
|
|
115
|
+
break;
|
|
116
|
+
case 0x0275:
|
|
117
|
+
result['valve_alarm'] = {1: true, 0: false}[value];
|
|
118
|
+
break;
|
|
119
|
+
case 247: {
|
|
120
|
+
const heartbeat = trv.decodeHeartbeat(meta, model, value);
|
|
121
|
+
|
|
122
|
+
meta.logger.debug(`${model.zigbeeModel}: Processed heartbeat message into payload ${JSON.stringify(heartbeat)}`);
|
|
123
|
+
|
|
124
|
+
if (heartbeat.firmware_version) {
|
|
125
|
+
// Overwrite the "placeholder" version `0.0.0_0025` advertised by `genBasic`
|
|
126
|
+
// with the correct version from the heartbeat.
|
|
127
|
+
// This is not reflected in the frontend unless the device is reconfigured
|
|
128
|
+
// or the whole service restarted.
|
|
129
|
+
// See https://github.com/Koenkk/zigbee-herdsman-converters/pull/5363#discussion_r1081477047
|
|
130
|
+
meta.device.softwareBuildID = heartbeat.firmware_version;
|
|
131
|
+
delete heartbeat.firmware_version;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
Object.assign(result, heartbeat);
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
case 0x027d:
|
|
138
|
+
result['schedule'] = {1: 'ON', 0: 'OFF'}[value];
|
|
139
|
+
break;
|
|
140
|
+
case 0x0276: {
|
|
141
|
+
const schedule = trv.decodeSchedule(value);
|
|
142
|
+
result['schedule_settings'] = trv.stringifySchedule(schedule);
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
case 0x00EE: {
|
|
146
|
+
meta.device.meta.aqaraFileVersion = value;
|
|
147
|
+
meta.device.save();
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
case 0xfff2:
|
|
151
|
+
case 0x00ff: // 4e:27:49:bb:24:b6:30:dd:74:de:53:76:89:44:c4:81
|
|
152
|
+
case 0x027c: // 0x00
|
|
153
|
+
case 0x0280: // 0x00/0x01
|
|
154
|
+
meta.logger.debug(`zigbee-herdsman-converters:aqara_trv: Unhandled key ${key} = ${value}`);
|
|
155
|
+
break;
|
|
156
|
+
default:
|
|
157
|
+
meta.logger.warn(`zigbee-herdsman-converters:aqara_trv: Unknown key ${key} = ${value}`);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
return result;
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
aqara_feeder: {
|
|
164
|
+
cluster: 'aqaraOpple',
|
|
165
|
+
type: ['attributeReport', 'readResponse'],
|
|
166
|
+
convert: (model, msg, publish, options, meta) => {
|
|
167
|
+
const result = {};
|
|
168
|
+
Object.entries(msg.data).forEach(([key, value]) => {
|
|
169
|
+
switch (parseInt(key)) {
|
|
170
|
+
case 0xfff1: {
|
|
171
|
+
const attr = value.slice(3, 7);
|
|
172
|
+
const len = value.slice(7, 8).readUInt8();
|
|
173
|
+
const val = value.slice(8, 8 + len);
|
|
174
|
+
switch (attr.readInt32BE()) {
|
|
175
|
+
case 0x04150055: // feeding
|
|
176
|
+
result['feed'] = '';
|
|
177
|
+
break;
|
|
178
|
+
case 0x041502bc: { // feeding report
|
|
179
|
+
const report = val.toString();
|
|
180
|
+
result['feeding_source'] = {0: 'schedule', 1: 'manual', 2: 'remote'}[parseInt(report.slice(0, 2))];
|
|
181
|
+
result['feeding_size'] = parseInt(report.slice(3, 4));
|
|
182
|
+
break;
|
|
183
|
+
}
|
|
184
|
+
case 0x0d680055: // portions per day
|
|
185
|
+
result['portions_per_day'] = val.readUInt16BE();
|
|
186
|
+
break;
|
|
187
|
+
case 0x0d690055: // weight per day
|
|
188
|
+
result['weight_per_day'] = val.readUInt32BE();
|
|
189
|
+
break;
|
|
190
|
+
case 0x0d0b0055: // error ?
|
|
191
|
+
result['error'] = {1: true, 0: false}[val.readUInt8()];
|
|
192
|
+
break;
|
|
193
|
+
case 0x080008c8: { // schedule string
|
|
194
|
+
const schlist = val.toString().split(',');
|
|
195
|
+
const schedule = [];
|
|
196
|
+
schlist.forEach((str) => { // 7f13000100
|
|
197
|
+
const feedtime = Buffer.from(str, 'hex');
|
|
198
|
+
schedule.push({
|
|
199
|
+
'days': daysLookup[feedtime[0]],
|
|
200
|
+
'hour': feedtime[1],
|
|
201
|
+
'minute': feedtime[2],
|
|
202
|
+
'size': feedtime[3],
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
result['schedule'] = schedule;
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
case 0x04170055: // indicator
|
|
209
|
+
result['led_indicator'] = {1: 'ON', 0: 'OFF'}[val.readUInt8()];
|
|
210
|
+
break;
|
|
211
|
+
case 0x04160055: // child lock
|
|
212
|
+
result['child_lock'] = {1: 'LOCK', 0: 'UNLOCK'}[val.readUInt8()];
|
|
213
|
+
break;
|
|
214
|
+
case 0x04180055: // mode
|
|
215
|
+
result['mode'] = {1: 'schedule', 0: 'manual'}[val.readUInt8()];
|
|
216
|
+
break;
|
|
217
|
+
case 0x0e5c0055: // serving size
|
|
218
|
+
result['serving_size'] = val.readUInt8();
|
|
219
|
+
break;
|
|
220
|
+
case 0x0e5f0055: // portion weight
|
|
221
|
+
result['portion_weight'] = val.readUInt8();
|
|
222
|
+
break;
|
|
223
|
+
case 0x080007d1: // ? 64
|
|
224
|
+
case 0x0d090055: // ? 00
|
|
225
|
+
meta.logger.warn(`zigbee-herdsman-converters:aqara_feeder: Unhandled attribute ${attr} = ${val}`);
|
|
226
|
+
break;
|
|
227
|
+
default:
|
|
228
|
+
meta.logger.warn(`zigbee-herdsman-converters:aqara_feeder: Unknown attribute ${attr} = ${val}`);
|
|
229
|
+
}
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
case 0x00ff: // 80:13:58:91:24:33:20:24:58:53:44:07:05:97:75:17
|
|
233
|
+
case 0x0007: // 00:00:00:00:1d:b5:a6:ed
|
|
234
|
+
case 0x00f7: // 05:21:14:00:0d:23:21:25:00:00:09:21:00:01
|
|
235
|
+
meta.logger.debug(`zigbee-herdsman-converters:aqara_feeder: Unhandled key ${key} = ${value}`);
|
|
236
|
+
break;
|
|
237
|
+
default:
|
|
238
|
+
meta.logger.warn(`zigbee-herdsman-converters:aqara_feeder: Unknown key ${key} = ${value}`);
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
return result;
|
|
242
|
+
},
|
|
243
|
+
},
|
|
244
|
+
aqara_fp1_region_events: {
|
|
245
|
+
cluster: 'aqaraOpple',
|
|
246
|
+
type: ['attributeReport', 'readResponse'],
|
|
247
|
+
convert: (model, msg, publish, options, meta) => {
|
|
248
|
+
/**
|
|
249
|
+
* @type {{ action?: string; }}
|
|
250
|
+
*/
|
|
251
|
+
const payload = {};
|
|
252
|
+
const log = utils.createLogger(meta.logger, 'xiaomi', 'aqara_fp1');
|
|
253
|
+
|
|
254
|
+
Object.entries(msg.data).forEach(([key, value]) => {
|
|
255
|
+
const eventKey = parseInt(key);
|
|
256
|
+
const eventKeyHex = printNumberAsHex(eventKey, 4);
|
|
257
|
+
|
|
258
|
+
switch (eventKey) {
|
|
259
|
+
case fp1.constants.region_event_key: {
|
|
260
|
+
if (
|
|
261
|
+
!Buffer.isBuffer(value) ||
|
|
262
|
+
!(typeof value[0] === 'string' || typeof value[0] === 'number') ||
|
|
263
|
+
!(typeof value[1] === 'string' || typeof value[1] === 'number')
|
|
264
|
+
) {
|
|
265
|
+
log('warn', `action: Unrecognized payload structure '${JSON.stringify(value)}'`);
|
|
266
|
+
break;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* @type {[ regionId: number | string, eventTypeCode: number | string ]}
|
|
271
|
+
*/
|
|
272
|
+
const [regionIdRaw, eventTypeCodeRaw] = value;
|
|
273
|
+
const regionId = parseInt(regionIdRaw, 10);
|
|
274
|
+
const eventTypeCode = parseInt(eventTypeCodeRaw, 10);
|
|
275
|
+
|
|
276
|
+
if (Number.isNaN(regionId)) {
|
|
277
|
+
log('warn', `action: Invalid regionId "${regionIdRaw}"`);
|
|
278
|
+
break;
|
|
279
|
+
}
|
|
280
|
+
if (!Object.values(fp1.constants.region_event_types).includes(eventTypeCode)) {
|
|
281
|
+
log('warn', `action: Unknown region event type "${eventTypeCode}"`);
|
|
282
|
+
break;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
const eventTypeName = fp1.mappers.aqara_fp1.region_event_type_names[eventTypeCode];
|
|
286
|
+
log('debug', `action: Triggered event (region "${regionId}", type "${eventTypeName}")`);
|
|
287
|
+
payload.action = `region_${regionId}_${eventTypeName}`;
|
|
288
|
+
break;
|
|
289
|
+
}
|
|
290
|
+
case 0xf7: {
|
|
291
|
+
const valueHexSequence = printNumbersAsHexSequence(value, 2);
|
|
292
|
+
log('debug', `Unhandled key ${eventKeyHex} = ${valueHexSequence}`);
|
|
293
|
+
break;
|
|
294
|
+
}
|
|
295
|
+
case 0x0142:
|
|
296
|
+
case 0x0143:
|
|
297
|
+
case 0x0144:
|
|
298
|
+
case 0x0146: {
|
|
299
|
+
log('debug', `Unhandled key ${eventKeyHex} = ${value}`);
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
default: {
|
|
303
|
+
log('warn', `Unknown key ${eventKeyHex} = ${value}`);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
return payload;
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
CTPR01_action_multistate: {
|
|
312
|
+
cluster: 'genMultistateInput',
|
|
313
|
+
type: ['attributeReport', 'readResponse'],
|
|
314
|
+
options: [],
|
|
315
|
+
convert: (model, msg, publish, options, meta) => {
|
|
316
|
+
const value = msg.data['presentValue'];
|
|
317
|
+
let payload;
|
|
318
|
+
|
|
319
|
+
if (value === 0) payload = {action: 'shake'};
|
|
320
|
+
else if (value === 1) payload = {action: 'throw'};
|
|
321
|
+
else if (value === 2) payload = {action: '1_min_inactivity'};
|
|
322
|
+
else if (value === 4) payload = {action: 'hold'};
|
|
323
|
+
else if (value >= 1024) payload = {action: 'flip_to_side', side: value - 1023};
|
|
324
|
+
else if (value >= 512) payload = {action: 'tap', side: value - 511};
|
|
325
|
+
else if (value >= 256) payload = {action: 'slide', side: value - 255};
|
|
326
|
+
else if (value >= 128) {
|
|
327
|
+
payload = {
|
|
328
|
+
action: 'flip180', side: value - 127,
|
|
329
|
+
action_from_side: 7 - value + 127,
|
|
330
|
+
};
|
|
331
|
+
} else if (value >= 64) {
|
|
332
|
+
payload = {
|
|
333
|
+
action: 'flip90', side: value % 8 + 1,
|
|
334
|
+
action_from_side: Math.floor((value - 64) / 8) + 1,
|
|
335
|
+
};
|
|
336
|
+
} else {
|
|
337
|
+
meta.logger.debug(`${model.zigbeeModel}: unknown action with value ${value}`);
|
|
338
|
+
}
|
|
339
|
+
return payload;
|
|
340
|
+
},
|
|
341
|
+
},
|
|
342
|
+
CTPR01_action_analog: {
|
|
343
|
+
cluster: 'genAnalogInput',
|
|
344
|
+
type: ['attributeReport', 'readResponse'],
|
|
345
|
+
options: [],
|
|
346
|
+
convert: (model, msg, publish, options, meta) => {
|
|
347
|
+
const value = msg.data['presentValue'];
|
|
348
|
+
return {
|
|
349
|
+
action: value < 0 ? 'rotate_left' : 'rotate_right',
|
|
350
|
+
action_angle: Math.floor(value * 100) / 100,
|
|
351
|
+
};
|
|
352
|
+
},
|
|
353
|
+
},
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
const tzLocal = {
|
|
357
|
+
aqara_trv: {
|
|
358
|
+
key: ['system_mode', 'preset', 'window_detection', 'valve_detection', 'child_lock', 'away_preset_temperature',
|
|
359
|
+
'calibrate', 'sensor', 'sensor_temp', 'identify', 'schedule', 'schedule_settings'],
|
|
360
|
+
convertSet: async (entity, key, value, meta) => {
|
|
361
|
+
const aqaraHeader = (counter, params, action) => {
|
|
362
|
+
const header = [0xaa, 0x71, params.length + 3, 0x44, counter];
|
|
363
|
+
const integrity = 512 - header.reduce((sum, elem) => sum + elem, 0);
|
|
364
|
+
return [...header, integrity, action, 0x41, params.length];
|
|
365
|
+
};
|
|
366
|
+
const sensor = Buffer.from('00158d00019d1b98', 'hex');
|
|
367
|
+
|
|
368
|
+
switch (key) {
|
|
369
|
+
case 'system_mode':
|
|
370
|
+
await entity.write('aqaraOpple', {0x0271: {value: {'off': 0, 'heat': 1}[value], type: 0x20}},
|
|
371
|
+
{manufacturerCode: 0x115f});
|
|
372
|
+
break;
|
|
373
|
+
case 'preset':
|
|
374
|
+
await entity.write('aqaraOpple', {0x0272: {value: {'manual': 0, 'auto': 1, 'away': 2}[value], type: 0x20}},
|
|
375
|
+
{manufacturerCode: 0x115f});
|
|
376
|
+
break;
|
|
377
|
+
case 'window_detection':
|
|
378
|
+
await entity.write('aqaraOpple', {0x0273: {value: {'OFF': 0, 'ON': 1}[value], type: 0x20}},
|
|
379
|
+
{manufacturerCode: 0x115f});
|
|
380
|
+
break;
|
|
381
|
+
case 'valve_detection':
|
|
382
|
+
await entity.write('aqaraOpple', {0x0274: {value: {'OFF': 0, 'ON': 1}[value], type: 0x20}},
|
|
383
|
+
{manufacturerCode: 0x115f});
|
|
384
|
+
break;
|
|
385
|
+
case 'child_lock':
|
|
386
|
+
await entity.write('aqaraOpple', {0x0277: {value: {'UNLOCK': 0, 'LOCK': 1}[value], type: 0x20}},
|
|
387
|
+
{manufacturerCode: 0x115f});
|
|
388
|
+
break;
|
|
389
|
+
case 'away_preset_temperature':
|
|
390
|
+
await entity.write('aqaraOpple', {0x0279: {value: Math.round(value * 100), type: 0x23}}, {manufacturerCode: 0x115f});
|
|
391
|
+
break;
|
|
392
|
+
case 'sensor': {
|
|
393
|
+
const device = Buffer.from(entity.deviceIeeeAddress.substring(2), 'hex');
|
|
394
|
+
const timestamp = Buffer.alloc(4);
|
|
395
|
+
timestamp.writeUint32BE(Date.now()/1000);
|
|
396
|
+
|
|
397
|
+
if (value === 'external') {
|
|
398
|
+
const params1 = [
|
|
399
|
+
...timestamp,
|
|
400
|
+
0x3d, 0x04,
|
|
401
|
+
...device,
|
|
402
|
+
...sensor,
|
|
403
|
+
0x00, 0x01, 0x00, 0x55,
|
|
404
|
+
0x13, 0x0a, 0x02, 0x00, 0x00, 0x64, 0x04, 0xce, 0xc2, 0xb6, 0xc8,
|
|
405
|
+
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x3d,
|
|
406
|
+
0x64,
|
|
407
|
+
0x65,
|
|
408
|
+
];
|
|
409
|
+
const params2 = [
|
|
410
|
+
...timestamp,
|
|
411
|
+
0x3d, 0x05,
|
|
412
|
+
...device,
|
|
413
|
+
...sensor,
|
|
414
|
+
0x08, 0x00, 0x07, 0xfd,
|
|
415
|
+
0x16, 0x0a, 0x02, 0x0a, 0xc9, 0xe8, 0xb1, 0xb8, 0xd4, 0xda, 0xcf, 0xdf, 0xc0, 0xeb,
|
|
416
|
+
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x3d,
|
|
417
|
+
0x04,
|
|
418
|
+
0x65,
|
|
419
|
+
];
|
|
420
|
+
|
|
421
|
+
const val1 = [...(aqaraHeader(0x12, params1, 0x02)), ...params1];
|
|
422
|
+
const val2 = [...(aqaraHeader(0x13, params2, 0x02)), ...params2];
|
|
423
|
+
|
|
424
|
+
await entity.write('aqaraOpple', {0xfff2: {value: val1, type: 0x41}}, {manufacturerCode: 0x115f});
|
|
425
|
+
await entity.write('aqaraOpple', {0xfff2: {value: val2, type: 0x41}}, {manufacturerCode: 0x115f});
|
|
426
|
+
} else if (value === 'internal') {
|
|
427
|
+
const params1 = [
|
|
428
|
+
...timestamp,
|
|
429
|
+
0x3d, 0x05,
|
|
430
|
+
...device,
|
|
431
|
+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
432
|
+
];
|
|
433
|
+
const params2 = [
|
|
434
|
+
...timestamp,
|
|
435
|
+
0x3d, 0x04,
|
|
436
|
+
...device,
|
|
437
|
+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
438
|
+
];
|
|
439
|
+
|
|
440
|
+
const val1 = [...(aqaraHeader(0x12, params1, 0x04)), ...params1];
|
|
441
|
+
const val2 = [...(aqaraHeader(0x13, params2, 0x04)), ...params2];
|
|
442
|
+
|
|
443
|
+
await entity.write('aqaraOpple', {0xfff2: {value: val1, type: 0x41}}, {manufacturerCode: 0x115f});
|
|
444
|
+
await entity.write('aqaraOpple', {0xfff2: {value: val2, type: 0x41}}, {manufacturerCode: 0x115f});
|
|
445
|
+
|
|
446
|
+
await entity.read('hvacThermostat', ['localTemp']);
|
|
447
|
+
}
|
|
448
|
+
break;
|
|
449
|
+
}
|
|
450
|
+
case 'sensor_temp':
|
|
451
|
+
if (meta.state['sensor'] === 'external') {
|
|
452
|
+
const temperatureBuf = Buffer.alloc(4);
|
|
453
|
+
temperatureBuf.writeFloatBE(Math.round(value * 100));
|
|
454
|
+
|
|
455
|
+
const params = [...sensor, 0x00, 0x01, 0x00, 0x55, ...temperatureBuf];
|
|
456
|
+
const data = [...(aqaraHeader(0x12, params, 0x05)), ...params];
|
|
457
|
+
|
|
458
|
+
await entity.write('aqaraOpple', {0xfff2: {value: data, type: 0x41}}, {manufacturerCode: 0x115f});
|
|
459
|
+
}
|
|
460
|
+
break;
|
|
461
|
+
case 'calibrate':
|
|
462
|
+
await entity.write('aqaraOpple', {0x0270: {value: 1, type: 0x20}}, {manufacturerCode: 0x115F});
|
|
463
|
+
break;
|
|
464
|
+
case 'identify':
|
|
465
|
+
await entity.command('genIdentify', 'identify', {identifytime: 5}, {});
|
|
466
|
+
break;
|
|
467
|
+
case 'schedule':
|
|
468
|
+
await entity.write('aqaraOpple', {0x027d: {value: {'OFF': 0, 'ON': 1}[value], type: 0x20}},
|
|
469
|
+
{manufacturerCode: 0x115f});
|
|
470
|
+
break;
|
|
471
|
+
case 'schedule_settings': {
|
|
472
|
+
const schedule = trv.parseSchedule(value);
|
|
473
|
+
trv.validateSchedule(schedule);
|
|
474
|
+
const buffer = trv.encodeSchedule(schedule);
|
|
475
|
+
await entity.write('aqaraOpple', {0x0276: {value: buffer, type: 0x41}}, {manufacturerCode: 0x115f});
|
|
476
|
+
break;
|
|
477
|
+
}
|
|
478
|
+
default: // Unknown key
|
|
479
|
+
meta.logger.warn(`zigbee-herdsman-converters:aqara_trv: Unhandled key ${key}`);
|
|
480
|
+
}
|
|
481
|
+
},
|
|
482
|
+
convertGet: async (entity, key, meta) => {
|
|
483
|
+
const dict = {'system_mode': 0x0271, 'preset': 0x0272, 'window_detection': 0x0273, 'valve_detection': 0x0274,
|
|
484
|
+
'child_lock': 0x0277, 'away_preset_temperature': 0x0279, 'calibrated': 0x027b, 'sensor': 0x027e,
|
|
485
|
+
'schedule': 0x027d, 'schedule_settings': 0x0276};
|
|
486
|
+
|
|
487
|
+
if (dict.hasOwnProperty(key)) {
|
|
488
|
+
await entity.read('aqaraOpple', [dict[key]], {manufacturerCode: 0x115F});
|
|
489
|
+
}
|
|
490
|
+
},
|
|
491
|
+
},
|
|
492
|
+
VOCKQJK11LM_display_unit: {
|
|
493
|
+
key: ['display_unit'],
|
|
494
|
+
convertSet: async (entity, key, value, meta) => {
|
|
495
|
+
await entity.write('aqaraOpple',
|
|
496
|
+
{0x0114: {value: xiaomi.VOCKQJK11LMDisplayUnit[value], type: 0x20}}, {manufacturerCode: 0x115F});
|
|
497
|
+
return {state: {display_unit: value}};
|
|
498
|
+
},
|
|
499
|
+
convertGet: async (entity, key, meta) => {
|
|
500
|
+
await entity.read('aqaraOpple', [0x0114], {manufacturerCode: 0x115F, disableDefaultResponse: true});
|
|
501
|
+
},
|
|
502
|
+
},
|
|
503
|
+
aqara_feeder: {
|
|
504
|
+
key: ['feed', 'schedule', 'led_indicator', 'child_lock', 'mode', 'serving_size', 'portion_weight'],
|
|
505
|
+
convertSet: async (entity, key, value, meta) => {
|
|
506
|
+
const sendAttr = async (attrCode, value, length) => {
|
|
507
|
+
entity.sendSeq = ((entity.sendSeq || 0)+1) % 256;
|
|
508
|
+
const val = Buffer.from([0x00, 0x02, entity.sendSeq, 0, 0, 0, 0, 0]);
|
|
509
|
+
entity.sendSeq += 1;
|
|
510
|
+
val.writeInt32BE(attrCode, 3);
|
|
511
|
+
val.writeUInt8(length, 7);
|
|
512
|
+
let v = Buffer.alloc(length);
|
|
513
|
+
switch (length) {
|
|
514
|
+
case 1:
|
|
515
|
+
v.writeUInt8(value);
|
|
516
|
+
break;
|
|
517
|
+
case 2:
|
|
518
|
+
v.writeUInt16BE(value);
|
|
519
|
+
break;
|
|
520
|
+
case 4:
|
|
521
|
+
v.writeUInt32BE(value);
|
|
522
|
+
break;
|
|
523
|
+
default:
|
|
524
|
+
v = value;
|
|
525
|
+
}
|
|
526
|
+
await entity.write('aqaraOpple', {0xfff1: {value: Buffer.concat([val, v]), type: 0x41}},
|
|
527
|
+
{manufacturerCode: 0x115f});
|
|
528
|
+
};
|
|
529
|
+
switch (key) {
|
|
530
|
+
case 'feed':
|
|
531
|
+
sendAttr(0x04150055, 1, 1);
|
|
532
|
+
break;
|
|
533
|
+
case 'schedule': {
|
|
534
|
+
const schedule = [];
|
|
535
|
+
value.forEach((item) => {
|
|
536
|
+
const schedItem = Buffer.from([
|
|
537
|
+
utils.getKey(daysLookup, item.days, 0x7f),
|
|
538
|
+
item.hour,
|
|
539
|
+
item.minute,
|
|
540
|
+
item.size,
|
|
541
|
+
0,
|
|
542
|
+
]);
|
|
543
|
+
schedule.push(schedItem.toString('hex'));
|
|
544
|
+
});
|
|
545
|
+
const val = Buffer.concat([Buffer.from(schedule.join(',')), Buffer.from([0])]);
|
|
546
|
+
sendAttr(0x080008c8, val, val.length);
|
|
547
|
+
break;
|
|
548
|
+
}
|
|
549
|
+
case 'led_indicator':
|
|
550
|
+
sendAttr(0x04170055, {'OFF': 0, 'ON': 1}[value], 1);
|
|
551
|
+
break;
|
|
552
|
+
case 'child_lock':
|
|
553
|
+
sendAttr(0x04160055, {'UNLOCK': 0, 'LOCK': 1}[value], 1);
|
|
554
|
+
break;
|
|
555
|
+
case 'mode':
|
|
556
|
+
sendAttr(0x04180055, {'manual': 0, 'schedule': 1}[value], 1);
|
|
557
|
+
break;
|
|
558
|
+
case 'serving_size':
|
|
559
|
+
sendAttr(0x0e5c0055, value, 4);
|
|
560
|
+
break;
|
|
561
|
+
case 'portion_weight':
|
|
562
|
+
sendAttr(0x0e5f0055, value, 4);
|
|
563
|
+
break;
|
|
564
|
+
default: // Unknown key
|
|
565
|
+
meta.logger.warn(`zigbee-herdsman-converters:aqara_feeder: Unhandled key ${key}`);
|
|
566
|
+
}
|
|
567
|
+
return {state: {[key]: value}};
|
|
568
|
+
},
|
|
569
|
+
},
|
|
570
|
+
aqara_fp1_region_upsert: {
|
|
571
|
+
key: ['region_upsert'],
|
|
572
|
+
convertSet: async (entity, key, value, meta) => {
|
|
573
|
+
const log = utils.createLogger(meta.logger, 'xiaomi', 'aqara_fp1:region_upsert');
|
|
574
|
+
const commandWrapper = fp1.parseAqaraFp1RegionUpsertInput(value);
|
|
575
|
+
|
|
576
|
+
if (!commandWrapper.isSuccess) {
|
|
577
|
+
log('warn',
|
|
578
|
+
`encountered an error (${commandWrapper.error.reason}) ` +
|
|
579
|
+
`while parsing configuration commands (input: ${JSON.stringify(value)})`,
|
|
580
|
+
);
|
|
581
|
+
|
|
582
|
+
return;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
const command = commandWrapper.payload.command;
|
|
586
|
+
|
|
587
|
+
log('debug', `trying to create region ${command.region_id}`);
|
|
588
|
+
|
|
589
|
+
/** @type {Record<string, Set<number>>} */
|
|
590
|
+
const sortedZonesAccumulator = {};
|
|
591
|
+
const sortedZones = command.zones
|
|
592
|
+
.reduce(
|
|
593
|
+
(accumulator, zone) => {
|
|
594
|
+
if (!accumulator[zone.y]) {
|
|
595
|
+
accumulator[zone.y] = new Set();
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
accumulator[zone.y].add(zone.x);
|
|
599
|
+
|
|
600
|
+
return accumulator;
|
|
601
|
+
},
|
|
602
|
+
sortedZonesAccumulator,
|
|
603
|
+
);
|
|
604
|
+
|
|
605
|
+
const deviceConfig = new Uint8Array(7);
|
|
606
|
+
|
|
607
|
+
// Command parameters
|
|
608
|
+
deviceConfig[0] = fp1.constants.region_config_cmds.create;
|
|
609
|
+
deviceConfig[1] = command.region_id;
|
|
610
|
+
deviceConfig[6] = fp1.constants.region_config_cmd_suffix_upsert;
|
|
611
|
+
// Zones definition
|
|
612
|
+
deviceConfig[2] |= fp1.encodeXCellsDefinition(sortedZones['1']);
|
|
613
|
+
deviceConfig[2] |= fp1.encodeXCellsDefinition(sortedZones['2']) << 4;
|
|
614
|
+
deviceConfig[3] |= fp1.encodeXCellsDefinition(sortedZones['3']);
|
|
615
|
+
deviceConfig[3] |= fp1.encodeXCellsDefinition(sortedZones['4']) << 4;
|
|
616
|
+
deviceConfig[4] |= fp1.encodeXCellsDefinition(sortedZones['5']);
|
|
617
|
+
deviceConfig[4] |= fp1.encodeXCellsDefinition(sortedZones['6']) << 4;
|
|
618
|
+
deviceConfig[5] |= fp1.encodeXCellsDefinition(sortedZones['7']);
|
|
619
|
+
|
|
620
|
+
log('info', `create region ${command.region_id} ${printNumbersAsHexSequence([...deviceConfig], 2)}`);
|
|
621
|
+
|
|
622
|
+
const payload = {
|
|
623
|
+
[fp1.constants.region_config_write_attribute]: {
|
|
624
|
+
value: deviceConfig,
|
|
625
|
+
type: fp1.constants.region_config_write_attribute_type,
|
|
626
|
+
},
|
|
627
|
+
};
|
|
628
|
+
|
|
629
|
+
await entity.write('aqaraOpple', payload, {manufacturerCode});
|
|
630
|
+
},
|
|
631
|
+
},
|
|
632
|
+
aqara_fp1_region_delete: {
|
|
633
|
+
key: ['region_delete'],
|
|
634
|
+
convertSet: async (entity, key, value, meta) => {
|
|
635
|
+
const log = utils.createLogger(meta.logger, 'xiaomi', 'aqara_fp1:region_delete');
|
|
636
|
+
const commandWrapper = fp1.parseAqaraFp1RegionDeleteInput(value);
|
|
637
|
+
|
|
638
|
+
if (!commandWrapper.isSuccess) {
|
|
639
|
+
log('warn',
|
|
640
|
+
`encountered an error (${commandWrapper.error.reason}) ` +
|
|
641
|
+
`while parsing configuration commands (input: ${JSON.stringify(value)})`,
|
|
642
|
+
);
|
|
643
|
+
return;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
const command = commandWrapper.payload.command;
|
|
647
|
+
|
|
648
|
+
log('debug', `trying to delete region ${command.region_id}`);
|
|
649
|
+
|
|
650
|
+
const deviceConfig = new Uint8Array(7);
|
|
651
|
+
|
|
652
|
+
// Command parameters
|
|
653
|
+
deviceConfig[0] = fp1.constants.region_config_cmds.delete;
|
|
654
|
+
deviceConfig[1] = command.region_id;
|
|
655
|
+
deviceConfig[6] = fp1.constants.region_config_cmd_suffix_delete;
|
|
656
|
+
// Zones definition
|
|
657
|
+
deviceConfig[2] = 0;
|
|
658
|
+
deviceConfig[3] = 0;
|
|
659
|
+
deviceConfig[4] = 0;
|
|
660
|
+
deviceConfig[5] = 0;
|
|
661
|
+
|
|
662
|
+
log('info',
|
|
663
|
+
`delete region ${command.region_id} ` +
|
|
664
|
+
`(${printNumbersAsHexSequence([...deviceConfig], 2)})`,
|
|
665
|
+
);
|
|
666
|
+
|
|
667
|
+
const payload = {
|
|
668
|
+
[fp1.constants.region_config_write_attribute]: {
|
|
669
|
+
value: deviceConfig,
|
|
670
|
+
type: fp1.constants.region_config_write_attribute_type,
|
|
671
|
+
},
|
|
672
|
+
};
|
|
673
|
+
|
|
674
|
+
await entity.write('aqaraOpple', payload, {manufacturerCode});
|
|
675
|
+
},
|
|
676
|
+
},
|
|
677
|
+
CTPR01_operation_mode: {
|
|
678
|
+
key: ['operation_mode'],
|
|
679
|
+
convertSet: async (entity, key, value, meta) => {
|
|
680
|
+
const lookup = {action_mode: 0, scene_mode: 1};
|
|
681
|
+
/**
|
|
682
|
+
* schedule the callback to run when the configuration window comes
|
|
683
|
+
*/
|
|
684
|
+
const callback = async () => {
|
|
685
|
+
await entity.write(
|
|
686
|
+
'aqaraOpple',
|
|
687
|
+
{0x0148: {value: lookup[value], type: 0x20}},
|
|
688
|
+
{manufacturerCode: 0x115f, disableDefaultResponse: true},
|
|
689
|
+
);
|
|
690
|
+
meta.logger.info('operation_mode switch success!');
|
|
691
|
+
};
|
|
692
|
+
globalStore.putValue(meta.device, 'opModeSwitchTask', {callback, newMode: value});
|
|
693
|
+
meta.logger.info('Now give your cube a forceful throw motion (Careful not to drop it)!');
|
|
694
|
+
},
|
|
695
|
+
},
|
|
696
|
+
};
|
|
697
|
+
|
|
698
|
+
module.exports = [
|
|
699
|
+
{
|
|
700
|
+
zigbeeModel: ['lumi.flood.acn001'],
|
|
701
|
+
model: 'SJCGQ13LM',
|
|
702
|
+
vendor: 'Xiaomi',
|
|
703
|
+
description: 'Aqara E1 water leak sensor',
|
|
704
|
+
fromZigbee: [fz.ias_water_leak_alarm_1, fz.aqara_opple, fz.battery],
|
|
705
|
+
toZigbee: [],
|
|
706
|
+
exposes: [e.water_leak(), e.battery(), e.battery_low(), e.battery_voltage(), e.device_temperature(), e.power_outage_count(false)],
|
|
707
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
708
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
709
|
+
const endpoint = device.getEndpoint(1);
|
|
710
|
+
await endpoint.read('genPowerCfg', ['batteryVoltage']);
|
|
711
|
+
},
|
|
712
|
+
ota: ota.zigbeeOTA,
|
|
713
|
+
},
|
|
714
|
+
{
|
|
715
|
+
zigbeeModel: ['lumi.airm.fhac01'],
|
|
716
|
+
model: 'KQJCMB11LM',
|
|
717
|
+
vendor: 'Xiaomi',
|
|
718
|
+
description: 'Aqara air monitoring panel S1',
|
|
719
|
+
fromZigbee: [fz.temperature, fz.humidity, fzLocal.aqara_s1_pm25, fzLocal.aqara_s1_co2],
|
|
720
|
+
toZigbee: [],
|
|
721
|
+
exposes: [e.temperature(), e.humidity(), e.pm25(), e.co2()],
|
|
722
|
+
ota: ota.zigbeeOTA,
|
|
723
|
+
},
|
|
724
|
+
{
|
|
725
|
+
zigbeeModel: ['lumi.magnet.acn001'],
|
|
726
|
+
model: 'MCCGQ14LM',
|
|
727
|
+
vendor: 'Xiaomi',
|
|
728
|
+
description: 'Aqara E1 door & window contact sensor',
|
|
729
|
+
fromZigbee: [fz.ias_contact_alarm_1, fz.aqara_opple, fz.battery],
|
|
730
|
+
toZigbee: [],
|
|
731
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
732
|
+
exposes: [e.contact(), e.battery(), e.battery_low(), e.battery_voltage()],
|
|
733
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
734
|
+
const endpoint = device.getEndpoint(1);
|
|
735
|
+
await endpoint.read('genPowerCfg', ['batteryVoltage']);
|
|
736
|
+
},
|
|
737
|
+
// OTA request: "fieldControl":0, "manufacturerCode":4447, "imageType":10635
|
|
738
|
+
ota: ota.zigbeeOTA,
|
|
739
|
+
},
|
|
740
|
+
{
|
|
741
|
+
zigbeeModel: ['lumi.magnet.ac01'],
|
|
742
|
+
model: 'MCCGQ13LM',
|
|
743
|
+
vendor: 'Xiaomi',
|
|
744
|
+
description: 'Aqara P1 door & window contact sensor',
|
|
745
|
+
fromZigbee: [fz.xiaomi_contact, fz.ias_contact_alarm_1, fz.aqara_opple],
|
|
746
|
+
toZigbee: [],
|
|
747
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
748
|
+
exposes: [e.contact(), e.battery(), e.battery_voltage(),
|
|
749
|
+
exposes.binary('battery_cover', ea.STATE, 'OPEN', 'CLOSE'),
|
|
750
|
+
],
|
|
751
|
+
},
|
|
752
|
+
{
|
|
753
|
+
zigbeeModel: ['lumi.dimmer.rcbac1'],
|
|
754
|
+
model: 'ZNDDMK11LM',
|
|
755
|
+
vendor: 'Xiaomi',
|
|
756
|
+
description: 'Aqara smart lightstrip driver',
|
|
757
|
+
fromZigbee: extend.light_onoff_brightness_colortemp_color().fromZigbee.concat([
|
|
758
|
+
fz.xiaomi_power, fz.aqara_opple]),
|
|
759
|
+
toZigbee: extend.light_onoff_brightness_colortemp_color().toZigbee.concat([
|
|
760
|
+
tz.xiaomi_dimmer_mode, tz.xiaomi_switch_power_outage_memory]),
|
|
761
|
+
meta: {multiEndpoint: true},
|
|
762
|
+
endpoint: (device) => {
|
|
763
|
+
return {l1: 1, l2: 2};
|
|
764
|
+
},
|
|
765
|
+
exposes: [e.power(), e.energy(), e.voltage(), e.device_temperature(), e.power_outage_memory(),
|
|
766
|
+
// When in rgbw mode, only one of color and colortemp will be valid, and l2 will be invalid
|
|
767
|
+
// Do not control l2 in rgbw mode
|
|
768
|
+
e.light_brightness_colortemp_colorxy([153, 370]).removeFeature('color_temp_startup').withEndpoint('l1'),
|
|
769
|
+
e.light_brightness_colortemp([153, 370]).removeFeature('color_temp_startup').withEndpoint('l2'),
|
|
770
|
+
exposes.enum('dimmer_mode', ea.ALL, ['rgbw', 'dual_ct'])
|
|
771
|
+
.withDescription('Switch between rgbw mode or dual color temperature mode')],
|
|
772
|
+
ota: ota.zigbeeOTA,
|
|
773
|
+
},
|
|
774
|
+
{
|
|
775
|
+
zigbeeModel: ['lumi.light.aqcn02'],
|
|
776
|
+
model: 'ZNLDP12LM',
|
|
777
|
+
vendor: 'Xiaomi',
|
|
778
|
+
description: 'Aqara smart LED bulb',
|
|
779
|
+
toZigbee: xiaomiExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 370]}).toZigbee.concat([
|
|
780
|
+
tz.xiaomi_light_power_outage_memory]),
|
|
781
|
+
fromZigbee: xiaomiExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 370]}).fromZigbee,
|
|
782
|
+
// power_on_behavior 'toggle' does not seem to be supported
|
|
783
|
+
exposes: xiaomiExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 370]}).exposes.concat([
|
|
784
|
+
e.power_outage_memory().withAccess(ea.STATE_SET)]),
|
|
785
|
+
ota: ota.zigbeeOTA,
|
|
786
|
+
},
|
|
787
|
+
{
|
|
788
|
+
zigbeeModel: ['lumi.light.acn003'],
|
|
789
|
+
model: 'ZNXDD01LM',
|
|
790
|
+
vendor: 'Xiaomi',
|
|
791
|
+
description: 'Aqara ceiling light L1-350',
|
|
792
|
+
extend: xiaomiExtend.light_onoff_brightness_colortemp({disableEffect: true, colorTempRange: [153, 370]}),
|
|
793
|
+
ota: ota.zigbeeOTA,
|
|
794
|
+
},
|
|
795
|
+
{
|
|
796
|
+
zigbeeModel: ['lumi.light.cwac02', 'lumi.light.acn014'],
|
|
797
|
+
model: 'ZNLDP13LM',
|
|
798
|
+
vendor: 'Xiaomi',
|
|
799
|
+
description: 'Aqara T1 smart LED bulb',
|
|
800
|
+
toZigbee: xiaomiExtend.light_onoff_brightness_colortemp({disableEffect: true, disablePowerOnBehavior: true}).toZigbee.concat([
|
|
801
|
+
tz.xiaomi_switch_power_outage_memory,
|
|
802
|
+
]),
|
|
803
|
+
fromZigbee: xiaomiExtend.light_onoff_brightness_colortemp({disableEffect: true, disablePowerOnBehavior: true}).fromZigbee.concat([
|
|
804
|
+
fz.aqara_opple,
|
|
805
|
+
]),
|
|
806
|
+
exposes: xiaomiExtend.light_onoff_brightness_colortemp({
|
|
807
|
+
disableEffect: true,
|
|
808
|
+
disablePowerOnBehavior: true,
|
|
809
|
+
colorTempRange: [153, 370],
|
|
810
|
+
}).exposes.concat([
|
|
811
|
+
e.power_outage_memory(),
|
|
812
|
+
e.device_temperature(),
|
|
813
|
+
e.power_outage_count(),
|
|
814
|
+
]),
|
|
815
|
+
ota: ota.zigbeeOTA,
|
|
816
|
+
},
|
|
817
|
+
{
|
|
818
|
+
zigbeeModel: ['lumi.light.cwopcn01'],
|
|
819
|
+
model: 'XDD11LM',
|
|
820
|
+
vendor: 'Xiaomi',
|
|
821
|
+
description: 'Aqara Opple MX960',
|
|
822
|
+
meta: {turnsOffAtBrightness1: true},
|
|
823
|
+
extend: xiaomiExtend.light_onoff_brightness_colortemp({disableEffect: true, disableColorTempStartup: true,
|
|
824
|
+
colorTempRange: [175, 370]}),
|
|
825
|
+
ota: ota.zigbeeOTA,
|
|
826
|
+
},
|
|
827
|
+
{
|
|
828
|
+
zigbeeModel: ['lumi.light.cwopcn02'],
|
|
829
|
+
model: 'XDD12LM',
|
|
830
|
+
vendor: 'Xiaomi',
|
|
831
|
+
description: 'Aqara Opple MX650',
|
|
832
|
+
meta: {turnsOffAtBrightness1: true},
|
|
833
|
+
extend: xiaomiExtend.light_onoff_brightness_colortemp({disableEffect: true, disableColorTempStartup: true,
|
|
834
|
+
colorTempRange: [175, 370]}),
|
|
835
|
+
ota: ota.zigbeeOTA,
|
|
836
|
+
},
|
|
837
|
+
{
|
|
838
|
+
zigbeeModel: ['lumi.light.cwopcn03'],
|
|
839
|
+
model: 'XDD13LM',
|
|
840
|
+
vendor: 'Xiaomi',
|
|
841
|
+
description: 'Aqara Opple MX480',
|
|
842
|
+
meta: {turnsOffAtBrightness1: true},
|
|
843
|
+
extend: xiaomiExtend.light_onoff_brightness_colortemp({disableEffect: true, disableColorTempStartup: true,
|
|
844
|
+
colorTempRange: [175, 370]}),
|
|
845
|
+
ota: ota.zigbeeOTA,
|
|
846
|
+
},
|
|
847
|
+
{
|
|
848
|
+
zigbeeModel: ['lumi.light.cwjwcn01'],
|
|
849
|
+
model: 'JWSP001A',
|
|
850
|
+
vendor: 'Xiaomi',
|
|
851
|
+
description: 'Jiawen LED Driver & Dimmer',
|
|
852
|
+
extend: xiaomiExtend.light_onoff_brightness_colortemp({disableEffect: true, disableColorTempStartup: true,
|
|
853
|
+
colorTempRange: [153, 370]}),
|
|
854
|
+
},
|
|
855
|
+
{
|
|
856
|
+
zigbeeModel: ['lumi.light.cwjwcn02'],
|
|
857
|
+
model: 'JWDL001A',
|
|
858
|
+
vendor: 'Xiaomi',
|
|
859
|
+
description: 'Aqara embedded spot led light',
|
|
860
|
+
extend: xiaomiExtend.light_onoff_brightness_colortemp({colorTempRange: [153, 370]}),
|
|
861
|
+
},
|
|
862
|
+
{
|
|
863
|
+
zigbeeModel: ['lumi.sensor_switch'],
|
|
864
|
+
model: 'WXKG01LM',
|
|
865
|
+
vendor: 'Xiaomi',
|
|
866
|
+
whiteLabel: [{vendor: 'Xiaomi', model: 'YTC4040GL'}, {vendor: 'Xiaomi', model: 'YTC4006CN'},
|
|
867
|
+
{vendor: 'Xiaomi', model: 'YTC4017CN'}, {vendor: 'Xiaomi', model: 'ZHTZ02LM'}],
|
|
868
|
+
description: 'MiJia wireless switch',
|
|
869
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
870
|
+
fromZigbee: [fz.xiaomi_basic, fz.xiaomi_WXKG01LM_action, fz.legacy.WXKG01LM_click],
|
|
871
|
+
exposes: [e.battery(), e.action(['single', 'double', 'triple', 'quadruple', 'hold', 'release', 'many']), e.battery_voltage(),
|
|
872
|
+
e.power_outage_count(false)],
|
|
873
|
+
toZigbee: [],
|
|
874
|
+
},
|
|
875
|
+
{
|
|
876
|
+
zigbeeModel: ['lumi.sensor_switch.aq2', 'lumi.remote.b1acn01'],
|
|
877
|
+
model: 'WXKG11LM',
|
|
878
|
+
vendor: 'Xiaomi',
|
|
879
|
+
description: 'Aqara wireless switch',
|
|
880
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
881
|
+
exposes: [e.battery(), e.battery_voltage(), e.action(['single', 'double', 'triple', 'quadruple', 'hold', 'release']),
|
|
882
|
+
e.device_temperature(), e.power_outage_count()],
|
|
883
|
+
fromZigbee: [fz.xiaomi_multistate_action, fz.xiaomi_WXKG11LM_action, fz.xiaomi_basic,
|
|
884
|
+
fz.legacy.WXKG11LM_click, fz.legacy.xiaomi_action_click_multistate],
|
|
885
|
+
toZigbee: [],
|
|
886
|
+
},
|
|
887
|
+
{
|
|
888
|
+
zigbeeModel: ['lumi.sensor_switch.aq3', 'lumi.sensor_swit'],
|
|
889
|
+
model: 'WXKG12LM',
|
|
890
|
+
vendor: 'Xiaomi',
|
|
891
|
+
description: 'Aqara wireless switch (with gyroscope)',
|
|
892
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
893
|
+
exposes: [e.battery(), e.action(['single', 'double', 'hold', 'release', 'shake']), e.battery_voltage()],
|
|
894
|
+
fromZigbee: [fz.xiaomi_basic, fz.xiaomi_multistate_action, fz.legacy.WXKG12LM_action_click_multistate],
|
|
895
|
+
toZigbee: [],
|
|
896
|
+
},
|
|
897
|
+
{
|
|
898
|
+
zigbeeModel: ['lumi.sensor_86sw1'],
|
|
899
|
+
model: 'WXKG03LM_rev1',
|
|
900
|
+
vendor: 'Xiaomi',
|
|
901
|
+
description: 'Aqara single key wireless wall switch (2016 model)',
|
|
902
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
903
|
+
exposes: [e.battery(), e.action(['single']), e.battery_voltage()],
|
|
904
|
+
fromZigbee: [fz.xiaomi_on_off_action, fz.xiaomi_basic, fz.legacy.WXKG03LM_click],
|
|
905
|
+
toZigbee: [],
|
|
906
|
+
onEvent: preventReset,
|
|
907
|
+
},
|
|
908
|
+
{
|
|
909
|
+
zigbeeModel: ['lumi.remote.b186acn01'],
|
|
910
|
+
model: 'WXKG03LM_rev2',
|
|
911
|
+
vendor: 'Xiaomi',
|
|
912
|
+
description: 'Aqara single key wireless wall switch (2018 model)',
|
|
913
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
914
|
+
exposes: [e.battery(), e.action(['single', 'double', 'hold']), e.battery_voltage()],
|
|
915
|
+
fromZigbee: [fz.xiaomi_on_off_action, fz.xiaomi_multistate_action, fz.xiaomi_basic,
|
|
916
|
+
fz.legacy.WXKG03LM_click, fz.legacy.xiaomi_action_click_multistate],
|
|
917
|
+
toZigbee: [],
|
|
918
|
+
onEvent: preventReset,
|
|
919
|
+
},
|
|
920
|
+
{
|
|
921
|
+
zigbeeModel: ['lumi.remote.b186acn02'],
|
|
922
|
+
model: 'WXKG06LM',
|
|
923
|
+
vendor: 'Xiaomi',
|
|
924
|
+
description: 'Aqara D1 single key wireless wall switch',
|
|
925
|
+
fromZigbee: [fz.xiaomi_basic, fz.xiaomi_on_off_action, fz.xiaomi_multistate_action],
|
|
926
|
+
toZigbee: [],
|
|
927
|
+
exposes: [e.battery(),
|
|
928
|
+
e.action(['single', 'double', 'hold']),
|
|
929
|
+
e.battery_voltage()],
|
|
930
|
+
onEvent: preventReset,
|
|
931
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
932
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
933
|
+
try {
|
|
934
|
+
const endpoint = device.endpoints[1];
|
|
935
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'genPowerCfg']);
|
|
936
|
+
} catch (error) {
|
|
937
|
+
// fails for some but device works as expected: https://github.com/Koenkk/zigbee2mqtt/issues/9136
|
|
938
|
+
}
|
|
939
|
+
},
|
|
940
|
+
},
|
|
941
|
+
{
|
|
942
|
+
zigbeeModel: ['lumi.sensor_86sw2', 'lumi.sensor_86sw2.es1'],
|
|
943
|
+
model: 'WXKG02LM_rev1',
|
|
944
|
+
vendor: 'Xiaomi',
|
|
945
|
+
description: 'Aqara double key wireless wall switch (2016 model)',
|
|
946
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
947
|
+
exposes: [e.battery(), e.action(['single_left', 'single_right', 'single_both']), e.battery_voltage(), e.power_outage_count(false)],
|
|
948
|
+
fromZigbee: [fz.xiaomi_on_off_action, fz.xiaomi_basic, fz.legacy.WXKG02LM_click],
|
|
949
|
+
toZigbee: [],
|
|
950
|
+
onEvent: preventReset,
|
|
951
|
+
},
|
|
952
|
+
{
|
|
953
|
+
zigbeeModel: ['lumi.remote.b286acn01'],
|
|
954
|
+
model: 'WXKG02LM_rev2',
|
|
955
|
+
vendor: 'Xiaomi',
|
|
956
|
+
description: 'Aqara double key wireless wall switch (2018 model)',
|
|
957
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
958
|
+
exposes: [e.battery(), e.action(['single_left', 'single_right', 'single_both', 'double_left', 'double_right', 'double_both',
|
|
959
|
+
'hold_left', 'hold_right', 'hold_both']), e.battery_voltage()],
|
|
960
|
+
fromZigbee: [fz.xiaomi_on_off_action, fz.xiaomi_multistate_action, fz.xiaomi_basic,
|
|
961
|
+
fz.legacy.WXKG02LM_click, fz.legacy.WXKG02LM_click_multistate],
|
|
962
|
+
toZigbee: [],
|
|
963
|
+
onEvent: preventReset,
|
|
964
|
+
},
|
|
965
|
+
{
|
|
966
|
+
zigbeeModel: ['lumi.switch.b1laus01'],
|
|
967
|
+
model: 'WS-USC01',
|
|
968
|
+
vendor: 'Xiaomi',
|
|
969
|
+
description: 'Aqara smart wall switch (no neutral, single rocker)',
|
|
970
|
+
fromZigbee: [fz.on_off, fz.xiaomi_multistate_action, fz.aqara_opple],
|
|
971
|
+
toZigbee: [tz.on_off, tz.xiaomi_switch_operation_mode_opple,
|
|
972
|
+
tz.xiaomi_flip_indicator_light, tz.aqara_switch_mode_switch],
|
|
973
|
+
exposes: [e.switch(), e.action(['single', 'double']), e.flip_indicator_light(),
|
|
974
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled']).withDescription('Decoupled mode'),
|
|
975
|
+
exposes.enum('mode_switch', ea.ALL, ['anti_flicker_mode', 'quick_mode'])
|
|
976
|
+
.withDescription('Anti flicker mode can be used to solve blinking issues of some lights.' +
|
|
977
|
+
'Quick mode makes the device respond faster.'),
|
|
978
|
+
e.power_outage_count(), e.device_temperature().withAccess(ea.STATE)],
|
|
979
|
+
onEvent: preventReset,
|
|
980
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
981
|
+
const endpoint1 = device.getEndpoint(1);
|
|
982
|
+
// set "event" mode
|
|
983
|
+
await endpoint1.write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
|
|
984
|
+
},
|
|
985
|
+
ota: ota.zigbeeOTA,
|
|
986
|
+
},
|
|
987
|
+
{
|
|
988
|
+
zigbeeModel: ['lumi.switch.b2laus01'],
|
|
989
|
+
model: 'WS-USC02',
|
|
990
|
+
vendor: 'Xiaomi',
|
|
991
|
+
description: 'Aqara smart wall switch (no neutral, double rocker)',
|
|
992
|
+
fromZigbee: [fz.on_off, fz.xiaomi_multistate_action, fz.aqara_opple],
|
|
993
|
+
toZigbee: [
|
|
994
|
+
tz.on_off, tz.xiaomi_switch_operation_mode_opple, tz.xiaomi_flip_indicator_light,
|
|
995
|
+
tz.xiaomi_switch_power_outage_memory, tz.aqara_switch_mode_switch],
|
|
996
|
+
exposes: [
|
|
997
|
+
e.switch().withEndpoint('top'),
|
|
998
|
+
e.switch().withEndpoint('bottom'),
|
|
999
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
1000
|
+
.withDescription('Decoupled mode for top button')
|
|
1001
|
+
.withEndpoint('top'),
|
|
1002
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
1003
|
+
.withDescription('Decoupled mode for bottom button')
|
|
1004
|
+
.withEndpoint('bottom'),
|
|
1005
|
+
exposes.enum('mode_switch', ea.ALL, ['anti_flicker_mode', 'quick_mode'])
|
|
1006
|
+
.withDescription(
|
|
1007
|
+
'Anti flicker mode can be used to solve blinking issues of some lights.' +
|
|
1008
|
+
'Quick mode makes the device respond faster.',
|
|
1009
|
+
),
|
|
1010
|
+
e.power_outage_count(),
|
|
1011
|
+
e.device_temperature().withAccess(ea.STATE),
|
|
1012
|
+
e.flip_indicator_light(),
|
|
1013
|
+
e.power_outage_memory(),
|
|
1014
|
+
e.action(['single_top', 'single_bottom', 'single_both', 'double_top', 'double_bottom', 'double_both'])],
|
|
1015
|
+
meta: {multiEndpoint: true},
|
|
1016
|
+
endpoint: (device) => {
|
|
1017
|
+
return {'top': 1, 'bottom': 2};
|
|
1018
|
+
},
|
|
1019
|
+
onEvent: preventReset,
|
|
1020
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1021
|
+
await device.getEndpoint(1).write(
|
|
1022
|
+
'aqaraOpple', {mode: 1}, {manufacturerCode: 0x115f, disableResponse: true},
|
|
1023
|
+
);
|
|
1024
|
+
},
|
|
1025
|
+
ota: ota.zigbeeOTA,
|
|
1026
|
+
},
|
|
1027
|
+
{
|
|
1028
|
+
zigbeeModel: ['lumi.switch.b1naus01'],
|
|
1029
|
+
model: 'WS-USC03',
|
|
1030
|
+
vendor: 'Xiaomi',
|
|
1031
|
+
description: 'Aqara smart wall switch (neutral, single rocker)',
|
|
1032
|
+
extend: extend.switch(),
|
|
1033
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1034
|
+
const endpoint = device.getEndpoint(1);
|
|
1035
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
|
|
1036
|
+
await reporting.onOff(endpoint);
|
|
1037
|
+
},
|
|
1038
|
+
ota: ota.zigbeeOTA,
|
|
1039
|
+
},
|
|
1040
|
+
{
|
|
1041
|
+
zigbeeModel: ['lumi.switch.b2naus01'],
|
|
1042
|
+
model: 'WS-USC04',
|
|
1043
|
+
vendor: 'Xiaomi',
|
|
1044
|
+
description: 'Aqara smart wall switch (neutral, double rocker)',
|
|
1045
|
+
fromZigbee: [fz.on_off, fz.xiaomi_power, fz.xiaomi_multistate_action, fz.aqara_opple],
|
|
1046
|
+
toZigbee: [
|
|
1047
|
+
tz.on_off, tz.xiaomi_power, tz.xiaomi_switch_operation_mode_opple, tz.xiaomi_switch_power_outage_memory,
|
|
1048
|
+
tz.xiaomi_flip_indicator_light],
|
|
1049
|
+
exposes: [
|
|
1050
|
+
e.switch().withEndpoint('top'),
|
|
1051
|
+
e.switch().withEndpoint('bottom'),
|
|
1052
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
1053
|
+
.withDescription('Decoupled mode for top button')
|
|
1054
|
+
.withEndpoint('top'),
|
|
1055
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
1056
|
+
.withDescription('Decoupled mode for bottom button')
|
|
1057
|
+
.withEndpoint('bottom'),
|
|
1058
|
+
e.power_outage_count(),
|
|
1059
|
+
e.device_temperature().withAccess(ea.STATE),
|
|
1060
|
+
e.flip_indicator_light(),
|
|
1061
|
+
e.power().withAccess(ea.STATE_GET),
|
|
1062
|
+
e.energy(),
|
|
1063
|
+
e.voltage(),
|
|
1064
|
+
e.power_outage_memory(),
|
|
1065
|
+
e.action(['single_top', 'single_bottom', 'single_both', 'double_top', 'double_bottom', 'double_both'])],
|
|
1066
|
+
meta: {multiEndpoint: true},
|
|
1067
|
+
endpoint: (device) => {
|
|
1068
|
+
return {'top': 1, 'bottom': 2};
|
|
1069
|
+
},
|
|
1070
|
+
onEvent: preventReset,
|
|
1071
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1072
|
+
await device.getEndpoint(1).write(
|
|
1073
|
+
'aqaraOpple', {mode: 1}, {manufacturerCode: 0x115f, disableResponse: true},
|
|
1074
|
+
);
|
|
1075
|
+
},
|
|
1076
|
+
ota: ota.zigbeeOTA,
|
|
1077
|
+
},
|
|
1078
|
+
{
|
|
1079
|
+
zigbeeModel: ['lumi.switch.l2acn1'],
|
|
1080
|
+
model: 'QBKG28LM',
|
|
1081
|
+
vendor: 'Xiaomi',
|
|
1082
|
+
description: 'Aqara smart wall switch H1 Pro (no neutral, double rocker)',
|
|
1083
|
+
fromZigbee: [fz.on_off, fz.xiaomi_multistate_action, fz.aqara_opple],
|
|
1084
|
+
toZigbee: [tz.on_off, tz.xiaomi_switch_operation_mode_opple, tz.xiaomi_switch_power_outage_memory,
|
|
1085
|
+
tz.xiaomi_flip_indicator_light, tz.xiaomi_led_disabled_night],
|
|
1086
|
+
meta: {multiEndpoint: true},
|
|
1087
|
+
endpoint: (device) => {
|
|
1088
|
+
return {'left': 1, 'right': 2};
|
|
1089
|
+
},
|
|
1090
|
+
exposes: [e.switch().withEndpoint('left'), e.switch().withEndpoint('right'), e.device_temperature(),
|
|
1091
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
1092
|
+
.withDescription('Decoupled mode for left button').withEndpoint('left'),
|
|
1093
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
1094
|
+
.withDescription('Decoupled mode for right button').withEndpoint('right'),
|
|
1095
|
+
e.action(['single_left', 'double_left', 'single_right', 'double_right', 'single_both', 'double_both']),
|
|
1096
|
+
e.power_outage_memory(), e.flip_indicator_light(), e.led_disabled_night()],
|
|
1097
|
+
onEvent: preventReset,
|
|
1098
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1099
|
+
await device.getEndpoint(1).write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
|
|
1100
|
+
},
|
|
1101
|
+
ota: ota.zigbeeOTA,
|
|
1102
|
+
},
|
|
1103
|
+
{
|
|
1104
|
+
zigbeeModel: ['lumi.switch.n2acn1'],
|
|
1105
|
+
model: 'QBKG31LM',
|
|
1106
|
+
vendor: 'Xiaomi',
|
|
1107
|
+
description: 'Aqara smart wall switch H1 Pro (with neutral, double rocker)',
|
|
1108
|
+
meta: {multiEndpoint: true},
|
|
1109
|
+
endpoint: (device) => {
|
|
1110
|
+
return {'left': 1, 'right': 2};
|
|
1111
|
+
},
|
|
1112
|
+
fromZigbee: [fz.on_off, fz.xiaomi_power, fz.aqara_opple, fz.xiaomi_multistate_action],
|
|
1113
|
+
toZigbee: [tz.on_off, tz.xiaomi_switch_operation_mode_opple, tz.xiaomi_switch_power_outage_memory,
|
|
1114
|
+
tz.xiaomi_led_disabled_night, tz.xiaomi_flip_indicator_light],
|
|
1115
|
+
exposes: [e.switch().withEndpoint('left'), e.switch().withEndpoint('right'), e.power(), e.energy(), e.voltage(),
|
|
1116
|
+
e.device_temperature(), e.power_outage_memory(), e.led_disabled_night(), e.flip_indicator_light(),
|
|
1117
|
+
e.action([
|
|
1118
|
+
'single_left', 'single_right', 'single_both',
|
|
1119
|
+
'double_left', 'double_right', 'double_both']),
|
|
1120
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
1121
|
+
.withDescription('Decoupled mode for left button').withEndpoint('left'),
|
|
1122
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
1123
|
+
.withDescription('Decoupled mode for right button').withEndpoint('right')],
|
|
1124
|
+
onEvent: preventReset,
|
|
1125
|
+
ota: ota.zigbeeOTA,
|
|
1126
|
+
},
|
|
1127
|
+
{
|
|
1128
|
+
zigbeeModel: ['lumi.switch.l1aeu1'],
|
|
1129
|
+
model: 'WS-EUK01',
|
|
1130
|
+
vendor: 'Xiaomi',
|
|
1131
|
+
description: 'Aqara smart wall switch H1 EU (no neutral, single rocker)',
|
|
1132
|
+
fromZigbee: [fz.on_off, fz.xiaomi_multistate_action, fz.aqara_opple],
|
|
1133
|
+
toZigbee: [tz.on_off, tz.xiaomi_switch_operation_mode_opple, tz.xiaomi_switch_power_outage_memory,
|
|
1134
|
+
tz.xiaomi_flip_indicator_light, tz.xiaomi_led_disabled_night, tz.aqara_switch_mode_switch],
|
|
1135
|
+
exposes: [e.switch(), e.action(['single', 'double']), e.power_outage_memory(), e.flip_indicator_light(),
|
|
1136
|
+
e.led_disabled_night(), e.power_outage_count(), e.device_temperature().withAccess(ea.STATE),
|
|
1137
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled']).withDescription('Decoupled mode'),
|
|
1138
|
+
exposes.enum('mode_switch', ea.ALL, ['anti_flicker_mode', 'quick_mode'])
|
|
1139
|
+
.withDescription('Anti flicker mode can be used to solve blinking issues of some lights.' +
|
|
1140
|
+
'Quick mode makes the device respond faster.')],
|
|
1141
|
+
onEvent: preventReset,
|
|
1142
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1143
|
+
const endpoint1 = device.getEndpoint(1);
|
|
1144
|
+
// set "event" mode
|
|
1145
|
+
await endpoint1.write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
|
|
1146
|
+
},
|
|
1147
|
+
},
|
|
1148
|
+
{
|
|
1149
|
+
zigbeeModel: ['lumi.switch.l2aeu1'],
|
|
1150
|
+
model: 'WS-EUK02',
|
|
1151
|
+
vendor: 'Xiaomi',
|
|
1152
|
+
description: 'Aqara smart wall switch H1 EU (no neutral, double rocker)',
|
|
1153
|
+
fromZigbee: [fz.on_off, fz.xiaomi_multistate_action, fz.aqara_opple],
|
|
1154
|
+
toZigbee: [tz.on_off, tz.xiaomi_switch_operation_mode_opple, tz.xiaomi_switch_power_outage_memory,
|
|
1155
|
+
tz.xiaomi_flip_indicator_light, tz.xiaomi_led_disabled_night, tz.aqara_switch_mode_switch],
|
|
1156
|
+
meta: {multiEndpoint: true},
|
|
1157
|
+
endpoint: (_device) => {
|
|
1158
|
+
return {'left': 1, 'right': 2};
|
|
1159
|
+
},
|
|
1160
|
+
exposes: [e.switch().withEndpoint('left'), e.switch().withEndpoint('right'), e.power_outage_memory(),
|
|
1161
|
+
e.flip_indicator_light(), e.led_disabled_night(), e.power_outage_count(),
|
|
1162
|
+
e.device_temperature().withAccess(ea.STATE),
|
|
1163
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
1164
|
+
.withDescription('Decoupled mode for left button')
|
|
1165
|
+
.withEndpoint('left'),
|
|
1166
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
1167
|
+
.withDescription('Decoupled mode for right button')
|
|
1168
|
+
.withEndpoint('right'),
|
|
1169
|
+
exposes.enum('mode_switch', ea.ALL, ['anti_flicker_mode', 'quick_mode'])
|
|
1170
|
+
.withDescription('Anti flicker mode can be used to solve blinking issues of some lights.' +
|
|
1171
|
+
'Quick mode makes the device respond faster.'),
|
|
1172
|
+
e.action(['single_left', 'double_left', 'single_right', 'double_right', 'single_both', 'double_both'])],
|
|
1173
|
+
onEvent: preventReset,
|
|
1174
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1175
|
+
await device.getEndpoint(1).write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
|
|
1176
|
+
},
|
|
1177
|
+
},
|
|
1178
|
+
{
|
|
1179
|
+
zigbeeModel: ['lumi.switch.l3acn1'],
|
|
1180
|
+
model: 'QBKG29LM',
|
|
1181
|
+
vendor: 'Xiaomi',
|
|
1182
|
+
description: 'Aqara smart wall switch H1 EU (no neutral, triple rocker)',
|
|
1183
|
+
fromZigbee: [fz.on_off, fz.xiaomi_multistate_action, fz.aqara_opple],
|
|
1184
|
+
toZigbee: [tz.on_off, tz.xiaomi_switch_operation_mode_opple, tz.xiaomi_switch_power_outage_memory,
|
|
1185
|
+
tz.xiaomi_flip_indicator_light, tz.xiaomi_led_disabled_night, tz.aqara_switch_mode_switch],
|
|
1186
|
+
meta: {multiEndpoint: true},
|
|
1187
|
+
endpoint: (device) => ({left: 1, center: 2, right: 3}),
|
|
1188
|
+
exposes: [
|
|
1189
|
+
e.switch().withEndpoint('left'), e.switch().withEndpoint('center'), e.switch().withEndpoint('right'),
|
|
1190
|
+
e.power_outage_memory(), e.flip_indicator_light(), e.led_disabled_night(), e.power_outage_count(),
|
|
1191
|
+
exposes
|
|
1192
|
+
.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
1193
|
+
.withDescription('Decoupled mode for left button')
|
|
1194
|
+
.withEndpoint('left'),
|
|
1195
|
+
exposes
|
|
1196
|
+
.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
1197
|
+
.withDescription('Decoupled mode for center button')
|
|
1198
|
+
.withEndpoint('center'),
|
|
1199
|
+
exposes
|
|
1200
|
+
.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
1201
|
+
.withDescription('Decoupled mode for right button')
|
|
1202
|
+
.withEndpoint('right'),
|
|
1203
|
+
exposes
|
|
1204
|
+
.enum('mode_switch', ea.ALL, ['anti_flicker_mode', 'quick_mode'])
|
|
1205
|
+
.withDescription(
|
|
1206
|
+
'Anti flicker mode can be used to solve blinking issues of some lights.' +
|
|
1207
|
+
'Quick mode makes the device respond faster.'),
|
|
1208
|
+
e.device_temperature().withAccess(ea.STATE),
|
|
1209
|
+
e.action([
|
|
1210
|
+
'single_left', 'double_left', 'single_center', 'double_center', 'single_right', 'double_right',
|
|
1211
|
+
'single_left_center', 'double_left_center', 'single_left_right', 'double_left_right',
|
|
1212
|
+
'single_center_right', 'double_center_right', 'single_all', 'double_all',
|
|
1213
|
+
]),
|
|
1214
|
+
],
|
|
1215
|
+
onEvent: preventReset,
|
|
1216
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1217
|
+
await device.getEndpoint(1).write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
|
|
1218
|
+
},
|
|
1219
|
+
},
|
|
1220
|
+
{
|
|
1221
|
+
zigbeeModel: ['lumi.switch.n1aeu1'],
|
|
1222
|
+
model: 'WS-EUK03',
|
|
1223
|
+
vendor: 'Xiaomi',
|
|
1224
|
+
description: 'Aqara smart wall switch H1 EU (with neutral, single rocker)',
|
|
1225
|
+
fromZigbee: [fz.on_off, fz.xiaomi_power, fz.xiaomi_multistate_action, fz.aqara_opple],
|
|
1226
|
+
toZigbee: [tz.on_off, tz.xiaomi_power, tz.xiaomi_switch_operation_mode_opple, tz.xiaomi_switch_power_outage_memory,
|
|
1227
|
+
tz.xiaomi_flip_indicator_light, tz.xiaomi_led_disabled_night],
|
|
1228
|
+
exposes: [e.switch(), e.action(['single', 'double']), e.power().withAccess(ea.STATE_GET), e.energy(), e.flip_indicator_light(),
|
|
1229
|
+
e.power_outage_memory(), e.device_temperature().withAccess(ea.STATE), e.led_disabled_night(), e.power_outage_count(),
|
|
1230
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled']).withDescription('Decoupled mode')],
|
|
1231
|
+
onEvent: preventReset,
|
|
1232
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1233
|
+
const endpoint1 = device.getEndpoint(1);
|
|
1234
|
+
// set "event" mode
|
|
1235
|
+
await endpoint1.write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
|
|
1236
|
+
},
|
|
1237
|
+
ota: ota.zigbeeOTA,
|
|
1238
|
+
},
|
|
1239
|
+
{
|
|
1240
|
+
zigbeeModel: ['lumi.switch.n2aeu1'],
|
|
1241
|
+
model: 'WS-EUK04',
|
|
1242
|
+
vendor: 'Xiaomi',
|
|
1243
|
+
description: 'Aqara smart wall switch H1 EU (with neutral, double rocker)',
|
|
1244
|
+
fromZigbee: [fz.on_off, fz.xiaomi_power, fz.xiaomi_multistate_action, fz.aqara_opple],
|
|
1245
|
+
toZigbee: [tz.on_off, tz.xiaomi_power, tz.xiaomi_switch_operation_mode_opple, tz.xiaomi_switch_power_outage_memory,
|
|
1246
|
+
tz.xiaomi_flip_indicator_light, tz.xiaomi_led_disabled_night],
|
|
1247
|
+
meta: {multiEndpoint: true},
|
|
1248
|
+
endpoint: (device) => {
|
|
1249
|
+
return {'left': 1, 'right': 2};
|
|
1250
|
+
},
|
|
1251
|
+
exposes: [e.switch().withEndpoint('left'), e.switch().withEndpoint('right'), e.power().withAccess(ea.STATE_GET), e.energy(),
|
|
1252
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled']).withDescription('Decoupled mode for left button')
|
|
1253
|
+
.withEndpoint('left'),
|
|
1254
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled']).withDescription('Decoupled mode for right button')
|
|
1255
|
+
.withEndpoint('right'),
|
|
1256
|
+
e.action(['single_left', 'double_left', 'single_right', 'double_right', 'single_both', 'double_both']),
|
|
1257
|
+
e.device_temperature().withAccess(ea.STATE), e.power_outage_memory(), e.flip_indicator_light(),
|
|
1258
|
+
e.led_disabled_night(), e.power_outage_count()],
|
|
1259
|
+
onEvent: preventReset,
|
|
1260
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1261
|
+
const endpoint1 = device.getEndpoint(1);
|
|
1262
|
+
// set "event" mode
|
|
1263
|
+
await endpoint1.write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
|
|
1264
|
+
},
|
|
1265
|
+
},
|
|
1266
|
+
{
|
|
1267
|
+
zigbeeModel: ['lumi.ctrl_neutral1'],
|
|
1268
|
+
model: 'QBKG04LM',
|
|
1269
|
+
vendor: 'Xiaomi',
|
|
1270
|
+
description: 'Aqara single key wired wall switch without neutral wire. Doesn\'t work as a router and doesn\'t support power meter',
|
|
1271
|
+
fromZigbee: [fz.xiaomi_on_off_ignore_endpoint_4_5_6, fz.xiaomi_on_off_action, fz.legacy.QBKG04LM_QBKG11LM_click,
|
|
1272
|
+
fz.xiaomi_operation_mode_basic],
|
|
1273
|
+
exposes: [
|
|
1274
|
+
e.switch(), e.action(['release', 'hold', 'double', 'single', 'hold_release']),
|
|
1275
|
+
exposes.enum('operation_mode', ea.STATE_SET, ['control_relay', 'decoupled'])
|
|
1276
|
+
.withDescription('Decoupled mode'),
|
|
1277
|
+
],
|
|
1278
|
+
toZigbee: [tz.on_off, {...tz.xiaomi_switch_operation_mode_basic, convertGet: null}],
|
|
1279
|
+
endpoint: (device) => {
|
|
1280
|
+
return {'system': 1, 'default': 2};
|
|
1281
|
+
},
|
|
1282
|
+
onEvent: preventReset,
|
|
1283
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1284
|
+
// Device advertises itself as Router but is an EndDevice
|
|
1285
|
+
device.type = 'EndDevice';
|
|
1286
|
+
device.save();
|
|
1287
|
+
},
|
|
1288
|
+
ota: ota.zigbeeOTA,
|
|
1289
|
+
},
|
|
1290
|
+
{
|
|
1291
|
+
zigbeeModel: ['lumi.ctrl_ln1.aq1', 'lumi.ctrl_ln1'],
|
|
1292
|
+
model: 'QBKG11LM',
|
|
1293
|
+
vendor: 'Xiaomi',
|
|
1294
|
+
description: 'Aqara single key wired wall switch',
|
|
1295
|
+
fromZigbee: [fz.xiaomi_on_off_action, fz.xiaomi_multistate_action, fz.xiaomi_on_off_ignore_endpoint_4_5_6,
|
|
1296
|
+
fz.legacy.QBKG04LM_QBKG11LM_click, fz.xiaomi_basic, fz.xiaomi_operation_mode_basic,
|
|
1297
|
+
fz.legacy.QBKG11LM_click, fz.ignore_multistate_report, fz.xiaomi_power],
|
|
1298
|
+
exposes: [
|
|
1299
|
+
e.switch(), e.power().withAccess(ea.STATE_GET), e.device_temperature(), e.energy(),
|
|
1300
|
+
e.action(['single', 'double', 'release', 'hold']),
|
|
1301
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
1302
|
+
.withDescription('Decoupled mode'),
|
|
1303
|
+
],
|
|
1304
|
+
toZigbee: [tz.on_off, tz.xiaomi_switch_operation_mode_basic, tz.xiaomi_power],
|
|
1305
|
+
endpoint: (device) => {
|
|
1306
|
+
return {'system': 1};
|
|
1307
|
+
},
|
|
1308
|
+
onEvent: preventReset,
|
|
1309
|
+
ota: ota.zigbeeOTA,
|
|
1310
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1311
|
+
device.powerSource = 'Mains (single phase)';
|
|
1312
|
+
device.save();
|
|
1313
|
+
},
|
|
1314
|
+
},
|
|
1315
|
+
{
|
|
1316
|
+
zigbeeModel: ['lumi.ctrl_neutral2'],
|
|
1317
|
+
model: 'QBKG03LM',
|
|
1318
|
+
vendor: 'Xiaomi',
|
|
1319
|
+
description: 'Aqara double key wired wall switch without neutral wire. Doesn\'t work as a router and doesn\'t support power meter',
|
|
1320
|
+
fromZigbee: [fz.xiaomi_on_off_action, fz.xiaomi_on_off_ignore_endpoint_4_5_6, fz.legacy.QBKG03LM_QBKG12LM_click,
|
|
1321
|
+
fz.legacy.QBKG03LM_buttons, fz.xiaomi_operation_mode_basic, fz.xiaomi_basic],
|
|
1322
|
+
exposes: [
|
|
1323
|
+
e.switch().withEndpoint('left'),
|
|
1324
|
+
e.switch().withEndpoint('right'),
|
|
1325
|
+
e.device_temperature(),
|
|
1326
|
+
e.action(['release_left', 'release_right', 'release_both', 'double_left', 'double_right',
|
|
1327
|
+
'single_left', 'single_right', 'hold_release_left', 'hold_release_left']),
|
|
1328
|
+
exposes.enum('operation_mode', ea.STATE_SET, ['control_left_relay', 'control_right_relay', 'decoupled'])
|
|
1329
|
+
.withDescription('Operation mode for left button')
|
|
1330
|
+
.withEndpoint('left'),
|
|
1331
|
+
exposes.enum('operation_mode', ea.STATE_SET, ['control_left_relay', 'control_right_relay', 'decoupled'])
|
|
1332
|
+
.withDescription('Operation mode for right button')
|
|
1333
|
+
.withEndpoint('right'),
|
|
1334
|
+
],
|
|
1335
|
+
toZigbee: [tz.on_off, {...tz.xiaomi_switch_operation_mode_basic, convertGet: null}, tz.xiaomi_power],
|
|
1336
|
+
meta: {multiEndpoint: true},
|
|
1337
|
+
endpoint: (device) => {
|
|
1338
|
+
return {'system': 1, 'left': 2, 'right': 3};
|
|
1339
|
+
},
|
|
1340
|
+
onEvent: preventReset,
|
|
1341
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1342
|
+
// Device advertises itself as Router but is an EndDevice
|
|
1343
|
+
device.type = 'EndDevice';
|
|
1344
|
+
device.save();
|
|
1345
|
+
},
|
|
1346
|
+
ota: ota.zigbeeOTA,
|
|
1347
|
+
},
|
|
1348
|
+
{
|
|
1349
|
+
zigbeeModel: ['lumi.ctrl_ln2.aq1', 'lumi.ctrl_ln2'],
|
|
1350
|
+
model: 'QBKG12LM',
|
|
1351
|
+
vendor: 'Xiaomi',
|
|
1352
|
+
description: 'Aqara double key wired wall switch',
|
|
1353
|
+
fromZigbee: [fz.xiaomi_on_off_action, fz.xiaomi_multistate_action, fz.xiaomi_on_off_ignore_endpoint_4_5_6,
|
|
1354
|
+
fz.legacy.QBKG03LM_QBKG12LM_click, fz.xiaomi_basic, fz.xiaomi_operation_mode_basic, fz.legacy.QBKG12LM_click,
|
|
1355
|
+
fz.xiaomi_power],
|
|
1356
|
+
exposes: [
|
|
1357
|
+
e.switch().withEndpoint('left'),
|
|
1358
|
+
e.switch().withEndpoint('right'),
|
|
1359
|
+
e.device_temperature(), e.energy(),
|
|
1360
|
+
e.power().withAccess(ea.STATE_GET),
|
|
1361
|
+
e.action(['single_left', 'single_right', 'single_both', 'double_left', 'double_right', 'double_both',
|
|
1362
|
+
'hold_left', 'hold_right', 'hold_both', 'release_left', 'release_right', 'release_both']),
|
|
1363
|
+
exposes.enum('operation_mode', ea.ALL, ['control_left_relay', 'control_right_relay', 'decoupled'])
|
|
1364
|
+
.withDescription('Operation mode for left button')
|
|
1365
|
+
.withEndpoint('left'),
|
|
1366
|
+
exposes.enum('operation_mode', ea.ALL, ['control_left_relay', 'control_right_relay', 'decoupled'])
|
|
1367
|
+
.withDescription('Operation mode for right button')
|
|
1368
|
+
.withEndpoint('right'),
|
|
1369
|
+
],
|
|
1370
|
+
meta: {multiEndpoint: true},
|
|
1371
|
+
toZigbee: [tz.on_off, tz.xiaomi_switch_operation_mode_basic, tz.xiaomi_power],
|
|
1372
|
+
endpoint: (device) => {
|
|
1373
|
+
return {'left': 1, 'right': 2, 'system': 1};
|
|
1374
|
+
},
|
|
1375
|
+
onEvent: preventReset,
|
|
1376
|
+
ota: ota.zigbeeOTA,
|
|
1377
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1378
|
+
device.powerSource = 'Mains (single phase)';
|
|
1379
|
+
device.save();
|
|
1380
|
+
},
|
|
1381
|
+
},
|
|
1382
|
+
{
|
|
1383
|
+
zigbeeModel: ['lumi.remote.b286acn02'],
|
|
1384
|
+
model: 'WXKG07LM',
|
|
1385
|
+
vendor: 'Xiaomi',
|
|
1386
|
+
description: 'Aqara D1 double key wireless wall switch',
|
|
1387
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
1388
|
+
fromZigbee: [fz.xiaomi_basic, fz.legacy.xiaomi_on_off_action, fz.legacy.xiaomi_multistate_action],
|
|
1389
|
+
toZigbee: [],
|
|
1390
|
+
endpoint: (device) => {
|
|
1391
|
+
return {left: 1, right: 2, both: 3};
|
|
1392
|
+
},
|
|
1393
|
+
exposes: [e.battery(), e.battery_voltage(), e.action([
|
|
1394
|
+
'single_left', 'single_right', 'single_both',
|
|
1395
|
+
'double_left', 'double_right', 'double_both',
|
|
1396
|
+
'hold_left', 'hold_right', 'hold_both'])],
|
|
1397
|
+
onEvent: preventReset,
|
|
1398
|
+
},
|
|
1399
|
+
{
|
|
1400
|
+
zigbeeModel: ['lumi.switch.b1lacn02'],
|
|
1401
|
+
model: 'QBKG21LM',
|
|
1402
|
+
vendor: 'Xiaomi',
|
|
1403
|
+
description: 'Aqara D1 single gang smart wall switch (no neutral wire)',
|
|
1404
|
+
fromZigbee: [fz.xiaomi_on_off_ignore_endpoint_4_5_6, fz.xiaomi_on_off_action, fz.legacy.QBKG04LM_QBKG11LM_click,
|
|
1405
|
+
fz.xiaomi_operation_mode_basic],
|
|
1406
|
+
exposes: [
|
|
1407
|
+
e.switch(), e.action(['release', 'hold', 'double', 'single', 'hold_release']),
|
|
1408
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
1409
|
+
.withDescription('Decoupled mode'),
|
|
1410
|
+
],
|
|
1411
|
+
toZigbee: [tz.on_off, tz.xiaomi_switch_operation_mode_basic],
|
|
1412
|
+
endpoint: (device) => {
|
|
1413
|
+
return {'system': 1, 'default': 2};
|
|
1414
|
+
},
|
|
1415
|
+
onEvent: preventReset,
|
|
1416
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1417
|
+
// Device advertises itself as Router but is an EndDevice
|
|
1418
|
+
device.type = 'EndDevice';
|
|
1419
|
+
device.save();
|
|
1420
|
+
},
|
|
1421
|
+
},
|
|
1422
|
+
{
|
|
1423
|
+
zigbeeModel: ['lumi.switch.b2lacn02'],
|
|
1424
|
+
model: 'QBKG22LM',
|
|
1425
|
+
vendor: 'Xiaomi',
|
|
1426
|
+
description: 'Aqara D1 2 gang smart wall switch (no neutral wire)',
|
|
1427
|
+
fromZigbee: [fz.xiaomi_on_off_ignore_endpoint_4_5_6, fz.xiaomi_on_off_action, fz.legacy.QBKG03LM_QBKG12LM_click,
|
|
1428
|
+
fz.legacy.QBKG03LM_buttons, fz.xiaomi_operation_mode_basic],
|
|
1429
|
+
exposes: [
|
|
1430
|
+
e.switch().withEndpoint('left'),
|
|
1431
|
+
e.switch().withEndpoint('right'),
|
|
1432
|
+
e.action(['release_left', 'release_right', 'release_both', 'double_left', 'double_right',
|
|
1433
|
+
'single_left', 'single_right', 'hold_release_left', 'hold_release_left']),
|
|
1434
|
+
exposes.enum('operation_mode', ea.ALL, ['control_left_relay', 'control_right_relay', 'decoupled'])
|
|
1435
|
+
.withDescription('Operation mode for left button')
|
|
1436
|
+
.withEndpoint('left'),
|
|
1437
|
+
exposes.enum('operation_mode', ea.ALL, ['control_left_relay', 'control_right_relay', 'decoupled'])
|
|
1438
|
+
.withDescription('Operation mode for right button')
|
|
1439
|
+
.withEndpoint('right'),
|
|
1440
|
+
],
|
|
1441
|
+
toZigbee: [tz.on_off, tz.xiaomi_switch_operation_mode_basic],
|
|
1442
|
+
meta: {multiEndpoint: true},
|
|
1443
|
+
endpoint: (device) => {
|
|
1444
|
+
return {'system': 1, 'left': 2, 'right': 3};
|
|
1445
|
+
},
|
|
1446
|
+
onEvent: preventReset,
|
|
1447
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1448
|
+
// Device advertises itself as Router but is an EndDevice
|
|
1449
|
+
device.type = 'EndDevice';
|
|
1450
|
+
device.save();
|
|
1451
|
+
},
|
|
1452
|
+
},
|
|
1453
|
+
{
|
|
1454
|
+
zigbeeModel: ['lumi.switch.l3acn3'],
|
|
1455
|
+
model: 'QBKG25LM',
|
|
1456
|
+
vendor: 'Xiaomi',
|
|
1457
|
+
description: 'Aqara D1 3 gang smart wall switch (no neutral wire)',
|
|
1458
|
+
fromZigbee: [fz.on_off, fz.xiaomi_multistate_action, fz.aqara_opple],
|
|
1459
|
+
toZigbee: [tz.on_off, tz.xiaomi_switch_operation_mode_opple, tz.xiaomi_switch_power_outage_memory, tz.xiaomi_led_disabled_night,
|
|
1460
|
+
tz.aqara_switch_mode_switch, tz.xiaomi_flip_indicator_light],
|
|
1461
|
+
meta: {multiEndpoint: true},
|
|
1462
|
+
endpoint: (device) => {
|
|
1463
|
+
return {'left': 1, 'center': 2, 'right': 3};
|
|
1464
|
+
},
|
|
1465
|
+
exposes: [
|
|
1466
|
+
e.switch().withEndpoint('left'), e.switch().withEndpoint('center'), e.switch().withEndpoint('right'),
|
|
1467
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
1468
|
+
.withDescription('Decoupled mode for left button')
|
|
1469
|
+
.withEndpoint('left'),
|
|
1470
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
1471
|
+
.withDescription('Decoupled mode for center button')
|
|
1472
|
+
.withEndpoint('center'),
|
|
1473
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
1474
|
+
.withDescription('Decoupled mode for right button')
|
|
1475
|
+
.withEndpoint('right'),
|
|
1476
|
+
exposes.enum('mode_switch', ea.ALL, ['anti_flicker_mode', 'quick_mode'])
|
|
1477
|
+
.withDescription('Anti flicker mode can be used to solve blinking issues of some lights.' +
|
|
1478
|
+
'Quick mode makes the device respond faster.'),
|
|
1479
|
+
e.power_outage_memory(), e.led_disabled_night(), e.device_temperature().withAccess(ea.STATE), e.flip_indicator_light(),
|
|
1480
|
+
e.action([
|
|
1481
|
+
'left_single', 'left_double', 'center_single', 'center_double', 'right_single', 'right_double',
|
|
1482
|
+
'single_left_center', 'double_left_center', 'single_left_right', 'double_left_right',
|
|
1483
|
+
'single_center_right', 'double_center_right', 'single_all', 'double_all']),
|
|
1484
|
+
e.power_outage_count(),
|
|
1485
|
+
],
|
|
1486
|
+
onEvent: preventReset,
|
|
1487
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1488
|
+
await device.getEndpoint(1).write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
|
|
1489
|
+
},
|
|
1490
|
+
ota: ota.zigbeeOTA,
|
|
1491
|
+
},
|
|
1492
|
+
{
|
|
1493
|
+
zigbeeModel: ['lumi.switch.n3acn3'],
|
|
1494
|
+
model: 'QBKG26LM',
|
|
1495
|
+
vendor: 'Xiaomi',
|
|
1496
|
+
description: 'Aqara D1 3 gang smart wall switch (with neutral wire)',
|
|
1497
|
+
exposes: [
|
|
1498
|
+
e.switch().withEndpoint('left'), e.switch().withEndpoint('center'), e.switch().withEndpoint('right'),
|
|
1499
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
1500
|
+
.withDescription('Decoupled mode for left button')
|
|
1501
|
+
.withEndpoint('left'),
|
|
1502
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
1503
|
+
.withDescription('Decoupled mode for center button')
|
|
1504
|
+
.withEndpoint('center'),
|
|
1505
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
1506
|
+
.withDescription('Decoupled mode for right button')
|
|
1507
|
+
.withEndpoint('right'),
|
|
1508
|
+
e.power().withAccess(ea.STATE), e.power_outage_memory(), e.led_disabled_night(), e.voltage(),
|
|
1509
|
+
e.device_temperature().withAccess(ea.STATE), e.flip_indicator_light(),
|
|
1510
|
+
e.action([
|
|
1511
|
+
'single_left', 'double_left', 'single_center', 'double_center', 'single_right', 'double_right',
|
|
1512
|
+
'single_left_center', 'double_left_center', 'single_left_right', 'double_left_right',
|
|
1513
|
+
'single_center_right', 'double_center_right', 'single_all', 'double_all']),
|
|
1514
|
+
],
|
|
1515
|
+
fromZigbee: [fz.on_off, fz.xiaomi_power, fz.aqara_opple, fz.xiaomi_multistate_action],
|
|
1516
|
+
toZigbee: [tz.on_off, tz.xiaomi_switch_operation_mode_opple, tz.xiaomi_switch_power_outage_memory,
|
|
1517
|
+
tz.xiaomi_led_disabled_night, tz.xiaomi_flip_indicator_light],
|
|
1518
|
+
meta: {multiEndpoint: true},
|
|
1519
|
+
endpoint: (device) => {
|
|
1520
|
+
return {'left': 1, 'center': 2, 'right': 3};
|
|
1521
|
+
},
|
|
1522
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1523
|
+
await device.getEndpoint(1).write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
|
|
1524
|
+
},
|
|
1525
|
+
onEvent: preventReset,
|
|
1526
|
+
ota: ota.zigbeeOTA,
|
|
1527
|
+
},
|
|
1528
|
+
{
|
|
1529
|
+
zigbeeModel: ['lumi.switch.b1nacn02'],
|
|
1530
|
+
model: 'QBKG23LM',
|
|
1531
|
+
vendor: 'Xiaomi',
|
|
1532
|
+
description: 'Aqara D1 1 gang smart wall switch (with neutral wire)',
|
|
1533
|
+
fromZigbee: [fz.on_off, fz.xiaomi_power, fz.xiaomi_basic, fz.xiaomi_multistate_action],
|
|
1534
|
+
toZigbee: [tz.on_off, tz.xiaomi_power, tz.xiaomi_switch_operation_mode_basic],
|
|
1535
|
+
endpoint: (device) => {
|
|
1536
|
+
return {'system': 1};
|
|
1537
|
+
},
|
|
1538
|
+
onEvent: preventReset,
|
|
1539
|
+
exposes: [
|
|
1540
|
+
e.switch(), e.power().withAccess(ea.STATE_GET),
|
|
1541
|
+
e.energy(), e.device_temperature().withAccess(ea.STATE),
|
|
1542
|
+
e.voltage(), e.action(['single', 'release']),
|
|
1543
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
1544
|
+
.withDescription('Decoupled mode'),
|
|
1545
|
+
],
|
|
1546
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1547
|
+
device.type = 'Router';
|
|
1548
|
+
device.powerSource = 'Mains (single phase)';
|
|
1549
|
+
device.save();
|
|
1550
|
+
},
|
|
1551
|
+
ota: ota.zigbeeOTA,
|
|
1552
|
+
},
|
|
1553
|
+
{
|
|
1554
|
+
zigbeeModel: ['lumi.switch.b2nacn02'],
|
|
1555
|
+
model: 'QBKG24LM',
|
|
1556
|
+
vendor: 'Xiaomi',
|
|
1557
|
+
description: 'Aqara D1 2 gang smart wall switch (with neutral wire)',
|
|
1558
|
+
fromZigbee: [fz.on_off, fz.xiaomi_power, fz.xiaomi_multistate_action, fz.xiaomi_operation_mode_basic],
|
|
1559
|
+
toZigbee: [tz.on_off, tz.xiaomi_power, tz.xiaomi_switch_operation_mode_basic],
|
|
1560
|
+
meta: {multiEndpoint: true},
|
|
1561
|
+
endpoint: (device) => {
|
|
1562
|
+
return {'left': 1, 'right': 2, 'system': 1};
|
|
1563
|
+
},
|
|
1564
|
+
exposes: [
|
|
1565
|
+
e.switch().withEndpoint('left'),
|
|
1566
|
+
e.switch().withEndpoint('right'),
|
|
1567
|
+
e.power().withAccess(ea.STATE_GET),
|
|
1568
|
+
e.action([
|
|
1569
|
+
'hold_left', 'single_left', 'double_left', 'single_right', 'double_right', 'single_both', 'double_both',
|
|
1570
|
+
]),
|
|
1571
|
+
exposes.enum('operation_mode', ea.ALL, ['control_left_relay', 'decoupled'])
|
|
1572
|
+
.withDescription('Decoupled mode for left button')
|
|
1573
|
+
.withEndpoint('left'),
|
|
1574
|
+
exposes.enum('operation_mode', ea.ALL, ['control_right_relay', 'decoupled'])
|
|
1575
|
+
.withDescription('Decoupled mode for right button')
|
|
1576
|
+
.withEndpoint('right'),
|
|
1577
|
+
],
|
|
1578
|
+
onEvent: preventReset,
|
|
1579
|
+
ota: ota.zigbeeOTA,
|
|
1580
|
+
},
|
|
1581
|
+
{
|
|
1582
|
+
zigbeeModel: ['lumi.switch.b1nacn01'],
|
|
1583
|
+
model: 'QBKG19LM',
|
|
1584
|
+
vendor: 'Xiaomi',
|
|
1585
|
+
description: 'Aqara smart wall switch T1 (with neutral, single rocker)',
|
|
1586
|
+
fromZigbee: [fz.on_off, fz.xiaomi_power, fz.xiaomi_multistate_action, fz.aqara_opple],
|
|
1587
|
+
toZigbee: [tz.on_off, tz.xiaomi_switch_operation_mode_opple, tz.xiaomi_switch_power_outage_memory,
|
|
1588
|
+
tz.xiaomi_led_disabled_night, tz.xiaomi_flip_indicator_light],
|
|
1589
|
+
exposes: [
|
|
1590
|
+
e.switch(), e.action(['single', 'double']), e.power().withAccess(ea.STATE), e.energy(),
|
|
1591
|
+
e.voltage(), e.device_temperature().withAccess(ea.STATE),
|
|
1592
|
+
e.power_outage_memory(), e.led_disabled_night(), e.flip_indicator_light(),
|
|
1593
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
1594
|
+
.withDescription('Decoupled mode for left button'),
|
|
1595
|
+
],
|
|
1596
|
+
onEvent: preventReset,
|
|
1597
|
+
ota: ota.zigbeeOTA,
|
|
1598
|
+
},
|
|
1599
|
+
{
|
|
1600
|
+
zigbeeModel: ['lumi.switch.b2nacn01'],
|
|
1601
|
+
model: 'QBKG20LM',
|
|
1602
|
+
vendor: 'Xiaomi',
|
|
1603
|
+
description: 'Aqara smart wall switch T1 (with neutral, double rocker)',
|
|
1604
|
+
fromZigbee: [fz.on_off, fz.xiaomi_power, fz.xiaomi_multistate_action, fz.aqara_opple],
|
|
1605
|
+
toZigbee: [tz.on_off, tz.xiaomi_switch_operation_mode_opple, tz.xiaomi_switch_power_outage_memory,
|
|
1606
|
+
tz.xiaomi_led_disabled_night, tz.xiaomi_flip_indicator_light],
|
|
1607
|
+
meta: {multiEndpoint: true},
|
|
1608
|
+
endpoint: (device) => {
|
|
1609
|
+
return {'left': 1, 'right': 2};
|
|
1610
|
+
},
|
|
1611
|
+
exposes: [
|
|
1612
|
+
e.switch().withEndpoint('left'), e.switch().withEndpoint('right'),
|
|
1613
|
+
e.power().withAccess(ea.STATE), e.energy(), e.voltage(), e.flip_indicator_light(),
|
|
1614
|
+
e.power_outage_memory(), e.led_disabled_night(), e.device_temperature().withAccess(ea.STATE),
|
|
1615
|
+
e.action([
|
|
1616
|
+
'single_left', 'double_left', 'single_right', 'double_right', 'single_both', 'double_both']),
|
|
1617
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
1618
|
+
.withDescription('Decoupled mode for left button')
|
|
1619
|
+
.withEndpoint('left'),
|
|
1620
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
1621
|
+
.withDescription('Decoupled mode for right button')
|
|
1622
|
+
.withEndpoint('right'),
|
|
1623
|
+
],
|
|
1624
|
+
onEvent: preventReset,
|
|
1625
|
+
ota: ota.zigbeeOTA,
|
|
1626
|
+
},
|
|
1627
|
+
{
|
|
1628
|
+
zigbeeModel: ['lumi.switch.b3n01'],
|
|
1629
|
+
model: 'QBKG34LM',
|
|
1630
|
+
vendor: 'Xiaomi',
|
|
1631
|
+
description: 'Aqara smart wall switch T1 (with neutral, three rocker)',
|
|
1632
|
+
fromZigbee: [fz.on_off, fz.xiaomi_power, fz.xiaomi_multistate_action, fz.aqara_opple],
|
|
1633
|
+
toZigbee: [tz.on_off, tz.xiaomi_switch_operation_mode_opple, tz.xiaomi_switch_power_outage_memory,
|
|
1634
|
+
tz.xiaomi_led_disabled_night, tz.xiaomi_flip_indicator_light],
|
|
1635
|
+
meta: {multiEndpoint: true},
|
|
1636
|
+
endpoint: (device) => {
|
|
1637
|
+
return {'left': 1, 'center': 2, 'right': 3};
|
|
1638
|
+
},
|
|
1639
|
+
exposes: [
|
|
1640
|
+
e.switch().withEndpoint('left'), e.switch().withEndpoint('center'), e.switch().withEndpoint('right'),
|
|
1641
|
+
e.power().withAccess(ea.STATE), e.energy(), e.voltage(), e.flip_indicator_light(),
|
|
1642
|
+
e.power_outage_memory(), e.led_disabled_night(), e.device_temperature().withAccess(ea.STATE),
|
|
1643
|
+
e.action([
|
|
1644
|
+
'single_left', 'double_left', 'single_center', 'double_center',
|
|
1645
|
+
'single_right', 'double_right', 'single_left_center', 'double_left_center',
|
|
1646
|
+
'single_left_right', 'double_left_right', 'single_center_right', 'double_center_right',
|
|
1647
|
+
'single_all', 'double_all']),
|
|
1648
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
1649
|
+
.withDescription('Decoupled mode for left button')
|
|
1650
|
+
.withEndpoint('left'),
|
|
1651
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
1652
|
+
.withDescription('Decoupled mode for right button')
|
|
1653
|
+
.withEndpoint('center'),
|
|
1654
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
1655
|
+
.withDescription('Decoupled mode for right button')
|
|
1656
|
+
.withEndpoint('right'),
|
|
1657
|
+
],
|
|
1658
|
+
onEvent: preventReset,
|
|
1659
|
+
ota: ota.zigbeeOTA,
|
|
1660
|
+
},
|
|
1661
|
+
{
|
|
1662
|
+
zigbeeModel: ['lumi.sens', 'lumi.sensor_ht'],
|
|
1663
|
+
model: 'WSDCGQ01LM',
|
|
1664
|
+
vendor: 'Xiaomi',
|
|
1665
|
+
whiteLabel: [{vendor: 'Xiaomi', model: 'YTC4042GL'}, {vendor: 'Xiaomi', model: 'YTC4007CN'},
|
|
1666
|
+
{vendor: 'Xiaomi', model: 'YTC4018CN'}],
|
|
1667
|
+
description: 'MiJia temperature & humidity sensor',
|
|
1668
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
1669
|
+
fromZigbee: [fz.xiaomi_basic, fz.xiaomi_temperature, fz.humidity],
|
|
1670
|
+
toZigbee: [],
|
|
1671
|
+
exposes: [e.battery(), e.temperature(), e.humidity(), e.battery_voltage()],
|
|
1672
|
+
},
|
|
1673
|
+
{
|
|
1674
|
+
zigbeeModel: ['lumi.weather'],
|
|
1675
|
+
model: 'WSDCGQ11LM',
|
|
1676
|
+
vendor: 'Xiaomi',
|
|
1677
|
+
description: 'Aqara temperature, humidity and pressure sensor',
|
|
1678
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
1679
|
+
fromZigbee: [fz.xiaomi_basic, fz.xiaomi_temperature, fz.humidity, fz.pressure],
|
|
1680
|
+
toZigbee: [],
|
|
1681
|
+
exposes: [e.battery(), e.temperature(), e.humidity(), e.pressure(), e.battery_voltage()],
|
|
1682
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1683
|
+
device.powerSource = 'Battery';
|
|
1684
|
+
device.save();
|
|
1685
|
+
},
|
|
1686
|
+
},
|
|
1687
|
+
{
|
|
1688
|
+
zigbeeModel: ['lumi.sensor_ht.agl02'],
|
|
1689
|
+
model: 'WSDCGQ12LM',
|
|
1690
|
+
vendor: 'Xiaomi',
|
|
1691
|
+
description: 'Aqara T1 temperature, humidity and pressure sensor',
|
|
1692
|
+
fromZigbee: [fz.aqara_opple, fz.temperature, fz.humidity, fz.pressure, fz.battery],
|
|
1693
|
+
toZigbee: [],
|
|
1694
|
+
exposes: [e.temperature(), e.humidity(), e.pressure(), e.device_temperature(), e.battery(), e.battery_voltage(),
|
|
1695
|
+
e.power_outage_count(false)],
|
|
1696
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
1697
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1698
|
+
const endpoint = device.getEndpoint(1);
|
|
1699
|
+
const binds = ['msTemperatureMeasurement', 'msRelativeHumidity', 'msPressureMeasurement'];
|
|
1700
|
+
await reporting.bind(endpoint, coordinatorEndpoint, binds);
|
|
1701
|
+
await endpoint.read('genPowerCfg', ['batteryVoltage']);
|
|
1702
|
+
},
|
|
1703
|
+
ota: ota.zigbeeOTA,
|
|
1704
|
+
},
|
|
1705
|
+
{
|
|
1706
|
+
zigbeeModel: ['lumi.sensor_motion'],
|
|
1707
|
+
model: 'RTCGQ01LM',
|
|
1708
|
+
vendor: 'Xiaomi',
|
|
1709
|
+
whiteLabel: [{vendor: 'Xiaomi', model: 'YTC4041GL'}, {vendor: 'Xiaomi', model: 'YTC4004CN'},
|
|
1710
|
+
{vendor: 'Xiaomi', model: 'YTC4016CN'}, {vendor: 'Xiaomi', model: 'ZHTZ02LM'}],
|
|
1711
|
+
description: 'MiJia human body movement sensor',
|
|
1712
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
1713
|
+
fromZigbee: [fz.xiaomi_basic, fz.occupancy_with_timeout],
|
|
1714
|
+
toZigbee: [],
|
|
1715
|
+
exposes: [e.battery(), e.occupancy(), e.battery_voltage(), e.power_outage_count(false)],
|
|
1716
|
+
},
|
|
1717
|
+
{
|
|
1718
|
+
zigbeeModel: ['lumi.sensor_motion.aq2'],
|
|
1719
|
+
model: 'RTCGQ11LM',
|
|
1720
|
+
vendor: 'Xiaomi',
|
|
1721
|
+
description: 'Aqara human body movement and illuminance sensor',
|
|
1722
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
1723
|
+
fromZigbee: [fz.xiaomi_basic, fz.occupancy_with_timeout, fz.RTCGQ11LM_illuminance],
|
|
1724
|
+
toZigbee: [],
|
|
1725
|
+
exposes: [e.battery(), e.occupancy(), e.device_temperature(), e.battery_voltage(), e.illuminance_lux().withProperty('illuminance'),
|
|
1726
|
+
e.illuminance().withUnit('lx').withDescription('Measured illuminance in lux'), e.power_outage_count(false)],
|
|
1727
|
+
},
|
|
1728
|
+
{
|
|
1729
|
+
zigbeeModel: ['lumi.motion.agl02'],
|
|
1730
|
+
model: 'RTCGQ12LM',
|
|
1731
|
+
vendor: 'Xiaomi',
|
|
1732
|
+
description: 'Aqara T1 human body movement and illuminance sensor',
|
|
1733
|
+
fromZigbee: [fz.aqara_occupancy_illuminance, fz.aqara_opple, fz.battery],
|
|
1734
|
+
toZigbee: [tz.aqara_detection_interval],
|
|
1735
|
+
exposes: [e.occupancy(), e.illuminance_lux().withProperty('illuminance'),
|
|
1736
|
+
e.illuminance().withUnit('lx').withDescription('Measured illuminance in lux'),
|
|
1737
|
+
exposes.numeric('detection_interval', ea.ALL).withValueMin(2).withValueMax(65535).withUnit('s')
|
|
1738
|
+
.withDescription('Time interval for detecting actions'),
|
|
1739
|
+
e.device_temperature(), e.battery(), e.battery_voltage(), e.power_outage_count(false)],
|
|
1740
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
1741
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1742
|
+
const endpoint = device.getEndpoint(1);
|
|
1743
|
+
await endpoint.read('genPowerCfg', ['batteryVoltage']);
|
|
1744
|
+
await endpoint.read('aqaraOpple', [0x0102], {manufacturerCode: 0x115f});
|
|
1745
|
+
},
|
|
1746
|
+
ota: ota.zigbeeOTA,
|
|
1747
|
+
},
|
|
1748
|
+
{
|
|
1749
|
+
zigbeeModel: ['lumi.motion.agl04'],
|
|
1750
|
+
model: 'RTCGQ13LM',
|
|
1751
|
+
vendor: 'Xiaomi',
|
|
1752
|
+
description: 'Aqara high precision motion sensor',
|
|
1753
|
+
fromZigbee: [fz.RTCGQ13LM_occupancy, fz.aqara_opple, fz.battery],
|
|
1754
|
+
toZigbee: [tz.aqara_detection_interval, tz.aqara_motion_sensitivity],
|
|
1755
|
+
exposes: [e.occupancy(), exposes.enum('motion_sensitivity', ea.ALL, ['low', 'medium', 'high']),
|
|
1756
|
+
exposes.numeric('detection_interval', ea.ALL).withValueMin(2).withValueMax(65535).withUnit('s')
|
|
1757
|
+
.withDescription('Time interval for detecting actions'),
|
|
1758
|
+
e.device_temperature(), e.battery(), e.battery_voltage(), e.power_outage_count(false)],
|
|
1759
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
1760
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1761
|
+
const endpoint = device.getEndpoint(1);
|
|
1762
|
+
await endpoint.read('genPowerCfg', ['batteryVoltage']);
|
|
1763
|
+
await endpoint.read('aqaraOpple', [0x0102], {manufacturerCode: 0x115f});
|
|
1764
|
+
await endpoint.read('aqaraOpple', [0x010c], {manufacturerCode: 0x115f});
|
|
1765
|
+
},
|
|
1766
|
+
ota: ota.zigbeeOTA,
|
|
1767
|
+
},
|
|
1768
|
+
{
|
|
1769
|
+
zigbeeModel: ['lumi.motion.ac02'],
|
|
1770
|
+
model: 'RTCGQ14LM',
|
|
1771
|
+
vendor: 'Xiaomi',
|
|
1772
|
+
whiteLabel: [{vendor: 'Xiaomi', model: 'MS-S02'}],
|
|
1773
|
+
description: 'Aqara P1 human body movement and illuminance sensor',
|
|
1774
|
+
fromZigbee: [fz.aqara_occupancy_illuminance, fz.aqara_opple, fz.battery],
|
|
1775
|
+
toZigbee: [tz.aqara_detection_interval, tz.aqara_motion_sensitivity, tz.RTCGQ14LM_trigger_indicator],
|
|
1776
|
+
exposes: [e.occupancy(), e.illuminance_lux().withProperty('illuminance'),
|
|
1777
|
+
e.illuminance().withUnit('lx').withDescription('Measured illuminance in lux'),
|
|
1778
|
+
exposes.enum('motion_sensitivity', ea.ALL, ['low', 'medium', 'high'])
|
|
1779
|
+
.withDescription('. Press pairing button right before changing this otherwise it will fail.'),
|
|
1780
|
+
exposes.numeric('detection_interval', ea.ALL).withValueMin(2).withValueMax(65535).withUnit('s')
|
|
1781
|
+
.withDescription('Time interval for detecting actions. ' +
|
|
1782
|
+
'Press pairing button right before changing this otherwise it will fail.'),
|
|
1783
|
+
exposes.binary('trigger_indicator', ea.ALL, true, false).withDescription('When this option is enabled then ' +
|
|
1784
|
+
'blue LED will blink once when motion is detected. ' +
|
|
1785
|
+
'Press pairing button right before changing this otherwise it will fail.'),
|
|
1786
|
+
e.device_temperature(), e.battery(), e.battery_voltage()],
|
|
1787
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
1788
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1789
|
+
const endpoint = device.getEndpoint(1);
|
|
1790
|
+
await endpoint.read('genPowerCfg', ['batteryVoltage']);
|
|
1791
|
+
await endpoint.read('aqaraOpple', [0x0102], {manufacturerCode: 0x115f});
|
|
1792
|
+
await endpoint.read('aqaraOpple', [0x010c], {manufacturerCode: 0x115f});
|
|
1793
|
+
await endpoint.read('aqaraOpple', [0x0152], {manufacturerCode: 0x115f});
|
|
1794
|
+
},
|
|
1795
|
+
ota: ota.zigbeeOTA,
|
|
1796
|
+
},
|
|
1797
|
+
{
|
|
1798
|
+
zigbeeModel: ['lumi.motion.acn001'],
|
|
1799
|
+
model: 'RTCGQ15LM',
|
|
1800
|
+
vendor: 'Xiaomi',
|
|
1801
|
+
description: 'Aqara E1 human body movement and illuminance sensor',
|
|
1802
|
+
fromZigbee: [fz.aqara_occupancy_illuminance, fz.aqara_opple, fz.battery],
|
|
1803
|
+
toZigbee: [tz.aqara_detection_interval],
|
|
1804
|
+
exposes: [e.occupancy(), e.illuminance_lux().withProperty('illuminance'),
|
|
1805
|
+
e.illuminance().withUnit('lx').withDescription('Measured illuminance in lux'),
|
|
1806
|
+
exposes.numeric('detection_interval', ea.ALL).withValueMin(2).withValueMax(65535).withUnit('s')
|
|
1807
|
+
.withDescription('Time interval for detecting actions'),
|
|
1808
|
+
e.device_temperature(), e.battery(), e.battery_voltage(), e.power_outage_count(false)],
|
|
1809
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
1810
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1811
|
+
const endpoint = device.getEndpoint(1);
|
|
1812
|
+
await endpoint.read('genPowerCfg', ['batteryVoltage']);
|
|
1813
|
+
await endpoint.read('aqaraOpple', [0x0102], {manufacturerCode: 0x115f});
|
|
1814
|
+
},
|
|
1815
|
+
ota: ota.zigbeeOTA,
|
|
1816
|
+
},
|
|
1817
|
+
{
|
|
1818
|
+
zigbeeModel: ['lumi.motion.ac01'],
|
|
1819
|
+
model: 'RTCZCGQ11LM',
|
|
1820
|
+
vendor: 'Xiaomi',
|
|
1821
|
+
description: 'Aqara presence detector FP1',
|
|
1822
|
+
fromZigbee: [fz.aqara_opple, fzLocal.aqara_fp1_region_events],
|
|
1823
|
+
toZigbee: [
|
|
1824
|
+
tz.RTCZCGQ11LM_presence, tz.RTCZCGQ11LM_monitoring_mode, tz.RTCZCGQ11LM_approach_distance, tz.aqara_motion_sensitivity,
|
|
1825
|
+
tz.RTCZCGQ11LM_reset_nopresence_status, tzLocal.aqara_fp1_region_upsert, tzLocal.aqara_fp1_region_delete,
|
|
1826
|
+
],
|
|
1827
|
+
exposes: [
|
|
1828
|
+
e.presence().withAccess(ea.STATE_GET), e.device_temperature(), e.power_outage_count(),
|
|
1829
|
+
exposes.enum('presence_event', ea.STATE, ['enter', 'leave', 'left_enter', 'right_leave', 'right_enter', 'left_leave',
|
|
1830
|
+
'approach', 'away']).withDescription('Presence events: "enter", "leave", "left_enter", "right_leave", ' +
|
|
1831
|
+
'"right_enter", "left_leave", "approach", "away"'),
|
|
1832
|
+
exposes.enum('monitoring_mode', ea.ALL, ['undirected', 'left_right']).withDescription('Monitoring mode with or ' +
|
|
1833
|
+
'without considering right and left sides'),
|
|
1834
|
+
exposes.enum('approach_distance', ea.ALL, ['far', 'medium', 'near']).withDescription('The distance at which the ' +
|
|
1835
|
+
'sensor detects approaching'),
|
|
1836
|
+
exposes.enum('motion_sensitivity', ea.ALL, ['low', 'medium', 'high']).withDescription('Different sensitivities ' +
|
|
1837
|
+
'means different static human body recognition rate and response speed of occupied'),
|
|
1838
|
+
exposes.enum('reset_nopresence_status', ea.SET, ['']).withDescription('Reset the status of no presence'),
|
|
1839
|
+
exposes.enum('action', ea.STATE, ['region_*_enter', 'region_*_leave', 'region_*_occupied',
|
|
1840
|
+
'region_*_unoccupied']).withDescription('Most recent region event. Event template is "region_<REGION_ID>_<EVENT_TYPE>", ' +
|
|
1841
|
+
'where <REGION_ID> is region number (1-10), <EVENT_TYPE> is one of "enter", "leave", "occupied", "unoccupied". ' +
|
|
1842
|
+
'"enter" / "leave" events are usually triggered first, followed by "occupied" / "unoccupied" after a couple of seconds.'),
|
|
1843
|
+
exposes.composite('region_upsert', 'region_upsert', ea.SET)
|
|
1844
|
+
.withDescription(
|
|
1845
|
+
'Definition of a new region to be added (or replace existing one). ' +
|
|
1846
|
+
'Creating or modifying a region requires you to define which zones of a 7x4 detection grid ' +
|
|
1847
|
+
'should be active for that zone. Regions can overlap, meaning that a zone can be defined ' +
|
|
1848
|
+
'in more than one region (eg. "zone x = 1 & y = 1" can be added to region 1 & 2). ' +
|
|
1849
|
+
'"Zone x = 1 & y = 1" is the nearest zone on the right (from sensor\'s perspective, along the detection path).',
|
|
1850
|
+
)
|
|
1851
|
+
.withFeature(
|
|
1852
|
+
exposes.numeric('region_id', ea.SET)
|
|
1853
|
+
.withValueMin(fp1.constants.region_config_regionId_min)
|
|
1854
|
+
.withValueMax(fp1.constants.region_config_regionId_max),
|
|
1855
|
+
)
|
|
1856
|
+
.withFeature(
|
|
1857
|
+
exposes.list('zones', ea.SET,
|
|
1858
|
+
exposes.composite('zone_position', ea.SET)
|
|
1859
|
+
.withFeature(exposes.numeric('x', ea.SET)
|
|
1860
|
+
.withValueMin(fp1.constants.region_config_zoneX_min)
|
|
1861
|
+
.withValueMax(fp1.constants.region_config_zoneX_max))
|
|
1862
|
+
.withFeature(exposes.numeric('y', ea.SET)
|
|
1863
|
+
.withValueMin(fp1.constants.region_config_zoneY_min)
|
|
1864
|
+
.withValueMax(fp1.constants.region_config_zoneY_max)),
|
|
1865
|
+
),
|
|
1866
|
+
),
|
|
1867
|
+
exposes.composite('region_delete', 'region_delete', ea.SET)
|
|
1868
|
+
.withDescription('Region definition to be deleted from the device.')
|
|
1869
|
+
.withFeature(exposes.numeric('region_id', ea.SET)
|
|
1870
|
+
.withValueMin(fp1.constants.region_config_regionId_min)
|
|
1871
|
+
.withValueMax(fp1.constants.region_config_regionId_max),
|
|
1872
|
+
),
|
|
1873
|
+
],
|
|
1874
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
1875
|
+
const endpoint = device.getEndpoint(1);
|
|
1876
|
+
await endpoint.read('aqaraOpple', [0x010c], {manufacturerCode: 0x115f});
|
|
1877
|
+
await endpoint.read('aqaraOpple', [0x0142], {manufacturerCode: 0x115f});
|
|
1878
|
+
await endpoint.read('aqaraOpple', [0x0144], {manufacturerCode: 0x115f});
|
|
1879
|
+
await endpoint.read('aqaraOpple', [0x0146], {manufacturerCode: 0x115f});
|
|
1880
|
+
},
|
|
1881
|
+
ota: ota.zigbeeOTA,
|
|
1882
|
+
},
|
|
1883
|
+
{
|
|
1884
|
+
zigbeeModel: ['lumi.sensor_magnet'],
|
|
1885
|
+
model: 'MCCGQ01LM',
|
|
1886
|
+
vendor: 'Xiaomi',
|
|
1887
|
+
whiteLabel: [{vendor: 'Xiaomi', model: 'YTC4039GL'}, {vendor: 'Xiaomi', model: 'YTC4005CN'},
|
|
1888
|
+
{vendor: 'Xiaomi', model: 'YTC4015CN'}, {vendor: 'Xiaomi', model: 'ZHTZ02LM'}],
|
|
1889
|
+
description: 'MiJia door & window contact sensor',
|
|
1890
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
1891
|
+
fromZigbee: [fz.xiaomi_basic, fz.xiaomi_contact],
|
|
1892
|
+
toZigbee: [],
|
|
1893
|
+
exposes: [e.battery(), e.contact(), e.battery_voltage(), e.power_outage_count(false)],
|
|
1894
|
+
},
|
|
1895
|
+
{
|
|
1896
|
+
zigbeeModel: ['lumi.sensor_magnet.aq2'],
|
|
1897
|
+
model: 'MCCGQ11LM',
|
|
1898
|
+
vendor: 'Xiaomi',
|
|
1899
|
+
description: 'Aqara door & window contact sensor',
|
|
1900
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
1901
|
+
fromZigbee: [fz.xiaomi_basic, fz.xiaomi_contact],
|
|
1902
|
+
toZigbee: [],
|
|
1903
|
+
exposes: [e.battery(), e.contact(), e.device_temperature(), e.battery_voltage(), e.power_outage_count(false)],
|
|
1904
|
+
configure: async (device) => {
|
|
1905
|
+
device.powerSource = 'Battery';
|
|
1906
|
+
device.save();
|
|
1907
|
+
},
|
|
1908
|
+
},
|
|
1909
|
+
{
|
|
1910
|
+
zigbeeModel: ['lumi.sensor_wleak.aq1'],
|
|
1911
|
+
model: 'SJCGQ11LM',
|
|
1912
|
+
vendor: 'Xiaomi',
|
|
1913
|
+
description: 'Aqara water leak sensor',
|
|
1914
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
1915
|
+
fromZigbee: [fz.xiaomi_basic, fz.ias_water_leak_alarm_1],
|
|
1916
|
+
toZigbee: [],
|
|
1917
|
+
exposes: [e.battery(), e.water_leak(), e.battery_low(), e.battery_voltage(), e.device_temperature(), e.power_outage_count(false)],
|
|
1918
|
+
},
|
|
1919
|
+
{
|
|
1920
|
+
zigbeeModel: ['lumi.flood.agl02'],
|
|
1921
|
+
model: 'SJCGQ12LM',
|
|
1922
|
+
vendor: 'Xiaomi',
|
|
1923
|
+
description: 'Aqara T1 water leak sensor',
|
|
1924
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
1925
|
+
fromZigbee: [fz.xiaomi_basic, fz.ias_water_leak_alarm_1],
|
|
1926
|
+
toZigbee: [],
|
|
1927
|
+
exposes: [e.battery(), e.water_leak(), e.battery_low(), e.tamper(), e.battery_voltage()],
|
|
1928
|
+
ota: ota.zigbeeOTA,
|
|
1929
|
+
},
|
|
1930
|
+
{
|
|
1931
|
+
zigbeeModel: ['lumi.sensor_cube', 'lumi.sensor_cube.aqgl01'],
|
|
1932
|
+
model: 'MFKZQ01LM',
|
|
1933
|
+
vendor: 'Xiaomi',
|
|
1934
|
+
description: 'Mi/Aqara smart home cube',
|
|
1935
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
1936
|
+
fromZigbee: [fz.xiaomi_basic, fz.MFKZQ01LM_action_multistate, fz.MFKZQ01LM_action_analog],
|
|
1937
|
+
exposes: [e.battery(), e.battery_voltage(), e.angle('action_angle'), e.device_temperature(), e.power_outage_count(false),
|
|
1938
|
+
e.cube_side('action_from_side'), e.cube_side('action_side'), e.cube_side('action_to_side'), e.cube_side('side'),
|
|
1939
|
+
e.action(['shake', 'throw', 'wakeup', 'fall', 'tap', 'slide', 'flip180', 'flip90', 'rotate_left', 'rotate_right'])],
|
|
1940
|
+
toZigbee: [],
|
|
1941
|
+
},
|
|
1942
|
+
{
|
|
1943
|
+
zigbeeModel: ['lumi.plug'],
|
|
1944
|
+
model: 'ZNCZ02LM',
|
|
1945
|
+
description: 'Mi power plug ZigBee',
|
|
1946
|
+
vendor: 'Xiaomi',
|
|
1947
|
+
fromZigbee: [fz.on_off, fz.xiaomi_power, fz.xiaomi_basic, fz.ignore_occupancy_report, fz.ignore_illuminance_report],
|
|
1948
|
+
toZigbee: [tz.on_off, tz.xiaomi_switch_power_outage_memory, tz.xiaomi_power],
|
|
1949
|
+
exposes: [e.switch(), e.power().withAccess(ea.STATE_GET), e.energy(), e.device_temperature(), e.power_outage_memory()],
|
|
1950
|
+
ota: ota.zigbeeOTA,
|
|
1951
|
+
},
|
|
1952
|
+
{
|
|
1953
|
+
zigbeeModel: ['lumi.plug.mitw01'],
|
|
1954
|
+
model: 'ZNCZ03LM',
|
|
1955
|
+
description: 'Mi power plug ZigBee TW',
|
|
1956
|
+
vendor: 'Xiaomi',
|
|
1957
|
+
fromZigbee: [fz.on_off, fz.xiaomi_power, fz.xiaomi_basic, fz.ignore_occupancy_report, fz.ignore_illuminance_report],
|
|
1958
|
+
toZigbee: [tz.on_off, tz.xiaomi_power],
|
|
1959
|
+
exposes: [e.switch(), e.power().withAccess(ea.STATE_GET), e.energy(), e.device_temperature().withAccess(ea.STATE),
|
|
1960
|
+
e.voltage()],
|
|
1961
|
+
},
|
|
1962
|
+
{
|
|
1963
|
+
zigbeeModel: ['lumi.plug.mmeu01'],
|
|
1964
|
+
model: 'ZNCZ04LM',
|
|
1965
|
+
description: 'Mi power plug ZigBee EU',
|
|
1966
|
+
vendor: 'Xiaomi',
|
|
1967
|
+
fromZigbee: [fz.on_off, fz.xiaomi_power, fz.aqara_opple, fz.ignore_occupancy_report, fz.ignore_illuminance_report,
|
|
1968
|
+
fz.ignore_time_read],
|
|
1969
|
+
toZigbee: [tz.on_off, tz.xiaomi_power, tz.xiaomi_switch_power_outage_memory, tz.xiaomi_auto_off, tz.xiaomi_led_disabled_night,
|
|
1970
|
+
tz.xiaomi_overload_protection],
|
|
1971
|
+
exposes: [
|
|
1972
|
+
e.switch(), e.power().withAccess(ea.STATE_GET), e.energy(), e.device_temperature().withAccess(ea.STATE),
|
|
1973
|
+
e.voltage(), e.current(), e.consumer_connected(), e.led_disabled_night(),
|
|
1974
|
+
e.power_outage_memory(), e.auto_off(20),
|
|
1975
|
+
e.overload_protection(100, 2300)],
|
|
1976
|
+
ota: ota.zigbeeOTA,
|
|
1977
|
+
},
|
|
1978
|
+
{
|
|
1979
|
+
zigbeeModel: ['lumi.plug.maus01'],
|
|
1980
|
+
model: 'ZNCZ12LM',
|
|
1981
|
+
description: 'Mi power plug ZigBee US',
|
|
1982
|
+
vendor: 'Xiaomi',
|
|
1983
|
+
fromZigbee: [fz.on_off, fz.xiaomi_power, fz.aqara_opple, fz.xiaomi_basic, fz.ignore_occupancy_report, fz.ignore_illuminance_report],
|
|
1984
|
+
toZigbee: [tz.on_off, tz.xiaomi_power, tz.xiaomi_switch_power_outage_memory, tz.xiaomi_auto_off, tz.xiaomi_led_disabled_night,
|
|
1985
|
+
tz.xiaomi_overload_protection],
|
|
1986
|
+
exposes: [
|
|
1987
|
+
e.switch(), e.power().withAccess(ea.STATE_GET), e.energy(), e.device_temperature().withAccess(ea.STATE),
|
|
1988
|
+
e.voltage(), e.current(), e.consumer_connected(), e.led_disabled_night(),
|
|
1989
|
+
e.power_outage_memory(), e.auto_off(20),
|
|
1990
|
+
e.overload_protection(100, 2300)],
|
|
1991
|
+
ota: ota.zigbeeOTA,
|
|
1992
|
+
},
|
|
1993
|
+
{
|
|
1994
|
+
zigbeeModel: ['lumi.plug.maeu01'],
|
|
1995
|
+
model: 'SP-EUC01',
|
|
1996
|
+
description: 'Aqara EU smart plug',
|
|
1997
|
+
vendor: 'Xiaomi',
|
|
1998
|
+
fromZigbee: [fz.on_off, fz.xiaomi_basic, fz.electrical_measurement, fz.metering,
|
|
1999
|
+
fz.aqara_opple, fz.xiaomi_power, fz.device_temperature],
|
|
2000
|
+
toZigbee: [tz.on_off, tz.xiaomi_switch_power_outage_memory, tz.xiaomi_led_disabled_night,
|
|
2001
|
+
tz.xiaomi_overload_protection, tz.xiaomi_auto_off, tz.xiaomi_socket_button_lock],
|
|
2002
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2003
|
+
const endpoint = device.getEndpoint(1);
|
|
2004
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
|
|
2005
|
+
await reporting.onOff(endpoint);
|
|
2006
|
+
|
|
2007
|
+
// Not all plugs support electricity measurements:
|
|
2008
|
+
// - https://github.com/Koenkk/zigbee2mqtt/issues/6861
|
|
2009
|
+
// - https://github.com/Koenkk/zigbee-herdsman-converters/issues/1050#issuecomment-673111969
|
|
2010
|
+
// Voltage and current are not supported:
|
|
2011
|
+
// - https://github.com/Koenkk/zigbee-herdsman-converters/issues/1050
|
|
2012
|
+
try {
|
|
2013
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['haElectricalMeasurement']);
|
|
2014
|
+
await endpoint.read('haElectricalMeasurement', ['acPowerMultiplier', 'acPowerDivisor']);
|
|
2015
|
+
} catch (e) {
|
|
2016
|
+
logger.warn(`SP-EUC01 failed to setup electricity measurements (${e.message})`);
|
|
2017
|
+
logger.debug(e.stack);
|
|
2018
|
+
}
|
|
2019
|
+
try {
|
|
2020
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['seMetering']);
|
|
2021
|
+
await reporting.readMeteringMultiplierDivisor(endpoint);
|
|
2022
|
+
await reporting.currentSummDelivered(endpoint, {change: 0});
|
|
2023
|
+
} catch (e) {
|
|
2024
|
+
logger.warn(`SP-EUC01 failed to setup metering (${e.message})`);
|
|
2025
|
+
logger.debug(e.stack);
|
|
2026
|
+
}
|
|
2027
|
+
},
|
|
2028
|
+
onEvent: async (type, data, device) => {
|
|
2029
|
+
const switchEndpoint = device.getEndpoint(1);
|
|
2030
|
+
if (switchEndpoint == null) {
|
|
2031
|
+
return;
|
|
2032
|
+
}
|
|
2033
|
+
|
|
2034
|
+
// This device doesn't support temperature reporting.
|
|
2035
|
+
// Therefore we read the temperature every 30 min.
|
|
2036
|
+
if (type === 'stop') {
|
|
2037
|
+
clearInterval(globalStore.getValue(device, 'interval'));
|
|
2038
|
+
globalStore.clearValue(device, 'interval');
|
|
2039
|
+
} else if (!globalStore.hasValue(device, 'interval')) {
|
|
2040
|
+
const interval = setInterval(async () => {
|
|
2041
|
+
try {
|
|
2042
|
+
await switchEndpoint.read('genDeviceTempCfg', ['currentTemperature']);
|
|
2043
|
+
} catch (error) {
|
|
2044
|
+
// Do nothing
|
|
2045
|
+
}
|
|
2046
|
+
}, 1800000);
|
|
2047
|
+
globalStore.putValue(device, 'interval', interval);
|
|
2048
|
+
}
|
|
2049
|
+
},
|
|
2050
|
+
exposes: [e.switch(), e.power(), e.energy(), e.power_outage_memory(), e.voltage(), e.current(),
|
|
2051
|
+
e.device_temperature().withDescription('Device temperature (polled every 30 min)'),
|
|
2052
|
+
e.consumer_connected(), e.led_disabled_night(), e.overload_protection(100, 2300),
|
|
2053
|
+
e.auto_off(20), e.button_lock()],
|
|
2054
|
+
ota: ota.zigbeeOTA,
|
|
2055
|
+
},
|
|
2056
|
+
{
|
|
2057
|
+
zigbeeModel: ['lumi.plug.aq1'],
|
|
2058
|
+
model: 'ZNCZ11LM',
|
|
2059
|
+
vendor: 'Xiaomi',
|
|
2060
|
+
description: 'Aqara power plug ZigBee',
|
|
2061
|
+
fromZigbee: [fz.on_off, fz.xiaomi_power, fz.ignore_occupancy_report, fz.xiaomi_basic],
|
|
2062
|
+
toZigbee: [tz.on_off, tz.xiaomi_power, tz.xiaomi_led_disabled_night,
|
|
2063
|
+
tz.xiaomi_switch_power_outage_memory, tz.xiaomi_auto_off],
|
|
2064
|
+
exposes: [e.switch(), e.power().withAccess(ea.STATE_GET), e.energy(), e.device_temperature(), e.voltage(),
|
|
2065
|
+
e.power_outage_memory(), e.led_disabled_night(),
|
|
2066
|
+
e.auto_off(30)],
|
|
2067
|
+
onEvent: async (type, data, device) => {
|
|
2068
|
+
device.skipTimeResponse = true;
|
|
2069
|
+
// According to the Zigbee the genTime.time should be the seconds since 1 January 2020 UTC
|
|
2070
|
+
// However the device expects this to be the seconds since 1 January in the local time zone.
|
|
2071
|
+
// Disable the responses of zigbee-herdsman and respond here instead.
|
|
2072
|
+
// https://github.com/Koenkk/zigbee-herdsman-converters/pull/2843#issuecomment-888532667
|
|
2073
|
+
if (type === 'message' && data.type === 'read' && data.cluster === 'genTime') {
|
|
2074
|
+
const oneJanuary2000 = new Date('January 01, 2000 00:00:00 UTC+00:00').getTime();
|
|
2075
|
+
const secondsUTC = Math.round(((new Date()).getTime() - oneJanuary2000) / 1000);
|
|
2076
|
+
const secondsLocal = secondsUTC - (new Date()).getTimezoneOffset() * 60;
|
|
2077
|
+
device.getEndpoint(1).readResponse('genTime', data.meta.zclTransactionSequenceNumber, {time: secondsLocal});
|
|
2078
|
+
}
|
|
2079
|
+
},
|
|
2080
|
+
},
|
|
2081
|
+
{
|
|
2082
|
+
zigbeeModel: ['lumi.ctrl_86plug', 'lumi.ctrl_86plug.aq1'],
|
|
2083
|
+
model: 'QBCZ11LM',
|
|
2084
|
+
description: 'Aqara socket Zigbee',
|
|
2085
|
+
vendor: 'Xiaomi',
|
|
2086
|
+
fromZigbee: [fz.on_off, fz.xiaomi_power, fz.xiaomi_basic],
|
|
2087
|
+
toZigbee: [tz.on_off, tz.xiaomi_switch_power_outage_memory, tz.xiaomi_power],
|
|
2088
|
+
exposes: [e.switch(), e.power().withAccess(ea.STATE_GET), e.energy(), e.device_temperature().withAccess(ea.STATE),
|
|
2089
|
+
e.voltage(), e.power_outage_memory()],
|
|
2090
|
+
ota: ota.zigbeeOTA,
|
|
2091
|
+
},
|
|
2092
|
+
{
|
|
2093
|
+
zigbeeModel: ['lumi.sensor_smoke'],
|
|
2094
|
+
model: 'JTYJ-GD-01LM/BW',
|
|
2095
|
+
description: 'MiJia Honeywell smoke detector',
|
|
2096
|
+
vendor: 'Xiaomi',
|
|
2097
|
+
whiteLabel: [{vendor: 'Xiaomi', model: 'YTC4020RT'}],
|
|
2098
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
2099
|
+
fromZigbee: [fz.xiaomi_basic, fz.JTYJGD01LMBW_smoke],
|
|
2100
|
+
toZigbee: [tz.JTQJBF01LMBW_JTYJGD01LMBW_sensitivity, tz.JTQJBF01LMBW_JTYJGD01LMBW_selfest],
|
|
2101
|
+
exposes: [
|
|
2102
|
+
e.smoke(), e.battery_low(), e.tamper(), e.battery(), exposes.enum('sensitivity', ea.STATE_SET, ['low', 'medium', 'high']),
|
|
2103
|
+
exposes.numeric('smoke_density', ea.STATE), exposes.enum('selftest', ea.SET, ['']), e.battery_voltage(),
|
|
2104
|
+
exposes.binary('test', ea.STATE, true, false).withDescription('Test mode activated'), e.device_temperature(),
|
|
2105
|
+
e.power_outage_count(false),
|
|
2106
|
+
],
|
|
2107
|
+
},
|
|
2108
|
+
{
|
|
2109
|
+
zigbeeModel: ['lumi.sensor_natgas'],
|
|
2110
|
+
model: 'JTQJ-BF-01LM/BW',
|
|
2111
|
+
vendor: 'Xiaomi',
|
|
2112
|
+
whiteLabel: [{vendor: 'Xiaomi', model: 'YTC4019RT'}],
|
|
2113
|
+
description: 'MiJia gas leak detector ',
|
|
2114
|
+
fromZigbee: [fz.ias_gas_alarm_1, fz.JTQJBF01LMBW_sensitivity, fz.JTQJBF01LMBW_gas_density],
|
|
2115
|
+
toZigbee: [tz.JTQJBF01LMBW_JTYJGD01LMBW_sensitivity, tz.JTQJBF01LMBW_JTYJGD01LMBW_selfest],
|
|
2116
|
+
exposes: [
|
|
2117
|
+
e.gas(), e.battery_low(), e.tamper(), exposes.enum('sensitivity', ea.STATE_SET, ['low', 'medium', 'high']),
|
|
2118
|
+
exposes.numeric('gas_density', ea.STATE), exposes.enum('selftest', ea.SET, ['']),
|
|
2119
|
+
],
|
|
2120
|
+
},
|
|
2121
|
+
{
|
|
2122
|
+
zigbeeModel: ['lumi.sensor_gas.acn02'],
|
|
2123
|
+
model: 'JT-BZ-01AQ/A',
|
|
2124
|
+
vendor: 'Xiaomi',
|
|
2125
|
+
description: 'Aqara smart natural gas detector',
|
|
2126
|
+
fromZigbee: [fz.aqara_opple],
|
|
2127
|
+
toZigbee: [tz.aqara_alarm, tz.aqara_density, tz.JTBZ01AQA_gas_sensitivity, tz.aqara_selftest, tz.aqara_buzzer,
|
|
2128
|
+
tz.aqara_buzzer_manual, tz.aqara_linkage_alarm, tz.JTBZ01AQA_state, tz.aqara_power_outage_count],
|
|
2129
|
+
exposes: [e.gas().withAccess(ea.STATE_GET),
|
|
2130
|
+
exposes.numeric('gas_density', ea.STATE_GET).withUnit('%LEL').withDescription('Value of gas concentration'),
|
|
2131
|
+
exposes.enum('gas_sensitivity', ea.ALL, ['10%LEL', '15%LEL']).withDescription('Gas concentration value at which ' +
|
|
2132
|
+
'an alarm is triggered ("10%LEL" is more sensitive than "15%LEL")'),
|
|
2133
|
+
exposes.enum('selftest', ea.SET, ['selftest']).withDescription('Starts the self-test process (checking the indicator ' +
|
|
2134
|
+
'light and buzzer work properly)'),
|
|
2135
|
+
exposes.binary('test', ea.STATE, true, false).withDescription('Self-test in progress'),
|
|
2136
|
+
exposes.enum('buzzer', ea.SET, ['mute', 'alarm']).withDescription('The buzzer can be muted and alarmed manually. ' +
|
|
2137
|
+
'During a gas alarm, the buzzer can be manually muted for 10 minutes ("mute"), but cannot be unmuted manually ' +
|
|
2138
|
+
'before this timeout expires. The buzzer cannot be pre-muted, as this function only works during a gas alarm. ' +
|
|
2139
|
+
'During the absence of a gas alarm, the buzzer can be manually alarmed ("alarm") and disalarmed ("mute")'),
|
|
2140
|
+
exposes.binary('buzzer_manual_alarm', ea.STATE_GET, true, false).withDescription('Buzzer alarmed (manually)'),
|
|
2141
|
+
exposes.binary('buzzer_manual_mute', ea.STATE_GET, true, false).withDescription('Buzzer muted (manually)'),
|
|
2142
|
+
exposes.binary('linkage_alarm', ea.ALL, true, false).withDescription('When this option is enabled and a gas ' +
|
|
2143
|
+
'alarm has occurred, then "linkage_alarm_state"=true, and when the gas alarm has ended or the buzzer has ' +
|
|
2144
|
+
'been manually muted, then "linkage_alarm_state"=false'),
|
|
2145
|
+
exposes.binary('linkage_alarm_state', ea.STATE, true, false).withDescription('"linkage_alarm" is triggered'),
|
|
2146
|
+
exposes.binary('state', ea.STATE_GET, 'preparation', 'work').withDescription('"Preparation" or "work" ' +
|
|
2147
|
+
'(measurement of the gas concentration value and triggering of an alarm are only performed in the "work" state)'),
|
|
2148
|
+
e.power_outage_count().withAccess(ea.STATE_GET)],
|
|
2149
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2150
|
+
const endpoint = device.getEndpoint(1);
|
|
2151
|
+
await endpoint.read('aqaraOpple', [0x013a], {manufacturerCode: 0x115f});
|
|
2152
|
+
await endpoint.read('aqaraOpple', [0x013b], {manufacturerCode: 0x115f});
|
|
2153
|
+
await endpoint.read('aqaraOpple', [0x013d], {manufacturerCode: 0x115f});
|
|
2154
|
+
await endpoint.read('aqaraOpple', [0x0126], {manufacturerCode: 0x115f});
|
|
2155
|
+
await endpoint.read('aqaraOpple', [0x0139], {manufacturerCode: 0x115f});
|
|
2156
|
+
await endpoint.read('aqaraOpple', [0x010c], {manufacturerCode: 0x115f});
|
|
2157
|
+
await endpoint.read('aqaraOpple', [0x014b], {manufacturerCode: 0x115f});
|
|
2158
|
+
await endpoint.read('aqaraOpple', [0x0002], {manufacturerCode: 0x115f});
|
|
2159
|
+
},
|
|
2160
|
+
ota: ota.zigbeeOTA,
|
|
2161
|
+
},
|
|
2162
|
+
{
|
|
2163
|
+
zigbeeModel: ['lumi.sensor_smoke.acn03'],
|
|
2164
|
+
model: 'JY-GZ-01AQ',
|
|
2165
|
+
vendor: 'Xiaomi',
|
|
2166
|
+
description: 'Aqara smart smoke detector',
|
|
2167
|
+
fromZigbee: [fz.aqara_opple, fz.battery],
|
|
2168
|
+
toZigbee: [tz.aqara_alarm, tz.aqara_density, tz.aqara_selftest, tz.aqara_buzzer, tz.aqara_buzzer_manual,
|
|
2169
|
+
tz.JYGZ01AQ_heartbeat_indicator, tz.aqara_linkage_alarm],
|
|
2170
|
+
exposes: [e.smoke().withAccess(ea.STATE_GET),
|
|
2171
|
+
exposes.numeric('smoke_density', ea.STATE_GET).withDescription('Value of smoke concentration'),
|
|
2172
|
+
exposes.numeric('smoke_density_dbm', ea.STATE_GET).withUnit('dB/m').withDescription('Value of smoke concentration in dB/m'),
|
|
2173
|
+
exposes.enum('selftest', ea.SET, ['selftest']).withDescription('Starts the self-test process (checking the indicator ' +
|
|
2174
|
+
'light and buzzer work properly)'),
|
|
2175
|
+
exposes.binary('test', ea.STATE, true, false).withDescription('Self-test in progress'),
|
|
2176
|
+
exposes.enum('buzzer', ea.SET, ['mute', 'alarm']).withDescription('The buzzer can be muted and alarmed manually. ' +
|
|
2177
|
+
'During a smoke alarm, the buzzer can be manually muted for 80 seconds ("mute") and unmuted ("alarm"). ' +
|
|
2178
|
+
'The buzzer cannot be pre-muted, as this function only works during a smoke alarm. ' +
|
|
2179
|
+
'During the absence of a smoke alarm, the buzzer can be manually alarmed ("alarm") and disalarmed ("mute")'),
|
|
2180
|
+
exposes.binary('buzzer_manual_alarm', ea.STATE_GET, true, false).withDescription('Buzzer alarmed (manually)'),
|
|
2181
|
+
exposes.binary('buzzer_manual_mute', ea.STATE_GET, true, false).withDescription('Buzzer muted (manually)'),
|
|
2182
|
+
exposes.binary('heartbeat_indicator', ea.ALL, true, false).withDescription('When this option is enabled then in ' +
|
|
2183
|
+
'the normal monitoring state, the green indicator light flashes every 60 seconds'),
|
|
2184
|
+
exposes.binary('linkage_alarm', ea.ALL, true, false).withDescription('When this option is enabled and a smoke ' +
|
|
2185
|
+
'alarm has occurred, then "linkage_alarm_state"=true, and when the smoke alarm has ended or the buzzer has ' +
|
|
2186
|
+
'been manually muted, then "linkage_alarm_state"=false'),
|
|
2187
|
+
exposes.binary('linkage_alarm_state', ea.STATE, true, false).withDescription('"linkage_alarm" is triggered'),
|
|
2188
|
+
e.battery(), e.battery_voltage(), e.power_outage_count(false)],
|
|
2189
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
2190
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2191
|
+
const endpoint = device.getEndpoint(1);
|
|
2192
|
+
await endpoint.read('genPowerCfg', ['batteryVoltage']);
|
|
2193
|
+
await endpoint.read('aqaraOpple', [0x013a], {manufacturerCode: 0x115f});
|
|
2194
|
+
await endpoint.read('aqaraOpple', [0x013b], {manufacturerCode: 0x115f});
|
|
2195
|
+
await endpoint.read('aqaraOpple', [0x013c], {manufacturerCode: 0x115f});
|
|
2196
|
+
await endpoint.read('aqaraOpple', [0x013d], {manufacturerCode: 0x115f});
|
|
2197
|
+
await endpoint.read('aqaraOpple', [0x0126], {manufacturerCode: 0x115f});
|
|
2198
|
+
await endpoint.read('aqaraOpple', [0x014b], {manufacturerCode: 0x115f});
|
|
2199
|
+
},
|
|
2200
|
+
ota: ota.zigbeeOTA,
|
|
2201
|
+
},
|
|
2202
|
+
{
|
|
2203
|
+
zigbeeModel: ['lumi.lock.v1'],
|
|
2204
|
+
model: 'A6121',
|
|
2205
|
+
vendor: 'Xiaomi',
|
|
2206
|
+
description: 'Vima Smart Lock',
|
|
2207
|
+
fromZigbee: [fz.xiaomi_lock_report],
|
|
2208
|
+
exposes: [exposes.text('inserted', ea.STATE)],
|
|
2209
|
+
toZigbee: [],
|
|
2210
|
+
},
|
|
2211
|
+
{
|
|
2212
|
+
zigbeeModel: ['lumi.vibration.aq1'],
|
|
2213
|
+
model: 'DJT11LM',
|
|
2214
|
+
vendor: 'Xiaomi',
|
|
2215
|
+
description: 'Aqara vibration sensor',
|
|
2216
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
2217
|
+
fromZigbee: [fz.xiaomi_basic, fz.DJT11LM_vibration],
|
|
2218
|
+
toZigbee: [tz.DJT11LM_vibration_sensitivity],
|
|
2219
|
+
exposes: [
|
|
2220
|
+
e.battery(), e.device_temperature(), e.vibration(), e.action(['vibration', 'tilt', 'drop']),
|
|
2221
|
+
exposes.numeric('strength', ea.STATE), exposes.enum('sensitivity', ea.STATE_SET, ['low', 'medium', 'high']),
|
|
2222
|
+
e.angle_axis('angle_x'), e.angle_axis('angle_y'), e.angle_axis('angle_z'), e.battery_voltage(), e.power_outage_count(false),
|
|
2223
|
+
],
|
|
2224
|
+
},
|
|
2225
|
+
{
|
|
2226
|
+
zigbeeModel: ['lumi.vibration.agl01'],
|
|
2227
|
+
model: 'DJT12LM',
|
|
2228
|
+
vendor: 'Xiaomi',
|
|
2229
|
+
description: 'Aqara T1 vibration sensor',
|
|
2230
|
+
fromZigbee: [fz.DJT12LM_vibration],
|
|
2231
|
+
exposes: [e.action(['vibration'])],
|
|
2232
|
+
toZigbee: [],
|
|
2233
|
+
ota: ota.zigbeeOTA,
|
|
2234
|
+
},
|
|
2235
|
+
{
|
|
2236
|
+
zigbeeModel: ['lumi.curtain'],
|
|
2237
|
+
model: 'ZNCLDJ11LM',
|
|
2238
|
+
description: 'Aqara curtain motor',
|
|
2239
|
+
vendor: 'Xiaomi',
|
|
2240
|
+
fromZigbee: [fz.xiaomi_basic, fz.xiaomi_curtain_position, fz.xiaomi_curtain_position_tilt],
|
|
2241
|
+
toZigbee: [tz.xiaomi_curtain_position_state, tz.xiaomi_curtain_options],
|
|
2242
|
+
exposes: [e.cover_position().setAccess('state', ea.ALL),
|
|
2243
|
+
exposes.binary('running', ea.STATE, true, false)
|
|
2244
|
+
.withDescription('Whether the motor is moving or not'),
|
|
2245
|
+
exposes.enum('motor_state', ea.STATE, ['stopped', 'opening', 'closing'])
|
|
2246
|
+
.withDescription('Motor state')],
|
|
2247
|
+
ota: ota.zigbeeOTA,
|
|
2248
|
+
},
|
|
2249
|
+
{
|
|
2250
|
+
zigbeeModel: ['lumi.curtain.aq2'],
|
|
2251
|
+
model: 'ZNGZDJ11LM',
|
|
2252
|
+
description: 'Aqara roller shade motor',
|
|
2253
|
+
vendor: 'Xiaomi',
|
|
2254
|
+
whiteLabel: [{vendor: 'Xiaomi', model: 'SRSC-M01'}],
|
|
2255
|
+
fromZigbee: [fz.xiaomi_basic, fz.xiaomi_curtain_position, fz.xiaomi_curtain_position_tilt],
|
|
2256
|
+
toZigbee: [tz.xiaomi_curtain_position_state, tz.xiaomi_curtain_options],
|
|
2257
|
+
exposes: [e.cover_position().setAccess('state', ea.ALL),
|
|
2258
|
+
exposes.binary('running', ea.STATE, true, false)
|
|
2259
|
+
.withDescription('Whether the motor is moving or not')],
|
|
2260
|
+
ota: ota.zigbeeOTA,
|
|
2261
|
+
},
|
|
2262
|
+
{
|
|
2263
|
+
zigbeeModel: ['lumi.curtain.hagl04'],
|
|
2264
|
+
model: 'ZNCLDJ12LM',
|
|
2265
|
+
vendor: 'Xiaomi',
|
|
2266
|
+
description: 'Aqara B1 curtain motor',
|
|
2267
|
+
fromZigbee: [fz.xiaomi_basic, fz.xiaomi_curtain_position, fz.xiaomi_curtain_position_tilt, fz.xiaomi_curtain_hagl04_status],
|
|
2268
|
+
toZigbee: [tz.xiaomi_curtain_position_state, tz.xiaomi_curtain_options],
|
|
2269
|
+
onEvent: async (type, data, device) => {
|
|
2270
|
+
// The position (genAnalogOutput.presentValue) reported via an attribute contains an invaid value
|
|
2271
|
+
// however when reading it will provide the correct value.
|
|
2272
|
+
if (data.type === 'attributeReport' && data.cluster === 'genAnalogOutput') {
|
|
2273
|
+
await device.endpoints[0].read('genAnalogOutput', ['presentValue']);
|
|
2274
|
+
}
|
|
2275
|
+
},
|
|
2276
|
+
exposes: [e.cover_position().setAccess('state', ea.ALL), e.battery(),
|
|
2277
|
+
exposes.binary('running', ea.STATE, true, false)
|
|
2278
|
+
.withDescription('Whether the motor is moving or not'),
|
|
2279
|
+
exposes.enum('motor_state', ea.STATE, ['closing', 'opening', 'stop'])
|
|
2280
|
+
.withDescription('The current state of the motor.'), e.power_outage_count()],
|
|
2281
|
+
ota: ota.zigbeeOTA,
|
|
2282
|
+
},
|
|
2283
|
+
{
|
|
2284
|
+
zigbeeModel: ['lumi.curtain.hagl07'],
|
|
2285
|
+
model: 'ZNCLDJ14LM',
|
|
2286
|
+
vendor: 'Xiaomi',
|
|
2287
|
+
description: 'Aqara C2 curtain motor',
|
|
2288
|
+
fromZigbee: [fz.xiaomi_basic, fz.xiaomi_curtain_position, fz.xiaomi_curtain_position_tilt, fz.xiaomi_curtain_hagl07_status],
|
|
2289
|
+
toZigbee: [tz.xiaomi_curtain_position_state, tz.xiaomi_curtain_options],
|
|
2290
|
+
onEvent: async (type, data, device) => {
|
|
2291
|
+
// The position (genAnalogOutput.presentValue) reported via an attribute contains an invaid value
|
|
2292
|
+
// however when reading it will provide the correct value.
|
|
2293
|
+
if (data.type === 'attributeReport' && data.cluster === 'genAnalogOutput') {
|
|
2294
|
+
await device.endpoints[0].read('genAnalogOutput', ['presentValue']);
|
|
2295
|
+
}
|
|
2296
|
+
},
|
|
2297
|
+
exposes: [e.cover_position().setAccess('state', ea.ALL),
|
|
2298
|
+
exposes.binary('running', ea.STATE, true, false)
|
|
2299
|
+
.withDescription('Whether the motor is moving or not'),
|
|
2300
|
+
exposes.enum('motor_state', ea.STATE, ['closing', 'opening', 'stop'])
|
|
2301
|
+
.withDescription('The current state of the motor.'), e.power_outage_count()],
|
|
2302
|
+
ota: ota.zigbeeOTA,
|
|
2303
|
+
},
|
|
2304
|
+
{
|
|
2305
|
+
zigbeeModel: ['lumi.curtain.acn002'],
|
|
2306
|
+
model: 'ZNJLBL01LM',
|
|
2307
|
+
description: 'Aqara roller shade companion E1',
|
|
2308
|
+
vendor: 'Xiaomi',
|
|
2309
|
+
whiteLabel: [{vendor: 'Xiaomi', model: 'RSD-M01'}],
|
|
2310
|
+
fromZigbee: [fz.xiaomi_curtain_position, fz.xiaomi_curtain_acn002_status, fz.ignore_basic_report, fz.aqara_opple],
|
|
2311
|
+
toZigbee: [tz.xiaomi_curtain_position_state, tz.xiaomi_curtain_acn002_battery, tz.xiaomi_curtain_acn002_charging_status],
|
|
2312
|
+
onEvent: async (type, data, device) => {
|
|
2313
|
+
if (type === 'message' && data.type === 'attributeReport' && data.cluster === 'genMultistateOutput' &&
|
|
2314
|
+
data.data.hasOwnProperty('presentValue') && data.data['presentValue'] > 1) {
|
|
2315
|
+
// Try to read the position after the motor stops, the device occasionally report wrong data right after stopping
|
|
2316
|
+
// Might need to add delay, seems to be working without one but needs more tests.
|
|
2317
|
+
await device.getEndpoint(1).read('genAnalogOutput', ['presentValue']);
|
|
2318
|
+
}
|
|
2319
|
+
},
|
|
2320
|
+
exposes: [e.cover_position().setAccess('state', ea.ALL), e.battery().withAccess(ea.STATE_GET), e.device_temperature(),
|
|
2321
|
+
exposes.binary('charging_status', ea.STATE_GET, true, false)
|
|
2322
|
+
.withDescription('The current charging status.'),
|
|
2323
|
+
exposes.enum('motor_state', ea.STATE, ['declining', 'rising', 'pause', 'blocked'])
|
|
2324
|
+
.withDescription('The current state of the motor.'),
|
|
2325
|
+
exposes.binary('running', ea.STATE, true, false)
|
|
2326
|
+
.withDescription('Whether the motor is moving or not')],
|
|
2327
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2328
|
+
device.powerSource = 'Battery';
|
|
2329
|
+
device.save();
|
|
2330
|
+
const endpoint = device.getEndpoint(1);
|
|
2331
|
+
await endpoint.read('aqaraOpple', [0x040a], {manufacturerCode: 0x115f});
|
|
2332
|
+
},
|
|
2333
|
+
ota: ota.zigbeeOTA,
|
|
2334
|
+
},
|
|
2335
|
+
{
|
|
2336
|
+
// 'lumi.curtain.acn003' - CN version (ZNCLBL01LM), 'lumi.curtain.agl001' - global version (CM-M01)
|
|
2337
|
+
zigbeeModel: ['lumi.curtain.acn003', 'lumi.curtain.agl001'],
|
|
2338
|
+
model: 'ZNCLBL01LM',
|
|
2339
|
+
vendor: 'Xiaomi',
|
|
2340
|
+
whiteLabel: [{vendor: 'Xiaomi', model: 'CM-M01'}],
|
|
2341
|
+
description: 'Aqara curtain driver E1',
|
|
2342
|
+
fromZigbee: [
|
|
2343
|
+
fz.battery,
|
|
2344
|
+
fz.xiaomi_curtain_position_tilt,
|
|
2345
|
+
fz.aqara_opple,
|
|
2346
|
+
fz.power_source,
|
|
2347
|
+
],
|
|
2348
|
+
toZigbee: [
|
|
2349
|
+
tz.xiaomi_curtain_position_state,
|
|
2350
|
+
tz.xiaomi_curtain_battery_voltage,
|
|
2351
|
+
tz.ZNCLBL01LM_hooks_lock,
|
|
2352
|
+
tz.ZNCLBL01LM_hooks_state,
|
|
2353
|
+
tz.ZNCLBL01LM_hand_open,
|
|
2354
|
+
tz.ZNCLBL01LM_limits_calibration,
|
|
2355
|
+
tz.power_source,
|
|
2356
|
+
tz.battery_percentage_remaining,
|
|
2357
|
+
],
|
|
2358
|
+
exposes: [
|
|
2359
|
+
e.cover_position().setAccess('state', ea.ALL),
|
|
2360
|
+
exposes.binary('hand_open', ea.ALL, true, false).withDescription('Pulling curtains by hand starts the motor'),
|
|
2361
|
+
exposes.enum('limits_calibration', ea.SET, ['start', 'end', 'reset']).withDescription('Calibrate the position limits'),
|
|
2362
|
+
e.battery().withAccess(ea.STATE_GET),
|
|
2363
|
+
e.battery_voltage().withAccess(ea.STATE_GET),
|
|
2364
|
+
e.device_temperature(),
|
|
2365
|
+
e.action(['manual_open', 'manual_close']),
|
|
2366
|
+
exposes.enum('motor_state', ea.STATE, ['stopped', 'opening', 'closing', 'pause']).withDescription('Motor state'),
|
|
2367
|
+
exposes.binary('running', ea.STATE, true, false).withDescription('Whether the motor is moving or not'),
|
|
2368
|
+
exposes.enum('hooks_lock', ea.STATE_SET, ['LOCK', 'UNLOCK']).withDescription('Lock the curtain driver hooks'),
|
|
2369
|
+
exposes.enum('hooks_state', ea.STATE_GET, ['unlocked', 'locked', 'locking', 'unlocking']).withDescription('Hooks state'),
|
|
2370
|
+
exposes.numeric('target_position', ea.STATE).withUnit('%').withDescription('Target position'),
|
|
2371
|
+
exposes.enum('power_source', ea.STATE_GET, ['battery', 'dc_source']).withDescription('The current power source'),
|
|
2372
|
+
exposes.binary('charging', ea.STATE_GET, true, false).withDescription('The current charging state'),
|
|
2373
|
+
],
|
|
2374
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2375
|
+
const endpoint = device.getEndpoint(1);
|
|
2376
|
+
await endpoint.read('genPowerCfg', ['batteryPercentageRemaining']);
|
|
2377
|
+
await endpoint.read('aqaraOpple', [0x040B], {manufacturerCode: 0x115f});
|
|
2378
|
+
await endpoint.read('aqaraOpple', [0x0428], {manufacturerCode: 0x115f});
|
|
2379
|
+
await endpoint.read('genBasic', ['powerSource']);
|
|
2380
|
+
await endpoint.read('closuresWindowCovering', ['currentPositionLiftPercentage']);
|
|
2381
|
+
},
|
|
2382
|
+
ota: ota.zigbeeOTA,
|
|
2383
|
+
},
|
|
2384
|
+
{
|
|
2385
|
+
zigbeeModel: ['lumi.relay.c2acn01'],
|
|
2386
|
+
model: 'LLKZMK11LM',
|
|
2387
|
+
vendor: 'Xiaomi',
|
|
2388
|
+
description: 'Aqara wireless relay controller',
|
|
2389
|
+
fromZigbee: [fz.xiaomi_basic, fz.xiaomi_power, fz.ignore_multistate_report, fz.on_off, fz.xiaomi_basic_raw],
|
|
2390
|
+
meta: {multiEndpoint: true},
|
|
2391
|
+
toZigbee: [tz.on_off, tz.LLKZMK11LM_interlock, tz.xiaomi_power, tz.xiaomi_switch_power_outage_memory],
|
|
2392
|
+
endpoint: (device) => {
|
|
2393
|
+
return {'l1': 1, 'l2': 2};
|
|
2394
|
+
},
|
|
2395
|
+
exposes: [e.power().withAccess(ea.STATE_GET), e.energy(), e.device_temperature(), e.voltage(), e.current(),
|
|
2396
|
+
e.switch().withEndpoint('l1'), e.switch().withEndpoint('l2'), e.power_outage_count(false),
|
|
2397
|
+
e.power_outage_memory(),
|
|
2398
|
+
exposes.binary('interlock', ea.STATE_SET, true, false)
|
|
2399
|
+
.withDescription('Enabling prevents both relais being on at the same time'),
|
|
2400
|
+
],
|
|
2401
|
+
ota: ota.zigbeeOTA,
|
|
2402
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2403
|
+
device.powerSource = 'Mains (single phase)';
|
|
2404
|
+
device.save();
|
|
2405
|
+
},
|
|
2406
|
+
},
|
|
2407
|
+
{
|
|
2408
|
+
zigbeeModel: ['lumi.lock.acn02'],
|
|
2409
|
+
model: 'ZNMS12LM',
|
|
2410
|
+
description: 'Aqara S2 lock',
|
|
2411
|
+
vendor: 'Xiaomi',
|
|
2412
|
+
fromZigbee: [fz.xiaomi_basic, fz.ZNMS12LM_ZNMS13LM_closuresDoorLock_report, fz.ZNMS12LM_low_battery],
|
|
2413
|
+
toZigbee: [],
|
|
2414
|
+
exposes: [
|
|
2415
|
+
e.battery(), e.battery_voltage(), e.battery_low(), exposes.binary('state', ea.STATE, 'UNLOCK', 'LOCK'),
|
|
2416
|
+
exposes.binary('reverse', ea.STATE, 'UNLOCK', 'LOCK'),
|
|
2417
|
+
exposes.enum('action', ea.STATE, [
|
|
2418
|
+
'finger_not_match', 'password_not_match', 'reverse_lock', 'reverse_lock_cancel', 'locked', 'lock_opened',
|
|
2419
|
+
'finger_add', 'finger_delete', 'password_add', 'password_delete', 'lock_opened_inside', 'lock_opened_outside',
|
|
2420
|
+
'ring_bell', 'change_language_to', 'finger_open', 'password_open', 'door_closed',
|
|
2421
|
+
]),
|
|
2422
|
+
],
|
|
2423
|
+
meta: {battery: {voltageToPercentage: '4LR6AA1_5v'}},
|
|
2424
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2425
|
+
// Device advertises itself as Router but is an EndDevice
|
|
2426
|
+
device.type = 'EndDevice';
|
|
2427
|
+
device.save();
|
|
2428
|
+
},
|
|
2429
|
+
ota: ota.zigbeeOTA,
|
|
2430
|
+
},
|
|
2431
|
+
{
|
|
2432
|
+
zigbeeModel: ['lumi.lock.acn03'],
|
|
2433
|
+
model: 'ZNMS13LM',
|
|
2434
|
+
description: 'Aqara S2 lock pro',
|
|
2435
|
+
vendor: 'Xiaomi',
|
|
2436
|
+
fromZigbee: [fz.ZNMS12LM_ZNMS13LM_closuresDoorLock_report, fz.ignore_basic_report],
|
|
2437
|
+
toZigbee: [],
|
|
2438
|
+
exposes: [
|
|
2439
|
+
exposes.binary('state', ea.STATE, 'UNLOCK', 'LOCK'),
|
|
2440
|
+
exposes.binary('reverse', ea.STATE, 'UNLOCK', 'LOCK'),
|
|
2441
|
+
exposes.enum('action', ea.STATE, [
|
|
2442
|
+
'finger_not_match', 'password_not_match', 'reverse_lock', 'reverse_lock_cancel', 'locked', 'lock_opened',
|
|
2443
|
+
'finger_add', 'finger_delete', 'password_add', 'password_delete', 'lock_opened_inside', 'lock_opened_outside',
|
|
2444
|
+
'ring_bell', 'change_language_to', 'finger_open', 'password_open', 'door_closed',
|
|
2445
|
+
]),
|
|
2446
|
+
],
|
|
2447
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2448
|
+
// Device advertises itself as Router but is an EndDevice
|
|
2449
|
+
device.type = 'EndDevice';
|
|
2450
|
+
device.save();
|
|
2451
|
+
},
|
|
2452
|
+
},
|
|
2453
|
+
{
|
|
2454
|
+
zigbeeModel: ['lumi.lock.aq1'],
|
|
2455
|
+
model: 'ZNMS11LM',
|
|
2456
|
+
description: 'Xiaomi Aqara smart lock',
|
|
2457
|
+
vendor: 'Xiaomi',
|
|
2458
|
+
fromZigbee: [fz.ZNMS11LM_closuresDoorLock_report, fz.ignore_basic_report],
|
|
2459
|
+
toZigbee: [],
|
|
2460
|
+
exposes: [
|
|
2461
|
+
exposes.binary('state', ea.STATE, 'UNLOCK', 'LOCK'),
|
|
2462
|
+
exposes.binary('reverse', ea.STATE, 'UNLOCK', 'LOCK'),
|
|
2463
|
+
exposes.enum('action', ea.STATE, [
|
|
2464
|
+
'finger_not_match', 'password_not_match', 'reverse_lock', 'reverse_lock_cancel', 'locked', 'lock_opened',
|
|
2465
|
+
'finger_add', 'finger_delete', 'password_add', 'password_delete', 'lock_opened_inside', 'lock_opened_outside',
|
|
2466
|
+
'ring_bell', 'change_language_to', 'finger_open', 'password_open', 'door_closed',
|
|
2467
|
+
]),
|
|
2468
|
+
],
|
|
2469
|
+
ota: ota.zigbeeOTA,
|
|
2470
|
+
},
|
|
2471
|
+
{
|
|
2472
|
+
zigbeeModel: ['lumi.remote.b286opcn01'],
|
|
2473
|
+
model: 'WXCJKG11LM',
|
|
2474
|
+
vendor: 'Xiaomi',
|
|
2475
|
+
description: 'Aqara Opple switch 1 band',
|
|
2476
|
+
fromZigbee: [fz.aqara_opple_on, fz.aqara_opple_off, fz.battery, fz.aqara_opple_multistate, fz.aqara_opple],
|
|
2477
|
+
exposes: [e.battery(), e.battery_voltage(), e.action([
|
|
2478
|
+
'button_1_hold', 'button_1_release', 'button_1_single', 'button_1_double', 'button_1_triple',
|
|
2479
|
+
'button_2_hold', 'button_2_release', 'button_2_single', 'button_2_double', 'button_2_triple',
|
|
2480
|
+
]), exposes.enum('operation_mode', ea.ALL, ['command', 'event'])
|
|
2481
|
+
.withDescription('Operation mode, select "command" to enable bindings (wake up the device before changing modes!)')],
|
|
2482
|
+
toZigbee: [tz.aqara_opple_operation_mode],
|
|
2483
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
2484
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2485
|
+
const endpoint = device.getEndpoint(1);
|
|
2486
|
+
await endpoint.write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f});
|
|
2487
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'genPowerCfg']);
|
|
2488
|
+
},
|
|
2489
|
+
},
|
|
2490
|
+
{
|
|
2491
|
+
zigbeeModel: ['lumi.remote.b486opcn01'],
|
|
2492
|
+
model: 'WXCJKG12LM',
|
|
2493
|
+
vendor: 'Xiaomi',
|
|
2494
|
+
description: 'Aqara Opple switch 2 bands',
|
|
2495
|
+
fromZigbee: [fz.aqara_opple_on, fz.aqara_opple_off, fz.aqara_opple_step, fz.aqara_opple_step_color_temp, fz.battery,
|
|
2496
|
+
fz.aqara_opple_multistate, fz.aqara_opple],
|
|
2497
|
+
exposes: [e.battery(), e.battery_voltage(), e.action([
|
|
2498
|
+
'button_1_hold', 'button_1_release', 'button_1_single', 'button_1_double', 'button_1_triple',
|
|
2499
|
+
'button_2_hold', 'button_2_release', 'button_2_single', 'button_2_double', 'button_2_triple',
|
|
2500
|
+
'button_3_hold', 'button_3_release', 'button_3_single', 'button_3_double', 'button_3_triple',
|
|
2501
|
+
'button_4_hold', 'button_4_release', 'button_4_single', 'button_4_double', 'button_4_triple',
|
|
2502
|
+
]), exposes.enum('operation_mode', ea.ALL, ['command', 'event'])
|
|
2503
|
+
.withDescription('Operation mode, select "command" to enable bindings (wake up the device before changing modes!)')],
|
|
2504
|
+
toZigbee: [tz.aqara_opple_operation_mode],
|
|
2505
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
2506
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2507
|
+
const endpoint = device.getEndpoint(1);
|
|
2508
|
+
await endpoint.write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f});
|
|
2509
|
+
await reporting.bind(endpoint, coordinatorEndpoint, [
|
|
2510
|
+
'genOnOff', 'genLevelCtrl', 'lightingColorCtrl', 'genPowerCfg',
|
|
2511
|
+
]);
|
|
2512
|
+
},
|
|
2513
|
+
},
|
|
2514
|
+
{
|
|
2515
|
+
zigbeeModel: ['lumi.remote.b686opcn01'],
|
|
2516
|
+
model: 'WXCJKG13LM',
|
|
2517
|
+
vendor: 'Xiaomi',
|
|
2518
|
+
description: 'Aqara Opple switch 3 bands',
|
|
2519
|
+
fromZigbee: [fz.aqara_opple_on, fz.aqara_opple_off, fz.aqara_opple_step, fz.aqara_opple_move, fz.aqara_opple_stop,
|
|
2520
|
+
fz.aqara_opple_step_color_temp, fz.aqara_opple_move_color_temp, fz.battery, fz.aqara_opple_multistate, fz.aqara_opple],
|
|
2521
|
+
exposes: [e.battery(), e.battery_voltage(), e.action([
|
|
2522
|
+
'button_1_hold', 'button_1_release', 'button_1_single', 'button_1_double', 'button_1_triple',
|
|
2523
|
+
'button_2_hold', 'button_2_release', 'button_2_single', 'button_2_double', 'button_2_triple',
|
|
2524
|
+
'button_3_hold', 'button_3_release', 'button_3_single', 'button_3_double', 'button_3_triple',
|
|
2525
|
+
'button_4_hold', 'button_4_release', 'button_4_single', 'button_4_double', 'button_4_triple',
|
|
2526
|
+
'button_5_hold', 'button_5_release', 'button_5_single', 'button_5_double', 'button_5_triple',
|
|
2527
|
+
'button_6_hold', 'button_6_release', 'button_6_single', 'button_6_double', 'button_6_triple',
|
|
2528
|
+
]), exposes.enum('operation_mode', ea.ALL, ['command', 'event'])
|
|
2529
|
+
.withDescription('Operation mode, select "command" to enable bindings (wake up the device before changing modes!)'),
|
|
2530
|
+
e.power_outage_count(false)],
|
|
2531
|
+
toZigbee: [tz.aqara_opple_operation_mode],
|
|
2532
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
2533
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2534
|
+
const endpoint = device.getEndpoint(1);
|
|
2535
|
+
await endpoint.write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f});
|
|
2536
|
+
await reporting.bind(endpoint, coordinatorEndpoint, [
|
|
2537
|
+
'genOnOff', 'genLevelCtrl', 'lightingColorCtrl', 'genPowerCfg',
|
|
2538
|
+
]);
|
|
2539
|
+
},
|
|
2540
|
+
},
|
|
2541
|
+
{
|
|
2542
|
+
zigbeeModel: ['lumi.sen_ill.mgl01'],
|
|
2543
|
+
model: 'GZCGQ01LM',
|
|
2544
|
+
vendor: 'Xiaomi',
|
|
2545
|
+
whiteLabel: [{vendor: 'Xiaomi', model: 'YTC4043GL'}],
|
|
2546
|
+
description: 'MiJia light intensity sensor',
|
|
2547
|
+
fromZigbee: [fz.battery, fz.illuminance, fz.aqara_opple],
|
|
2548
|
+
toZigbee: [tz.illuminance],
|
|
2549
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
2550
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2551
|
+
const endpoint = device.getEndpoint(1);
|
|
2552
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['msIlluminanceMeasurement']);
|
|
2553
|
+
await reporting.illuminance(endpoint, {min: 15, max: constants.repInterval.HOUR, change: 500});
|
|
2554
|
+
await endpoint.read('genPowerCfg', ['batteryVoltage']);
|
|
2555
|
+
},
|
|
2556
|
+
exposes: [e.battery(), e.battery_voltage(), e.illuminance().withAccess(ea.STATE_GET),
|
|
2557
|
+
e.illuminance_lux().withAccess(ea.STATE_GET), e.power_outage_count(false)],
|
|
2558
|
+
},
|
|
2559
|
+
{
|
|
2560
|
+
zigbeeModel: ['lumi.light.rgbac1'],
|
|
2561
|
+
model: 'ZNTGMK11LM',
|
|
2562
|
+
vendor: 'Xiaomi',
|
|
2563
|
+
description: 'Aqara smart RGBW light controller',
|
|
2564
|
+
extend: extend.light_onoff_brightness_colortemp_color({supportsHS: true}),
|
|
2565
|
+
ota: ota.zigbeeOTA,
|
|
2566
|
+
},
|
|
2567
|
+
{
|
|
2568
|
+
zigbeeModel: ['lumi.light.cbacn1'],
|
|
2569
|
+
model: 'HLQDQ01LM',
|
|
2570
|
+
vendor: 'Xiaomi',
|
|
2571
|
+
description: 'Aqara zigbee LED-controller ',
|
|
2572
|
+
extend: extend.light_onoff_brightness(),
|
|
2573
|
+
ota: ota.zigbeeOTA,
|
|
2574
|
+
},
|
|
2575
|
+
{
|
|
2576
|
+
zigbeeModel: ['lumi.light.acn004'],
|
|
2577
|
+
model: 'SSWQD02LM',
|
|
2578
|
+
vendor: 'Xiaomi',
|
|
2579
|
+
description: 'Aqara smart dimmer controller t1 pro',
|
|
2580
|
+
extend: extend.light_onoff_brightness_colortemp({
|
|
2581
|
+
disableEffect: true, disablePowerOnBehavior: true, disableColorTempStartup: true, colorTempRange: [153, 370]}),
|
|
2582
|
+
ota: ota.zigbeeOTA,
|
|
2583
|
+
},
|
|
2584
|
+
{
|
|
2585
|
+
zigbeeModel: ['lumi.light.acn026'],
|
|
2586
|
+
model: 'SSWQD03LM',
|
|
2587
|
+
vendor: 'Xiaomi',
|
|
2588
|
+
description: 'Aqara spotlight T2',
|
|
2589
|
+
extend: extend.light_onoff_brightness_colortemp({
|
|
2590
|
+
disableEffect: true, disablePowerOnBehavior: true, disableColorTempStartup: true, colorTempRange: [153, 370]}),
|
|
2591
|
+
ota: ota.zigbeeOTA,
|
|
2592
|
+
},
|
|
2593
|
+
{
|
|
2594
|
+
zigbeeModel: ['lumi.switch.n0agl1'],
|
|
2595
|
+
model: 'SSM-U01',
|
|
2596
|
+
vendor: 'Xiaomi',
|
|
2597
|
+
description: 'Aqara single switch module T1 (with neutral)',
|
|
2598
|
+
// Ignore energy metering reports, rely on aqara_opple: https://github.com/Koenkk/zigbee2mqtt/issues/10709
|
|
2599
|
+
fromZigbee: [fz.on_off, fz.device_temperature, fz.aqara_opple, fz.ignore_metering, fz.ignore_electrical_measurement,
|
|
2600
|
+
fz.xiaomi_power],
|
|
2601
|
+
exposes: [e.switch(), e.energy(), e.power(), e.device_temperature(), e.power_outage_memory(), e.power_outage_count(),
|
|
2602
|
+
e.switch_type(), e.voltage(), e.current(),
|
|
2603
|
+
],
|
|
2604
|
+
toZigbee: [tz.xiaomi_switch_type, tz.on_off, tz.xiaomi_switch_power_outage_memory, tz.xiaomi_led_disabled_night],
|
|
2605
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2606
|
+
const endpoint = device.getEndpoint(1);
|
|
2607
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'genDeviceTempCfg']);
|
|
2608
|
+
await reporting.onOff(endpoint);
|
|
2609
|
+
await reporting.deviceTemperature(endpoint);
|
|
2610
|
+
device.powerSource = 'Mains (single phase)';
|
|
2611
|
+
device.type = 'Router';
|
|
2612
|
+
device.save();
|
|
2613
|
+
},
|
|
2614
|
+
ota: ota.zigbeeOTA,
|
|
2615
|
+
},
|
|
2616
|
+
{
|
|
2617
|
+
zigbeeModel: ['lumi.switch.n0acn2'],
|
|
2618
|
+
model: 'DLKZMK11LM',
|
|
2619
|
+
vendor: 'Xiaomi',
|
|
2620
|
+
description: 'Aqara single switch module T1 (with neutral)',
|
|
2621
|
+
fromZigbee: [fz.on_off, fz.xiaomi_power, fz.aqara_opple],
|
|
2622
|
+
toZigbee: [tz.on_off, tz.xiaomi_power, tz.xiaomi_switch_type, tz.xiaomi_switch_power_outage_memory, tz.xiaomi_led_disabled_night],
|
|
2623
|
+
exposes: [e.switch(), e.power().withAccess(ea.STATE_GET), e.energy(), e.device_temperature().withAccess(ea.STATE),
|
|
2624
|
+
e.voltage(), e.power_outage_memory(), e.led_disabled_night(), e.switch_type()],
|
|
2625
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2626
|
+
await device.getEndpoint(1).write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
|
|
2627
|
+
device.powerSource = 'Mains (single phase)';
|
|
2628
|
+
device.save();
|
|
2629
|
+
},
|
|
2630
|
+
ota: ota.zigbeeOTA,
|
|
2631
|
+
},
|
|
2632
|
+
{
|
|
2633
|
+
zigbeeModel: ['lumi.switch.l0agl1'],
|
|
2634
|
+
model: 'SSM-U02',
|
|
2635
|
+
vendor: 'Xiaomi',
|
|
2636
|
+
description: 'Aqara single switch module T1 (without neutral). Doesn\'t work as a router and doesn\'t support power meter',
|
|
2637
|
+
fromZigbee: [fz.on_off, fz.aqara_opple],
|
|
2638
|
+
exposes: [e.switch(), e.power_outage_memory(), e.switch_type(), e.power_outage_count(), e.device_temperature()],
|
|
2639
|
+
toZigbee: [tz.xiaomi_switch_type, tz.on_off, tz.xiaomi_switch_power_outage_memory],
|
|
2640
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2641
|
+
const endpoint = device.getEndpoint(1);
|
|
2642
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
|
|
2643
|
+
await reporting.onOff(endpoint);
|
|
2644
|
+
device.powerSource = 'Mains (single phase)';
|
|
2645
|
+
device.save();
|
|
2646
|
+
},
|
|
2647
|
+
},
|
|
2648
|
+
{
|
|
2649
|
+
zigbeeModel: ['lumi.switch.l0acn1'],
|
|
2650
|
+
model: 'DLKZMK12LM',
|
|
2651
|
+
vendor: 'Xiaomi',
|
|
2652
|
+
description: 'Aqara single switch module T1 (without neutral). Doesn\'t work as a router and doesn\'t support power meter',
|
|
2653
|
+
fromZigbee: [fz.on_off, fz.aqara_opple],
|
|
2654
|
+
exposes: [e.switch(), e.power_outage_memory(), e.switch_type()],
|
|
2655
|
+
toZigbee: [tz.xiaomi_switch_type, tz.on_off, tz.xiaomi_switch_power_outage_memory],
|
|
2656
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2657
|
+
const endpoint = device.getEndpoint(1);
|
|
2658
|
+
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
|
|
2659
|
+
await reporting.onOff(endpoint);
|
|
2660
|
+
device.powerSource = 'Mains (single phase)';
|
|
2661
|
+
device.save();
|
|
2662
|
+
},
|
|
2663
|
+
},
|
|
2664
|
+
{
|
|
2665
|
+
zigbeeModel: ['lumi.switch.n4acn4'],
|
|
2666
|
+
model: 'ZNCJMB14LM',
|
|
2667
|
+
vendor: 'Xiaomi',
|
|
2668
|
+
description: 'Aqara S1 smart touch panel',
|
|
2669
|
+
fromZigbee: [fz.on_off, fz.ZNCJMB14LM],
|
|
2670
|
+
toZigbee: [tz.on_off, tz.ZNCJMB14LM],
|
|
2671
|
+
meta: {multiEndpoint: true},
|
|
2672
|
+
endpoint: (device) => {
|
|
2673
|
+
return {'left': 1, 'center': 2, 'right': 3};
|
|
2674
|
+
},
|
|
2675
|
+
exposes: [e.switch().withEndpoint('left'), e.switch().withEndpoint('center'),
|
|
2676
|
+
e.switch().withEndpoint('right'),
|
|
2677
|
+
exposes.binary('standby_enabled', ea.STATE_SET, true, false).withDescription('Enable standby'),
|
|
2678
|
+
exposes.enum('theme', ea.STATE_SET, ['classic', 'concise']).withDescription('Display theme'),
|
|
2679
|
+
exposes.enum('beep_volume', ea.STATE_SET, ['mute', 'low', 'medium', 'high']).withDescription('Beep volume'),
|
|
2680
|
+
exposes.numeric('lcd_brightness', ea.STATE_SET).withValueMin(1).withValueMax(100).withUnit('%')
|
|
2681
|
+
.withDescription('LCD brightness (will not persist if auto-brightness is enabled)'),
|
|
2682
|
+
exposes.enum('language', ea.STATE_SET, ['chinese', 'english']).withDescription('Interface language'),
|
|
2683
|
+
exposes.enum('screen_saver_style', ea.STATE_SET, ['classic', 'analog clock']).withDescription('Screen saver style'),
|
|
2684
|
+
exposes.numeric('standby_time', ea.STATE_SET).withValueMin(0).withValueMax(65534).withUnit('s')
|
|
2685
|
+
.withDescription('Display standby time'),
|
|
2686
|
+
exposes.enum('font_size', ea.STATE_SET, ['small', 'medium', 'large']).withDescription('Display font size'),
|
|
2687
|
+
exposes.binary('lcd_auto_brightness_enabled', ea.STATE_SET, true, false).withDescription('Enable LCD auto brightness'),
|
|
2688
|
+
exposes.enum('homepage', ea.STATE_SET, ['scene', 'feel', 'thermostat', 'switch']).withDescription('Default display homepage'),
|
|
2689
|
+
exposes.binary('screen_saver_enabled', ea.STATE_SET, true, false).withDescription('Enable screen saver'),
|
|
2690
|
+
exposes.numeric('standby_lcd_brightness', ea.STATE_SET).withValueMin(1).withValueMax(100).withUnit('%')
|
|
2691
|
+
.withDescription('Standby LCD brightness'),
|
|
2692
|
+
exposes.enum('available_switches', ea.STATE_SET, ['none', '1', '2', '3', '1 and 2', '1 and 3', '2 and 3', 'all'])
|
|
2693
|
+
.withDescription('Control which switches are available in the switches screen (none disables switches screen)'),
|
|
2694
|
+
exposes.composite('switch_1_text_icon', 'switch_1_text_icon', ea.STATE_SET).withDescription('Switch 1 text and icon')
|
|
2695
|
+
.withFeature(exposes.enum('switch_1_icon', ea.STATE_SET, ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11'])
|
|
2696
|
+
.withDescription('Icon'))
|
|
2697
|
+
.withFeature(exposes.text('switch_1_text', ea.STATE_SET)
|
|
2698
|
+
.withDescription('Text')),
|
|
2699
|
+
exposes.composite('switch_2_text_icon', 'switch_2_text_icon', ea.STATE_SET).withDescription('Switch 2 text and icon')
|
|
2700
|
+
.withFeature(exposes.enum('switch_2_icon', ea.STATE_SET, ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11'])
|
|
2701
|
+
.withDescription('Icon'))
|
|
2702
|
+
.withFeature(exposes.text('switch_2_text', ea.STATE_SET)
|
|
2703
|
+
.withDescription('Text')),
|
|
2704
|
+
exposes.composite('switch_3_text_icon', 'switch_3_text_icon', ea.STATE_SET).withDescription('Switch 3 text and icon')
|
|
2705
|
+
.withFeature(exposes.enum('switch_3_icon', ea.STATE_SET, ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11'])
|
|
2706
|
+
.withDescription('Icon'))
|
|
2707
|
+
.withFeature(exposes.text('switch_3_text', ea.STATE_SET)
|
|
2708
|
+
.withDescription('Text'))],
|
|
2709
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2710
|
+
await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
|
|
2711
|
+
await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
|
|
2712
|
+
await reporting.bind(device.getEndpoint(3), coordinatorEndpoint, ['genOnOff']);
|
|
2713
|
+
await reporting.onOff(device.getEndpoint(1));
|
|
2714
|
+
// await reporting.onOff(device.getEndpoint(2)); ToDo: Currently fails
|
|
2715
|
+
// await reporting.onOff(device.getEndpoint(3)); ToDo: Currently fails
|
|
2716
|
+
},
|
|
2717
|
+
ota: ota.zigbeeOTA,
|
|
2718
|
+
},
|
|
2719
|
+
{
|
|
2720
|
+
zigbeeModel: ['lumi.remote.b28ac1'],
|
|
2721
|
+
model: 'WXKG15LM',
|
|
2722
|
+
vendor: 'Xiaomi',
|
|
2723
|
+
whiteLabel: [{vendor: 'Xiaomi', model: 'WRS-R02'}],
|
|
2724
|
+
description: 'Aqara wireless remote switch H1 (double rocker)',
|
|
2725
|
+
fromZigbee: [fz.battery, fz.xiaomi_multistate_action, fz.aqara_opple, fz.command_toggle],
|
|
2726
|
+
toZigbee: [tz.xiaomi_switch_click_mode, tz.aqara_opple_operation_mode],
|
|
2727
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}, multiEndpoint: true},
|
|
2728
|
+
exposes: [
|
|
2729
|
+
e.battery(), e.battery_voltage(), e.action([
|
|
2730
|
+
'single_left', 'single_right', 'single_both',
|
|
2731
|
+
'double_left', 'double_right', 'double_both',
|
|
2732
|
+
'triple_left', 'triple_right', 'triple_both',
|
|
2733
|
+
'hold_left', 'hold_right', 'hold_both']),
|
|
2734
|
+
exposes.enum('click_mode', ea.ALL, ['fast', 'multi'])
|
|
2735
|
+
.withDescription('Click mode, fast: only supports single click which will be send immediately after clicking.' +
|
|
2736
|
+
'multi: supports more events like double and hold'),
|
|
2737
|
+
exposes.enum('operation_mode', ea.ALL, ['command', 'event'])
|
|
2738
|
+
.withDescription('Operation mode, select "command" to enable bindings (wake up the device before changing modes!)'),
|
|
2739
|
+
],
|
|
2740
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2741
|
+
const endpoint1 = device.getEndpoint(1);
|
|
2742
|
+
const endpoint2 = device.getEndpoint(3);
|
|
2743
|
+
// set "event" mode
|
|
2744
|
+
await endpoint1.write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f});
|
|
2745
|
+
// turn on the "multiple clicks" mode, otherwise the only "single click" events.
|
|
2746
|
+
// if value is 1 - there will be single clicks, 2 - multiple.
|
|
2747
|
+
await endpoint1.write('aqaraOpple', {0x0125: {value: 0x02, type: 0x20}}, {manufacturerCode: 0x115f});
|
|
2748
|
+
await reporting.bind(endpoint1, coordinatorEndpoint, ['genOnOff', 'genPowerCfg']);
|
|
2749
|
+
await reporting.bind(endpoint2, coordinatorEndpoint, ['genOnOff']);
|
|
2750
|
+
// TODO/BUG:
|
|
2751
|
+
// Did not understand how to separate the left and right keys in command mode -
|
|
2752
|
+
// the "toggleCommand" always arrives from the first endpoint
|
|
2753
|
+
},
|
|
2754
|
+
},
|
|
2755
|
+
{
|
|
2756
|
+
zigbeeModel: ['lumi.switch.b1lc04'],
|
|
2757
|
+
model: 'QBKG38LM',
|
|
2758
|
+
vendor: 'Xiaomi',
|
|
2759
|
+
description: 'Aqara E1 1 gang switch (without neutral)',
|
|
2760
|
+
fromZigbee: [fz.on_off, fz.xiaomi_multistate_action, fz.aqara_opple],
|
|
2761
|
+
toZigbee: [tz.on_off, tz.xiaomi_switch_operation_mode_opple, tz.xiaomi_switch_power_outage_memory,
|
|
2762
|
+
tz.aqara_switch_mode_switch, tz.xiaomi_flip_indicator_light],
|
|
2763
|
+
exposes: [e.switch(), e.power_outage_memory(), e.action(['single', 'double']),
|
|
2764
|
+
e.device_temperature(), e.flip_indicator_light(),
|
|
2765
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
2766
|
+
.withDescription('Decoupled mode for button'),
|
|
2767
|
+
exposes.enum('mode_switch', ea.ALL, ['anti_flicker_mode', 'quick_mode'])
|
|
2768
|
+
.withDescription('Anti flicker mode can be used to solve blinking issues of some lights.' +
|
|
2769
|
+
'Quick mode makes the device respond faster.')],
|
|
2770
|
+
onEvent: preventReset,
|
|
2771
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2772
|
+
await device.getEndpoint(1).write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
|
|
2773
|
+
},
|
|
2774
|
+
ota: ota.zigbeeOTA,
|
|
2775
|
+
},
|
|
2776
|
+
{
|
|
2777
|
+
zigbeeModel: ['lumi.switch.b2lc04'],
|
|
2778
|
+
model: 'QBKG39LM',
|
|
2779
|
+
vendor: 'Xiaomi',
|
|
2780
|
+
description: 'Aqara E1 2 gang switch (without neutral)',
|
|
2781
|
+
fromZigbee: [fz.on_off, fz.xiaomi_multistate_action, fz.aqara_opple],
|
|
2782
|
+
toZigbee: [tz.on_off, tz.xiaomi_switch_operation_mode_opple, tz.xiaomi_switch_power_outage_memory,
|
|
2783
|
+
tz.aqara_switch_mode_switch, tz.xiaomi_flip_indicator_light],
|
|
2784
|
+
meta: {multiEndpoint: true},
|
|
2785
|
+
endpoint: (device) => {
|
|
2786
|
+
return {'left': 1, 'right': 2};
|
|
2787
|
+
},
|
|
2788
|
+
exposes: [
|
|
2789
|
+
e.switch().withEndpoint('left'), e.switch().withEndpoint('right'), e.device_temperature(),
|
|
2790
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
2791
|
+
.withDescription('Decoupled mode for left button')
|
|
2792
|
+
.withEndpoint('left'),
|
|
2793
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
2794
|
+
.withDescription('Decoupled mode for right button')
|
|
2795
|
+
.withEndpoint('right'),
|
|
2796
|
+
exposes.enum('mode_switch', ea.ALL, ['anti_flicker_mode', 'quick_mode'])
|
|
2797
|
+
.withDescription('Anti flicker mode can be used to solve blinking issues of some lights.' +
|
|
2798
|
+
'Quick mode makes the device respond faster.'),
|
|
2799
|
+
e.action(['single_left', 'double_left', 'single_right', 'double_right', 'single_both', 'double_both']),
|
|
2800
|
+
e.power_outage_memory(), e.flip_indicator_light(),
|
|
2801
|
+
],
|
|
2802
|
+
onEvent: preventReset,
|
|
2803
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2804
|
+
await device.getEndpoint(1).write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
|
|
2805
|
+
},
|
|
2806
|
+
ota: ota.zigbeeOTA,
|
|
2807
|
+
},
|
|
2808
|
+
{
|
|
2809
|
+
zigbeeModel: ['lumi.airmonitor.acn01'],
|
|
2810
|
+
model: 'VOCKQJK11LM',
|
|
2811
|
+
vendor: 'Xiaomi',
|
|
2812
|
+
whiteLabel: [{vendor: 'Xiaomi', model: 'AAQS-S01'}],
|
|
2813
|
+
description: 'Aqara TVOC air quality monitor',
|
|
2814
|
+
fromZigbee: [fz.xiaomi_tvoc, fz.battery, fz.temperature, fz.humidity, fz.aqara_opple],
|
|
2815
|
+
toZigbee: [tzLocal.VOCKQJK11LM_display_unit],
|
|
2816
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
2817
|
+
exposes: [e.temperature(), e.humidity(), e.voc().withUnit('ppb'), e.device_temperature(), e.battery(), e.battery_voltage(),
|
|
2818
|
+
exposes.enum('display_unit', ea.ALL, ['mgm3_celsius', 'ppb_celsius', 'mgm3_fahrenheit', 'ppb_fahrenheit'])
|
|
2819
|
+
.withDescription('Units to show on the display')],
|
|
2820
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2821
|
+
const endpoint = device.getEndpoint(1);
|
|
2822
|
+
const binds = ['msTemperatureMeasurement', 'msRelativeHumidity', 'genAnalogInput'];
|
|
2823
|
+
await reporting.bind(endpoint, coordinatorEndpoint, binds);
|
|
2824
|
+
await reporting.humidity(endpoint);
|
|
2825
|
+
await reporting.temperature(endpoint);
|
|
2826
|
+
const payload = reporting.payload('presentValue', 10, constants.repInterval.HOUR, 5);
|
|
2827
|
+
await endpoint.configureReporting('genAnalogInput', payload);
|
|
2828
|
+
await endpoint.read('genPowerCfg', ['batteryVoltage']);
|
|
2829
|
+
},
|
|
2830
|
+
ota: ota.zigbeeOTA,
|
|
2831
|
+
},
|
|
2832
|
+
{
|
|
2833
|
+
zigbeeModel: ['lumi.switch.b2nc01'],
|
|
2834
|
+
model: 'QBKG41LM',
|
|
2835
|
+
vendor: 'Xiaomi',
|
|
2836
|
+
description: 'Aqara E1 2 gang switch (with neutral)',
|
|
2837
|
+
fromZigbee: [fz.on_off, fz.xiaomi_multistate_action, fz.aqara_opple],
|
|
2838
|
+
toZigbee: [tz.on_off, tz.xiaomi_switch_operation_mode_opple, tz.xiaomi_switch_power_outage_memory,
|
|
2839
|
+
tz.xiaomi_flip_indicator_light],
|
|
2840
|
+
meta: {multiEndpoint: true},
|
|
2841
|
+
endpoint: (device) => {
|
|
2842
|
+
return {'left': 1, 'right': 2};
|
|
2843
|
+
},
|
|
2844
|
+
exposes: [
|
|
2845
|
+
e.switch().withEndpoint('left'), e.switch().withEndpoint('right'),
|
|
2846
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
2847
|
+
.withDescription('Decoupled mode for left button')
|
|
2848
|
+
.withEndpoint('left'),
|
|
2849
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
2850
|
+
.withDescription('Decoupled mode for right button')
|
|
2851
|
+
.withEndpoint('right'),
|
|
2852
|
+
e.action(['single_left', 'double_left', 'single_right', 'double_right', 'single_both', 'double_both']),
|
|
2853
|
+
e.power_outage_memory(), e.device_temperature(), e.flip_indicator_light(),
|
|
2854
|
+
],
|
|
2855
|
+
onEvent: preventReset,
|
|
2856
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2857
|
+
await device.getEndpoint(1).write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
|
|
2858
|
+
},
|
|
2859
|
+
ota: ota.zigbeeOTA,
|
|
2860
|
+
},
|
|
2861
|
+
{
|
|
2862
|
+
zigbeeModel: ['lumi.plug.macn01'],
|
|
2863
|
+
model: 'ZNCZ15LM',
|
|
2864
|
+
vendor: 'Xiaomi',
|
|
2865
|
+
description: 'Aqara smart plug T1 (china standard)',
|
|
2866
|
+
fromZigbee: [fz.on_off, fz.xiaomi_power, fz.aqara_opple],
|
|
2867
|
+
toZigbee: [tz.on_off, tz.xiaomi_switch_power_outage_memory, tz.xiaomi_led_disabled_night,
|
|
2868
|
+
tz.xiaomi_overload_protection, tz.xiaomi_socket_button_lock],
|
|
2869
|
+
exposes: [e.switch(), e.power().withAccess(ea.STATE), e.energy(), e.device_temperature().withAccess(ea.STATE),
|
|
2870
|
+
e.voltage(), e.current(), e.consumer_connected().withAccess(ea.STATE),
|
|
2871
|
+
e.power_outage_memory(), e.led_disabled_night(), e.button_lock(),
|
|
2872
|
+
e.overload_protection(100, 2500)],
|
|
2873
|
+
ota: ota.zigbeeOTA,
|
|
2874
|
+
},
|
|
2875
|
+
{
|
|
2876
|
+
zigbeeModel: ['lumi.switch.b1nc01'],
|
|
2877
|
+
model: 'QBKG40LM',
|
|
2878
|
+
vendor: 'Xiaomi',
|
|
2879
|
+
description: 'Aqara E1 1 gang switch (with neutral)',
|
|
2880
|
+
fromZigbee: [fz.on_off, fz.xiaomi_multistate_action, fz.aqara_opple],
|
|
2881
|
+
toZigbee: [tz.on_off, tz.xiaomi_switch_operation_mode_opple, tz.xiaomi_switch_power_outage_memory,
|
|
2882
|
+
tz.xiaomi_flip_indicator_light],
|
|
2883
|
+
exposes: [e.switch(), e.action(['single', 'double']), e.power_outage_memory(), e.device_temperature(), e.flip_indicator_light(),
|
|
2884
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled']).withDescription('Decoupled mode')],
|
|
2885
|
+
onEvent: preventReset,
|
|
2886
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2887
|
+
await device.getEndpoint(1).write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
|
|
2888
|
+
},
|
|
2889
|
+
ota: ota.zigbeeOTA,
|
|
2890
|
+
},
|
|
2891
|
+
{
|
|
2892
|
+
zigbeeModel: ['lumi.remote.b1acn02'],
|
|
2893
|
+
model: 'WXKG13LM',
|
|
2894
|
+
vendor: 'Xiaomi',
|
|
2895
|
+
description: 'Aqara T1 wireless mini switch',
|
|
2896
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
2897
|
+
fromZigbee: [fz.battery, fz.aqara_opple_multistate, fz.aqara_opple],
|
|
2898
|
+
toZigbee: [],
|
|
2899
|
+
exposes: [e.battery(), e.battery_voltage(), e.action(['single', 'double', 'triple', 'quintuple', 'hold', 'release', 'many'])],
|
|
2900
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2901
|
+
const endpoint1 = device.getEndpoint(1);
|
|
2902
|
+
await endpoint1.write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
|
|
2903
|
+
},
|
|
2904
|
+
ota: ota.zigbeeOTA,
|
|
2905
|
+
},
|
|
2906
|
+
{
|
|
2907
|
+
zigbeeModel: ['lumi.sen_ill.agl01'],
|
|
2908
|
+
model: 'GZCGQ11LM',
|
|
2909
|
+
vendor: 'Xiaomi',
|
|
2910
|
+
description: 'Aqara T1 light intensity sensor',
|
|
2911
|
+
fromZigbee: [fz.battery, fz.illuminance, fz.aqara_opple],
|
|
2912
|
+
toZigbee: [tz.GZCGQ11LM_detection_period],
|
|
2913
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
2914
|
+
exposes: [e.battery(), e.battery_voltage(), e.illuminance(), e.illuminance_lux(),
|
|
2915
|
+
exposes.numeric('detection_period', exposes.access.ALL).withValueMin(1).withValueMax(59).withUnit('s')
|
|
2916
|
+
.withDescription('Time interval in seconds to report after light changes')],
|
|
2917
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2918
|
+
const endpoint = device.getEndpoint(1);
|
|
2919
|
+
await device.getEndpoint(1).write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
|
|
2920
|
+
await endpoint.read('aqaraOpple', [0x0000], {manufactureCode: 0x115f});
|
|
2921
|
+
},
|
|
2922
|
+
ota: ota.zigbeeOTA,
|
|
2923
|
+
},
|
|
2924
|
+
{
|
|
2925
|
+
zigbeeModel: ['lumi.plug.sacn03'],
|
|
2926
|
+
model: 'QBCZ15LM',
|
|
2927
|
+
vendor: 'Xiaomi',
|
|
2928
|
+
description: 'Aqara smart wall outlet H1 (USB)',
|
|
2929
|
+
fromZigbee: [fz.on_off, fz.xiaomi_power, fz.aqara_opple],
|
|
2930
|
+
toZigbee: [tz.on_off, tz.xiaomi_switch_power_outage_memory, tz.xiaomi_led_disabled_night,
|
|
2931
|
+
tz.xiaomi_button_switch_mode, tz.xiaomi_overload_protection, tz.xiaomi_socket_button_lock],
|
|
2932
|
+
meta: {multiEndpoint: true},
|
|
2933
|
+
endpoint: () => {
|
|
2934
|
+
return {'relay': 1, 'usb': 2};
|
|
2935
|
+
},
|
|
2936
|
+
exposes: [
|
|
2937
|
+
e.switch().withEndpoint('relay'), e.switch().withEndpoint('usb'),
|
|
2938
|
+
e.power().withAccess(ea.STATE), e.energy(), e.device_temperature().withAccess(ea.STATE), e.voltage(),
|
|
2939
|
+
e.current(), e.power_outage_memory(), e.led_disabled_night(), e.button_lock(),
|
|
2940
|
+
exposes.enum('button_switch_mode', exposes.access.ALL, ['relay', 'relay_and_usb'])
|
|
2941
|
+
.withDescription('Control both relay and usb or only the relay with the physical switch button'),
|
|
2942
|
+
e.overload_protection(100, 2500)],
|
|
2943
|
+
ota: ota.zigbeeOTA,
|
|
2944
|
+
},
|
|
2945
|
+
{
|
|
2946
|
+
zigbeeModel: ['lumi.magnet.agl02'],
|
|
2947
|
+
model: 'MCCGQ12LM',
|
|
2948
|
+
vendor: 'Xiaomi',
|
|
2949
|
+
description: 'Aqara T1 door & window contact sensor',
|
|
2950
|
+
fromZigbee: [fz.xiaomi_contact, fz.aqara_opple],
|
|
2951
|
+
toZigbee: [],
|
|
2952
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
2953
|
+
exposes: [e.contact(), e.battery(), e.battery_voltage()],
|
|
2954
|
+
ota: ota.zigbeeOTA,
|
|
2955
|
+
},
|
|
2956
|
+
{
|
|
2957
|
+
zigbeeModel: ['lumi.plug.sacn02'],
|
|
2958
|
+
model: 'QBCZ14LM',
|
|
2959
|
+
vendor: 'Xiaomi',
|
|
2960
|
+
description: 'Aqara smart wall outlet T1',
|
|
2961
|
+
fromZigbee: [fz.on_off, fz.xiaomi_power, fz.aqara_opple],
|
|
2962
|
+
toZigbee: [tz.on_off, tz.xiaomi_switch_power_outage_memory, tz.xiaomi_led_disabled_night,
|
|
2963
|
+
tz.xiaomi_overload_protection, tz.xiaomi_socket_button_lock],
|
|
2964
|
+
exposes: [
|
|
2965
|
+
e.switch(), e.power().withAccess(ea.STATE), e.energy(),
|
|
2966
|
+
e.device_temperature().withAccess(ea.STATE), e.voltage(),
|
|
2967
|
+
e.current(), e.power_outage_memory(), e.led_disabled_night(), e.button_lock(),
|
|
2968
|
+
e.overload_protection(100, 2500)],
|
|
2969
|
+
ota: ota.zigbeeOTA,
|
|
2970
|
+
},
|
|
2971
|
+
{
|
|
2972
|
+
zigbeeModel: ['lumi.remote.rkba01'],
|
|
2973
|
+
model: 'ZNXNKG02LM',
|
|
2974
|
+
vendor: 'Xiaomi',
|
|
2975
|
+
description: 'Aqara knob H1 (wireless)',
|
|
2976
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
2977
|
+
exposes: [e.battery(), e.battery_voltage(),
|
|
2978
|
+
e.action(['single', 'double', 'hold', 'release', 'start_rotating', 'rotation', 'stop_rotating']),
|
|
2979
|
+
exposes.enum('operation_mode', ea.ALL, ['event', 'command']).withDescription('Button mode'),
|
|
2980
|
+
exposes.numeric('action_rotation_angle', ea.STATE).withUnit('*').withDescription('Rotation angle'),
|
|
2981
|
+
exposes.numeric('action_rotation_angle_speed', ea.STATE).withUnit('*').withDescription('Rotation angle speed'),
|
|
2982
|
+
exposes.numeric('action_rotation_percent', ea.STATE).withUnit('%').withDescription('Rotation percent'),
|
|
2983
|
+
exposes.numeric('action_rotation_percent_speed', ea.STATE).withUnit('%').withDescription('Rotation percent speed'),
|
|
2984
|
+
exposes.numeric('action_rotation_time', ea.STATE).withUnit('ms').withDescription('Rotation time'),
|
|
2985
|
+
],
|
|
2986
|
+
fromZigbee: [fz.xiaomi_on_off_action, fz.xiaomi_multistate_action, fz.xiaomi_basic, fz.aqara_opple, fz.aqara_knob_rotation],
|
|
2987
|
+
toZigbee: [tz.aqara_opple_operation_mode],
|
|
2988
|
+
onEvent: preventReset,
|
|
2989
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
2990
|
+
const endpoint1 = device.getEndpoint(1);
|
|
2991
|
+
await endpoint1.write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
|
|
2992
|
+
},
|
|
2993
|
+
},
|
|
2994
|
+
{
|
|
2995
|
+
zigbeeModel: ['lumi.remote.acn003'],
|
|
2996
|
+
model: 'WXKG16LM',
|
|
2997
|
+
vendor: 'Xiaomi',
|
|
2998
|
+
description: 'Aqara wireless remote switch E1 (single rocker)',
|
|
2999
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
3000
|
+
fromZigbee: [fz.xiaomi_multistate_action, fz.aqara_opple],
|
|
3001
|
+
toZigbee: [tz.xiaomi_switch_click_mode],
|
|
3002
|
+
exposes: [e.battery(), e.battery_voltage(), e.action(['single', 'double', 'hold']),
|
|
3003
|
+
exposes.enum('click_mode', ea.ALL, ['fast', 'multi'])
|
|
3004
|
+
.withDescription('Click mode, fast: only supports single click which will be send immediately after clicking.' +
|
|
3005
|
+
'multi: supports more events like double and hold')],
|
|
3006
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
3007
|
+
await device.getEndpoint(1).write('aqaraOpple', {0x0125: {value: 0x02, type: 0x20}}, {manufacturerCode: 0x115f});
|
|
3008
|
+
},
|
|
3009
|
+
},
|
|
3010
|
+
{
|
|
3011
|
+
zigbeeModel: ['lumi.remote.acn004'],
|
|
3012
|
+
model: 'WXKG17LM',
|
|
3013
|
+
vendor: 'Xiaomi',
|
|
3014
|
+
description: 'Aqara E1 double key wireless switch',
|
|
3015
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
3016
|
+
exposes: [e.battery(), e.battery_voltage(),
|
|
3017
|
+
e.action(['single_left', 'single_right', 'single_both', 'double_left', 'double_right', 'hold_left', 'hold_right']),
|
|
3018
|
+
// eslint-disable-next-line max-len
|
|
3019
|
+
exposes.enum('click_mode', ea.ALL, ['fast', 'multi']).withDescription('Click mode, fast: only supports single click which will be send immediately after clicking, multi: supports more events like double and hold'),
|
|
3020
|
+
],
|
|
3021
|
+
fromZigbee: [fz.xiaomi_multistate_action, fz.aqara_opple],
|
|
3022
|
+
toZigbee: [tz.xiaomi_switch_click_mode],
|
|
3023
|
+
onEvent: preventReset,
|
|
3024
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
3025
|
+
const endpoint1 = device.getEndpoint(1);
|
|
3026
|
+
// set multiclick mode
|
|
3027
|
+
await endpoint1.write('aqaraOpple', {0x0125: {value: 0x02, type: 0x20}}, {manufacturerCode: 0x115f});
|
|
3028
|
+
},
|
|
3029
|
+
},
|
|
3030
|
+
{
|
|
3031
|
+
zigbeeModel: ['lumi.remote.b18ac1'],
|
|
3032
|
+
model: 'WXKG14LM',
|
|
3033
|
+
vendor: 'Xiaomi',
|
|
3034
|
+
description: 'Aqara wireless remote switch H1 (single rocker)',
|
|
3035
|
+
fromZigbee: [fz.xiaomi_multistate_action, fz.aqara_opple, fz.command_toggle],
|
|
3036
|
+
toZigbee: [tz.xiaomi_switch_click_mode, tz.aqara_opple_operation_mode],
|
|
3037
|
+
exposes: [e.battery(), e.battery_voltage(), e.action(['single', 'double', 'triple', 'hold']),
|
|
3038
|
+
exposes.enum('click_mode', ea.ALL, ['fast', 'multi'])
|
|
3039
|
+
.withDescription('Click mode, fast: only supports single click which will be send immediately after clicking.' +
|
|
3040
|
+
'multi: supports more events like double and hold'),
|
|
3041
|
+
exposes.enum('operation_mode', ea.ALL, ['command', 'event'])
|
|
3042
|
+
.withDescription('Operation mode, select "command" to enable bindings (wake up the device before changing modes!)')],
|
|
3043
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
3044
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
3045
|
+
const endpoint1 = device.getEndpoint(1);
|
|
3046
|
+
await endpoint1.write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
|
|
3047
|
+
await endpoint1.read('aqaraOpple', [0x0125], {manufacturerCode: 0x115f});
|
|
3048
|
+
},
|
|
3049
|
+
},
|
|
3050
|
+
{
|
|
3051
|
+
zigbeeModel: ['lumi.airrtc.agl001'],
|
|
3052
|
+
model: 'SRTS-A01',
|
|
3053
|
+
vendor: 'Xiaomi',
|
|
3054
|
+
description: 'Aqara Smart Radiator Thermostat E1',
|
|
3055
|
+
fromZigbee: [fzLocal.aqara_trv, fz.thermostat, fz.battery],
|
|
3056
|
+
toZigbee: [tzLocal.aqara_trv, tz.thermostat_occupied_heating_setpoint],
|
|
3057
|
+
exposes: [
|
|
3058
|
+
exposes.binary('setup', ea.STATE, true, false)
|
|
3059
|
+
.withDescription('Indicates if the device is in setup mode (E11)'),
|
|
3060
|
+
exposes.climate()
|
|
3061
|
+
.withSetpoint('occupied_heating_setpoint', 5, 30, 0.5)
|
|
3062
|
+
.withLocalTemperature(ea.STATE, 'Current temperature measured by the internal or external sensor')
|
|
3063
|
+
.withSystemMode(['off', 'heat'], ea.ALL)
|
|
3064
|
+
.withPreset(['manual', 'away', 'auto']).setAccess('preset', ea.ALL),
|
|
3065
|
+
e.temperature_sensor_select(['internal', 'external']).withAccess(ea.ALL),
|
|
3066
|
+
exposes.binary('calibrated', ea.STATE, true, false)
|
|
3067
|
+
.withDescription('Is the valve calibrated'),
|
|
3068
|
+
e.child_lock().setAccess('state', ea.ALL),
|
|
3069
|
+
e.window_detection().setAccess('state', ea.ALL),
|
|
3070
|
+
exposes.binary('window_open', ea.STATE, true, false),
|
|
3071
|
+
e.valve_detection().setAccess('state', ea.ALL)
|
|
3072
|
+
.withDescription('Determines if temperature control abnormalities should be detected'),
|
|
3073
|
+
exposes.binary('valve_alarm', ea.STATE, true, false)
|
|
3074
|
+
.withDescription('Notifies of a temperature control abnormality if valve detection is enabled ' +
|
|
3075
|
+
'(e.g., thermostat not installed correctly, valve failure or incorrect calibration, ' +
|
|
3076
|
+
'incorrect link to external temperature sensor)'),
|
|
3077
|
+
e.away_preset_temperature().withAccess(ea.ALL),
|
|
3078
|
+
e.battery_voltage(),
|
|
3079
|
+
e.battery(),
|
|
3080
|
+
e.power_outage_count(),
|
|
3081
|
+
e.device_temperature(),
|
|
3082
|
+
exposes.switch().withState('schedule', true,
|
|
3083
|
+
'When being ON, the thermostat will change its state based on your settings',
|
|
3084
|
+
ea.ALL, 'ON', 'OFF'),
|
|
3085
|
+
exposes.text('schedule_settings', ea.ALL)
|
|
3086
|
+
.withDescription('Smart schedule configuration (default: mon,tue,wed,thu,fri|8:00,24.0|18:00,17.0|23:00,22.0|8:00,22.0)'),
|
|
3087
|
+
],
|
|
3088
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
3089
|
+
const endpoint = device.getEndpoint(1);
|
|
3090
|
+
|
|
3091
|
+
// Initialize battery percentage and voltage
|
|
3092
|
+
await endpoint.read('aqaraOpple', [0x040a], {manufacturerCode: 0x115f});
|
|
3093
|
+
await endpoint.read('genPowerCfg', ['batteryVoltage']);
|
|
3094
|
+
|
|
3095
|
+
// This cluster is not discovered automatically and needs to be explicitly attached to enable OTA
|
|
3096
|
+
utils.attachOutputCluster(device, 'genOta');
|
|
3097
|
+
},
|
|
3098
|
+
ota: ota.zigbeeOTA,
|
|
3099
|
+
},
|
|
3100
|
+
{
|
|
3101
|
+
zigbeeModel: ['aqara.feeder.acn001'],
|
|
3102
|
+
model: 'ZNCWWSQ01LM',
|
|
3103
|
+
vendor: 'Xiaomi',
|
|
3104
|
+
description: 'Aqara pet feeder C1',
|
|
3105
|
+
fromZigbee: [fzLocal.aqara_feeder],
|
|
3106
|
+
toZigbee: [tzLocal.aqara_feeder],
|
|
3107
|
+
exposes: [
|
|
3108
|
+
exposes.enum('feed', ea.STATE_SET, ['', 'START']).withDescription('Start feeding'),
|
|
3109
|
+
exposes.enum('feeding_source', ea.STATE, ['schedule', 'manual', 'remote']).withDescription('Feeding source'),
|
|
3110
|
+
exposes.numeric('feeding_size', ea.STATE).withDescription('Feeding size').withUnit('portion'),
|
|
3111
|
+
exposes.numeric('portions_per_day', ea.STATE).withDescription('Portions per day'),
|
|
3112
|
+
exposes.numeric('weight_per_day', ea.STATE).withDescription('Weight per day').withUnit('g'),
|
|
3113
|
+
exposes.binary('error', ea.STATE, true, false)
|
|
3114
|
+
.withDescription('Indicates wether there is an error with the feeder'),
|
|
3115
|
+
exposes.list('schedule', ea.STATE_SET, exposes.composite('dayTime', 'dayTime', exposes.access.STATE_SET)
|
|
3116
|
+
.withFeature(exposes.enum('days', exposes.access.STATE_SET, [
|
|
3117
|
+
'everyday', 'workdays', 'weekend', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun',
|
|
3118
|
+
'mon-wed-fri-sun', 'tue-thu-sat']))
|
|
3119
|
+
.withFeature(exposes.numeric('hour', exposes.access.STATE_SET))
|
|
3120
|
+
.withFeature(exposes.numeric('minute', exposes.access.STATE_SET))
|
|
3121
|
+
.withFeature(exposes.numeric('size', exposes.access.STATE_SET)),
|
|
3122
|
+
).withDescription('Feeding schedule'),
|
|
3123
|
+
exposes.switch().withState('led_indicator', true, 'Led indicator', ea.STATE_SET, 'ON', 'OFF'),
|
|
3124
|
+
e.child_lock(),
|
|
3125
|
+
exposes.enum('mode', ea.STATE_SET, ['schedule', 'manual']).withDescription('Feeding mode'),
|
|
3126
|
+
exposes.numeric('serving_size', ea.STATE_SET).withValueMin(1).withValueMax(10).withDescription('One serving size')
|
|
3127
|
+
.withUnit('portion'),
|
|
3128
|
+
exposes.numeric('portion_weight', ea.STATE_SET).withValueMin(1).withValueMax(20).withDescription('Portion weight')
|
|
3129
|
+
.withUnit('g'),
|
|
3130
|
+
],
|
|
3131
|
+
ota: ota.zigbeeOTA,
|
|
3132
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
3133
|
+
const endpoint = device.getEndpoint(1);
|
|
3134
|
+
await endpoint.read('aqaraOpple', [0xfff1], {manufacturerCode: 0x115f});
|
|
3135
|
+
device.powerSource = 'Mains (single phase)';
|
|
3136
|
+
device.save();
|
|
3137
|
+
},
|
|
3138
|
+
},
|
|
3139
|
+
{
|
|
3140
|
+
zigbeeModel: ['lumi.remote.acn007'],
|
|
3141
|
+
model: 'WXKG20LM',
|
|
3142
|
+
vendor: 'Xiaomi',
|
|
3143
|
+
description: 'Aqara E1 wireless mini switch',
|
|
3144
|
+
fromZigbee: [fz.battery, fz.aqara_opple_multistate, fz.aqara_opple],
|
|
3145
|
+
toZigbee: [],
|
|
3146
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
3147
|
+
exposes: [e.battery(), e.battery_voltage(), e.action(['single', 'double', 'hold', 'release']),
|
|
3148
|
+
e.device_temperature(), e.power_outage_count()],
|
|
3149
|
+
},
|
|
3150
|
+
{
|
|
3151
|
+
zigbeeModel: ['lumi.remote.cagl02'],
|
|
3152
|
+
model: 'CTP-R01',
|
|
3153
|
+
vendor: 'Xiaomi',
|
|
3154
|
+
whiteLabel: [{vendor: 'Xiaomi', model: 'MFCZQ12LM'}],
|
|
3155
|
+
description: 'Aqara magic cube T1 Pro',
|
|
3156
|
+
meta: {battery: {voltageToPercentage: '3V_2850_3000'}},
|
|
3157
|
+
ota: ota.zigbeeOTA,
|
|
3158
|
+
fromZigbee: [fz.aqara_opple, fzLocal.CTPR01_action_multistate, fzLocal.CTPR01_action_analog, fz.ignore_onoff_report],
|
|
3159
|
+
toZigbee: [tzLocal.CTPR01_operation_mode],
|
|
3160
|
+
exposes: [
|
|
3161
|
+
e.battery(),
|
|
3162
|
+
e.battery_voltage(),
|
|
3163
|
+
e.power_outage_count(false),
|
|
3164
|
+
exposes
|
|
3165
|
+
.enum('operation_mode', ea.SET, ['action_mode', 'scene_mode'])
|
|
3166
|
+
.withDescription('[Soft Switch]: There is a configuration window, opens once an hour on itself, ' +
|
|
3167
|
+
'only during which the cube will respond to mode switch. ' +
|
|
3168
|
+
'Mode switch will be scheduled to take effect when the window becomes available. ' +
|
|
3169
|
+
'You can also give it a throw action (no backward motion) to force a respond! ' +
|
|
3170
|
+
'Otherwise, you may open lid and click LINK once to make the cube respond immediately. ' +
|
|
3171
|
+
'[Hard Switch]: Open lid and click LINK button 5 times.'),
|
|
3172
|
+
e.cube_side('side'),
|
|
3173
|
+
e.action([
|
|
3174
|
+
'shake', 'throw', 'tap', 'slide', 'flip180', 'flip90', 'hold', 'side_up',
|
|
3175
|
+
'rotate_left', 'rotate_right', '1_min_inactivity', 'flip_to_side',
|
|
3176
|
+
]).withDescription('Triggered action'),
|
|
3177
|
+
e.cube_side('action_from_side'),
|
|
3178
|
+
e.angle('action_angle'),
|
|
3179
|
+
],
|
|
3180
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
3181
|
+
device.softwareBuildID = `0.0.0_00${device.applicationVersion}`;
|
|
3182
|
+
device.save();
|
|
3183
|
+
|
|
3184
|
+
const endpoint = device.getEndpoint(1);
|
|
3185
|
+
await endpoint.write('aqaraOpple', {mode: 1}, {manufacturerCode: 0x115f, disableDefaultResponse: true, disableResponse: true});
|
|
3186
|
+
await endpoint.read('aqaraOpple', [0x148], {manufacturerCode: 0x115f, disableDefaultResponse: true, disableResponse: true});
|
|
3187
|
+
},
|
|
3188
|
+
},
|
|
3189
|
+
{
|
|
3190
|
+
zigbeeModel: ['lumi.switch.acn040'],
|
|
3191
|
+
model: 'ZNQBKG31LM',
|
|
3192
|
+
vendor: 'Xiaomi',
|
|
3193
|
+
description: 'Aqara E1 3 gang switch (with neutral)',
|
|
3194
|
+
fromZigbee: [fz.on_off, fz.xiaomi_multistate_action, fz.aqara_opple],
|
|
3195
|
+
toZigbee: [tz.on_off, tz.xiaomi_switch_operation_mode_opple, tz.xiaomi_switch_power_outage_memory, tz.aqara_switch_mode_switch,
|
|
3196
|
+
tz.xiaomi_flip_indicator_light],
|
|
3197
|
+
endpoint: (device) => {
|
|
3198
|
+
return {'left': 1, 'center': 2, 'right': 3};
|
|
3199
|
+
},
|
|
3200
|
+
meta: {multiEndpoint: true},
|
|
3201
|
+
exposes: [
|
|
3202
|
+
e.switch().withEndpoint('left'), e.switch().withEndpoint('center'), e.switch().withEndpoint('right'),
|
|
3203
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
3204
|
+
.withDescription('Decoupled mode for left button')
|
|
3205
|
+
.withEndpoint('left'),
|
|
3206
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
3207
|
+
.withDescription('Decoupled mode for center button')
|
|
3208
|
+
.withEndpoint('center'),
|
|
3209
|
+
exposes.enum('operation_mode', ea.ALL, ['control_relay', 'decoupled'])
|
|
3210
|
+
.withDescription('Decoupled mode for right button')
|
|
3211
|
+
.withEndpoint('right'),
|
|
3212
|
+
e.action(['single_left', 'double_left', 'single_center', 'double_center', 'single_right', 'double_right',
|
|
3213
|
+
'single_left_center', 'double_left_center', 'single_left_right', 'double_left_right',
|
|
3214
|
+
'single_center_right', 'double_center_right', 'single_all', 'double_all']),
|
|
3215
|
+
e.power_outage_memory(), e.device_temperature(), e.flip_indicator_light(),
|
|
3216
|
+
],
|
|
3217
|
+
onEvent: preventReset,
|
|
3218
|
+
configure: async (device, coordinatorEndpoint, logger) => {
|
|
3219
|
+
await device.getEndpoint(1).write('aqaraOpple', {'mode': 1}, {manufacturerCode: 0x115f, disableResponse: true});
|
|
3220
|
+
},
|
|
3221
|
+
ota: ota.zigbeeOTA,
|
|
3222
|
+
},
|
|
3223
|
+
];
|