@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.
Files changed (312) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +7 -0
  3. package/converters/fromZigbee.js +8439 -0
  4. package/converters/toZigbee.js +7162 -0
  5. package/devices/ITCommander.js +37 -0
  6. package/devices/RMC002.js +20 -0
  7. package/devices/acova.js +101 -0
  8. package/devices/acuity_brands_lighting.js +11 -0
  9. package/devices/adeo.js +256 -0
  10. package/devices/adurosmart.js +130 -0
  11. package/devices/aeotec.js +13 -0
  12. package/devices/airam.js +59 -0
  13. package/devices/ajax_online.js +49 -0
  14. package/devices/akuvox.js +28 -0
  15. package/devices/alchemy.js +18 -0
  16. package/devices/aldi.js +53 -0
  17. package/devices/alecto.js +98 -0
  18. package/devices/anchor.js +17 -0
  19. package/devices/atlantic.js +110 -0
  20. package/devices/atsmart.js +28 -0
  21. package/devices/aubess.js +21 -0
  22. package/devices/aurora_lighting.js +292 -0
  23. package/devices/automaton.js +44 -0
  24. package/devices/awox.js +184 -0
  25. package/devices/axis.js +22 -0
  26. package/devices/bankamp.js +11 -0
  27. package/devices/bega.js +22 -0
  28. package/devices/belkin.js +11 -0
  29. package/devices/bitron.js +334 -0
  30. package/devices/blaupunkt.js +27 -0
  31. package/devices/blitzwolf.js +47 -0
  32. package/devices/bosch.js +702 -0
  33. package/devices/brimate.js +15 -0
  34. package/devices/bseed.js +17 -0
  35. package/devices/bticino.js +118 -0
  36. package/devices/busch-jaeger.js +140 -0
  37. package/devices/byun.js +24 -0
  38. package/devices/calex.js +37 -0
  39. package/devices/candeo.js +49 -0
  40. package/devices/casaia.js +52 -0
  41. package/devices/centralite.js +359 -0
  42. package/devices/cleode.js +20 -0
  43. package/devices/cleverio.js +36 -0
  44. package/devices/climax.js +138 -0
  45. package/devices/commercial_electric.js +16 -0
  46. package/devices/connecte.js +46 -0
  47. package/devices/cree.js +11 -0
  48. package/devices/ctm.js +999 -0
  49. package/devices/current_products_corp.js +24 -0
  50. package/devices/custom_devices_diy.js +850 -0
  51. package/devices/cy-lighting.js +11 -0
  52. package/devices/danalock.js +26 -0
  53. package/devices/danfoss.js +340 -0
  54. package/devices/databyte.ch.js +55 -0
  55. package/devices/datek.js +246 -0
  56. package/devices/dawon_dns.js +338 -0
  57. package/devices/develco.js +868 -0
  58. package/devices/digi.js +14 -0
  59. package/devices/diyruz.js +305 -0
  60. package/devices/dlink.js +37 -0
  61. package/devices/dnake.js +11 -0
  62. package/devices/dresden_elektronik.js +47 -0
  63. package/devices/easyaccess.js +27 -0
  64. package/devices/eatonhalo_led.js +11 -0
  65. package/devices/echostar.js +25 -0
  66. package/devices/ecodim.js +145 -0
  67. package/devices/ecolink.js +21 -0
  68. package/devices/ecosmart.js +64 -0
  69. package/devices/ecozy.js +31 -0
  70. package/devices/edp.js +39 -0
  71. package/devices/eglo.js +25 -0
  72. package/devices/elko.js +176 -0
  73. package/devices/enbrighten.js +163 -0
  74. package/devices/enocean.js +52 -0
  75. package/devices/envilar.js +73 -0
  76. package/devices/essentialb.js +87 -0
  77. package/devices/eurotronic.js +48 -0
  78. package/devices/evanell.js +29 -0
  79. package/devices/evn.js +31 -0
  80. package/devices/evology.js +24 -0
  81. package/devices/evvr.js +17 -0
  82. package/devices/ewelink.js +184 -0
  83. package/devices/ezex.js +24 -0
  84. package/devices/fantem.js +77 -0
  85. package/devices/feibit.js +172 -0
  86. package/devices/fireangel.js +15 -0
  87. package/devices/frankever.js +23 -0
  88. package/devices/garza.js +11 -0
  89. package/devices/ge.js +111 -0
  90. package/devices/gewiss.js +48 -0
  91. package/devices/gidealed.js +11 -0
  92. package/devices/giderwel.js +11 -0
  93. package/devices/giex.js +222 -0
  94. package/devices/girier.js +19 -0
  95. package/devices/gledopto.js +756 -0
  96. package/devices/gmy.js +11 -0
  97. package/devices/gs.js +29 -0
  98. package/devices/halemeier.js +18 -0
  99. package/devices/hampton_bay.js +37 -0
  100. package/devices/heiman.js +805 -0
  101. package/devices/hej.js +107 -0
  102. package/devices/hfh.js +11 -0
  103. package/devices/hgkg.js +54 -0
  104. package/devices/hilux.js +11 -0
  105. package/devices/hive.js +524 -0
  106. package/devices/home_control_as.js +27 -0
  107. package/devices/hommyn.js +24 -0
  108. package/devices/honyar.js +29 -0
  109. package/devices/hornbach.js +53 -0
  110. package/devices/hzc.js +21 -0
  111. package/devices/hzc_electric.js +42 -0
  112. package/devices/icasa.js +121 -0
  113. package/devices/idinio.js +19 -0
  114. package/devices/ihorn.js +61 -0
  115. package/devices/ikea.js +1168 -0
  116. package/devices/ilightsin.js +11 -0
  117. package/devices/iluminize.js +262 -0
  118. package/devices/ilux.js +11 -0
  119. package/devices/immax.js +203 -0
  120. package/devices/innr.js +705 -0
  121. package/devices/inovelli.js +1315 -0
  122. package/devices/insta.js +110 -0
  123. package/devices/iolloi.js +20 -0
  124. package/devices/iotperfect.js +20 -0
  125. package/devices/iris.js +180 -0
  126. package/devices/istar.js +20 -0
  127. package/devices/jasco.js +55 -0
  128. package/devices/javis.js +37 -0
  129. package/devices/jethome.js +48 -0
  130. package/devices/jiawen.js +18 -0
  131. package/devices/jumitech.js +18 -0
  132. package/devices/jxuan.js +49 -0
  133. package/devices/kami.js +15 -0
  134. package/devices/keen_home.js +80 -0
  135. package/devices/klikaanklikuit.js +17 -0
  136. package/devices/kmpcil.js +148 -0
  137. package/devices/konke.js +141 -0
  138. package/devices/ksentry.js +17 -0
  139. package/devices/kurvia.js +17 -0
  140. package/devices/kwikset.js +120 -0
  141. package/devices/lanesto.js +11 -0
  142. package/devices/lds.js +11 -0
  143. package/devices/led_trading.js +69 -0
  144. package/devices/ledvance.js +353 -0
  145. package/devices/leedarson.js +130 -0
  146. package/devices/legrand.js +554 -0
  147. package/devices/lellki.js +146 -0
  148. package/devices/letsled.js +11 -0
  149. package/devices/letv.js +18 -0
  150. package/devices/leviton.js +142 -0
  151. package/devices/lg.js +18 -0
  152. package/devices/lidl.js +1000 -0
  153. package/devices/lifecontrol.js +92 -0
  154. package/devices/lightsolutions.js +37 -0
  155. package/devices/linkind.js +205 -0
  156. package/devices/livingwise.js +59 -0
  157. package/devices/livolo.js +286 -0
  158. package/devices/lixee.js +779 -0
  159. package/devices/lonsonho.js +218 -0
  160. package/devices/lubeez.js +18 -0
  161. package/devices/lupus.js +74 -0
  162. package/devices/lutron.js +32 -0
  163. package/devices/lux.js +40 -0
  164. package/devices/m-elec.js +18 -0
  165. package/devices/makegood.js +51 -0
  166. package/devices/matcall_bv.js +18 -0
  167. package/devices/meazon.js +47 -0
  168. package/devices/mercator.js +225 -0
  169. package/devices/miboxer.js +72 -0
  170. package/devices/micromatic.js +29 -0
  171. package/devices/moes.js +400 -0
  172. package/devices/mycket.js +11 -0
  173. package/devices/m/303/274ller_licht.js +220 -0
  174. package/devices/namron.js +774 -0
  175. package/devices/nanoleaf.js +11 -0
  176. package/devices/neo.js +86 -0
  177. package/devices/net2grid.js +29 -0
  178. package/devices/netvox.js +35 -0
  179. package/devices/niko.js +314 -0
  180. package/devices/ninja_blocks.js +24 -0
  181. package/devices/niviss.js +11 -0
  182. package/devices/nodon.js +109 -0
  183. package/devices/nordtronic.js +30 -0
  184. package/devices/nous.js +88 -0
  185. package/devices/novo.js +17 -0
  186. package/devices/nue_3a.js +417 -0
  187. package/devices/nyce.js +67 -0
  188. package/devices/onesti.js +59 -0
  189. package/devices/openlumi.js +22 -0
  190. package/devices/orvibo.js +515 -0
  191. package/devices/osram.js +519 -0
  192. package/devices/oujiabao.js +15 -0
  193. package/devices/owon.js +352 -0
  194. package/devices/ozsmartthings.js +11 -0
  195. package/devices/paul_neuhaus.js +96 -0
  196. package/devices/paulmann.js +158 -0
  197. package/devices/peq.js +24 -0
  198. package/devices/perenio.js +413 -0
  199. package/devices/philips.js +3118 -0
  200. package/devices/plaid.js +25 -0
  201. package/devices/plugwise.js +173 -0
  202. package/devices/popp.js +10 -0
  203. package/devices/profalux.js +47 -0
  204. package/devices/prolight.js +54 -0
  205. package/devices/qmotion.js +33 -0
  206. package/devices/qoto.js +113 -0
  207. package/devices/quotra.js +18 -0
  208. package/devices/rademacher.js +18 -0
  209. package/devices/rgb_genie.js +119 -0
  210. package/devices/robb.js +335 -0
  211. package/devices/roome.js +15 -0
  212. package/devices/rtx.js +90 -0
  213. package/devices/salus_controls.js +137 -0
  214. package/devices/samotech.js +93 -0
  215. package/devices/saswell.js +58 -0
  216. package/devices/scanproducts.js +32 -0
  217. package/devices/schlage.js +24 -0
  218. package/devices/schneider_electric.js +1039 -0
  219. package/devices/schwaiger.js +62 -0
  220. package/devices/seastar_intelligence.js +16 -0
  221. package/devices/securifi.js +39 -0
  222. package/devices/sengled.js +332 -0
  223. package/devices/sercomm.js +140 -0
  224. package/devices/shenzhen_homa.js +53 -0
  225. package/devices/shinasystem.js +686 -0
  226. package/devices/siglis.js +440 -0
  227. package/devices/sinope.js +1257 -0
  228. package/devices/siterwell.js +46 -0
  229. package/devices/skydance.js +112 -0
  230. package/devices/slv.js +27 -0
  231. package/devices/smart9.js +27 -0
  232. package/devices/smart_home_pty.js +18 -0
  233. package/devices/smartenit.js +42 -0
  234. package/devices/smartthings.js +495 -0
  235. package/devices/smartwings.js +24 -0
  236. package/devices/sohan_electric.js +13 -0
  237. package/devices/solaredge.js +11 -0
  238. package/devices/somgoms.js +47 -0
  239. package/devices/sonoff.js +262 -0
  240. package/devices/spotmau.js +36 -0
  241. package/devices/sprut.js +317 -0
  242. package/devices/stelpro.js +216 -0
  243. package/devices/sunricher.js +625 -0
  244. package/devices/swann.js +33 -0
  245. package/devices/sylvania.js +200 -0
  246. package/devices/tci.js +25 -0
  247. package/devices/technicolor.js +47 -0
  248. package/devices/terncy.js +64 -0
  249. package/devices/the_light_group.js +70 -0
  250. package/devices/third_reality.js +195 -0
  251. package/devices/titan_products.js +22 -0
  252. package/devices/tplink.js +42 -0
  253. package/devices/trust.js +114 -0
  254. package/devices/tubeszb.js +20 -0
  255. package/devices/tuya.js +4215 -0
  256. package/devices/ubisys.js +938 -0
  257. package/devices/uhome.js +25 -0
  258. package/devices/universal_electronics_inc.js +119 -0
  259. package/devices/urlighting.js +12 -0
  260. package/devices/useelink.js +52 -0
  261. package/devices/vbled.js +18 -0
  262. package/devices/vesternet.js +188 -0
  263. package/devices/viessmann.js +51 -0
  264. package/devices/villeroy_boch.js +18 -0
  265. package/devices/vimar.js +78 -0
  266. package/devices/visonic.js +80 -0
  267. package/devices/vrey.js +18 -0
  268. package/devices/wally.js +25 -0
  269. package/devices/waxman.js +45 -0
  270. package/devices/weiser.js +67 -0
  271. package/devices/weten.js +13 -0
  272. package/devices/wisdom.js +11 -0
  273. package/devices/woox.js +177 -0
  274. package/devices/wyze.js +23 -0
  275. package/devices/xiaomi.js +3223 -0
  276. package/devices/xinghuoyuan.js +11 -0
  277. package/devices/yale.js +227 -0
  278. package/devices/ynoa.js +68 -0
  279. package/devices/yookee.js +23 -0
  280. package/devices/ysrsai.js +26 -0
  281. package/devices/zemismart.js +254 -0
  282. package/devices/zen.js +34 -0
  283. package/devices/zipato.js +11 -0
  284. package/index.js +242 -0
  285. package/lib/color.js +784 -0
  286. package/lib/configureKey.js +944 -0
  287. package/lib/constants.js +316 -0
  288. package/lib/exposes.js +677 -0
  289. package/lib/extend.js +180 -0
  290. package/lib/kelvinToXy.js +1912 -0
  291. package/lib/legacy.js +2223 -0
  292. package/lib/light.js +111 -0
  293. package/lib/ota/OTA_URLs.md +119 -0
  294. package/lib/ota/common.js +476 -0
  295. package/lib/ota/index.js +10 -0
  296. package/lib/ota/inovelli.js +72 -0
  297. package/lib/ota/ledvance.js +52 -0
  298. package/lib/ota/lixee.js +57 -0
  299. package/lib/ota/salus.js +82 -0
  300. package/lib/ota/securifi.js +25 -0
  301. package/lib/ota/tradfri.js +45 -0
  302. package/lib/ota/ubisys.js +61 -0
  303. package/lib/ota/zigbeeOTA.js +161 -0
  304. package/lib/philips.js +667 -0
  305. package/lib/reporting.js +234 -0
  306. package/lib/store.js +57 -0
  307. package/lib/tuya.js +2027 -0
  308. package/lib/utils.js +527 -0
  309. package/lib/xiaomi.d.ts +11 -0
  310. package/lib/xiaomi.js +1288 -0
  311. package/lib/zosung.js +243 -0
  312. package/package.json +39 -0
