@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
package/index.js ADDED
@@ -0,0 +1,242 @@
1
+ 'use strict';
2
+
3
+ const configureKey = require('./lib/configureKey');
4
+ const exposes = require('./lib/exposes');
5
+ const toZigbee = require('./converters/toZigbee');
6
+ const fromZigbee = require('./converters/fromZigbee');
7
+ const assert = require('assert');
8
+ const tz = require('./converters/toZigbee');
9
+ const fs = require('fs');
10
+ const path = require('path');
11
+
12
+ // key: zigbeeModel, value: array of definitions (most of the times 1)
13
+ const lookup = new Map();
14
+ const definitions = [];
15
+
16
+ function arrayEquals(as, bs) {
17
+ if (as.length !== bs.length) return false;
18
+ for (const a of as) if (!bs.includes(a)) return false;
19
+ return true;
20
+ }
21
+
22
+ function addToLookup(zigbeeModel, definition) {
23
+ zigbeeModel = zigbeeModel ? zigbeeModel.toLowerCase() : null;
24
+ if (!lookup.has(zigbeeModel)) {
25
+ lookup.set(zigbeeModel, []);
26
+ }
27
+
28
+ if (!lookup.get(zigbeeModel).includes(definition)) {
29
+ lookup.get(zigbeeModel).splice(0, 0, definition);
30
+ }
31
+ }
32
+
33
+ function getFromLookup(zigbeeModel) {
34
+ zigbeeModel = zigbeeModel ? zigbeeModel.toLowerCase() : null;
35
+ if (lookup.has(zigbeeModel)) {
36
+ return lookup.get(zigbeeModel);
37
+ }
38
+
39
+ zigbeeModel = zigbeeModel ? zigbeeModel.replace(/\0(.|\n)*$/g, '').trim() : null;
40
+ return lookup.get(zigbeeModel);
41
+ }
42
+
43
+ const converterRequiredFields = {
44
+ model: 'String',
45
+ vendor: 'String',
46
+ description: 'String',
47
+ fromZigbee: 'Array',
48
+ toZigbee: 'Array',
49
+ };
50
+
51
+ function validateDefinition(definition) {
52
+ for (const [field, expectedType] of Object.entries(converterRequiredFields)) {
53
+ assert.notStrictEqual(null, definition[field], `Converter field ${field} is null`);
54
+ assert.notStrictEqual(undefined, definition[field], `Converter field ${field} is undefined`);
55
+ const msg = `Converter field ${field} expected type doenst match to ${definition[field]}`;
56
+ assert.strictEqual(definition[field].constructor.name, expectedType, msg);
57
+ }
58
+ assert.ok(Array.isArray(definition.exposes) || typeof definition.exposes === 'function', 'Exposes incorrect');
59
+ }
60
+
61
+ function addDefinition(definition) {
62
+ const {extend, ...definitionWithoutExtend} = definition;
63
+ if (extend) {
64
+ if (extend.hasOwnProperty('configure') && definition.hasOwnProperty('configure')) {
65
+ assert.fail(`'${definition.model}' has configure in extend and device, this is not allowed`);
66
+ }
67
+
68
+ definition = {
69
+ ...extend,
70
+ ...definitionWithoutExtend,
71
+ meta: extend.meta || definitionWithoutExtend.meta ? {
72
+ ...extend.meta,
73
+ ...definitionWithoutExtend.meta,
74
+ } : undefined,
75
+ };
76
+ }
77
+
78
+ definition.toZigbee.push(tz.scene_store, tz.scene_recall, tz.scene_add, tz.scene_remove, tz.scene_remove_all, tz.read, tz.write,
79
+ tz.command, tz.factory_reset);
80
+
81
+ if (definition.exposes && Array.isArray(definition.exposes) && !definition.exposes.find((e) => e.name === 'linkquality')) {
82
+ definition.exposes = definition.exposes.concat([exposes.presets.linkquality()]);
83
+ }
84
+
85
+ validateDefinition(definition);
86
+ definitions.splice(0, 0, definition);
87
+
88
+ if (!definition.options) definition.options = [];
89
+ const optionKeys = definition.options.map((o) => o.name);
90
+ for (const converter of [...definition.toZigbee, ...definition.fromZigbee]) {
91
+ if (converter.options) {
92
+ const options = typeof converter.options === 'function' ? converter.options(definition) : converter.options;
93
+ for (const option of options) {
94
+ if (!optionKeys.includes(option.name)) {
95
+ definition.options.push(option);
96
+ optionKeys.push(option.name);
97
+ }
98
+ }
99
+ }
100
+ }
101
+
102
+ if (definition.hasOwnProperty('fingerprint')) {
103
+ for (const fingerprint of definition.fingerprint) {
104
+ addToLookup(fingerprint.modelID, definition);
105
+ }
106
+ }
107
+
108
+ if (definition.hasOwnProperty('zigbeeModel')) {
109
+ for (const zigbeeModel of definition.zigbeeModel) {
110
+ addToLookup(zigbeeModel, definition);
111
+ }
112
+ }
113
+ }
114
+
115
+ // Load all definitions from devices folder
116
+ const devicesPath = path.join(__dirname, 'devices');
117
+ for (const file of fs.readdirSync(devicesPath)) {
118
+ for (const definition of require(path.join(devicesPath, file))) {
119
+ addDefinition(definition);
120
+ }
121
+ }
122
+
123
+ function findByZigbeeModel(zigbeeModel) {
124
+ if (!zigbeeModel) {
125
+ return null;
126
+ }
127
+
128
+ const candidates = getFromLookup(zigbeeModel);
129
+ // Multiple candidates possible, to use external converters in priority, use last one.
130
+ return candidates ? candidates[candidates.length-1] : null;
131
+ }
132
+
133
+ function findByDevice(device) {
134
+ if (!device) {
135
+ return null;
136
+ }
137
+
138
+ const candidates = getFromLookup(device.modelID);
139
+ if (!candidates) {
140
+ return null;
141
+ } else if (candidates.length === 1 && candidates[0].hasOwnProperty('zigbeeModel')) {
142
+ return candidates[0];
143
+ } else {
144
+ // First try to match based on fingerprint, return the first matching one.
145
+ const fingerprintMatch = {priority: null, definition: null};
146
+ for (const candidate of candidates) {
147
+ if (candidate.hasOwnProperty('fingerprint')) {
148
+ for (const fingerprint of candidate.fingerprint) {
149
+ const priority = fingerprint.hasOwnProperty('priority') ? fingerprint.priority : 0;
150
+ if (isFingerprintMatch(fingerprint, device) && (!fingerprintMatch.definition || priority > fingerprintMatch.priority)) {
151
+ fingerprintMatch.definition = candidate;
152
+ fingerprintMatch.priority = priority;
153
+ }
154
+ }
155
+ }
156
+ }
157
+
158
+ if (fingerprintMatch.definition) {
159
+ return fingerprintMatch.definition;
160
+ }
161
+
162
+ // Match based on fingerprint failed, return first matching definition based on zigbeeModel
163
+ for (const candidate of candidates) {
164
+ if (candidate.hasOwnProperty('zigbeeModel') && candidate.zigbeeModel.includes(device.modelID)) {
165
+ return candidate;
166
+ }
167
+ }
168
+ }
169
+
170
+ return null;
171
+ }
172
+
173
+ function isFingerprintMatch(fingerprint, device) {
174
+ let match =
175
+ (!fingerprint.applicationVersion || device.applicationVersion === fingerprint.applicationVersion) &&
176
+ (!fingerprint.manufacturerID || device.manufacturerID === fingerprint.manufacturerID) &&
177
+ (!fingerprint.type || device.type === fingerprint.type) &&
178
+ (!fingerprint.dateCode || device.dateCode === fingerprint.dateCode) &&
179
+ (!fingerprint.hardwareVersion || device.hardwareVersion === fingerprint.hardwareVersion) &&
180
+ (!fingerprint.manufacturerName || device.manufacturerName === fingerprint.manufacturerName) &&
181
+ (!fingerprint.modelID || device.modelID === fingerprint.modelID) &&
182
+ (!fingerprint.powerSource || device.powerSource === fingerprint.powerSource) &&
183
+ (!fingerprint.softwareBuildID || device.softwareBuildID === fingerprint.softwareBuildID) &&
184
+ (!fingerprint.stackVersion || device.stackVersion === fingerprint.stackVersion) &&
185
+ (!fingerprint.zclVersion || device.zclVersion === fingerprint.zclVersion) &&
186
+ (!fingerprint.ieeeAddr || device.ieeeAddr.match(fingerprint.ieeeAddr)) &&
187
+ (!fingerprint.endpoints ||
188
+ arrayEquals(device.endpoints.map((e) => e.ID), fingerprint.endpoints.map((e) => e.ID)));
189
+
190
+ if (match && fingerprint.endpoints) {
191
+ for (const fingerprintEndpoint of fingerprint.endpoints) {
192
+ const deviceEndpoint = device.getEndpoint(fingerprintEndpoint.ID);
193
+ match = match &&
194
+ (!fingerprintEndpoint.deviceID || deviceEndpoint.deviceID === fingerprintEndpoint.deviceID) &&
195
+ (!fingerprintEndpoint.profileID || deviceEndpoint.profileID === fingerprintEndpoint.profileID) &&
196
+ (!fingerprintEndpoint.inputClusters ||
197
+ arrayEquals(deviceEndpoint.inputClusters, fingerprintEndpoint.inputClusters)) &&
198
+ (!fingerprintEndpoint.outputClusters ||
199
+ arrayEquals(deviceEndpoint.outputClusters, fingerprintEndpoint.outputClusters));
200
+ }
201
+ }
202
+
203
+ return match;
204
+ }
205
+
206
+ module.exports = {
207
+ getConfigureKey: configureKey.getConfigureKey,
208
+ devices: definitions,
209
+ exposes,
210
+ definitions,
211
+ findByZigbeeModel, // Legacy method, use findByDevice instead.
212
+ findByDevice,
213
+ toZigbeeConverters: toZigbee,
214
+ fromZigbeeConverters: fromZigbee,
215
+ addDeviceDefinition: addDefinition,
216
+ // Can be used to handle events for devices which are not fully paired yet (no modelID).
217
+ // Example usecase: https://github.com/Koenkk/zigbee2mqtt/issues/2399#issuecomment-570583325
218
+ onEvent: async (type, data, device) => {
219
+ // support Legrand security protocol
220
+ // when pairing, a powered device will send a read frame to every device on the network
221
+ // it expects at least one answer. The payload contains the number of seconds
222
+ // since when the device is powered. If the value is too high, it will leave & not pair
223
+ // 23 works, 200 doesn't
224
+ if (data.meta && data.meta.manufacturerCode === 0x1021 && type === 'message' && data.type === 'read' &&
225
+ data.cluster === 'genBasic' && data.data && data.data.includes(61440)) {
226
+ const endpoint = device.getEndpoint(1);
227
+ const options = {manufacturerCode: 0x1021, disableDefaultResponse: true};
228
+ const payload = {0xf00: {value: 23, type: 35}};
229
+ await endpoint.readResponse('genBasic', data.meta.zclTransactionSequenceNumber, payload, options);
230
+ }
231
+ // Aqara feeder C1 polls the time during the interview, need to send back the local time instead of the UTC.
232
+ // The device.definition has not yet been set - therefore the device.definition.onEvent method does not work.
233
+ if (type === 'message' && data.type === 'read' && data.cluster === 'genTime' &&
234
+ device.modelID === 'aqara.feeder.acn001') {
235
+ device.skipTimeResponse = true;
236
+ const oneJanuary2000 = new Date('January 01, 2000 00:00:00 UTC+00:00').getTime();
237
+ const secondsUTC = Math.round(((new Date()).getTime() - oneJanuary2000) / 1000);
238
+ const secondsLocal = secondsUTC - (new Date()).getTimezoneOffset() * 60;
239
+ await device.getEndpoint(1).readResponse('genTime', data.meta.zclTransactionSequenceNumber, {time: secondsLocal});
240
+ }
241
+ },
242
+ };