@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,82 @@
1
+ const url = 'https://eu.salusconnect.io/demo/default/status/firmware?timestamp=0';
2
+ const assert = require('assert');
3
+ const common = require('./common');
4
+ const tar = require('tar-stream');
5
+ const axios = common.getAxios();
6
+
7
+ /**
8
+ * Helper functions
9
+ */
10
+
11
+ async function getImageMeta(current, logger, device) {
12
+ const modelID = device.modelID;
13
+ const images = (await axios.get(url)).data.versions;
14
+ const image = images.find((i) => i.model === modelID);
15
+ assert(image, `No image available for modelID '${modelID}'`);
16
+ return {
17
+ fileVersion: parseInt(image.version, 16),
18
+ url: image.url.replace(/^http:\/\//, 'https://'),
19
+ };
20
+ }
21
+
22
+ async function untar(tarStream) {
23
+ return new Promise((resolve, reject) => {
24
+ const extract = tar.extract();
25
+
26
+ const result = [];
27
+
28
+ extract.on('error', reject);
29
+
30
+ extract.on('entry', (headers, stream, next) => {
31
+ const buffers = [];
32
+
33
+ stream.on('data', function(data) {
34
+ buffers.push(data);
35
+ });
36
+
37
+ stream.on('end', function() {
38
+ result.push({
39
+ headers,
40
+ data: Buffer.concat(buffers),
41
+ });
42
+
43
+ next();
44
+ });
45
+
46
+ stream.resume();
47
+ });
48
+
49
+ extract.on('finish', () => {
50
+ resolve(result);
51
+ });
52
+
53
+ tarStream.pipe(extract);
54
+ });
55
+ }
56
+
57
+ async function downloadImage(meta, logger) {
58
+ const download = await axios.get(meta.url, {responseType: 'stream'});
59
+
60
+ const files = await untar(download.data);
61
+
62
+ const imageFile = files.find((file) => file.headers.name.endsWith('.ota'));
63
+
64
+ return imageFile;
65
+ }
66
+
67
+ /**
68
+ * Interface implementation
69
+ */
70
+
71
+ async function isUpdateAvailable(device, logger, requestPayload=null) {
72
+ return common.isUpdateAvailable(device, logger, common.isNewImageAvailable, requestPayload, getImageMeta);
73
+ }
74
+
75
+ async function updateToLatest(device, logger, onProgress) {
76
+ return common.updateToLatest(device, logger, onProgress, common.getNewImage, getImageMeta, downloadImage);
77
+ }
78
+
79
+ module.exports = {
80
+ isUpdateAvailable,
81
+ updateToLatest,
82
+ };
@@ -0,0 +1,25 @@
1
+ const common = require('./common');
2
+ const zigbeeOTA = require('./zigbeeOTA');
3
+
4
+ async function isUpdateAvailable(device, logger, requestPayload=null) {
5
+ if (device.modelID === 'PP-WHT-US') {
6
+ // see https://github.com/Koenkk/zigbee-OTA/pull/14
7
+ const scenesEndpoint = device.endpoints.find((e) => e.supportsOutputCluster('genScenes'));
8
+ await scenesEndpoint.write('genScenes', {currentGroup: 49502});
9
+ }
10
+ return common.isUpdateAvailable(device, logger, common.isNewImageAvailable, requestPayload, zigbeeOTA.getImageMeta);
11
+ }
12
+
13
+ async function updateToLatest(device, logger, onProgress) {
14
+ if (device.modelID === 'PP-WHT-US') {
15
+ // see https://github.com/Koenkk/zigbee-OTA/pull/14
16
+ const scenesEndpoint = device.endpoints.find((e) => e.supportsOutputCluster('genScenes'));
17
+ await scenesEndpoint.write('genScenes', {currentGroup: 49502});
18
+ }
19
+ return common.updateToLatest(device, logger, onProgress, common.getNewImage, zigbeeOTA.getImageMeta);
20
+ }
21
+
22
+ module.exports = {
23
+ isUpdateAvailable,
24
+ updateToLatest,
25
+ };
@@ -0,0 +1,45 @@
1
+ const productionURL = 'http://fw.ota.homesmart.ikea.net/feed/version_info.json';
2
+ const testURL = 'http://fw.test.ota.homesmart.ikea.net/feed/version_info.json';
3
+ const common = require('./common');
4
+ const axios = common.getAxios();
5
+ let useTestURL = false;
6
+
7
+ /**
8
+ * Helper functions
9
+ */
10
+
11
+ async function getImageMeta(current, logger, device) {
12
+ const url = useTestURL ? testURL : productionURL;
13
+ const imageType = current.imageType;
14
+ const images = (await axios.get(url)).data;
15
+ const image = images.find((i) => i.fw_image_type === imageType);
16
+
17
+ if (!image) {
18
+ throw new Error(`No image available for imageType '${imageType}'`);
19
+ }
20
+
21
+ return {
22
+ fileVersion: (image.fw_file_version_MSB << 16) | image.fw_file_version_LSB,
23
+ url: image.fw_binary_url,
24
+ };
25
+ }
26
+
27
+ /**
28
+ * Interface implementation
29
+ */
30
+
31
+ async function isUpdateAvailable(device, logger, requestPayload=null) {
32
+ return common.isUpdateAvailable(device, logger, common.isNewImageAvailable, requestPayload, getImageMeta);
33
+ }
34
+
35
+ async function updateToLatest(device, logger, onProgress) {
36
+ return common.updateToLatest(device, logger, onProgress, common.getNewImage, getImageMeta);
37
+ }
38
+
39
+ module.exports = {
40
+ isUpdateAvailable,
41
+ updateToLatest,
42
+ useTestURL: () => {
43
+ useTestURL = true;
44
+ },
45
+ };
@@ -0,0 +1,61 @@
1
+ const firmwareHtmlPageUrl = 'http://fwu.ubisys.de/smarthome/OTA/release/index';
2
+ const imageRegex = /10F2-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{8})\S*ota1?\.zigbee/gi;
3
+ const assert = require('assert');
4
+ const url = require('url');
5
+ const common = require('./common');
6
+ const axios = common.getAxios();
7
+
8
+ /**
9
+ * Helper functions
10
+ */
11
+
12
+ async function getImageMeta(current, logger, device) {
13
+ const imageType = current.imageType;
14
+ const hardwareVersion = device.hardwareVersion;
15
+
16
+ const firmwarePage = await axios.get(firmwareHtmlPageUrl);
17
+ logger.debug(
18
+ `OTA ubisys: got firmware page, status: ${firmwarePage.status}, data.length: ${firmwarePage.data.length}`);
19
+ assert(firmwarePage.status === 200, `HTTP Error getting ubisys firmware page`);
20
+ const firmwarePageHtml = firmwarePage.data;
21
+
22
+ imageRegex.lastIndex = 0; // reset (global) regex for next exec to match from the beginning again
23
+ let imageMatch = imageRegex.exec(firmwarePageHtml);
24
+ let highestMatch = null;
25
+ while (imageMatch != null) {
26
+ logger.debug(`OTA ubisys: image found: ${imageMatch[0]}`);
27
+ if (parseInt(imageMatch[1], 16) === imageType &&
28
+ parseInt(imageMatch[2], 16) <= hardwareVersion && hardwareVersion <= parseInt(imageMatch[3], 16)) {
29
+ if (highestMatch === null || parseInt(highestMatch[4], 16) < parseInt(imageMatch[4], 16)) {
30
+ highestMatch = imageMatch;
31
+ }
32
+ }
33
+ imageMatch = imageRegex.exec(firmwarePageHtml);
34
+ }
35
+ assert(highestMatch !== null,
36
+ `No image available for imageType '0x${imageType.toString(16)}' with hardware version ${hardwareVersion}`);
37
+
38
+ return {
39
+ hardwareVersionMin: parseInt(highestMatch[2], 16),
40
+ hardwareVersionMax: parseInt(highestMatch[3], 16),
41
+ fileVersion: parseInt(highestMatch[4], 16),
42
+ url: url.resolve(firmwareHtmlPageUrl, highestMatch[0]),
43
+ };
44
+ }
45
+
46
+ /**
47
+ * Interface implementation
48
+ */
49
+
50
+ async function isUpdateAvailable(device, logger, requestPayload=null) {
51
+ return common.isUpdateAvailable(device, logger, common.isNewImageAvailable, requestPayload, getImageMeta);
52
+ }
53
+
54
+ async function updateToLatest(device, logger, onProgress) {
55
+ return common.updateToLatest(device, logger, onProgress, common.getNewImage, getImageMeta);
56
+ }
57
+
58
+ module.exports = {
59
+ isUpdateAvailable,
60
+ updateToLatest,
61
+ };
@@ -0,0 +1,161 @@
1
+ const url = 'https://raw.githubusercontent.com/Koenkk/zigbee-OTA/master/index.json';
2
+ const common = require('./common');
3
+ const axios = common.getAxios();
4
+ const fs = require('fs');
5
+ const URI = require('uri-js');
6
+ const path = require('path');
7
+
8
+ let overrideIndexFileName = null;
9
+ let dataDir = null;
10
+
11
+ /**
12
+ * Helper functions
13
+ */
14
+
15
+
16
+ function isValidUrl(url) {
17
+ let parsed;
18
+ try {
19
+ parsed = URI.parse(url);
20
+ } catch (_) {
21
+ return false;
22
+ }
23
+ return parsed.scheme === 'http' || parsed.scheme === 'https';
24
+ }
25
+
26
+ async function getIndexFile(urlOrName) {
27
+ if (isValidUrl(urlOrName)) {
28
+ return (await axios.get(urlOrName)).data;
29
+ }
30
+
31
+ return JSON.parse(fs.readFileSync(urlOrName));
32
+ }
33
+
34
+ function readLocalFile(fileName, logger) {
35
+ // If the file name is not a full path, then treat it as a relative to the data directory
36
+ if (!path.isAbsolute(fileName) && dataDir) {
37
+ fileName = path.join(dataDir, fileName);
38
+ }
39
+
40
+ logger.debug(`ZigbeeOTA: getting local firmware file ${fileName}`);
41
+ return fs.readFileSync(fileName);
42
+ }
43
+
44
+ async function getFirmwareFile(image, logger) {
45
+ const urlOrName = image.url;
46
+
47
+ // First try to download firmware file with the URL provided
48
+ if (isValidUrl(urlOrName)) {
49
+ logger.debug(`ZigbeeOTA: downloading firmware image from ${urlOrName}`);
50
+ return await axios.get(urlOrName, {responseType: 'arraybuffer'});
51
+ }
52
+
53
+ return {data: readLocalFile(urlOrName, logger)};
54
+ }
55
+
56
+ function fillImageInfo(meta, logger) {
57
+ // Web-hosted images must come with all fields filled already
58
+ if (isValidUrl(meta.url)) {
59
+ return meta;
60
+ }
61
+
62
+ // Nothing to do if needed fields were filled already
63
+ if (meta.hasOwnProperty('imageType') &&
64
+ meta.hasOwnProperty('manufacturerCode') &&
65
+ meta.hasOwnProperty('fileVersion')) {
66
+ return meta;
67
+ }
68
+
69
+ // If no fields provided - get them from the image file
70
+ const buffer = readLocalFile(meta.url, logger);
71
+ const start = buffer.indexOf(common.upgradeFileIdentifier);
72
+ const image = common.parseImage(buffer.slice(start));
73
+
74
+ // Will fill only those fields that were absent
75
+ if (!meta.hasOwnProperty('imageType')) meta.imageType = image.header.imageType;
76
+ if (!meta.hasOwnProperty('manufacturerCode')) meta.manufacturerCode = image.header.manufacturerCode;
77
+ if (!meta.hasOwnProperty('fileVersion')) meta.fileVersion = image.header.fileVersion;
78
+ return meta;
79
+ }
80
+
81
+ async function getIndex(logger) {
82
+ const index = (await axios.get(url)).data;
83
+
84
+ logger.debug(`ZigbeeOTA: downloaded main index`);
85
+
86
+ if (overrideIndexFileName) {
87
+ logger.debug(`ZigbeeOTA: Loading override index ${overrideIndexFileName}`);
88
+ const localIndex = await getIndexFile(overrideIndexFileName);
89
+
90
+ // Resulting index will have overriden items first
91
+ return localIndex.concat(index).map((item) => isValidUrl(item.url) ? item : fillImageInfo(item, logger));
92
+ }
93
+
94
+ return index;
95
+ }
96
+
97
+ async function getImageMeta(current, logger, device) {
98
+ const modelId = device.modelID;
99
+ const imageType = current.imageType;
100
+ const manufacturerCode = current.manufacturerCode;
101
+ const manufacturerName = device.manufacturerName;
102
+ const images = await getIndex(logger);
103
+
104
+ // NOTE: Officially an image can be determined with a combination of manufacturerCode and imageType.
105
+ // However Gledopto pro products use the same imageType (0) for every device while the image is different.
106
+ // For this case additional identification through the modelId is done.
107
+ // In the case of Tuya and Moes, additional identification is carried out through the manufacturerName.
108
+ const image = images.find((i) => i.imageType === imageType && i.manufacturerCode === manufacturerCode &&
109
+ (!i.minFileVersion || current.fileVersion >= i.minFileVersion) && (!i.maxFileVersion || current.fileVersion <= i.maxFileVersion) &&
110
+ (!i.modelId || i.modelId === modelId) && (!i.manufacturerName || i.manufacturerName.includes(manufacturerName)));
111
+
112
+ if (!image) {
113
+ throw new Error(`No image available for imageType '${imageType}'`);
114
+ }
115
+
116
+ return {
117
+ fileVersion: image.fileVersion,
118
+ fileSize: image.fileSize,
119
+ url: image.url,
120
+ sha512: image.sha512,
121
+ force: image.force,
122
+ };
123
+ }
124
+
125
+ async function isNewImageAvailable(current, logger, device, getImageMeta) {
126
+ if (device.modelID === 'lumi.airrtc.agl001') {
127
+ // The current.fileVersion which comes from the device is wrong.
128
+ // Use the `aqaraFileVersion` which comes from the aqaraOpple.attributeReport instead.
129
+ // https://github.com/Koenkk/zigbee2mqtt/issues/16345#issuecomment-1454835056
130
+ // https://github.com/Koenkk/zigbee2mqtt/issues/16345 doesn't seem to be needed for all
131
+ if (device.meta.aqaraFileVersion) {
132
+ current = {...current, fileVersion: device.meta.aqaraFileVersion};
133
+ }
134
+ }
135
+
136
+ return common.isNewImageAvailable(current, logger, device, getImageMeta);
137
+ }
138
+
139
+ /**
140
+ * Interface implementation
141
+ */
142
+
143
+ async function isUpdateAvailable(device, logger, requestPayload=null) {
144
+ return common.isUpdateAvailable(device, logger, isNewImageAvailable, requestPayload, getImageMeta);
145
+ }
146
+
147
+ async function updateToLatest(device, logger, onProgress) {
148
+ return common.updateToLatest(device, logger, onProgress, common.getNewImage, getImageMeta, getFirmwareFile);
149
+ }
150
+
151
+ module.exports = {
152
+ getImageMeta,
153
+ isUpdateAvailable,
154
+ updateToLatest,
155
+ useIndexOverride: (indexFileName) => {
156
+ overrideIndexFileName = indexFileName;
157
+ },
158
+ setDataDir: (dir) => {
159
+ dataDir = dir;
160
+ },
161
+ };