@@ -0,0 +1,4215 @@
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 tuya = require('../lib/tuya');
6
+ const reporting = require('../lib/reporting');
7
+ const extend = require('../lib/extend');
8
+ const e = exposes.presets;
9
+ const ea = exposes.access;
10
+ const libColor = require('../lib/color');
11
+ const utils = require('../lib/utils');
12
+ const zosung = require('../lib/zosung');
13
+ const fzZosung = zosung.fzZosung;
14
+ const tzZosung = zosung.tzZosung;
15
+ const ez = zosung.presetsZosung;
16
+ const globalStore = require('../lib/store');
17
+
18
+ const tzLocal = {
19
+ TS110E_options: {
20
+ key: ['min_brightness', 'max_brightness', 'light_type', 'switch_type'],
21
+ convertSet: async (entity, key, value, meta) => {
22
+ let payload = null;
23
+ if (key === 'min_brightness' || key == 'max_brightness') {
24
+ const id = key === 'min_brightness' ? 64515 : 64516;
25
+ payload = {[id]: {value: utils.mapNumberRange(value, 1, 255, 0, 1000), type: 0x21}};
26
+ } else if (key === 'light_type' || key === 'switch_type') {
27
+ const lookup = key === 'light_type' ? {led: 0, incandescent: 1, halogen: 2} : {momentary: 0, toggle: 1, state: 2};
28
+ payload = {64514: {value: lookup[value], type: 0x20}};
29
+ }
30
+ await entity.write('genLevelCtrl', payload, utils.getOptions(meta.mapped, entity));
31
+ return {state: {[key]: value}};
32
+ },
33
+ convertGet: async (entity, key, meta) => {
34
+ let id = null;
35
+ if (key === 'min_brightness') id = 64515;
36
+ if (key === 'max_brightness') id = 64516;
37
+ if (key === 'light_type' || key === 'switch_type') id = 64514;
38
+ await entity.read('genLevelCtrl', [id]);
39
+ },
40
+ },
41
+ TS110E_onoff_brightness: {
42
+ key: ['state', 'brightness'],
43
+ options: [],
44
+ convertSet: async (entity, key, value, meta) => {
45
+ const {message, state} = meta;
46
+ if (message.state === 'OFF' || (message.hasOwnProperty('state') && !message.hasOwnProperty('brightness'))) {
47
+ return await tz.on_off.convertSet(entity, key, value, meta);
48
+ } else if (message.hasOwnProperty('brightness')) {
49
+ // set brightness
50
+ if (state.state === 'OFF') {
51
+ await entity.command('genOnOff', 'on', {}, utils.getOptions(meta.mapped, entity));
52
+ }
53
+
54
+ const level = utils.mapNumberRange(message.brightness, 0, 254, 0, 1000);
55
+ await entity.command('genLevelCtrl', 'moveToLevelTuya', {level, transtime: 100}, utils.getOptions(meta.mapped, entity));
56
+ return {state: {state: 'ON', brightness: message.brightness}};
57
+ }
58
+ },
59
+ convertGet: async (entity, key, meta) => {
60
+ if (key === 'state') await tz.on_off.convertGet(entity, key, meta);
61
+ if (key === 'brightness') await entity.read('genLevelCtrl', [61440]);
62
+ },
63
+ },
64
+ TS110E_light_onoff_brightness: {
65
+ ...tz.light_onoff_brightness,
66
+ convertSet: async (entity, key, value, meta) => {
67
+ const {message} = meta;
68
+ if (message.state === 'ON' || message.brightness > 1) {
69
+ // Does not turn off with physical press when turned on with just moveToLevelWithOnOff, required on before.
70
+ // https://github.com/Koenkk/zigbee2mqtt/issues/15902#issuecomment-1382848150
71
+ await entity.command('genOnOff', 'on', {}, utils.getOptions(meta.mapped, entity));
72
+ }
73
+ return tz.light_onoff_brightness.convertSet(entity, key, value, meta);
74
+ },
75
+ },
76
+ SA12IZL_silence_siren: {
77
+ key: ['silence_siren'],
78
+ convertSet: async (entity, key, value, meta) => {
79
+ await tuya.sendDataPointBool(entity, 16, value);
80
+ },
81
+ },
82
+ SA12IZL_alarm: {
83
+ key: ['alarm'],
84
+ convertSet: async (entity, key, value, meta) => {
85
+ await tuya.sendDataPointEnum(entity, 20, {true: 0, false: 1}[value]);
86
+ },
87
+ },
88
+ hpsz: {
89
+ key: ['led_state'],
90
+ convertSet: async (entity, key, value, meta) => {
91
+ await tuya.sendDataPointBool(entity, tuya.dataPoints.HPSZLEDState, value);
92
+ },
93
+ },
94
+ TS0504B_color: {
95
+ key: ['color'],
96
+ convertSet: async (entity, key, value, meta) => {
97
+ const color = libColor.Color.fromConverterArg(value);
98
+ console.log(color);
99
+ const enableWhite =
100
+ (color.isRGB() && (color.rgb.red === 1 && color.rgb.green === 1 && color.rgb.blue === 1)) ||
101
+ // Zigbee2MQTT frontend white value
102
+ (color.isXY() && (color.xy.x === 0.3125 || color.xy.y === 0.32894736842105265)) ||
103
+ // Home Assistant white color picker value
104
+ (color.isXY() && (color.xy.x === 0.323 || color.xy.y === 0.329));
105
+
106
+ if (enableWhite) {
107
+ await entity.command('lightingColorCtrl', 'tuyaRgbMode', {enable: false});
108
+ const newState = {color_mode: 'xy'};
109
+ if (color.isXY()) {
110
+ newState.color = color.xy;
111
+ } else {
112
+ newState.color = color.rgb.gammaCorrected().toXY().rounded(4);
113
+ }
114
+ return {state: libColor.syncColorState(newState, meta.state, entity, meta.options, meta.logger)};
115
+ } else {
116
+ return await tz.light_color.convertSet(entity, key, value, meta);
117
+ }
118
+ },
119
+ },
120
+ TS0224: {
121
+ key: ['light', 'duration', 'volume'],
122
+ convertSet: async (entity, key, value, meta) => {
123
+ if (key === 'light') {
124
+ await entity.command('genOnOff', value.toLowerCase() === 'on' ? 'on' : 'off', {}, utils.getOptions(meta.mapped, entity));
125
+ } else if (key === 'duration') {
126
+ await entity.write('ssIasWd', {'maxDuration': value}, utils.getOptions(meta.mapped, entity));
127
+ } else if (key === 'volume') {
128
+ const lookup = {'mute': 0, 'low': 10, 'medium': 30, 'high': 50};
129
+ value = value.toLowerCase();
130
+ utils.validateValue(value, Object.keys(lookup));
131
+ await entity.write('ssIasWd', {0x0002: {value: lookup[value], type: 0x0a}}, utils.getOptions(meta.mapped, entity));
132
+ }
133
+ return {state: {[key]: value}};
134
+ },
135
+ },
136
+ zb_sm_cover: {
137
+ key: ['state', 'position', 'reverse_direction', 'top_limit', 'bottom_limit', 'favorite_position', 'goto_positon', 'report'],
138
+ convertSet: async (entity, key, value, meta) => {
139
+ switch (key) {
140
+ case 'position': {
141
+ const invert = (meta.state) ? !meta.state.invert_cover : false;
142
+ value = invert ? 100 - value : value;
143
+ if (value >= 0 && value <= 100) {
144
+ await tuya.sendDataPointValue(entity, tuya.dataPoints.coverPosition, value);
145
+ } else {
146
+ throw new Error('TuYa_cover_control: Curtain motor position is out of range');
147
+ }
148
+ break;
149
+ }
150
+ case 'state': {
151
+ const stateEnums = tuya.getCoverStateEnums(meta.device.manufacturerName);
152
+ meta.logger.debug(`TuYa_cover_control: Using state enums for ${meta.device.manufacturerName}:
153
+ ${JSON.stringify(stateEnums)}`);
154
+
155
+ value = value.toLowerCase();
156
+ switch (value) {
157
+ case 'close':
158
+ await tuya.sendDataPointEnum(entity, tuya.dataPoints.state, stateEnums.close);
159
+ break;
160
+ case 'open':
161
+ await tuya.sendDataPointEnum(entity, tuya.dataPoints.state, stateEnums.open);
162
+ break;
163
+ case 'stop':
164
+ await tuya.sendDataPointEnum(entity, tuya.dataPoints.state, stateEnums.stop);
165
+ break;
166
+ default:
167
+ throw new Error('TuYa_cover_control: Invalid command received');
168
+ }
169
+ break;
170
+ }
171
+ case 'reverse_direction': {
172
+ meta.logger.info(`Motor direction ${(value) ? 'reverse' : 'forward'}`);
173
+ await tuya.sendDataPointEnum(entity, tuya.dataPoints.motorDirection, (value) ? 1 : 0);
174
+ break;
175
+ }
176
+ case 'top_limit': {
177
+ await tuya.sendDataPointEnum(entity, 104, {'SET': 0, 'CLEAR': 1}[value]);
178
+ break;
179
+ }
180
+ case 'bottom_limit': {
181
+ await tuya.sendDataPointEnum(entity, 103, {'SET': 0, 'CLEAR': 1}[value]);
182
+ break;
183
+ }
184
+ case 'favorite_position': {
185
+ await tuya.sendDataPointValue(entity, 115, value);
186
+ break;
187
+ }
188
+ case 'goto_positon': {
189
+ if (value == 'FAVORITE') {
190
+ value = (meta.state) ? meta.state.favorite_position : null;
191
+ } else {
192
+ value = parseInt(value);
193
+ }
194
+ return tz.tuya_cover_control.convertSet(entity, 'position', value, meta);
195
+ }
196
+ case 'report': {
197
+ await tuya.sendDataPointBool(entity, 116, 0);
198
+ break;
199
+ }
200
+ }
201
+ },
202
+ },
203
+ x5h_thermostat: {
204
+ key: ['system_mode', 'current_heating_setpoint', 'sensor', 'brightness_state', 'sound', 'frost_protection', 'week', 'factory_reset',
205
+ 'local_temperature_calibration', 'heating_temp_limit', 'deadzone_temperature', 'upper_temp', 'preset', 'child_lock',
206
+ 'schedule'],
207
+ convertSet: async (entity, key, value, meta) => {
208
+ switch (key) {
209
+ case 'system_mode':
210
+ await tuya.sendDataPointBool(entity, tuya.dataPoints.x5hState, value === 'heat');
211
+ break;
212
+ case 'preset': {
213
+ value = value.toLowerCase();
214
+ const lookup = {manual: 0, program: 1};
215
+ utils.validateValue(value, Object.keys(lookup));
216
+ value = lookup[value];
217
+ await tuya.sendDataPointEnum(entity, tuya.dataPoints.x5hMode, value);
218
+ break;
219
+ }
220
+ case 'upper_temp':
221
+ if (value >= 35 && value <= 95) {
222
+ await tuya.sendDataPointValue(entity, tuya.dataPoints.x5hSetTempCeiling, value);
223
+ const setpoint = globalStore.getValue(entity, 'currentHeatingSetpoint', 20);
224
+ const setpointRaw = Math.round(setpoint * 10);
225
+ await new Promise((r) => setTimeout(r, 500));
226
+ await tuya.sendDataPointValue(entity, tuya.dataPoints.x5hSetTemp, setpointRaw);
227
+ } else {
228
+ throw new Error('Supported values are in range [35, 95]');
229
+ }
230
+ break;
231
+ case 'deadzone_temperature':
232
+ if (value >= 0.5 && value <= 9.5) {
233
+ value = Math.round(value * 10);
234
+ await tuya.sendDataPointValue(entity, tuya.dataPoints.x5hTempDiff, value);
235
+ } else {
236
+ throw new Error('Supported values are in range [0.5, 9.5]');
237
+ }
238
+ break;
239
+ case 'heating_temp_limit':
240
+ if (value >= 5 && value <= 60) {
241
+ await tuya.sendDataPointValue(entity, tuya.dataPoints.x5hProtectionTempLimit, value);
242
+ } else {
243
+ throw new Error('Supported values are in range [5, 60]');
244
+ }
245
+ break;
246
+ case 'local_temperature_calibration':
247
+ if (value >= -9.9 && value <= 9.9) {
248
+ value = Math.round(value * 10);
249
+
250
+ if (value < 0) {
251
+ value = 0xFFFFFFFF + value + 1;
252
+ }
253
+
254
+ await tuya.sendDataPointValue(entity, tuya.dataPoints.x5hTempCorrection, value);
255
+ } else {
256
+ throw new Error('Supported values are in range [-9.9, 9.9]');
257
+ }
258
+ break;
259
+ case 'factory_reset':
260
+ await tuya.sendDataPointBool(entity, tuya.dataPoints.x5hFactoryReset, value === 'ON');
261
+ break;
262
+ case 'week':
263
+ await tuya.sendDataPointEnum(entity, tuya.dataPoints.x5hWorkingDaySetting,
264
+ utils.getKey(tuya.thermostatWeekFormat, value, value, Number));
265
+ break;
266
+ case 'frost_protection':
267
+ await tuya.sendDataPointBool(entity, tuya.dataPoints.x5hFrostProtection, value === 'ON');
268
+ break;
269
+ case 'sound':
270
+ await tuya.sendDataPointBool(entity, tuya.dataPoints.x5hSound, value === 'ON');
271
+ break;
272
+ case 'brightness_state': {
273
+ value = value.toLowerCase();
274
+ const lookup = {off: 0, low: 1, medium: 2, high: 3};
275
+ utils.validateValue(value, Object.keys(lookup));
276
+ value = lookup[value];
277
+ await tuya.sendDataPointEnum(entity, tuya.dataPoints.x5hBackplaneBrightness, value);
278
+ break;
279
+ }
280
+ case 'sensor': {
281
+ value = value.toLowerCase();
282
+ const lookup = {'internal': 0, 'external': 1, 'both': 2};
283
+ utils.validateValue(value, Object.keys(lookup));
284
+ value = lookup[value];
285
+ await tuya.sendDataPointEnum(entity, tuya.dataPoints.x5hSensorSelection, value);
286
+ break;
287
+ }
288
+ case 'current_heating_setpoint':
289
+ if (value >= 5 && value <= 60) {
290
+ value = Math.round(value * 10);
291
+ await tuya.sendDataPointValue(entity, tuya.dataPoints.x5hSetTemp, value);
292
+ } else {
293
+ throw new Error(`Unsupported value: ${value}`);
294
+ }
295
+ break;
296
+ case 'child_lock':
297
+ await tuya.sendDataPointBool(entity, tuya.dataPoints.x5hChildLock, value === 'LOCK');
298
+ break;
299
+ case 'schedule': {
300
+ const periods = value.split(' ');
301
+ const periodsNumber = 8;
302
+ const payload = [];
303
+
304
+ for (let i = 0; i < periodsNumber; i++) {
305
+ const timeTemp = periods[i].split('/');
306
+ const hm = timeTemp[0].split(':', 2);
307
+ const h = parseInt(hm[0]);
308
+ const m = parseInt(hm[1]);
309
+ const temp = parseFloat(timeTemp[1]);
310
+
311
+ if (h < 0 || h >= 24 || m < 0 || m >= 60 || temp < 5 || temp > 60) {
312
+ throw new Error('Invalid hour, minute or temperature of: ' + periods[i]);
313
+ }
314
+
315
+ const tempHexArray = tuya.convertDecimalValueTo2ByteHexArray(Math.round(temp * 10));
316
+ // 1 byte for hour, 1 byte for minutes, 2 bytes for temperature
317
+ payload.push(h, m, ...tempHexArray);
318
+ }
319
+
320
+ await tuya.sendDataPointRaw(entity, tuya.dataPoints.x5hWeeklyProcedure, payload);
321
+ break;
322
+ }
323
+ default:
324
+ break;
325
+ }
326
+ },
327
+ },
328
+ temperature_unit: {
329
+ key: ['temperature_unit'],
330
+ convertSet: async (entity, key, value, meta) => {
331
+ switch (key) {
332
+ case 'temperature_unit': {
333
+ await entity.write('manuSpecificTuya_2', {'57355': {value: {'celsius': 0, 'fahrenheit': 1}[value], type: 48}});
334
+ break;
335
+ }
336
+ default: // Unknown key
337
+ meta.logger.warn(`Unhandled key ${key}`);
338
+ }
339
+ },
340
+ },
341
+ };
342
+
343
+ const fzLocal = {
344
+ TS110E: {
345
+ cluster: 'genLevelCtrl',
346
+ type: ['attributeReport', 'readResponse'],
347
+ convert: (model, msg, publish, options, meta) => {
348
+ const result = {};
349
+ if (msg.data.hasOwnProperty('64515')) {
350
+ result['min_brightness'] = utils.mapNumberRange(msg.data['64515'], 0, 1000, 1, 255);
351
+ }
352
+ if (msg.data.hasOwnProperty('64516')) {
353
+ result['max_brightness'] = utils.mapNumberRange(msg.data['64516'], 0, 1000, 1, 255);
354
+ }
355
+ if (msg.data.hasOwnProperty('61440')) {
356
+ result['brightness'] = utils.mapNumberRange(msg.data['61440'], 0, 1000, 0, 255);
357
+ }
358
+ return result;
359
+ },
360
+ },
361
+ TS110E_light_type: {
362
+ cluster: 'genLevelCtrl',
363
+ type: ['attributeReport', 'readResponse'],
364
+ convert: (model, msg, publish, options, meta) => {
365
+ const result = {};
366
+ if (msg.data.hasOwnProperty('64514')) {
367
+ const lookup = {0: 'led', 1: 'incandescent', 2: 'halogen'};
368
+ result['light_type'] = lookup[msg.data['64514']];
369
+ }
370
+ return result;
371
+ },
372
+ },
373
+ TS110E_switch_type: {
374
+ cluster: 'genLevelCtrl',
375
+ type: ['attributeReport', 'readResponse'],
376
+ convert: (model, msg, publish, options, meta) => {
377
+ const result = {};
378
+ if (msg.data.hasOwnProperty('64514')) {
379
+ const lookup = {0: 'momentary', 1: 'toggle', 2: 'state'};
380
+ const propertyName = utils.postfixWithEndpointName('switch_type', msg, model, meta);
381
+ result[propertyName] = lookup[msg.data['64514']];
382
+ }
383
+ return result;
384
+ },
385
+ },
386
+ SA12IZL: {
387
+ cluster: 'manuSpecificTuya',
388
+ type: ['commandDataResponse', 'commandDataReport'],
389
+ convert: (model, msg, publish, options, meta) => {
390
+ const result = {};
391
+ for (const dpValue of msg.data.dpValues) {
392
+ const dp = dpValue.dp;
393
+ const value = tuya.getDataValue(dpValue);
394
+ switch (dp) {
395
+ case tuya.dataPoints.state:
396
+ result.smoke = value === 0;
397
+ break;
398
+ case 15:
399
+ result.battery = value;
400
+ break;
401
+ case 16:
402
+ result.silence_siren = value;
403
+ break;
404
+ case 20: {
405
+ const alarm = {0: true, 1: false};
406
+ result.alarm = alarm[value];
407
+ break;
408
+ }
409
+ default:
410
+ meta.logger.warn(`zigbee-herdsman-converters:SA12IZL: NOT RECOGNIZED DP #${
411
+ dp} with data ${JSON.stringify(dpValue)}`);
412
+ }
413
+ }
414
+ return result;
415
+ },
416
+ },
417
+ tuya_dinrail_switch2: {
418
+ cluster: 'manuSpecificTuya',
419
+ type: ['commandDataReport', 'commandDataResponse', 'commandActiveStatusReport'],
420
+ convert: (model, msg, publish, options, meta) => {
421
+ const dpValue = tuya.firstDpValue(msg, meta, 'tuya_dinrail_switch2');
422
+ const dp = dpValue.dp;
423
+ const value = tuya.getDataValue(dpValue);
424
+ const state = value ? 'ON' : 'OFF';
425
+
426
+ switch (dp) {
427
+ case tuya.dataPoints.state: // DPID that we added to common
428
+ return {state: state};
429
+ case tuya.dataPoints.dinrailPowerMeterTotalEnergy2:
430
+ return {energy: value/100};
431
+ case tuya.dataPoints.dinrailPowerMeterPower2:
432
+ return {power: value};
433
+ default:
434
+ meta.logger.warn(`zigbee-herdsman-converters:TuyaDinRailSwitch: NOT RECOGNIZED DP ` +
435
+ `#${dp} with data ${JSON.stringify(dpValue)}`);
436
+ }
437
+ },
438
+ },
439
+ hpsz: {
440
+ cluster: 'manuSpecificTuya',
441
+ type: ['commandDataResponse', 'commandDataReport'],
442
+ convert: (model, msg, publish, options, meta) => {
443
+ const dpValue = tuya.firstDpValue(msg, meta, 'hpsz');
444
+ const dp = dpValue.dp;
445
+ const value = tuya.getDataValue(dpValue);
446
+ let result = null;
447
+ switch (dp) {
448
+ case tuya.dataPoints.HPSZInductionState:
449
+ result = {presence: value === 1};
450
+ break;
451
+ case tuya.dataPoints.HPSZPresenceTime:
452
+ result = {duration_of_attendance: value};
453
+ break;
454
+ case tuya.dataPoints.HPSZLeavingTime:
455
+ result = {duration_of_absence: value};
456
+ break;
457
+ case tuya.dataPoints.HPSZLEDState:
458
+ result = {led_state: value};
459
+ break;
460
+ default:
461
+ meta.logger.warn(`zigbee-herdsman-converters:hpsz: NOT RECOGNIZED DP #${
462
+ dp} with data ${JSON.stringify(dpValue)}`);
463
+ }
464
+ return result;
465
+ },
466
+ },
467
+ scenes_recall_scene_65029: {
468
+ cluster: '65029',
469
+ type: ['raw', 'attributeReport'],
470
+ convert: (model, msg, publish, options, meta) => {
471
+ const id = meta.device.modelID === '005f0c3b' ? msg.data[0] : msg.data[msg.data.length - 1];
472
+ return {action: `scene_${id}`};
473
+ },
474
+ },
475
+ TS0201_battery: {
476
+ cluster: 'genPowerCfg',
477
+ type: ['attributeReport', 'readResponse'],
478
+ convert: (model, msg, publish, options, meta) => {
479
+ // https://github.com/Koenkk/zigbee2mqtt/issues/11470
480
+ if (msg.data.batteryPercentageRemaining == 200 && msg.data.batteryVoltage < 30) return;
481
+ return fz.battery.convert(model, msg, publish, options, meta);
482
+ },
483
+ },
484
+ TS0201_humidity: {
485
+ ...fz.humidity,
486
+ convert: (model, msg, publish, options, meta) => {
487
+ if (meta.device.manufacturerName === '_TZ3000_ywagc4rj') {
488
+ msg.data['measuredValue'] *= 10;
489
+ }
490
+ return fz.humidity.convert(model, msg, publish, options, meta);
491
+ },
492
+ },
493
+ TS0222: {
494
+ cluster: 'manuSpecificTuya',
495
+ type: ['commandDataResponse', 'commandDataReport'],
496
+ convert: (model, msg, publish, options, meta) => {
497
+ const result = {};
498
+ for (const dpValue of msg.data.dpValues) {
499
+ const dp = dpValue.dp;
500
+ const value = tuya.getDataValue(dpValue);
501
+ switch (dp) {
502
+ case 2:
503
+ result.illuminance = value;
504
+ result.illuminance_lux = value;
505
+ break;
506
+ case 4:
507
+ result.battery = value;
508
+ break;
509
+ default:
510
+ meta.logger.warn(`zigbee-herdsman-converters:TS0222 Unrecognized DP #${dp} with data ${JSON.stringify(dpValue)}`);
511
+ }
512
+ }
513
+ return result;
514
+ },
515
+ },
516
+ ZM35HQ_battery: {
517
+ cluster: 'manuSpecificTuya',
518
+ type: ['commandDataReport'],
519
+ convert: (model, msg, publish, options, meta) => {
520
+ const dpValue = tuya.firstDpValue(msg, meta, 'ZM35HQ');
521
+ const dp = dpValue.dp;
522
+ const value = tuya.getDataValue(dpValue);
523
+ if (dp === 4) return {battery: value};
524
+ else {
525
+ meta.logger.warn(`zigbee-herdsman-converters:ZM35HQ: NOT RECOGNIZED DP #${dp} with data ${JSON.stringify(dpValue)}`);
526
+ }
527
+ },
528
+ },
529
+ zb_sm_cover: {
530
+ cluster: 'manuSpecificTuya',
531
+ type: ['commandDataReport', 'commandDataResponse'],
532
+ convert: (model, msg, publish, options, meta) => {
533
+ const result = {};
534
+ for (const dpValue of msg.data.dpValues) {
535
+ const dp = dpValue.dp;
536
+ const value = tuya.getDataValue(dpValue);
537
+
538
+ switch (dp) {
539
+ case tuya.dataPoints.coverPosition: // Started moving to position (triggered from Zigbee)
540
+ case tuya.dataPoints.coverArrived: { // Arrived at position
541
+ const invert = (meta.state) ? !meta.state.invert_cover : false;
542
+ const position = invert ? 100 - (value & 0xFF) : (value & 0xFF);
543
+ if (position > 0 && position <= 100) {
544
+ result.position = position;
545
+ result.state = 'OPEN';
546
+ } else if (position == 0) { // Report fully closed
547
+ result.position = position;
548
+ result.state = 'CLOSE';
549
+ }
550
+ break;
551
+ }
552
+ case 1: // report state
553
+ result.state = {0: 'OPEN', 1: 'STOP', 2: 'CLOSE'}[value];
554
+ break;
555
+ case tuya.dataPoints.motorDirection: // reverse direction
556
+ result.reverse_direction = (value == 1);
557
+ break;
558
+ case 10: // cycle time
559
+ result.cycle_time = value;
560
+ break;
561
+ case 101: // model
562
+ result.motor_type = {0: '', 1: 'AM0/6-28R-Sm', 2: 'AM0/10-19R-Sm',
563
+ 3: 'AM1/10-13R-Sm', 4: 'AM1/20-13R-Sm', 5: 'AM1/30-13R-Sm'}[value];
564
+ break;
565
+ case 102: // cycles
566
+ result.cycle_count = value;
567
+ break;
568
+ case 103: // set or clear bottom limit
569
+ result.bottom_limit = {0: 'SET', 1: 'CLEAR'}[value];
570
+ break;
571
+ case 104: // set or clear top limit
572
+ result.top_limit = {0: 'SET', 1: 'CLEAR'}[value];
573
+ break;
574
+ case 109: // active power
575
+ result.active_power = value;
576
+ break;
577
+ case 115: // favorite_position
578
+ result.favorite_position = (value != 101) ? value : null;
579
+ break;
580
+ case 116: // report confirmation
581
+ break;
582
+ case 121: // running state
583
+ result.motor_state = {0: 'OPENING', 1: 'STOPPED', 2: 'CLOSING'}[value];
584
+ result.running = (value !== 1) ? true : false;
585
+ break;
586
+ default: // Unknown code
587
+ meta.logger.warn(`zb_sm_tuya_cover: Unhandled DP #${dp} for ${meta.device.manufacturerName}:
588
+ ${JSON.stringify(dpValue)}`);
589
+ }
590
+ }
591
+ return result;
592
+ },
593
+ },
594
+ x5h_thermostat: {
595
+ cluster: 'manuSpecificTuya',
596
+ type: ['commandDataResponse', 'commandDataReport'],
597
+ convert: (model, msg, publish, options, meta) => {
598
+ const dpValue = tuya.firstDpValue(msg, meta, 'x5h_thermostat');
599
+ const dp = dpValue.dp;
600
+ const value = tuya.getDataValue(dpValue);
601
+
602
+ switch (dp) {
603
+ case tuya.dataPoints.x5hState: {
604
+ return {system_mode: value ? 'heat' : 'off'};
605
+ }
606
+ case tuya.dataPoints.x5hWorkingStatus: {
607
+ return {running_state: value ? 'heat' : 'idle'};
608
+ }
609
+ case tuya.dataPoints.x5hSound: {
610
+ return {sound: value ? 'ON' : 'OFF'};
611
+ }
612
+ case tuya.dataPoints.x5hFrostProtection: {
613
+ return {frost_protection: value ? 'ON' : 'OFF'};
614
+ }
615
+ case tuya.dataPoints.x5hWorkingDaySetting: {
616
+ return {week: tuya.thermostatWeekFormat[value]};
617
+ }
618
+ case tuya.dataPoints.x5hFactoryReset: {
619
+ if (value) {
620
+ clearTimeout(globalStore.getValue(msg.endpoint, 'factoryResetTimer'));
621
+ const timer = setTimeout(() => publish({factory_reset: 'OFF'}), 60 * 1000);
622
+ globalStore.putValue(msg.endpoint, 'factoryResetTimer', timer);
623
+ meta.logger.info('The thermostat is resetting now. It will be available in 1 minute.');
624
+ }
625
+
626
+ return {factory_reset: value ? 'ON' : 'OFF'};
627
+ }
628
+ case tuya.dataPoints.x5hTempDiff: {
629
+ return {deadzone_temperature: parseFloat((value / 10).toFixed(1))};
630
+ }
631
+ case tuya.dataPoints.x5hProtectionTempLimit: {
632
+ return {heating_temp_limit: value};
633
+ }
634
+ case tuya.dataPoints.x5hBackplaneBrightness: {
635
+ const lookup = {0: 'off', 1: 'low', 2: 'medium', 3: 'high'};
636
+
637
+ if (value >= 0 && value <= 3) {
638
+ globalStore.putValue(msg.endpoint, 'brightnessState', value);
639
+ return {brightness_state: lookup[value]};
640
+ }
641
+
642
+ // Sometimes, for example on thermostat restart, it sends message like:
643
+ // {"dpValues":[{"data":{"data":[90],"type":"Buffer"},"datatype":4,"dp":104}
644
+ // It doesn't represent any brightness value and brightness remains the previous value
645
+ const lastValue = globalStore.getValue(msg.endpoint, 'brightnessState') || 1;
646
+ return {brightness_state: lookup[lastValue]};
647
+ }
648
+ case tuya.dataPoints.x5hWeeklyProcedure: {
649
+ const periods = [];
650
+ const periodSize = 4;
651
+ const periodsNumber = 8;
652
+
653
+ for (let i = 0; i < periodsNumber; i++) {
654
+ const hours = value[i * periodSize];
655
+ const minutes = value[i * periodSize + 1];
656
+ const tempHexArray = [value[i * periodSize + 2], value[i * periodSize + 3]];
657
+ const tempRaw = Buffer.from(tempHexArray).readUIntBE(0, tempHexArray.length);
658
+ const strHours = hours.toString().padStart(2, '0');
659
+ const strMinutes = minutes.toString().padStart(2, '0');
660
+ const temp = parseFloat((tempRaw / 10).toFixed(1));
661
+ periods.push(`${strHours}:${strMinutes}/${temp}`);
662
+ }
663
+
664
+ const schedule = periods.join(' ');
665
+ return {schedule};
666
+ }
667
+ case tuya.dataPoints.x5hChildLock: {
668
+ return {child_lock: value ? 'LOCK' : 'UNLOCK'};
669
+ }
670
+ case tuya.dataPoints.x5hSetTemp: {
671
+ const setpoint = parseFloat((value / 10).toFixed(1));
672
+ globalStore.putValue(msg.endpoint, 'currentHeatingSetpoint', setpoint);
673
+ return {current_heating_setpoint: setpoint};
674
+ }
675
+ case tuya.dataPoints.x5hSetTempCeiling: {
676
+ return {upper_temp: value};
677
+ }
678
+ case tuya.dataPoints.x5hCurrentTemp: {
679
+ const temperature = value & (1 << 15) ? value - (1 << 16) + 1 : value;
680
+ return {local_temperature: parseFloat((temperature / 10).toFixed(1))};
681
+ }
682
+ case tuya.dataPoints.x5hTempCorrection: {
683
+ return {local_temperature_calibration: parseFloat((value / 10).toFixed(1))};
684
+ }
685
+ case tuya.dataPoints.x5hMode: {
686
+ const lookup = {0: 'manual', 1: 'program'};
687
+ return {preset: lookup[value]};
688
+ }
689
+ case tuya.dataPoints.x5hSensorSelection: {
690
+ const lookup = {0: 'internal', 1: 'external', 2: 'both'};
691
+ return {sensor: lookup[value]};
692
+ }
693
+ case tuya.dataPoints.x5hOutputReverse: {
694
+ return {output_reverse: value};
695
+ }
696
+ default: {
697
+ meta.logger.warn(`fromZigbee:x5h_thermostat: Unrecognized DP #${dp} with data ${JSON.stringify(dpValue)}`);
698
+ }
699
+ }
700
+ },
701
+ },
702
+ humidity10: {
703
+ cluster: 'msRelativeHumidity',
704
+ type: ['attributeReport', 'readResponse'],
705
+ options: [exposes.options.precision('humidity'), exposes.options.calibration('humidity')],
706
+ convert: (model, msg, publish, options, meta) => {
707
+ const humidity = parseFloat(msg.data['measuredValue']) / 10.0;
708
+ if (humidity >= 0 && humidity <= 100) {
709
+ return {humidity: utils.calibrateAndPrecisionRoundOptions(humidity, options, 'humidity')};
710
+ }
711
+ },
712
+ },
713
+ temperature_unit: {
714
+ cluster: 'manuSpecificTuya_2',
715
+ type: ['attributeReport', 'readResponse'],
716
+ convert: (model, msg, publish, options, meta) => {
717
+ const result = {};
718
+ if (msg.data.hasOwnProperty('57355')) {
719
+ result.temperature_unit = {'0': 'celsius', '1': 'fahrenheit'}[msg.data['57355']];
720
+ }
721
+ return result;
722
+ },
723
+ },
724
+ };
725
+
726
+ module.exports = [
727
+ {
728
+ zigbeeModel: ['TS0204'],
729
+ model: 'TS0204',
730
+ vendor: 'TuYa',
731
+ description: 'Gas sensor',
732
+ whiteLabel: [{vendor: 'Tesla Smart', model: 'TSL-SEN-GAS'}],
733
+ fromZigbee: [fz.ias_gas_alarm_1, fz.ignore_basic_report],
734
+ toZigbee: [],
735
+ exposes: [e.gas(), e.tamper()],
736
+ },
737
+ {
738
+ zigbeeModel: ['TS0205'],
739
+ model: 'TS0205',
740
+ vendor: 'TuYa',
741
+ description: 'Smoke sensor',
742
+ whiteLabel: [{vendor: 'Tesla Smart', model: 'TSL-SEN-SMOKE'}],
743
+ fromZigbee: [fz.ias_smoke_alarm_1, fz.battery, fz.ignore_basic_report],
744
+ toZigbee: [],
745
+ exposes: [e.smoke(), e.battery_low(), e.tamper(), e.battery()],
746
+ },
747
+ {
748
+ zigbeeModel: ['TS0111'],
749
+ model: 'TS0111',
750
+ vendor: 'TuYa',
751
+ description: 'Socket',
752
+ extend: tuya.extend.switch(),
753
+ },
754
+ {
755
+ zigbeeModel: ['TS0218'],
756
+ model: 'TS0218',
757
+ vendor: 'TuYa',
758
+ description: 'Button',
759
+ fromZigbee: [fz.legacy.TS0218_click, fz.battery],
760
+ exposes: [e.battery(), e.action(['click'])],
761
+ toZigbee: [],
762
+ },
763
+ {
764
+ zigbeeModel: ['TS0203'],
765
+ model: 'TS0203',
766
+ vendor: 'TuYa',
767
+ description: 'Door sensor',
768
+ fromZigbee: [fz.ias_contact_alarm_1, fz.battery, fz.ignore_basic_report, fz.ias_contact_alarm_1_report],
769
+ toZigbee: [],
770
+ exposes: [e.contact(), e.battery_low(), e.tamper(), e.battery(), e.battery_voltage()],
771
+ whiteLabel: [
772
+ {vendor: 'CR Smart Home', model: 'TS0203'},
773
+ {vendor: 'TuYa', model: 'iH-F001'},
774
+ {vendor: 'Tesla Smart', model: 'TSL-SEN-DOOR'},
775
+ {vendor: 'Cleverio', model: 'SS100'},
776
+ ],
777
+ configure: async (device, coordinatorEndpoint, logger) => {
778
+ try {
779
+ const endpoint = device.getEndpoint(1);
780
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
781
+ await reporting.batteryPercentageRemaining(endpoint);
782
+ await reporting.batteryVoltage(endpoint);
783
+ } catch (error) {/* Fails for some*/}
784
+ },
785
+ },
786
+ {
787
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_bq5c8xfe'},
788
+ {modelID: 'TS0601', manufacturerName: '_TZE200_bjawzodf'},
789
+ {modelID: 'TS0601', manufacturerName: '_TZE200_qyflbnbj'},
790
+ {modelID: 'TS0601', manufacturerName: '_TZE200_9yapgbuv'},
791
+ {modelID: 'TS0601', manufacturerName: '_TZE200_zl1kmjqx'}],
792
+ model: 'TS0601_temperature_humidity_sensor',
793
+ vendor: 'TuYa',
794
+ description: 'Temperature & humidity sensor',
795
+ fromZigbee: [fz.tuya_temperature_humidity_sensor],
796
+ toZigbee: [],
797
+ exposes: (device, options) => {
798
+ const exps = [e.temperature(), e.humidity(), e.battery()];
799
+ if (!device || device.manufacturerName === '_TZE200_qyflbnbj') {
800
+ exps.push(e.battery_low());
801
+ exps.push(exposes.enum('battery_level', ea.STATE, ['low', 'middle', 'high']).withDescription('Battery level state'));
802
+ }
803
+ exps.push(e.linkquality());
804
+ return exps;
805
+ },
806
+ },
807
+ {
808
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_vzqtvljm'}],
809
+ model: 'TS0601_illuminance_temperature_humidity_sensor',
810
+ vendor: 'TuYa',
811
+ description: 'Illuminance, temperature & humidity sensor',
812
+ fromZigbee: [fz.tuya_illuminance_temperature_humidity_sensor],
813
+ toZigbee: [],
814
+ exposes: [e.temperature(), e.humidity(), e.illuminance_lux(), e.battery()],
815
+ },
816
+ {
817
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_8ygsuhe1'},
818
+ {modelID: 'TS0601', manufacturerName: '_TZE200_yvx5lh6k'},
819
+ {modelID: 'TS0601', manufacturerName: '_TZE200_ryfmq5rl'},
820
+ {modelID: 'TS0601', manufacturerName: '_TZE200_c2fmom5z'}],
821
+ model: 'TS0601_air_quality_sensor',
822
+ vendor: 'TuYa',
823
+ description: 'Air quality sensor',
824
+ fromZigbee: [fz.tuya_air_quality],
825
+ toZigbee: [],
826
+ exposes: [e.temperature(), e.humidity(), e.co2(), e.voc().withUnit('ppm'), e.formaldehyd()],
827
+ },
828
+ {
829
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_dwcarsat'}],
830
+ model: 'TS0601_smart_air_house_keeper',
831
+ vendor: 'TuYa',
832
+ description: 'Smart air house keeper',
833
+ fromZigbee: [fz.tuya_air_quality],
834
+ toZigbee: [],
835
+ exposes: [e.temperature(), e.humidity(), e.co2(), e.voc().withUnit('ppm'), e.formaldehyd().withUnit('µg/m³'),
836
+ e.pm25().withValueMin(0).withValueMax(999).withValueStep(1)],
837
+ },
838
+ {
839
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE200_ogkdpgy2', '_TZE200_3ejwxpmu']),
840
+ model: 'TS0601_co2_sensor',
841
+ vendor: 'TuYa',
842
+ description: 'NDIR co2 sensor',
843
+ fromZigbee: [fz.tuya_air_quality],
844
+ toZigbee: [],
845
+ exposes: [e.temperature(), e.humidity(), e.co2()],
846
+ },
847
+ {
848
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_7bztmfm1'}],
849
+ model: 'TS0601_smart_CO_air_box',
850
+ vendor: 'TuYa',
851
+ description: 'Smart air box (carbon monoxide)',
852
+ fromZigbee: [fz.tuya_CO],
853
+ toZigbee: [],
854
+ exposes: [e.carbon_monoxide(), e.co()],
855
+ },
856
+ {
857
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE200_ggev5fsl', '_TZE200_u319yc66']),
858
+ model: 'TS0601_gas_sensor_1',
859
+ vendor: 'TuYa',
860
+ description: 'Gas sensor',
861
+ fromZigbee: [tuya.fz.datapoints],
862
+ toZigbee: [tuya.tz.datapoints],
863
+ configure: tuya.configureMagicPacket,
864
+ exposes: [e.gas(), tuya.exposes.selfTest(), tuya.exposes.selfTestResult(), tuya.exposes.faultAlarm(), tuya.exposes.silence()],
865
+ meta: {
866
+ tuyaDatapoints: [
867
+ [1, 'gas', tuya.valueConverter.trueFalse0],
868
+ [8, 'self_test', tuya.valueConverter.raw],
869
+ [9, 'self_test_result', tuya.valueConverter.selfTestResult],
870
+ [11, 'fault_alarm', tuya.valueConverter.trueFalse1],
871
+ [16, 'silence', tuya.valueConverter.raw],
872
+ ],
873
+ },
874
+ },
875
+ {
876
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE200_yojqa8xn']),
877
+ model: 'TS0601_gas_sensor_2',
878
+ vendor: 'TuYa',
879
+ description: 'Gas sensor',
880
+ fromZigbee: [tuya.fz.datapoints],
881
+ toZigbee: [tuya.tz.datapoints],
882
+ configure: tuya.configureMagicPacket,
883
+ exposes: [
884
+ e.gas(), tuya.exposes.gasValue().withUnit('LEL'), tuya.exposes.selfTest(), tuya.exposes.selfTestResult(),
885
+ tuya.exposes.silence(),
886
+ exposes.enum('alarm_ringtone', ea.STATE_SET, ['1', '2', '3', '4', '5']).withDescription('Ringtone of the alarm'),
887
+ exposes.numeric('alarm_time', ea.STATE_SET).withValueMin(1).withValueMax(180).withValueStep(1)
888
+ .withUnit('s').withDescription('Alarm time'),
889
+ exposes.binary('preheat', ea.STATE, true, false).withDescription('Indicates sensor preheat is active'),
890
+ ],
891
+ meta: {
892
+ tuyaDatapoints: [
893
+ [1, 'gas', tuya.valueConverter.trueFalseEnum0],
894
+ [2, 'gas_value', tuya.valueConverter.divideBy10],
895
+ [6, 'alarm_ringtone', tuya.valueConverterBasic.lookup({'1': 0, '2': 1, '3': 2, '4': 3, '5': 4})],
896
+ [7, 'alarm_time', tuya.valueConverter.raw],
897
+ [8, 'self_test', tuya.valueConverter.raw],
898
+ [9, 'self_test_result', tuya.valueConverter.selfTestResult],
899
+ [10, 'preheat', tuya.valueConverter.raw],
900
+ [13, null, null], // alarm_switch; ignore for now since it is unclear what it does
901
+ [16, 'silence', tuya.valueConverter.raw],
902
+ ],
903
+ },
904
+ },
905
+ {
906
+ fingerprint: [{modelID: 'TS0001', manufacturerName: '_TZ3000_hktqahrq'}, {manufacturerName: '_TZ3000_hktqahrq'},
907
+ {manufacturerName: '_TZ3000_q6a3tepg'}, {modelID: 'TS000F', manufacturerName: '_TZ3000_m9af2l6g'},
908
+ {modelID: 'TS000F', manufacturerName: '_TZ3000_mx3vgyea'},
909
+ {modelID: 'TS0001', manufacturerName: '_TZ3000_npzfdcof'},
910
+ {modelID: 'TS0001', manufacturerName: '_TZ3000_5ng23zjs'},
911
+ {modelID: 'TS0001', manufacturerName: '_TZ3000_rmjr4ufz'},
912
+ {modelID: 'TS0001', manufacturerName: '_TZ3000_v7gnj3ad'},
913
+ {modelID: 'TS0001', manufacturerName: '_TZ3000_3a9beq8a'},
914
+ {modelID: 'TS0001', manufacturerName: '_TZ3000_ark8nv4y'},
915
+ {modelID: 'TS0001', manufacturerName: '_TZ3000_mx3vgyea'},
916
+ {modelID: 'TS0001', manufacturerName: '_TZ3000_qsp2pwtf'},
917
+ {modelID: 'TS0001', manufacturerName: '_TZ3000_46t1rvdu'}],
918
+ model: 'WHD02',
919
+ vendor: 'TuYa',
920
+ whiteLabel: [{vendor: 'TuYa', model: 'iHSW02'}, {vendor: 'Aubess', model: 'TMZ02'}],
921
+ description: 'Wall switch module',
922
+ extend: tuya.extend.switch({switchType: true}),
923
+ configure: async (device, coordinatorEndpoint, logger) => {
924
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
925
+ const endpoint = device.getEndpoint(1);
926
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
927
+ await reporting.onOff(endpoint);
928
+ },
929
+ },
930
+ {
931
+ fingerprint: [{modelID: 'TS011F', manufacturerName: '_TZ3000_mvn6jl7x'},
932
+ {modelID: 'TS011F', manufacturerName: '_TZ3000_raviyuvk'}, {modelID: 'TS011F', manufacturerName: '_TYZB01_hlla45kx'},
933
+ {modelID: 'TS011F', manufacturerName: '_TZ3000_92qd4sqa'}, {modelID: 'TS011F', manufacturerName: '_TZ3000_zwaadvus'},
934
+ {modelID: 'TS011F', manufacturerName: '_TZ3000_k6fvknrr'}, {modelID: 'TS011F', manufacturerName: '_TZ3000_6s5dc9lx'}],
935
+ model: 'TS011F_2_gang_wall',
936
+ vendor: 'TuYa',
937
+ description: '2 gang wall outlet',
938
+ extend: tuya.extend.switch({backlightModeLowMediumHigh: true, childLock: true, endpoints: ['l1', 'l2']}),
939
+ whiteLabel: [{vendor: 'ClickSmart+', model: 'CMA30036'}],
940
+ endpoint: (device) => {
941
+ return {'l1': 1, 'l2': 2};
942
+ },
943
+ meta: {multiEndpoint: true},
944
+ configure: tuya.configureMagicPacket,
945
+ },
946
+ {
947
+ fingerprint: [{modelID: 'TS011F', manufacturerName: '_TZ3000_rk2yzt0u'},
948
+ {modelID: 'TS0001', manufacturerName: '_TZ3000_o4cjetlm'}, {manufacturerName: '_TZ3000_o4cjetlm'},
949
+ {modelID: 'TS0001', manufacturerName: '_TZ3000_iedbgyxt'}, {modelID: 'TS0001', manufacturerName: '_TZ3000_h3noz0a5'},
950
+ {modelID: 'TS0001', manufacturerName: '_TYZB01_4tlksk8a'}, {modelID: 'TS0011', manufacturerName: '_TYZB01_rifa0wlb'}],
951
+ model: 'ZN231392',
952
+ vendor: 'TuYa',
953
+ description: 'Smart water/gas valve',
954
+ extend: tuya.extend.switch({powerOnBehavior: true}),
955
+ configure: async (device, coordinatorEndpoint, logger) => {
956
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
957
+ const endpoint = device.getEndpoint(1);
958
+ await endpoint.read('genOnOff', ['onOff', 'moesStartUpOnOff']);
959
+ },
960
+ },
961
+ {
962
+ fingerprint: [{modelID: 'TS011F', manufacturerName: '_TZ3000_1hwjutgo'}, {modelID: 'TS011F', manufacturerName: '_TZ3000_lnggrqqi'}],
963
+ model: 'TS011F_circuit_breaker',
964
+ vendor: 'TuYa',
965
+ description: 'Circuit breaker',
966
+ extend: tuya.extend.switch(),
967
+ whiteLabel: [{vendor: 'Mumubiz', model: 'ZJSB9-80Z'}],
968
+ },
969
+ {
970
+ fingerprint: [{modelID: 'TS011F', manufacturerName: '_TZ3000_8fdayfch'}],
971
+ model: 'TS011F_relay_switch',
972
+ vendor: 'TuYa',
973
+ description: 'Dry contact relay switch',
974
+ extend: tuya.extend.switch(),
975
+ whiteLabel: [{vendor: 'KTNNKG', model: 'ZB1248-10A'}],
976
+ },
977
+ {
978
+ zigbeeModel: ['CK-BL702-AL-01(7009_Z102LG03-1)'],
979
+ model: 'CK-BL702-AL-01',
980
+ vendor: 'TuYa',
981
+ description: 'Zigbee LED bulb',
982
+ extend: tuya.extend.light_onoff_brightness_colortemp_color({colorTempRange: [142, 500]}),
983
+ },
984
+ {
985
+ zigbeeModel: ['TS0505B'],
986
+ model: 'TS0505B',
987
+ vendor: 'TuYa',
988
+ description: 'Zigbee RGB+CCT light',
989
+ whiteLabel: [{vendor: 'Mercator Ikuü', model: 'SMD4106W-RGB-ZB'},
990
+ {vendor: 'TuYa', model: 'A5C-21F7-01'}, {vendor: 'Mercator Ikuü', model: 'S9E27LED9W-RGB-Z'},
991
+ {vendor: 'Aldi', model: 'L122CB63H11A9.0W', description: 'LIGHTWAY smart home LED-lamp - bulb'},
992
+ {vendor: 'Lidl', model: '14153706L', description: 'Livarno smart LED ceiling light'},
993
+ {vendor: 'Zemismart', model: 'LXZB-ZB-09A', description: 'Zemismart LED Surface Mounted Downlight 9W RGBW'},
994
+ {vendor: 'Feconn', model: 'FE-GU10-5W', description: 'Zigbee GU10 5W smart bulb'},
995
+ {vendor: 'Nedis', model: 'ZBLC1E14'},
996
+ ],
997
+ extend: tuya.extend.light_onoff_brightness_colortemp_color({colorTempRange: [153, 500]}),
998
+ },
999
+ {
1000
+ zigbeeModel: ['TS0503B'],
1001
+ model: 'TS0503B',
1002
+ vendor: 'TuYa',
1003
+ description: 'Zigbee RGB light',
1004
+ whiteLabel: [{vendor: 'BTF-Lighting', model: 'C03Z'}],
1005
+ extend: tuya.extend.light_onoff_brightness_color(),
1006
+ },
1007
+ {
1008
+ zigbeeModel: ['TS0504B'],
1009
+ model: 'TS0504B',
1010
+ vendor: 'TuYa',
1011
+ description: 'Zigbee RGBW light',
1012
+ extend: tuya.extend.light_onoff_brightness_color(),
1013
+ exposes: [e.light_brightness_color({disablePowerOnBehavior: true})
1014
+ .setAccess('color_xy', ea.STATE_SET).setAccess('color_hs', ea.STATE_SET)],
1015
+ toZigbee: utils.replaceInArray(tuya.extend.light_onoff_brightness_color().toZigbee, [tz.light_color], [tzLocal.TS0504B_color]),
1016
+ meta: {applyRedFix: true},
1017
+ },
1018
+ {
1019
+ zigbeeModel: ['TS0501A'],
1020
+ model: 'TS0501A',
1021
+ description: 'Zigbee light',
1022
+ vendor: 'TuYa',
1023
+ extend: tuya.extend.light_onoff_brightness(),
1024
+ },
1025
+ {
1026
+ zigbeeModel: ['TS0501B'],
1027
+ model: 'TS0501B',
1028
+ description: 'Zigbee light',
1029
+ vendor: 'TuYa',
1030
+ extend: tuya.extend.light_onoff_brightness(),
1031
+ },
1032
+ {
1033
+ fingerprint: tuya.fingerprint('TS0202', ['_TYZB01_vwqnz1sn']),
1034
+ model: 'TS0202_3',
1035
+ vendor: 'TuYa',
1036
+ description: 'Motion detector with illuminance',
1037
+ fromZigbee: [fz.ias_occupancy_alarm_1, fz.battery, fz.ignore_basic_report, fz.ias_occupancy_alarm_1_report, fz.illuminance],
1038
+ toZigbee: [],
1039
+ onEvent: tuya.onEventSetTime,
1040
+ configure: tuya.configureMagicPacket,
1041
+ exposes: [e.occupancy(), e.battery_low(), e.battery(), e.tamper(), e.illuminance_lux()],
1042
+ },
1043
+ {
1044
+ fingerprint: tuya.fingerprint('TS0202', ['_TZ3210_cwamkvua']),
1045
+ model: 'TS0202_2',
1046
+ vendor: 'TuYa',
1047
+ description: 'Motion sensor with scene switch',
1048
+ fromZigbee: [tuya.fz.datapoints, fz.ias_occupancy_alarm_1, fz.battery],
1049
+ toZigbee: [tuya.tz.datapoints],
1050
+ configure: async (device, coordinatorEndpoint, logger) => {
1051
+ const endpoint = device.getEndpoint(1);
1052
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
1053
+ await reporting.batteryPercentageRemaining(endpoint);
1054
+ await reporting.batteryVoltage(endpoint);
1055
+ },
1056
+ whiteLabel: [{vendor: 'Linkoze', model: 'LKMSZ001'}],
1057
+ exposes: [e.battery(), e.battery_voltage(), e.occupancy(), e.action(['single', 'double', 'hold']),
1058
+ exposes.enum('light', ea.STATE, ['dark', 'bright'])],
1059
+ meta: {
1060
+ tuyaDatapoints: [
1061
+ [102, 'light', tuya.valueConverterBasic.lookup({'dark': false, 'bright': true})],
1062
+ [101, 'action', tuya.valueConverterBasic.lookup({'single': 0, 'double': 1, 'hold': 2})],
1063
+ ],
1064
+ },
1065
+ },
1066
+ {
1067
+ fingerprint: [{modelID: 'TS0202', manufacturerName: '_TYZB01_jytabjkb'},
1068
+ {modelID: 'TS0202', manufacturerName: '_TZ3000_lltemgsf'},
1069
+ {modelID: 'TS0202', manufacturerName: '_TYZB01_5nr7ncpl'},
1070
+ {modelID: 'TS0202', manufacturerName: '_TZ3000_mg4dy6z6'},
1071
+ {modelID: 'TS0202', manufacturerName: '_TZ3040_bb6xaihh'}],
1072
+ model: 'TS0202_1',
1073
+ vendor: 'TuYa',
1074
+ description: 'Motion sensor',
1075
+ // Requires alarm_1_with_timeout https://github.com/Koenkk/zigbee2mqtt/issues/2818#issuecomment-776119586
1076
+ fromZigbee: [fz.ias_occupancy_alarm_1_with_timeout, fz.battery, fz.ignore_basic_report],
1077
+ toZigbee: [],
1078
+ exposes: [e.occupancy(), e.battery_low(), e.linkquality(), e.battery(), e.battery_voltage()],
1079
+ configure: async (device, coordinatorEndpoint, logger) => {
1080
+ const endpoint = device.getEndpoint(1);
1081
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
1082
+ await reporting.batteryPercentageRemaining(endpoint);
1083
+ },
1084
+ },
1085
+ {
1086
+ fingerprint: [{modelID: 'TS0202', manufacturerName: '_TYZB01_dr6sduka'},
1087
+ {modelID: 'TS0202', manufacturerName: '_TYZB01_ef5xlc9q'},
1088
+ {modelID: 'TS0202', manufacturerName: '_TYZB01_2b8f6cio'},
1089
+ {modelID: 'TS0202', manufacturerName: '_TYZB01_71kfvvma'},
1090
+ {modelID: 'TS0202', manufacturerName: '_TZE200_bq5c8xfe'},
1091
+ {modelID: 'TS0202', manufacturerName: '_TYZB01_dl7cejts'},
1092
+ {modelID: 'TS0202', manufacturerName: '_TZ3000_nss8amz9'},
1093
+ {modelID: 'TS0202', manufacturerName: '_TZ3000_mmtwjmaq'},
1094
+ {modelID: 'TS0202', manufacturerName: '_TYZB01_zwvaj5wy'},
1095
+ {modelID: 'TS0202', manufacturerName: '_TZ3000_bsvqrxru'},
1096
+ {modelID: 'TS0202', manufacturerName: '_TZ3000_wrgn6xrz'},
1097
+ {modelID: 'TS0202', manufacturerName: '_TYZB01_tv3wxhcz'},
1098
+ {modelID: 'TS0202', manufacturerName: '_TYZB01_rwb0hxtf'},
1099
+ {modelID: 'TS0202', manufacturerName: '_TYZB01_hqbdru35'},
1100
+ {modelID: 'TS0202', manufacturerName: '_TZ3000_otvn3lne'},
1101
+ {modelID: 'TS0202', manufacturerName: '_TZ3000_tiwq83wk'},
1102
+ {modelID: 'TS0202', manufacturerName: '_TZ3000_ykwcwxmz'},
1103
+ // _TZ3000_kmh5qpmb = NAS-PD07 without temperature/humidity sensor
1104
+ // https://github.com/Koenkk/zigbee2mqtt/issues/15481#issuecomment-1366003011
1105
+ {modelID: 'TS0202', manufacturerName: '_TZ3000_kmh5qpmb'},
1106
+ {modelID: 'TS0202', manufacturerName: '_TZ3000_hgu1dlak'},
1107
+ {modelID: 'TS0202', manufacturerName: '_TZ3000_h4wnrtck'},
1108
+ {modelID: 'TS0202', manufacturerName: '_TZ3000_sr0vaafi'},
1109
+ {modelID: 'WHD02', manufacturerName: '_TZ3000_hktqahrq'},
1110
+ ],
1111
+ model: 'TS0202',
1112
+ vendor: 'TuYa',
1113
+ description: 'Motion sensor',
1114
+ whiteLabel: [{vendor: 'Mercator Ikuü', model: 'SMA02P'},
1115
+ {vendor: 'TuYa', model: 'TY-ZPR06'},
1116
+ {vendor: 'Tesla Smart', model: 'TS0202'}],
1117
+ fromZigbee: [fz.ias_occupancy_alarm_1, fz.battery, fz.ignore_basic_report, fz.ias_occupancy_alarm_1_report],
1118
+ toZigbee: [],
1119
+ exposes: [e.occupancy(), e.battery_low(), e.tamper(), e.battery(), e.battery_voltage()],
1120
+ configure: async (device, coordinatorEndpoint, logger) => {
1121
+ const endpoint = device.getEndpoint(1);
1122
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
1123
+ try {
1124
+ await reporting.batteryPercentageRemaining(endpoint);
1125
+ await reporting.batteryVoltage(endpoint);
1126
+ } catch (error) {/* Fails for some https://github.com/Koenkk/zigbee2mqtt/issues/13708*/}
1127
+ },
1128
+ },
1129
+ {
1130
+ fingerprint: [{modelID: 'TS0202', manufacturerName: '_TZ3000_msl6wxk9'}, {modelID: 'TS0202', manufacturerName: '_TZ3040_fwxuzcf4'}],
1131
+ model: 'ZM-35H-Q',
1132
+ vendor: 'TuYa',
1133
+ description: 'Motion sensor',
1134
+ fromZigbee: [fz.ias_occupancy_alarm_1, fz.battery, fz.ignore_basic_report, fz.ZM35HQ_attr, fzLocal.ZM35HQ_battery],
1135
+ toZigbee: [tz.ZM35HQ_attr],
1136
+ exposes: [e.occupancy(), e.battery_low(), e.tamper(), e.battery(),
1137
+ exposes.enum('sensitivity', ea.ALL, ['low', 'medium', 'high']).withDescription('PIR sensor sensitivity'),
1138
+ exposes.enum('keep_time', ea.ALL, [30, 60, 120]).withDescription('PIR keep time in seconds'),
1139
+ ],
1140
+ configure: tuya.configureMagicPacket,
1141
+ },
1142
+ {
1143
+ fingerprint: [{modelID: 'TS0202', manufacturerName: '_TZ3040_msl6wxk9'}],
1144
+ model: '40ZH-O',
1145
+ vendor: 'TuYa',
1146
+ description: 'Motion sensor',
1147
+ fromZigbee: [fz.ias_occupancy_alarm_1, fz.battery, fz.ignore_basic_report, fz.ZM35HQ_attr, fzLocal.ZM35HQ_battery],
1148
+ toZigbee: [tz.ZM35HQ_attr],
1149
+ exposes: [e.occupancy(), e.battery_low(), e.tamper(), e.battery(),
1150
+ exposes.enum('sensitivity', ea.ALL, ['low', 'medium', 'high']).withDescription('PIR sensor sensitivity'),
1151
+ exposes.enum('keep_time', ea.ALL, [30, 60, 120]).withDescription('PIR keep time in seconds'),
1152
+ ],
1153
+ configure: tuya.configureMagicPacket,
1154
+ },
1155
+ {
1156
+ fingerprint: tuya.fingerprint('TS0202', ['_TZ3000_mcxw5ehu', '_TZ3000_6ygjfyll', '_TZ3040_6ygjfyll']),
1157
+ model: 'IH012-RT01',
1158
+ vendor: 'TuYa',
1159
+ description: 'Motion sensor',
1160
+ fromZigbee: [fz.ias_occupancy_alarm_1, fz.ignore_basic_report, fz.ZM35HQ_attr, fz.battery],
1161
+ toZigbee: [tz.ZM35HQ_attr],
1162
+ exposes: [e.occupancy(), e.battery_low(), e.tamper(), e.battery(), e.battery_voltage(),
1163
+ exposes.enum('sensitivity', ea.ALL, ['low', 'medium', 'high']).withDescription('PIR sensor sensitivity'),
1164
+ exposes.enum('keep_time', ea.ALL, [30, 60, 120]).withDescription('PIR keep time in seconds'),
1165
+ ],
1166
+ configure: async (device, coordinatorEndpoint, logger) => {
1167
+ const endpoint = device.getEndpoint(1);
1168
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
1169
+ await reporting.batteryPercentageRemaining(endpoint);
1170
+ await reporting.batteryVoltage(endpoint);
1171
+ },
1172
+ },
1173
+ {
1174
+ fingerprint: [{modelID: 'TS0207', manufacturerName: '_TZ3000_m0vaazab'},
1175
+ {modelID: 'TS0207', manufacturerName: '_TZ3000_ufttklsz'},
1176
+ {modelID: 'TS0207', manufacturerName: '_TZ3000_nkkl7uzv'},
1177
+ {modelID: 'TS0207', manufacturerName: '_TZ3000_misw04hq'},
1178
+ {modelID: 'TS0207', manufacturerName: '_TZ3000_gszjt2xx'},
1179
+ {modelID: 'TS0207', manufacturerName: '_TZ3000_5k5vh43t'}],
1180
+ model: 'TS0207_repeater',
1181
+ vendor: 'TuYa',
1182
+ description: 'Repeater',
1183
+ fromZigbee: [fz.linkquality_from_basic],
1184
+ toZigbee: [],
1185
+ exposes: [],
1186
+ },
1187
+ {
1188
+ zigbeeModel: ['TS0207', 'FNB54-WTS08ML1.0'],
1189
+ fingerprint: [{modelID: 'TS0207', manufacturerName: '_TZ3000_upgcbody'}],
1190
+ model: 'TS0207_water_leak_detector',
1191
+ vendor: 'TuYa',
1192
+ description: 'Water leak detector',
1193
+ fromZigbee: [fz.ias_water_leak_alarm_1, fz.battery],
1194
+ whiteLabel: [{vendor: 'CR Smart Home', model: 'TS0207'}],
1195
+ toZigbee: [],
1196
+ configure: async (device, coordinatorEndpoint, logger) => {
1197
+ const endpoint = device.getEndpoint(1);
1198
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
1199
+ await reporting.batteryPercentageRemaining(endpoint);
1200
+ },
1201
+ exposes: [e.water_leak(), e.battery_low(), e.battery()],
1202
+ },
1203
+ {
1204
+ fingerprint: tuya.fingerprint('TS0101', ['_TYZB01_ijihzffk', '_TZ3210_tfxwxklq']),
1205
+ model: 'TS0101',
1206
+ vendor: 'TuYa',
1207
+ description: 'Zigbee Socket',
1208
+ whiteLabel: [{vendor: 'Larkkey', model: 'PS080'}, {vendor: 'Mercator', model: 'SPBS01G'}],
1209
+ extend: tuya.extend.switch(),
1210
+ meta: {disableDefaultResponse: true},
1211
+ },
1212
+ {
1213
+ fingerprint: [{modelID: 'TS0108', manufacturerName: '_TYZB01_7yidyqxd'}],
1214
+ model: 'TS0108',
1215
+ vendor: 'TuYa',
1216
+ description: 'Socket with 2 USB',
1217
+ whiteLabel: [{vendor: 'Larkkey', model: 'PS580'}],
1218
+ extend: tuya.extend.switch(),
1219
+ exposes: [e.switch().withEndpoint('l1'), e.switch().withEndpoint('l2')],
1220
+ endpoint: (device) => {
1221
+ return {'l1': 1, 'l2': 7};
1222
+ },
1223
+ meta: {multiEndpoint: true, disableDefaultResponse: true},
1224
+ configure: async (device, coordinatorEndpoint, logger) => {
1225
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
1226
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
1227
+ await reporting.bind(device.getEndpoint(7), coordinatorEndpoint, ['genOnOff']);
1228
+ },
1229
+ },
1230
+ {
1231
+ fingerprint: [
1232
+ {modelID: 'TS0601', manufacturerName: '_TZE200_whpb9yts'},
1233
+ {modelID: 'TS0601', manufacturerName: '_TZE200_ebwgzdqq'},
1234
+ {modelID: 'TS0601', manufacturerName: '_TZE200_ctq0k47x'},
1235
+ {modelID: 'TS0601', manufacturerName: '_TZE200_9i9dt8is'},
1236
+ {modelID: 'TS0601', manufacturerName: '_TZE200_dfxkcots'},
1237
+ {modelID: 'TS0601', manufacturerName: '_TZE200_w4cryh2i'},
1238
+ {modelID: 'TS0601', manufacturerName: '_TZE200_ojzhk75b'},
1239
+ {modelID: 'TS0601', manufacturerName: '_TZE200_swaamsoy'},
1240
+ {modelID: 'TS0601', manufacturerName: '_TZE200_3p5ydos3'},
1241
+ ],
1242
+ model: 'TS0601_dimmer',
1243
+ vendor: 'TuYa',
1244
+ description: 'Zigbee smart dimmer',
1245
+ fromZigbee: [fz.tuya_dimmer, fz.ignore_basic_report],
1246
+ toZigbee: [tz.tuya_dimmer_state, tz.tuya_dimmer_level],
1247
+ configure: async (device, coordinatorEndpoint, logger) => {
1248
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
1249
+ const endpoint = device.getEndpoint(1);
1250
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
1251
+ },
1252
+ exposes: [e.light_brightness().withMinBrightness().withMaxBrightness().setAccess(
1253
+ 'state', ea.STATE_SET).setAccess('brightness', ea.STATE_SET).setAccess(
1254
+ 'min_brightness', ea.STATE_SET).setAccess('max_brightness', ea.STATE_SET)],
1255
+ whiteLabel: [
1256
+ {vendor: 'Larkkey', model: 'ZSTY-SM-1DMZG-EU'},
1257
+ {vendor: 'Earda', model: 'EDM-1ZAA-EU'},
1258
+ {vendor: 'Earda', model: 'EDM-1ZAB-EU'},
1259
+ {vendor: 'Earda', model: 'EDM-1ZBA-EU'},
1260
+ {vendor: 'Mercator Ikuü', model: 'SSWD01'},
1261
+ {vendor: 'Moes', model: 'ZS-USD'},
1262
+ {vendor: 'Moes', model: 'EDM-1ZBB-EU'},
1263
+ ],
1264
+ },
1265
+ {
1266
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE200_myd45weu']),
1267
+ model: 'TS0601_soil',
1268
+ vendor: 'TuYa',
1269
+ description: 'Soil sensor',
1270
+ fromZigbee: [tuya.fz.datapoints],
1271
+ toZigbee: [tuya.tz.datapoints],
1272
+ configure: tuya.configureMagicPacket,
1273
+ exposes: [e.temperature(), e.soil_moisture(), tuya.exposes.temperatureUnit(), e.battery(), tuya.exposes.batteryState()],
1274
+ meta: {
1275
+ tuyaDatapoints: [
1276
+ [3, 'soil_moisture', tuya.valueConverter.raw],
1277
+ [5, 'temperature', tuya.valueConverter.raw],
1278
+ [9, 'temperature_unit', tuya.valueConverter.temperatureUnit],
1279
+ [14, 'battery_state', tuya.valueConverter.batteryState],
1280
+ [15, 'battery', tuya.valueConverter.raw],
1281
+ ],
1282
+ },
1283
+ },
1284
+ {
1285
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE200_ip2akl4w', '_TZE200_1agwnems', '_TZE200_la2c2uo9', '_TZE200_579lguh2',
1286
+ '_TZE200_vucankjx', '_TZE200_4mh6tyyo']),
1287
+ model: 'TS0601_dimmer_1',
1288
+ vendor: 'TuYa',
1289
+ description: '1 gang smart dimmer',
1290
+ fromZigbee: [tuya.fz.datapoints],
1291
+ toZigbee: [tuya.tz.datapoints],
1292
+ configure: tuya.configureMagicPacket,
1293
+ exposes: [tuya.exposes.lightBrightnessWithMinMax(), e.power_on_behavior(),
1294
+ tuya.exposes.countdown(), tuya.exposes.lightType()],
1295
+ meta: {
1296
+ tuyaDatapoints: [
1297
+ [1, 'state', tuya.valueConverter.onOff, {skip: tuya.skip.stateOnAndBrightnessPresent}],
1298
+ [2, 'brightness', tuya.valueConverter.scale0_254to0_1000],
1299
+ [3, 'min_brightness', tuya.valueConverter.scale0_254to0_1000],
1300
+ [4, 'light_type', tuya.valueConverter.lightType],
1301
+ [5, 'max_brightness', tuya.valueConverter.scale0_254to0_1000],
1302
+ [6, 'countdown', tuya.valueConverter.countdown],
1303
+ [14, 'power_on_behavior', tuya.valueConverter.powerOnBehavior],
1304
+ ],
1305
+ },
1306
+ whiteLabel: [
1307
+ {vendor: 'Moes', model: 'MS-105Z'},
1308
+ {vendor: 'Lerlink', model: 'X706U'},
1309
+ {vendor: 'Moes', model: 'ZS-EUD_1gang'},
1310
+ ],
1311
+ },
1312
+ {
1313
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE200_fjjbhx9d']),
1314
+ model: 'TS0601_dimmer_2',
1315
+ vendor: 'TuYa',
1316
+ description: '2 gang smart dimmer',
1317
+ fromZigbee: [tuya.fz.datapoints],
1318
+ toZigbee: [tuya.tz.datapoints],
1319
+ configure: tuya.configureMagicPacket,
1320
+ exposes: [
1321
+ tuya.exposes.lightBrightnessWithMinMax().withEndpoint('l1'),
1322
+ tuya.exposes.lightBrightnessWithMinMax().withEndpoint('l2'),
1323
+ tuya.exposes.countdown().withEndpoint('l1'),
1324
+ tuya.exposes.countdown().withEndpoint('l2'),
1325
+ ],
1326
+ meta: {
1327
+ multiEndpoint: true,
1328
+ tuyaDatapoints: [
1329
+ [1, 'state_l1', tuya.valueConverter.onOff, {skip: tuya.skip.stateOnAndBrightnessPresent}],
1330
+ [2, 'brightness_l1', tuya.valueConverter.scale0_254to0_1000],
1331
+ [3, 'min_brightness_l1', tuya.valueConverter.scale0_254to0_1000],
1332
+ [5, 'max_brightness_l1', tuya.valueConverter.scale0_254to0_1000],
1333
+ [6, 'countdown_l1', tuya.valueConverter.countdown],
1334
+ [7, 'state_l2', tuya.valueConverter.onOff, {skip: tuya.skip.stateOnAndBrightnessPresent}],
1335
+ [8, 'brightness_l2', tuya.valueConverter.scale0_254to0_1000],
1336
+ [9, 'min_brightness_l2', tuya.valueConverter.scale0_254to0_1000],
1337
+ [11, 'max_brightness_l2', tuya.valueConverter.scale0_254to0_1000],
1338
+ [12, 'countdown_l2', tuya.valueConverter.countdown],
1339
+ ],
1340
+ },
1341
+ endpoint: (device) => {
1342
+ return {'l1': 1, 'l2': 1};
1343
+ },
1344
+ whiteLabel: [
1345
+ {vendor: 'Moes', model: 'ZS-EUD_2gang'},
1346
+ ],
1347
+ },
1348
+ {
1349
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE200_vm1gyrso']),
1350
+ model: 'TS0601_dimmer_3',
1351
+ vendor: 'TuYa',
1352
+ description: '3 gang smart dimmer',
1353
+ fromZigbee: [tuya.fz.datapoints],
1354
+ toZigbee: [tuya.tz.datapoints],
1355
+ configure: tuya.configureMagicPacket,
1356
+ exposes: [tuya.exposes.lightBrightness().withEndpoint('l1'), tuya.exposes.lightBrightness().withEndpoint('l2'),
1357
+ tuya.exposes.lightBrightness().withEndpoint('l3')],
1358
+ meta: {
1359
+ multiEndpoint: true,
1360
+ tuyaDatapoints: [
1361
+ [1, 'state_l1', tuya.valueConverter.onOff, {skip: tuya.skip.stateOnAndBrightnessPresent}],
1362
+ [2, 'brightness_l1', tuya.valueConverter.scale0_254to0_1000],
1363
+ [7, 'state_l2', tuya.valueConverter.onOff, {skip: tuya.skip.stateOnAndBrightnessPresent}],
1364
+ [8, 'brightness_l2', tuya.valueConverter.scale0_254to0_1000],
1365
+ [15, 'state_l3', tuya.valueConverter.onOff, {skip: tuya.skip.stateOnAndBrightnessPresent}],
1366
+ [16, 'brightness_l3', tuya.valueConverter.scale0_254to0_1000],
1367
+ ],
1368
+ },
1369
+ endpoint: (device) => {
1370
+ return {'l1': 1, 'l2': 1, 'l3': 1};
1371
+ },
1372
+ whiteLabel: [
1373
+ {vendor: 'Moes', model: 'ZS-EUD_3gang'},
1374
+ ],
1375
+ },
1376
+ {
1377
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE200_p0gzbqct']),
1378
+ model: 'TS0601_dimmer_knob',
1379
+ vendor: 'TuYa',
1380
+ description: 'Zigbee smart knob dimmer',
1381
+ fromZigbee: [tuya.fz.datapoints],
1382
+ toZigbee: [tuya.tz.datapoints],
1383
+ configure: tuya.configureMagicPacket,
1384
+ exposes: [tuya.exposes.lightBrightness().withMinBrightness().setAccess('min_brightness', ea.STATE_SET), tuya.exposes.lightType(),
1385
+ tuya.exposes.indicatorModeNoneRelayPos()],
1386
+ meta: {
1387
+ tuyaDatapoints: [
1388
+ [1, 'state', tuya.valueConverter.onOff, {skip: tuya.skip.stateOnAndBrightnessPresent}],
1389
+ [2, 'brightness', tuya.valueConverter.scale0_254to0_1000],
1390
+ [3, 'min_brightness', tuya.valueConverter.scale0_254to0_1000],
1391
+ [4, 'light_type', tuya.valueConverter.lightType],
1392
+ [21, 'indicator_mode', tuya.valueConverterBasic.lookup({0: 'none', 1: 'relay', 2: 'pos'})],
1393
+ ],
1394
+ },
1395
+ whiteLabel: [
1396
+ {vendor: 'Moes', model: 'WS-SY-EURD'},
1397
+ {vendor: 'Moes', model: 'WS-SY-EURD-WH-MS'},
1398
+ ],
1399
+ },
1400
+ {
1401
+ fingerprint: [{modelID: 'TS011F', manufacturerName: '_TZ3000_oiymh3qu'}],
1402
+ model: 'TS011F_socket_module',
1403
+ vendor: 'TuYa',
1404
+ description: 'Socket module',
1405
+ extend: tuya.extend.switch(),
1406
+ whiteLabel: [{vendor: 'LoraTap', model: 'RR400ZB'}, {vendor: 'LoraTap', model: 'SP400ZB'}],
1407
+ configure: async (device, coordinatorEndpoint, logger) => {
1408
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
1409
+ const endpoint = device.getEndpoint(1);
1410
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
1411
+ await reporting.onOff(endpoint);
1412
+ },
1413
+ },
1414
+ {
1415
+ fingerprint: [{modelID: 'TS011F', manufacturerName: '_TZ3000_wxtp7c5y'},
1416
+ {modelID: 'TS011F', manufacturerName: '_TYZB01_mtunwanm'},
1417
+ {modelID: 'TS011F', manufacturerName: '_TZ3000_o1jzcxou'}],
1418
+ model: 'TS011F_wall_outlet',
1419
+ vendor: 'TuYa',
1420
+ description: 'In-wall outlet',
1421
+ extend: tuya.extend.switch(),
1422
+ whiteLabel: [{vendor: 'Teekar', model: 'SWP86-01OG'},
1423
+ {vendor: 'ClickSmart+', model: 'CMA30035'},
1424
+ {vendor: 'BSEED', model: 'Zigbee Socket'}],
1425
+ },
1426
+ {
1427
+ fingerprint: [{modelID: 'isltm67\u0000', manufacturerName: '_TYST11_pisltm67'},
1428
+ {modelID: 'TS0601', manufacturerName: '_TZE200_pisltm67'}],
1429
+ model: 'S-LUX-ZB',
1430
+ vendor: 'TuYa',
1431
+ description: 'Light sensor',
1432
+ fromZigbee: [fz.SLUXZB],
1433
+ toZigbee: [],
1434
+ configure: async (device, coordinatorEndpoint, logger) => {
1435
+ const endpoint = device.getEndpoint(1);
1436
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genBasic']);
1437
+ },
1438
+ exposes: [e.battery(), e.illuminance_lux(), e.linkquality(),
1439
+ exposes.enum('brightness_level', ea.STATE, ['LOW', 'MEDIUM', 'HIGH'])],
1440
+ },
1441
+ {
1442
+ zigbeeModel: ['TS130F'],
1443
+ model: 'TS130F',
1444
+ vendor: 'TuYa',
1445
+ description: 'Curtain/blind switch',
1446
+ fromZigbee: [fz.cover_position_tilt, tuya.fz.backlight_mode_low_medium_high, fz.tuya_cover_options],
1447
+ toZigbee: [tz.cover_state, tz.cover_position_tilt, tz.tuya_cover_calibration, tz.tuya_cover_reversal,
1448
+ tuya.tz.backlight_indicator_mode_1],
1449
+ meta: {coverInverted: true},
1450
+ whiteLabel: [{vendor: 'LoraTap', model: 'SC400'}],
1451
+ exposes: [e.cover_position(), exposes.enum('moving', ea.STATE, ['UP', 'STOP', 'DOWN']),
1452
+ exposes.binary('calibration', ea.ALL, 'ON', 'OFF'), exposes.binary('motor_reversal', ea.ALL, 'ON', 'OFF'),
1453
+ exposes.enum('backlight_mode', ea.ALL, ['LOW', 'MEDIUM', 'HIGH']),
1454
+ exposes.numeric('calibration_time', ea.STATE).withUnit('S').withDescription('Calibration time')],
1455
+ },
1456
+ {
1457
+ zigbeeModel: ['qnazj70', 'kjintbl'],
1458
+ fingerprint: [
1459
+ {modelID: 'TS0601', manufacturerName: '_TZE200_wunufsil'},
1460
+ {modelID: 'TS0601', manufacturerName: '_TZE200_vhy3iakz'},
1461
+ {modelID: 'TS0601', manufacturerName: '_TZE200_oisqyl4o'},
1462
+ {modelID: 'TS0601', manufacturerName: '_TZ3000_uim07oem'},
1463
+ {modelID: 'TS0601', manufacturerName: '_TZE200_js3mgbjb'},
1464
+ {modelID: 'TS0601', manufacturerName: '_TZE200_7deq70b8'},
1465
+ ],
1466
+ model: 'TS0601_switch',
1467
+ vendor: 'TuYa',
1468
+ description: '1, 2, 3 or 4 gang switch',
1469
+ exposes: [e.switch().withEndpoint('l1').setAccess('state', ea.STATE_SET),
1470
+ e.switch().withEndpoint('l2').setAccess('state', ea.STATE_SET),
1471
+ e.switch().withEndpoint('l3').setAccess('state', ea.STATE_SET), e.switch().withEndpoint('l4').setAccess('state', ea.STATE_SET)],
1472
+ fromZigbee: [fz.ignore_basic_report, fz.tuya_switch],
1473
+ toZigbee: [tz.tuya_switch_state],
1474
+ meta: {multiEndpoint: true},
1475
+ whiteLabel: [
1476
+ {vendor: 'Norklmes', model: 'MKS-CM-W5'},
1477
+ {vendor: 'Somgoms', model: 'ZSQB-SMB-ZB'},
1478
+ {vendor: 'Moes', model: 'WS-EUB1-ZG'},
1479
+ {vendor: 'AVATTO', model: 'ZGB-WS-EU'},
1480
+ ],
1481
+ configure: async (device, coordinatorEndpoint, logger) => {
1482
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
1483
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
1484
+ if (device.getEndpoint(2)) await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
1485
+ if (device.getEndpoint(3)) await reporting.bind(device.getEndpoint(3), coordinatorEndpoint, ['genOnOff']);
1486
+ if (device.getEndpoint(4)) await reporting.bind(device.getEndpoint(4), coordinatorEndpoint, ['genOnOff']);
1487
+ },
1488
+ endpoint: (device) => {
1489
+ // Endpoint selection is made in tuya_switch_state
1490
+ return {'l1': 1, 'l2': 1, 'l3': 1, 'l4': 1};
1491
+ },
1492
+ },
1493
+ {
1494
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE200_aqnazj70', '_TZE200_k6jhsr0q', '_TZE200_di3tfv5b', '_TZE200_mexisfik']),
1495
+ model: 'TS0601_switch_4_gang',
1496
+ vendor: 'TuYa',
1497
+ description: '4 gang switch',
1498
+ exposes: [e.switch().withEndpoint('l1').setAccess('state', ea.STATE_SET),
1499
+ e.switch().withEndpoint('l2').setAccess('state', ea.STATE_SET),
1500
+ e.switch().withEndpoint('l3').setAccess('state', ea.STATE_SET),
1501
+ e.switch().withEndpoint('l4').setAccess('state', ea.STATE_SET)],
1502
+ fromZigbee: [fz.ignore_basic_report, fz.tuya_switch],
1503
+ toZigbee: [tz.tuya_switch_state],
1504
+ meta: {multiEndpoint: true},
1505
+ endpoint: (device) => {
1506
+ // Endpoint selection is made in tuya_switch_state
1507
+ return {'l1': 1, 'l2': 1, 'l3': 1, 'l4': 1};
1508
+ },
1509
+ },
1510
+ {
1511
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE200_jwsjbxjs']),
1512
+ model: 'TS0601_switch_5_gang',
1513
+ vendor: 'TuYa',
1514
+ description: '5 gang switch',
1515
+ fromZigbee: [tuya.fz.datapoints],
1516
+ toZigbee: [tuya.tz.datapoints],
1517
+ configure: tuya.configureMagicPacket,
1518
+ exposes: [
1519
+ tuya.exposes.switch().withEndpoint('l1'),
1520
+ tuya.exposes.switch().withEndpoint('l2'),
1521
+ tuya.exposes.switch().withEndpoint('l3'),
1522
+ tuya.exposes.switch().withEndpoint('l4'),
1523
+ tuya.exposes.switch().withEndpoint('l5'),
1524
+ ],
1525
+ endpoint: (device) => {
1526
+ return {'l1': 1, 'l2': 1, 'l3': 1, 'l4': 1, 'l5': 1};
1527
+ },
1528
+ meta: {
1529
+ multiEndpoint: true,
1530
+ tuyaDatapoints: [
1531
+ [1, 'state_l1', tuya.valueConverter.onOff],
1532
+ [2, 'state_l2', tuya.valueConverter.onOff],
1533
+ [3, 'state_l3', tuya.valueConverter.onOff],
1534
+ [4, 'state_l4', tuya.valueConverter.onOff],
1535
+ [5, 'state_l5', tuya.valueConverter.onOff],
1536
+ ],
1537
+ },
1538
+ },
1539
+ {
1540
+ fingerprint: [
1541
+ {modelID: 'TS0601', manufacturerName: '_TZE200_nkjintbl'},
1542
+ {modelID: 'TS0601', manufacturerName: '_TZE200_ji1gn7rw'},
1543
+ {modelID: 'TS0601', manufacturerName: '_TZE200_3t91nb6k'},
1544
+ ],
1545
+ model: 'TS0601_switch_2_gang',
1546
+ vendor: 'TuYa',
1547
+ description: '2 gang switch',
1548
+ exposes: [e.switch().withEndpoint('l1').setAccess('state', ea.STATE_SET),
1549
+ e.switch().withEndpoint('l2').setAccess('state', ea.STATE_SET)],
1550
+ fromZigbee: [fz.ignore_basic_report, fz.tuya_switch],
1551
+ toZigbee: [tz.tuya_switch_state],
1552
+ meta: {multiEndpoint: true},
1553
+ configure: async (device, coordinatorEndpoint, logger) => {
1554
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
1555
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
1556
+ if (device.getEndpoint(2)) await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
1557
+ },
1558
+ endpoint: (device) => {
1559
+ // Endpoint selection is made in tuya_switch_state
1560
+ return {'l1': 1, 'l2': 1};
1561
+ },
1562
+ },
1563
+ {
1564
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_kyfqmmyl'},
1565
+ {modelID: 'TS0601', manufacturerName: '_TZE200_2hf7x9n3'},
1566
+ {modelID: 'TS0601', manufacturerName: '_TZE200_bynnczcb'},
1567
+ {modelID: 'TS0601', manufacturerName: '_TZE200_atpwqgml'}],
1568
+ model: 'TS0601_switch_3_gang',
1569
+ vendor: 'TuYa',
1570
+ description: '3 gang switch',
1571
+ whiteLabel: [{vendor: 'NOVADIGITAL', model: 'WS-US-ZB', description: 'Interruptor touch Zigbee 3 Teclas'}],
1572
+ exposes: [e.switch().withEndpoint('l1').setAccess('state', ea.STATE_SET),
1573
+ e.switch().withEndpoint('l2').setAccess('state', ea.STATE_SET),
1574
+ e.switch().withEndpoint('l3').setAccess('state', ea.STATE_SET)],
1575
+ fromZigbee: [fz.ignore_basic_report, fz.tuya_switch],
1576
+ toZigbee: [tz.tuya_switch_state],
1577
+ meta: {multiEndpoint: true},
1578
+ configure: async (device, coordinatorEndpoint, logger) => {
1579
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
1580
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
1581
+ await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
1582
+ },
1583
+ endpoint: (device) => {
1584
+ // Endpoint selection is made in tuya_switch_state
1585
+ return {'l1': 1, 'l2': 1, 'l3': 1};
1586
+ },
1587
+ },
1588
+ {
1589
+ fingerprint: tuya.fingerprint('TS0215A', ['_TZ3000_4fsgukof', '_TZ3000_wr2ucaj9', '_TZ3000_zsh6uat3', '_TZ3000_tj4pwzzm',
1590
+ '_TZ3000_2izubafb', '_TZ3000_pkfazisv']),
1591
+ model: 'TS0215A_sos',
1592
+ vendor: 'TuYa',
1593
+ description: 'SOS button',
1594
+ fromZigbee: [fz.command_emergency, fz.battery],
1595
+ exposes: [e.battery(), e.battery_voltage(), e.action(['emergency'])],
1596
+ toZigbee: [],
1597
+ configure: async (device, coordinatorEndpoint, logger) => {
1598
+ const endpoint = device.getEndpoint(1);
1599
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'genTime', 'genBasic', 'ssIasAce', 'ssIasZone']);
1600
+ await reporting.batteryPercentageRemaining(endpoint);
1601
+ await reporting.batteryVoltage(endpoint);
1602
+ },
1603
+ },
1604
+ {
1605
+ fingerprint: [{modelID: 'TS0215A', manufacturerName: '_TZ3000_p6ju8myv'},
1606
+ {modelID: 'TS0215A', manufacturerName: '_TZ3000_0zrccfgx'},
1607
+ {modelID: 'TS0215A', manufacturerName: '_TZ3000_fsiepnrh'},
1608
+ {modelID: 'TS0215A', manufacturerName: '_TZ3000_ug1vtuzn'}],
1609
+ model: 'TS0215A_remote',
1610
+ vendor: 'TuYa',
1611
+ description: 'Security remote control',
1612
+ fromZigbee: [fz.command_arm, fz.command_emergency, fz.battery],
1613
+ exposes: [e.battery(), e.action(['disarm', 'arm_day_zones', 'arm_night_zones', 'arm_all_zones', 'exit_delay', 'emergency'])],
1614
+ toZigbee: [],
1615
+ whiteLabel: [{vendor: 'Woox', model: 'R7054'}, {vendor: 'Nedis', model: 'ZBRC10WT'}],
1616
+ configure: async (device, coordinatorEndpoint, logger) => {
1617
+ const endpoint = device.getEndpoint(1);
1618
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'genTime', 'genBasic', 'ssIasAce', 'ssIasZone']);
1619
+ },
1620
+ },
1621
+ {
1622
+ fingerprint: [{modelID: 'TS0503A', manufacturerName: '_TZ3000_obacbukl'}],
1623
+ model: 'TS0503A',
1624
+ vendor: 'TuYa',
1625
+ description: 'Led strip controller',
1626
+ extend: tuya.extend.light_onoff_brightness_color(),
1627
+ },
1628
+ {
1629
+ zigbeeModel: ['TS0503A'],
1630
+ model: 'TYZS1L',
1631
+ vendor: 'TuYa',
1632
+ description: 'Led strip controller HSB',
1633
+ exposes: [e.light_colorhs()],
1634
+ fromZigbee: [fz.on_off, fz.tuya_led_controller],
1635
+ toZigbee: [tz.tuya_led_controller, tz.ignore_transition, tz.ignore_rate],
1636
+ },
1637
+ {
1638
+ zigbeeModel: ['TS0502A'],
1639
+ model: 'TS0502A',
1640
+ vendor: 'TuYa',
1641
+ description: 'Light controller',
1642
+ extend: tuya.extend.light_onoff_brightness_colortemp(),
1643
+ },
1644
+ {
1645
+ zigbeeModel: ['TS0502B'],
1646
+ model: 'TS0502B',
1647
+ vendor: 'TuYa',
1648
+ description: 'Light controller',
1649
+ whiteLabel: [
1650
+ {vendor: 'Mercator Ikuü', model: 'SMI7040', description: 'Ford Batten Light'},
1651
+ {vendor: 'Mercator Ikuü', model: 'SMD9300', description: 'Donovan Panel Light'},
1652
+ ],
1653
+ extend: tuya.extend.light_onoff_brightness_colortemp({colorTempRange: [153, 500]}),
1654
+ },
1655
+ {
1656
+ zigbeeModel: ['TS0504A'],
1657
+ model: 'TS0504A',
1658
+ vendor: 'TuYa',
1659
+ description: 'RGBW LED controller',
1660
+ extend: tuya.extend.light_onoff_brightness_colortemp_color(),
1661
+ },
1662
+ {
1663
+ fingerprint: [{modelID: 'TS0505A', manufacturerName: '_TZ3000_sosdczdl'}],
1664
+ model: 'TS0505A_led',
1665
+ vendor: 'TuYa',
1666
+ description: 'RGB+CCT LED',
1667
+ toZigbee: [tz.on_off, tz.tuya_led_control],
1668
+ fromZigbee: [fz.on_off, fz.tuya_led_controller, fz.brightness, fz.ignore_basic_report],
1669
+ exposes: [e.light_brightness_colortemp_colorhs([153, 500]).removeFeature('color_temp_startup')],
1670
+ },
1671
+ {
1672
+ zigbeeModel: ['TS0505A'],
1673
+ model: 'TS0505A',
1674
+ vendor: 'TuYa',
1675
+ description: 'RGB+CCT light controller',
1676
+ extend: tuya.extend.light_onoff_brightness_colortemp_color(),
1677
+ },
1678
+ {
1679
+ fingerprint: [{manufacturerName: '_TZ2000_a476raq2'}],
1680
+ zigbeeModel: ['TS0201', 'SNTZ003'],
1681
+ model: 'TS0201',
1682
+ vendor: 'TuYa',
1683
+ description: 'Temperature & humidity sensor with display',
1684
+ whiteLabel: [{vendor: 'BlitzWolf', model: 'BW-IS4'}],
1685
+ fromZigbee: [fzLocal.TS0201_battery, fz.temperature, fzLocal.TS0201_humidity],
1686
+ toZigbee: [],
1687
+ exposes: [e.battery(), e.temperature(), e.humidity(), e.battery_voltage()],
1688
+ configure: tuya.configureMagicPacket,
1689
+ },
1690
+ {
1691
+ fingerprint: [
1692
+ {modelID: 'TS0201', manufacturerName: '_TZ3000_bguser20'},
1693
+ {modelID: 'TS0201', manufacturerName: '_TZ3000_fllyghyj'},
1694
+ {modelID: 'TS0201', manufacturerName: '_TZ3000_yd2e749y'},
1695
+ {modelID: 'TS0201', manufacturerName: '_TZ3000_6uzkisv2'},
1696
+ {modelID: 'TS0201', manufacturerName: '_TZ3000_xr3htd96'},
1697
+ ],
1698
+ model: 'WSD500A',
1699
+ vendor: 'TuYa',
1700
+ description: 'Temperature & humidity sensor',
1701
+ fromZigbee: [fzLocal.TS0201_battery, fz.temperature, fz.humidity],
1702
+ toZigbee: [],
1703
+ exposes: [e.battery(), e.temperature(), e.humidity(), e.battery_voltage()],
1704
+ configure: tuya.configureMagicPacket,
1705
+ },
1706
+ {
1707
+ fingerprint: tuya.fingerprint('TS0201', ['_TZ3000_dowj6gyi', '_TZ3000_8ybe88nf']),
1708
+ model: 'IH-K009',
1709
+ vendor: 'TuYa',
1710
+ description: 'Temperature & humidity sensor',
1711
+ fromZigbee: [fzLocal.TS0201_battery, fz.temperature, fz.humidity],
1712
+ toZigbee: [],
1713
+ exposes: [e.battery(), e.temperature(), e.humidity(), e.battery_voltage()],
1714
+ configure: tuya.configureMagicPacket,
1715
+ },
1716
+ {
1717
+ fingerprint: tuya.fingerprint('SM0201', ['_TYZB01_cbiezpds', '_TYZB01_zqvwka4k']),
1718
+ model: 'SM0201',
1719
+ vendor: 'TuYa',
1720
+ description: 'Temperature & humidity sensor with LED screen',
1721
+ fromZigbee: [fz.battery, fz.temperature, fz.humidity],
1722
+ toZigbee: [],
1723
+ exposes: [e.battery(), e.temperature(), e.humidity(), e.battery_voltage()],
1724
+ },
1725
+ {
1726
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE200_yjjdcqsq']),
1727
+ model: 'ZTH01',
1728
+ vendor: 'TuYa',
1729
+ description: 'Temperature and humidity sensor',
1730
+ fromZigbee: [tuya.fz.datapoints, tuya.fz.gateway_connection_status],
1731
+ toZigbee: [tuya.tz.datapoints],
1732
+ configure: tuya.configureMagicPacket,
1733
+ exposes: [e.temperature(), e.humidity(), tuya.exposes.batteryState(), e.battery_low()],
1734
+ meta: {
1735
+ tuyaDatapoints: [
1736
+ [1, 'temperature', tuya.valueConverter.divideBy10],
1737
+ [2, 'humidity', tuya.valueConverter.raw],
1738
+ [3, 'battery_state', tuya.valueConverter.batteryState],
1739
+ // [9, 'temperature_unit', tuya.valueConverter.raw], This DP is not properly supported by the device
1740
+ ],
1741
+ },
1742
+ },
1743
+ {
1744
+ fingerprint: [{modelID: 'TS011F', manufacturerName: '_TZ3000_3zofvcaa'}],
1745
+ model: 'TS011F_2_gang_2_usb_wall',
1746
+ vendor: 'TuYa',
1747
+ description: '2 gang 2 usb wall outlet',
1748
+ extend: tuya.extend.switch({backlightModeLowMediumHigh: true, endpoints: ['l1', 'l2', 'l3', 'l4']}),
1749
+ endpoint: () => {
1750
+ return {'l1': 1, 'l2': 2, 'l3': 3, 'l4': 4};
1751
+ },
1752
+ meta: {multiEndpoint: true},
1753
+ configure: async (device, coordinatorEndpoint, logger) => {
1754
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
1755
+ for (const endpointID of [1, 2, 3, 4]) {
1756
+ const endpoint = device.getEndpoint(endpointID);
1757
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
1758
+ await reporting.onOff(endpoint);
1759
+ }
1760
+ },
1761
+ },
1762
+ {
1763
+ zigbeeModel: ['TS0041'],
1764
+ fingerprint: [{manufacturerName: '_TZ3000_tk3s5tyg'}],
1765
+ model: 'TS0041',
1766
+ vendor: 'TuYa',
1767
+ description: 'Wireless switch with 1 button',
1768
+ whiteLabel: [{vendor: 'Smart9', model: 'S9TSZGB'}, {vendor: 'Lonsonho', model: 'TS0041'}, {vendor: 'Benexmart', model: 'ZM-sui1'}],
1769
+ exposes: [e.battery(), e.action(['single', 'double', 'hold'])],
1770
+ fromZigbee: [fz.tuya_on_off_action, fz.battery],
1771
+ toZigbee: [],
1772
+ configure: tuya.configureMagicPacket,
1773
+ /*
1774
+ * reporting.batteryPercentageRemaining removed as it was causing devices to fall of the network
1775
+ * every 1 hour, with light flashing when it happened, extremely short battery life, 2 presses for
1776
+ * action to register: https://github.com/Koenkk/zigbee2mqtt/issues/8072
1777
+ * Initially wrapped in a try catch: https://github.com/Koenkk/zigbee2mqtt/issues/6313
1778
+ */
1779
+ },
1780
+ {
1781
+ zigbeeModel: ['TS0042'],
1782
+ model: 'TS0042',
1783
+ vendor: 'TuYa',
1784
+ description: 'Wireless switch with 2 buttons',
1785
+ whiteLabel: [{vendor: 'Smart9', model: 'S9TSZGB'}, {vendor: 'Lonsonho', model: 'TS0042'},
1786
+ {vendor: 'ClickSmart+', model: 'CSPGM2075PW'}],
1787
+ exposes: [e.battery(), e.action(['1_single', '1_double', '1_hold', '2_single', '2_double', '2_hold'])],
1788
+ fromZigbee: [fz.tuya_on_off_action, fz.battery],
1789
+ toZigbee: [],
1790
+ configure: tuya.configureMagicPacket,
1791
+ /*
1792
+ * reporting.batteryPercentageRemaining removed as it was causing devices to fall of the network
1793
+ * every 1 hour, with light flashing when it happened, extremely short battery life, 2 presses for
1794
+ * action to register: https://github.com/Koenkk/zigbee2mqtt/issues/8072
1795
+ * Initially wrapped in a try catch: https://github.com/Koenkk/zigbee2mqtt/issues/6313
1796
+ */
1797
+ },
1798
+ {
1799
+ zigbeeModel: ['TS0043'],
1800
+ model: 'TS0043',
1801
+ vendor: 'TuYa',
1802
+ description: 'Wireless switch with 3 buttons',
1803
+ whiteLabel: [{vendor: 'Smart9', model: 'S9TSZGB'}, {vendor: 'Lonsonho', model: 'TS0043'}, {vendor: 'LoraTap', model: 'SS600ZB'}],
1804
+ exposes: [e.battery(),
1805
+ e.action(['1_single', '1_double', '1_hold', '2_single', '2_double', '2_hold', '3_single', '3_double', '3_hold'])],
1806
+ fromZigbee: [fz.tuya_on_off_action, fz.battery],
1807
+ toZigbee: [],
1808
+ configure: tuya.configureMagicPacket,
1809
+ /*
1810
+ * reporting.batteryPercentageRemaining removed as it was causing devices to fall of the network
1811
+ * every 1 hour, with light flashing when it happened, extremely short battery life, 2 presses for
1812
+ * action to register: https://github.com/Koenkk/zigbee2mqtt/issues/8072
1813
+ * Initially wrapped in a try catch: https://github.com/Koenkk/zigbee2mqtt/issues/6313
1814
+ */
1815
+ },
1816
+ {
1817
+ zigbeeModel: ['TS0044'],
1818
+ model: 'TS0044',
1819
+ vendor: 'TuYa',
1820
+ description: 'Wireless switch with 4 buttons',
1821
+ whiteLabel: [{vendor: 'Lonsonho', model: 'TS0044'}, {vendor: 'Haozee', model: 'ESW-OZAA-EU'},
1822
+ {vendor: 'LoraTap', model: 'SS6400ZB'}, {vendor: 'Moes', model: 'ZT-SY-EU-G-4S-WH-MS'}],
1823
+ fromZigbee: [fz.tuya_on_off_action, fz.battery],
1824
+ exposes: [e.battery(), e.action(['1_single', '1_double', '1_hold', '2_single', '2_double', '2_hold',
1825
+ '3_single', '3_double', '3_hold', '4_single', '4_double', '4_hold'])],
1826
+ toZigbee: [],
1827
+ configure: tuya.configureMagicPacket,
1828
+ /*
1829
+ * reporting.batteryPercentageRemaining removed as it was causing devices to fall of the network
1830
+ * every 1 hour, with light flashing when it happened, extremely short battery life, 2 presses for
1831
+ * action to register: https://github.com/Koenkk/zigbee2mqtt/issues/8072
1832
+ * Initially wrapped in a try catch: https://github.com/Koenkk/zigbee2mqtt/issues/6313
1833
+ */
1834
+ },
1835
+ {
1836
+ fingerprint: tuya.fingerprint('TS004F', ['_TZ3000_xabckq1v', '_TZ3000_czuyt8lz']),
1837
+ model: 'TS004F',
1838
+ vendor: 'TuYa',
1839
+ description: 'Wireless switch with 4 buttons',
1840
+ exposes: [e.battery(), e.action(['1_single', '1_double', '1_hold', '2_single', '2_double', '2_hold',
1841
+ '3_single', '3_double', '3_hold', '4_single', '4_double', '4_hold'])],
1842
+ fromZigbee: [fz.battery, fz.tuya_on_off_action],
1843
+ toZigbee: [tz.tuya_operation_mode],
1844
+ configure: async (device, coordinatorEndpoint, logger) => {
1845
+ const endpoint = device.getEndpoint(1);
1846
+ await endpoint.read('genBasic', [0x0004, 0x000, 0x0001, 0x0005, 0x0007, 0xfffe]);
1847
+ await endpoint.write('genOnOff', {'tuyaOperationMode': 1});
1848
+ await endpoint.read('genOnOff', ['tuyaOperationMode']);
1849
+ try {
1850
+ await endpoint.read(0xE001, [0xD011]);
1851
+ } catch (err) {/* do nothing */}
1852
+ await endpoint.read('genPowerCfg', ['batteryVoltage', 'batteryPercentageRemaining']);
1853
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
1854
+ for (const ep of [1, 2, 3, 4]) {
1855
+ // Not all variants have all endpoints
1856
+ // https://github.com/Koenkk/zigbee2mqtt/issues/15730#issuecomment-1364498358
1857
+ if (device.getEndpoint(ep)) {
1858
+ await reporting.bind(device.getEndpoint(ep), coordinatorEndpoint, ['genOnOff']);
1859
+ }
1860
+ }
1861
+ },
1862
+ },
1863
+ {
1864
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_qq9mpfhw'}],
1865
+ model: 'TS0601_water_sensor',
1866
+ vendor: 'TuYa',
1867
+ description: 'Water leak sensor',
1868
+ fromZigbee: [fz.tuya_water_leak, fz.ignore_basic_report],
1869
+ exposes: [e.water_leak()],
1870
+ toZigbee: [],
1871
+ whiteLabel: [{vendor: 'Neo', model: 'NAS-WS02B0'}],
1872
+ },
1873
+ {
1874
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_jthf7vb6'}],
1875
+ model: 'WLS-100z',
1876
+ vendor: 'TuYa',
1877
+ description: 'Water leak sensor',
1878
+ fromZigbee: [fz.ignore_basic_report, fz.ignore_tuya_raw, fz.wls100z_water_leak],
1879
+ toZigbee: [],
1880
+ onEvent: tuya.onEventSetTime,
1881
+ configure: async (device, coordinatorEndpoint, logger) => {
1882
+ const endpoint = device.getEndpoint(1);
1883
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genBasic']);
1884
+ },
1885
+ exposes: [e.battery(), e.water_leak()],
1886
+ },
1887
+ {
1888
+ fingerprint: tuya.fingerprint('TS0001', ['_TZ3000_xkap8wtb', '_TZ3000_qnejhcsu', '_TZ3000_x3ewpzyr',
1889
+ '_TZ3000_mkhkxx1p', '_TZ3000_tgddllx4']),
1890
+ model: 'TS0001_power',
1891
+ description: 'Switch with power monitoring',
1892
+ vendor: 'TuYa',
1893
+ fromZigbee: [fz.on_off, fz.electrical_measurement, fz.metering, fz.ignore_basic_report,
1894
+ tuya.fz.power_outage_memory, tuya.fz.switch_type],
1895
+ toZigbee: [tz.on_off, tuya.tz.power_on_behavior_1, tuya.tz.switch_type],
1896
+ configure: async (device, coordinatorEndpoint, logger) => {
1897
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
1898
+ const endpoint = device.getEndpoint(1);
1899
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement', 'seMetering']);
1900
+ await reporting.rmsVoltage(endpoint, {change: 5});
1901
+ await reporting.rmsCurrent(endpoint, {change: 50});
1902
+ await reporting.activePower(endpoint, {change: 10});
1903
+ await reporting.currentSummDelivered(endpoint);
1904
+ endpoint.saveClusterAttributeKeyValue('haElectricalMeasurement', {acCurrentDivisor: 1000, acCurrentMultiplier: 1});
1905
+ endpoint.saveClusterAttributeKeyValue('seMetering', {divisor: 100, multiplier: 1});
1906
+ device.save();
1907
+ },
1908
+ exposes: [e.switch(), e.power(), e.current(), e.voltage(), e.energy(), tuya.exposes.switchType(),
1909
+ exposes.enum('power_outage_memory', ea.ALL, ['on', 'off', 'restore']).withDescription('Recover state after power outage')],
1910
+ },
1911
+ {
1912
+ fingerprint: [{modelID: 'TS0002', manufacturerName: '_TZ3000_irrmjcgi'}],
1913
+ model: 'TS0002_power',
1914
+ vendor: 'TuYa',
1915
+ description: '2 gang switch with power monitoring',
1916
+ extend: tuya.extend.switch({switchType: true, endpoints: ['l1', 'l2'], electricalMeasurements: true}),
1917
+ endpoint: (device) => {
1918
+ return {'l1': 1, 'l2': 2};
1919
+ },
1920
+ meta: {multiEndpoint: true, multiEndpointSkip: ['energy', 'current', 'voltage', 'power']},
1921
+ configure: async (device, coordinatorEndpoint, logger) => {
1922
+ const endpoint = device.getEndpoint(1);
1923
+ await endpoint.read('genBasic', ['manufacturerName', 'zclVersion', 'appVersion', 'modelId', 'powerSource', 0xfffe]);
1924
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement', 'seMetering']);
1925
+ await reporting.rmsVoltage(endpoint, {change: 5});
1926
+ await reporting.rmsCurrent(endpoint, {change: 50});
1927
+ await reporting.activePower(endpoint, {change: 10});
1928
+ await reporting.currentSummDelivered(endpoint);
1929
+ endpoint.saveClusterAttributeKeyValue('haElectricalMeasurement', {acCurrentDivisor: 1000, acCurrentMultiplier: 1});
1930
+ endpoint.saveClusterAttributeKeyValue('seMetering', {divisor: 100, multiplier: 1});
1931
+ device.save();
1932
+ await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
1933
+ },
1934
+ },
1935
+ {
1936
+ fingerprint: tuya.fingerprint('TS000F', ['_TZ3000_xkap8wtb']),
1937
+ model: 'TS000F_power',
1938
+ description: 'Switch with power monitoring',
1939
+ vendor: 'TuYa',
1940
+ fromZigbee: [fz.on_off, fz.electrical_measurement, fz.metering, fz.ignore_basic_report, tuya.fz.power_on_behavior_1,
1941
+ tuya.fz.switch_type],
1942
+ toZigbee: [tz.on_off, tuya.tz.power_on_behavior_1, tuya.tz.switch_type],
1943
+ configure: async (device, coordinatorEndpoint, logger) => {
1944
+ const endpoint = device.getEndpoint(1);
1945
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
1946
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement', 'seMetering']);
1947
+ await reporting.rmsVoltage(endpoint, {change: 5});
1948
+ await reporting.rmsCurrent(endpoint, {change: 50});
1949
+ await reporting.currentSummDelivered(endpoint);
1950
+ endpoint.saveClusterAttributeKeyValue('seMetering', {divisor: 100, multiplier: 1});
1951
+ device.save();
1952
+ },
1953
+ whiteLabel: [{vendor: 'Aubess', model: 'WHD02'}],
1954
+ exposes: [e.switch(), e.power(), e.current(), e.voltage(), e.energy(), e.power_on_behavior(),
1955
+ tuya.exposes.switchType()],
1956
+ },
1957
+ {
1958
+ zigbeeModel: ['TS0001'],
1959
+ model: 'TS0001',
1960
+ vendor: 'TuYa',
1961
+ description: '1 gang switch',
1962
+ extend: tuya.extend.switch(),
1963
+ whiteLabel: [{vendor: 'CR Smart Home', model: 'TS0001', description: 'Valve control'}, {vendor: 'Lonsonho', model: 'X701'},
1964
+ {vendor: 'Bandi', model: 'BDS03G1'}],
1965
+ configure: async (device, coordinatorEndpoint, logger) => {
1966
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
1967
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
1968
+ },
1969
+ },
1970
+ {
1971
+ zigbeeModel: ['TS0002'],
1972
+ model: 'TS0002',
1973
+ vendor: 'TuYa',
1974
+ description: '2 gang switch',
1975
+ whiteLabel: [{vendor: 'Zemismart', model: 'ZM-CSW002-D_switch'}, {vendor: 'Lonsonho', model: 'X702'},
1976
+ {vendor: 'Avatto', model: 'ZTS02'}],
1977
+ extend: tuya.extend.switch(),
1978
+ exposes: [e.switch().withEndpoint('l1'), e.switch().withEndpoint('l2')],
1979
+ endpoint: (device) => {
1980
+ return {'l1': 1, 'l2': 2};
1981
+ },
1982
+ meta: {multiEndpoint: true},
1983
+ configure: async (device, coordinatorEndpoint, logger) => {
1984
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
1985
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
1986
+ await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
1987
+ },
1988
+ },
1989
+ {
1990
+ fingerprint: tuya.fingerprint('TS0001', ['_TZ3000_tqlv4ug4', '_TZ3000_gjrubzje', '_TZ3000_tygpxwqa']),
1991
+ model: 'TS0001_switch_module',
1992
+ vendor: 'TuYa',
1993
+ description: '1 gang switch module',
1994
+ whiteLabel: [{vendor: 'OXT', model: 'SWTZ21'}],
1995
+ extend: tuya.extend.switch({switchType: true}),
1996
+ configure: async (device, coordinatorEndpoint, logger) => {
1997
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
1998
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
1999
+ },
2000
+ },
2001
+ {
2002
+ fingerprint: tuya.fingerprint('TS0002', ['_TZ3000_01gpyda5', '_TZ3000_bvrlqyj7', '_TZ3000_7ed9cqgi', '_TZ3000_zmy4lslw']),
2003
+ model: 'TS0002_switch_module',
2004
+ vendor: 'TuYa',
2005
+ description: '2 gang switch module',
2006
+ whiteLabel: [{vendor: 'OXT', model: 'SWTZ22'}],
2007
+ extend: tuya.extend.switch({switchType: true, endpoints: ['l1', 'l2']}),
2008
+ endpoint: (device) => {
2009
+ return {'l1': 1, 'l2': 2};
2010
+ },
2011
+ meta: {multiEndpoint: true},
2012
+ configure: async (device, coordinatorEndpoint, logger) => {
2013
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
2014
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
2015
+ await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
2016
+ },
2017
+ },
2018
+ {
2019
+ fingerprint: tuya.fingerprint('TS0002', ['_TZ3000_fisb3ajo', '_TZ3000_5gey1ohx']),
2020
+ model: 'TS0002_switch_module_2',
2021
+ vendor: 'TuYa',
2022
+ description: '2 gang switch module',
2023
+ extend: tuya.extend.switch({endpoints: ['l1', 'l2']}),
2024
+ endpoint: (device) => {
2025
+ return {'l1': 1, 'l2': 2};
2026
+ },
2027
+ meta: {multiEndpoint: true},
2028
+ configure: async (device, coordinatorEndpoint, logger) => {
2029
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
2030
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
2031
+ await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
2032
+ },
2033
+ },
2034
+ {
2035
+ fingerprint: [{modelID: 'TS0003', manufacturerName: '_TZ3000_4o16jdca'}],
2036
+ model: 'TS0003_switch_module_2',
2037
+ vendor: 'TuYa',
2038
+ description: '3 gang switch module',
2039
+ extend: tuya.extend.switch({endpoints: ['l1', 'l2', 'l3']}),
2040
+ endpoint: (device) => {
2041
+ return {'l1': 1, 'l2': 2, 'l3': 3};
2042
+ },
2043
+ meta: {multiEndpoint: true},
2044
+ configure: async (device, coordinatorEndpoint, logger) => {
2045
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
2046
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
2047
+ await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
2048
+ await reporting.bind(device.getEndpoint(3), coordinatorEndpoint, ['genOnOff']);
2049
+ },
2050
+ },
2051
+ {
2052
+ fingerprint: tuya.fingerprint('TS0003', ['_TZ3000_vsasbzkf', '_TZ3000_odzoiovu']),
2053
+ model: 'TS0003_switch_module_1',
2054
+ vendor: 'TuYa',
2055
+ description: '3 gang switch module',
2056
+ whiteLabel: [{vendor: 'OXT', model: 'SWTZ23'}],
2057
+ extend: tuya.extend.switch({switchType: true, backlightModeOffOn: true, endpoints: ['l1', 'l2', 'l3']}),
2058
+ endpoint: (device) => {
2059
+ return {'l1': 1, 'l2': 2, 'l3': 3};
2060
+ },
2061
+ meta: {multiEndpoint: true},
2062
+ configure: async (device, coordinatorEndpoint, logger) => {
2063
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
2064
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
2065
+ await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
2066
+ await reporting.bind(device.getEndpoint(3), coordinatorEndpoint, ['genOnOff']);
2067
+ },
2068
+ },
2069
+ {
2070
+ fingerprint: [{modelID: 'TS0004', manufacturerName: '_TZ3000_ltt60asa'}],
2071
+ model: 'TS0004_switch_module',
2072
+ vendor: 'TuYa',
2073
+ description: '4 gang switch module',
2074
+ whiteLabel: [{vendor: 'OXT', model: 'SWTZ27'}],
2075
+ extend: tuya.extend.switch({switchType: true, endpoints: ['l1', 'l2', 'l3', 'l4']}),
2076
+ endpoint: (device) => {
2077
+ return {'l1': 1, 'l2': 2, 'l3': 3, 'l4': 4};
2078
+ },
2079
+ meta: {multiEndpoint: true},
2080
+ configure: async (device, coordinatorEndpoint, logger) => {
2081
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
2082
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
2083
+ await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
2084
+ await reporting.bind(device.getEndpoint(3), coordinatorEndpoint, ['genOnOff']);
2085
+ await reporting.bind(device.getEndpoint(4), coordinatorEndpoint, ['genOnOff']);
2086
+ },
2087
+ },
2088
+ {
2089
+ zigbeeModel: [
2090
+ 'owvfni3\u0000', 'owvfni3', 'u1rkty3', 'aabybja', // Curtain motors
2091
+ 'mcdj3aq', 'mcdj3aq\u0000', // Tubular motors
2092
+ ],
2093
+ fingerprint: [
2094
+ // Curtain motors:
2095
+ {modelID: 'TS0601', manufacturerName: '_TZE200_5zbp6j0u'},
2096
+ {modelID: 'TS0601', manufacturerName: '_TZE200_nkoabg8w'},
2097
+ {modelID: 'TS0601', manufacturerName: '_TZE200_xuzcvlku'},
2098
+ {modelID: 'TS0601', manufacturerName: '_TZE200_4vobcgd3'},
2099
+ {modelID: 'TS0601', manufacturerName: '_TZE200_nogaemzt'},
2100
+ {modelID: 'TS0601', manufacturerName: '_TZE200_r0jdjrvi'},
2101
+ {modelID: 'TS0601', manufacturerName: '_TZE200_pk0sfzvr'},
2102
+ {modelID: 'TS0601', manufacturerName: '_TZE200_fdtjuw7u'},
2103
+ {modelID: 'TS0601', manufacturerName: '_TZE200_zpzndjez'},
2104
+ {modelID: 'TS0601', manufacturerName: '_TZE200_wmcdj3aq'},
2105
+ {modelID: 'TS0601', manufacturerName: '_TZE200_cowvfni3'},
2106
+ {modelID: 'TS0601', manufacturerName: '_TZE200_rddyvrci'},
2107
+ {modelID: 'TS0601', manufacturerName: '_TZE200_nueqqe6k'},
2108
+ {modelID: 'TS0601', manufacturerName: '_TZE200_bqcqqjpb'},
2109
+ {modelID: 'TS0601', manufacturerName: '_TZE200_xaabybja'},
2110
+ {modelID: 'TS0601', manufacturerName: '_TZE200_rmymn92d'},
2111
+ {modelID: 'TS0601', manufacturerName: '_TZE200_3i3exuay'},
2112
+ {modelID: 'TS0601', manufacturerName: '_TZE200_tvrvdj6o'},
2113
+ {modelID: 'zo2pocs\u0000', manufacturerName: '_TYST11_fzo2pocs'},
2114
+ {modelID: 'TS0601', manufacturerName: '_TZE200_cf1sl3tj'},
2115
+ {modelID: 'TS0601', manufacturerName: '_TZE200_b2u1drdv'},
2116
+ {modelID: 'TS0601', manufacturerName: '_TZE200_ol5jlkkr'},
2117
+ // Roller blinds:
2118
+ {modelID: 'TS0601', manufacturerName: '_TZE200_fctwhugx'},
2119
+ {modelID: 'TS0601', manufacturerName: '_TZE200_zah67ekd'},
2120
+ {modelID: 'TS0601', manufacturerName: '_TZE200_hsgrhjpf'},
2121
+ {modelID: 'TS0601', manufacturerName: '_TZE200_pw7mji0l'},
2122
+ // Window pushers:
2123
+ {modelID: 'TS0601', manufacturerName: '_TZE200_g5wdnuow'},
2124
+ // Tubular motors:
2125
+ {modelID: 'TS0601', manufacturerName: '_TZE200_5sbebbzs'},
2126
+ {modelID: 'TS0601', manufacturerName: '_TZE200_udank5zs'},
2127
+ {modelID: 'TS0601', manufacturerName: '_TZE200_zuz7f94z'},
2128
+ {modelID: 'TS0601', manufacturerName: '_TZE200_nv6nxo0c'},
2129
+ {modelID: 'TS0601', manufacturerName: '_TZE200_68nvbio9'},
2130
+ {modelID: 'TS0601', manufacturerName: '_TZE200_3ylew7b4'},
2131
+ {modelID: 'TS0601', manufacturerName: '_TZE200_llm0epxg'},
2132
+ {modelID: 'TS0601', manufacturerName: '_TZE200_n1aauwb4'},
2133
+ ],
2134
+ model: 'TS0601_cover_1',
2135
+ vendor: 'TuYa',
2136
+ description: 'Curtain motor/roller blind motor/window pusher/tubular motor',
2137
+ whiteLabel: [
2138
+ {vendor: 'Yushun', model: 'YS-MT750'},
2139
+ {vendor: 'Zemismart', model: 'ZM79E-DT'},
2140
+ {vendor: 'Binthen', model: 'BCM100D'},
2141
+ {vendor: 'Binthen', model: 'CV01A'},
2142
+ {vendor: 'Zemismart', model: 'M515EGB'},
2143
+ {vendor: 'OZ Smart Things', model: 'ZM85EL-1Z'},
2144
+ {vendor: 'TuYa', model: 'M515EGZT'},
2145
+ {vendor: 'TuYa', model: 'DT82LEMA-1.2N'},
2146
+ {vendor: 'TuYa', model: 'ZD82TN', description: 'Curtain motor'},
2147
+ {vendor: 'Moes', model: 'AM43-0.45/40-ES-EB'},
2148
+ {vendor: 'Larkkey', model: 'ZSTY-SM-1SRZG-EU'},
2149
+ {vendor: 'Zemismart', model: 'ZM85EL-2Z', description: 'Roman Rod I type curtains track'},
2150
+ {vendor: 'Zemismart', model: 'AM43', description: 'Roller blind motor'},
2151
+ {vendor: 'Zemismart', model: 'M2805EGBZTN', description: 'Tubular motor'},
2152
+ {vendor: 'Zemismart', model: 'BCM500DS-TYZ', description: 'Curtain motor'},
2153
+ {vendor: 'A-OK', model: 'AM25', description: 'Tubular motor'},
2154
+ {vendor: 'Alutech', model: 'AM/R-Sm', description: 'Tubular motor'},
2155
+ ],
2156
+ fromZigbee: [fz.tuya_cover, fz.ignore_basic_report],
2157
+ toZigbee: [tz.tuya_cover_control, tz.tuya_cover_options],
2158
+ exposes: [
2159
+ e.cover_position().setAccess('position', ea.STATE_SET),
2160
+ exposes.composite('options', 'options', ea.STATE_SET)
2161
+ .withFeature(exposes.numeric('motor_speed', ea.STATE_SET)
2162
+ .withValueMin(0).withValueMax(255).withDescription('Motor speed'))
2163
+ .withFeature(exposes.binary('reverse_direction', ea.STATE_SET, true, false)
2164
+ .withDescription('Reverse the motor direction'))],
2165
+ },
2166
+ {
2167
+ fingerprint: [
2168
+ // Curtain motors:
2169
+ {modelID: 'TS0601', manufacturerName: '_TZE200_eegnwoyw'},
2170
+ ],
2171
+ model: 'TS0601_cover_2',
2172
+ vendor: 'TuYa',
2173
+ description: 'Curtain motor fixed speed',
2174
+ whiteLabel: [
2175
+ {vendor: 'Zemismart', model: 'BCM100DB'},
2176
+ ],
2177
+ fromZigbee: [fz.tuya_cover, fz.ignore_basic_report],
2178
+ toZigbee: [tz.tuya_cover_control],
2179
+ exposes: [e.cover_position().setAccess('position', ea.STATE_SET)],
2180
+ },
2181
+ {
2182
+ zigbeeModel: ['kud7u2l'],
2183
+ fingerprint: [
2184
+ {modelID: 'TS0601', manufacturerName: '_TZE200_ckud7u2l'},
2185
+ {modelID: 'TS0601', manufacturerName: '_TZE200_ywdxldoj'},
2186
+ {modelID: 'TS0601', manufacturerName: '_TZE200_do5qy8zo'},
2187
+ {modelID: 'TS0601', manufacturerName: '_TZE200_cwnjrr72'},
2188
+ {modelID: 'TS0601', manufacturerName: '_TZE200_pvvbommb'},
2189
+ {modelID: 'TS0601', manufacturerName: '_TZE200_9sfg7gm0'}, // HomeCloud
2190
+ {modelID: 'TS0601', manufacturerName: '_TZE200_2atgpdho'}, // HY367
2191
+ {modelID: 'TS0601', manufacturerName: '_TZE200_cpmgn2cf'},
2192
+ {modelID: 'TS0601', manufacturerName: '_TZE200_8thwkzxl'}, // Tervix eva2
2193
+ {modelID: 'TS0601', manufacturerName: '_TZE200_4eeyebrt'}, // Immax 07732B
2194
+ {modelID: 'TS0601', manufacturerName: '_TZE200_8whxpsiw'}, // EVOLVEO
2195
+ {modelID: 'TS0601', manufacturerName: '_TZE200_xby0s3ta'}, // Sandy Beach HY367
2196
+ {modelID: 'TS0601', manufacturerName: '_TZE200_7fqkphoq'}, // AFINTEK
2197
+ ],
2198
+ model: 'TS0601_thermostat',
2199
+ vendor: 'TuYa',
2200
+ description: 'Radiator valve with thermostat',
2201
+ whiteLabel: [
2202
+ {vendor: 'Moes', model: 'HY368'},
2203
+ {vendor: 'Moes', model: 'HY369RT'},
2204
+ {vendor: 'SHOJZJ', model: '378RT'},
2205
+ {vendor: 'Silvercrest', model: 'TVR01'},
2206
+ {vendor: 'Immax', model: '07732B'},
2207
+ {vendor: 'Evolveo', model: 'Heat M30'},
2208
+ ],
2209
+ meta: {tuyaThermostatPreset: tuya.thermostatPresets, tuyaThermostatSystemMode: tuya.thermostatSystemModes3},
2210
+ ota: ota.zigbeeOTA,
2211
+ onEvent: tuya.onEventSetLocalTime,
2212
+ fromZigbee: [fz.tuya_thermostat, fz.ignore_basic_report, fz.ignore_tuya_set_time],
2213
+ toZigbee: [tz.tuya_thermostat_child_lock, tz.tuya_thermostat_window_detection, tz.tuya_thermostat_valve_detection,
2214
+ tz.tuya_thermostat_current_heating_setpoint, tz.tuya_thermostat_auto_lock,
2215
+ tz.tuya_thermostat_calibration, tz.tuya_thermostat_min_temp, tz.tuya_thermostat_max_temp,
2216
+ tz.tuya_thermostat_boost_time, tz.tuya_thermostat_comfort_temp, tz.tuya_thermostat_eco_temp,
2217
+ tz.tuya_thermostat_force_to_mode, tz.tuya_thermostat_force, tz.tuya_thermostat_preset, tz.tuya_thermostat_away_mode,
2218
+ tz.tuya_thermostat_window_detect, tz.tuya_thermostat_schedule, tz.tuya_thermostat_week, tz.tuya_thermostat_away_preset,
2219
+ tz.tuya_thermostat_schedule_programming_mode],
2220
+ exposes: [
2221
+ e.child_lock(), e.window_detection(),
2222
+ exposes.binary('window_open', ea.STATE).withDescription('Window open?'),
2223
+ e.battery_low(), e.valve_detection(), e.position(),
2224
+ exposes.climate().withSetpoint('current_heating_setpoint', 5, 35, 0.5, ea.STATE_SET)
2225
+ .withLocalTemperature(ea.STATE).withSystemMode(['heat', 'auto', 'off'], ea.STATE_SET,
2226
+ 'Mode of this device, in the `heat` mode the TS0601 will remain continuously heating, i.e. it does not regulate ' +
2227
+ 'to the desired temperature. If you want TRV to properly regulate the temperature you need to use mode `auto` ' +
2228
+ 'instead setting the desired temperature.')
2229
+ .withLocalTemperatureCalibration(-9, 9, 0.5, ea.STATE_SET)
2230
+ .withPreset(['schedule', 'manual', 'boost', 'complex', 'comfort', 'eco', 'away'])
2231
+ .withRunningState(['idle', 'heat'], ea.STATE),
2232
+ e.auto_lock(), e.away_mode(), e.away_preset_days(), e.boost_time(), e.comfort_temperature(), e.eco_temperature(), e.force(),
2233
+ e.max_temperature().withValueMin(16).withValueMax(70), e.min_temperature(), e.away_preset_temperature(),
2234
+ exposes.composite('programming_mode', 'programming_mode', ea.STATE).withDescription('Schedule MODE ⏱ - In this mode, ' +
2235
+ 'the device executes a preset week programming temperature time and temperature.')
2236
+ .withFeature(e.week())
2237
+ .withFeature(exposes.text('workdays_schedule', ea.STATE_SET))
2238
+ .withFeature(exposes.text('holidays_schedule', ea.STATE_SET))],
2239
+ },
2240
+ {
2241
+ fingerprint: tuya.fingerprint('TS0601', [
2242
+ '_TZE200_sur6q7ko', /* model: '3012732', vendor: 'LSC Smart Connect' */
2243
+ '_TZE200_hue3yfsn', /* model: 'TV02-Zigbee', vendor: 'TuYa' */
2244
+ '_TZE200_e9ba97vf', /* model: 'TV01-ZB', vendor: 'Moes' */
2245
+ '_TZE200_husqqvux', /* model: 'TSL-TRV-TV01ZG', vendor: 'Tesla Smart' */
2246
+ '_TZE200_lnbfnyxd', /* model: 'TSL-TRV-TV01ZG', vendor: 'Tesla Smart' */
2247
+ '_TZE200_lllliz3p', /* model: 'TV02-Zigbee', vendor: 'TuYa' */
2248
+ '_TZE200_mudxchsu', /* model: 'TV05-ZG curve', vendor: 'TuYa' */
2249
+ '_TZE200_7yoranx2', /* model: 'TV01-ZB', vendor: 'Moes' */
2250
+ '_TZE200_kds0pmmv', /* model: 'TV01-ZB', vendor: 'Moes' */
2251
+ ]),
2252
+ model: 'TV02-Zigbee',
2253
+ vendor: 'TuYa',
2254
+ description: 'Thermostat radiator valve',
2255
+ whiteLabel: [
2256
+ {vendor: 'Moes', model: 'TV01-ZB'},
2257
+ {vendor: 'AVATTO', model: 'TRV06'},
2258
+ {vendor: 'Tesla Smart', model: 'TSL-TRV-TV01ZG'},
2259
+ {vendor: 'Unknown/id3.pl', model: 'GTZ08'},
2260
+ ],
2261
+ ota: ota.zigbeeOTA,
2262
+ fromZigbee: [tuya.fz.datapoints],
2263
+ toZigbee: [tuya.tz.datapoints],
2264
+ onEvent: tuya.onEventSetLocalTime,
2265
+ configure: tuya.configureMagicPacket,
2266
+ exposes: [
2267
+ e.battery_low(), e.child_lock(), e.open_window(), e.open_window_temperature().withValueMin(5).withValueMax(30),
2268
+ e.comfort_temperature().withValueMin(5).withValueMax(30), e.eco_temperature().withValueMin(5).withValueMax(30),
2269
+ exposes.climate().withPreset(['auto', 'manual', 'holiday']).withLocalTemperatureCalibration(-5, 5, 0.1, ea.STATE_SET)
2270
+ .withLocalTemperature(ea.STATE).withSetpoint('current_heating_setpoint', 5, 30, 0.5, ea.STATE_SET)
2271
+ .withSystemMode(['off', 'heat'], ea.STATE_SET, 'Only for Homeassistant'),
2272
+ exposes.binary('heating_stop', ea.STATE_SET, 'ON', 'OFF').withDescription('Battery life can be prolonged'+
2273
+ ' by switching the heating off. To achieve this, the valve is closed fully. To activate the '+
2274
+ 'heating stop, the device display "HS", press the pair button to cancel.'),
2275
+ tuya.exposes.frostProtection('When Anti-Freezing function is activated, the temperature in the house is kept '+
2276
+ 'at 8 °C, the device display "AF".press the pair button to cancel.'),
2277
+ exposes.numeric('boost_timeset_countdown', ea.STATE_SET).withUnit('second').withDescription('Setting '+
2278
+ 'minimum 0 - maximum 465 seconds boost time. The boost (♨) function is activated. The remaining '+
2279
+ 'time for the function will be counted down in seconds ( 465 to 0 ).').withValueMin(0).withValueMax(465),
2280
+ e.holiday_temperature().withValueMin(5).withValueMax(30),
2281
+ exposes.text('holiday_start_stop', ea.STATE_SET).withDescription('The holiday mode will automatically start ' +
2282
+ 'at the set time starting point and run the holiday temperature. Can be defined in the following format: ' +
2283
+ '`startYear/startMonth/startDay startHours:startMinutes | endYear/endMonth/endDay endHours:endMinutes`. ' +
2284
+ 'For example: `2022/10/01 16:30 | 2022/10/21 18:10`. After the end of holiday mode, it switches to "auto" ' +
2285
+ 'mode and uses schedule.'),
2286
+ exposes.enum('working_day', ea.STATE_SET, ['mon_sun', 'mon_fri+sat+sun', 'separate']).withDescription('`mon_sun` ' +
2287
+ '- schedule for Monday used for each day (define it only for Monday). `mon_fri+sat+sun` - schedule for ' +
2288
+ 'workdays used from Monday (define it only for Monday), Saturday and Sunday are defined separately. `separate` ' +
2289
+ '- schedule for each day is defined separately.'),
2290
+ exposes.composite('schedule', 'schedule', ea.SET).withFeature(exposes.enum('week_day', ea.SET, ['monday', 'tuesday',
2291
+ 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'])).withFeature(exposes.text('schedule', ea.SET))
2292
+ .withDescription('Schedule will work with "auto" preset. In this mode, the device executes ' +
2293
+ 'a preset week programming temperature time and temperature. Before using these properties, check `working_day` ' +
2294
+ 'property. Each day can contain up to 10 segments. At least 1 segment should be defined. Different count of segments ' +
2295
+ 'can be defined for each day, e.g., 3 segments for Monday, 5 segments for Thursday, etc. It should be defined in the ' +
2296
+ 'following format: `hours:minutes/temperature`. Minutes can be only tens, i.e., 00, 10, 20, 30, 40, 50. Segments should ' +
2297
+ 'be divided by space symbol. Each day should end with the last segment of 24:00. Examples: `04:00/20 08:30/22 10:10/18 ' +
2298
+ '18:40/24 22:50/19.5`; `06:00/21.5 17:20/26 24:00/18`. The temperature will be set from the beginning/start of one ' +
2299
+ 'period and until the next period, e.g., `04:00/20 24:00/22` means that from 00:00 to 04:00 temperature will be 20 ' +
2300
+ 'degrees and from 04:00 to 00:00 temperature will be 22 degrees.'),
2301
+ ...tuya.exposes.scheduleAllDays(ea.STATE, 'HH:MM/C'),
2302
+ exposes.binary('online', ea.STATE_SET, 'ON', 'OFF').withDescription('The current data request from the device.'),
2303
+ tuya.exposes.errorStatus(),
2304
+ ],
2305
+ meta: {
2306
+ tuyaDatapoints: [
2307
+ [2, 'preset', tuya.valueConverterBasic.lookup({'auto': tuya.enum(0), 'manual': tuya.enum(1), 'holiday': tuya.enum(3)})],
2308
+ [8, 'open_window', tuya.valueConverter.onOff],
2309
+ [10, null, tuya.valueConverter.TV02FrostProtection],
2310
+ [10, 'frost_protection', tuya.valueConverter.TV02FrostProtection],
2311
+ [16, 'current_heating_setpoint', tuya.valueConverter.divideBy10],
2312
+ [24, 'local_temperature', tuya.valueConverter.divideBy10],
2313
+ [27, 'local_temperature_calibration', tuya.valueConverter.localTempCalibration1],
2314
+ [31, 'working_day', tuya.valueConverterBasic.lookup({'mon_sun': tuya.enum(0), 'mon_fri+sat+sun': tuya.enum(1),
2315
+ 'separate': tuya.enum(2)})],
2316
+ [32, 'holiday_temperature', tuya.valueConverter.divideBy10],
2317
+ [35, 'battery_low', tuya.valueConverter.trueFalse0],
2318
+ [40, 'child_lock', tuya.valueConverter.lockUnlock],
2319
+ [45, 'error_status', tuya.valueConverter.raw],
2320
+ [46, 'holiday_start_stop', tuya.valueConverter.thermostatHolidayStartStop],
2321
+ [101, 'boost_timeset_countdown', tuya.valueConverter.raw],
2322
+ [102, 'open_window_temperature', tuya.valueConverter.divideBy10],
2323
+ [104, 'comfort_temperature', tuya.valueConverter.divideBy10],
2324
+ [105, 'eco_temperature', tuya.valueConverter.divideBy10],
2325
+ [106, 'schedule', tuya.valueConverter.thermostatScheduleDaySingleDP],
2326
+ [107, null, tuya.valueConverter.TV02SystemMode],
2327
+ [107, 'system_mode', tuya.valueConverter.TV02SystemMode],
2328
+ [107, 'heating_stop', tuya.valueConverter.TV02SystemMode],
2329
+ [115, 'online', tuya.valueConverter.onOffNotStrict],
2330
+ [108, 'schedule_monday', tuya.valueConverter.thermostatScheduleDaySingleDP],
2331
+ [112, 'schedule_tuesday', tuya.valueConverter.thermostatScheduleDaySingleDP],
2332
+ [109, 'schedule_wednesday', tuya.valueConverter.thermostatScheduleDaySingleDP],
2333
+ [113, 'schedule_thursday', tuya.valueConverter.thermostatScheduleDaySingleDP],
2334
+ [110, 'schedule_friday', tuya.valueConverter.thermostatScheduleDaySingleDP],
2335
+ [114, 'schedule_saturday', tuya.valueConverter.thermostatScheduleDaySingleDP],
2336
+ [111, 'schedule_sunday', tuya.valueConverter.thermostatScheduleDaySingleDP],
2337
+ ],
2338
+ },
2339
+ },
2340
+ {
2341
+ fingerprint: tuya.fingerprint('TS0601', [
2342
+ '_TZE200_0hg58wyk', /* model: 'S366', vendor: 'Cloud Even' */
2343
+ ]),
2344
+ model: 'TS0601_thermostat_2',
2345
+ vendor: 'TuYa',
2346
+ description: 'Thermostat radiator valve',
2347
+ whiteLabel: [
2348
+ {vendor: 'S366', model: 'Cloud Even'},
2349
+ ],
2350
+ fromZigbee: [tuya.fz.datapoints],
2351
+ toZigbee: [tuya.tz.datapoints],
2352
+ onEvent: tuya.onEventSetLocalTime,
2353
+ configure: tuya.configureMagicPacket,
2354
+ meta: {
2355
+ tuyaDatapoints: [
2356
+ [1, 'system_mode', tuya.valueConverterBasic.lookup({'heat': true, 'off': false})],
2357
+ [2, 'preset', tuya.valueConverterBasic.lookup({'manual': tuya.enum(0), 'holiday': tuya.enum(1), 'program': tuya.enum(2)})],
2358
+ [3, null, null], // TODO: Unknown DP
2359
+ [8, 'open_window', tuya.valueConverter.onOff],
2360
+ [10, 'frost_protection', tuya.valueConverter.onOff],
2361
+ [16, 'current_heating_setpoint', tuya.valueConverter.divideBy10],
2362
+ [24, 'local_temperature', tuya.valueConverter.divideBy10],
2363
+ [27, 'local_temperature_calibration', tuya.valueConverter.localTempCalibration1],
2364
+ [35, 'battery_low', tuya.valueConverter.trueFalse0],
2365
+ [40, 'child_lock', tuya.valueConverter.lockUnlock],
2366
+ [45, 'error_status', tuya.valueConverter.raw],
2367
+ [101, 'schedule_monday', tuya.valueConverter.thermostatScheduleDayMultiDP],
2368
+ [102, 'schedule_tuesday', tuya.valueConverter.thermostatScheduleDayMultiDP],
2369
+ [103, 'schedule_wednesday', tuya.valueConverter.thermostatScheduleDayMultiDP],
2370
+ [104, 'schedule_thursday', tuya.valueConverter.thermostatScheduleDayMultiDP],
2371
+ [105, 'schedule_friday', tuya.valueConverter.thermostatScheduleDayMultiDP],
2372
+ [106, 'schedule_saturday', tuya.valueConverter.thermostatScheduleDayMultiDP],
2373
+ [107, 'schedule_sunday', tuya.valueConverter.thermostatScheduleDayMultiDP],
2374
+ ],
2375
+ },
2376
+ exposes: [
2377
+ e.battery_low(), e.child_lock(), e.open_window(), tuya.exposes.frostProtection(), tuya.exposes.errorStatus(),
2378
+ exposes.climate()
2379
+ .withSystemMode(['off', 'heat'], ea.STATE_SET)
2380
+ .withPreset(['manual', 'holiday', 'program'])
2381
+ .withLocalTemperatureCalibration(-5, 5, 0.1, ea.STATE_SET)
2382
+ .withLocalTemperature(ea.STATE)
2383
+ .withSetpoint('current_heating_setpoint', 5, 30, 0.5, ea.STATE_SET),
2384
+ ...tuya.exposes.scheduleAllDays(ea.STATE_SET, 'HH:MM/C HH:MM/C HH:MM/C HH:MM/C'),
2385
+ ],
2386
+ },
2387
+ {
2388
+ fingerprint: tuya.fingerprint('TS0601', [
2389
+ '_TZE200_bvu2wnxz', /* model: 'ME167', vendor: 'Avatto' */
2390
+ '_TZE200_6rdj8dzm', /* model: 'ME167', vendor: 'Avatto' */
2391
+ '_TZE200_gd4rvykv', // Sanico
2392
+ ]),
2393
+ model: 'TS0601_thermostat_3',
2394
+ vendor: 'TuYa',
2395
+ description: 'Thermostatic radiator valve',
2396
+ fromZigbee: [tuya.fzDataPoints],
2397
+ toZigbee: [tuya.tzDataPoints],
2398
+ whiteLabel: [{vendor: 'Avatto', model: 'ME167'}],
2399
+ onEvent: tuya.onEventSetTime,
2400
+ configure: tuya.configureMagicPacket,
2401
+ exposes: [
2402
+ e.child_lock(), e.battery_low(),
2403
+ exposes.climate()
2404
+ .withSetpoint('current_heating_setpoint', 5, 35, 1, ea.STATE_SET)
2405
+ .withLocalTemperature(ea.STATE)
2406
+ .withSystemMode(['auto', 'heat', 'off'], ea.STATE_SET)
2407
+ .withRunningState(['idle', 'heat'], ea.STATE)
2408
+ .withLocalTemperatureCalibration(-3, 3, 1, ea.STATE_SET),
2409
+ exposes.binary('scale_protection', ea.STATE_SET, 'ON', 'OFF').withDescription('If the heat sink is not fully opened within ' +
2410
+ 'two weeks or is not used for a long time, the valve will be blocked due to silting up and the heat sink will not be ' +
2411
+ 'able to be used. To ensure normal use of the heat sink, the controller will automatically open the valve fully every ' +
2412
+ 'two weeks. It will run for 30 seconds per time with the screen displaying "Ad", then return to its normal working state ' +
2413
+ 'again.'),
2414
+ exposes.binary('frost_protection', ea.STATE_SET, 'ON', 'OFF').withDescription('When the room temperature is lower than ' +
2415
+ '5 °C, the valve opens; when the temperature rises to 8 °C, the valve closes.'),
2416
+ exposes.numeric('error', ea.STATE).withDescription('If NTC is damaged, "Er" will be on the TRV display.'),
2417
+ ],
2418
+ meta: {
2419
+ tuyaDatapoints: [
2420
+ [2, 'system_mode', tuya.valueConverterBasic.lookup({'auto': tuya.enum(0), 'heat': tuya.enum(1), 'off': tuya.enum(2)})],
2421
+ [3, 'running_state', tuya.valueConverterBasic.lookup({'heat': tuya.enum(0), 'idle': tuya.enum(1)})],
2422
+ [4, 'current_heating_setpoint', tuya.valueConverter.divideBy10],
2423
+ [5, 'local_temperature', tuya.valueConverter.divideBy10],
2424
+ [7, 'child_lock', tuya.valueConverter.lockUnlock],
2425
+ [35, null, tuya.valueConverter.errorOrBatteryLow],
2426
+ [36, 'frost_protection', tuya.valueConverter.onOff],
2427
+ [39, 'scale_protection', tuya.valueConverter.onOff],
2428
+ [47, 'local_temperature_calibration', tuya.valueConverter.localTempCalibration2],
2429
+ ],
2430
+ },
2431
+ },
2432
+ {
2433
+ fingerprint: [
2434
+ {modelID: 'v90ladg\u0000', manufacturerName: '_TYST11_wv90ladg'},
2435
+ {modelID: 'TS0601', manufacturerName: '_TZE200_wv90ladg'},
2436
+ ],
2437
+ model: 'HT-08',
2438
+ vendor: 'ETOP',
2439
+ description: 'Wall-mount thermostat',
2440
+ fromZigbee: [fz.legacy.tuya_thermostat_weekly_schedule, fz.etop_thermostat, fz.ignore_basic_report, fz.ignore_tuya_set_time],
2441
+ toZigbee: [tz.etop_thermostat_system_mode, tz.etop_thermostat_away_mode, tz.tuya_thermostat_child_lock,
2442
+ tz.tuya_thermostat_current_heating_setpoint, tz.tuya_thermostat_weekly_schedule],
2443
+ onEvent: tuya.onEventSetTime,
2444
+ meta: {
2445
+ thermostat: {
2446
+ weeklyScheduleMaxTransitions: 4,
2447
+ weeklyScheduleSupportedModes: [1], // bits: 0-heat present, 1-cool present (dec: 1-heat,2-cool,3-heat+cool)
2448
+ weeklyScheduleFirstDayDpId: tuya.dataPoints.schedule,
2449
+ },
2450
+ },
2451
+ exposes: [e.child_lock(), e.away_mode(), exposes.climate().withSetpoint('current_heating_setpoint', 5, 35, 0.5, ea.STATE_SET)
2452
+ .withLocalTemperature(ea.STATE)
2453
+ .withSystemMode(['off', 'heat', 'auto'], ea.STATE_SET).withRunningState(['idle', 'heat'], ea.STATE)],
2454
+ },
2455
+ {
2456
+ fingerprint: [{modelID: 'dpplnsn\u0000', manufacturerName: '_TYST11_2dpplnsn'},
2457
+ {modelID: 'TS0601', manufacturerName: '_TZE200_2dpplnsn'}],
2458
+ model: 'HT-10',
2459
+ vendor: 'ETOP',
2460
+ description: 'Radiator valve',
2461
+ fromZigbee: [fz.legacy.tuya_thermostat_weekly_schedule, fz.etop_thermostat, fz.ignore_basic_report, fz.ignore_tuya_set_time],
2462
+ toZigbee: [tz.etop_thermostat_system_mode, tz.etop_thermostat_away_mode, tz.tuya_thermostat_child_lock,
2463
+ tz.tuya_thermostat_current_heating_setpoint, tz.tuya_thermostat_weekly_schedule],
2464
+ onEvent: tuya.onEventSetTime,
2465
+ meta: {
2466
+ timeout: 20000, // TRV wakes up every 10sec
2467
+ thermostat: {
2468
+ weeklyScheduleMaxTransitions: 4,
2469
+ weeklyScheduleSupportedModes: [1], // bits: 0-heat present, 1-cool present (dec: 1-heat,2-cool,3-heat+cool)
2470
+ weeklyScheduleFirstDayDpId: tuya.dataPoints.schedule,
2471
+ },
2472
+ },
2473
+ exposes: [
2474
+ e.battery_low(), e.child_lock(), e.away_mode(), exposes.climate()
2475
+ .withSetpoint('current_heating_setpoint', 5, 35, 0.5, ea.STATE_SET)
2476
+ .withLocalTemperature(ea.STATE)
2477
+ .withSystemMode(['off', 'heat', 'auto'], ea.STATE_SET).withRunningState(['idle', 'heat'], ea.STATE),
2478
+ ],
2479
+ },
2480
+ {
2481
+ fingerprint: [
2482
+ {modelID: 'TS0601', manufacturerName: '_TZE200_a4bpgplm'},
2483
+ {modelID: 'TS0601', manufacturerName: '_TZE200_dv8abrrz'},
2484
+ {modelID: 'TS0601', manufacturerName: '_TZE200_z1tyspqw'},
2485
+ ],
2486
+ model: 'TS0601_thermostat_1',
2487
+ vendor: 'TuYa',
2488
+ description: 'Thermostatic radiator valve',
2489
+ whiteLabel: [
2490
+ {vendor: 'Unknown/id3.pl', model: 'GTZ06'},
2491
+ ],
2492
+ onEvent: tuya.onEventSetLocalTime,
2493
+ fromZigbee: [tuya.fzDataPoints],
2494
+ toZigbee: [tuya.tzDataPoints],
2495
+ configure: tuya.configureMagicPacket,
2496
+ exposes: [
2497
+ e.battery(), e.child_lock(), e.max_temperature(), e.min_temperature(),
2498
+ e.position(), e.window_detection(),
2499
+ exposes.binary('window', ea.STATE, 'CLOSED', 'OPEN').withDescription('Window status closed or open '),
2500
+ exposes.binary('alarm_switch', ea.STATE, 'ON', 'OFF').withDescription('Thermostat in error state'),
2501
+ exposes.climate()
2502
+ .withLocalTemperature(ea.STATE).withSetpoint('current_heating_setpoint', 5, 35, 0.5, ea.STATE_SET)
2503
+ .withLocalTemperatureCalibration(-30, 30, 0.1, ea.STATE_SET)
2504
+ .withPreset(['auto', 'manual', 'off', 'on'],
2505
+ 'MANUAL MODE ☝ - In this mode, the device executes manual temperature setting. ' +
2506
+ 'When the set temperature is lower than the "minimum temperature", the valve is closed (forced closed). ' +
2507
+ 'AUTO MODE ⏱ - In this mode, the device executes a preset week programming temperature time and temperature. ' +
2508
+ 'ON - In this mode, the thermostat stays open ' +
2509
+ 'OFF - In this mode, the thermostat stays closed')
2510
+ .withSystemMode(['auto', 'heat', 'off'], ea.STATE)
2511
+ .withRunningState(['idle', 'heat'], ea.STATE),
2512
+ ...tuya.exposes.scheduleAllDays(ea.STATE_SET, 'HH:MM/C HH:MM/C HH:MM/C HH:MM/C'),
2513
+ exposes.binary('boost_heating', ea.STATE_SET, 'ON', 'OFF')
2514
+ .withDescription('Boost Heating: press and hold "+" for 3 seconds, ' +
2515
+ 'the device will enter the boost heating mode, and the ▷╵◁ will flash. The countdown will be displayed in the APP'),
2516
+ exposes.numeric('boost_time', ea.STATE_SET).withUnit('min').withDescription('Countdown in minutes')
2517
+ .withValueMin(0).withValueMax(1000),
2518
+ ],
2519
+ meta: {
2520
+ tuyaDatapoints: [
2521
+ [1, null,
2522
+ {
2523
+ from: (v) => {
2524
+ const presetLookup = {0: 'auto', 1: 'manual', 2: 'off', 3: 'on'};
2525
+ const systemModeLookup = {0: 'auto', 1: 'auto', 2: 'off', 3: 'heat'};
2526
+ return {preset: presetLookup[v], system_mode: systemModeLookup[v]};
2527
+ },
2528
+ },
2529
+ ],
2530
+ [1, 'system_mode', tuya.valueConverterBasic.lookup({'auto': tuya.enum(1), 'off': tuya.enum(2), 'heat': tuya.enum(3)})],
2531
+ [1, 'preset', tuya.valueConverterBasic.lookup(
2532
+ {'auto': tuya.enum(0), 'manual': tuya.enum(1), 'off': tuya.enum(2), 'on': tuya.enum(3)})],
2533
+ [2, 'current_heating_setpoint', tuya.valueConverter.divideBy10],
2534
+ [3, 'local_temperature', tuya.valueConverter.divideBy10],
2535
+ [4, 'boost_heating', tuya.valueConverter.onOff],
2536
+ [5, 'boost_time', tuya.valueConverter.countdown],
2537
+ [6, 'running_state', tuya.valueConverterBasic.lookup({'heat': 1, 'idle': 0})],
2538
+ [7, 'window', tuya.valueConverterBasic.lookup({'OPEN': 1, 'CLOSE': 0})],
2539
+ [8, 'window_detection', tuya.valueConverter.onOff],
2540
+ [12, 'child_lock', tuya.valueConverter.lockUnlock],
2541
+ [13, 'battery', tuya.valueConverter.raw],
2542
+ [14, 'alarm_switch', tuya.valueConverter.onOff],
2543
+ [15, 'min_temperature', tuya.valueConverter.divideBy10],
2544
+ [16, 'max_temperature', tuya.valueConverter.divideBy10],
2545
+ [17, 'schedule_monday', tuya.valueConverter.thermostatScheduleDayMultiDPWithDayNumber(1)],
2546
+ [18, 'schedule_tuesday', tuya.valueConverter.thermostatScheduleDayMultiDPWithDayNumber(2)],
2547
+ [19, 'schedule_wednesday', tuya.valueConverter.thermostatScheduleDayMultiDPWithDayNumber(3)],
2548
+ [20, 'schedule_thursday', tuya.valueConverter.thermostatScheduleDayMultiDPWithDayNumber(4)],
2549
+ [21, 'schedule_friday', tuya.valueConverter.thermostatScheduleDayMultiDPWithDayNumber(5)],
2550
+ [22, 'schedule_saturday', tuya.valueConverter.thermostatScheduleDayMultiDPWithDayNumber(6)],
2551
+ [23, 'schedule_sunday', tuya.valueConverter.thermostatScheduleDayMultiDPWithDayNumber(7)],
2552
+ [101, 'local_temperature_calibration', tuya.valueConverter.localTempCalibration1],
2553
+ [102, 'position', tuya.valueConverter.divideBy10],
2554
+ ],
2555
+ },
2556
+ },
2557
+ {
2558
+ zigbeeModel: ['TS0121'],
2559
+ model: 'TS0121_plug',
2560
+ description: '10A UK or 16A EU smart plug',
2561
+ whiteLabel: [
2562
+ {vendor: 'BlitzWolf', model: 'BW-SHP13'},
2563
+ {vendor: 'Connecte', model: '4500990'},
2564
+ {vendor: 'Connecte', model: '4500991'},
2565
+ {vendor: 'Connecte', model: '4500992'},
2566
+ {vendor: 'Connecte', model: '4500993'},
2567
+ ],
2568
+ vendor: 'TuYa',
2569
+ fromZigbee: [fz.on_off, fz.electrical_measurement, fz.metering, fz.ignore_basic_report, tuya.fz.power_outage_memory,
2570
+ tuya.fz.indicator_mode],
2571
+ toZigbee: [tz.on_off, tuya.tz.power_on_behavior_1, tuya.tz.backlight_indicator_mode_1],
2572
+ configure: async (device, coordinatorEndpoint, logger) => {
2573
+ const endpoint = device.getEndpoint(1);
2574
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement', 'seMetering']);
2575
+ endpoint.saveClusterAttributeKeyValue('seMetering', {divisor: 100, multiplier: 1});
2576
+ endpoint.saveClusterAttributeKeyValue('haElectricalMeasurement', {
2577
+ acVoltageMultiplier: 1, acVoltageDivisor: 1, acCurrentMultiplier: 1, acCurrentDivisor: 1000, acPowerMultiplier: 1,
2578
+ acPowerDivisor: 1,
2579
+ });
2580
+ try {
2581
+ await reporting.currentSummDelivered(endpoint);
2582
+ await reporting.rmsVoltage(endpoint, {change: 5});
2583
+ await reporting.rmsCurrent(endpoint, {change: 50});
2584
+ await reporting.activePower(endpoint, {change: 10});
2585
+ } catch (error) {/* fails for some https://github.com/Koenkk/zigbee2mqtt/issues/11179
2586
+ and https://github.com/Koenkk/zigbee2mqtt/issues/16864 */}
2587
+ await endpoint.read('genOnOff', ['onOff', 'moesStartUpOnOff', 'tuyaBacklightMode']);
2588
+ },
2589
+ options: [exposes.options.measurement_poll_interval()],
2590
+ // This device doesn't support reporting correctly.
2591
+ // https://github.com/Koenkk/zigbee-herdsman-converters/pull/1270
2592
+ exposes: [e.switch(), e.power(), e.current(), e.voltage(),
2593
+ e.energy(), exposes.enum('power_outage_memory', ea.ALL, ['on', 'off', 'restore'])
2594
+ .withDescription('Recover state after power outage'),
2595
+ exposes.enum('indicator_mode', ea.ALL, ['off', 'off/on', 'on/off']).withDescription('LED indicator mode')],
2596
+ onEvent: tuya.onEventMeasurementPoll,
2597
+ },
2598
+ {
2599
+ fingerprint: [{modelID: 'TS0111', manufacturerName: '_TYZB01_ymcdbl3u'}],
2600
+ model: 'TS0111_valve',
2601
+ vendor: 'TuYa',
2602
+ whiteLabel: [{vendor: 'TuYa', model: 'SM-AW713Z'}],
2603
+ description: 'Smart water/gas valve',
2604
+ extend: tuya.extend.switch({indicatorMode: true}),
2605
+ },
2606
+ {
2607
+ // Note: below you will find the TS011F_plug_2 and TS011F_plug_3. These are identified via a fingerprint and
2608
+ // thus preferred above the TS011F_plug_1 if the fingerprint matches
2609
+ zigbeeModel: ['TS011F'],
2610
+ model: 'TS011F_plug_1',
2611
+ description: 'Smart plug (with power monitoring)',
2612
+ vendor: 'TuYa',
2613
+ whiteLabel: [{vendor: 'LELLKI', model: 'TS011F_plug'}, {vendor: 'NEO', model: 'NAS-WR01B'},
2614
+ {vendor: 'BlitzWolf', model: 'BW-SHP15'}, {vendor: 'Nous', model: 'A1Z'}, {vendor: 'BlitzWolf', model: 'BW-SHP13'},
2615
+ {vendor: 'MatSee Plus', model: 'PJ-ZSW01'}, {vendor: 'MODEMIX', model: 'MOD037'}, {vendor: 'MODEMIX', model: 'MOD048'},
2616
+ {vendor: 'Coswall', model: 'CS-AJ-DE2U-ZG-11'}, {vendor: 'Aubess', model: 'TS011F_plug_1'}, {vendor: 'Immax', model: '07752L'}],
2617
+ ota: ota.zigbeeOTA,
2618
+ extend: tuya.extend.switch({electricalMeasurements: true, powerOutageMemory: true, indicatorMode: true, childLock: true}),
2619
+ configure: async (device, coordinatorEndpoint, logger) => {
2620
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
2621
+ const endpoint = device.getEndpoint(1);
2622
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement', 'seMetering']);
2623
+ await reporting.rmsVoltage(endpoint, {change: 5});
2624
+ await reporting.rmsCurrent(endpoint, {change: 50});
2625
+ await reporting.activePower(endpoint, {change: 10});
2626
+ await reporting.currentSummDelivered(endpoint);
2627
+ endpoint.saveClusterAttributeKeyValue('haElectricalMeasurement', {acCurrentDivisor: 1000, acCurrentMultiplier: 1});
2628
+ endpoint.saveClusterAttributeKeyValue('seMetering', {divisor: 100, multiplier: 1});
2629
+ device.save();
2630
+ },
2631
+ },
2632
+ {
2633
+ fingerprint: tuya.fingerprint('TS011F',
2634
+ ['_TZ3000_hyfvrar3', '_TZ3000_v1pdxuqq', '_TZ3000_8a833yls', '_TZ3000_bfn1w0mm', '_TZ3000_nzkqcvvs', '_TZ3000_rtcrrvia']),
2635
+ model: 'TS011F_plug_2',
2636
+ description: 'Smart plug (without power monitoring)',
2637
+ vendor: 'TuYa',
2638
+ extend: tuya.extend.switch({powerOutageMemory: true, indicatorMode: true, childLock: true}),
2639
+ configure: async (device, coordinatorEndpoint, logger) => {
2640
+ const endpoint = device.getEndpoint(1);
2641
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
2642
+ },
2643
+ },
2644
+ {
2645
+ fingerprint: [160, 100, 69, 68, 65, 64, 66].map((applicationVersion) => {
2646
+ return {modelID: 'TS011F', applicationVersion, priority: -1};
2647
+ }),
2648
+ model: 'TS011F_plug_3',
2649
+ description: 'Smart plug (with power monitoring by polling)',
2650
+ vendor: 'TuYa',
2651
+ whiteLabel: [{vendor: 'VIKEFON', model: 'TS011F'}, {vendor: 'BlitzWolf', model: 'BW-SHP15'},
2652
+ {vendor: 'Avatto', model: 'MIUCOT10Z'}, {vendor: 'Neo', model: 'NAS-WR01B'}, {vendor: 'Neo', model: 'PLUG-001SPB2'}],
2653
+ ota: ota.zigbeeOTA,
2654
+ extend: tuya.extend.switch({electricalMeasurements: true, powerOutageMemory: true, indicatorMode: true, childLock: true}),
2655
+ configure: async (device, coordinatorEndpoint, logger) => {
2656
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
2657
+ const endpoint = device.getEndpoint(1);
2658
+ endpoint.saveClusterAttributeKeyValue('haElectricalMeasurement', {acCurrentDivisor: 1000, acCurrentMultiplier: 1});
2659
+ endpoint.saveClusterAttributeKeyValue('seMetering', {divisor: 100, multiplier: 1});
2660
+ device.save();
2661
+ },
2662
+ options: [exposes.options.measurement_poll_interval()],
2663
+ onEvent: (type, data, device, options) =>
2664
+ tuya.onEventMeasurementPoll(type, data, device, options,
2665
+ device.applicationVersion !== 66, // polling for voltage, current and power
2666
+ [66, 100, 160].includes(device.applicationVersion), // polling for energy
2667
+ ),
2668
+ },
2669
+ {
2670
+ fingerprint: [{modelID: 'TS011F', manufacturerName: '_TZ3000_wbloefbf'}],
2671
+ model: 'TS011F_switch_5_gang',
2672
+ description: '2 gang 2 usb 1 wall ac outlet',
2673
+ whiteLabel: [{vendor: 'Milfra', model: 'M11Z'}],
2674
+ vendor: 'TuYa',
2675
+ extend: tuya.extend.switch({powerOutageMemory: true, childLock: true, endpoints: ['l1', 'l2', 'l3', 'l4', 'l5']}),
2676
+ endpoint: (device) => {
2677
+ return {l1: 1, l2: 2, l3: 3, l4: 4, l5: 5};
2678
+ },
2679
+ meta: {multiEndpoint: true},
2680
+ configure: async (device, coordinatorEndpoint, logger) => {
2681
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
2682
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
2683
+ await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
2684
+ await reporting.bind(device.getEndpoint(3), coordinatorEndpoint, ['genOnOff']);
2685
+ await reporting.bind(device.getEndpoint(4), coordinatorEndpoint, ['genOnOff']);
2686
+ await reporting.bind(device.getEndpoint(5), coordinatorEndpoint, ['genOnOff']);
2687
+ },
2688
+ },
2689
+ {
2690
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE200_ntcy3xu1', '_TZE200_ytibqbra']),
2691
+ model: 'TS0601_smoke_1',
2692
+ vendor: 'TuYa',
2693
+ description: 'Smoke sensor',
2694
+ fromZigbee: [tuya.fz.datapoints],
2695
+ toZigbee: [tuya.tz.datapoints],
2696
+ configure: tuya.configureMagicPacket,
2697
+ exposes: [e.smoke(), e.tamper(), e.battery_low()],
2698
+ meta: {
2699
+ tuyaDatapoints: [
2700
+ [1, 'smoke', tuya.valueConverter.trueFalse0],
2701
+ [4, 'tamper', tuya.valueConverter.raw],
2702
+ [14, 'battery_low', tuya.valueConverter.trueFalse0],
2703
+ ],
2704
+ },
2705
+ },
2706
+ {
2707
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE200_m9skfctm']),
2708
+ model: 'TS0601_smoke_2',
2709
+ vendor: 'TuYa',
2710
+ description: 'Photoelectric smoke detector',
2711
+ fromZigbee: [tuya.fz.datapoints],
2712
+ toZigbee: [tuya.tz.datapoints],
2713
+ onEvent: tuya.onEventSetTime,
2714
+ configure: tuya.configureMagicPacket,
2715
+ exposes: [
2716
+ e.smoke(), e.battery(), e.test(),
2717
+ exposes.numeric('smoke_concentration', ea.STATE).withUnit('ppm').withDescription('Parts per million of smoke detected'),
2718
+ exposes.binary('device_fault', ea.STATE, true, false).withDescription('Indicates a fault with the device'),
2719
+ ],
2720
+ meta: {
2721
+ tuyaDatapoints: [
2722
+ [1, 'smoke', tuya.valueConverter.trueFalse0],
2723
+ [2, 'smoke_concentration', tuya.valueConverter.divideBy10],
2724
+ [11, 'device_fault', tuya.valueConverter.raw],
2725
+ [15, 'battery', tuya.valueConverter.raw],
2726
+ [101, 'test', tuya.valueConverter.raw],
2727
+ ],
2728
+ },
2729
+ },
2730
+ {
2731
+ fingerprint: [
2732
+ {modelID: 'TS0601', manufacturerName: '_TZE200_ux5v4dbd'}, // [KnockautX / Brelag AG, Switzerland](https://www.brelag.com)
2733
+ ],
2734
+ vendor: 'TuYa',
2735
+ model: 'TS0601_smoke_3',
2736
+ description: 'Photoelectric smoke detector',
2737
+ whiteLabel: [
2738
+ {vendor: 'KnockautX', model: 'SMOAL024'},
2739
+ ],
2740
+ configure: tuya.configureMagicPacket,
2741
+ fromZigbee: [tuya.fz.datapoints],
2742
+ toZigbee: [tuya.tz.datapoints],
2743
+ exposes: [e.smoke(), tuya.exposes.batteryState()],
2744
+ meta: {
2745
+ tuyaDatapoints: [
2746
+ /**
2747
+ * According to the Vendor "KnockautX / Brelag AG" DP 16 "muffling"
2748
+ * is supported as well. But it was not possible to verify this using
2749
+ * SMOLA024 devices - therefore it is not included in the device definition.
2750
+ *
2751
+ * Data Transfer Type: Send and Report
2752
+ * Data Type: Bool
2753
+ * muffling: 16,
2754
+ */
2755
+ [1, 'smoke', tuya.valueConverter.trueFalse0],
2756
+ [14, 'battery_state', tuya.valueConverter.batteryState],
2757
+ ],
2758
+ },
2759
+ },
2760
+ {
2761
+ zigbeeModel: ['5p1vj8r'],
2762
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE200_t5p1vj8r', '_TZE200_uebojraa', '_TZE200_vzekyi4c', '_TZE200_yh7aoahi',
2763
+ '_TZE200_dnz6yvl2', '_TZE200_dq1mfjug']),
2764
+ model: 'TS0601_smoke',
2765
+ vendor: 'TuYa',
2766
+ description: 'Smoke sensor',
2767
+ fromZigbee: [tuya.fz.datapoints],
2768
+ toZigbee: [tuya.tz.datapoints],
2769
+ exposes: [e.smoke(), e.battery(), tuya.exposes.batteryState()],
2770
+ meta: {
2771
+ tuyaDatapoints: [
2772
+ [1, 'smoke', tuya.valueConverter.trueFalse0],
2773
+ [14, 'battery_state', tuya.valueConverter.batteryState],
2774
+ [15, 'battery', tuya.valueConverter.raw],
2775
+ ],
2776
+ },
2777
+ },
2778
+ {
2779
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_5d3vhjro'}],
2780
+ model: 'SA12IZL',
2781
+ vendor: 'TuYa',
2782
+ description: 'Smart smoke alarm',
2783
+ meta: {timeout: 30000, disableDefaultResponse: true},
2784
+ fromZigbee: [fzLocal.SA12IZL],
2785
+ toZigbee: [tzLocal.SA12IZL_silence_siren, tzLocal.SA12IZL_alarm],
2786
+ exposes: [e.battery(),
2787
+ exposes.binary('smoke', ea.STATE, true, false).withDescription('Smoke alarm status'),
2788
+ exposes.enum('battery_level', ea.STATE, ['low', 'middle', 'high']).withDescription('Battery level state'),
2789
+ exposes.binary('alarm', ea.STATE_SET, true, false).withDescription('Enable the alarm'),
2790
+ exposes.binary('silence_siren', ea.STATE_SET, true, false).withDescription('Silence the siren')],
2791
+ onEvent: tuya.onEventsetTime,
2792
+ },
2793
+ {
2794
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE204_cjbofhxw']),
2795
+ model: 'TS0601_clamp_meter',
2796
+ vendor: 'TuYa',
2797
+ description: 'Clamp meter',
2798
+ fromZigbee: [tuya.fz.datapoints, tuya.fz.gateway_connection_status],
2799
+ toZigbee: [tuya.tz.datapoints],
2800
+ configure: tuya.configureMagicPacket,
2801
+ exposes: [e.current(), e.power(), e.voltage(), e.energy()],
2802
+ meta: {
2803
+ tuyaDatapoints: [
2804
+ [18, 'current', tuya.valueConverter.divideBy1000],
2805
+ [19, 'power', tuya.valueConverter.divideBy10],
2806
+ [20, 'voltage', tuya.valueConverter.divideBy10],
2807
+ [101, 'energy', tuya.valueConverter.divideBy1000],
2808
+ ],
2809
+ },
2810
+ },
2811
+ {
2812
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE200_bkkmqmyo', '_TZE200_eaac7dkw']),
2813
+ model: 'TS0601_din_1',
2814
+ vendor: 'TuYa',
2815
+ description: 'Zigbee DIN energy meter',
2816
+ fromZigbee: [tuya.fz.datapoints],
2817
+ toZigbee: [tuya.tz.datapoints],
2818
+ configure: tuya.configureMagicPacket,
2819
+ exposes: [tuya.exposes.switch(), e.ac_frequency(), e.energy(), e.power(), e.power_factor(), e.voltage(), e.current(),
2820
+ e.produced_energy()],
2821
+ meta: {
2822
+ tuyaDatapoints: [
2823
+ [1, 'energy', tuya.valueConverter.divideBy100],
2824
+ [6, null, tuya.valueConverter.phaseVariant1], // voltage and current
2825
+ [16, 'state', tuya.valueConverter.onOff],
2826
+ [102, 'produced_energy', tuya.valueConverter.divideBy100],
2827
+ [103, 'power', tuya.valueConverter.raw],
2828
+ [105, 'ac_frequency', tuya.valueConverter.divideBy100],
2829
+ [111, 'power_factor', tuya.valueConverter.divideBy10],
2830
+ // Ignored for now; we don't know what the values mean
2831
+ [109, null, null], // reactive_power in VArh, ignored for now
2832
+ [101, null, null], // total active power (translated from chinese) - same as energy dp 1??
2833
+ [9, null, null], // Fault - we don't know the possible values here
2834
+ [110, null, null], // total reactive power (translated from chinese) - value is 0.03kvar, we already have kvarh on dp 109
2835
+ [17, null, null], // Alarm set1 - value seems garbage "AAAAAAAAAAAAAABkAAEOAACqAAAAAAAKAAAAAAAA"
2836
+ [18, null, null], // 18 - Alarm set2 - value seems garbage "AAUAZAAFAB4APAAAAAAAAAA="
2837
+ ],
2838
+ },
2839
+ whiteLabel: [{vendor: 'Hiking', model: 'DDS238-2'}, {vendor: 'TuYa', model: 'RC-MCB'}],
2840
+ },
2841
+ {
2842
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE200_lsanae15']),
2843
+ model: 'TS0601_din_2',
2844
+ vendor: 'TuYa',
2845
+ description: 'Zigbee DIN energy meter',
2846
+ fromZigbee: [tuya.fz.datapoints],
2847
+ toZigbee: [tuya.tz.datapoints],
2848
+ configure: tuya.configureMagicPacket,
2849
+ whiteLabel: [{vendor: 'XOCA', model: 'DAC2161C'}],
2850
+ exposes: [tuya.exposes.switch(), e.energy(), e.power(), e.voltage(), e.current(),
2851
+ exposes.enum('fault', ea.STATE, ['clear', 'over_current_threshold', 'over_power_threshold',
2852
+ 'over_voltage threshold', 'wrong_frequency_threshold']).withDescription('Fault status of the device (clear = nothing)'),
2853
+ exposes.enum('threshold_1', ea.STATE, ['not_set', 'over_current_threshold', 'over_voltage_threshold'])
2854
+ .withDescription('State of threshold_1'),
2855
+ exposes.binary('threshold_1_protection', ea.STATE, 'ON', 'OFF')
2856
+ .withDescription('OFF - alarm only, ON - relay will be off when threshold reached'),
2857
+ exposes.numeric('threshold_1_value', ea.STATE)
2858
+ .withDescription('Can be in Volt or Ampere depending on threshold setting. Setup the value on the device'),
2859
+ exposes.enum('threshold_2', ea.STATE, ['not_set', 'over_current_threshold', 'over_voltage_threshold'])
2860
+ .withDescription('State of threshold_2'),
2861
+ exposes.binary('threshold_2_protection', ea.STATE, 'ON', 'OFF')
2862
+ .withDescription('OFF - alarm only, ON - relay will be off when threshold reached'),
2863
+ exposes.numeric('threshold_2_value', ea.STATE)
2864
+ .withDescription('Setup value on the device'),
2865
+ exposes.binary('clear_fault', ea.STATE_SET, 'ON', 'OFF')
2866
+ .withDescription('Turn ON to clear last the fault'),
2867
+ exposes.text('meter_id', ea.STATE).withDescription('Meter ID (ID of device)'),
2868
+ ],
2869
+ meta: {
2870
+ tuyaDatapoints: [
2871
+ [1, 'energy', tuya.valueConverter.divideBy100],
2872
+ [3, null, null], // Monthly, but sends data only after request
2873
+ [4, null, null], // Dayly, but sends data only after request
2874
+ [6, null, tuya.valueConverter.phaseVariant2], // voltage and current
2875
+ [10, 'fault', tuya.valueConverterBasic.lookup({'clear': 0, 'over_current_threshold': 1,
2876
+ 'over_power_threshold': 2, 'over_voltage_threshold': 4, 'wrong_frequency_threshold': 8})],
2877
+ [11, null, null], // Frozen - strange function, in native app - nothing is clear
2878
+ [16, 'state', tuya.valueConverter.onOff],
2879
+ [17, null, tuya.valueConverter.threshold], // It's settable, but can't write converter
2880
+ [18, 'meter_id', tuya.valueConverter.raw],
2881
+ [20, 'clear_fault', tuya.valueConverter.onOff], // Clear fault
2882
+ [21, null, null], // Forward Energy T1 - don't know what this
2883
+ [22, null, null], // Forward Energy T2 - don't know what this
2884
+ [23, null, null], // Forward Energy T3 - don't know what this
2885
+ [24, null, null], // Forward Energy T4 - don't know what this
2886
+ ],
2887
+ },
2888
+ },
2889
+ {
2890
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE200_rhblgy0z']),
2891
+ model: 'TS0601_din_3',
2892
+ vendor: 'TuYa',
2893
+ description: 'Zigbee DIN energy meter',
2894
+ fromZigbee: [tuya.fz.datapoints],
2895
+ toZigbee: [tuya.tz.datapoints],
2896
+ configure: tuya.configureMagicPacket,
2897
+ whiteLabel: [{vendor: 'XOCA', model: 'DAC2161C'}],
2898
+ exposes: [tuya.exposes.switch(), e.energy(), e.produced_energy(), e.power(), e.voltage(), e.current(),
2899
+ exposes.enum('fault', ea.STATE, ['clear', 'over_current_threshold', 'over_power_threshold',
2900
+ 'over_voltage threshold', 'wrong_frequency_threshold']).withDescription('Fault status of the device (clear = nothing)'),
2901
+ exposes.enum('threshold_1', ea.STATE, ['not_set', 'over_current_threshold', 'over_voltage_threshold'])
2902
+ .withDescription('State of threshold_1'),
2903
+ exposes.binary('threshold_1_protection', ea.STATE, 'ON', 'OFF')
2904
+ .withDescription('OFF - alarm only, ON - relay will be off when threshold reached'),
2905
+ exposes.numeric('threshold_1_value', ea.STATE)
2906
+ .withDescription('Can be in Volt or Ampere depending on threshold setting. Setup the value on the device'),
2907
+ exposes.enum('threshold_2', ea.STATE, ['not_set', 'over_current_threshold', 'over_voltage_threshold'])
2908
+ .withDescription('State of threshold_2'),
2909
+ exposes.binary('threshold_2_protection', ea.STATE, 'ON', 'OFF')
2910
+ .withDescription('OFF - alarm only, ON - relay will be off when threshold reached'),
2911
+ exposes.numeric('threshold_2_value', ea.STATE)
2912
+ .withDescription('Setup value on the device'),
2913
+ exposes.binary('clear_fault', ea.STATE_SET, 'ON', 'OFF')
2914
+ .withDescription('Turn ON to clear last the fault'),
2915
+ exposes.text('meter_id', ea.STATE).withDescription('Meter ID (ID of device)'),
2916
+ ],
2917
+ meta: {
2918
+ tuyaDatapoints: [
2919
+ [1, 'energy', tuya.valueConverter.divideBy100],
2920
+ [2, 'produced_energy', tuya.valueConverter.divideBy100],
2921
+ [3, null, null], // Monthly, but sends data only after request
2922
+ [4, null, null], // Dayly, but sends data only after request
2923
+ [6, null, tuya.valueConverter.phaseVariant2], // voltage and current
2924
+ [10, 'fault', tuya.valueConverterBasic.lookup({'clear': 0, 'over_current_threshold': 1,
2925
+ 'over_power_threshold': 2, 'over_voltage_threshold': 4, 'wrong_frequency_threshold': 8})],
2926
+ [11, null, null], // Frozen - strange function, in native app - nothing is clear
2927
+ [16, 'state', tuya.valueConverter.onOff],
2928
+ [17, null, tuya.valueConverter.threshold], // It's settable, but can't write converter
2929
+ [18, 'meter_id', tuya.valueConverter.raw],
2930
+ [20, 'clear_fault', tuya.valueConverter.onOff], // Clear fault
2931
+ [21, null, null], // Forward Energy T1 - don't know what this
2932
+ [22, null, null], // Forward Energy T2 - don't know what this
2933
+ [23, null, null], // Forward Energy T3 - don't know what this
2934
+ [24, null, null], // Forward Energy T4 - don't know what this
2935
+ ],
2936
+ },
2937
+ },
2938
+ {
2939
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_byzdayie'},
2940
+ {modelID: 'TS0601', manufacturerName: '_TZE200_fsb6zw01'},
2941
+ {modelID: 'TS0601', manufacturerName: '_TZE200_ewxhg6o9'}],
2942
+ model: 'TS0601_din',
2943
+ vendor: 'TuYa',
2944
+ description: 'Zigbee smart energy meter DDS238-2 Zigbee',
2945
+ fromZigbee: [fz.tuya_dinrail_switch],
2946
+ toZigbee: [tz.tuya_switch_state],
2947
+ configure: async (device, coordinatorEndpoint, logger) => {
2948
+ const endpoint = device.getEndpoint(1);
2949
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
2950
+ },
2951
+ exposes: [e.switch().setAccess('state', ea.STATE_SET), e.voltage(), e.power(), e.current(), e.energy()],
2952
+ },
2953
+ {
2954
+ fingerprint: [{modelID: 'TS1101', manufacturerName: '_TZ3000_xfs39dbf'}],
2955
+ model: 'TS1101_dimmer_module_1ch',
2956
+ vendor: 'TuYa',
2957
+ description: 'Zigbee dimmer module 1 channel',
2958
+ extend: tuya.extend.light_onoff_brightness({minBrightness: true}),
2959
+ },
2960
+ {
2961
+ fingerprint: [{modelID: 'TS1101', manufacturerName: '_TZ3000_7ysdnebc'}],
2962
+ model: 'TS1101_dimmer_module_2ch',
2963
+ vendor: 'TuYa',
2964
+ description: 'Zigbee dimmer module 2 channel',
2965
+ whiteLabel: [{vendor: 'OXT', model: 'SWTZ25'}],
2966
+ extend: tuya.extend.light_onoff_brightness({minBrightness: true, endpoints: ['l1', 'l2'], noConfigure: true}),
2967
+ endpoint: (device) => {
2968
+ return {'l1': 1, 'l2': 2};
2969
+ },
2970
+ meta: {multiEndpoint: true},
2971
+ configure: async (device, coordinatorEndpoint, logger) => {
2972
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
2973
+ await tuya.extend.light_onoff_brightness().configure(device, coordinatorEndpoint, logger);
2974
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
2975
+ await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
2976
+ },
2977
+ },
2978
+ {
2979
+ zigbeeModel: ['RH3001'],
2980
+ fingerprint: [{type: 'EndDevice', manufacturerID: 4098, applicationVersion: 66, endpoints: [
2981
+ {ID: 1, profileID: 260, deviceID: 1026, inputClusters: [0, 10, 1, 1280], outputClusters: [25]},
2982
+ ]}],
2983
+ model: 'SNTZ007',
2984
+ vendor: 'TuYa',
2985
+ description: 'Rechargeable Zigbee contact sensor',
2986
+ fromZigbee: [fz.ias_contact_alarm_1, fz.battery, fz.ignore_basic_report, fz.ignore_time_read],
2987
+ toZigbee: [],
2988
+ exposes: [e.contact(), e.battery_low(), e.tamper(), e.battery()],
2989
+ whiteLabel: [{vendor: 'BlitzWolf', model: 'BW-IS2'}],
2990
+ },
2991
+ {
2992
+ zigbeeModel: ['RH3040'],
2993
+ model: 'RH3040',
2994
+ vendor: 'TuYa',
2995
+ description: 'PIR sensor',
2996
+ fromZigbee: [fz.battery, fz.ignore_basic_report, fz.ias_occupancy_alarm_1],
2997
+ toZigbee: [],
2998
+ whiteLabel: [{vendor: 'Samotech', model: 'SM301Z'}, {vendor: 'Nedis', model: 'ZBSM10WT'}],
2999
+ exposes: [e.battery(), e.occupancy(), e.battery_low(), e.tamper()],
3000
+ },
3001
+ {
3002
+ zigbeeModel: ['TS0115'],
3003
+ model: 'TS0115',
3004
+ vendor: 'TuYa',
3005
+ description: 'Multiprise with 4 AC outlets and 2 USB super charging ports (10A or 16A)',
3006
+ extend: tuya.extend.switch({endpoints: ['l1', 'l2', 'l3', 'l4', 'l5']}),
3007
+ whiteLabel: [{vendor: 'UseeLink', model: 'SM-SO306E/K/M'}],
3008
+ endpoint: (device) => {
3009
+ return {l1: 1, l2: 2, l3: 3, l4: 4, l5: 7};
3010
+ },
3011
+ meta: {multiEndpoint: true},
3012
+ configure: async (device, coordinatorEndpoint, logger) => {
3013
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
3014
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
3015
+ await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
3016
+ await reporting.bind(device.getEndpoint(3), coordinatorEndpoint, ['genOnOff']);
3017
+ await reporting.bind(device.getEndpoint(4), coordinatorEndpoint, ['genOnOff']);
3018
+ await reporting.bind(device.getEndpoint(7), coordinatorEndpoint, ['genOnOff']);
3019
+ await device.getEndpoint(1).read('genOnOff', ['onOff', 'moesStartUpOnOff']);
3020
+ await device.getEndpoint(2).read('genOnOff', ['onOff']);
3021
+ await device.getEndpoint(3).read('genOnOff', ['onOff']);
3022
+ await device.getEndpoint(4).read('genOnOff', ['onOff']);
3023
+ await device.getEndpoint(7).read('genOnOff', ['onOff']);
3024
+ },
3025
+ },
3026
+ {
3027
+ zigbeeModel: ['RH3052'],
3028
+ model: 'TT001ZAV20',
3029
+ vendor: 'TuYa',
3030
+ description: 'Temperature & humidity sensor',
3031
+ fromZigbee: [fz.humidity, fz.temperature, fz.battery],
3032
+ toZigbee: [],
3033
+ exposes: [e.humidity(), e.temperature(), e.battery()],
3034
+ },
3035
+ {
3036
+ fingerprint: [{modelID: 'TS0011', manufacturerName: '_TZ3000_l8fsgo6p'}],
3037
+ zigbeeModel: ['TS0011'],
3038
+ model: 'TS0011',
3039
+ vendor: 'TuYa',
3040
+ description: 'Smart light switch - 1 gang',
3041
+ extend: tuya.extend.switch({backlightModeOffNormalInverted: true}),
3042
+ whiteLabel: [
3043
+ {vendor: 'Vrey', model: 'VR-X712U-0013'},
3044
+ {vendor: 'TUYATEC', model: 'GDKES-01TZXD'},
3045
+ {vendor: 'Lonsonho', model: 'QS-Zigbee-S05-L', description: '1 gang smart switch module without neutral wire'},
3046
+ {vendor: 'Mercator Ikuü', model: 'SSW01'},
3047
+ ],
3048
+ configure: async (device, coordinatorEndpoint, logger) => {
3049
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
3050
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
3051
+ // Reports itself as battery which is not correct: https://github.com/Koenkk/zigbee2mqtt/issues/6190
3052
+ device.powerSource = 'Mains (single phase)';
3053
+ device.save();
3054
+ },
3055
+ },
3056
+ {
3057
+ fingerprint: [{modelID: 'TS0011', manufacturerName: '_TZ3000_qmi1cfuq'},
3058
+ {modelID: 'TS0011', manufacturerName: '_TZ3000_txpirhfq'}, {modelID: 'TS0011', manufacturerName: '_TZ3000_ji4araar'}],
3059
+ model: 'TS0011_switch_module',
3060
+ vendor: 'TuYa',
3061
+ description: '1 gang switch module - (without neutral)',
3062
+ extend: tuya.extend.switch({switchType: true}),
3063
+ whiteLabel: [{vendor: 'AVATTO', model: '1gang N-ZLWSM01'}, {vendor: 'SMATRUL', model: 'TMZ02L-16A-W'},
3064
+ {vendor: 'Aubess', model: 'TMZ02L-16A-B'}],
3065
+ configure: async (device, coordinatorEndpoint, logger) => {
3066
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
3067
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
3068
+ device.powerSource = 'Mains (single phase)';
3069
+ device.save();
3070
+ },
3071
+ },
3072
+ {
3073
+ zigbeeModel: ['TS0012'],
3074
+ model: 'TS0012',
3075
+ vendor: 'TuYa',
3076
+ description: 'Smart light switch - 2 gang',
3077
+ whiteLabel: [{vendor: 'Vrey', model: 'VR-X712U-0013'}, {vendor: 'TUYATEC', model: 'GDKES-02TZXD'},
3078
+ {vendor: 'Earda', model: 'ESW-2ZAA-EU'}, {vendor: 'Moes', model: 'ZS-US2-WH-MS'}, {vendor: 'Moes', model: 'ZS-US2-BK-MS'}],
3079
+ extend: tuya.extend.switch({backlightModeOffNormalInverted: true, endpoints: ['left', 'right']}),
3080
+ endpoint: (device) => {
3081
+ return {'left': 1, 'right': 2};
3082
+ },
3083
+ meta: {multiEndpoint: true},
3084
+ configure: async (device, coordinatorEndpoint, logger) => {
3085
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
3086
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
3087
+ await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
3088
+ device.powerSource = 'Mains (single phase)';
3089
+ device.save();
3090
+ },
3091
+ },
3092
+ {
3093
+ fingerprint: [{modelID: 'TS0012', manufacturerName: '_TZ3000_jl7qyupf'},
3094
+ {modelID: 'TS0012', manufacturerName: '_TZ3000_nPGIPl5D'},
3095
+ {modelID: 'TS0012', manufacturerName: '_TZ3000_4zf0crgo'}],
3096
+ model: 'TS0012_switch_module',
3097
+ vendor: 'TuYa',
3098
+ description: '2 gang switch module - (without neutral)',
3099
+ whiteLabel: [{vendor: 'AVATTO', model: '2gang N-ZLWSM01'}],
3100
+ extend: tuya.extend.switch({switchType: true, endpoints: ['left', 'right']}),
3101
+ endpoint: (device) => {
3102
+ return {'left': 1, 'right': 2};
3103
+ },
3104
+ meta: {multiEndpoint: true},
3105
+ configure: async (device, coordinatorEndpoint, logger) => {
3106
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
3107
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
3108
+ await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
3109
+ device.powerSource = 'Mains (single phase)';
3110
+ device.save();
3111
+ },
3112
+ },
3113
+ {
3114
+ zigbeeModel: ['TS0013'],
3115
+ model: 'TS0013',
3116
+ vendor: 'TuYa',
3117
+ description: 'Smart light switch - 3 gang without neutral wire',
3118
+ extend: tuya.extend.switch({backlightModeLowMediumHigh: true, endpoints: ['left', 'center', 'right']}),
3119
+ endpoint: (device) => {
3120
+ return {'left': 1, 'center': 2, 'right': 3};
3121
+ },
3122
+ whiteLabel: [{vendor: 'TUYATEC', model: 'GDKES-03TZXD'}],
3123
+ meta: {multiEndpoint: true},
3124
+ configure: async (device, coordinatorEndpoint, logger) => {
3125
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
3126
+ try {
3127
+ for (const ID of [1, 2, 3]) {
3128
+ const endpoint = device.getEndpoint(ID);
3129
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
3130
+ }
3131
+ } catch (e) {
3132
+ // Fails for some: https://github.com/Koenkk/zigbee2mqtt/issues/4872
3133
+ }
3134
+ device.powerSource = 'Mains (single phase)';
3135
+ device.save();
3136
+ },
3137
+ },
3138
+ {
3139
+ fingerprint: [{modelID: 'TS0013', manufacturerName: '_TZ3000_ypgri8yz'}],
3140
+ model: 'TS0013_switch_module',
3141
+ vendor: 'TuYa',
3142
+ description: '3 gang switch module - (without neutral)',
3143
+ whiteLabel: [{vendor: 'AVATTO', model: '3gang N-ZLWSM01'}],
3144
+ extend: tuya.extend.switch({switchType: true, endpoints: ['left', 'center', 'right']}),
3145
+ endpoint: (device) => {
3146
+ return {'left': 1, 'center': 2, 'right': 3};
3147
+ },
3148
+ meta: {multiEndpoint: true},
3149
+ configure: async (device, coordinatorEndpoint, logger) => {
3150
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
3151
+ try {
3152
+ for (const ID of [1, 2, 3]) {
3153
+ const endpoint = device.getEndpoint(ID);
3154
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
3155
+ }
3156
+ } catch (e) {
3157
+ // Fails for some: https://github.com/Koenkk/zigbee2mqtt/issues/4872
3158
+ }
3159
+ device.powerSource = 'Mains (single phase)';
3160
+ device.save();
3161
+ },
3162
+ },
3163
+ {
3164
+ fingerprint: tuya.fingerprint('TS0014', ['_TZ3000_jr2atpww', '_TYZB01_dvakyzhd', '_TZ3000_mrduubod',
3165
+ '_TZ3210_w3hl6rao', '_TYZB01_bagt1e4o', '_TZ3000_r0pmi2p3', '_TZ3000_fxjdcikv', '_TZ3000_q6vxaod1']),
3166
+ model: 'TS0014',
3167
+ vendor: 'TuYa',
3168
+ description: 'Smart light switch - 4 gang without neutral wire',
3169
+ extend: tuya.extend.switch({backlightModeLowMediumHigh: true, endpoints: ['l1', 'l2', 'l3', 'l4']}),
3170
+ endpoint: (device) => {
3171
+ return {'l1': 1, 'l2': 2, 'l3': 3, 'l4': 4};
3172
+ },
3173
+ whiteLabel: [{vendor: 'TUYATEC', model: 'GDKES-04TZXD'}, {vendor: 'Vizo', model: 'VZ-222S'},
3174
+ {vendor: 'MakeGood', model: 'MG-ZG04W/B/G'}, {vendor: 'Mercator Ikuü', model: 'SSW04'}],
3175
+ meta: {multiEndpoint: true},
3176
+ configure: async (device, coordinatorEndpoint, logger) => {
3177
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
3178
+ try {
3179
+ for (const ID of [1, 2, 3, 4]) {
3180
+ const endpoint = device.getEndpoint(ID);
3181
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
3182
+ }
3183
+ } catch (e) {
3184
+ // Fails for some: https://github.com/Koenkk/zigbee2mqtt/issues/4872
3185
+ }
3186
+ device.powerSource = 'Mains (single phase)';
3187
+ device.save();
3188
+ },
3189
+ },
3190
+ {
3191
+ zigbeeModel: ['gq8b1uv'],
3192
+ model: 'gq8b1uv',
3193
+ vendor: 'TuYa',
3194
+ description: 'Zigbee smart dimmer',
3195
+ fromZigbee: [fz.tuya_dimmer, fz.ignore_basic_report],
3196
+ toZigbee: [tz.tuya_dimmer_state, tz.tuya_dimmer_level],
3197
+ exposes: [e.light_brightness().setAccess('state', ea.STATE_SET).setAccess('brightness', ea.STATE_SET)],
3198
+ configure: async (device, coordinatorEndpoint, logger) => {
3199
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
3200
+ const endpoint = device.getEndpoint(1);
3201
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
3202
+ },
3203
+ },
3204
+ {
3205
+ zigbeeModel: ['HY0017', '005f0c3b'],
3206
+ model: 'U86KCJ-ZP',
3207
+ vendor: 'TuYa',
3208
+ description: 'Smart 6 key scene wall switch',
3209
+ fromZigbee: [fzLocal.scenes_recall_scene_65029],
3210
+ exposes: [e.action(['scene_1', 'scene_2', 'scene_3', 'scene_4', 'scene_5', 'scene_6'])],
3211
+ toZigbee: [],
3212
+ },
3213
+ {
3214
+ zigbeeModel: ['TS0026'],
3215
+ model: 'TS0026',
3216
+ vendor: 'TuYa',
3217
+ description: '6 button scene wall switch',
3218
+ fromZigbee: [fzLocal.scenes_recall_scene_65029],
3219
+ exposes: [e.action(['scene_1', 'scene_2', 'scene_3', 'scene_4', 'scene_5', 'scene_6'])],
3220
+ toZigbee: [],
3221
+ },
3222
+ {
3223
+ zigbeeModel: ['q9mpfhw'],
3224
+ model: 'SNTZ009',
3225
+ vendor: 'TuYa',
3226
+ description: 'Water leak sensor',
3227
+ fromZigbee: [fz.tuya_water_leak, fz.ignore_basic_report],
3228
+ exposes: [e.water_leak()],
3229
+ toZigbee: [],
3230
+ },
3231
+ {
3232
+ zigbeeModel: ['TS0004'],
3233
+ model: 'TS0004',
3234
+ vendor: 'TuYa',
3235
+ description: 'Smart light switch - 4 gang with neutral wire',
3236
+ fromZigbee: [fz.on_off, tuya.fz.power_on_behavior_2, fz.ignore_basic_report],
3237
+ toZigbee: [tz.on_off, tuya.tz.power_on_behavior_2],
3238
+ exposes: [e.switch().withEndpoint('l1'), e.power_on_behavior().withEndpoint('l1'), e.switch().withEndpoint('l2'),
3239
+ e.power_on_behavior().withEndpoint('l2'), e.switch().withEndpoint('l3'), e.power_on_behavior().withEndpoint('l3'),
3240
+ e.switch().withEndpoint('l4'), e.power_on_behavior().withEndpoint('l4')],
3241
+ endpoint: (device) => {
3242
+ return {'l1': 1, 'l2': 2, 'l3': 3, 'l4': 4};
3243
+ },
3244
+ meta: {multiEndpoint: true},
3245
+ configure: async (device, coordinatorEndpoint, logger) => {
3246
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
3247
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
3248
+ await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
3249
+ await reporting.bind(device.getEndpoint(3), coordinatorEndpoint, ['genOnOff']);
3250
+ await reporting.bind(device.getEndpoint(4), coordinatorEndpoint, ['genOnOff']);
3251
+ },
3252
+ },
3253
+ {
3254
+ fingerprint: [{modelID: 'TS0006', manufacturerName: '_TYZB01_ltundz9m'},
3255
+ {modelID: 'TS0006', manufacturerName: '_TZ3000_jyupj3fw'}],
3256
+ model: 'TS0006',
3257
+ vendor: 'TuYa',
3258
+ description: '6 gang switch module with neutral wire',
3259
+ extend: tuya.extend.switch(),
3260
+ exposes: [e.switch().withEndpoint('l1'), e.switch().withEndpoint('l2'), e.switch().withEndpoint('l3'),
3261
+ e.switch().withEndpoint('l4'), e.switch().withEndpoint('l5'), e.switch().withEndpoint('l6')],
3262
+ endpoint: (device) => {
3263
+ return {'l1': 1, 'l2': 2, 'l3': 3, 'l4': 4, 'l5': 5, 'l6': 6};
3264
+ },
3265
+ meta: {multiEndpoint: true},
3266
+ configure: async (device, coordinatorEndpoint, logger) => {
3267
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
3268
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
3269
+ await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
3270
+ await reporting.bind(device.getEndpoint(3), coordinatorEndpoint, ['genOnOff']);
3271
+ await reporting.bind(device.getEndpoint(4), coordinatorEndpoint, ['genOnOff']);
3272
+ await reporting.bind(device.getEndpoint(5), coordinatorEndpoint, ['genOnOff']);
3273
+ await reporting.bind(device.getEndpoint(6), coordinatorEndpoint, ['genOnOff']);
3274
+ },
3275
+ },
3276
+ {
3277
+ zigbeeModel: ['HY0080'],
3278
+ model: 'U86KWF-ZPSJ',
3279
+ vendor: 'TuYa',
3280
+ description: 'Environment controller',
3281
+ fromZigbee: [fz.legacy.thermostat_att_report, fz.fan],
3282
+ toZigbee: [tz.thermostat_local_temperature, tz.thermostat_local_temperature_calibration,
3283
+ tz.thermostat_occupancy, tz.thermostat_occupied_heating_setpoint, tz.thermostat_unoccupied_heating_setpoint,
3284
+ tz.thermostat_occupied_cooling_setpoint, tz.thermostat_unoccupied_cooling_setpoint,
3285
+ tz.thermostat_setpoint_raise_lower, tz.thermostat_remote_sensing,
3286
+ tz.thermostat_control_sequence_of_operation, tz.thermostat_system_mode, tz.thermostat_weekly_schedule,
3287
+ tz.thermostat_clear_weekly_schedule, tz.thermostat_relay_status_log,
3288
+ tz.thermostat_temperature_setpoint_hold, tz.thermostat_temperature_setpoint_hold_duration, tz.fan_mode],
3289
+ exposes: [exposes.climate().withSetpoint('occupied_heating_setpoint', 5, 30, 0.5).withLocalTemperature()
3290
+ .withSystemMode(['off', 'auto', 'heat'], ea.ALL)
3291
+ .withRunningState(['idle', 'heat', 'cool'], ea.STATE)
3292
+ .withLocalTemperatureCalibration(-30, 30, 0.1, ea.ALL).withPiHeatingDemand()],
3293
+ configure: async (device, coordinatorEndpoint, logger) => {
3294
+ const endpoint = device.getEndpoint(9);
3295
+ await reporting.bind(endpoint, coordinatorEndpoint, ['hvacThermostat', 'hvacFanCtrl']);
3296
+ await reporting.thermostatTemperature(endpoint);
3297
+ await reporting.thermostatSystemMode(endpoint);
3298
+ await reporting.thermostatOccupiedHeatingSetpoint(endpoint);
3299
+ await reporting.thermostatUnoccupiedHeatingSetpoint(endpoint);
3300
+ await reporting.thermostatOccupiedCoolingSetpoint(endpoint);
3301
+ await reporting.thermostatUnoccupiedCoolingSetpoint(endpoint);
3302
+ await reporting.fanMode(endpoint);
3303
+ },
3304
+ },
3305
+ {
3306
+ zigbeeModel: ['6dfgetq'],
3307
+ model: 'D3-DPWK-TY',
3308
+ vendor: 'TuYa',
3309
+ description: 'HVAC controller',
3310
+ exposes: [exposes.climate().withSetpoint('current_heating_setpoint', 5, 30, 0.5, ea.STATE_SET)
3311
+ .withLocalTemperature(ea.STATE)
3312
+ .withSystemMode(['off', 'auto', 'heat'], ea.STATE_SET)
3313
+ .withRunningState(['idle', 'heat', 'cool'], ea.STATE)],
3314
+ fromZigbee: [fz.tuya_thermostat, fz.ignore_basic_report, fz.tuya_dimmer],
3315
+ meta: {tuyaThermostatSystemMode: tuya.thermostatSystemModes2, tuyaThermostatPreset: tuya.thermostatPresets},
3316
+ toZigbee: [tz.tuya_thermostat_current_heating_setpoint, tz.tuya_thermostat_system_mode,
3317
+ tz.tuya_thermostat_fan_mode, tz.tuya_dimmer_state],
3318
+ },
3319
+ {
3320
+ zigbeeModel: ['E220-KR4N0Z0-HA', 'JZ-ZB-004'],
3321
+ model: 'E220-KR4N0Z0-HA',
3322
+ vendor: 'TuYa',
3323
+ description: 'Multiprise with 4 AC outlets and 2 USB super charging ports (16A)',
3324
+ extend: tuya.extend.switch(),
3325
+ fromZigbee: [fz.on_off_skip_duplicate_transaction],
3326
+ exposes: [e.switch().withEndpoint('l1'), e.switch().withEndpoint('l2'), e.switch().withEndpoint('l3'),
3327
+ e.switch().withEndpoint('l4')],
3328
+ whiteLabel: [{vendor: 'LEELKI', model: 'WP33-EU'}],
3329
+ meta: {multiEndpoint: true},
3330
+ endpoint: (device) => {
3331
+ return {l1: 1, l2: 2, l3: 3, l4: 4};
3332
+ },
3333
+ configure: async (device, coordinatorEndpoint, logger) => {
3334
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
3335
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff']);
3336
+ await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff']);
3337
+ await reporting.bind(device.getEndpoint(3), coordinatorEndpoint, ['genOnOff']);
3338
+ await reporting.bind(device.getEndpoint(4), coordinatorEndpoint, ['genOnOff']);
3339
+ },
3340
+ },
3341
+ {
3342
+ zigbeeModel: ['TS0216'],
3343
+ model: 'TS0216',
3344
+ vendor: 'TuYa',
3345
+ description: 'Sound and flash siren',
3346
+ fromZigbee: [fz.ts0216_siren, fz.battery],
3347
+ exposes: [e.battery(), exposes.binary('alarm', ea.STATE_SET, true, false),
3348
+ exposes.numeric('volume', ea.ALL).withValueMin(0).withValueMax(100).withDescription('Volume of siren')],
3349
+ toZigbee: [tz.ts0216_alarm, tz.ts0216_duration, tz.ts0216_volume],
3350
+ configure: async (device, coordinatorEndpoint, logger) => {
3351
+ const endpoint = device.getEndpoint(1);
3352
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
3353
+ // Device advertises itself as Router but is an EndDevice
3354
+ device.type = 'EndDevice';
3355
+ device.save();
3356
+ },
3357
+ },
3358
+ {
3359
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_znzs7yaw'}],
3360
+ model: 'HY08WE',
3361
+ vendor: 'TuYa',
3362
+ description: 'Wall-mount thermostat',
3363
+ fromZigbee: [fz.hy_thermostat, fz.ignore_basic_report],
3364
+ toZigbee: [tz.hy_thermostat],
3365
+ onEvent: tuya.onEventSetTime,
3366
+ exposes: [exposes.climate().withSetpoint('current_heating_setpoint', 5, 30, 0.5, ea.STATE_SET)
3367
+ .withLocalTemperature(ea.STATE)
3368
+ .withSystemMode(['off', 'auto', 'heat'], ea.STATE_SET).withRunningState(['idle', 'heat'], ea.STATE)],
3369
+ },
3370
+ {
3371
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_2ekuz3dz'}],
3372
+ model: 'X5H-GB-B',
3373
+ vendor: 'TuYa',
3374
+ description: 'Wall-mount thermostat',
3375
+ fromZigbee: [fz.ignore_basic_report, fzLocal.x5h_thermostat],
3376
+ toZigbee: [tzLocal.x5h_thermostat],
3377
+ whiteLabel: [{vendor: 'Beok', model: 'TGR85-ZB'}],
3378
+ exposes: [
3379
+ exposes.climate().withSetpoint('current_heating_setpoint', 5, 60, 0.5, ea.STATE_SET)
3380
+ .withLocalTemperature(ea.STATE).withLocalTemperatureCalibration(-9.9, 9.9, 0.1, ea.STATE_SET)
3381
+ .withSystemMode(['off', 'heat'], ea.STATE_SET).withRunningState(['idle', 'heat'], ea.STATE)
3382
+ .withPreset(['manual', 'program']),
3383
+ e.temperature_sensor_select(['internal', 'external', 'both']),
3384
+ exposes.text('schedule', ea.STATE_SET).withDescription('There are 8 periods in the schedule in total. ' +
3385
+ '6 for workdays and 2 for holidays. It should be set in the following format for each of the periods: ' +
3386
+ '`hours:minutes/temperature`. All periods should be set at once and delimited by the space symbol. ' +
3387
+ 'For example: `06:00/20.5 08:00/15 11:30/15 13:30/15 17:00/22 22:00/15 06:00/20 22:00/15`. ' +
3388
+ 'The thermostat doesn\'t report the schedule by itself even if you change it manually from device'),
3389
+ e.child_lock(), e.week(),
3390
+ exposes.enum('brightness_state', ea.STATE_SET, ['off', 'low', 'medium', 'high'])
3391
+ .withDescription('Screen brightness'),
3392
+ exposes.binary('sound', ea.STATE_SET, 'ON', 'OFF')
3393
+ .withDescription('Switches beep sound when interacting with thermostat'),
3394
+ exposes.binary('frost_protection', ea.STATE_SET, 'ON', 'OFF')
3395
+ .withDescription('Antifreeze function'),
3396
+ exposes.binary('factory_reset', ea.STATE_SET, 'ON', 'OFF')
3397
+ .withDescription('Resets all settings to default. Doesn\'t unpair device.'),
3398
+ exposes.numeric('heating_temp_limit', ea.STATE_SET).withUnit('°C').withValueMax(60)
3399
+ .withValueMin(5).withValueStep(1).withPreset('default', 35, 'Default value')
3400
+ .withDescription('Heating temperature limit'),
3401
+ exposes.numeric('deadzone_temperature', ea.STATE_SET).withUnit('°C').withValueMax(9.5)
3402
+ .withValueMin(0.5).withValueStep(0.5).withPreset('default', 1, 'Default value')
3403
+ .withDescription('The delta between local_temperature and current_heating_setpoint to trigger Heat'),
3404
+ exposes.numeric('upper_temp', ea.STATE_SET).withUnit('°C').withValueMax(95)
3405
+ .withValueMin(35).withValueStep(1).withPreset('default', 60, 'Default value'),
3406
+ ],
3407
+ onEvent: tuya.onEventSetTime,
3408
+ },
3409
+ {
3410
+ fingerprint: [{modelID: 'TS0222', manufacturerName: '_TYZB01_4mdqxxnn'},
3411
+ {modelID: 'TS0222', manufacturerName: '_TYZB01_m6ec2pgj'}],
3412
+ model: 'TS0222',
3413
+ vendor: 'TuYa',
3414
+ description: 'Light intensity sensor',
3415
+ fromZigbee: [fz.battery, fz.illuminance, fzLocal.TS0222],
3416
+ toZigbee: [],
3417
+ exposes: [e.battery(), e.illuminance(), e.illuminance_lux()],
3418
+ configure: tuya.configureMagicPacket,
3419
+ },
3420
+ {
3421
+ fingerprint: [{modelID: 'TS0210', manufacturerName: '_TYZB01_3zv6oleo'},
3422
+ {modelID: 'TS0210', manufacturerName: '_TYZB01_j9xxahcl'},
3423
+ {modelID: 'TS0210', manufacturerName: '_TYZB01_kulduhbj'},
3424
+ {modelID: 'TS0210', manufacturerName: '_TYZB01_cc3jzhlj'},
3425
+ {modelID: 'TS0210', manufacturerName: '_TZ3000_bmfw9ykl'},
3426
+ {modelID: 'TS0210', manufacturerName: '_TYZB01_geigpsy4'},
3427
+ {modelID: 'TS0210', manufacturerName: '_TZ3000_fkxmyics'}],
3428
+ model: 'TS0210',
3429
+ vendor: 'TuYa',
3430
+ description: 'Vibration sensor',
3431
+ fromZigbee: [fz.battery, fz.ias_vibration_alarm_1_with_timeout],
3432
+ toZigbee: [tz.TS0210_sensitivity],
3433
+ exposes: [e.battery(), e.battery_voltage(), e.vibration(), exposes.enum('sensitivity', ea.STATE_SET, ['low', 'medium', 'high'])],
3434
+ },
3435
+ {
3436
+ fingerprint: [{modelID: 'TS011F', manufacturerName: '_TZ3000_8bxrzyxz'},
3437
+ {modelID: 'TS011F', manufacturerName: '_TZ3000_ky0fq4ho'}, {modelID: 'TS011F', manufacturerName: '_TZ3000_qeuvnohg'}],
3438
+ model: 'TS011F_din_smart_relay',
3439
+ description: 'Din smart relay (with power monitoring)',
3440
+ vendor: 'TuYa',
3441
+ fromZigbee: [fz.on_off, fz.electrical_measurement, fz.metering, fz.ignore_basic_report, tuya.fz.power_outage_memory,
3442
+ fz.tuya_relay_din_led_indicator],
3443
+ toZigbee: [tz.on_off, tuya.tz.power_on_behavior_1, tz.tuya_relay_din_led_indicator],
3444
+ whiteLabel: [{vendor: 'MatSee Plus', model: 'ATMS1602Z'}, {vendor: 'Tongou', model: 'TO-Q-SY1-JZT'}],
3445
+ ota: ota.zigbeeOTA,
3446
+ configure: async (device, coordinatorEndpoint, logger) => {
3447
+ const endpoint = device.getEndpoint(1);
3448
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'haElectricalMeasurement', 'seMetering']);
3449
+ await reporting.rmsVoltage(endpoint, {change: 5});
3450
+ await reporting.rmsCurrent(endpoint, {change: 50});
3451
+ await reporting.activePower(endpoint, {change: 10});
3452
+ await reporting.currentSummDelivered(endpoint);
3453
+ endpoint.saveClusterAttributeKeyValue('haElectricalMeasurement', {acCurrentDivisor: 1000, acCurrentMultiplier: 1});
3454
+ endpoint.saveClusterAttributeKeyValue('seMetering', {divisor: 100, multiplier: 1});
3455
+ device.save();
3456
+ },
3457
+ exposes: [e.switch(), e.power(), e.current(), e.voltage(),
3458
+ e.energy(), exposes.enum('power_outage_memory', ea.ALL, ['on', 'off', 'restore'])
3459
+ .withDescription('Recover state after power outage'),
3460
+ exposes.enum('indicator_mode', ea.STATE_SET, ['off', 'on_off', 'off_on'])
3461
+ .withDescription('Relay LED indicator mode')],
3462
+ },
3463
+ {
3464
+ fingerprint: [{modelID: 'TS011F', manufacturerName: '_TZ3000_7issjl2q'}],
3465
+ model: 'ATMS1601Z',
3466
+ description: 'Din smart relay (without power monitoring)',
3467
+ vendor: 'TuYa',
3468
+ fromZigbee: [fz.on_off, fz.ignore_basic_report, tuya.fz.power_outage_memory, fz.tuya_relay_din_led_indicator],
3469
+ toZigbee: [tz.on_off, tuya.tz.power_on_behavior_1, tz.tuya_relay_din_led_indicator],
3470
+ configure: async (device, coordinatorEndpoint, logger) => {
3471
+ const endpoint = device.getEndpoint(1);
3472
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
3473
+ device.save();
3474
+ },
3475
+ exposes: [e.switch(),
3476
+ exposes.enum('power_outage_memory', ea.ALL, ['on', 'off', 'restore'])
3477
+ .withDescription('Recover state after power outage'),
3478
+ exposes.enum('indicator_mode', ea.STATE_SET, ['off', 'on_off', 'off_on'])
3479
+ .withDescription('Relay LED indicator mode')],
3480
+ },
3481
+ {
3482
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_nklqjk62'}],
3483
+ model: 'PJ-ZGD01',
3484
+ vendor: 'TuYa',
3485
+ description: 'Garage door opener',
3486
+ fromZigbee: [fz.matsee_garage_door_opener, fz.ignore_basic_report],
3487
+ toZigbee: [tz.matsee_garage_door_opener, tz.tuya_data_point_test],
3488
+ whiteLabel: [{vendor: 'MatSee Plus', model: 'PJ-ZGD01'}],
3489
+ configure: async (device, coordinatorEndpoint, logger) => {
3490
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
3491
+ const endpoint = device.getEndpoint(1);
3492
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genBasic']);
3493
+ },
3494
+ exposes: [exposes.binary('trigger', ea.STATE_SET, true, false).withDescription('Trigger the door movement'),
3495
+ exposes.binary('garage_door_contact', ea.STATE, true, false)],
3496
+ },
3497
+ {
3498
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_wfxuhoea'}],
3499
+ model: 'GDC311ZBQ1',
3500
+ vendor: 'TuYa',
3501
+ description: 'LoraTap garage door opener with wireless sensor',
3502
+ fromZigbee: [fz.matsee_garage_door_opener, fz.ignore_basic_report],
3503
+ toZigbee: [tz.matsee_garage_door_opener, tz.tuya_data_point_test],
3504
+ whiteLabel: [{vendor: 'LoraTap', model: 'GDC311ZBQ1'}],
3505
+ configure: async (device, coordinatorEndpoint, logger) => {
3506
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
3507
+ const endpoint = device.getEndpoint(1);
3508
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genBasic']);
3509
+ },
3510
+ exposes: [exposes.binary('trigger', ea.STATE_SET, true, false).withDescription('Trigger the door movement'),
3511
+ exposes.binary('garage_door_contact', ea.STATE, false, true)
3512
+ .withDescription('Indicates if the garage door contact is closed (= true) or open (= false)')],
3513
+ },
3514
+ {
3515
+ fingerprint: [{modelID: 'TS0201', manufacturerName: '_TZ3000_qaaysllp'}],
3516
+ model: 'LCZ030',
3517
+ vendor: 'TuYa',
3518
+ description: 'Temperature & humidity & illuminance sensor with display',
3519
+ fromZigbee: [fz.battery, fz.illuminance, fz.temperature, fz.humidity, fz.ts0201_temperature_humidity_alarm],
3520
+ toZigbee: [tz.ts0201_temperature_humidity_alarm],
3521
+ configure: async (device, coordinatorEndpoint, logger) => {
3522
+ const endpoint = device.getEndpoint(1);
3523
+ // Enables reporting of measurement state changes
3524
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
3525
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genBasic', 'genPowerCfg',
3526
+ 'msTemperatureMeasurement', 'msIlluminanceMeasurement', 'msRelativeHumidity', 'manuSpecificTuya_2']);
3527
+ },
3528
+ exposes: [e.temperature(), e.humidity(), e.battery(), e.illuminance(), e.illuminance_lux(),
3529
+ exposes.numeric('alarm_temperature_max', ea.STATE_SET).withUnit('°C').withDescription('Alarm temperature max')
3530
+ .withValueMin(-20).withValueMax(80),
3531
+ exposes.numeric('alarm_temperature_min', ea.STATE_SET).withUnit('°C').withDescription('Alarm temperature min')
3532
+ .withValueMin(-20).withValueMax(80),
3533
+ exposes.numeric('alarm_humidity_max', ea.STATE_SET).withUnit('%').withDescription('Alarm humidity max')
3534
+ .withValueMin(0).withValueMax(100),
3535
+ exposes.numeric('alarm_humidity_min', ea.STATE_SET).withUnit('%').withDescription('Alarm humidity min')
3536
+ .withValueMin(0).withValueMax(100),
3537
+ exposes.enum('alarm_humidity', ea.STATE, ['below_min_humdity', 'over_humidity', 'off'])
3538
+ .withDescription('Alarm humidity status'),
3539
+ exposes.enum('alarm_temperature', ea.STATE, ['below_min_temperature', 'over_temperature', 'off'])
3540
+ .withDescription('Alarm temperature status'),
3541
+ ],
3542
+ },
3543
+ {
3544
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_auin8mzr'}],
3545
+ model: 'TS0601_motion_sensor',
3546
+ vendor: 'TuYa',
3547
+ description: 'Human presence sensor AIR',
3548
+ fromZigbee: [fz.tuya_motion_sensor],
3549
+ toZigbee: [tz.tuya_motion_sensor],
3550
+ exposes: [
3551
+ e.occupancy(),
3552
+ exposes.enum('o_sensitivity', ea.STATE_SET, Object.values(tuya.msLookups.OSensitivity)).withDescription('O-Sensitivity mode'),
3553
+ exposes.enum('v_sensitivity', ea.STATE_SET, Object.values(tuya.msLookups.VSensitivity)).withDescription('V-Sensitivity mode'),
3554
+ exposes.enum('led_status', ea.STATE_SET, ['ON', 'OFF']).withDescription('Led status switch'),
3555
+ exposes.numeric('vacancy_delay', ea.STATE_SET).withUnit('sec').withDescription('Vacancy delay').withValueMin(0)
3556
+ .withValueMax(1000),
3557
+ exposes.numeric('light_on_luminance_prefer', ea.STATE_SET).withDescription('Light-On luminance prefer')
3558
+ .withValueMin(0).withValueMax(10000),
3559
+ exposes.numeric('light_off_luminance_prefer', ea.STATE_SET).withDescription('Light-Off luminance prefer')
3560
+ .withValueMin(0).withValueMax(10000),
3561
+ exposes.enum('mode', ea.STATE_SET, Object.values(tuya.msLookups.Mode)).withDescription('Working mode'),
3562
+ exposes.numeric('luminance_level', ea.STATE).withDescription('Luminance level'),
3563
+ exposes.numeric('reference_luminance', ea.STATE).withDescription('Reference luminance'),
3564
+ exposes.numeric('vacant_confirm_time', ea.STATE).withDescription('Vacant confirm time'),
3565
+ ],
3566
+ },
3567
+ {
3568
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE200_lu01t0zl', '_TZE200_vrfecyku']),
3569
+ model: 'MIR-HE200-TY',
3570
+ vendor: 'TuYa',
3571
+ description: 'Human presence sensor with fall function',
3572
+ fromZigbee: [tuya.fz.datapoints],
3573
+ toZigbee: [tuya.tz.datapoints],
3574
+ configure: async (device, coordinatorEndpoint, logger) => {
3575
+ const endpoint = device.getEndpoint(1);
3576
+ await tuya.sendDataPointEnum(endpoint, tuya.dataPoints.trsfTumbleSwitch, false);
3577
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
3578
+ },
3579
+ exposes: [
3580
+ e.illuminance_lux(), e.presence(), e.occupancy(),
3581
+ exposes.numeric('motion_speed', ea.STATE).withDescription('Speed of movement'),
3582
+ exposes.enum('motion_direction', ea.STATE, ['standing_still', 'moving_forward', 'moving_backward'])
3583
+ .withDescription('direction of movement from the point of view of the radar'),
3584
+ exposes.numeric('radar_sensitivity', ea.STATE_SET).withValueMin(0).withValueMax(10).withValueStep(1)
3585
+ .withDescription('Sensitivity of the radar'),
3586
+ exposes.enum('radar_scene', ea.STATE_SET, ['default', 'area', 'toilet', 'bedroom', 'parlour', 'office', 'hotel'])
3587
+ .withDescription('Presets for sensitivity for presence and movement'),
3588
+ exposes.enum('tumble_switch', ea.STATE_SET, ['ON', 'OFF']).withDescription('Tumble status switch'),
3589
+ exposes.numeric('fall_sensitivity', ea.STATE_SET).withValueMin(1).withValueMax(10).withValueStep(1)
3590
+ .withDescription('Fall sensitivity of the radar'),
3591
+ exposes.numeric('tumble_alarm_time', ea.STATE_SET).withValueMin(1).withValueMax(5).withValueStep(1)
3592
+ .withUnit('min').withDescription('Tumble alarm time'),
3593
+ exposes.enum('fall_down_status', ea.STATE, ['none', 'maybe_fall', 'fall'])
3594
+ .withDescription('Fall down status'),
3595
+ exposes.text('static_dwell_alarm', ea.STATE).withDescription('Static dwell alarm'),
3596
+ ],
3597
+ meta: {
3598
+ tuyaDatapoints: [
3599
+ [1, 'presence', tuya.valueConverter.trueFalse1],
3600
+ [2, 'radar_sensitivity', tuya.valueConverter.raw],
3601
+ [102, 'occupancy', tuya.valueConverter.trueFalse1],
3602
+ [103, 'illuminance_lux', tuya.valueConverter.raw],
3603
+ [105, 'tumble_switch', tuya.valueConverter.plus1],
3604
+ [106, 'tumble_alarm_time', tuya.valueConverter.raw],
3605
+ [112, 'radar_scene', tuya.valueConverterBasic.lookup(
3606
+ {'default': 0, 'area': 1, 'toilet': 2, 'bedroom': 3, 'parlour': 4, 'office': 5, 'hotel': 6})],
3607
+ [114, 'motion_direction', tuya.valueConverterBasic.lookup(
3608
+ {'standing_still': 0, 'moving_forward': 1, 'moving_backward': 2})],
3609
+ [115, 'motion_speed', tuya.valueConverter.raw],
3610
+ [116, 'fall_down_status', tuya.valueConverterBasic.lookup({'none': 0, 'maybe_fall': 1, 'fall': 2})],
3611
+ [117, 'static_dwell_alarm', tuya.valueConverter.raw],
3612
+ [118, 'fall_sensitivity', tuya.valueConverter.raw],
3613
+ // Below are ignored
3614
+ [101, null, null], // reset_flag_code
3615
+ [104, null, null], // detection_flag_code
3616
+ [107, null, null], // radar_check_end_code
3617
+ [108, null, null], // radar_check_start_code
3618
+ [109, null, null], // hw_version_code
3619
+ [110, null, null], // sw_version_code
3620
+ [111, null, null], // radar_id_code
3621
+ ],
3622
+ },
3623
+ },
3624
+ {
3625
+ zigbeeModel: ['TS0046'],
3626
+ model: 'TS0046',
3627
+ vendor: 'TuYa',
3628
+ description: 'Wireless switch with 6 buttons',
3629
+ whiteLabel: [{vendor: 'LoraTap', model: 'SS9600ZB'}],
3630
+ fromZigbee: [fz.tuya_on_off_action, fz.battery],
3631
+ exposes: [e.battery(), e.action(['1_single', '1_double', '1_hold', '2_single', '2_double', '2_hold',
3632
+ '3_single', '3_double', '3_hold', '4_single', '4_double', '4_hold',
3633
+ '5_single', '5_double', '5_hold', '6_single', '6_double', '6_hold'])],
3634
+ toZigbee: [],
3635
+ configure: tuya.configureMagicPacket,
3636
+ },
3637
+ {
3638
+ fingerprint: [{modelID: 'TS004F', manufacturerName: '_TZ3000_pcqjmcud'}],
3639
+ model: 'YSR-MINI-Z',
3640
+ vendor: 'TuYa',
3641
+ description: '2 in 1 dimming remote control and scene control',
3642
+ exposes: [
3643
+ e.battery(),
3644
+ e.action(['on', 'off',
3645
+ 'brightness_move_up', 'brightness_step_up', 'brightness_step_down', 'brightness_move_down', 'brightness_stop',
3646
+ 'color_temperature_step_down', 'color_temperature_step_up',
3647
+ '1_single', '1_double', '1_hold', '2_single', '2_double', '2_hold',
3648
+ '3_single', '3_double', '3_hold', '4_single', '4_double', '4_hold',
3649
+ ]),
3650
+ exposes.enum('operation_mode', ea.ALL, ['command', 'event']).withDescription(
3651
+ 'Operation mode: "command" - for group control, "event" - for clicks'),
3652
+ ],
3653
+ fromZigbee: [fz.battery, fz.command_on, fz.command_off, fz.command_step, fz.command_move, fz.command_stop,
3654
+ fz.command_step_color_temperature, fz.tuya_on_off_action, fz.tuya_operation_mode],
3655
+ toZigbee: [tz.tuya_operation_mode],
3656
+ onEvent: tuya.onEventSetLocalTime,
3657
+ configure: async (device, coordinatorEndpoint, logger) => {
3658
+ const endpoint = device.getEndpoint(1);
3659
+ await endpoint.read('genBasic', [0x0004, 0x000, 0x0001, 0x0005, 0x0007, 0xfffe]);
3660
+ await endpoint.write('genOnOff', {'tuyaOperationMode': 1});
3661
+ await endpoint.read('genOnOff', ['tuyaOperationMode']);
3662
+ try {
3663
+ await endpoint.read(0xE001, [0xD011]);
3664
+ } catch (err) {/* do nothing */}
3665
+ await endpoint.read('genPowerCfg', ['batteryVoltage', 'batteryPercentageRemaining']);
3666
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
3667
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
3668
+ await reporting.batteryPercentageRemaining(endpoint);
3669
+ },
3670
+ },
3671
+ {
3672
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_hkdl5fmv'}],
3673
+ model: 'TS0601_rcbo',
3674
+ vendor: 'TuYa',
3675
+ whiteLabel: [
3676
+ {vendor: 'HOCH', model: 'ZJSBL7-100Z'},
3677
+ {vendor: 'WDYK', model: 'ZJSBL7-100Z'},
3678
+ ],
3679
+ description: 'DIN mount RCBO with smart energy metering',
3680
+ fromZigbee: [fz.hoch_din],
3681
+ toZigbee: [tz.hoch_din],
3682
+ exposes: [
3683
+ exposes.text('meter_number', ea.STATE),
3684
+ exposes.binary('state', ea.STATE_SET, 'ON', 'OFF'),
3685
+ exposes.text('alarm', ea.STATE),
3686
+ exposes.binary('trip', ea.STATE_SET, 'trip', 'clear'),
3687
+ exposes.binary('child_lock', ea.STATE_SET, 'ON', 'OFF'),
3688
+ exposes.enum('power_on_behavior', ea.STATE_SET, ['off', 'on', 'previous']),
3689
+ exposes.numeric('countdown_timer', ea.STATE_SET).withValueMin(0).withValueMax(86400).withUnit('s'),
3690
+ exposes.numeric('voltage_rms', ea.STATE).withUnit('V'),
3691
+ exposes.numeric('current', ea.STATE).withUnit('A'),
3692
+ exposes.numeric('current_average', ea.STATE).withUnit('A'),
3693
+ e.power(), e.voltage(), e.energy(), e.temperature(),
3694
+ exposes.numeric('energy_consumed', ea.STATE).withUnit('kWh'),
3695
+ exposes.enum('clear_device_data', ea.SET, ['']),
3696
+ ],
3697
+ },
3698
+ {
3699
+ fingerprint: [{modelID: 'TS004F', manufacturerName: '_TZ3000_4fjiwweb'}, {modelID: 'TS004F', manufacturerName: '_TZ3000_uri7ongn'},
3700
+ {modelID: 'TS004F', manufacturerName: '_TZ3000_ixla93vd'}, {modelID: 'TS004F', manufacturerName: '_TZ3000_qja6nq5z'}],
3701
+ model: 'ERS-10TZBVK-AA',
3702
+ vendor: 'TuYa',
3703
+ description: 'Smart knob',
3704
+ fromZigbee: [
3705
+ fz.command_step, fz.command_toggle, fz.command_move_hue, fz.command_step_color_temperature, fz.command_stop_move_raw,
3706
+ fz.tuya_multi_action, fz.tuya_operation_mode, fz.battery,
3707
+ ],
3708
+ toZigbee: [tz.tuya_operation_mode],
3709
+ exposes: [
3710
+ e.action([
3711
+ 'toggle', 'brightness_step_up', 'brightness_step_down', 'color_temperature_step_up', 'color_temperature_step_down',
3712
+ 'saturation_move', 'hue_move', 'hue_stop', 'single', 'double', 'hold', 'rotate_left', 'rotate_right',
3713
+ ]),
3714
+ exposes.numeric('action_step_size', ea.STATE).withValueMin(0).withValueMax(255),
3715
+ exposes.numeric('action_transition_time', ea.STATE).withUnit('s'),
3716
+ exposes.numeric('action_rate', ea.STATE).withValueMin(0).withValueMax(255),
3717
+ e.battery(),
3718
+ exposes.enum('operation_mode', ea.ALL, ['command', 'event']).withDescription(
3719
+ 'Operation mode: "command" - for group control, "event" - for clicks'),
3720
+ ],
3721
+ configure: async (device, coordinatorEndpoint, logger) => {
3722
+ const endpoint = device.getEndpoint(1);
3723
+ await endpoint.read('genBasic', [0x0004, 0x000, 0x0001, 0x0005, 0x0007, 0xfffe]);
3724
+ await endpoint.write('genOnOff', {'tuyaOperationMode': 1});
3725
+ await endpoint.read('genOnOff', ['tuyaOperationMode']);
3726
+ try {
3727
+ await endpoint.read(0xE001, [0xD011]);
3728
+ } catch (err) {/* do nothing */}
3729
+ await endpoint.read('genPowerCfg', ['batteryVoltage', 'batteryPercentageRemaining']);
3730
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
3731
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
3732
+ await reporting.batteryPercentageRemaining(endpoint);
3733
+ },
3734
+ },
3735
+ {
3736
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_kzm5w4iz'}],
3737
+ model: 'TS0601_vibration_sensor',
3738
+ vendor: 'TuYa',
3739
+ description: 'Smart vibration sensor',
3740
+ fromZigbee: [fz.tuya_smart_vibration_sensor],
3741
+ toZigbee: [],
3742
+ exposes: [e.contact(), e.battery(), e.vibration()],
3743
+ },
3744
+ {
3745
+ fingerprint: [{modelID: `TS0601`, manufacturerName: `_TZE200_yi4jtqq1`}, {modelID: `TS0601`, manufacturerName: `_TZE200_khx7nnka`}],
3746
+ model: `XFY-CGQ-ZIGB`,
3747
+ vendor: `TuYa`,
3748
+ description: `Illuminance sensor`,
3749
+ fromZigbee: [fz.tuya_illuminance_sensor],
3750
+ toZigbee: [],
3751
+ exposes: [e.illuminance_lux(), e.brightness_state()],
3752
+ },
3753
+ {
3754
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_kltffuzl'}, {modelID: 'TS0601', manufacturerName: '_TZE200_fwoorn8y'}],
3755
+ model: 'TM001-ZA/TM081',
3756
+ vendor: 'TuYa',
3757
+ description: 'Door and window sensor',
3758
+ fromZigbee: [fz.tm081],
3759
+ toZigbee: [],
3760
+ exposes: [e.contact(), e.battery()],
3761
+ },
3762
+ {
3763
+ fingerprint: [{modelID: `TS0601`, manufacturerName: `_TZE200_2m38mh6k`}],
3764
+ model: 'SS9600ZB',
3765
+ vendor: 'TuYa',
3766
+ description: '6 gang remote',
3767
+ exposes: [e.battery(),
3768
+ e.action(['1_single', '1_double', '1_hold', '2_single', '2_double', '2_hold', '3_single', '3_double', '3_hold',
3769
+ '4_single', '4_double', '4_hold', '5_single', '5_double', '5_hold', '6_single', '6_double', '6_hold'])],
3770
+ fromZigbee: [fz.tuya_remote],
3771
+ toZigbee: [],
3772
+ },
3773
+ {
3774
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_ikvncluo'},
3775
+ {modelID: 'TS0601', manufacturerName: '_TZE200_lyetpprm'},
3776
+ {modelID: 'TS0601', manufacturerName: '_TZE200_jva8ink8'},
3777
+ {modelID: 'TS0601', manufacturerName: '_TZE200_holel4dk'},
3778
+ {modelID: 'TS0601', manufacturerName: '_TZE200_wukb7rhc'},
3779
+ {modelID: 'TS0601', manufacturerName: '_TZE204_ztc6ggyl'},
3780
+ {modelID: 'TS0601', manufacturerName: '_TZE200_ztc6ggyl'}],
3781
+ model: 'TS0601_smart_human_presence_sensor',
3782
+ vendor: 'TuYa',
3783
+ description: 'Smart Human presence sensor',
3784
+ fromZigbee: [fz.tuya_smart_human_presense_sensor],
3785
+ toZigbee: [tz.tuya_smart_human_presense_sensor],
3786
+ exposes: [
3787
+ e.illuminance_lux(), e.presence(),
3788
+ exposes.numeric('target_distance', ea.STATE).withDescription('Distance to target').withUnit('m'),
3789
+ exposes.numeric('radar_sensitivity', ea.STATE_SET).withValueMin(0).withValueMax(9).withValueStep(1)
3790
+ .withDescription('sensitivity of the radar'),
3791
+ exposes.numeric('minimum_range', ea.STATE_SET).withValueMin(0).withValueMax(9.5).withValueStep(0.15)
3792
+ .withDescription('Minimum range').withUnit('m'),
3793
+ exposes.numeric('maximum_range', ea.STATE_SET).withValueMin(0).withValueMax(9.5).withValueStep(0.15)
3794
+ .withDescription('Maximum range').withUnit('m'),
3795
+ exposes.numeric('detection_delay', ea.STATE_SET).withValueMin(0).withValueMax(10).withValueStep(0.1)
3796
+ .withDescription('Detection delay').withUnit('s'),
3797
+ exposes.numeric('fading_time', ea.STATE_SET).withValueMin(0).withValueMax(1500).withValueStep(1)
3798
+ .withDescription('Fading time').withUnit('s'),
3799
+ // exposes.text('cli', ea.STATE).withDescription('not recognize'),
3800
+ exposes.enum('self_test', ea.STATE, Object.values(tuya.tuyaHPSCheckingResult))
3801
+ .withDescription('Self_test, possible resuts: checking, check_success, check_failure, others, comm_fault, radar_fault.'),
3802
+ ],
3803
+ },
3804
+ {
3805
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_whkgqxse'}],
3806
+ model: 'JM-TRH-ZGB-V1',
3807
+ vendor: 'TuYa',
3808
+ description: 'Temperature & humidity sensor with clock',
3809
+ fromZigbee: [fz.nous_lcd_temperature_humidity_sensor, fz.ignore_tuya_set_time],
3810
+ toZigbee: [tz.nous_lcd_temperature_humidity_sensor],
3811
+ onEvent: tuya.onEventSetLocalTime,
3812
+ configure: async (device, coordinatorEndpoint, logger) => {
3813
+ const endpoint = device.getEndpoint(1);
3814
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genBasic']);
3815
+ },
3816
+ exposes: [
3817
+ e.temperature(), e.humidity(), e.battery(),
3818
+ exposes.numeric('temperature_report_interval', ea.STATE_SET).withUnit('min').withValueMin(5).withValueMax(60).withValueStep(5)
3819
+ .withDescription('Temperature Report interval'),
3820
+ exposes.enum('temperature_unit_convert', ea.STATE_SET, ['celsius', 'fahrenheit']).withDescription('Current display unit'),
3821
+ exposes.enum('temperature_alarm', ea.STATE, ['canceled', 'lower_alarm', 'upper_alarm'])
3822
+ .withDescription('Temperature alarm status'),
3823
+ exposes.numeric('max_temperature', ea.STATE_SET).withUnit('°C').withValueMin(-20).withValueMax(60)
3824
+ .withDescription('Alarm temperature max'),
3825
+ exposes.numeric('min_temperature', ea.STATE_SET).withUnit('°C').withValueMin(-20).withValueMax(60)
3826
+ .withDescription('Alarm temperature min'),
3827
+ exposes.enum('humidity_alarm', ea.STATE, ['canceled', 'lower_alarm', 'upper_alarm'])
3828
+ .withDescription('Humidity alarm status'),
3829
+ exposes.numeric('max_humidity', ea.STATE_SET).withUnit('%').withValueMin(0).withValueMax(100)
3830
+ .withDescription('Alarm humidity max'),
3831
+ exposes.numeric('min_humidity', ea.STATE_SET).withUnit('%').withValueMin(0).withValueMax(100)
3832
+ .withDescription('Alarm humidity min'),
3833
+ ],
3834
+ },
3835
+ {
3836
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE200_3towulqd', '_TZE200_1ibpyhdc', '_TZE200_bh3n6gk8']),
3837
+ model: 'ZG-204ZL',
3838
+ vendor: 'TuYa',
3839
+ description: 'Luminance motion sensor',
3840
+ fromZigbee: [fz.ZG204ZL_lms],
3841
+ toZigbee: [tz.ZG204ZL_lms],
3842
+ exposes: [
3843
+ e.occupancy(), e.illuminance().withUnit('lx'), e.battery(),
3844
+ exposes.enum('sensitivity', ea.ALL, ['low', 'medium', 'high'])
3845
+ .withDescription('PIR sensor sensitivity (refresh and update only while active)'),
3846
+ exposes.enum('keep_time', ea.ALL, ['10', '30', '60', '120'])
3847
+ .withDescription('PIR keep time in seconds (refresh and update only while active)'),
3848
+ ],
3849
+ },
3850
+ {
3851
+ fingerprint: [{modelID: 'TS004F', manufacturerName: '_TZ3000_kjfzuycl'},
3852
+ {modelID: 'TS004F', manufacturerName: '_TZ3000_ja5osu5g'}],
3853
+ model: 'ERS-10TZBVB-AA',
3854
+ vendor: 'TuYa',
3855
+ description: 'Smart button',
3856
+ fromZigbee: [
3857
+ fz.command_step, fz.command_on, fz.command_off, fz.command_move_to_color_temp, fz.command_move_to_level,
3858
+ fz.tuya_multi_action, fz.tuya_operation_mode, fz.battery,
3859
+ ],
3860
+ toZigbee: [tz.tuya_operation_mode],
3861
+ exposes: [
3862
+ e.action([
3863
+ 'single', 'double', 'hold', 'brightness_move_to_level', 'color_temperature_move',
3864
+ 'brightness_step_up', 'brightness_step_down', 'on', 'off',
3865
+ ]),
3866
+ e.battery(),
3867
+ exposes.enum('operation_mode', ea.ALL, ['command', 'event']).withDescription(
3868
+ 'Operation mode: "command" - for group control, "event" - for clicks'),
3869
+ ],
3870
+ configure: async (device, coordinatorEndpoint, logger) => {
3871
+ const endpoint = device.getEndpoint(1);
3872
+ await endpoint.read('genBasic', [0x0004, 0x000, 0x0001, 0x0005, 0x0007, 0xfffe]);
3873
+ await endpoint.write('genOnOff', {'tuyaOperationMode': 1});
3874
+ await endpoint.read('genOnOff', ['tuyaOperationMode']);
3875
+ try {
3876
+ await endpoint.read(0xE001, [0xD011]);
3877
+ } catch (err) {/* do nothing */}
3878
+ await endpoint.read('genPowerCfg', ['batteryVoltage', 'batteryPercentageRemaining']);
3879
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg']);
3880
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff']);
3881
+ await reporting.batteryPercentageRemaining(endpoint);
3882
+ },
3883
+ },
3884
+ {
3885
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_zyrdrmno'}],
3886
+ model: 'ZB-Sm',
3887
+ vendor: 'TuYa',
3888
+ description: 'Tubular motor',
3889
+ fromZigbee: [fzLocal.zb_sm_cover, fz.ignore_basic_report],
3890
+ toZigbee: [tzLocal.zb_sm_cover],
3891
+ onEvent: tuya.onEventSetTime,
3892
+ exposes: [
3893
+ e.cover_position().setAccess('position', ea.STATE_SET),
3894
+ exposes.enum('goto_positon', ea.SET, ['25', '50', '75', 'FAVORITE']),
3895
+ exposes.enum('motor_state', ea.STATE, ['OPENING', 'CLOSING', 'STOPPED']),
3896
+ exposes.numeric('active_power', ea.STATE).withDescription('Active power').withUnit('mWt'),
3897
+ exposes.numeric('cycle_count', ea.STATE).withDescription('Cycle count'),
3898
+ exposes.numeric('cycle_time', ea.STATE).withDescription('Cycle time').withUnit('ms'),
3899
+ exposes.enum('top_limit', ea.STATE_SET, ['SET', 'CLEAR']).withDescription('Setup or clear top limit'),
3900
+ exposes.enum('bottom_limit', ea.STATE_SET, ['SET', 'CLEAR']).withDescription('Setup or clear bottom limit'),
3901
+ exposes.numeric('favorite_position', ea.STATE_SET).withValueMin(0).withValueMax(100)
3902
+ .withDescription('Favorite position of this cover'),
3903
+ exposes.binary(`reverse_direction`, ea.STATE_SET, true, false).withDescription(`Inverts the cover direction`),
3904
+ exposes.text('motor_type', ea.STATE),
3905
+ exposes.enum('report', ea.SET, ['']),
3906
+ ],
3907
+ },
3908
+ {
3909
+ fingerprint: [{modelID: 'TS1201', manufacturerName: '_TZ3290_7v1k4vufotpowp9z'}],
3910
+ model: 'ZS06',
3911
+ vendor: 'TuYa',
3912
+ description: 'Universal smart IR remote control',
3913
+ fromZigbee: [
3914
+ fzZosung.zosung_send_ir_code_00, fzZosung.zosung_send_ir_code_01, fzZosung.zosung_send_ir_code_02,
3915
+ fzZosung.zosung_send_ir_code_03, fzZosung.zosung_send_ir_code_04, fzZosung.zosung_send_ir_code_05,
3916
+ ],
3917
+ toZigbee: [tzZosung.zosung_ir_code_to_send, tzZosung.zosung_learn_ir_code],
3918
+ exposes: [ez.learn_ir_code(), ez.learned_ir_code(), ez.ir_code_to_send()],
3919
+ },
3920
+ {
3921
+ fingerprint: [{modelID: 'TS0201', manufacturerName: '_TZ3000_itnrsufe'}],
3922
+ model: 'KCTW1Z',
3923
+ vendor: 'TuYa',
3924
+ description: 'Temperature & humidity sensor with LCD',
3925
+ fromZigbee: [fz.temperature, fzLocal.humidity10, fzLocal.temperature_unit, fz.battery, fz.ignore_tuya_set_time],
3926
+ toZigbee: [tzLocal.temperature_unit],
3927
+ onEvent: tuya.onEventSetLocalTime,
3928
+ exposes: [
3929
+ e.temperature(), e.humidity(), e.battery(), e.battery_voltage(),
3930
+ exposes.enum('temperature_unit', ea.STATE_SET, ['celsius', 'fahrenheit']).withDescription('Current display unit'),
3931
+ ],
3932
+ configure: async (device, coordinatorEndpoint, logger) => {
3933
+ const endpoint = device.getEndpoint(1);
3934
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genPowerCfg', 'msTemperatureMeasurement', 'msRelativeHumidity']);
3935
+ await endpoint.read('genPowerCfg', ['batteryVoltage', 'batteryPercentageRemaining']);
3936
+ await reporting.batteryPercentageRemaining(endpoint);
3937
+ },
3938
+ },
3939
+ {
3940
+ fingerprint: [{modelID: 'TS0601', manufacturerName: '_TZE200_0u3bj3rc'},
3941
+ {modelID: 'TS0601', manufacturerName: '_TZE200_v6ossqfy'},
3942
+ {modelID: 'TS0601', manufacturerName: '_TZE200_mx6u6l4y'}],
3943
+ model: 'TS0601_human_presence_sensor',
3944
+ vendor: 'TuYa',
3945
+ description: 'Human presence sensor Zigbee',
3946
+ fromZigbee: [fzLocal.hpsz],
3947
+ toZigbee: [tzLocal.hpsz],
3948
+ onEvent: tuya.onEventSetLocalTime,
3949
+ exposes: [e.presence(),
3950
+ exposes.numeric('duration_of_attendance', ea.STATE).withUnit('min')
3951
+ .withDescription('Shows the presence duration in minutes'),
3952
+ exposes.numeric('duration_of_absence', ea.STATE).withUnit('min')
3953
+ .withDescription('Shows the duration of the absence in minutes'),
3954
+ exposes.binary('led_state', ea.STATE_SET, true, false)
3955
+ .withDescription('Turns the onboard LED on or off'),
3956
+ ],
3957
+ },
3958
+ {
3959
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE200_qoy0ekbd', '_TZE200_znbl8dj5', '_TZE200_a8sdabtg']),
3960
+ model: 'ZG-227ZL',
3961
+ vendor: 'TuYa',
3962
+ description: 'Temperature & humidity LCD sensor',
3963
+ fromZigbee: [tuya.fz.datapoints],
3964
+ toZigbee: [tuya.tz.datapoints],
3965
+ configure: tuya.configureMagicPacket,
3966
+ exposes: [e.temperature(), e.humidity(), tuya.exposes.temperatureUnit(), tuya.exposes.temperatureCalibration(),
3967
+ tuya.exposes.humidityCalibration(), e.battery()],
3968
+ meta: {
3969
+ tuyaDatapoints: [
3970
+ [1, 'temperature', tuya.valueConverter.divideBy10],
3971
+ [2, 'humidity', tuya.valueConverter.raw],
3972
+ [4, 'battery', tuya.valueConverter.raw],
3973
+ [9, 'temperature_unit', tuya.valueConverter.temperatureUnit],
3974
+ [23, 'temperature_calibration', tuya.valueConverter.divideBy10],
3975
+ [24, 'humidity_calibration', tuya.valueConverter.raw],
3976
+ ],
3977
+ },
3978
+ },
3979
+ {
3980
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE200_n8dljorx', '_TZE200_pay2byax']),
3981
+ model: 'ZG-102ZL',
3982
+ vendor: 'TuYa',
3983
+ description: 'Luminance door sensor',
3984
+ fromZigbee: [tuya.fz.datapoints],
3985
+ toZigbee: [tuya.tz.datapoints],
3986
+ configure: tuya.configureMagicPacket,
3987
+ exposes: [e.contact(), e.illuminance().withUnit('lx'), e.battery()],
3988
+ meta: {
3989
+ tuyaDatapoints: [
3990
+ [1, 'contact', tuya.valueConverter.inverse],
3991
+ [101, 'illuminance', tuya.valueConverter.raw],
3992
+ [2, 'battery', tuya.valueConverter.raw],
3993
+ ],
3994
+ },
3995
+ },
3996
+ {
3997
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE200_8isdky6j']),
3998
+ model: 'ZG-225Z',
3999
+ vendor: 'TuYa',
4000
+ description: 'Gas sensor',
4001
+ fromZigbee: [tuya.fz.datapoints],
4002
+ toZigbee: [tuya.tz.datapoints],
4003
+ configure: tuya.configureMagicPacket,
4004
+ exposes: [e.gas(), tuya.exposes.gasValue().withUnit('ppm')],
4005
+ meta: {
4006
+ tuyaDatapoints: [
4007
+ [1, 'gas', tuya.valueConverter.trueFalse0],
4008
+ [2, 'gas_value', tuya.valueConverter.raw],
4009
+ ],
4010
+ },
4011
+ },
4012
+ {
4013
+ fingerprint: tuya.fingerprint('TS110E', ['_TZ3210_zxbtub8r', '_TZ3210_k1msuvg6']),
4014
+ model: 'TS110E_1gang_1',
4015
+ vendor: 'TuYa',
4016
+ description: '1 channel dimmer',
4017
+ fromZigbee: extend.light_onoff_brightness({disablePowerOnBehavior: true, disableMoveStep: true, disableTransition: true})
4018
+ .fromZigbee.concat([tuya.fz.power_on_behavior_1, fzLocal.TS110E_switch_type, fzLocal.TS110E]),
4019
+ toZigbee: utils.replaceInArray(
4020
+ extend.light_onoff_brightness({disablePowerOnBehavior: true, disableMoveStep: true, disableTransition: true})
4021
+ .toZigbee.concat([tuya.tz.power_on_behavior_1, tzLocal.TS110E_options]),
4022
+ [tz.light_onoff_brightness],
4023
+ [tzLocal.TS110E_light_onoff_brightness],
4024
+ ),
4025
+ exposes: [e.light_brightness().withMinBrightness().withMaxBrightness(), e.power_on_behavior(), tuya.exposes.switchType()],
4026
+ configure: async (device, coordinatorEndpoint, logger) => {
4027
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
4028
+ await extend.light_onoff_brightness().configure(device, coordinatorEndpoint, logger);
4029
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
4030
+ },
4031
+ },
4032
+ {
4033
+ fingerprint: tuya.fingerprint('TS110E', ['_TZ3210_ngqk6jia']),
4034
+ model: 'TS110E_1gang_2',
4035
+ vendor: 'TuYa',
4036
+ description: '1 channel dimmer',
4037
+ whiteLabel: [{vendor: 'RTX', model: 'QS-Zigbee-D02-TRIAC-LN'}],
4038
+ fromZigbee: [fzLocal.TS110E, fzLocal.TS110E_light_type, tuya.fz.power_on_behavior_1, fz.on_off],
4039
+ toZigbee: [tzLocal.TS110E_onoff_brightness, tzLocal.TS110E_options, tuya.tz.power_on_behavior_1, tz.light_brightness_move],
4040
+ exposes: [
4041
+ e.light_brightness().withMinBrightness().withMaxBrightness(),
4042
+ tuya.exposes.lightType().withAccess(ea.ALL), e.power_on_behavior().withAccess(ea.ALL)],
4043
+ configure: async (device, coordinatorEndpoint, logger) => {
4044
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
4045
+ const endpoint = device.getEndpoint(1);
4046
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
4047
+ await reporting.onOff(endpoint);
4048
+ },
4049
+ },
4050
+ {
4051
+ fingerprint: [{modelID: 'TS110E', manufacturerName: '_TZ3210_wdexaypg'}, {modelID: 'TS110E', manufacturerName: '_TZ3210_3mpwqzuu'}],
4052
+ model: 'TS110E_2gang_1',
4053
+ vendor: 'TuYa',
4054
+ description: '2 channel dimmer',
4055
+ fromZigbee: extend.light_onoff_brightness({disablePowerOnBehavior: true, disableMoveStep: true, disableTransition: true})
4056
+ .fromZigbee.concat([tuya.fz.power_on_behavior_1, fzLocal.TS110E_switch_type, fzLocal.TS110E]),
4057
+ toZigbee: utils.replaceInArray(
4058
+ extend.light_onoff_brightness({disablePowerOnBehavior: true, disableMoveStep: true, disableTransition: true})
4059
+ .toZigbee.concat([tuya.tz.power_on_behavior_1, tzLocal.TS110E_options]),
4060
+ [tz.light_onoff_brightness],
4061
+ [tzLocal.TS110E_light_onoff_brightness],
4062
+ ),
4063
+ meta: {multiEndpoint: true},
4064
+ exposes: [
4065
+ e.light_brightness().withMinBrightness().withMaxBrightness().withEndpoint('l1'),
4066
+ e.light_brightness().withMinBrightness().withMaxBrightness().withEndpoint('l2'),
4067
+ e.power_on_behavior(),
4068
+ tuya.exposes.switchType().withEndpoint('l1'),
4069
+ tuya.exposes.switchType().withEndpoint('l2'),
4070
+ ],
4071
+ configure: async (device, coordinatorEndpoint, logger) => {
4072
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
4073
+ await extend.light_onoff_brightness().configure(device, coordinatorEndpoint, logger);
4074
+ await reporting.bind(device.getEndpoint(1), coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
4075
+ await reporting.bind(device.getEndpoint(2), coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
4076
+ },
4077
+ endpoint: (device) => {
4078
+ return {l1: 1, l2: 2};
4079
+ },
4080
+ },
4081
+ {
4082
+ fingerprint: tuya.fingerprint('TS110E', ['_TZ3210_pagajpog', '_TZ3210_4ubylghk']),
4083
+ model: 'TS110E_2gang_2',
4084
+ vendor: 'TuYa',
4085
+ description: '2 channel dimmer',
4086
+ fromZigbee: [fzLocal.TS110E, fzLocal.TS110E_light_type, tuya.fz.power_on_behavior_1, fz.on_off],
4087
+ toZigbee: [tzLocal.TS110E_onoff_brightness, tzLocal.TS110E_options, tuya.tz.power_on_behavior_1, tz.light_brightness_move],
4088
+ meta: {multiEndpoint: true},
4089
+ exposes: [
4090
+ e.light_brightness().withMinBrightness().withMaxBrightness().withEndpoint('l1'),
4091
+ e.light_brightness().withMinBrightness().withMaxBrightness().withEndpoint('l2'),
4092
+ e.power_on_behavior().withAccess(ea.ALL)],
4093
+ configure: async (device, coordinatorEndpoint, logger) => {
4094
+ await tuya.configureMagicPacket(device, coordinatorEndpoint, logger);
4095
+ const endpoint = device.getEndpoint(1);
4096
+ await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
4097
+ await reporting.onOff(endpoint);
4098
+ },
4099
+ endpoint: (device) => {
4100
+ return {l1: 1, l2: 2};
4101
+ },
4102
+ },
4103
+ {
4104
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE200_nslr42tt']),
4105
+ model: 'TS0601_3_phase_clamp_meter',
4106
+ vendor: 'TuYa',
4107
+ description: '3-phase clamp power meter',
4108
+ fromZigbee: [tuya.fz.datapoints],
4109
+ toZigbee: [tuya.tz.datapoints],
4110
+ configure: tuya.configureMagicPacket,
4111
+ whiteLabel: [{vendor: 'MatSeePlus', model: 'PC321-Z-TY'}],
4112
+ exposes: [
4113
+ e.ac_frequency(), e.temperature(), e.current(), e.power(), e.energy(),
4114
+ tuya.exposes.energyWithPhase('a'), tuya.exposes.energyWithPhase('b'), tuya.exposes.energyWithPhase('c'),
4115
+ tuya.exposes.voltageWithPhase('a'), tuya.exposes.voltageWithPhase('b'), tuya.exposes.voltageWithPhase('c'),
4116
+ tuya.exposes.powerWithPhase('a'), tuya.exposes.powerWithPhase('b'), tuya.exposes.powerWithPhase('c'),
4117
+ tuya.exposes.currentWithPhase('a'), tuya.exposes.currentWithPhase('b'), tuya.exposes.currentWithPhase('c'),
4118
+ tuya.exposes.powerFactorWithPhase('a'), tuya.exposes.powerFactorWithPhase('b'), tuya.exposes.powerFactorWithPhase('c'),
4119
+ ],
4120
+ meta: {
4121
+ tuyaDatapoints: [
4122
+ [132, 'ac_frequency', tuya.valueConverter.raw],
4123
+ [133, 'temperature', tuya.valueConverter.divideBy10],
4124
+ [1, 'energy', tuya.valueConverter.divideBy100],
4125
+ [101, 'energy_a', tuya.valueConverter.divideBy1000],
4126
+ [111, 'energy_b', tuya.valueConverter.divideBy1000],
4127
+ [121, 'energy_c', tuya.valueConverter.divideBy1000],
4128
+ [131, 'current', tuya.valueConverter.divideBy1000],
4129
+ [9, 'power', tuya.valueConverter.raw],
4130
+ [102, 'power_factor_a', tuya.valueConverter.raw],
4131
+ [112, 'power_factor_b', tuya.valueConverter.raw],
4132
+ [122, 'power_factor_c', tuya.valueConverter.raw],
4133
+ [6, null, tuya.valueConverter.phaseVariant2WithPhase('a')],
4134
+ [7, null, tuya.valueConverter.phaseVariant2WithPhase('b')],
4135
+ [8, null, tuya.valueConverter.phaseVariant2WithPhase('c')],
4136
+ [134, 'device_status', tuya.valueConverter.raw],
4137
+ ],
4138
+ },
4139
+ },
4140
+ {
4141
+ zigbeeModel: ['TS0049'],
4142
+ model: 'TS0049',
4143
+ vendor: 'TuYa',
4144
+ description: 'Water valve',
4145
+ fromZigbee: [tuya.fz.datapoints],
4146
+ toZigbee: [tuya.tz.datapoints],
4147
+ onEvent: tuya.onEventSetLocalTime,
4148
+ configure: tuya.configureMagicPacket,
4149
+ exposes: [tuya.exposes.errorStatus(), tuya.exposes.switch(), tuya.exposes.batteryState(),
4150
+ tuya.exposes.countdown().withValueMin(0).withValueMax(255).withUnit('minutes')
4151
+ .withDescription('Max on time in minutes'),
4152
+ ],
4153
+ meta: {
4154
+ tuyaSendCommand: 'sendData',
4155
+ tuyaDatapoints: [
4156
+ [26, 'error_status', tuya.valueConverter.raw],
4157
+ [101, 'state', tuya.valueConverter.onOff],
4158
+ [111, 'countdown', tuya.valueConverter.raw],
4159
+ [115, 'battery_state', tuya.valueConverter.batteryState],
4160
+ ],
4161
+ },
4162
+ },
4163
+ {
4164
+ fingerprint: tuya.fingerprint('TS0601', ['_TZE200_r32ctezx']),
4165
+ model: 'TS0601_fan_switch',
4166
+ vendor: 'TuYa',
4167
+ description: 'Fan switch',
4168
+ fromZigbee: [tuya.fz.datapoints],
4169
+ toZigbee: [tuya.tz.datapoints],
4170
+ configure: tuya.configureMagicPacket,
4171
+ exposes: [
4172
+ tuya.exposes.switch(), e.power_on_behavior(['off', 'on']).withAccess(ea.STATE_SET),
4173
+ tuya.exposes.countdown().withValueMin(0).withValueMax(43200).withUnit('s').withDescription('Max ON time in seconds'),
4174
+ exposes.numeric('fan_speed', ea.STATE_SET).withValueMin(1).withValueMax(5).withValueStep(1)
4175
+ .withDescription('Speed off the fan'),
4176
+ ],
4177
+ meta: {
4178
+ tuyaDatapoints: [
4179
+ [1, 'state', tuya.valueConverter.onOff],
4180
+ [2, 'countdown', tuya.valueConverter.countdown],
4181
+ [3, 'fan_speed', tuya.valueConverterBasic
4182
+ .lookup({'1': tuya.enum(0), '2': tuya.enum(1), '3': tuya.enum(2), '4': tuya.enum(3), '5': tuya.enum(4)})],
4183
+ [11, 'power_on_behavior', tuya.valueConverterBasic.lookup({'off': tuya.enum(0), 'on': tuya.enum(1)})],
4184
+ ],
4185
+ },
4186
+ whiteLabel: [
4187
+ {vendor: 'Lerlink', model: 'T2-Z67/T2-W67'},
4188
+ ],
4189
+ },
4190
+ {
4191
+ zigbeeModel: ['TS0224'],
4192
+ model: 'TS0224',
4193
+ vendor: 'TuYa',
4194
+ description: 'Smart light & sound siren',
4195
+ fromZigbee: [],
4196
+ toZigbee: [tz.warning, tzLocal.TS0224],
4197
+ exposes: [e.warning(),
4198
+ exposes.binary('light', ea.STATE_SET, 'ON', 'OFF').withDescription('Turn the light of the alarm ON/OFF'),
4199
+ exposes.numeric('duration', ea.STATE_SET).withValueMin(60).withValueMax(3600).withValueStep(1).withUnit('s')
4200
+ .withDescription('Duration of the alarm'),
4201
+ exposes.enum('volume', ea.STATE_SET, ['mute', 'low', 'medium', 'high'])
4202
+ .withDescription('Volume of the alarm'),
4203
+ ],
4204
+ },
4205
+ {
4206
+ fingerprint: tuya.fingerprint('TS0041', ['_TZ3000_fa9mlvja']),
4207
+ model: 'IH-K663',
4208
+ vendor: 'TuYa',
4209
+ description: 'Smart button',
4210
+ exposes: [e.battery(), e.battery_voltage(), e.action(['single', 'double'])],
4211
+ fromZigbee: [fz.tuya_on_off_action, fz.battery],
4212
+ toZigbee: [],
4213
+ configure: tuya.configureMagicPacket,
4214
+ },
4215
+ ];