@zwave-js/config 15.7.0 → 15.9.0

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 (674) hide show
  1. package/build/cjs/_version.d.ts +1 -1
  2. package/build/cjs/_version.js +1 -1
  3. package/build/cjs/_version.js.map +1 -1
  4. package/build/cjs/devices/DeviceConfig.d.ts +3 -1
  5. package/build/cjs/devices/DeviceConfig.js +115 -6
  6. package/build/cjs/devices/DeviceConfig.js.map +2 -2
  7. package/build/esm/_version.d.ts +1 -1
  8. package/build/esm/_version.js +1 -1
  9. package/build/esm/devices/DeviceConfig.d.ts +3 -1
  10. package/build/esm/devices/DeviceConfig.d.ts.map +1 -1
  11. package/build/esm/devices/DeviceConfig.js +133 -9
  12. package/build/esm/devices/DeviceConfig.js.map +1 -1
  13. package/config/devices/0x001d/dzpa1.json +8 -2
  14. package/config/devices/0x001d/dzpd3.json +2 -2
  15. package/config/devices/0x0039/39336_39443_zw3104.json +3 -3
  16. package/config/devices/0x0039/39337_39444_zw4103.json +3 -3
  17. package/config/devices/0x0039/39339_39346_zw3107.json +3 -3
  18. package/config/devices/0x0039/39342_39449_zw4106.json +3 -3
  19. package/config/devices/0x0039/39348_39455_zw4005.json +3 -3
  20. package/config/devices/0x0039/39348_39455_zw4008.json +3 -3
  21. package/config/devices/0x0039/39349_39456_zw1002.json +3 -3
  22. package/config/devices/0x0039/39351_39458_zw3005.json +3 -3
  23. package/config/devices/0x0039/39351_39458_zw3010.json +3 -3
  24. package/config/devices/0x0039/39354_39461_zw4003.json +3 -3
  25. package/config/devices/0x0039/39354_39461_zw4009.json +3 -3
  26. package/config/devices/0x0039/39357_39464_zw3004.json +3 -3
  27. package/config/devices/0x0039/39357_39464_zw3011.json +3 -3
  28. package/config/devices/0x0039/39358_39465_zw4002.json +3 -3
  29. package/config/devices/0x0039/39363_39470_zw4203.json +3 -3
  30. package/config/devices/0x0039/l7000-me.json +1 -1
  31. package/config/devices/0x0047/sy-iot101.json +3 -3
  32. package/config/devices/0x0047/z2rtseu-5.json +3 -3
  33. package/config/devices/0x004f/fxs-m08.json +1 -1
  34. package/config/devices/0x0059/bbk001-z00.json +3 -3
  35. package/config/devices/0x0059/max10y-376.json +3 -3
  36. package/config/devices/0x0059/max10z-737.json +3 -3
  37. package/config/devices/0x0059/ssp_301.json +3 -3
  38. package/config/devices/0x0059/ssp_301_anz.json +3 -3
  39. package/config/devices/0x0059/ssp_302_anz.json +3 -3
  40. package/config/devices/0x0059/ssr-302.json +3 -3
  41. package/config/devices/0x0060/ac136.json +3 -3
  42. package/config/devices/0x0060/ac137.json +3 -3
  43. package/config/devices/0x0060/ac301.json +3 -3
  44. package/config/devices/0x0060/ad146.json +3 -3
  45. package/config/devices/0x0060/ad147.json +3 -3
  46. package/config/devices/0x0060/an184.json +3 -3
  47. package/config/devices/0x0060/an186.json +3 -3
  48. package/config/devices/0x0060/an188.json +3 -3
  49. package/config/devices/0x0060/an196.json +3 -3
  50. package/config/devices/0x0060/eh403.json +3 -3
  51. package/config/devices/0x0060/se813.json +3 -3
  52. package/config/devices/0x0060/sm810.json +3 -3
  53. package/config/devices/0x0060/sp815.json +3 -3
  54. package/config/devices/0x0063/14286_zw1001.json +3 -3
  55. package/config/devices/0x0063/14287_zw4002.json +3 -3
  56. package/config/devices/0x0063/14288_zw1002.json +3 -3
  57. package/config/devices/0x0063/14293_zw4009.json +3 -3
  58. package/config/devices/0x0063/14297_zw1002.json +3 -3
  59. package/config/devices/0x0063/14298_zw4203.json +3 -3
  60. package/config/devices/0x0063/14307_zw3107.json +3 -3
  61. package/config/devices/0x0063/14309_zw4106.json +3 -3
  62. package/config/devices/0x0063/14311_zw4201.json +3 -3
  63. package/config/devices/0x0063/14313_zw1001.json +3 -3
  64. package/config/devices/0x0063/14314_zw4002.json +3 -3
  65. package/config/devices/0x0063/14315_zw1002.json +3 -3
  66. package/config/devices/0x0063/14319_zw4003.json +3 -3
  67. package/config/devices/0x0063/14320_zw4003.json +3 -3
  68. package/config/devices/0x0063/14322_zw3004.json +3 -3
  69. package/config/devices/0x0063/14325_zw4203.json +3 -3
  70. package/config/devices/0x0063/14326_zw3006.json +3 -3
  71. package/config/devices/0x0063/24770_zw4006.json +3 -3
  72. package/config/devices/0x0063/28166_zw3104.json +3 -3
  73. package/config/devices/0x0063/28170_zw3105.json +3 -3
  74. package/config/devices/0x0063/28171_zw3105.json +3 -3
  75. package/config/devices/0x0063/28172_zw4104.json +3 -3
  76. package/config/devices/0x0063/28173_zw4104.json +3 -3
  77. package/config/devices/0x0063/28176_zw4105.json +3 -3
  78. package/config/devices/0x0063/32562_zw6301.json +3 -3
  79. package/config/devices/0x0063/34172_zw5304.json +1 -1
  80. package/config/devices/0x0063/34174_zw5305.json +1 -1
  81. package/config/devices/0x0063/34176_zw5306.json +1 -1
  82. package/config/devices/0x0063/34184_zw5307.json +1 -1
  83. package/config/devices/0x0063/34193_zw6302.json +3 -3
  84. package/config/devices/0x0063/34194_zw6302.json +3 -3
  85. package/config/devices/0x0063/35211_zw6302B.json +3 -3
  86. package/config/devices/0x0063/35530_zw6302B.json +3 -3
  87. package/config/devices/0x0063/37792_zw5307.json +1 -1
  88. package/config/devices/0x0063/38957_zw6305.json +3 -3
  89. package/config/devices/0x0063/38959_zw6306.json +3 -3
  90. package/config/devices/0x0063/39348_54890_54891_zw4008.json +3 -3
  91. package/config/devices/0x0063/39351_zw3010.json +3 -3
  92. package/config/devices/0x0063/39354_54912_zw4009.json +3 -3
  93. package/config/devices/0x0063/43072_zw4008dv.json +3 -3
  94. package/config/devices/0x0063/43074_zw4009dv.json +3 -3
  95. package/config/devices/0x0063/43105_zw3010dv.json +3 -3
  96. package/config/devices/0x0063/43107_zw3011dv.json +3 -3
  97. package/config/devices/0x0063/43973_zw6305.json +3 -3
  98. package/config/devices/0x0063/43985_zw6306.json +3 -3
  99. package/config/devices/0x0063/45743_zw4002.json +3 -3
  100. package/config/devices/0x0063/46201_zw4008.json +3 -3
  101. package/config/devices/0x0063/46202_zw4009.json +3 -3
  102. package/config/devices/0x0063/46203_zw3010.json +3 -3
  103. package/config/devices/0x0063/46204_zw3011.json +3 -3
  104. package/config/devices/0x0063/46562_zw4008.json +3 -3
  105. package/config/devices/0x0063/46563_zw4009.json +3 -3
  106. package/config/devices/0x0063/46565_zw3011.json +3 -3
  107. package/config/devices/0x0063/52190_zw7105.json +3 -3
  108. package/config/devices/0x0063/52247_zw6309.json +3 -3
  109. package/config/devices/0x0063/52249_zw6308.json +3 -3
  110. package/config/devices/0x0063/52251_zw6307.json +3 -3
  111. package/config/devices/0x0063/52252_zw3012.json +3 -3
  112. package/config/devices/0x0063/53829_zw5313.json +3 -3
  113. package/config/devices/0x0063/53831_zw5314.json +2 -2
  114. package/config/devices/0x0063/55249_zw4106.json +3 -3
  115. package/config/devices/0x0063/55250_zw4104.json +3 -3
  116. package/config/devices/0x0063/55251_zw3107.json +3 -3
  117. package/config/devices/0x0063/55252_zw3105.json +3 -3
  118. package/config/devices/0x0063/55256_zw1002.json +3 -3
  119. package/config/devices/0x0063/55257_zw1002.json +3 -3
  120. package/config/devices/0x0063/55258_zw4002.json +3 -3
  121. package/config/devices/0x0063/55259_zw4002.json +3 -3
  122. package/config/devices/0x0063/56590_zw3012.json +3 -3
  123. package/config/devices/0x0063/58433_59344_zwa4011.json +3 -3
  124. package/config/devices/0x0063/58438_59346_zwa3016.json +3 -3
  125. package/config/devices/0x0063/58446_zwa4013.json +3 -3
  126. package/config/devices/0x0063/59337_zwa4011dv.json +61 -2
  127. package/config/devices/0x0063/59338_zwa4012dv.json +61 -2
  128. package/config/devices/0x0063/59350_59372_59373_zwa3016.json +3 -3
  129. package/config/devices/0x0063/59368_zwa4012.json +3 -3
  130. package/config/devices/0x0063/64637_zw7105.json +3 -3
  131. package/config/devices/0x0063/76596_ZWN4015.json +3 -3
  132. package/config/devices/0x0063/templates/jasco_template.json +4 -0
  133. package/config/devices/0x0068/gateway_fg2200.json +1 -1
  134. package/config/devices/0x0068/gateway_fg3200.json +1 -1
  135. package/config/devices/0x0068/td13010.json +3 -3
  136. package/config/devices/0x0068/td13320.json +3 -3
  137. package/config/devices/0x0068/tr1b120z1.json +3 -3
  138. package/config/devices/0x0068/ts2001.json +3 -3
  139. package/config/devices/0x0084/fts05.json +3 -3
  140. package/config/devices/0x0084/fts05p.json +3 -3
  141. package/config/devices/0x0084/spm1.json +3 -3
  142. package/config/devices/0x0085/arz_z-wave.json +3 -3
  143. package/config/devices/0x0085/zws12n.json +3 -3
  144. package/config/devices/0x0086/dsa03202.json +1 -1
  145. package/config/devices/0x0086/dsb09.json +3 -3
  146. package/config/devices/0x0086/dsb29.json +4 -4
  147. package/config/devices/0x0086/dsb54.json +1 -2
  148. package/config/devices/0x0086/dsc26.json +4 -4
  149. package/config/devices/0x0086/zw056.json +3 -3
  150. package/config/devices/0x0086/zw062.json +3 -3
  151. package/config/devices/0x0086/zw074.json +3 -3
  152. package/config/devices/0x0086/zw075.json +3 -3
  153. package/config/devices/0x0086/zw078.json +6 -6
  154. package/config/devices/0x0086/zw080.json +3 -3
  155. package/config/devices/0x0086/zw088.json +1 -1
  156. package/config/devices/0x0086/zw089.json +3 -3
  157. package/config/devices/0x0086/zw090.json +4 -4
  158. package/config/devices/0x0086/zw095.json +3 -3
  159. package/config/devices/0x0086/zw096.json +3 -3
  160. package/config/devices/0x0086/zw097.json +3 -3
  161. package/config/devices/0x0086/zw098.json +3 -3
  162. package/config/devices/0x0086/zw099.json +3 -3
  163. package/config/devices/0x0086/zw100.json +3 -3
  164. package/config/devices/0x0086/zw111.json +3 -3
  165. package/config/devices/0x0086/zw112.json +3 -3
  166. package/config/devices/0x0086/zw116.json +3 -3
  167. package/config/devices/0x0086/zw117.json +3 -3
  168. package/config/devices/0x0086/zw120.json +3 -3
  169. package/config/devices/0x0086/zw121.json +3 -3
  170. package/config/devices/0x0086/zw122.json +3 -3
  171. package/config/devices/0x0086/zw129.json +1 -1
  172. package/config/devices/0x0086/zw130.json +3 -3
  173. package/config/devices/0x0086/zw132.json +3 -3
  174. package/config/devices/0x0086/zw139.json +3 -3
  175. package/config/devices/0x0086/zw140.json +3 -3
  176. package/config/devices/0x0086/zw141.json +3 -3
  177. package/config/devices/0x0090/8225.json +3 -3
  178. package/config/devices/0x0090/8252.json +3 -3
  179. package/config/devices/0x0090/910.json +3 -3
  180. package/config/devices/0x0090/ged1455.json +3 -3
  181. package/config/devices/0x0090/ged2350.json +3 -3
  182. package/config/devices/0x0090/smartcode_888.json +3 -3
  183. package/config/devices/0x0094/2gig-edg-n.json +1 -1
  184. package/config/devices/0x0094/adc-200h-ev.json +3 -3
  185. package/config/devices/0x0094/adc-470l.json +1 -1
  186. package/config/devices/0x0094/adc-620t.json +1 -1
  187. package/config/devices/0x0094/adc-nk-100t.json +1 -1
  188. package/config/devices/0x0094/adc-sg130z.json +1 -1
  189. package/config/devices/0x0094/adtzwm_for_comman.json +1 -1
  190. package/config/devices/0x0094/ht-138s.json +3 -3
  191. package/config/devices/0x0094/ws900-29.json +3 -3
  192. package/config/devices/0x0099/gws-hr-001.json +1 -1
  193. package/config/devices/0x009b/2gig-stz.json +3 -3
  194. package/config/devices/0x0106/649496_02012_5.json +1 -1
  195. package/config/devices/0x0106/ch-1000.json +1 -1
  196. package/config/devices/0x0106/piper_nv.json +1 -1
  197. package/config/devices/0x0108/dch-g020.json +1 -1
  198. package/config/devices/0x0108/dch-g021.json +1 -1
  199. package/config/devices/0x0108/dch-g022.json +1 -1
  200. package/config/devices/0x0108/dch-z112.json +3 -3
  201. package/config/devices/0x0108/dch-z120.json +3 -3
  202. package/config/devices/0x0108/dch-z310.json +3 -3
  203. package/config/devices/0x0108/dch-z510.json +3 -3
  204. package/config/devices/0x0109/azl7434.json +3 -3
  205. package/config/devices/0x0109/za1011eu-5.json +1 -1
  206. package/config/devices/0x0109/zb5311us-5.json +3 -3
  207. package/config/devices/0x0109/zd2105.json +3 -3
  208. package/config/devices/0x0109/zd2106us-7.json +3 -3
  209. package/config/devices/0x0109/zd2112jp-5.json +3 -3
  210. package/config/devices/0x0109/zd2201.json +3 -3
  211. package/config/devices/0x0109/zd2301eu-5.json +3 -3
  212. package/config/devices/0x0109/zf5201eu-5.json +3 -3
  213. package/config/devices/0x0109/zg8101.json +3 -3
  214. package/config/devices/0x0109/zl7201de-5.json +3 -3
  215. package/config/devices/0x0109/zl7435-5.json +3 -3
  216. package/config/devices/0x0109/zm1601-5.json +3 -3
  217. package/config/devices/0x0109/zm1602-5.json +3 -3
  218. package/config/devices/0x0109/zm1602.json +3 -3
  219. package/config/devices/0x0109/zm1611jp-5.json +3 -3
  220. package/config/devices/0x0109/zm1621.json +3 -3
  221. package/config/devices/0x0109/zp3111-5.json +4 -4
  222. package/config/devices/0x0109/zp3113-7.json +3 -3
  223. package/config/devices/0x0109/zr1202.json +3 -3
  224. package/config/devices/0x0109/zs5101us-5.json +3 -3
  225. package/config/devices/0x0109/zs6101.json +2 -2
  226. package/config/devices/0x0109/zs6102eu-5.json +2 -3
  227. package/config/devices/0x0109/zs6301-5.json +2 -3
  228. package/config/devices/0x0109/zt1101.json +1 -1
  229. package/config/devices/0x0109/zt1141eu-5.json +1 -1
  230. package/config/devices/0x0109/zw4111eu-5.json +3 -3
  231. package/config/devices/0x010a/vitrum_i_dimmer.json +2 -2
  232. package/config/devices/0x010a/vitrum_i_switch.json +2 -2
  233. package/config/devices/0x010a/vitrum_ii_dimmer.json +3 -3
  234. package/config/devices/0x010a/vitrum_ii_switch.json +3 -3
  235. package/config/devices/0x010a/vitrum_iii_eu_dimmer.json +3 -3
  236. package/config/devices/0x010a/vitrum_satellite_i.json +3 -3
  237. package/config/devices/0x010a/vitrum_satellite_iv.json +3 -3
  238. package/config/devices/0x010a/vitrum_satellite_vi.json +3 -3
  239. package/config/devices/0x010b/dn3g6ja069.json +2 -2
  240. package/config/devices/0x010b/dn3g6ja082.json +2 -2
  241. package/config/devices/0x010b/dn3g6ja084.json +2 -2
  242. package/config/devices/0x010e/danalock_v3-btze.json +3 -3
  243. package/config/devices/0x010f/fgbs222.json +2 -2
  244. package/config/devices/0x010f/fgpb101.json +2 -2
  245. package/config/devices/0x010f/fgr-224.json +2 -2
  246. package/config/devices/0x010f/fgwp102.json +2 -2
  247. package/config/devices/0x0123/ne-ssen.json +3 -3
  248. package/config/devices/0x0123/smart-bridge_c3.json +1 -1
  249. package/config/devices/0x0123/smart-bridge_cl.json +1 -1
  250. package/config/devices/0x0127/738zpl.json +1 -1
  251. package/config/devices/0x0127/xtlpl.json +1 -1
  252. package/config/devices/0x0129/nf-yrc612-zw3.json +1 -1
  253. package/config/devices/0x0129/nf-yrc622-zw3.json +1 -1
  254. package/config/devices/0x0129/nf-yrd612-zw2.json +3 -3
  255. package/config/devices/0x0129/nf-yrd612-zw3.json +1 -1
  256. package/config/devices/0x0129/nf-yrd622-zw2.json +3 -3
  257. package/config/devices/0x0129/nf-yrd622-zw3.json +1 -1
  258. package/config/devices/0x0129/ntb610.json +3 -3
  259. package/config/devices/0x0129/ntb612-zw2.json +3 -3
  260. package/config/devices/0x0129/ntb620.json +3 -3
  261. package/config/devices/0x0129/ntb622-zw2.json +3 -3
  262. package/config/devices/0x0129/ntb632-zw2.json +3 -3
  263. package/config/devices/0x0129/ntb642-zw2.json +3 -3
  264. package/config/devices/0x0129/ntm610.json +3 -3
  265. package/config/devices/0x0129/ntm612-zw2.json +3 -3
  266. package/config/devices/0x0129/ntm617-zw2.json +3 -3
  267. package/config/devices/0x0129/ntm622-zw2.json +3 -3
  268. package/config/devices/0x0129/ntm625.json +3 -3
  269. package/config/devices/0x0129/ntm627-zw2.json +3 -3
  270. package/config/devices/0x0129/ntm632-zw2.json +3 -3
  271. package/config/devices/0x0129/ntm637-zw2.json +3 -3
  272. package/config/devices/0x0129/ntm642-zw2.json +3 -3
  273. package/config/devices/0x0129/ntm647-zw2.json +3 -3
  274. package/config/devices/0x0129/ntt610.json +3 -3
  275. package/config/devices/0x0129/ntt612-zw2.json +3 -3
  276. package/config/devices/0x0129/ntt620-zw2.json +3 -3
  277. package/config/devices/0x0129/ntt622-zw2.json +3 -3
  278. package/config/devices/0x0129/sd-l1000-ch.json +3 -3
  279. package/config/devices/0x0129/sr-bx-zw.json +3 -3
  280. package/config/devices/0x0129/templates/yale_template.json +4 -4
  281. package/config/devices/0x0129/yale_smart_door_lock_z-wave_module.json +3 -3
  282. package/config/devices/0x0129/ydm3109.json +3 -3
  283. package/config/devices/0x0129/ydm3109a.json +3 -3
  284. package/config/devices/0x0129/ydm4109plus.json +3 -3
  285. package/config/devices/0x0129/yrc216-zw3.json +1 -1
  286. package/config/devices/0x0129/yrc226-zw3.json +1 -1
  287. package/config/devices/0x0129/yrc256-zw3.json +1 -1
  288. package/config/devices/0x0129/yrc622-zw3.json +1 -1
  289. package/config/devices/0x0129/yrc642-zw3.json +1 -1
  290. package/config/devices/0x0129/yrc652-zw3.json +1 -1
  291. package/config/devices/0x0129/yrc_yrd_226_246_256_446-zw2.json +7 -4
  292. package/config/devices/0x0129/yrd136.json +3 -3
  293. package/config/devices/0x0129/yrd156.json +3 -3
  294. package/config/devices/0x0129/yrd216-zw2.json +3 -3
  295. package/config/devices/0x0129/yrd216-zw3.json +1 -1
  296. package/config/devices/0x0129/yrd226-zw3.json +1 -1
  297. package/config/devices/0x0129/yrd256-zw3.json +1 -1
  298. package/config/devices/0x0129/yrd410-zw2.json +3 -3
  299. package/config/devices/0x0129/yrd410-zw3.json +1 -1
  300. package/config/devices/0x0129/yrd416.json +3 -3
  301. package/config/devices/0x0129/yrd420-zw2.json +3 -3
  302. package/config/devices/0x0129/yrd420-zw3.json +1 -1
  303. package/config/devices/0x0129/yrd430-zw2.json +3 -3
  304. package/config/devices/0x0129/yrd430-zw3.json +1 -1
  305. package/config/devices/0x0129/yrd446.json +3 -3
  306. package/config/devices/0x0129/yrd450-zw2.json +3 -3
  307. package/config/devices/0x0129/yrd450-zw3.json +1 -1
  308. package/config/devices/0x0129/yrd4x0-f-zw3.json +1 -1
  309. package/config/devices/0x0129/yrd620.json +3 -3
  310. package/config/devices/0x0129/yrd622-zw2.json +3 -3
  311. package/config/devices/0x0129/yrd622-zw3.json +1 -1
  312. package/config/devices/0x0129/yrd642-zw2.json +3 -3
  313. package/config/devices/0x0129/yrd642-zw3.json +1 -1
  314. package/config/devices/0x0129/yrd652-zw2.json +3 -3
  315. package/config/devices/0x0129/yrd652-zw3.json +1 -1
  316. package/config/devices/0x0129/yrl216.json +3 -3
  317. package/config/devices/0x0129/yrl226.json +3 -3
  318. package/config/devices/0x0129/yrl256.json +3 -3
  319. package/config/devices/0x0129/yrm276.json +3 -3
  320. package/config/devices/0x0129/yrm476.json +3 -3
  321. package/config/devices/0x012a/iq_dimmer.json +1 -1
  322. package/config/devices/0x012a/iq_outlet.json +1 -1
  323. package/config/devices/0x012a/iqpanel2.json +1 -1
  324. package/config/devices/0x012a/qs9201-1208-840.json +1 -1
  325. package/config/devices/0x012a/qz2130-840.json +1 -1
  326. package/config/devices/0x012a/qz2140-840.json +1 -1
  327. package/config/devices/0x012a/qz2142-840.json +1 -1
  328. package/config/devices/0x0130/6500-1400-6000.json +3 -3
  329. package/config/devices/0x0130/qb3_x.json +3 -3
  330. package/config/devices/0x0131/ah-neo-ds07z.json +3 -3
  331. package/config/devices/0x0131/gr-105.json +3 -3
  332. package/config/devices/0x0131/ne-nas-ds01z.json +3 -3
  333. package/config/devices/0x0131/ne_nas_ab02z.json +3 -3
  334. package/config/devices/0x0131/vs-zd2301.json +3 -3
  335. package/config/devices/0x0131/zb_zw_g.json +1 -1
  336. package/config/devices/0x0133/pgzng1-2adnas.json +1 -1
  337. package/config/devices/0x0136/sl-1500.json +1 -1
  338. package/config/devices/0x0138/smco400.json +3 -3
  339. package/config/devices/0x0138/zcombo-g.json +4 -4
  340. package/config/devices/0x013c/nsg-ab-02.json +1 -1
  341. package/config/devices/0x013c/pac01.json +1 -1
  342. package/config/devices/0x013c/pad07.json +3 -3
  343. package/config/devices/0x013c/pad09.json +1 -1
  344. package/config/devices/0x013c/pan15-1-nes.json +1 -1
  345. package/config/devices/0x013c/pan26.json +3 -3
  346. package/config/devices/0x013c/pan34.json +3 -3
  347. package/config/devices/0x013c/psc03.json +1 -1
  348. package/config/devices/0x013c/psm09.json +2 -2
  349. package/config/devices/0x013c/psr03-b.json +1 -1
  350. package/config/devices/0x013c/psr07.json +1 -1
  351. package/config/devices/0x013c/pst02-a-br.json +3 -3
  352. package/config/devices/0x013c/pst02a.json +3 -3
  353. package/config/devices/0x013c/pst02b.json +3 -3
  354. package/config/devices/0x0140/fkabz002.json +1 -3
  355. package/config/devices/0x0140/sc428zw.json +3 -3
  356. package/config/devices/0x0147/razberry7_pro.json +0 -1
  357. package/config/devices/0x0149/wmsr.json +1 -1
  358. package/config/devices/0x014a/ddls2-zwave5.json +2 -2
  359. package/config/devices/0x014a/dls-zwave5.json +1 -1
  360. package/config/devices/0x014a/dtls2-zwave5.json +2 -2
  361. package/config/devices/0x014a/dwzwave25.json +2 -2
  362. package/config/devices/0x014a/ff-zwave5-eco.json +2 -2
  363. package/config/devices/0x014a/flf-zwave5_r1.json +3 -3
  364. package/config/devices/0x014a/gdzw7-eco.json +3 -3
  365. package/config/devices/0x014a/iszw7-eco.json +3 -3
  366. package/config/devices/0x014a/sc-zwave5.json +2 -2
  367. package/config/devices/0x014a/sdls2-zwave5.json +2 -2
  368. package/config/devices/0x014a/stls2-zwave5.json +2 -2
  369. package/config/devices/0x014a/tstat-tbz500.json +2 -2
  370. package/config/devices/0x014d/dkc1000.json +1 -1
  371. package/config/devices/0x014d/dkc1001.json +1 -1
  372. package/config/devices/0x014d/ibdk-01.json +1 -1
  373. package/config/devices/0x014d/ss302.json +1 -1
  374. package/config/devices/0x014f/2gig-gc2.json +1 -1
  375. package/config/devices/0x014f/el-sc-100.json +1 -1
  376. package/config/devices/0x014f/f-adt-hub.json +3 -3
  377. package/config/devices/0x014f/gd00z-6-7-8.json +3 -3
  378. package/config/devices/0x014f/husbz.json +0 -1
  379. package/config/devices/0x014f/lb60z-1.json +2 -2
  380. package/config/devices/0x014f/ps15emz51.json +2 -2
  381. package/config/devices/0x014f/wadwaz-1.json +2 -2
  382. package/config/devices/0x014f/wf00z.json +3 -3
  383. package/config/devices/0x014f/wo15emz5.json +3 -3
  384. package/config/devices/0x014f/wo15z.json +2 -2
  385. package/config/devices/0x014f/ws15z-1.json +2 -2
  386. package/config/devices/0x0157/ebv-105.json +3 -3
  387. package/config/devices/0x015a/jtb-3005-03.json +3 -3
  388. package/config/devices/0x015a/jtb-3011-03.json +3 -3
  389. package/config/devices/0x015b/ihu50.json +1 -1
  390. package/config/devices/0x015b/lap255u.json +1 -1
  391. package/config/devices/0x015d/nzw1201.json +3 -3
  392. package/config/devices/0x015d/nzw31t.json +3 -3
  393. package/config/devices/0x015d/zen20.json +3 -3
  394. package/config/devices/0x015d/zen21.json +3 -3
  395. package/config/devices/0x015d/zw-1104.json +3 -3
  396. package/config/devices/0x015d/zw1101.json +3 -3
  397. package/config/devices/0x015d/zw1103.json +3 -3
  398. package/config/devices/0x015d/zw1105.json +3 -3
  399. package/config/devices/0x015d/zw112.json +3 -3
  400. package/config/devices/0x015d/zw1201.json +3 -3
  401. package/config/devices/0x015d/zw1204.json +3 -3
  402. package/config/devices/0x015d/zw15.json +3 -3
  403. package/config/devices/0x015d/zw1502.json +3 -3
  404. package/config/devices/0x015d/zw30.json +3 -3
  405. package/config/devices/0x015d/zw31.json +3 -3
  406. package/config/devices/0x015d/zw32.json +3 -3
  407. package/config/devices/0x015d/zw36.json +3 -3
  408. package/config/devices/0x015d/zw37.json +3 -3
  409. package/config/devices/0x015d/zw38.json +3 -3
  410. package/config/devices/0x015d/zw39.json +3 -3
  411. package/config/devices/0x015d/zw661.json +3 -3
  412. package/config/devices/0x015d/zw671.json +3 -3
  413. package/config/devices/0x015d/zw96.json +3 -3
  414. package/config/devices/0x015d/zw97.json +3 -3
  415. package/config/devices/0x015d/zw98.json +3 -3
  416. package/config/devices/0x015f/a8-9.json +3 -3
  417. package/config/devices/0x015f/mh-p220.json +3 -3
  418. package/config/devices/0x015f/mh-s314-7102.json +2 -2
  419. package/config/devices/0x015f/mh-s412-5102.json +3 -3
  420. package/config/devices/0x015f/mh-s510.json +3 -3
  421. package/config/devices/0x015f/mh4936.json +4 -0
  422. package/config/devices/0x015f/mh6-hp.json +2 -2
  423. package/config/devices/0x015f/mh7h.json +3 -3
  424. package/config/devices/0x016a/ft098-k55.json +3 -3
  425. package/config/devices/0x016a/ft100.json +3 -3
  426. package/config/devices/0x016a/ft101.json +1 -1
  427. package/config/devices/0x016a/ft102.json +3 -3
  428. package/config/devices/0x016a/ft111.json +3 -3
  429. package/config/devices/0x016a/ft112.json +3 -3
  430. package/config/devices/0x016a/ft130-k.json +3 -3
  431. package/config/devices/0x016a/ufa01.json +3 -3
  432. package/config/devices/0x016b/204063.json +1 -1
  433. package/config/devices/0x017c/9601921000.json +3 -3
  434. package/config/devices/0x017e/tgfx-hub1.json +1 -1
  435. package/config/devices/0x017f/pwhub-wh01.json +1 -1
  436. package/config/devices/0x017f/wink_d_w_sensor.json +3 -3
  437. package/config/devices/0x017f/wink_motion_sensor.json +3 -3
  438. package/config/devices/0x018b/gcr-01s.json +3 -3
  439. package/config/devices/0x018b/gihg20.json +1 -1
  440. package/config/devices/0x018b/gwg-02.json +1 -1
  441. package/config/devices/0x018b/irhg-01.json +1 -1
  442. package/config/devices/0x018c/pm-b400zw-n.json +3 -3
  443. package/config/devices/0x018c/ssd-105.json +3 -3
  444. package/config/devices/0x018c/ssd-205.json +3 -3
  445. package/config/devices/0x018c/ssd-305.json +3 -3
  446. package/config/devices/0x018e/acgs-23zw.json +3 -3
  447. package/config/devices/0x018e/bx-32zw.json +3 -3
  448. package/config/devices/0x018e/bx-35zw.json +3 -3
  449. package/config/devices/0x018e/clmt-1zw.json +3 -3
  450. package/config/devices/0x018e/co-8zw.json +3 -3
  451. package/config/devices/0x018e/dc-15zw.json +3 -3
  452. package/config/devices/0x018e/dc-23zw.json +3 -3
  453. package/config/devices/0x018e/emd-1zw.json +3 -3
  454. package/config/devices/0x018e/hd-9zw.json +3 -3
  455. package/config/devices/0x018e/ir-16zw.json +3 -3
  456. package/config/devices/0x018e/lm-1zw.json +3 -3
  457. package/config/devices/0x018e/psm-29zw.json +3 -3
  458. package/config/devices/0x018e/psm-din2-zw.json +3 -3
  459. package/config/devices/0x018e/psm-din3-zw.json +3 -3
  460. package/config/devices/0x018e/pss-29zw.json +3 -3
  461. package/config/devices/0x018e/rmb-35zw.json +3 -3
  462. package/config/devices/0x018e/s-2zw.json +3 -3
  463. package/config/devices/0x018e/sd-16zw.json +3 -3
  464. package/config/devices/0x018e/sd-29.json +3 -3
  465. package/config/devices/0x018e/sd-8zw.json +3 -3
  466. package/config/devices/0x018e/sdco.json +3 -3
  467. package/config/devices/0x018e/srac-23zw.json +3 -3
  468. package/config/devices/0x018e/wls-23-zw.json +3 -3
  469. package/config/devices/0x018e/ws-15zw.json +3 -3
  470. package/config/devices/0x018f/zme_wallc-s.json +3 -3
  471. package/config/devices/0x019a/11-01-011.json +4 -4
  472. package/config/devices/0x019a/11_01_022.json +4 -4
  473. package/config/devices/0x019a/11_02_011.json +4 -4
  474. package/config/devices/0x019a/11_02_022.json +4 -4
  475. package/config/devices/0x019a/11_04_21_22_28.json +4 -4
  476. package/config/devices/0x019b/4512688.json +3 -3
  477. package/config/devices/0x019b/4512689.json +3 -3
  478. package/config/devices/0x019b/45_126_86.json +3 -3
  479. package/config/devices/0x019b/leakage-stopper.json +3 -3
  480. package/config/devices/0x019b/tf016_tf021.json +3 -3
  481. package/config/devices/0x019b/z-dim2.json +3 -3
  482. package/config/devices/0x019b/z-han2.json +3 -3
  483. package/config/devices/0x019b/z-ph_wall_controller.json +3 -3
  484. package/config/devices/0x019b/z-temp3.json +3 -3
  485. package/config/devices/0x019b/z-trm6.json +3 -3
  486. package/config/devices/0x019b/z-water2.json +3 -3
  487. package/config/devices/0x019b/zm_dimmer.json +3 -3
  488. package/config/devices/0x019b/zm_single_relay_16.json +3 -3
  489. package/config/devices/0x019b/zm_thermostat_16.json +3 -3
  490. package/config/devices/0x0208/hkzw_fld01.json +3 -3
  491. package/config/devices/0x0208/hkzw_so03.json +3 -3
  492. package/config/devices/0x0208/za-216001.json +3 -3
  493. package/config/devices/0x020e/zrksw.json +3 -3
  494. package/config/devices/0x0217/8001.json +3 -3
  495. package/config/devices/0x0217/9001.json +1 -1
  496. package/config/devices/0x021c/ilock15.json +3 -3
  497. package/config/devices/0x021d/db1.json +3 -3
  498. package/config/devices/0x021d/db2.json +3 -3
  499. package/config/devices/0x021d/ddl240x.json +3 -3
  500. package/config/devices/0x021d/hu03.json +3 -3
  501. package/config/devices/0x021d/ml2.json +3 -3
  502. package/config/devices/0x021f/dmex1.json +3 -3
  503. package/config/devices/0x021f/dmgw1.json +1 -1
  504. package/config/devices/0x021f/dms01.json +3 -3
  505. package/config/devices/0x021f/dmwv1.json +3 -3
  506. package/config/devices/0x0224/s30.json +1 -1
  507. package/config/devices/0x022a/hy-15-05.json +3 -3
  508. package/config/devices/0x022c/osr-01.json +3 -3
  509. package/config/devices/0x022c/osr-02.json +3 -3
  510. package/config/devices/0x022c/sa08.json +3 -3
  511. package/config/devices/0x022d/mc01-1702ops.json +3 -3
  512. package/config/devices/0x022d/mc01-507l.json +1 -1
  513. package/config/devices/0x022d/mc03-611zm.json +1 -1
  514. package/config/devices/0x022e/shp-gs100m.json +1 -1
  515. package/config/devices/0x022e/shp-ha502m.json +1 -1
  516. package/config/devices/0x022e/shp-sb100z.json +3 -3
  517. package/config/devices/0x022e/shp-sg100z.json +3 -3
  518. package/config/devices/0x022e/shp-sr100z.json +3 -3
  519. package/config/devices/0x022e/shp-tb100z.json +3 -3
  520. package/config/devices/0x0232/mit-sb100.json +1 -1
  521. package/config/devices/0x0239/stzw402.json +1 -1
  522. package/config/devices/0x023a/khez-0001.json +3 -3
  523. package/config/devices/0x023b/f4-zb-zwe.json +1 -1
  524. package/config/devices/0x023c/qbbiozw.json +3 -3
  525. package/config/devices/0x023c/qldlzw.json +3 -3
  526. package/config/devices/0x023d/dch-01.json +3 -3
  527. package/config/devices/0x023f/ca-1_c4-zwu.json +1 -1
  528. package/config/devices/0x023f/ea-1_c4-zwu.json +1 -1
  529. package/config/devices/0x023f/ea-3_c4-zwu.json +1 -1
  530. package/config/devices/0x023f/ea-5_c4-zwu.json +1 -1
  531. package/config/devices/0x0241/6336-brain-00008.json +1 -1
  532. package/config/devices/0x0242/03110101.json +3 -3
  533. package/config/devices/0x024a/heimdall.json +1 -1
  534. package/config/devices/0x024b/1015.json +1 -1
  535. package/config/devices/0x024c/ht-a10.json +3 -3
  536. package/config/devices/0x024c/ht-a20.json +3 -3
  537. package/config/devices/0x024d/dn3g6ja062.json +3 -3
  538. package/config/devices/0x024d/zg-500-v1.json +1 -1
  539. package/config/devices/0x024d/zg-501-v1.json +1 -1
  540. package/config/devices/0x024f/ad1-10v.json +3 -3
  541. package/config/devices/0x024f/am.json +3 -3
  542. package/config/devices/0x024f/ar1p.json +3 -3
  543. package/config/devices/0x024f/ar2p.json +3 -3
  544. package/config/devices/0x025b/ez0001.json +1 -1
  545. package/config/devices/0x025b/ezlopl.json +1 -1
  546. package/config/devices/0x025b/ezlosecure.json +1 -1
  547. package/config/devices/0x025b/zl-100.json +1 -1
  548. package/config/devices/0x026b/eia650rfz.json +3 -3
  549. package/config/devices/0x026e/brz1.json +1 -1
  550. package/config/devices/0x026e/crzb.json +3 -3
  551. package/config/devices/0x026e/csz1.json +3 -3
  552. package/config/devices/0x026e/mcz1.json +1 -1
  553. package/config/devices/0x026e/vcz1.json +1 -1
  554. package/config/devices/0x026f/zht-630.json +3 -3
  555. package/config/devices/0x027a/templates/zooz_template.json +3 -3
  556. package/config/devices/0x027a/zac03.json +3 -3
  557. package/config/devices/0x027a/zac36.json +3 -3
  558. package/config/devices/0x027a/zen06.json +3 -3
  559. package/config/devices/0x027a/zen14.json +3 -3
  560. package/config/devices/0x027a/zen15.json +3 -3
  561. package/config/devices/0x027a/zen17.json +3 -3
  562. package/config/devices/0x027a/zen20.json +3 -3
  563. package/config/devices/0x027a/zen21.json +3 -3
  564. package/config/devices/0x027a/zen26.json +3 -3
  565. package/config/devices/0x027a/zen27.json +3 -3
  566. package/config/devices/0x027a/zen30.json +3 -3
  567. package/config/devices/0x027a/zen32.json +3 -3
  568. package/config/devices/0x027a/zen34.json +4 -4
  569. package/config/devices/0x027a/zen37.json +4 -4
  570. package/config/devices/0x027a/zen71.json +3 -3
  571. package/config/devices/0x027a/zen72.json +3 -3
  572. package/config/devices/0x027a/zen73.json +3 -3
  573. package/config/devices/0x027a/zen74.json +3 -3
  574. package/config/devices/0x027a/zen76.json +3 -3
  575. package/config/devices/0x027a/zen77.json +3 -3
  576. package/config/devices/0x027a/zse01.json +3 -3
  577. package/config/devices/0x027a/zse02.json +3 -3
  578. package/config/devices/0x027a/zse11.json +3 -3
  579. package/config/devices/0x027a/zse18.json +4 -4
  580. package/config/devices/0x027a/zse29.json +3 -3
  581. package/config/devices/0x027a/zse40.json +3 -3
  582. package/config/devices/0x027a/zse41.json +4 -4
  583. package/config/devices/0x027a/zse42.json +4 -4
  584. package/config/devices/0x027a/zse43.json +4 -4
  585. package/config/devices/0x027a/zse44.json +3 -3
  586. package/config/devices/0x027a/zse70_800lr.json +3 -3
  587. package/config/devices/0x027b/sh-zw_cbb_ut.json +1 -1
  588. package/config/devices/0x028c/pwly-274343.json +1 -1
  589. package/config/devices/0x029c/o2_smart_box_2.json +3 -3
  590. package/config/devices/0x030a/dt82tv_f-1_2_14.json +3 -3
  591. package/config/devices/0x030c/fios-g1100-v1.json +1 -1
  592. package/config/devices/0x0312/n4002.json +2 -2
  593. package/config/devices/0x031c/zweve-usb-0001.json +0 -1
  594. package/config/devices/0x031d/zweecit1.json +3 -3
  595. package/config/devices/0x031e/lzw30-sn.json +4 -4
  596. package/config/devices/0x031e/lzw31-sn.json +4 -4
  597. package/config/devices/0x031e/lzw40.json +3 -3
  598. package/config/devices/0x031e/lzw41.json +3 -3
  599. package/config/devices/0x031e/lzw42.json +3 -3
  600. package/config/devices/0x031e/lzw60.json +3 -3
  601. package/config/devices/0x031e/vzw31-sn.json +1 -1
  602. package/config/devices/0x031e/vzw32-sn.json +1013 -0
  603. package/config/devices/0x032b/zd2102-5.json +3 -3
  604. package/config/devices/0x032c/sk-3003-06.json +3 -3
  605. package/config/devices/0x032c/sk-3003-07.json +3 -3
  606. package/config/devices/0x032c/sk-5005-02.json +1 -1
  607. package/config/devices/0x032d/bsl01.json +3 -3
  608. package/config/devices/0x033f/asl-03.json +3 -3
  609. package/config/devices/0x0349/estmk-z-wav.json +3 -3
  610. package/config/devices/0x0349/homee_0002.json +1 -1
  611. package/config/devices/0x034b/irm-03wl.json +1 -1
  612. package/config/devices/0x034c/kas-z10.json +3 -3
  613. package/config/devices/0x034c/kms-z10.json +3 -3
  614. package/config/devices/0x034e/mtbas-100-wl.json +3 -3
  615. package/config/devices/0x034e/mtrgb-100-wl.json +2 -3
  616. package/config/devices/0x034f/pl2s0s10-zw.json +3 -3
  617. package/config/devices/0x0353/re6100.json +1 -3
  618. package/config/devices/0x0369/7440-mc-fs.json +3 -3
  619. package/config/devices/0x0369/cw7.json +1 -1
  620. package/config/devices/0x036f/sentinel_2_0.json +1 -1
  621. package/config/devices/0x0371/zwa060.json +16 -0
  622. package/config/devices/0x037b/gkbc-3100z.json +3 -3
  623. package/config/devices/0x037b/gkdl-5000z.json +3 -3
  624. package/config/devices/0x037b/gkdl-5100z.json +3 -3
  625. package/config/devices/0x037b/gkw-1000z.json +3 -3
  626. package/config/devices/0x037b/gkw-2000.json +3 -3
  627. package/config/devices/0x037c/pad07-3e.json +5 -5
  628. package/config/devices/0x037c/psm08-3e.json +3 -3
  629. package/config/devices/0x038e/tfw-01.json +3 -3
  630. package/config/devices/0x039a/INT-SMDWD-01.json +3 -3
  631. package/config/devices/0x039a/INT-SMMD-N1.json +3 -3
  632. package/config/devices/0x039b/uzw4010tim2.json +0 -1
  633. package/config/devices/0x0407/ls090wh.json +1 -1
  634. package/config/devices/0x040b/pgzng1-2adnas.json +1 -3
  635. package/config/devices/0x040d/zw100.json +1 -1
  636. package/config/devices/0x040d/zw300.json +3 -3
  637. package/config/devices/0x040f/rs-zwirex1.json +3 -3
  638. package/config/devices/0x041a/kp-sw-07.json +3 -3
  639. package/config/devices/0x041a/kp-sw-08.json +3 -3
  640. package/config/devices/0x041b/39446_zw3107.json +3 -3
  641. package/config/devices/0x041b/39449_zw4106.json +3 -3
  642. package/config/devices/0x041b/39453_zw4203.json +3 -3
  643. package/config/devices/0x041b/39455_zw4008.json +3 -3
  644. package/config/devices/0x041b/39456_zw1002.json +3 -3
  645. package/config/devices/0x041b/39458_zw3010.json +2 -3
  646. package/config/devices/0x041b/proa7pl.json +0 -1
  647. package/config/devices/0x041b/smco410.json +57 -0
  648. package/config/devices/0x041b/tuxedow.json +3 -3
  649. package/config/devices/0x041c/51110.json +3 -3
  650. package/config/devices/0x041c/51111.json +3 -3
  651. package/config/devices/0x041c/51112.json +3 -3
  652. package/config/devices/0x041c/51114.json +3 -3
  653. package/config/devices/0x041e/eih-100e.json +0 -1
  654. package/config/devices/0x042a/zd2105us-5.json +3 -3
  655. package/config/devices/0x042c/wmbr.json +3 -3
  656. package/config/devices/0x042f/connect2.json +2 -2
  657. package/config/devices/0x043d/pgd728f_zpu.json +3 -3
  658. package/config/devices/0x0447/sqr62101whz.json +3 -3
  659. package/config/devices/0x044b/wp-02sf.json +2 -3
  660. package/config/devices/0x044c/myot.json +2 -2
  661. package/config/devices/0x044c/myot2.json +2 -2
  662. package/config/devices/0x044c/myot4.json +2 -2
  663. package/config/devices/0x044f/uvh1301.json +0 -3
  664. package/config/devices/0x045a/WB04V.json +3 -3
  665. package/config/devices/0x045a/WM25L.json +3 -3
  666. package/config/devices/0x045a/Z-TRV-V01.json +3 -3
  667. package/config/devices/0x0460/qldm-0A101.json +129 -0
  668. package/config/devices/0x0460/qlht-OU2Z.json +70 -0
  669. package/config/devices/0x0460/qlmo-003F.json +70 -0
  670. package/config/devices/0x0460/templates/wave_template.json +86 -1
  671. package/config/devices/0x0466/zwa-2.json +1 -1
  672. package/config/devices/0x046a/WB04V.json +3 -3
  673. package/config/devices/0x046a/WM25L.json +3 -3
  674. package/package.json +9 -9
@@ -1,2 +1,2 @@
1
- export declare const PACKAGE_VERSION = "15.7.0";
1
+ export declare const PACKAGE_VERSION = "15.9.0";
2
2
  //# sourceMappingURL=_version.d.ts.map
@@ -21,7 +21,7 @@ __export(version_exports, {
21
21
  PACKAGE_VERSION: () => PACKAGE_VERSION
22
22
  });
23
23
  module.exports = __toCommonJS(version_exports);
24
- const PACKAGE_VERSION = "15.7.0";
24
+ const PACKAGE_VERSION = "15.9.0";
25
25
  // Annotate the CommonJS export names for ESM import in node:
26
26
  0 && (module.exports = {
27
27
  PACKAGE_VERSION
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/_version.ts"],
4
- "sourcesContent": ["// This file is auto-generated by the codegen maintenance script\nexport const PACKAGE_VERSION = \"15.7.0\";\n"],
4
+ "sourcesContent": ["// This file is auto-generated by the codegen maintenance script\nexport const PACKAGE_VERSION = \"15.9.0\";\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;;;;;AAAA;;;;;AACO,MAAM,kBAAkB;",
6
6
  "names": []
7
7
  }
@@ -114,6 +114,8 @@ export declare class DeviceConfig {
114
114
  /**
115
115
  * Returns a hash code that can be used to check whether a device config has changed enough to require a re-interview.
116
116
  */
117
- getHash(algorithm?: "md5" | "sha-256"): Promise<Uint8Array>;
117
+ getHash(version?: 0 | 1 | 2): Promise<Uint8Array>;
118
+ static get maxHashVersion(): 2;
119
+ static areHashesEqual(hash: Uint8Array, other: Uint8Array): boolean;
118
120
  }
119
121
  //# sourceMappingURL=DeviceConfig.d.ts.map
@@ -206,6 +206,40 @@ function isFirmwareVersion(val) {
206
206
  return typeof val === "string" && firmwareVersionRegex.test(val) && val.split(".").map((str) => parseInt(str, 10)).every((num) => num >= 0 && num <= 255);
207
207
  }
208
208
  __name(isFirmwareVersion, "isFirmwareVersion");
209
+ const deflateDict = import_shared.Bytes.from(
210
+ // Substrings appearing in the device config files in descending order of frequency
211
+ // except for very short ones like 0, 1, ...
212
+ // WARNING: THIS MUST NOT BE CHANGED! Doing so breaks decompressing stored hashes.
213
+ [
214
+ `"parameterNumber":`,
215
+ `255`,
216
+ `"value":`,
217
+ `"defaultValue":`,
218
+ `"valueSize":`,
219
+ `"maxValue":`,
220
+ `"minValue":`,
221
+ `"options":`,
222
+ `true`,
223
+ `false`,
224
+ `"allowManualEntry":`,
225
+ `"maxNodes":`,
226
+ `100`,
227
+ `"unsigned":`,
228
+ `"paramInformation":`,
229
+ `"isLifeline":`,
230
+ `"seconds"`,
231
+ `99`,
232
+ `127`,
233
+ `"%"`,
234
+ `65535`,
235
+ `32767`,
236
+ `"minutes"`,
237
+ `"endpoints":`,
238
+ `"hours"`,
239
+ `"multiChannel":`
240
+ ].join(""),
241
+ "utf8"
242
+ );
209
243
  class ConditionalDeviceConfig {
210
244
  static {
211
245
  __name(this, "ConditionalDeviceConfig");
@@ -400,7 +434,7 @@ class DeviceConfig {
400
434
  return this.endpoints?.get(endpointIndex)?.associations?.get(group);
401
435
  }
402
436
  }
403
- getHashable() {
437
+ getHashable(version) {
404
438
  let hashable = {
405
439
  // endpoints: {
406
440
  // associations: {},
@@ -432,7 +466,7 @@ class DeviceConfig {
432
466
  if (!map || !map.size)
433
467
  return;
434
468
  const getParamKey = /* @__PURE__ */ __name((param) => `${param.parameterNumber}${param.valueBitMask ? `[${(0, import_shared.num2hex)(param.valueBitMask)}]` : ""}`, "getParamKey");
435
- target.paramInformation = [...map.values()].sort((a, b) => getParamKey(a).localeCompare(getParamKey(b)));
469
+ target.paramInformation = [...map.values()].sort((a, b) => getParamKey(a).localeCompare(getParamKey(b))).map((p) => (0, import_shared.cloneDeep)(p));
436
470
  }, "cloneParamInformationMap");
437
471
  {
438
472
  let ep0 = {};
@@ -494,17 +528,92 @@ class DeviceConfig {
494
528
  hashable.compat = c;
495
529
  }
496
530
  }
531
+ if (version > 1) {
532
+ for (const ep of Object.values(hashable.endpoints ?? {})) {
533
+ for (const param of ep.paramInformation ?? []) {
534
+ delete param.label;
535
+ delete param.description;
536
+ for (const opt of param.options ?? []) {
537
+ delete opt.label;
538
+ }
539
+ }
540
+ }
541
+ }
497
542
  hashable = sortObject(hashable);
498
- return import_shared.Bytes.from(JSON.stringify(hashable), "utf8");
543
+ return hashable;
499
544
  }
500
545
  /**
501
546
  * Returns a hash code that can be used to check whether a device config has changed enough to require a re-interview.
502
547
  */
503
- getHash(algorithm = "sha-256") {
504
- const buffer = this.getHashable();
505
- return (0, import_core.digest)(algorithm, buffer);
548
+ async getHash(version = DeviceConfig.maxHashVersion) {
549
+ const hashable = this.getHashable(version);
550
+ let hash;
551
+ if (version === 0) {
552
+ const buffer = import_shared.Bytes.from(JSON.stringify(hashable), "utf8");
553
+ return await (0, import_core.digest)("md5", buffer);
554
+ } else if (version === 1) {
555
+ const buffer = import_shared.Bytes.from(JSON.stringify(hashable), "utf8");
556
+ return await (0, import_core.digest)("sha-256", buffer);
557
+ } else {
558
+ hash = (0, import_core.deflateSync)(
559
+ import_shared.Bytes.from(JSON.stringify(hashable), "utf8"),
560
+ // Try to make the hash as small as possible
561
+ { level: 9, dictionary: deflateDict }
562
+ );
563
+ }
564
+ const prefixBytes = import_shared.Bytes.from(`$v${version}$`, "utf8");
565
+ return import_shared.Bytes.concat([prefixBytes, hash]);
566
+ }
567
+ static get maxHashVersion() {
568
+ return 2;
569
+ }
570
+ static areHashesEqual(hash, other) {
571
+ const parsedHash = parseHash(hash);
572
+ const parsedOther = parseHash(other);
573
+ if (!parsedHash || !parsedOther)
574
+ return false;
575
+ if (parsedHash.version < 2 && parsedOther.version < 2) {
576
+ return import_shared.Bytes.view(parsedHash.hashData).equals(parsedOther.hashData);
577
+ }
578
+ if (parsedHash.version < 2 || parsedOther.version < 2) {
579
+ return false;
580
+ }
581
+ if (parsedHash.version === parsedOther.version) {
582
+ return import_shared.Bytes.view(parsedHash.hashData).equals(parsedOther.hashData);
583
+ }
584
+ return false;
585
+ }
586
+ }
587
+ function parseHash(hash) {
588
+ const hashString = import_shared.Bytes.view(hash).toString("utf8");
589
+ const versionMatch = hashString.match(/^\$v(\d+)\$/);
590
+ if (versionMatch) {
591
+ const version = parseInt(versionMatch[1], 10);
592
+ const hashData = hash.subarray(
593
+ // The prefix is ASCII, so this is safe to do even in the context of UTF-8
594
+ versionMatch[0].length
595
+ );
596
+ return {
597
+ version,
598
+ hashData
599
+ };
600
+ }
601
+ switch (hash.length) {
602
+ case 16:
603
+ return {
604
+ version: 0,
605
+ hashData: hash
606
+ };
607
+ case 32:
608
+ return {
609
+ version: 1,
610
+ hashData: hash
611
+ };
612
+ default:
613
+ return void 0;
506
614
  }
507
615
  }
616
+ __name(parseHash, "parseHash");
508
617
  // Annotate the CommonJS export names for ESM import in node:
509
618
  0 && (module.exports = {
510
619
  ConditionalDeviceConfig,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/devices/DeviceConfig.ts"],
4
- "sourcesContent": ["import { configDir } from \"#config_dir\";\nimport { ZWaveError, ZWaveErrorCodes, digest } from \"@zwave-js/core\";\nimport {\n\tBytes,\n\ttype JSONObject,\n\tenumFilesRecursive,\n\tformatId,\n\tgetenv,\n\tnum2hex,\n\tpadVersion,\n\tpathExists,\n\tpick,\n\treadTextFile,\n\tstringify,\n\twriteTextFile,\n} from \"@zwave-js/shared\";\nimport type {\n\tReadFile,\n\tReadFileSystemInfo,\n\tWriteFile,\n} from \"@zwave-js/shared/bindings\";\nimport { isArray, isObject } from \"alcalzone-shared/typeguards\";\nimport JSON5 from \"json5\";\nimport path from \"pathe\";\nimport semverGt from \"semver/functions/gt.js\";\nimport { clearTemplateCache, readJsonWithTemplate } from \"../JsonTemplate.js\";\nimport type { ConfigLogger } from \"../Logger.js\";\nimport { hexKeyRegex4Digits, throwInvalidConfig } from \"../utils_safe.js\";\nimport {\n\ttype AssociationConfig,\n\tConditionalAssociationConfig,\n} from \"./AssociationConfig.js\";\nimport { type CompatConfig, ConditionalCompatConfig } from \"./CompatConfig.js\";\nimport { evaluateDeep, validateCondition } from \"./ConditionalItem.js\";\nimport {\n\ttype ConditionalPrimitive,\n\tparseConditionalPrimitive,\n} from \"./ConditionalPrimitive.js\";\nimport {\n\tConditionalDeviceMetadata,\n\ttype DeviceMetadata,\n} from \"./DeviceMetadata.js\";\nimport {\n\tConditionalEndpointConfig,\n\ttype EndpointConfig,\n} from \"./EndpointConfig.js\";\nimport {\n\ttype ConditionalParamInfoMap,\n\ttype ParamInfoMap,\n\ttype ParamInformation,\n\tparseConditionalParamInformationMap,\n} from \"./ParamInformation.js\";\nimport type { DeviceID, FirmwareVersionRange } from \"./shared.js\";\n\nexport interface DeviceConfigIndexEntry {\n\tmanufacturerId: string;\n\tproductType: string;\n\tproductId: string;\n\tfirmwareVersion: FirmwareVersionRange;\n\tpreferred?: true;\n\trootDir?: string;\n\tfilename: string;\n}\n\nexport interface FulltextDeviceConfigIndexEntry {\n\tmanufacturerId: string;\n\tmanufacturer: string;\n\tlabel: string;\n\tdescription: string;\n\tproductType: string;\n\tproductId: string;\n\tfirmwareVersion: FirmwareVersionRange;\n\tpreferred?: true;\n\trootDir?: string;\n\tfilename: string;\n}\n\nexport const embeddedDevicesDir = path.join(configDir, \"devices\");\nconst fulltextIndexPath = path.join(embeddedDevicesDir, \"fulltext_index.json\");\n\nexport function getDevicesPaths(configDir: string): {\n\tdevicesDir: string;\n\tindexPath: string;\n} {\n\tconst devicesDir = path.join(configDir, \"devices\");\n\tconst indexPath = path.join(devicesDir, \"index.json\");\n\treturn { devicesDir, indexPath };\n}\n\nexport type DeviceConfigIndex = DeviceConfigIndexEntry[];\nexport type FulltextDeviceConfigIndex = FulltextDeviceConfigIndexEntry[];\n\nasync function hasChangedDeviceFiles(\n\tfs: ReadFileSystemInfo,\n\tdevicesRoot: string,\n\tdir: string,\n\tlastChange: Date,\n): Promise<boolean> {\n\t// Check if there are any files BUT index.json that were changed\n\t// or directories that were modified\n\tconst filesAndDirs = await fs.readDir(dir);\n\tfor (const f of filesAndDirs) {\n\t\tconst fullPath = path.join(dir, f);\n\n\t\tconst stat = await fs.stat(fullPath);\n\t\tif (\n\t\t\t(dir !== devicesRoot || f !== \"index.json\")\n\t\t\t&& (stat.isFile() || stat.isDirectory())\n\t\t\t&& stat.mtime > lastChange\n\t\t) {\n\t\t\treturn true;\n\t\t} else if (stat.isDirectory()) {\n\t\t\t// we need to go deeper!\n\t\t\tif (\n\t\t\t\tawait hasChangedDeviceFiles(\n\t\t\t\t\tfs,\n\t\t\t\t\tdevicesRoot,\n\t\t\t\t\tfullPath,\n\t\t\t\t\tlastChange,\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Read all device config files from a given directory and return them as index entries.\n * Does not update the index itself.\n */\nasync function generateIndex<T extends Record<string, unknown>>(\n\tfs: ReadFileSystemInfo & ReadFile,\n\tdevicesDir: string,\n\tisEmbedded: boolean,\n\textractIndexEntries: (config: DeviceConfig) => T[],\n\tlogger?: ConfigLogger,\n): Promise<(T & { filename: string; rootDir?: string })[]> {\n\tconst index: (T & { filename: string; rootDir?: string })[] = [];\n\n\tclearTemplateCache();\n\tconst configFiles = await enumFilesRecursive(\n\t\tfs,\n\t\tdevicesDir,\n\t\t(file) =>\n\t\t\tfile.endsWith(\".json\")\n\t\t\t&& !file.endsWith(\"index.json\")\n\t\t\t&& !file.includes(\"/templates/\")\n\t\t\t&& !file.includes(\"\\\\templates\\\\\"),\n\t);\n\n\t// Add the embedded devices dir as a fallback if necessary\n\tconst fallbackDirs = devicesDir !== embeddedDevicesDir\n\t\t? [embeddedDevicesDir]\n\t\t: undefined;\n\n\tfor (const file of configFiles) {\n\t\tconst relativePath = path\n\t\t\t.relative(devicesDir, file)\n\t\t\t.replaceAll(\"\\\\\", \"/\");\n\t\t// Try parsing the file\n\t\ttry {\n\t\t\tconst config = await DeviceConfig.from(\n\t\t\t\tfs,\n\t\t\t\tfile,\n\t\t\t\tisEmbedded,\n\t\t\t\t{\n\t\t\t\t\trootDir: devicesDir,\n\t\t\t\t\tfallbackDirs,\n\t\t\t\t\trelative: true,\n\t\t\t\t},\n\t\t\t);\n\t\t\t// Add the file to the index\n\t\t\tindex.push(\n\t\t\t\t...extractIndexEntries(config).map((entry) => {\n\t\t\t\t\tconst ret: T & { filename: string; rootDir?: string } = {\n\t\t\t\t\t\t...entry,\n\t\t\t\t\t\tfilename: relativePath,\n\t\t\t\t\t};\n\t\t\t\t\t// Only add the root dir to the index if necessary\n\t\t\t\t\tif (devicesDir !== embeddedDevicesDir) {\n\t\t\t\t\t\tret.rootDir = devicesDir;\n\t\t\t\t\t}\n\t\t\t\t\treturn ret;\n\t\t\t\t}),\n\t\t\t);\n\t\t} catch (e) {\n\t\t\tconst message = `Error parsing config file ${relativePath}: ${\n\t\t\t\t(e as Error).message\n\t\t\t}`;\n\t\t\t// Crash hard during tests, just print an error when in production systems.\n\t\t\t// A user could have changed a config file\n\t\t\tif (process.env.NODE_ENV === \"test\" || !!getenv(\"CI\")) {\n\t\t\t\tthrow new ZWaveError(message, ZWaveErrorCodes.Config_Invalid);\n\t\t\t} else {\n\t\t\t\tlogger?.print(message, \"error\");\n\t\t\t}\n\t\t}\n\t}\n\n\treturn index;\n}\n\nasync function loadDeviceIndexShared<T extends Record<string, unknown>>(\n\tfs: ReadFileSystemInfo & ReadFile & WriteFile,\n\tdevicesDir: string,\n\tindexPath: string,\n\textractIndexEntries: (config: DeviceConfig) => T[],\n\tlogger?: ConfigLogger,\n): Promise<(T & { filename: string })[]> {\n\t// The index file needs to be regenerated if it does not exist\n\tlet needsUpdate = !(await pathExists(fs, indexPath));\n\tlet index: (T & { filename: string })[] | undefined;\n\tlet mtimeIndex: Date | undefined;\n\t// ...or if cannot be parsed\n\tif (!needsUpdate) {\n\t\ttry {\n\t\t\tconst fileContents = await readTextFile(fs, indexPath, \"utf8\");\n\t\t\tindex = JSON5.parse(fileContents);\n\t\t\tmtimeIndex = (await fs.stat(indexPath)).mtime;\n\t\t} catch {\n\t\t\tlogger?.print(\n\t\t\t\t\"Error while parsing index file - regenerating...\",\n\t\t\t\t\"warn\",\n\t\t\t);\n\t\t\tneedsUpdate = true;\n\t\t} finally {\n\t\t\tif (!index) {\n\t\t\t\tlogger?.print(\n\t\t\t\t\t\"Index file was malformed - regenerating...\",\n\t\t\t\t\t\"warn\",\n\t\t\t\t);\n\t\t\t\tneedsUpdate = true;\n\t\t\t}\n\t\t}\n\t}\n\n\t// ...or if there were any changes in the file system\n\tif (!needsUpdate) {\n\t\tneedsUpdate = await hasChangedDeviceFiles(\n\t\t\tfs,\n\t\t\tdevicesDir,\n\t\t\tdevicesDir,\n\t\t\tmtimeIndex!,\n\t\t);\n\t\tif (needsUpdate) {\n\t\t\tlogger?.print(\n\t\t\t\t\"Device configuration files on disk changed - regenerating index...\",\n\t\t\t\t\"verbose\",\n\t\t\t);\n\t\t}\n\t}\n\n\tif (needsUpdate) {\n\t\t// Read all files from disk and generate an index\n\t\tindex = await generateIndex(\n\t\t\tfs,\n\t\t\tdevicesDir,\n\t\t\ttrue,\n\t\t\textractIndexEntries,\n\t\t\tlogger,\n\t\t);\n\t\t// Save the index to disk\n\t\ttry {\n\t\t\tawait writeTextFile(\n\t\t\t\tfs,\n\t\t\t\tpath.join(indexPath),\n\t\t\t\t`// This file is auto-generated. DO NOT edit it by hand if you don't know what you're doing!\"\n${stringify(index, \"\\t\")}\n`,\n\t\t\t\t\"utf8\",\n\t\t\t);\n\t\t\tlogger?.print(\"Device index regenerated\", \"verbose\");\n\t\t} catch (e) {\n\t\t\tlogger?.print(\n\t\t\t\t`Writing the device index to disk failed: ${\n\t\t\t\t\t(e as Error).message\n\t\t\t\t}`,\n\t\t\t\t\"error\",\n\t\t\t);\n\t\t}\n\t}\n\n\treturn index!;\n}\n\n/**\n * @internal\n * Loads the index file to quickly access the device configs.\n * Transparently handles updating the index if necessary\n */\nexport async function generatePriorityDeviceIndex(\n\tfs: ReadFileSystemInfo & ReadFile,\n\tdeviceConfigPriorityDir: string,\n\tlogger?: ConfigLogger,\n): Promise<DeviceConfigIndex> {\n\treturn (\n\t\tawait generateIndex(\n\t\t\tfs,\n\t\t\tdeviceConfigPriorityDir,\n\t\t\tfalse,\n\t\t\t(config) =>\n\t\t\t\tconfig.devices.map((dev) => ({\n\t\t\t\t\tmanufacturerId: formatId(\n\t\t\t\t\t\tconfig.manufacturerId.toString(16),\n\t\t\t\t\t),\n\t\t\t\t\tmanufacturer: config.manufacturer,\n\t\t\t\t\tlabel: config.label,\n\t\t\t\t\tproductType: formatId(dev.productType),\n\t\t\t\t\tproductId: formatId(dev.productId),\n\t\t\t\t\tfirmwareVersion: config.firmwareVersion,\n\t\t\t\t\t...(config.preferred ? { preferred: true as const } : {}),\n\t\t\t\t\trootDir: deviceConfigPriorityDir,\n\t\t\t\t})),\n\t\t\tlogger,\n\t\t)\n\t).map(({ filename, ...entry }) => ({\n\t\t...entry,\n\t\t// The generated index makes the filenames relative to the given directory\n\t\t// but we need them to be absolute\n\t\tfilename: path.join(deviceConfigPriorityDir, filename),\n\t}));\n}\n\n/**\n * @internal\n * Loads the index file to quickly access the device configs.\n * Transparently handles updating the index if necessary\n */\nexport async function loadDeviceIndexInternal(\n\tfs: ReadFileSystemInfo & ReadFile & WriteFile,\n\tlogger?: ConfigLogger,\n\texternalConfigDir?: string,\n): Promise<DeviceConfigIndex> {\n\tconst { devicesDir, indexPath } = getDevicesPaths(\n\t\texternalConfigDir || configDir,\n\t);\n\n\treturn loadDeviceIndexShared(\n\t\tfs,\n\t\tdevicesDir,\n\t\tindexPath,\n\t\t(config) =>\n\t\t\tconfig.devices.map((dev) => ({\n\t\t\t\tmanufacturerId: formatId(config.manufacturerId.toString(16)),\n\t\t\t\tmanufacturer: config.manufacturer,\n\t\t\t\tlabel: config.label,\n\t\t\t\tproductType: formatId(dev.productType),\n\t\t\t\tproductId: formatId(dev.productId),\n\t\t\t\tfirmwareVersion: config.firmwareVersion,\n\t\t\t\t...(config.preferred ? { preferred: true as const } : {}),\n\t\t\t})),\n\t\tlogger,\n\t);\n}\n\n/**\n * @internal\n * Loads the full text index file to quickly search the device configs.\n * Transparently handles updating the index if necessary\n */\nexport async function loadFulltextDeviceIndexInternal(\n\tfs: ReadFileSystemInfo & ReadFile & WriteFile,\n\tlogger?: ConfigLogger,\n): Promise<FulltextDeviceConfigIndex> {\n\t// This method is not meant to operate with the external device index!\n\treturn loadDeviceIndexShared(\n\t\tfs,\n\t\tembeddedDevicesDir,\n\t\tfulltextIndexPath,\n\t\t(config) =>\n\t\t\tconfig.devices.map((dev) => ({\n\t\t\t\tmanufacturerId: formatId(config.manufacturerId.toString(16)),\n\t\t\t\tmanufacturer: config.manufacturer,\n\t\t\t\tlabel: config.label,\n\t\t\t\tdescription: config.description,\n\t\t\t\tproductType: formatId(dev.productType),\n\t\t\t\tproductId: formatId(dev.productId),\n\t\t\t\tfirmwareVersion: config.firmwareVersion,\n\t\t\t\t...(config.preferred ? { preferred: true as const } : {}),\n\t\t\t\trootDir: embeddedDevicesDir,\n\t\t\t})),\n\t\tlogger,\n\t);\n}\n\nfunction isHexKeyWith4Digits(val: any): val is string {\n\treturn typeof val === \"string\" && hexKeyRegex4Digits.test(val);\n}\n\nconst firmwareVersionRegex = /^\\d{1,3}\\.\\d{1,3}(\\.\\d{1,3})?$/;\nfunction isFirmwareVersion(val: any): val is string {\n\treturn (\n\t\ttypeof val === \"string\"\n\t\t&& firmwareVersionRegex.test(val)\n\t\t&& val\n\t\t\t.split(\".\")\n\t\t\t.map((str) => parseInt(str, 10))\n\t\t\t.every((num) => num >= 0 && num <= 255)\n\t);\n}\n\n/** This class represents a device config entry whose conditional settings have not been evaluated yet */\nexport class ConditionalDeviceConfig {\n\tpublic static async from(\n\t\tfs: ReadFileSystemInfo & ReadFile,\n\t\tfilename: string,\n\t\tisEmbedded: boolean,\n\t\toptions: {\n\t\t\trootDir: string;\n\t\t\tfallbackDirs?: string[];\n\t\t\trelative?: boolean;\n\t\t},\n\t): Promise<ConditionalDeviceConfig> {\n\t\tconst { relative, rootDir } = options;\n\n\t\tconst relativePath = relative\n\t\t\t? path.relative(rootDir, filename).replaceAll(\"\\\\\", \"/\")\n\t\t\t: filename;\n\t\tconst json = await readJsonWithTemplate(\n\t\t\tfs,\n\t\t\tfilename,\n\t\t\t[\n\t\t\t\toptions.rootDir,\n\t\t\t\t...(options.fallbackDirs ?? []),\n\t\t\t],\n\t\t);\n\t\treturn new ConditionalDeviceConfig(relativePath, isEmbedded, json);\n\t}\n\n\tpublic constructor(\n\t\tfilename: string,\n\t\tisEmbedded: boolean,\n\t\tdefinition: JSONObject,\n\t) {\n\t\tthis.filename = filename;\n\t\tthis.isEmbedded = isEmbedded;\n\n\t\tif (!isHexKeyWith4Digits(definition.manufacturerId)) {\n\t\t\tthrowInvalidConfig(\n\t\t\t\t`device`,\n\t\t\t\t`packages/config/config/devices/${filename}:\nmanufacturer id must be a lowercase hexadecimal number with 4 digits`,\n\t\t\t);\n\t\t}\n\t\tthis.manufacturerId = parseInt(definition.manufacturerId, 16);\n\n\t\tfor (const prop of [\"manufacturer\", \"label\", \"description\"] as const) {\n\t\t\tthis[prop] = parseConditionalPrimitive(\n\t\t\t\tfilename,\n\t\t\t\t\"string\",\n\t\t\t\tprop,\n\t\t\t\tdefinition[prop],\n\t\t\t);\n\t\t}\n\n\t\tif (\n\t\t\t!isArray(definition.devices)\n\t\t\t|| !(definition.devices as any[]).every(\n\t\t\t\t(dev: unknown) =>\n\t\t\t\t\tisObject(dev)\n\t\t\t\t\t&& isHexKeyWith4Digits(dev.productType)\n\t\t\t\t\t&& isHexKeyWith4Digits(dev.productId),\n\t\t\t)\n\t\t) {\n\t\t\tthrowInvalidConfig(\n\t\t\t\t`device`,\n\t\t\t\t`packages/config/config/devices/${filename}:\ndevices is malformed (not an object or type/id that is not a lowercase 4-digit hex key)`,\n\t\t\t);\n\t\t}\n\t\tthis.devices = (definition.devices as any[]).map(\n\t\t\t({ productType, productId }) => ({\n\t\t\t\tproductType: parseInt(productType, 16),\n\t\t\t\tproductId: parseInt(productId, 16),\n\t\t\t}),\n\t\t);\n\n\t\tif (\n\t\t\t!isObject(definition.firmwareVersion)\n\t\t\t|| !isFirmwareVersion(definition.firmwareVersion.min)\n\t\t\t|| !isFirmwareVersion(definition.firmwareVersion.max)\n\t\t) {\n\t\t\tthrowInvalidConfig(\n\t\t\t\t`device`,\n\t\t\t\t`packages/config/config/devices/${filename}:\nfirmwareVersion is malformed or invalid. Must be x.y or x.y.z where x, y, and z are integers between 0 and 255`,\n\t\t\t);\n\t\t} else {\n\t\t\tconst { min, max } = definition.firmwareVersion;\n\t\t\tif (semverGt(padVersion(min), padVersion(max))) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t`device`,\n\t\t\t\t\t`packages/config/config/devices/${filename}:\nfirmwareVersion.min ${min} must not be greater than firmwareVersion.max ${max}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.firmwareVersion = { min, max };\n\t\t}\n\n\t\tif (\n\t\t\tdefinition.preferred != undefined\n\t\t\t&& definition.preferred !== true\n\t\t) {\n\t\t\tthrowInvalidConfig(\n\t\t\t\t`device`,\n\t\t\t\t`packages/config/config/devices/${filename}:\npreferred must be true or omitted`,\n\t\t\t);\n\t\t}\n\t\tthis.preferred = !!definition.preferred;\n\n\t\tif (definition.endpoints != undefined) {\n\t\t\tconst endpoints = new Map<number, ConditionalEndpointConfig>();\n\t\t\tif (!isObject(definition.endpoints)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t`device`,\n\t\t\t\t\t`packages/config/config/devices/${filename}:\nendpoints is not an object`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tfor (const [key, ep] of Object.entries(definition.endpoints)) {\n\t\t\t\tif (!/^\\d+$/.test(key)) {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t`device`,\n\t\t\t\t\t\t`packages/config/config/devices/${filename}:\nfound non-numeric endpoint index \"${key}\" in endpoints`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tconst epIndex = parseInt(key, 10);\n\t\t\t\tendpoints.set(\n\t\t\t\t\tepIndex,\n\t\t\t\t\tnew ConditionalEndpointConfig(this, epIndex, ep as any),\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.endpoints = endpoints;\n\t\t}\n\n\t\tif (definition.associations != undefined) {\n\t\t\tconst associations = new Map<\n\t\t\t\tnumber,\n\t\t\t\tConditionalAssociationConfig\n\t\t\t>();\n\t\t\tif (!isObject(definition.associations)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t`device`,\n\t\t\t\t\t`packages/config/config/devices/${filename}:\nassociations is not an object`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tfor (\n\t\t\t\tconst [key, assocDefinition] of Object.entries(\n\t\t\t\t\tdefinition.associations,\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tif (!/^[1-9][0-9]*$/.test(key)) {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t`device`,\n\t\t\t\t\t\t`packages/config/config/devices/${filename}:\nfound non-numeric group id \"${key}\" in associations`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tconst keyNum = parseInt(key, 10);\n\t\t\t\tassociations.set(\n\t\t\t\t\tkeyNum,\n\t\t\t\t\tnew ConditionalAssociationConfig(\n\t\t\t\t\t\tfilename,\n\t\t\t\t\t\tkeyNum,\n\t\t\t\t\t\tassocDefinition as any,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.associations = associations;\n\t\t}\n\n\t\tif (definition.paramInformation != undefined) {\n\t\t\tthis.paramInformation = parseConditionalParamInformationMap(\n\t\t\t\tdefinition,\n\t\t\t\tthis,\n\t\t\t);\n\t\t}\n\n\t\tif (definition.proprietary != undefined) {\n\t\t\tif (!isObject(definition.proprietary)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t`device`,\n\t\t\t\t\t`packages/config/config/devices/${filename}:\nproprietary is not an object`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.proprietary = definition.proprietary;\n\t\t}\n\n\t\tif (definition.compat != undefined) {\n\t\t\tif (\n\t\t\t\tisArray(definition.compat)\n\t\t\t\t&& definition.compat.every((item: any) => isObject(item))\n\t\t\t) {\n\t\t\t\t// Make sure all conditions are valid\n\t\t\t\tfor (const entry of definition.compat) {\n\t\t\t\t\tvalidateCondition(\n\t\t\t\t\t\tfilename,\n\t\t\t\t\t\tentry,\n\t\t\t\t\t\t`At least one entry of compat contains an`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tthis.compat = definition.compat.map(\n\t\t\t\t\t(item: any) => new ConditionalCompatConfig(filename, item),\n\t\t\t\t);\n\t\t\t} else if (isObject(definition.compat)) {\n\t\t\t\tthis.compat = new ConditionalCompatConfig(\n\t\t\t\t\tfilename,\n\t\t\t\t\tdefinition.compat,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t`device`,\n\t\t\t\t\t`packages/config/config/devices/${filename}:\ncompat must be an object or any array of conditional objects`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tif (definition.metadata != undefined) {\n\t\t\tif (!isObject(definition.metadata)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t`device`,\n\t\t\t\t\t`packages/config/config/devices/${filename}:\nmetadata is not an object`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.metadata = new ConditionalDeviceMetadata(\n\t\t\t\tfilename,\n\t\t\t\tdefinition.metadata,\n\t\t\t);\n\t\t}\n\t}\n\n\tpublic readonly filename: string;\n\n\tpublic readonly manufacturer!: ConditionalPrimitive<string>;\n\tpublic readonly manufacturerId: number;\n\tpublic readonly label!: ConditionalPrimitive<string>;\n\tpublic readonly description!: ConditionalPrimitive<string>;\n\tpublic readonly devices: readonly {\n\t\tproductType: number;\n\t\tproductId: number;\n\t}[];\n\tpublic readonly firmwareVersion: FirmwareVersionRange;\n\t/** Mark this configuration as preferred over other config files with an overlapping firmware range */\n\tpublic readonly preferred: boolean;\n\tpublic readonly endpoints?: ReadonlyMap<number, ConditionalEndpointConfig>;\n\tpublic readonly associations?: ReadonlyMap<\n\t\tnumber,\n\t\tConditionalAssociationConfig\n\t>;\n\tpublic readonly paramInformation?: ConditionalParamInfoMap;\n\t/**\n\t * Contains manufacturer-specific support information for the\n\t * ManufacturerProprietary CC\n\t */\n\tpublic readonly proprietary?: Record<string, unknown>;\n\t/** Contains compatibility options */\n\tpublic readonly compat?:\n\t\t| ConditionalCompatConfig\n\t\t| ConditionalCompatConfig[];\n\t/** Contains instructions and other metadata for the device */\n\tpublic readonly metadata?: ConditionalDeviceMetadata;\n\n\t/** Whether this is an embedded configuration or not */\n\tpublic readonly isEmbedded: boolean;\n\n\tpublic evaluate(deviceId?: DeviceID): DeviceConfig {\n\t\treturn new DeviceConfig(\n\t\t\tthis.filename,\n\t\t\tthis.isEmbedded,\n\t\t\tevaluateDeep(this.manufacturer, deviceId),\n\t\t\tthis.manufacturerId,\n\t\t\tevaluateDeep(this.label, deviceId),\n\t\t\tevaluateDeep(this.description, deviceId),\n\t\t\tthis.devices,\n\t\t\tthis.firmwareVersion,\n\t\t\tthis.preferred,\n\t\t\tevaluateDeep(this.endpoints, deviceId),\n\t\t\tevaluateDeep(this.associations, deviceId),\n\t\t\tevaluateDeep(this.paramInformation, deviceId),\n\t\t\tthis.proprietary,\n\t\t\tevaluateDeep(this.compat, deviceId),\n\t\t\tevaluateDeep(this.metadata, deviceId),\n\t\t);\n\t}\n}\n\nexport class DeviceConfig {\n\tpublic static async from(\n\t\tfs: ReadFileSystemInfo & ReadFile,\n\t\tfilename: string,\n\t\tisEmbedded: boolean,\n\t\toptions: {\n\t\t\trootDir: string;\n\t\t\tfallbackDirs?: string[];\n\t\t\trelative?: boolean;\n\t\t\tdeviceId?: DeviceID;\n\t\t},\n\t): Promise<DeviceConfig> {\n\t\tconst ret = await ConditionalDeviceConfig.from(\n\t\t\tfs,\n\t\t\tfilename,\n\t\t\tisEmbedded,\n\t\t\toptions,\n\t\t);\n\t\treturn ret.evaluate(options.deviceId);\n\t}\n\n\tpublic constructor(\n\t\tfilename: string,\n\t\tisEmbedded: boolean,\n\t\tmanufacturer: string,\n\t\tmanufacturerId: number,\n\t\tlabel: string,\n\t\tdescription: string,\n\t\tdevices: readonly {\n\t\t\tproductType: number;\n\t\t\tproductId: number;\n\t\t}[],\n\t\tfirmwareVersion: FirmwareVersionRange,\n\t\tpreferred: boolean,\n\t\tendpoints?: ReadonlyMap<number, EndpointConfig>,\n\t\tassociations?: ReadonlyMap<number, AssociationConfig>,\n\t\tparamInformation?: ParamInfoMap,\n\t\tproprietary?: Record<string, unknown>,\n\t\tcompat?: CompatConfig,\n\t\tmetadata?: DeviceMetadata,\n\t) {\n\t\tthis.filename = filename;\n\t\tthis.isEmbedded = isEmbedded;\n\t\tthis.manufacturer = manufacturer;\n\t\tthis.manufacturerId = manufacturerId;\n\t\tthis.label = label;\n\t\tthis.description = description;\n\t\tthis.devices = devices;\n\t\tthis.firmwareVersion = firmwareVersion;\n\t\tthis.preferred = preferred;\n\t\tthis.endpoints = endpoints;\n\t\tthis.associations = associations;\n\t\tthis.paramInformation = paramInformation;\n\t\tthis.proprietary = proprietary;\n\t\tthis.compat = compat;\n\t\tthis.metadata = metadata;\n\t}\n\n\tpublic readonly filename: string;\n\t/** Whether this is an embedded configuration or not */\n\tpublic readonly isEmbedded: boolean;\n\tpublic readonly manufacturer: string;\n\tpublic readonly manufacturerId: number;\n\tpublic readonly label: string;\n\tpublic readonly description: string;\n\tpublic readonly devices: readonly {\n\t\tproductType: number;\n\t\tproductId: number;\n\t}[];\n\tpublic readonly firmwareVersion: FirmwareVersionRange;\n\t/** Mark this configuration as preferred over other config files with an overlapping firmware range */\n\tpublic readonly preferred: boolean;\n\tpublic readonly endpoints?: ReadonlyMap<number, EndpointConfig>;\n\tpublic readonly associations?: ReadonlyMap<number, AssociationConfig>;\n\tpublic readonly paramInformation?: ParamInfoMap;\n\t/**\n\t * Contains manufacturer-specific support information for the\n\t * ManufacturerProprietary CC\n\t */\n\tpublic readonly proprietary?: Record<string, unknown>;\n\t/** Contains compatibility options */\n\tpublic readonly compat?: CompatConfig;\n\t/** Contains instructions and other metadata for the device */\n\tpublic readonly metadata?: DeviceMetadata;\n\n\t/** Returns the association config for a given endpoint */\n\tpublic getAssociationConfigForEndpoint(\n\t\tendpointIndex: number,\n\t\tgroup: number,\n\t): AssociationConfig | undefined {\n\t\tif (endpointIndex === 0) {\n\t\t\t// The root endpoint's associations may be configured separately or as part of \"endpoints\"\n\t\t\treturn (\n\t\t\t\tthis.associations?.get(group)\n\t\t\t\t\t?? this.endpoints?.get(0)?.associations?.get(group)\n\t\t\t);\n\t\t} else {\n\t\t\t// The other endpoints can only have a configuration as part of \"endpoints\"\n\t\t\treturn this.endpoints?.get(endpointIndex)?.associations?.get(group);\n\t\t}\n\t}\n\n\tprivate getHashable(): Uint8Array {\n\t\t// We only need to compare the information that is persisted elsewhere:\n\t\t// - config parameters\n\t\t// - functional association settings\n\t\t// - CC-related compat flags\n\n\t\tlet hashable: Record<string, any> = {\n\t\t\t// endpoints: {\n\t\t\t// \tassociations: {},\n\t\t\t// \tparamInformation: []\n\t\t\t// },\n\t\t\t// proprietary: {},\n\t\t\t// compat: {},\n\t\t};\n\n\t\tconst sortObject = (obj: Record<string, any>) => {\n\t\t\tconst ret: Record<string, any> = {};\n\t\t\tfor (const key of Object.keys(obj).sort()) {\n\t\t\t\tret[key] = obj[key];\n\t\t\t}\n\t\t\treturn ret;\n\t\t};\n\n\t\tconst cloneAssociationConfig = (a: AssociationConfig) => {\n\t\t\treturn sortObject(\n\t\t\t\tpick(a, [\"maxNodes\", \"multiChannel\", \"isLifeline\"]),\n\t\t\t);\n\t\t};\n\t\tconst cloneAssociationMap = (\n\t\t\ttarget: Record<string, any>,\n\t\t\tmap: ReadonlyMap<number, AssociationConfig> | undefined,\n\t\t) => {\n\t\t\tif (!map || !map.size) return;\n\t\t\ttarget.associations = {};\n\t\t\tfor (const [key, value] of map) {\n\t\t\t\ttarget.associations[key] = cloneAssociationConfig(value);\n\t\t\t}\n\t\t\ttarget.associations = sortObject(target.associations);\n\t\t};\n\n\t\tconst cloneParamInformationMap = (\n\t\t\ttarget: Record<string, any>,\n\t\t\tmap: ParamInfoMap | undefined,\n\t\t) => {\n\t\t\tif (!map || !map.size) return;\n\t\t\tconst getParamKey = (param: ParamInformation) =>\n\t\t\t\t`${param.parameterNumber}${\n\t\t\t\t\tparam.valueBitMask ? `[${num2hex(param.valueBitMask)}]` : \"\"\n\t\t\t\t}`;\n\t\t\ttarget.paramInformation = [...map.values()].sort((a, b) =>\n\t\t\t\tgetParamKey(a).localeCompare(getParamKey(b))\n\t\t\t);\n\t\t};\n\n\t\t// Clone associations and param information on the root (ep 0) and endpoints\n\t\t{\n\t\t\tlet ep0: Record<string, any> = {};\n\t\t\tcloneAssociationMap(ep0, this.associations);\n\t\t\tcloneParamInformationMap(ep0, this.paramInformation);\n\t\t\tep0 = sortObject(ep0);\n\n\t\t\tif (Object.keys(ep0).length > 0) {\n\t\t\t\thashable.endpoints ??= {};\n\t\t\t\thashable.endpoints[0] = ep0;\n\t\t\t}\n\t\t}\n\n\t\tif (this.endpoints) {\n\t\t\tfor (const [index, endpoint] of this.endpoints) {\n\t\t\t\tlet ep: Record<string, any> = {};\n\n\t\t\t\tcloneAssociationMap(ep, endpoint.associations);\n\t\t\t\tcloneParamInformationMap(ep, endpoint.paramInformation);\n\n\t\t\t\tep = sortObject(ep);\n\n\t\t\t\tif (Object.keys(ep).length > 0) {\n\t\t\t\t\thashable.endpoints ??= {};\n\t\t\t\t\thashable.endpoints[index] = ep;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Clone proprietary config\n\t\tif (this.proprietary && Object.keys(this.proprietary).length > 0) {\n\t\t\thashable.proprietary = sortObject({ ...this.proprietary });\n\t\t}\n\n\t\t// Clone relevant compat flags\n\t\tif (this.compat) {\n\t\t\tlet c: Record<string, any> = {};\n\n\t\t\t// Copy some simple flags over\n\t\t\tfor (\n\t\t\t\tconst prop of [\n\t\t\t\t\t\"forceSceneControllerGroupCount\",\n\t\t\t\t\t\"mapRootReportsToEndpoint\",\n\t\t\t\t\t\"mapBasicSet\",\n\t\t\t\t\t\"preserveRootApplicationCCValueIDs\",\n\t\t\t\t\t\"preserveEndpoints\",\n\t\t\t\t\t\"removeEndpoints\",\n\t\t\t\t\t\"treatMultilevelSwitchSetAsEvent\",\n\t\t\t\t] as const\n\t\t\t) {\n\t\t\t\tif (this.compat[prop] != undefined) {\n\t\t\t\t\tc[prop] = this.compat[prop];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Copy other, more complex flags\n\t\t\tif (this.compat.overrideQueries) {\n\t\t\t\tc.overrideQueries = Object.fromEntries(\n\t\t\t\t\tthis.compat.overrideQueries[\"overrides\"],\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (this.compat.addCCs) {\n\t\t\t\tc.addCCs = Object.fromEntries(\n\t\t\t\t\t[...this.compat.addCCs].map(([ccId, def]) => [\n\t\t\t\t\t\tccId,\n\t\t\t\t\t\tObject.fromEntries(def.endpoints),\n\t\t\t\t\t]),\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (this.compat.removeCCs) {\n\t\t\t\tc.removeCCs = Object.fromEntries(this.compat.removeCCs);\n\t\t\t}\n\t\t\tif (this.compat.treatSetAsReport) {\n\t\t\t\tc.treatSetAsReport = [...this.compat.treatSetAsReport].sort();\n\t\t\t}\n\n\t\t\tc = sortObject(c);\n\t\t\tif (Object.keys(c).length > 0) {\n\t\t\t\thashable.compat = c;\n\t\t\t}\n\t\t}\n\n\t\thashable = sortObject(hashable);\n\n\t\treturn Bytes.from(JSON.stringify(hashable), \"utf8\");\n\t}\n\n\t/**\n\t * Returns a hash code that can be used to check whether a device config has changed enough to require a re-interview.\n\t */\n\tpublic getHash(\n\t\talgorithm: \"md5\" | \"sha-256\" = \"sha-256\",\n\t): Promise<Uint8Array> {\n\t\t// Figure out what to hash\n\t\tconst buffer = this.getHashable();\n\n\t\t// And create a hash from it. This does not need to be cryptographically secure, just good enough to detect changes.\n\t\treturn digest(algorithm, buffer);\n\t}\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { configDir } from \"#config_dir\";\nimport {\n\tZWaveError,\n\tZWaveErrorCodes,\n\tdeflateSync,\n\tdigest,\n} from \"@zwave-js/core\";\nimport {\n\tBytes,\n\ttype JSONObject,\n\tcloneDeep,\n\tenumFilesRecursive,\n\tformatId,\n\tgetenv,\n\tnum2hex,\n\tpadVersion,\n\tpathExists,\n\tpick,\n\treadTextFile,\n\tstringify,\n\twriteTextFile,\n} from \"@zwave-js/shared\";\nimport type {\n\tReadFile,\n\tReadFileSystemInfo,\n\tWriteFile,\n} from \"@zwave-js/shared/bindings\";\nimport { isArray, isObject } from \"alcalzone-shared/typeguards\";\nimport JSON5 from \"json5\";\nimport path from \"pathe\";\nimport semverGt from \"semver/functions/gt.js\";\nimport { clearTemplateCache, readJsonWithTemplate } from \"../JsonTemplate.js\";\nimport type { ConfigLogger } from \"../Logger.js\";\nimport { hexKeyRegex4Digits, throwInvalidConfig } from \"../utils_safe.js\";\nimport {\n\ttype AssociationConfig,\n\tConditionalAssociationConfig,\n} from \"./AssociationConfig.js\";\nimport { type CompatConfig, ConditionalCompatConfig } from \"./CompatConfig.js\";\nimport { evaluateDeep, validateCondition } from \"./ConditionalItem.js\";\nimport {\n\ttype ConditionalPrimitive,\n\tparseConditionalPrimitive,\n} from \"./ConditionalPrimitive.js\";\nimport {\n\tConditionalDeviceMetadata,\n\ttype DeviceMetadata,\n} from \"./DeviceMetadata.js\";\nimport {\n\tConditionalEndpointConfig,\n\ttype EndpointConfig,\n} from \"./EndpointConfig.js\";\nimport {\n\ttype ConditionalParamInfoMap,\n\ttype ParamInfoMap,\n\ttype ParamInformation,\n\tparseConditionalParamInformationMap,\n} from \"./ParamInformation.js\";\nimport type { DeviceID, FirmwareVersionRange } from \"./shared.js\";\n\nexport interface DeviceConfigIndexEntry {\n\tmanufacturerId: string;\n\tproductType: string;\n\tproductId: string;\n\tfirmwareVersion: FirmwareVersionRange;\n\tpreferred?: true;\n\trootDir?: string;\n\tfilename: string;\n}\n\nexport interface FulltextDeviceConfigIndexEntry {\n\tmanufacturerId: string;\n\tmanufacturer: string;\n\tlabel: string;\n\tdescription: string;\n\tproductType: string;\n\tproductId: string;\n\tfirmwareVersion: FirmwareVersionRange;\n\tpreferred?: true;\n\trootDir?: string;\n\tfilename: string;\n}\n\nexport const embeddedDevicesDir = path.join(configDir, \"devices\");\nconst fulltextIndexPath = path.join(embeddedDevicesDir, \"fulltext_index.json\");\n\nexport function getDevicesPaths(configDir: string): {\n\tdevicesDir: string;\n\tindexPath: string;\n} {\n\tconst devicesDir = path.join(configDir, \"devices\");\n\tconst indexPath = path.join(devicesDir, \"index.json\");\n\treturn { devicesDir, indexPath };\n}\n\nexport type DeviceConfigIndex = DeviceConfigIndexEntry[];\nexport type FulltextDeviceConfigIndex = FulltextDeviceConfigIndexEntry[];\n\nasync function hasChangedDeviceFiles(\n\tfs: ReadFileSystemInfo,\n\tdevicesRoot: string,\n\tdir: string,\n\tlastChange: Date,\n): Promise<boolean> {\n\t// Check if there are any files BUT index.json that were changed\n\t// or directories that were modified\n\tconst filesAndDirs = await fs.readDir(dir);\n\tfor (const f of filesAndDirs) {\n\t\tconst fullPath = path.join(dir, f);\n\n\t\tconst stat = await fs.stat(fullPath);\n\t\tif (\n\t\t\t(dir !== devicesRoot || f !== \"index.json\")\n\t\t\t&& (stat.isFile() || stat.isDirectory())\n\t\t\t&& stat.mtime > lastChange\n\t\t) {\n\t\t\treturn true;\n\t\t} else if (stat.isDirectory()) {\n\t\t\t// we need to go deeper!\n\t\t\tif (\n\t\t\t\tawait hasChangedDeviceFiles(\n\t\t\t\t\tfs,\n\t\t\t\t\tdevicesRoot,\n\t\t\t\t\tfullPath,\n\t\t\t\t\tlastChange,\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\n/**\n * Read all device config files from a given directory and return them as index entries.\n * Does not update the index itself.\n */\nasync function generateIndex<T extends Record<string, unknown>>(\n\tfs: ReadFileSystemInfo & ReadFile,\n\tdevicesDir: string,\n\tisEmbedded: boolean,\n\textractIndexEntries: (config: DeviceConfig) => T[],\n\tlogger?: ConfigLogger,\n): Promise<(T & { filename: string; rootDir?: string })[]> {\n\tconst index: (T & { filename: string; rootDir?: string })[] = [];\n\n\tclearTemplateCache();\n\tconst configFiles = await enumFilesRecursive(\n\t\tfs,\n\t\tdevicesDir,\n\t\t(file) =>\n\t\t\tfile.endsWith(\".json\")\n\t\t\t&& !file.endsWith(\"index.json\")\n\t\t\t&& !file.includes(\"/templates/\")\n\t\t\t&& !file.includes(\"\\\\templates\\\\\"),\n\t);\n\n\t// Add the embedded devices dir as a fallback if necessary\n\tconst fallbackDirs = devicesDir !== embeddedDevicesDir\n\t\t? [embeddedDevicesDir]\n\t\t: undefined;\n\n\tfor (const file of configFiles) {\n\t\tconst relativePath = path\n\t\t\t.relative(devicesDir, file)\n\t\t\t.replaceAll(\"\\\\\", \"/\");\n\t\t// Try parsing the file\n\t\ttry {\n\t\t\tconst config = await DeviceConfig.from(\n\t\t\t\tfs,\n\t\t\t\tfile,\n\t\t\t\tisEmbedded,\n\t\t\t\t{\n\t\t\t\t\trootDir: devicesDir,\n\t\t\t\t\tfallbackDirs,\n\t\t\t\t\trelative: true,\n\t\t\t\t},\n\t\t\t);\n\t\t\t// Add the file to the index\n\t\t\tindex.push(\n\t\t\t\t...extractIndexEntries(config).map((entry) => {\n\t\t\t\t\tconst ret: T & { filename: string; rootDir?: string } = {\n\t\t\t\t\t\t...entry,\n\t\t\t\t\t\tfilename: relativePath,\n\t\t\t\t\t};\n\t\t\t\t\t// Only add the root dir to the index if necessary\n\t\t\t\t\tif (devicesDir !== embeddedDevicesDir) {\n\t\t\t\t\t\tret.rootDir = devicesDir;\n\t\t\t\t\t}\n\t\t\t\t\treturn ret;\n\t\t\t\t}),\n\t\t\t);\n\t\t} catch (e) {\n\t\t\tconst message = `Error parsing config file ${relativePath}: ${\n\t\t\t\t(e as Error).message\n\t\t\t}`;\n\t\t\t// Crash hard during tests, just print an error when in production systems.\n\t\t\t// A user could have changed a config file\n\t\t\tif (process.env.NODE_ENV === \"test\" || !!getenv(\"CI\")) {\n\t\t\t\tthrow new ZWaveError(message, ZWaveErrorCodes.Config_Invalid);\n\t\t\t} else {\n\t\t\t\tlogger?.print(message, \"error\");\n\t\t\t}\n\t\t}\n\t}\n\n\treturn index;\n}\n\nasync function loadDeviceIndexShared<T extends Record<string, unknown>>(\n\tfs: ReadFileSystemInfo & ReadFile & WriteFile,\n\tdevicesDir: string,\n\tindexPath: string,\n\textractIndexEntries: (config: DeviceConfig) => T[],\n\tlogger?: ConfigLogger,\n): Promise<(T & { filename: string })[]> {\n\t// The index file needs to be regenerated if it does not exist\n\tlet needsUpdate = !(await pathExists(fs, indexPath));\n\tlet index: (T & { filename: string })[] | undefined;\n\tlet mtimeIndex: Date | undefined;\n\t// ...or if cannot be parsed\n\tif (!needsUpdate) {\n\t\ttry {\n\t\t\tconst fileContents = await readTextFile(fs, indexPath, \"utf8\");\n\t\t\tindex = JSON5.parse(fileContents);\n\t\t\tmtimeIndex = (await fs.stat(indexPath)).mtime;\n\t\t} catch {\n\t\t\tlogger?.print(\n\t\t\t\t\"Error while parsing index file - regenerating...\",\n\t\t\t\t\"warn\",\n\t\t\t);\n\t\t\tneedsUpdate = true;\n\t\t} finally {\n\t\t\tif (!index) {\n\t\t\t\tlogger?.print(\n\t\t\t\t\t\"Index file was malformed - regenerating...\",\n\t\t\t\t\t\"warn\",\n\t\t\t\t);\n\t\t\t\tneedsUpdate = true;\n\t\t\t}\n\t\t}\n\t}\n\n\t// ...or if there were any changes in the file system\n\tif (!needsUpdate) {\n\t\tneedsUpdate = await hasChangedDeviceFiles(\n\t\t\tfs,\n\t\t\tdevicesDir,\n\t\t\tdevicesDir,\n\t\t\tmtimeIndex!,\n\t\t);\n\t\tif (needsUpdate) {\n\t\t\tlogger?.print(\n\t\t\t\t\"Device configuration files on disk changed - regenerating index...\",\n\t\t\t\t\"verbose\",\n\t\t\t);\n\t\t}\n\t}\n\n\tif (needsUpdate) {\n\t\t// Read all files from disk and generate an index\n\t\tindex = await generateIndex(\n\t\t\tfs,\n\t\t\tdevicesDir,\n\t\t\ttrue,\n\t\t\textractIndexEntries,\n\t\t\tlogger,\n\t\t);\n\t\t// Save the index to disk\n\t\ttry {\n\t\t\tawait writeTextFile(\n\t\t\t\tfs,\n\t\t\t\tpath.join(indexPath),\n\t\t\t\t`// This file is auto-generated. DO NOT edit it by hand if you don't know what you're doing!\"\n${stringify(index, \"\\t\")}\n`,\n\t\t\t\t\"utf8\",\n\t\t\t);\n\t\t\tlogger?.print(\"Device index regenerated\", \"verbose\");\n\t\t} catch (e) {\n\t\t\tlogger?.print(\n\t\t\t\t`Writing the device index to disk failed: ${\n\t\t\t\t\t(e as Error).message\n\t\t\t\t}`,\n\t\t\t\t\"error\",\n\t\t\t);\n\t\t}\n\t}\n\n\treturn index!;\n}\n\n/**\n * @internal\n * Loads the index file to quickly access the device configs.\n * Transparently handles updating the index if necessary\n */\nexport async function generatePriorityDeviceIndex(\n\tfs: ReadFileSystemInfo & ReadFile,\n\tdeviceConfigPriorityDir: string,\n\tlogger?: ConfigLogger,\n): Promise<DeviceConfigIndex> {\n\treturn (\n\t\tawait generateIndex(\n\t\t\tfs,\n\t\t\tdeviceConfigPriorityDir,\n\t\t\tfalse,\n\t\t\t(config) =>\n\t\t\t\tconfig.devices.map((dev) => ({\n\t\t\t\t\tmanufacturerId: formatId(\n\t\t\t\t\t\tconfig.manufacturerId.toString(16),\n\t\t\t\t\t),\n\t\t\t\t\tmanufacturer: config.manufacturer,\n\t\t\t\t\tlabel: config.label,\n\t\t\t\t\tproductType: formatId(dev.productType),\n\t\t\t\t\tproductId: formatId(dev.productId),\n\t\t\t\t\tfirmwareVersion: config.firmwareVersion,\n\t\t\t\t\t...(config.preferred ? { preferred: true as const } : {}),\n\t\t\t\t\trootDir: deviceConfigPriorityDir,\n\t\t\t\t})),\n\t\t\tlogger,\n\t\t)\n\t).map(({ filename, ...entry }) => ({\n\t\t...entry,\n\t\t// The generated index makes the filenames relative to the given directory\n\t\t// but we need them to be absolute\n\t\tfilename: path.join(deviceConfigPriorityDir, filename),\n\t}));\n}\n\n/**\n * @internal\n * Loads the index file to quickly access the device configs.\n * Transparently handles updating the index if necessary\n */\nexport async function loadDeviceIndexInternal(\n\tfs: ReadFileSystemInfo & ReadFile & WriteFile,\n\tlogger?: ConfigLogger,\n\texternalConfigDir?: string,\n): Promise<DeviceConfigIndex> {\n\tconst { devicesDir, indexPath } = getDevicesPaths(\n\t\texternalConfigDir || configDir,\n\t);\n\n\treturn loadDeviceIndexShared(\n\t\tfs,\n\t\tdevicesDir,\n\t\tindexPath,\n\t\t(config) =>\n\t\t\tconfig.devices.map((dev) => ({\n\t\t\t\tmanufacturerId: formatId(config.manufacturerId.toString(16)),\n\t\t\t\tmanufacturer: config.manufacturer,\n\t\t\t\tlabel: config.label,\n\t\t\t\tproductType: formatId(dev.productType),\n\t\t\t\tproductId: formatId(dev.productId),\n\t\t\t\tfirmwareVersion: config.firmwareVersion,\n\t\t\t\t...(config.preferred ? { preferred: true as const } : {}),\n\t\t\t})),\n\t\tlogger,\n\t);\n}\n\n/**\n * @internal\n * Loads the full text index file to quickly search the device configs.\n * Transparently handles updating the index if necessary\n */\nexport async function loadFulltextDeviceIndexInternal(\n\tfs: ReadFileSystemInfo & ReadFile & WriteFile,\n\tlogger?: ConfigLogger,\n): Promise<FulltextDeviceConfigIndex> {\n\t// This method is not meant to operate with the external device index!\n\treturn loadDeviceIndexShared(\n\t\tfs,\n\t\tembeddedDevicesDir,\n\t\tfulltextIndexPath,\n\t\t(config) =>\n\t\t\tconfig.devices.map((dev) => ({\n\t\t\t\tmanufacturerId: formatId(config.manufacturerId.toString(16)),\n\t\t\t\tmanufacturer: config.manufacturer,\n\t\t\t\tlabel: config.label,\n\t\t\t\tdescription: config.description,\n\t\t\t\tproductType: formatId(dev.productType),\n\t\t\t\tproductId: formatId(dev.productId),\n\t\t\t\tfirmwareVersion: config.firmwareVersion,\n\t\t\t\t...(config.preferred ? { preferred: true as const } : {}),\n\t\t\t\trootDir: embeddedDevicesDir,\n\t\t\t})),\n\t\tlogger,\n\t);\n}\n\nfunction isHexKeyWith4Digits(val: any): val is string {\n\treturn typeof val === \"string\" && hexKeyRegex4Digits.test(val);\n}\n\nconst firmwareVersionRegex = /^\\d{1,3}\\.\\d{1,3}(\\.\\d{1,3})?$/;\nfunction isFirmwareVersion(val: any): val is string {\n\treturn (\n\t\ttypeof val === \"string\"\n\t\t&& firmwareVersionRegex.test(val)\n\t\t&& val\n\t\t\t.split(\".\")\n\t\t\t.map((str) => parseInt(str, 10))\n\t\t\t.every((num) => num >= 0 && num <= 255)\n\t);\n}\n\nconst deflateDict = Bytes.from(\n\t// Substrings appearing in the device config files in descending order of frequency\n\t// except for very short ones like 0, 1, ...\n\t// WARNING: THIS MUST NOT BE CHANGED! Doing so breaks decompressing stored hashes.\n\t[\n\t\t`\"parameterNumber\":`,\n\t\t`255`,\n\t\t`\"value\":`,\n\t\t`\"defaultValue\":`,\n\t\t`\"valueSize\":`,\n\t\t`\"maxValue\":`,\n\t\t`\"minValue\":`,\n\t\t`\"options\":`,\n\t\t`true`,\n\t\t`false`,\n\t\t`\"allowManualEntry\":`,\n\t\t`\"maxNodes\":`,\n\t\t`100`,\n\t\t`\"unsigned\":`,\n\t\t`\"paramInformation\":`,\n\t\t`\"isLifeline\":`,\n\t\t`\"seconds\"`,\n\t\t`99`,\n\t\t`127`,\n\t\t`\"%\"`,\n\t\t`65535`,\n\t\t`32767`,\n\t\t`\"minutes\"`,\n\t\t`\"endpoints\":`,\n\t\t`\"hours\"`,\n\t\t`\"multiChannel\":`,\n\t]\n\t\t.join(\"\"),\n\t\"utf8\",\n);\n\n/** This class represents a device config entry whose conditional settings have not been evaluated yet */\nexport class ConditionalDeviceConfig {\n\tpublic static async from(\n\t\tfs: ReadFileSystemInfo & ReadFile,\n\t\tfilename: string,\n\t\tisEmbedded: boolean,\n\t\toptions: {\n\t\t\trootDir: string;\n\t\t\tfallbackDirs?: string[];\n\t\t\trelative?: boolean;\n\t\t},\n\t): Promise<ConditionalDeviceConfig> {\n\t\tconst { relative, rootDir } = options;\n\n\t\tconst relativePath = relative\n\t\t\t? path.relative(rootDir, filename).replaceAll(\"\\\\\", \"/\")\n\t\t\t: filename;\n\t\tconst json = await readJsonWithTemplate(\n\t\t\tfs,\n\t\t\tfilename,\n\t\t\t[\n\t\t\t\toptions.rootDir,\n\t\t\t\t...(options.fallbackDirs ?? []),\n\t\t\t],\n\t\t);\n\t\treturn new ConditionalDeviceConfig(relativePath, isEmbedded, json);\n\t}\n\n\tpublic constructor(\n\t\tfilename: string,\n\t\tisEmbedded: boolean,\n\t\tdefinition: JSONObject,\n\t) {\n\t\tthis.filename = filename;\n\t\tthis.isEmbedded = isEmbedded;\n\n\t\tif (!isHexKeyWith4Digits(definition.manufacturerId)) {\n\t\t\tthrowInvalidConfig(\n\t\t\t\t`device`,\n\t\t\t\t`packages/config/config/devices/${filename}:\nmanufacturer id must be a lowercase hexadecimal number with 4 digits`,\n\t\t\t);\n\t\t}\n\t\tthis.manufacturerId = parseInt(definition.manufacturerId, 16);\n\n\t\tfor (const prop of [\"manufacturer\", \"label\", \"description\"] as const) {\n\t\t\tthis[prop] = parseConditionalPrimitive(\n\t\t\t\tfilename,\n\t\t\t\t\"string\",\n\t\t\t\tprop,\n\t\t\t\tdefinition[prop],\n\t\t\t);\n\t\t}\n\n\t\tif (\n\t\t\t!isArray(definition.devices)\n\t\t\t|| !(definition.devices as any[]).every(\n\t\t\t\t(dev: unknown) =>\n\t\t\t\t\tisObject(dev)\n\t\t\t\t\t&& isHexKeyWith4Digits(dev.productType)\n\t\t\t\t\t&& isHexKeyWith4Digits(dev.productId),\n\t\t\t)\n\t\t) {\n\t\t\tthrowInvalidConfig(\n\t\t\t\t`device`,\n\t\t\t\t`packages/config/config/devices/${filename}:\ndevices is malformed (not an object or type/id that is not a lowercase 4-digit hex key)`,\n\t\t\t);\n\t\t}\n\t\tthis.devices = (definition.devices as any[]).map(\n\t\t\t({ productType, productId }) => ({\n\t\t\t\tproductType: parseInt(productType, 16),\n\t\t\t\tproductId: parseInt(productId, 16),\n\t\t\t}),\n\t\t);\n\n\t\tif (\n\t\t\t!isObject(definition.firmwareVersion)\n\t\t\t|| !isFirmwareVersion(definition.firmwareVersion.min)\n\t\t\t|| !isFirmwareVersion(definition.firmwareVersion.max)\n\t\t) {\n\t\t\tthrowInvalidConfig(\n\t\t\t\t`device`,\n\t\t\t\t`packages/config/config/devices/${filename}:\nfirmwareVersion is malformed or invalid. Must be x.y or x.y.z where x, y, and z are integers between 0 and 255`,\n\t\t\t);\n\t\t} else {\n\t\t\tconst { min, max } = definition.firmwareVersion;\n\t\t\tif (semverGt(padVersion(min), padVersion(max))) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t`device`,\n\t\t\t\t\t`packages/config/config/devices/${filename}:\nfirmwareVersion.min ${min} must not be greater than firmwareVersion.max ${max}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.firmwareVersion = { min, max };\n\t\t}\n\n\t\tif (\n\t\t\tdefinition.preferred != undefined\n\t\t\t&& definition.preferred !== true\n\t\t) {\n\t\t\tthrowInvalidConfig(\n\t\t\t\t`device`,\n\t\t\t\t`packages/config/config/devices/${filename}:\npreferred must be true or omitted`,\n\t\t\t);\n\t\t}\n\t\tthis.preferred = !!definition.preferred;\n\n\t\tif (definition.endpoints != undefined) {\n\t\t\tconst endpoints = new Map<number, ConditionalEndpointConfig>();\n\t\t\tif (!isObject(definition.endpoints)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t`device`,\n\t\t\t\t\t`packages/config/config/devices/${filename}:\nendpoints is not an object`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tfor (const [key, ep] of Object.entries(definition.endpoints)) {\n\t\t\t\tif (!/^\\d+$/.test(key)) {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t`device`,\n\t\t\t\t\t\t`packages/config/config/devices/${filename}:\nfound non-numeric endpoint index \"${key}\" in endpoints`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tconst epIndex = parseInt(key, 10);\n\t\t\t\tendpoints.set(\n\t\t\t\t\tepIndex,\n\t\t\t\t\tnew ConditionalEndpointConfig(this, epIndex, ep as any),\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.endpoints = endpoints;\n\t\t}\n\n\t\tif (definition.associations != undefined) {\n\t\t\tconst associations = new Map<\n\t\t\t\tnumber,\n\t\t\t\tConditionalAssociationConfig\n\t\t\t>();\n\t\t\tif (!isObject(definition.associations)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t`device`,\n\t\t\t\t\t`packages/config/config/devices/${filename}:\nassociations is not an object`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tfor (\n\t\t\t\tconst [key, assocDefinition] of Object.entries(\n\t\t\t\t\tdefinition.associations,\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tif (!/^[1-9][0-9]*$/.test(key)) {\n\t\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t\t`device`,\n\t\t\t\t\t\t`packages/config/config/devices/${filename}:\nfound non-numeric group id \"${key}\" in associations`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tconst keyNum = parseInt(key, 10);\n\t\t\t\tassociations.set(\n\t\t\t\t\tkeyNum,\n\t\t\t\t\tnew ConditionalAssociationConfig(\n\t\t\t\t\t\tfilename,\n\t\t\t\t\t\tkeyNum,\n\t\t\t\t\t\tassocDefinition as any,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.associations = associations;\n\t\t}\n\n\t\tif (definition.paramInformation != undefined) {\n\t\t\tthis.paramInformation = parseConditionalParamInformationMap(\n\t\t\t\tdefinition,\n\t\t\t\tthis,\n\t\t\t);\n\t\t}\n\n\t\tif (definition.proprietary != undefined) {\n\t\t\tif (!isObject(definition.proprietary)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t`device`,\n\t\t\t\t\t`packages/config/config/devices/${filename}:\nproprietary is not an object`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.proprietary = definition.proprietary;\n\t\t}\n\n\t\tif (definition.compat != undefined) {\n\t\t\tif (\n\t\t\t\tisArray(definition.compat)\n\t\t\t\t&& definition.compat.every((item: any) => isObject(item))\n\t\t\t) {\n\t\t\t\t// Make sure all conditions are valid\n\t\t\t\tfor (const entry of definition.compat) {\n\t\t\t\t\tvalidateCondition(\n\t\t\t\t\t\tfilename,\n\t\t\t\t\t\tentry,\n\t\t\t\t\t\t`At least one entry of compat contains an`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tthis.compat = definition.compat.map(\n\t\t\t\t\t(item: any) => new ConditionalCompatConfig(filename, item),\n\t\t\t\t);\n\t\t\t} else if (isObject(definition.compat)) {\n\t\t\t\tthis.compat = new ConditionalCompatConfig(\n\t\t\t\t\tfilename,\n\t\t\t\t\tdefinition.compat,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t`device`,\n\t\t\t\t\t`packages/config/config/devices/${filename}:\ncompat must be an object or any array of conditional objects`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tif (definition.metadata != undefined) {\n\t\t\tif (!isObject(definition.metadata)) {\n\t\t\t\tthrowInvalidConfig(\n\t\t\t\t\t`device`,\n\t\t\t\t\t`packages/config/config/devices/${filename}:\nmetadata is not an object`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.metadata = new ConditionalDeviceMetadata(\n\t\t\t\tfilename,\n\t\t\t\tdefinition.metadata,\n\t\t\t);\n\t\t}\n\t}\n\n\tpublic readonly filename: string;\n\n\tpublic readonly manufacturer!: ConditionalPrimitive<string>;\n\tpublic readonly manufacturerId: number;\n\tpublic readonly label!: ConditionalPrimitive<string>;\n\tpublic readonly description!: ConditionalPrimitive<string>;\n\tpublic readonly devices: readonly {\n\t\tproductType: number;\n\t\tproductId: number;\n\t}[];\n\tpublic readonly firmwareVersion: FirmwareVersionRange;\n\t/** Mark this configuration as preferred over other config files with an overlapping firmware range */\n\tpublic readonly preferred: boolean;\n\tpublic readonly endpoints?: ReadonlyMap<number, ConditionalEndpointConfig>;\n\tpublic readonly associations?: ReadonlyMap<\n\t\tnumber,\n\t\tConditionalAssociationConfig\n\t>;\n\tpublic readonly paramInformation?: ConditionalParamInfoMap;\n\t/**\n\t * Contains manufacturer-specific support information for the\n\t * ManufacturerProprietary CC\n\t */\n\tpublic readonly proprietary?: Record<string, unknown>;\n\t/** Contains compatibility options */\n\tpublic readonly compat?:\n\t\t| ConditionalCompatConfig\n\t\t| ConditionalCompatConfig[];\n\t/** Contains instructions and other metadata for the device */\n\tpublic readonly metadata?: ConditionalDeviceMetadata;\n\n\t/** Whether this is an embedded configuration or not */\n\tpublic readonly isEmbedded: boolean;\n\n\tpublic evaluate(deviceId?: DeviceID): DeviceConfig {\n\t\treturn new DeviceConfig(\n\t\t\tthis.filename,\n\t\t\tthis.isEmbedded,\n\t\t\tevaluateDeep(this.manufacturer, deviceId),\n\t\t\tthis.manufacturerId,\n\t\t\tevaluateDeep(this.label, deviceId),\n\t\t\tevaluateDeep(this.description, deviceId),\n\t\t\tthis.devices,\n\t\t\tthis.firmwareVersion,\n\t\t\tthis.preferred,\n\t\t\tevaluateDeep(this.endpoints, deviceId),\n\t\t\tevaluateDeep(this.associations, deviceId),\n\t\t\tevaluateDeep(this.paramInformation, deviceId),\n\t\t\tthis.proprietary,\n\t\t\tevaluateDeep(this.compat, deviceId),\n\t\t\tevaluateDeep(this.metadata, deviceId),\n\t\t);\n\t}\n}\n\nexport class DeviceConfig {\n\tpublic static async from(\n\t\tfs: ReadFileSystemInfo & ReadFile,\n\t\tfilename: string,\n\t\tisEmbedded: boolean,\n\t\toptions: {\n\t\t\trootDir: string;\n\t\t\tfallbackDirs?: string[];\n\t\t\trelative?: boolean;\n\t\t\tdeviceId?: DeviceID;\n\t\t},\n\t): Promise<DeviceConfig> {\n\t\tconst ret = await ConditionalDeviceConfig.from(\n\t\t\tfs,\n\t\t\tfilename,\n\t\t\tisEmbedded,\n\t\t\toptions,\n\t\t);\n\t\treturn ret.evaluate(options.deviceId);\n\t}\n\n\tpublic constructor(\n\t\tfilename: string,\n\t\tisEmbedded: boolean,\n\t\tmanufacturer: string,\n\t\tmanufacturerId: number,\n\t\tlabel: string,\n\t\tdescription: string,\n\t\tdevices: readonly {\n\t\t\tproductType: number;\n\t\t\tproductId: number;\n\t\t}[],\n\t\tfirmwareVersion: FirmwareVersionRange,\n\t\tpreferred: boolean,\n\t\tendpoints?: ReadonlyMap<number, EndpointConfig>,\n\t\tassociations?: ReadonlyMap<number, AssociationConfig>,\n\t\tparamInformation?: ParamInfoMap,\n\t\tproprietary?: Record<string, unknown>,\n\t\tcompat?: CompatConfig,\n\t\tmetadata?: DeviceMetadata,\n\t) {\n\t\tthis.filename = filename;\n\t\tthis.isEmbedded = isEmbedded;\n\t\tthis.manufacturer = manufacturer;\n\t\tthis.manufacturerId = manufacturerId;\n\t\tthis.label = label;\n\t\tthis.description = description;\n\t\tthis.devices = devices;\n\t\tthis.firmwareVersion = firmwareVersion;\n\t\tthis.preferred = preferred;\n\t\tthis.endpoints = endpoints;\n\t\tthis.associations = associations;\n\t\tthis.paramInformation = paramInformation;\n\t\tthis.proprietary = proprietary;\n\t\tthis.compat = compat;\n\t\tthis.metadata = metadata;\n\t}\n\n\tpublic readonly filename: string;\n\t/** Whether this is an embedded configuration or not */\n\tpublic readonly isEmbedded: boolean;\n\tpublic readonly manufacturer: string;\n\tpublic readonly manufacturerId: number;\n\tpublic readonly label: string;\n\tpublic readonly description: string;\n\tpublic readonly devices: readonly {\n\t\tproductType: number;\n\t\tproductId: number;\n\t}[];\n\tpublic readonly firmwareVersion: FirmwareVersionRange;\n\t/** Mark this configuration as preferred over other config files with an overlapping firmware range */\n\tpublic readonly preferred: boolean;\n\tpublic readonly endpoints?: ReadonlyMap<number, EndpointConfig>;\n\tpublic readonly associations?: ReadonlyMap<number, AssociationConfig>;\n\tpublic readonly paramInformation?: ParamInfoMap;\n\t/**\n\t * Contains manufacturer-specific support information for the\n\t * ManufacturerProprietary CC\n\t */\n\tpublic readonly proprietary?: Record<string, unknown>;\n\t/** Contains compatibility options */\n\tpublic readonly compat?: CompatConfig;\n\t/** Contains instructions and other metadata for the device */\n\tpublic readonly metadata?: DeviceMetadata;\n\n\t/** Returns the association config for a given endpoint */\n\tpublic getAssociationConfigForEndpoint(\n\t\tendpointIndex: number,\n\t\tgroup: number,\n\t): AssociationConfig | undefined {\n\t\tif (endpointIndex === 0) {\n\t\t\t// The root endpoint's associations may be configured separately or as part of \"endpoints\"\n\t\t\treturn (\n\t\t\t\tthis.associations?.get(group)\n\t\t\t\t\t?? this.endpoints?.get(0)?.associations?.get(group)\n\t\t\t);\n\t\t} else {\n\t\t\t// The other endpoints can only have a configuration as part of \"endpoints\"\n\t\t\treturn this.endpoints?.get(endpointIndex)?.associations?.get(group);\n\t\t}\n\t}\n\n\tprivate getHashable(version: 0 | 1 | 2): Record<string, any> {\n\t\t// We only need to compare the information that is persisted elsewhere:\n\t\t// - config parameters\n\t\t// - functional association settings\n\t\t// - CC-related compat flags\n\n\t\tlet hashable: Record<string, any> = {\n\t\t\t// endpoints: {\n\t\t\t// \tassociations: {},\n\t\t\t// \tparamInformation: []\n\t\t\t// },\n\t\t\t// proprietary: {},\n\t\t\t// compat: {},\n\t\t};\n\n\t\tconst sortObject = (obj: Record<string, any>) => {\n\t\t\tconst ret: Record<string, any> = {};\n\t\t\tfor (const key of Object.keys(obj).sort()) {\n\t\t\t\tret[key] = obj[key];\n\t\t\t}\n\t\t\treturn ret;\n\t\t};\n\n\t\tconst cloneAssociationConfig = (a: AssociationConfig) => {\n\t\t\treturn sortObject(\n\t\t\t\tpick(a, [\"maxNodes\", \"multiChannel\", \"isLifeline\"]),\n\t\t\t);\n\t\t};\n\t\tconst cloneAssociationMap = (\n\t\t\ttarget: Record<string, any>,\n\t\t\tmap: ReadonlyMap<number, AssociationConfig> | undefined,\n\t\t) => {\n\t\t\tif (!map || !map.size) return;\n\t\t\ttarget.associations = {};\n\t\t\tfor (const [key, value] of map) {\n\t\t\t\ttarget.associations[key] = cloneAssociationConfig(value);\n\t\t\t}\n\t\t\ttarget.associations = sortObject(target.associations);\n\t\t};\n\n\t\tconst cloneParamInformationMap = (\n\t\t\ttarget: Record<string, any>,\n\t\t\tmap: ParamInfoMap | undefined,\n\t\t) => {\n\t\t\tif (!map || !map.size) return;\n\t\t\tconst getParamKey = (param: ParamInformation) =>\n\t\t\t\t`${param.parameterNumber}${\n\t\t\t\t\tparam.valueBitMask ? `[${num2hex(param.valueBitMask)}]` : \"\"\n\t\t\t\t}`;\n\t\t\ttarget.paramInformation = [...map.values()]\n\t\t\t\t.sort((a, b) => getParamKey(a).localeCompare(getParamKey(b)))\n\t\t\t\t.map((p) => cloneDeep(p));\n\t\t};\n\n\t\t// Clone associations and param information on the root (ep 0) and endpoints\n\t\t{\n\t\t\tlet ep0: Record<string, any> = {};\n\t\t\tcloneAssociationMap(ep0, this.associations);\n\t\t\tcloneParamInformationMap(ep0, this.paramInformation);\n\t\t\tep0 = sortObject(ep0);\n\n\t\t\tif (Object.keys(ep0).length > 0) {\n\t\t\t\thashable.endpoints ??= {};\n\t\t\t\thashable.endpoints[0] = ep0;\n\t\t\t}\n\t\t}\n\n\t\tif (this.endpoints) {\n\t\t\tfor (const [index, endpoint] of this.endpoints) {\n\t\t\t\tlet ep: Record<string, any> = {};\n\n\t\t\t\tcloneAssociationMap(ep, endpoint.associations);\n\t\t\t\tcloneParamInformationMap(ep, endpoint.paramInformation);\n\n\t\t\t\tep = sortObject(ep);\n\n\t\t\t\tif (Object.keys(ep).length > 0) {\n\t\t\t\t\thashable.endpoints ??= {};\n\t\t\t\t\thashable.endpoints[index] = ep;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Clone proprietary config\n\t\tif (this.proprietary && Object.keys(this.proprietary).length > 0) {\n\t\t\thashable.proprietary = sortObject({ ...this.proprietary });\n\t\t}\n\n\t\t// Clone relevant compat flags\n\t\tif (this.compat) {\n\t\t\tlet c: Record<string, any> = {};\n\n\t\t\t// Copy some simple flags over\n\t\t\tfor (\n\t\t\t\tconst prop of [\n\t\t\t\t\t\"forceSceneControllerGroupCount\",\n\t\t\t\t\t\"mapRootReportsToEndpoint\",\n\t\t\t\t\t\"mapBasicSet\",\n\t\t\t\t\t\"preserveRootApplicationCCValueIDs\",\n\t\t\t\t\t\"preserveEndpoints\",\n\t\t\t\t\t\"removeEndpoints\",\n\t\t\t\t\t\"treatMultilevelSwitchSetAsEvent\",\n\t\t\t\t] as const\n\t\t\t) {\n\t\t\t\tif (this.compat[prop] != undefined) {\n\t\t\t\t\tc[prop] = this.compat[prop];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Copy other, more complex flags\n\t\t\tif (this.compat.overrideQueries) {\n\t\t\t\tc.overrideQueries = Object.fromEntries(\n\t\t\t\t\tthis.compat.overrideQueries[\"overrides\"],\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (this.compat.addCCs) {\n\t\t\t\tc.addCCs = Object.fromEntries(\n\t\t\t\t\t[...this.compat.addCCs].map(([ccId, def]) => [\n\t\t\t\t\t\tccId,\n\t\t\t\t\t\tObject.fromEntries(def.endpoints),\n\t\t\t\t\t]),\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (this.compat.removeCCs) {\n\t\t\t\tc.removeCCs = Object.fromEntries(this.compat.removeCCs);\n\t\t\t}\n\t\t\tif (this.compat.treatSetAsReport) {\n\t\t\t\tc.treatSetAsReport = [...this.compat.treatSetAsReport].sort();\n\t\t\t}\n\n\t\t\tc = sortObject(c);\n\t\t\tif (Object.keys(c).length > 0) {\n\t\t\t\thashable.compat = c;\n\t\t\t}\n\t\t}\n\n\t\tif (version > 1) {\n\t\t\t// From version 2 and on, we ignore labels and descriptions, and load them dynamically\n\t\t\tfor (\n\t\t\t\tconst ep of Object.values<Record<string, any>>(\n\t\t\t\t\thashable.endpoints ?? {},\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tfor (const param of ep.paramInformation ?? []) {\n\t\t\t\t\tdelete param.label;\n\t\t\t\t\tdelete param.description;\n\t\t\t\t\tfor (const opt of param.options ?? []) {\n\t\t\t\t\t\tdelete opt.label;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\thashable = sortObject(hashable);\n\t\treturn hashable;\n\t}\n\n\t/**\n\t * Returns a hash code that can be used to check whether a device config has changed enough to require a re-interview.\n\t */\n\tpublic async getHash(\n\t\tversion: 0 | 1 | 2 = DeviceConfig.maxHashVersion,\n\t): Promise<Uint8Array> {\n\t\t// Figure out what to hash\n\t\tconst hashable = this.getHashable(version);\n\n\t\t// And create a \"hash\" from it. Older versions used a non-cryptographic hash,\n\t\t// newer versions compress a subset of the config file.\n\t\tlet hash: Uint8Array;\n\t\tif (version === 0) {\n\t\t\tconst buffer = Bytes.from(JSON.stringify(hashable), \"utf8\");\n\t\t\treturn await digest(\"md5\", buffer);\n\t\t} else if (version === 1) {\n\t\t\tconst buffer = Bytes.from(JSON.stringify(hashable), \"utf8\");\n\t\t\treturn await digest(\"sha-256\", buffer);\n\t\t} else {\n\t\t\thash = deflateSync(\n\t\t\t\tBytes.from(JSON.stringify(hashable), \"utf8\"),\n\t\t\t\t// Try to make the hash as small as possible\n\t\t\t\t{ level: 9, dictionary: deflateDict },\n\t\t\t);\n\t\t}\n\n\t\t// Version the hash from v2 onwards, so we can change the format in the future\n\t\tconst prefixBytes = Bytes.from(`$v${version}$`, \"utf8\");\n\t\treturn Bytes.concat([prefixBytes, hash]);\n\t}\n\n\tpublic static get maxHashVersion(): 2 {\n\t\treturn 2;\n\t}\n\n\tpublic static areHashesEqual(hash: Uint8Array, other: Uint8Array): boolean {\n\t\tconst parsedHash = parseHash(hash);\n\t\tconst parsedOther = parseHash(other);\n\t\t// If one of the hashes could not be parsed, they are not equal\n\t\tif (!parsedHash || !parsedOther) return false;\n\n\t\t// For legacy hashes, we only compare the hash data. We already make sure during\n\t\t// parsing of the cache files that we only need to compare hashes of the same version,\n\t\t// so simply comparing the contents is sufficient.\n\t\tif (parsedHash.version < 2 && parsedOther.version < 2) {\n\t\t\treturn Bytes.view(parsedHash.hashData).equals(parsedOther.hashData);\n\t\t}\n\t\t// We take care during loading to downlevel the current config hash to legacy versions if needed.\n\t\t// If we end up with just one legacy hash here, something went wrong. Just bail in that case.\n\t\tif (parsedHash.version < 2 || parsedOther.version < 2) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// This is a versioned hash. If both versions are equal, it's simple - just compare the hash data\n\t\tif (parsedHash.version === parsedOther.version) {\n\t\t\treturn Bytes.view(parsedHash.hashData).equals(parsedOther.hashData);\n\t\t}\n\n\t\t// For different versions, we have to do some case by case checks. For example, a newer hash version\n\t\t// might remove or add data into the hashable, so we cannot simply convert between versions easily.\n\t\t// Implement when that is actually needed.\n\t\treturn false;\n\t}\n}\n\nfunction parseHash(hash: Uint8Array): {\n\tversion: number;\n\thashData: Uint8Array;\n} | undefined {\n\tconst hashString = Bytes.view(hash).toString(\"utf8\");\n\tconst versionMatch = hashString.match(/^\\$v(\\d+)\\$/);\n\tif (versionMatch) {\n\t\t// This is a versioned hash\n\t\tconst version = parseInt(versionMatch[1], 10);\n\t\tconst hashData = hash.subarray(\n\t\t\t// The prefix is ASCII, so this is safe to do even in the context of UTF-8\n\t\t\tversionMatch[0].length,\n\t\t);\n\t\treturn {\n\t\t\tversion,\n\t\t\thashData,\n\t\t};\n\t}\n\n\t// This is probably an unversioned legacy hash\n\tswitch (hash.length) {\n\t\tcase 16: // MD5\n\t\t\treturn {\n\t\t\t\tversion: 0,\n\t\t\t\thashData: hash,\n\t\t\t};\n\t\tcase 32: // SHA-256\n\t\t\treturn {\n\t\t\t\tversion: 1,\n\t\t\t\thashData: hash,\n\t\t\t};\n\t\tdefault:\n\t\t\t// This is not a valid hash\n\t\t\treturn undefined;\n\t}\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["path", "configDir", "JSON5", "semverGt"]
7
7
  }
@@ -1,2 +1,2 @@
1
- export declare const PACKAGE_VERSION = "15.7.0";
1
+ export declare const PACKAGE_VERSION = "15.9.0";
2
2
  //# sourceMappingURL=_version.d.ts.map
@@ -1,3 +1,3 @@
1
1
  // This file is auto-generated by the codegen maintenance script
2
- export const PACKAGE_VERSION = "15.7.0";
2
+ export const PACKAGE_VERSION = "15.9.0";
3
3
  //# sourceMappingURL=_version.js.map
@@ -114,6 +114,8 @@ export declare class DeviceConfig {
114
114
  /**
115
115
  * Returns a hash code that can be used to check whether a device config has changed enough to require a re-interview.
116
116
  */
117
- getHash(algorithm?: "md5" | "sha-256"): Promise<Uint8Array>;
117
+ getHash(version?: 0 | 1 | 2): Promise<Uint8Array>;
118
+ static get maxHashVersion(): 2;
119
+ static areHashesEqual(hash: Uint8Array, other: Uint8Array): boolean;
118
120
  }
119
121
  //# sourceMappingURL=DeviceConfig.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DeviceConfig.d.ts","sourceRoot":"","sources":["../../../src/devices/DeviceConfig.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"DeviceConfig.d.ts","sourceRoot":"","sources":["../../../src/devices/DeviceConfig.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { configDir } from "#config_dir";
2
- import { ZWaveError, ZWaveErrorCodes, digest } from "@zwave-js/core";
3
- import { Bytes, enumFilesRecursive, formatId, getenv, num2hex, padVersion, pathExists, pick, readTextFile, stringify, writeTextFile, } from "@zwave-js/shared";
2
+ import { ZWaveError, ZWaveErrorCodes, deflateSync, digest, } from "@zwave-js/core";
3
+ import { Bytes, cloneDeep, enumFilesRecursive, formatId, getenv, num2hex, padVersion, pathExists, pick, readTextFile, stringify, writeTextFile, } from "@zwave-js/shared";
4
4
  import { isArray, isObject } from "alcalzone-shared/typeguards";
5
5
  import JSON5 from "json5";
6
6
  import path from "pathe";
@@ -211,6 +211,39 @@ function isFirmwareVersion(val) {
211
211
  .map((str) => parseInt(str, 10))
212
212
  .every((num) => num >= 0 && num <= 255));
213
213
  }
214
+ const deflateDict = Bytes.from(
215
+ // Substrings appearing in the device config files in descending order of frequency
216
+ // except for very short ones like 0, 1, ...
217
+ // WARNING: THIS MUST NOT BE CHANGED! Doing so breaks decompressing stored hashes.
218
+ [
219
+ `"parameterNumber":`,
220
+ `255`,
221
+ `"value":`,
222
+ `"defaultValue":`,
223
+ `"valueSize":`,
224
+ `"maxValue":`,
225
+ `"minValue":`,
226
+ `"options":`,
227
+ `true`,
228
+ `false`,
229
+ `"allowManualEntry":`,
230
+ `"maxNodes":`,
231
+ `100`,
232
+ `"unsigned":`,
233
+ `"paramInformation":`,
234
+ `"isLifeline":`,
235
+ `"seconds"`,
236
+ `99`,
237
+ `127`,
238
+ `"%"`,
239
+ `65535`,
240
+ `32767`,
241
+ `"minutes"`,
242
+ `"endpoints":`,
243
+ `"hours"`,
244
+ `"multiChannel":`,
245
+ ]
246
+ .join(""), "utf8");
214
247
  /** This class represents a device config entry whose conditional settings have not been evaluated yet */
215
248
  export class ConditionalDeviceConfig {
216
249
  static async from(fs, filename, isEmbedded, options) {
@@ -417,7 +450,7 @@ export class DeviceConfig {
417
450
  return this.endpoints?.get(endpointIndex)?.associations?.get(group);
418
451
  }
419
452
  }
420
- getHashable() {
453
+ getHashable(version) {
421
454
  // We only need to compare the information that is persisted elsewhere:
422
455
  // - config parameters
423
456
  // - functional association settings
@@ -453,7 +486,9 @@ export class DeviceConfig {
453
486
  if (!map || !map.size)
454
487
  return;
455
488
  const getParamKey = (param) => `${param.parameterNumber}${param.valueBitMask ? `[${num2hex(param.valueBitMask)}]` : ""}`;
456
- target.paramInformation = [...map.values()].sort((a, b) => getParamKey(a).localeCompare(getParamKey(b)));
489
+ target.paramInformation = [...map.values()]
490
+ .sort((a, b) => getParamKey(a).localeCompare(getParamKey(b)))
491
+ .map((p) => cloneDeep(p));
457
492
  };
458
493
  // Clone associations and param information on the root (ep 0) and endpoints
459
494
  {
@@ -520,17 +555,106 @@ export class DeviceConfig {
520
555
  hashable.compat = c;
521
556
  }
522
557
  }
558
+ if (version > 1) {
559
+ // From version 2 and on, we ignore labels and descriptions, and load them dynamically
560
+ for (const ep of Object.values(hashable.endpoints ?? {})) {
561
+ for (const param of ep.paramInformation ?? []) {
562
+ delete param.label;
563
+ delete param.description;
564
+ for (const opt of param.options ?? []) {
565
+ delete opt.label;
566
+ }
567
+ }
568
+ }
569
+ }
523
570
  hashable = sortObject(hashable);
524
- return Bytes.from(JSON.stringify(hashable), "utf8");
571
+ return hashable;
525
572
  }
526
573
  /**
527
574
  * Returns a hash code that can be used to check whether a device config has changed enough to require a re-interview.
528
575
  */
529
- getHash(algorithm = "sha-256") {
576
+ async getHash(version = DeviceConfig.maxHashVersion) {
530
577
  // Figure out what to hash
531
- const buffer = this.getHashable();
532
- // And create a hash from it. This does not need to be cryptographically secure, just good enough to detect changes.
533
- return digest(algorithm, buffer);
578
+ const hashable = this.getHashable(version);
579
+ // And create a "hash" from it. Older versions used a non-cryptographic hash,
580
+ // newer versions compress a subset of the config file.
581
+ let hash;
582
+ if (version === 0) {
583
+ const buffer = Bytes.from(JSON.stringify(hashable), "utf8");
584
+ return await digest("md5", buffer);
585
+ }
586
+ else if (version === 1) {
587
+ const buffer = Bytes.from(JSON.stringify(hashable), "utf8");
588
+ return await digest("sha-256", buffer);
589
+ }
590
+ else {
591
+ hash = deflateSync(Bytes.from(JSON.stringify(hashable), "utf8"),
592
+ // Try to make the hash as small as possible
593
+ { level: 9, dictionary: deflateDict });
594
+ }
595
+ // Version the hash from v2 onwards, so we can change the format in the future
596
+ const prefixBytes = Bytes.from(`$v${version}$`, "utf8");
597
+ return Bytes.concat([prefixBytes, hash]);
598
+ }
599
+ static get maxHashVersion() {
600
+ return 2;
601
+ }
602
+ static areHashesEqual(hash, other) {
603
+ const parsedHash = parseHash(hash);
604
+ const parsedOther = parseHash(other);
605
+ // If one of the hashes could not be parsed, they are not equal
606
+ if (!parsedHash || !parsedOther)
607
+ return false;
608
+ // For legacy hashes, we only compare the hash data. We already make sure during
609
+ // parsing of the cache files that we only need to compare hashes of the same version,
610
+ // so simply comparing the contents is sufficient.
611
+ if (parsedHash.version < 2 && parsedOther.version < 2) {
612
+ return Bytes.view(parsedHash.hashData).equals(parsedOther.hashData);
613
+ }
614
+ // We take care during loading to downlevel the current config hash to legacy versions if needed.
615
+ // If we end up with just one legacy hash here, something went wrong. Just bail in that case.
616
+ if (parsedHash.version < 2 || parsedOther.version < 2) {
617
+ return false;
618
+ }
619
+ // This is a versioned hash. If both versions are equal, it's simple - just compare the hash data
620
+ if (parsedHash.version === parsedOther.version) {
621
+ return Bytes.view(parsedHash.hashData).equals(parsedOther.hashData);
622
+ }
623
+ // For different versions, we have to do some case by case checks. For example, a newer hash version
624
+ // might remove or add data into the hashable, so we cannot simply convert between versions easily.
625
+ // Implement when that is actually needed.
626
+ return false;
627
+ }
628
+ }
629
+ function parseHash(hash) {
630
+ const hashString = Bytes.view(hash).toString("utf8");
631
+ const versionMatch = hashString.match(/^\$v(\d+)\$/);
632
+ if (versionMatch) {
633
+ // This is a versioned hash
634
+ const version = parseInt(versionMatch[1], 10);
635
+ const hashData = hash.subarray(
636
+ // The prefix is ASCII, so this is safe to do even in the context of UTF-8
637
+ versionMatch[0].length);
638
+ return {
639
+ version,
640
+ hashData,
641
+ };
642
+ }
643
+ // This is probably an unversioned legacy hash
644
+ switch (hash.length) {
645
+ case 16: // MD5
646
+ return {
647
+ version: 0,
648
+ hashData: hash,
649
+ };
650
+ case 32: // SHA-256
651
+ return {
652
+ version: 1,
653
+ hashData: hash,
654
+ };
655
+ default:
656
+ // This is not a valid hash
657
+ return undefined;
534
658
  }
535
659
  }
536
660
  //# sourceMappingURL=DeviceConfig.js.map