matterbridge 2.2.4 → 2.2.5-dev.3

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 (288) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/cli.js +2 -37
  3. package/dist/cluster/export.js +0 -2
  4. package/dist/defaultConfigSchema.js +0 -23
  5. package/dist/deviceManager.js +1 -94
  6. package/dist/frontend.js +70 -334
  7. package/dist/index.js +1 -28
  8. package/dist/logger/export.js +0 -1
  9. package/dist/matter/behaviors.js +0 -2
  10. package/dist/matter/clusters.js +0 -2
  11. package/dist/matter/devices.js +0 -2
  12. package/dist/matter/endpoints.js +0 -2
  13. package/dist/matter/export.js +0 -2
  14. package/dist/matter/types.js +0 -2
  15. package/dist/matterbridge.js +46 -743
  16. package/dist/matterbridgeAccessoryPlatform.js +0 -33
  17. package/dist/matterbridgeBehaviors.js +1 -32
  18. package/dist/matterbridgeDeviceTypes.js +11 -112
  19. package/dist/matterbridgeDynamicPlatform.js +0 -33
  20. package/dist/matterbridgeEndpoint.js +6 -690
  21. package/dist/matterbridgeEndpointHelpers.js +9 -118
  22. package/dist/matterbridgePlatform.js +13 -185
  23. package/dist/matterbridgeTypes.js +0 -24
  24. package/dist/pluginManager.js +7 -230
  25. package/dist/shelly.js +6 -121
  26. package/dist/storage/export.js +0 -1
  27. package/dist/update.js +0 -45
  28. package/dist/utils/colorUtils.js +2 -205
  29. package/dist/utils/copyDirectory.js +1 -37
  30. package/dist/utils/createZip.js +2 -42
  31. package/dist/utils/deepCopy.js +0 -40
  32. package/dist/utils/deepEqual.js +1 -65
  33. package/dist/utils/export.js +0 -1
  34. package/dist/utils/isvalid.js +0 -86
  35. package/dist/utils/network.js +5 -77
  36. package/dist/utils/parameter.js +0 -41
  37. package/dist/utils/wait.js +5 -48
  38. package/frontend/build/asset-manifest.json +80 -64
  39. package/frontend/build/index.html +1 -1
  40. package/frontend/build/static/css/main.ea7910e9.css +2 -0
  41. package/frontend/build/static/css/main.ea7910e9.css.map +1 -0
  42. package/frontend/build/static/js/453.d855a71b.chunk.js +2 -0
  43. package/frontend/build/static/js/{453.abd36b29.chunk.js.map → 453.d855a71b.chunk.js.map} +1 -1
  44. package/frontend/build/static/js/main.b42b0a2a.js +115 -0
  45. package/frontend/build/static/js/{main.4a12038d.js.LICENSE.txt → main.b42b0a2a.js.LICENSE.txt} +12 -27
  46. package/frontend/build/static/js/{main.4a12038d.js.map → main.b42b0a2a.js.map} +1 -1
  47. package/frontend/build/static/media/roboto-cyrillic-300-normal.44340549d94d10899346.woff +0 -0
  48. package/frontend/build/static/media/roboto-cyrillic-300-normal.89d0351bce4bc857dba6.woff2 +0 -0
  49. package/frontend/build/static/media/roboto-cyrillic-400-normal.86d5c52f4588f9f221d7.woff2 +0 -0
  50. package/frontend/build/static/media/roboto-cyrillic-400-normal.d67ac585bb6a05dbf71c.woff +0 -0
  51. package/frontend/build/static/media/roboto-cyrillic-500-normal.1fb2c6d685bfb888cfa3.woff2 +0 -0
  52. package/frontend/build/static/media/roboto-cyrillic-500-normal.36f79cc7e73a69da4438.woff +0 -0
  53. package/frontend/build/static/media/roboto-cyrillic-700-normal.e00802373a2c2db6b30d.woff +0 -0
  54. package/frontend/build/static/media/roboto-cyrillic-700-normal.fd3dfdd6cb1a9175b63d.woff2 +0 -0
  55. package/frontend/build/static/media/roboto-cyrillic-ext-300-normal.a80c0d0719b1acb8f731.woff +0 -0
  56. package/frontend/build/static/media/roboto-cyrillic-ext-300-normal.b9d87b04a9119d8d2fdf.woff2 +0 -0
  57. package/frontend/build/static/media/roboto-cyrillic-ext-400-normal.31476620b88eec076438.woff2 +0 -0
  58. package/frontend/build/static/media/roboto-cyrillic-ext-400-normal.5e3f232f89080810567d.woff +0 -0
  59. package/frontend/build/static/media/roboto-cyrillic-ext-500-normal.634ee2238bf30f362d52.woff2 +0 -0
  60. package/frontend/build/static/media/roboto-cyrillic-ext-500-normal.d6c661248da2fde17768.woff +0 -0
  61. package/frontend/build/static/media/roboto-cyrillic-ext-700-normal.361cdfd3a3f9c4bb09ca.woff2 +0 -0
  62. package/frontend/build/static/media/roboto-cyrillic-ext-700-normal.6b08bc756cd72f5af9e8.woff +0 -0
  63. package/frontend/build/static/media/roboto-greek-300-normal.8300b541aa89b8301a6f.woff +0 -0
  64. package/frontend/build/static/media/roboto-greek-300-normal.fdd1f928a606aa116a44.woff2 +0 -0
  65. package/frontend/build/static/media/roboto-greek-400-normal.98a717d5a38e77c0f657.woff2 +0 -0
  66. package/frontend/build/static/media/roboto-greek-400-normal.ecd8572d631f20ff5bd5.woff +0 -0
  67. package/frontend/build/static/media/roboto-greek-500-normal.4fe733bc436afc295c24.woff +0 -0
  68. package/frontend/build/static/media/roboto-greek-500-normal.5c8100481d4e784afbf2.woff2 +0 -0
  69. package/frontend/build/static/media/roboto-greek-700-normal.d23e03cf87ba44e5af6f.woff +0 -0
  70. package/frontend/build/static/media/roboto-greek-700-normal.d7dfd0b02cd8311e2a97.woff2 +0 -0
  71. package/frontend/build/static/media/roboto-greek-ext-300-normal.60729cafbded24073dfb.woff +0 -0
  72. package/frontend/build/static/media/roboto-greek-ext-300-normal.a88b77bb10633a8045e3.woff2 +0 -0
  73. package/frontend/build/static/media/roboto-greek-ext-400-normal.2d5875b032a1cca91eb2.woff2 +0 -0
  74. package/frontend/build/static/media/roboto-greek-ext-400-normal.a0baf7d6726d8f751a27.woff +0 -0
  75. package/frontend/build/static/media/roboto-greek-ext-500-normal.1964239c2800b6bd7e39.woff +0 -0
  76. package/frontend/build/static/media/roboto-greek-ext-500-normal.bef9c15c7164d6435aad.woff2 +0 -0
  77. package/frontend/build/static/media/roboto-greek-ext-700-normal.1aff9f4cd71608489b9a.woff +0 -0
  78. package/frontend/build/static/media/roboto-greek-ext-700-normal.eb28a447335ba6d54fcb.woff2 +0 -0
  79. package/frontend/build/static/media/roboto-latin-300-normal.cb14f8e80cc69ddbac34.woff +0 -0
  80. package/frontend/build/static/media/roboto-latin-300-normal.db56943a88e4852343ae.woff2 +0 -0
  81. package/frontend/build/static/media/roboto-latin-400-normal.50a0a61e29c19a2f05cb.woff +0 -0
  82. package/frontend/build/static/media/roboto-latin-400-normal.df1be0be92f6f19b8115.woff2 +0 -0
  83. package/frontend/build/static/media/roboto-latin-500-normal.599f66a60bdf974e578e.woff2 +0 -0
  84. package/frontend/build/static/media/roboto-latin-500-normal.c320def131b39bceabd8.woff +0 -0
  85. package/frontend/build/static/media/roboto-latin-700-normal.bcfbe8accc968a375a8e.woff +0 -0
  86. package/frontend/build/static/media/roboto-latin-700-normal.c4d6cab43bec89049809.woff2 +0 -0
  87. package/frontend/build/static/media/roboto-latin-ext-300-normal.6ddd1cfdbc5e74bcdab8.woff +0 -0
  88. package/frontend/build/static/media/roboto-latin-ext-300-normal.948c05192b1e64d931b1.woff2 +0 -0
  89. package/frontend/build/static/media/roboto-latin-ext-400-normal.0f86a30ca7e981fcfc99.woff2 +0 -0
  90. package/frontend/build/static/media/roboto-latin-ext-400-normal.2bfbba2d51a85c8702dd.woff +0 -0
  91. package/frontend/build/static/media/roboto-latin-ext-500-normal.8f02573e78730021ef49.woff2 +0 -0
  92. package/frontend/build/static/media/roboto-latin-ext-500-normal.aecaab4c4da2bf91377a.woff +0 -0
  93. package/frontend/build/static/media/roboto-latin-ext-700-normal.2d3c3ba6fe2d9c1026a5.woff +0 -0
  94. package/frontend/build/static/media/roboto-latin-ext-700-normal.8e656eff240311c6050a.woff2 +0 -0
  95. package/frontend/build/static/media/roboto-math-300-normal.90364ecfad5101ceb1a0.woff +0 -0
  96. package/frontend/build/static/media/roboto-math-300-normal.acc9c7c1d1fe3a1c7d44.woff2 +0 -0
  97. package/frontend/build/static/media/roboto-math-400-normal.3d3a272e5233c5fb1969.woff +0 -0
  98. package/frontend/build/static/media/roboto-math-400-normal.b60d9fba1e21da7497e6.woff2 +0 -0
  99. package/frontend/build/static/media/roboto-math-500-normal.41db483cb764343fca71.woff2 +0 -0
  100. package/frontend/build/static/media/roboto-math-500-normal.c3014a611cd9d8fa6252.woff +0 -0
  101. package/frontend/build/static/media/roboto-math-700-normal.a6fde3ddcb1629fd58b7.woff +0 -0
  102. package/frontend/build/static/media/roboto-math-700-normal.f6f4b54add6ab9d60a0f.woff2 +0 -0
  103. package/frontend/build/static/media/roboto-symbols-300-normal.52cdf8344b378f0c4580.woff +0 -0
  104. package/frontend/build/static/media/roboto-symbols-300-normal.616638ec44336b3da884.woff2 +0 -0
  105. package/frontend/build/static/media/roboto-symbols-400-normal.bb5b5d1459beb07bd3d5.woff2 +0 -0
  106. package/frontend/build/static/media/roboto-symbols-400-normal.f4f7e3bd8264f1a640cb.woff +0 -0
  107. package/frontend/build/static/media/roboto-symbols-500-normal.09b674875029289fd9a7.woff +0 -0
  108. package/frontend/build/static/media/roboto-symbols-500-normal.a5457b0ec984fd4cc8da.woff2 +0 -0
  109. package/frontend/build/static/media/roboto-symbols-700-normal.017e476ef02f62144169.woff +0 -0
  110. package/frontend/build/static/media/roboto-symbols-700-normal.634070e045ac99822c21.woff2 +0 -0
  111. package/frontend/build/static/media/roboto-vietnamese-300-normal.53f399e4522b647bafa7.woff +0 -0
  112. package/frontend/build/static/media/roboto-vietnamese-300-normal.6f0bf63e956c09377ef8.woff2 +0 -0
  113. package/frontend/build/static/media/roboto-vietnamese-400-normal.1cffe58e71a9109191a2.woff +0 -0
  114. package/frontend/build/static/media/roboto-vietnamese-400-normal.b1b8baa94fbcaa57d098.woff2 +0 -0
  115. package/frontend/build/static/media/roboto-vietnamese-500-normal.148734d63bd96c6e964f.woff2 +0 -0
  116. package/frontend/build/static/media/roboto-vietnamese-500-normal.72dbf2a25dd55b80b137.woff +0 -0
  117. package/frontend/build/static/media/roboto-vietnamese-700-normal.44a103f706f3ffe6a041.woff2 +0 -0
  118. package/frontend/build/static/media/roboto-vietnamese-700-normal.fa58a041a3336692af1e.woff +0 -0
  119. package/npm-shrinkwrap.json +2 -2
  120. package/package.json +1 -2
  121. package/dist/cli.d.ts +0 -29
  122. package/dist/cli.d.ts.map +0 -1
  123. package/dist/cli.js.map +0 -1
  124. package/dist/cluster/export.d.ts +0 -2
  125. package/dist/cluster/export.d.ts.map +0 -1
  126. package/dist/cluster/export.js.map +0 -1
  127. package/dist/defaultConfigSchema.d.ts +0 -27
  128. package/dist/defaultConfigSchema.d.ts.map +0 -1
  129. package/dist/defaultConfigSchema.js.map +0 -1
  130. package/dist/deviceManager.d.ts +0 -114
  131. package/dist/deviceManager.d.ts.map +0 -1
  132. package/dist/deviceManager.js.map +0 -1
  133. package/dist/frontend.d.ts +0 -221
  134. package/dist/frontend.d.ts.map +0 -1
  135. package/dist/frontend.js.map +0 -1
  136. package/dist/index.d.ts +0 -35
  137. package/dist/index.d.ts.map +0 -1
  138. package/dist/index.js.map +0 -1
  139. package/dist/logger/export.d.ts +0 -2
  140. package/dist/logger/export.d.ts.map +0 -1
  141. package/dist/logger/export.js.map +0 -1
  142. package/dist/matter/behaviors.d.ts +0 -2
  143. package/dist/matter/behaviors.d.ts.map +0 -1
  144. package/dist/matter/behaviors.js.map +0 -1
  145. package/dist/matter/clusters.d.ts +0 -2
  146. package/dist/matter/clusters.d.ts.map +0 -1
  147. package/dist/matter/clusters.js.map +0 -1
  148. package/dist/matter/devices.d.ts +0 -2
  149. package/dist/matter/devices.d.ts.map +0 -1
  150. package/dist/matter/devices.js.map +0 -1
  151. package/dist/matter/endpoints.d.ts +0 -2
  152. package/dist/matter/endpoints.d.ts.map +0 -1
  153. package/dist/matter/endpoints.js.map +0 -1
  154. package/dist/matter/export.d.ts +0 -5
  155. package/dist/matter/export.d.ts.map +0 -1
  156. package/dist/matter/export.js.map +0 -1
  157. package/dist/matter/types.d.ts +0 -3
  158. package/dist/matter/types.d.ts.map +0 -1
  159. package/dist/matter/types.js.map +0 -1
  160. package/dist/matterbridge.d.ts +0 -422
  161. package/dist/matterbridge.d.ts.map +0 -1
  162. package/dist/matterbridge.js.map +0 -1
  163. package/dist/matterbridgeAccessoryPlatform.d.ts +0 -39
  164. package/dist/matterbridgeAccessoryPlatform.d.ts.map +0 -1
  165. package/dist/matterbridgeAccessoryPlatform.js.map +0 -1
  166. package/dist/matterbridgeBehaviors.d.ts +0 -1056
  167. package/dist/matterbridgeBehaviors.d.ts.map +0 -1
  168. package/dist/matterbridgeBehaviors.js.map +0 -1
  169. package/dist/matterbridgeDeviceTypes.d.ts +0 -177
  170. package/dist/matterbridgeDeviceTypes.d.ts.map +0 -1
  171. package/dist/matterbridgeDeviceTypes.js.map +0 -1
  172. package/dist/matterbridgeDynamicPlatform.d.ts +0 -39
  173. package/dist/matterbridgeDynamicPlatform.d.ts.map +0 -1
  174. package/dist/matterbridgeDynamicPlatform.js.map +0 -1
  175. package/dist/matterbridgeEndpoint.d.ts +0 -835
  176. package/dist/matterbridgeEndpoint.d.ts.map +0 -1
  177. package/dist/matterbridgeEndpoint.js.map +0 -1
  178. package/dist/matterbridgeEndpointHelpers.d.ts +0 -2275
  179. package/dist/matterbridgeEndpointHelpers.d.ts.map +0 -1
  180. package/dist/matterbridgeEndpointHelpers.js.map +0 -1
  181. package/dist/matterbridgePlatform.d.ts +0 -251
  182. package/dist/matterbridgePlatform.d.ts.map +0 -1
  183. package/dist/matterbridgePlatform.js.map +0 -1
  184. package/dist/matterbridgeTypes.d.ts +0 -178
  185. package/dist/matterbridgeTypes.d.ts.map +0 -1
  186. package/dist/matterbridgeTypes.js.map +0 -1
  187. package/dist/pluginManager.d.ts +0 -236
  188. package/dist/pluginManager.d.ts.map +0 -1
  189. package/dist/pluginManager.js.map +0 -1
  190. package/dist/shelly.d.ts +0 -77
  191. package/dist/shelly.d.ts.map +0 -1
  192. package/dist/shelly.js.map +0 -1
  193. package/dist/storage/export.d.ts +0 -2
  194. package/dist/storage/export.d.ts.map +0 -1
  195. package/dist/storage/export.js.map +0 -1
  196. package/dist/update.d.ts +0 -32
  197. package/dist/update.d.ts.map +0 -1
  198. package/dist/update.js.map +0 -1
  199. package/dist/utils/colorUtils.d.ts +0 -61
  200. package/dist/utils/colorUtils.d.ts.map +0 -1
  201. package/dist/utils/colorUtils.js.map +0 -1
  202. package/dist/utils/copyDirectory.d.ts +0 -32
  203. package/dist/utils/copyDirectory.d.ts.map +0 -1
  204. package/dist/utils/copyDirectory.js.map +0 -1
  205. package/dist/utils/createZip.d.ts +0 -38
  206. package/dist/utils/createZip.d.ts.map +0 -1
  207. package/dist/utils/createZip.js.map +0 -1
  208. package/dist/utils/deepCopy.d.ts +0 -31
  209. package/dist/utils/deepCopy.d.ts.map +0 -1
  210. package/dist/utils/deepCopy.js.map +0 -1
  211. package/dist/utils/deepEqual.d.ts +0 -53
  212. package/dist/utils/deepEqual.d.ts.map +0 -1
  213. package/dist/utils/deepEqual.js.map +0 -1
  214. package/dist/utils/export.d.ts +0 -10
  215. package/dist/utils/export.d.ts.map +0 -1
  216. package/dist/utils/export.js.map +0 -1
  217. package/dist/utils/isvalid.d.ts +0 -87
  218. package/dist/utils/isvalid.d.ts.map +0 -1
  219. package/dist/utils/isvalid.js.map +0 -1
  220. package/dist/utils/network.d.ts +0 -70
  221. package/dist/utils/network.d.ts.map +0 -1
  222. package/dist/utils/network.js.map +0 -1
  223. package/dist/utils/parameter.d.ts +0 -44
  224. package/dist/utils/parameter.d.ts.map +0 -1
  225. package/dist/utils/parameter.js.map +0 -1
  226. package/dist/utils/wait.d.ts +0 -43
  227. package/dist/utils/wait.d.ts.map +0 -1
  228. package/dist/utils/wait.js.map +0 -1
  229. package/frontend/build/static/css/main.e52977d6.css +0 -2
  230. package/frontend/build/static/css/main.e52977d6.css.map +0 -1
  231. package/frontend/build/static/js/453.abd36b29.chunk.js +0 -2
  232. package/frontend/build/static/js/main.4a12038d.js +0 -115
  233. package/frontend/build/static/media/roboto-cyrillic-300-normal.1b79538ccd585c259996.woff2 +0 -0
  234. package/frontend/build/static/media/roboto-cyrillic-300-normal.5f077fd7b977d1715acf.woff +0 -0
  235. package/frontend/build/static/media/roboto-cyrillic-400-normal.5d2930082227d172f62c.woff +0 -0
  236. package/frontend/build/static/media/roboto-cyrillic-400-normal.a9e19870cf6c4b973427.woff2 +0 -0
  237. package/frontend/build/static/media/roboto-cyrillic-500-normal.0ae2428323939af5e1ad.woff2 +0 -0
  238. package/frontend/build/static/media/roboto-cyrillic-500-normal.dd7bc8a52c6c70c5a3f5.woff +0 -0
  239. package/frontend/build/static/media/roboto-cyrillic-700-normal.3f6e1548bd5175a8c342.woff +0 -0
  240. package/frontend/build/static/media/roboto-cyrillic-700-normal.4fdfc29a10e7d4b7c527.woff2 +0 -0
  241. package/frontend/build/static/media/roboto-cyrillic-ext-300-normal.795dbc8140e3fef82983.woff +0 -0
  242. package/frontend/build/static/media/roboto-cyrillic-ext-300-normal.80947a31d23c70204b47.woff2 +0 -0
  243. package/frontend/build/static/media/roboto-cyrillic-ext-400-normal.135d076fa32aa0b4d105.woff +0 -0
  244. package/frontend/build/static/media/roboto-cyrillic-ext-400-normal.5cec61a21cc20180fbe1.woff2 +0 -0
  245. package/frontend/build/static/media/roboto-cyrillic-ext-500-normal.6de16332fda843a3dc3d.woff2 +0 -0
  246. package/frontend/build/static/media/roboto-cyrillic-ext-500-normal.c0a0638f90b31d6454ba.woff +0 -0
  247. package/frontend/build/static/media/roboto-cyrillic-ext-700-normal.4750292c47fa2bc6ac1a.woff2 +0 -0
  248. package/frontend/build/static/media/roboto-cyrillic-ext-700-normal.ca247189fc12d00de361.woff +0 -0
  249. package/frontend/build/static/media/roboto-greek-300-normal.285f3e6261d8eb20417d.woff2 +0 -0
  250. package/frontend/build/static/media/roboto-greek-300-normal.889beddda1c9bd9f97df.woff +0 -0
  251. package/frontend/build/static/media/roboto-greek-400-normal.160a791a8e4f46bca3cc.woff +0 -0
  252. package/frontend/build/static/media/roboto-greek-400-normal.2c32b1315be61477013a.woff2 +0 -0
  253. package/frontend/build/static/media/roboto-greek-500-normal.60810e07c7b0273013aa.woff +0 -0
  254. package/frontend/build/static/media/roboto-greek-500-normal.f95e757c5483310f9c11.woff2 +0 -0
  255. package/frontend/build/static/media/roboto-greek-700-normal.77dd370f2001e184ba0d.woff2 +0 -0
  256. package/frontend/build/static/media/roboto-greek-700-normal.df87b053fae3d7ad5f7a.woff +0 -0
  257. package/frontend/build/static/media/roboto-greek-ext-300-normal.b590dbe5c639944366d1.woff +0 -0
  258. package/frontend/build/static/media/roboto-greek-ext-300-normal.d6049cb54aa6fbe14c42.woff2 +0 -0
  259. package/frontend/build/static/media/roboto-greek-ext-400-normal.16eb83b4a3b1ea994243.woff +0 -0
  260. package/frontend/build/static/media/roboto-greek-ext-400-normal.1df4abad55796d11a0c8.woff2 +0 -0
  261. package/frontend/build/static/media/roboto-greek-ext-500-normal.4a96ba31abcce0f5d52b.woff2 +0 -0
  262. package/frontend/build/static/media/roboto-greek-ext-500-normal.fd28d9c008bf3af1bed7.woff +0 -0
  263. package/frontend/build/static/media/roboto-greek-ext-700-normal.2dd6febad11502dec6a6.woff2 +0 -0
  264. package/frontend/build/static/media/roboto-greek-ext-700-normal.4abdc9fff4507f17d726.woff +0 -0
  265. package/frontend/build/static/media/roboto-latin-300-normal.b850f1ff581ea232fac9.woff2 +0 -0
  266. package/frontend/build/static/media/roboto-latin-300-normal.c4bc0593c9954d79cb3a.woff +0 -0
  267. package/frontend/build/static/media/roboto-latin-400-normal.047a7839f69b209db815.woff +0 -0
  268. package/frontend/build/static/media/roboto-latin-400-normal.297d48e1b5a10c0831a9.woff2 +0 -0
  269. package/frontend/build/static/media/roboto-latin-500-normal.68d40d6d01c6f85d24ba.woff +0 -0
  270. package/frontend/build/static/media/roboto-latin-500-normal.7077203b1982951ecf76.woff2 +0 -0
  271. package/frontend/build/static/media/roboto-latin-700-normal.4535474e1cf8598695ad.woff2 +0 -0
  272. package/frontend/build/static/media/roboto-latin-700-normal.9f6a16a7770c87b2042b.woff +0 -0
  273. package/frontend/build/static/media/roboto-latin-ext-300-normal.14982a9e4857a93b6dce.woff +0 -0
  274. package/frontend/build/static/media/roboto-latin-ext-300-normal.97cbc447d4a8d41a9543.woff2 +0 -0
  275. package/frontend/build/static/media/roboto-latin-ext-400-normal.27da5b36b6d3a16f53f4.woff +0 -0
  276. package/frontend/build/static/media/roboto-latin-ext-400-normal.2eeae187764baf05867d.woff2 +0 -0
  277. package/frontend/build/static/media/roboto-latin-ext-500-normal.06c30711d588145a4541.woff +0 -0
  278. package/frontend/build/static/media/roboto-latin-ext-500-normal.9a18d7bb9ff7a6af7b32.woff2 +0 -0
  279. package/frontend/build/static/media/roboto-latin-ext-700-normal.18841836e391d39e83a8.woff2 +0 -0
  280. package/frontend/build/static/media/roboto-latin-ext-700-normal.3c5bcdd0e69c4c3ffafe.woff +0 -0
  281. package/frontend/build/static/media/roboto-vietnamese-300-normal.c96b16e5c05c7b7c3e89.woff2 +0 -0
  282. package/frontend/build/static/media/roboto-vietnamese-300-normal.f5e7cea32756dfe7af40.woff +0 -0
  283. package/frontend/build/static/media/roboto-vietnamese-400-normal.0dc97c66f9b542d6fa17.woff +0 -0
  284. package/frontend/build/static/media/roboto-vietnamese-400-normal.d3f8e26d6c27de8102b6.woff2 +0 -0
  285. package/frontend/build/static/media/roboto-vietnamese-500-normal.090fabef926bdc0e9b9f.woff2 +0 -0
  286. package/frontend/build/static/media/roboto-vietnamese-500-normal.23b7b8a2524d2d4b637b.woff +0 -0
  287. package/frontend/build/static/media/roboto-vietnamese-700-normal.0a79a9fabfc32e33f360.woff2 +0 -0
  288. package/frontend/build/static/media/roboto-vietnamese-700-normal.35ed0597568ff6f19c16.woff +0 -0
package/dist/frontend.js CHANGED
@@ -1,28 +1,4 @@
1
- /**
2
- * This file contains the class Frontend.
3
- *
4
- * @file frontend.ts
5
- * @author Luca Liguori
6
- * @date 2025-01-13
7
- * @version 1.0.2
8
- *
9
- * Copyright 2025, 2026, 2027 Luca Liguori.
10
- *
11
- * Licensed under the Apache License, Version 2.0 (the "License");
12
- * you may not use this file except in compliance with the License.
13
- * You may obtain a copy of the License at
14
- *
15
- * http://www.apache.org/licenses/LICENSE-2.0
16
- *
17
- * Unless required by applicable law or agreed to in writing, software
18
- * distributed under the License is distributed on an "AS IS" BASIS,
19
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
- * See the License for the specific language governing permissions and
21
- * limitations under the License. *
22
- */
23
- // @matter
24
1
  import { EndpointServer, Logger, LogLevel as MatterLogLevel, LogFormat as MatterLogFormat, Lifecycle } from '@matter/main';
25
- // Node modules
26
2
  import { createServer } from 'node:http';
27
3
  import os from 'node:os';
28
4
  import path from 'node:path';
@@ -31,75 +7,21 @@ import https from 'https';
31
7
  import express from 'express';
32
8
  import WebSocket, { WebSocketServer } from 'ws';
33
9
  import multer from 'multer';
34
- // AnsiLogger module
35
- import { AnsiLogger, stringify, debugStringify, CYAN, db, er, nf, rs, UNDERLINE, UNDERLINEOFF, wr, YELLOW } from './logger/export.js';
36
- // Matterbridge
10
+ import { AnsiLogger, stringify, debugStringify, CYAN, db, er, nf, rs, UNDERLINE, UNDERLINEOFF, wr, YELLOW, nt } from './logger/export.js';
37
11
  import { createZip, deepCopy, isValidArray, isValidNumber, isValidObject, isValidString } from './utils/export.js';
38
12
  import { plg } from './matterbridgeTypes.js';
39
13
  import { hasParameter } from './utils/export.js';
40
14
  import { BridgedDeviceBasicInformation } from '@matter/main/clusters';
41
- /**
42
- * Websocket message ID for logging.
43
- * @constant {number}
44
- */
45
15
  export const WS_ID_LOG = 0;
46
- /**
47
- * Websocket message ID indicating a refresh is needed.
48
- * @constant {number}
49
- */
50
16
  export const WS_ID_REFRESH_NEEDED = 1;
51
- /**
52
- * Websocket message ID indicating a restart is needed.
53
- * @constant {number}
54
- */
55
17
  export const WS_ID_RESTART_NEEDED = 2;
56
- /**
57
- * Websocket message ID indicating a cpu update.
58
- * @constant {number}
59
- */
60
18
  export const WS_ID_CPU_UPDATE = 3;
61
- /**
62
- * Websocket message ID indicating a memory update.
63
- * @constant {number}
64
- */
65
19
  export const WS_ID_MEMORY_UPDATE = 4;
66
- /**
67
- * Websocket message ID indicating an uptime update.
68
- * @constant {number}
69
- */
70
20
  export const WS_ID_UPTIME_UPDATE = 5;
71
- /**
72
- * Websocket message ID indicating a snackbar message.
73
- * @constant {number}
74
- */
75
21
  export const WS_ID_SNACKBAR = 6;
76
- /**
77
- * Websocket message ID indicating matterbridge has un update available.
78
- * @constant {number}
79
- */
80
22
  export const WS_ID_UPDATE_NEEDED = 7;
81
- /**
82
- * Websocket message ID indicating a state update.
83
- * @constant {number}
84
- */
85
23
  export const WS_ID_STATEUPDATE = 8;
86
- /**
87
- * Websocket message ID indicating a shelly system update.
88
- * check:
89
- * curl -k http://127.0.0.1:8101/api/updates/sys/check
90
- * perform:
91
- * curl -k http://127.0.0.1:8101/api/updates/sys/perform
92
- * @constant {number}
93
- */
94
24
  export const WS_ID_SHELLY_SYS_UPDATE = 100;
95
- /**
96
- * Websocket message ID indicating a shelly main update.
97
- * check:
98
- * curl -k http://127.0.0.1:8101/api/updates/main/check
99
- * perform:
100
- * curl -k http://127.0.0.1:8101/api/updates/main/perform
101
- * @constant {number}
102
- */
103
25
  export const WS_ID_SHELLY_MAIN_UPDATE = 101;
104
26
  export class Frontend {
105
27
  matterbridge;
@@ -117,7 +39,7 @@ export class Frontend {
117
39
  memoryTimeout;
118
40
  constructor(matterbridge) {
119
41
  this.matterbridge = matterbridge;
120
- this.log = new AnsiLogger({ logName: 'Frontend', logTimestampFormat: 4 /* TimestampFormat.TIME_MILLIS */, logLevel: hasParameter('debug') ? "debug" /* LogLevel.DEBUG */ : "info" /* LogLevel.INFO */ });
42
+ this.log = new AnsiLogger({ logName: 'Frontend', logTimestampFormat: 4, logLevel: hasParameter('debug') ? "debug" : "info" });
121
43
  }
122
44
  set logLevel(logLevel) {
123
45
  this.log.logLevel = logLevel;
@@ -125,25 +47,13 @@ export class Frontend {
125
47
  async start(port = 8283) {
126
48
  this.port = port;
127
49
  this.log.debug(`Initializing the frontend ${hasParameter('ssl') ? 'https' : 'http'} server on port ${YELLOW}${this.port}${db}`);
128
- // Initialize multer with the upload directory
129
50
  const uploadDir = path.join(this.matterbridge.matterbridgeDirectory, 'uploads');
130
51
  await fs.mkdir(uploadDir, { recursive: true });
131
52
  const upload = multer({ dest: uploadDir });
132
- // Create the express app that serves the frontend
133
53
  this.expressApp = express();
134
- // Log all requests to the server for debugging
135
- /*
136
- this.expressApp.use((req, res, next) => {
137
- this.log.debug(`Received request on expressApp: ${req.method} ${req.url}`);
138
- next();
139
- });
140
- */
141
- // Serve static files from '/static' endpoint
142
54
  this.expressApp.use(express.static(path.join(this.matterbridge.rootDirectory, 'frontend/build')));
143
55
  if (!hasParameter('ssl')) {
144
- // Create an HTTP server and attach the express app
145
56
  this.httpServer = createServer(this.expressApp);
146
- // Listen on the specified port
147
57
  if (hasParameter('ingress')) {
148
58
  this.httpServer.listen(this.port, '0.0.0.0', () => {
149
59
  this.log.info(`The frontend http server is listening on ${UNDERLINE}http://0.0.0.0:${this.port}${UNDERLINEOFF}${rs}`);
@@ -157,7 +67,6 @@ export class Frontend {
157
67
  this.log.info(`The frontend http server is listening on ${UNDERLINE}http://[${this.matterbridge.systemInformation.ipv6Address}]:${this.port}${UNDERLINEOFF}${rs}`);
158
68
  });
159
69
  }
160
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
161
70
  this.httpServer.on('error', (error) => {
162
71
  this.log.error(`Frontend http server error listening on ${this.port}`);
163
72
  switch (error.code) {
@@ -173,7 +82,6 @@ export class Frontend {
173
82
  });
174
83
  }
175
84
  else {
176
- // Load the SSL certificate, the private key and optionally the CA certificate
177
85
  let cert;
178
86
  try {
179
87
  cert = await fs.readFile(path.join(this.matterbridge.matterbridgeDirectory, 'certs/cert.pem'), 'utf8');
@@ -201,9 +109,7 @@ export class Frontend {
201
109
  this.log.info(`CA certificate file ${path.join(this.matterbridge.matterbridgeDirectory, 'certs/ca.pem')} not loaded: ${error}`);
202
110
  }
203
111
  const serverOptions = { cert, key, ca };
204
- // Create an HTTPS server with the SSL certificate and private key (ca is optional) and attach the express app
205
112
  this.httpsServer = https.createServer(serverOptions, this.expressApp);
206
- // Listen on the specified port
207
113
  if (hasParameter('ingress')) {
208
114
  this.httpsServer.listen(this.port, '0.0.0.0', () => {
209
115
  this.log.info(`The frontend https server is listening on ${UNDERLINE}https://0.0.0.0:${this.port}${UNDERLINEOFF}${rs}`);
@@ -217,7 +123,6 @@ export class Frontend {
217
123
  this.log.info(`The frontend https server is listening on ${UNDERLINE}https://[${this.matterbridge.systemInformation.ipv6Address}]:${this.port}${UNDERLINEOFF}${rs}`);
218
124
  });
219
125
  }
220
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
221
126
  this.httpsServer.on('error', (error) => {
222
127
  this.log.error(`Frontend https server error listening on ${this.port}`);
223
128
  switch (error.code) {
@@ -234,18 +139,16 @@ export class Frontend {
234
139
  }
235
140
  if (this.initializeError)
236
141
  return;
237
- // Create a WebSocket server and attach it to the http or https server
238
142
  const wssPort = this.port;
239
143
  const wssHost = hasParameter('ssl') ? `wss://${this.matterbridge.systemInformation.ipv4Address}:${wssPort}` : `ws://${this.matterbridge.systemInformation.ipv4Address}:${wssPort}`;
240
144
  this.webSocketServer = new WebSocketServer(hasParameter('ssl') ? { server: this.httpsServer } : { server: this.httpServer });
241
145
  this.webSocketServer.on('connection', (ws, request) => {
242
146
  const clientIp = request.socket.remoteAddress;
243
- // Set the global logger callback for the WebSocketServer
244
- let callbackLogLevel = "notice" /* LogLevel.NOTICE */;
245
- if (this.matterbridge.matterbridgeInformation.loggerLevel === "info" /* LogLevel.INFO */ || this.matterbridge.matterbridgeInformation.matterLoggerLevel === MatterLogLevel.INFO)
246
- callbackLogLevel = "info" /* LogLevel.INFO */;
247
- if (this.matterbridge.matterbridgeInformation.loggerLevel === "debug" /* LogLevel.DEBUG */ || this.matterbridge.matterbridgeInformation.matterLoggerLevel === MatterLogLevel.DEBUG)
248
- callbackLogLevel = "debug" /* LogLevel.DEBUG */;
147
+ let callbackLogLevel = "notice";
148
+ if (this.matterbridge.matterbridgeInformation.loggerLevel === "info" || this.matterbridge.matterbridgeInformation.matterLoggerLevel === MatterLogLevel.INFO)
149
+ callbackLogLevel = "info";
150
+ if (this.matterbridge.matterbridgeInformation.loggerLevel === "debug" || this.matterbridge.matterbridgeInformation.matterLoggerLevel === MatterLogLevel.DEBUG)
151
+ callbackLogLevel = "debug";
249
152
  AnsiLogger.setGlobalCallback(this.wssSendMessage.bind(this), callbackLogLevel);
250
153
  this.log.debug(`WebSocketServer logger global callback set to ${callbackLogLevel}`);
251
154
  this.log.info(`WebSocketServer client "${clientIp}" connected to Matterbridge`);
@@ -279,7 +182,6 @@ export class Frontend {
279
182
  this.webSocketServer.on('error', (ws, error) => {
280
183
  this.log.error(`WebSocketServer error: ${error}`);
281
184
  });
282
- // Subscribe to cli events
283
185
  const { cliEmitter } = await import('./cli.js');
284
186
  cliEmitter.removeAllListeners();
285
187
  cliEmitter.on('uptime', (systemUptime, processUptime) => {
@@ -291,7 +193,6 @@ export class Frontend {
291
193
  cliEmitter.on('cpu', (cpuUsage) => {
292
194
  this.wssSendCpuUpdate(cpuUsage);
293
195
  });
294
- // Endpoint to validate login code
295
196
  this.expressApp.post('/api/login', express.json(), async (req, res) => {
296
197
  const { password } = req.body;
297
198
  this.log.debug('The frontend sent /api/login', password);
@@ -310,27 +211,23 @@ export class Frontend {
310
211
  this.log.warn('/api/login error wrong password');
311
212
  res.json({ valid: false });
312
213
  }
313
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
314
214
  }
315
215
  catch (error) {
316
216
  this.log.error('/api/login error getting password');
317
217
  res.json({ valid: false });
318
218
  }
319
219
  });
320
- // Endpoint to provide health check
321
220
  this.expressApp.get('/health', (req, res) => {
322
221
  this.log.debug('Express received /health');
323
222
  const healthStatus = {
324
- status: 'ok', // Indicate service is healthy
325
- uptime: process.uptime(), // Server uptime in seconds
326
- timestamp: new Date().toISOString(), // Current timestamp
223
+ status: 'ok',
224
+ uptime: process.uptime(),
225
+ timestamp: new Date().toISOString(),
327
226
  };
328
227
  res.status(200).json(healthStatus);
329
228
  });
330
- // Endpoint to provide memory usage details
331
229
  this.expressApp.get('/memory', async (req, res) => {
332
230
  this.log.debug('Express received /memory');
333
- // Memory usage from process
334
231
  const memoryUsageRaw = process.memoryUsage();
335
232
  const memoryUsage = {
336
233
  rss: this.formatMemoryUsage(memoryUsageRaw.rss),
@@ -339,13 +236,10 @@ export class Frontend {
339
236
  external: this.formatMemoryUsage(memoryUsageRaw.external),
340
237
  arrayBuffers: this.formatMemoryUsage(memoryUsageRaw.arrayBuffers),
341
238
  };
342
- // V8 heap statistics
343
239
  const { default: v8 } = await import('node:v8');
344
240
  const heapStatsRaw = v8.getHeapStatistics();
345
241
  const heapSpacesRaw = v8.getHeapSpaceStatistics();
346
- // Format heapStats
347
242
  const heapStats = Object.fromEntries(Object.entries(heapStatsRaw).map(([key, value]) => [key, this.formatMemoryUsage(value)]));
348
- // Format heapSpaces
349
243
  const heapSpaces = heapSpacesRaw.map((space) => ({
350
244
  ...space,
351
245
  space_size: this.formatMemoryUsage(space.space_size),
@@ -363,7 +257,6 @@ export class Frontend {
363
257
  };
364
258
  res.status(200).json(memoryReport);
365
259
  });
366
- // Endpoint to start advertising the server node
367
260
  this.expressApp.get('/api/advertise', express.json(), async (req, res) => {
368
261
  const pairingCodes = await this.matterbridge.advertiseServerNode(this.matterbridge.serverNode);
369
262
  if (pairingCodes) {
@@ -374,22 +267,18 @@ export class Frontend {
374
267
  res.status(500).json({ error: 'Failed to generate pairing codes' });
375
268
  }
376
269
  });
377
- // Endpoint to provide settings
378
270
  this.expressApp.get('/api/settings', express.json(), async (req, res) => {
379
271
  this.log.debug('The frontend sent /api/settings');
380
272
  res.json(await this.getApiSettings());
381
273
  });
382
- // Endpoint to provide plugins
383
274
  this.expressApp.get('/api/plugins', async (req, res) => {
384
275
  this.log.debug('The frontend sent /api/plugins');
385
276
  res.json(this.getBaseRegisteredPlugins());
386
277
  });
387
- // Endpoint to provide devices
388
278
  this.expressApp.get('/api/devices', (req, res) => {
389
279
  this.log.debug('The frontend sent /api/devices');
390
280
  const devices = [];
391
281
  this.matterbridge.devices.forEach(async (device) => {
392
- // Check if the device has the required properties
393
282
  if (!device.plugin || !device.name || !device.deviceName || !device.serialNumber || !device.uniqueId || !device.lifecycle.isReady)
394
283
  return;
395
284
  const cluster = this.getClusterTextFromDevice(device);
@@ -408,7 +297,6 @@ export class Frontend {
408
297
  });
409
298
  res.json(devices);
410
299
  });
411
- // Endpoint to provide the cluster servers of the devices
412
300
  this.expressApp.get('/api/devices_clusters/:selectedPluginName/:selectedDeviceEndpoint', (req, res) => {
413
301
  const selectedPluginName = req.params.selectedPluginName;
414
302
  const selectedDeviceEndpoint = parseInt(req.params.selectedDeviceEndpoint, 10);
@@ -481,7 +369,6 @@ export class Frontend {
481
369
  });
482
370
  res.json(data);
483
371
  });
484
- // Endpoint to view the log
485
372
  this.expressApp.get('/api/view-log', async (req, res) => {
486
373
  this.log.debug('The frontend sent /api/log');
487
374
  try {
@@ -494,12 +381,10 @@ export class Frontend {
494
381
  res.status(500).send('Error reading log file');
495
382
  }
496
383
  });
497
- // Endpoint to download the matterbridge log
498
384
  this.expressApp.get('/api/download-mblog', async (req, res) => {
499
385
  this.log.debug('The frontend sent /api/download-mblog');
500
386
  try {
501
387
  await fs.access(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterbrideLoggerFile), fs.constants.F_OK);
502
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
503
388
  }
504
389
  catch (error) {
505
390
  fs.appendFile(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterbrideLoggerFile), 'Enable the log on file in the settings to enable the file logger');
@@ -511,12 +396,10 @@ export class Frontend {
511
396
  }
512
397
  });
513
398
  });
514
- // Endpoint to download the matter log
515
399
  this.expressApp.get('/api/download-mjlog', async (req, res) => {
516
400
  this.log.debug('The frontend sent /api/download-mjlog');
517
401
  try {
518
402
  await fs.access(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterLoggerFile), fs.constants.F_OK);
519
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
520
403
  }
521
404
  catch (error) {
522
405
  fs.appendFile(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterLoggerFile), 'Enable the log on file in the settings to enable the file logger');
@@ -528,12 +411,10 @@ export class Frontend {
528
411
  }
529
412
  });
530
413
  });
531
- // Endpoint to download the matter log
532
414
  this.expressApp.get('/api/shellydownloadsystemlog', async (req, res) => {
533
415
  this.log.debug('The frontend sent /api/shellydownloadsystemlog');
534
416
  try {
535
417
  await fs.access(path.join(this.matterbridge.matterbridgeDirectory, 'shelly.log'), fs.constants.F_OK);
536
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
537
418
  }
538
419
  catch (error) {
539
420
  fs.appendFile(path.join(this.matterbridge.matterbridgeDirectory, 'shelly.log'), 'Create the Shelly system log before downloading it.');
@@ -545,7 +426,6 @@ export class Frontend {
545
426
  }
546
427
  });
547
428
  });
548
- // Endpoint to download the matter storage file
549
429
  this.expressApp.get('/api/download-mjstorage', async (req, res) => {
550
430
  this.log.debug('The frontend sent /api/download-mjstorage');
551
431
  await createZip(path.join(os.tmpdir(), `matterbridge.${this.matterbridge.matterStorageName}.zip`), path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterStorageName));
@@ -556,7 +436,6 @@ export class Frontend {
556
436
  }
557
437
  });
558
438
  });
559
- // Endpoint to download the matterbridge storage directory
560
439
  this.expressApp.get('/api/download-mbstorage', async (req, res) => {
561
440
  this.log.debug('The frontend sent /api/download-mbstorage');
562
441
  await createZip(path.join(os.tmpdir(), `matterbridge.${this.matterbridge.nodeStorageName}.zip`), path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.nodeStorageName));
@@ -567,7 +446,6 @@ export class Frontend {
567
446
  }
568
447
  });
569
448
  });
570
- // Endpoint to download the matterbridge plugin directory
571
449
  this.expressApp.get('/api/download-pluginstorage', async (req, res) => {
572
450
  this.log.debug('The frontend sent /api/download-pluginstorage');
573
451
  await createZip(path.join(os.tmpdir(), `matterbridge.pluginstorage.zip`), this.matterbridge.matterbridgePluginDirectory);
@@ -578,11 +456,9 @@ export class Frontend {
578
456
  }
579
457
  });
580
458
  });
581
- // Endpoint to download the matterbridge plugin config files
582
459
  this.expressApp.get('/api/download-pluginconfig', async (req, res) => {
583
460
  this.log.debug('The frontend sent /api/download-pluginconfig');
584
461
  await createZip(path.join(os.tmpdir(), `matterbridge.pluginconfig.zip`), path.relative(process.cwd(), path.join(this.matterbridge.matterbridgeDirectory, '*.config.json')));
585
- // await createZip(path.join(os.tmpdir(), `matterbridge.pluginconfig.zip`), path.relative(process.cwd(), path.join(this.matterbridge.matterbridgeDirectory, 'certs', '*.*')), path.relative(process.cwd(), path.join(this.matterbridge.matterbridgeDirectory, '*.config.json')));
586
462
  res.download(path.join(os.tmpdir(), `matterbridge.pluginconfig.zip`), `matterbridge.pluginconfig.zip`, (error) => {
587
463
  if (error) {
588
464
  this.log.error(`Error downloading file matterbridge.pluginstorage.zip: ${error instanceof Error ? error.message : error}`);
@@ -590,7 +466,6 @@ export class Frontend {
590
466
  }
591
467
  });
592
468
  });
593
- // Endpoint to download the matterbridge plugin config files
594
469
  this.expressApp.get('/api/download-backup', async (req, res) => {
595
470
  this.log.debug('The frontend sent /api/download-backup');
596
471
  res.download(path.join(os.tmpdir(), `matterbridge.backup.zip`), `matterbridge.backup.zip`, (error) => {
@@ -600,7 +475,6 @@ export class Frontend {
600
475
  }
601
476
  });
602
477
  });
603
- // Endpoint to receive commands
604
478
  this.expressApp.post('/api/command/:command/:param', express.json(), async (req, res) => {
605
479
  const command = req.params.command;
606
480
  let param = req.params.param;
@@ -610,15 +484,13 @@ export class Frontend {
610
484
  return;
611
485
  }
612
486
  this.log.debug(`Received frontend command: ${command}:${param}`);
613
- // Handle the command setpassword from Settings
614
487
  if (command === 'setpassword') {
615
- const password = param.slice(1, -1); // Remove the first and last characters
488
+ const password = param.slice(1, -1);
616
489
  this.log.debug('setpassword', param, password);
617
490
  await this.matterbridge.nodeContext?.set('password', password);
618
491
  res.json({ message: 'Command received' });
619
492
  return;
620
493
  }
621
- // Handle the command setbridgemode from Settings
622
494
  if (command === 'setbridgemode') {
623
495
  this.log.debug(`setbridgemode: ${param}`);
624
496
  this.wssSendRestartRequired();
@@ -626,7 +498,6 @@ export class Frontend {
626
498
  res.json({ message: 'Command received' });
627
499
  return;
628
500
  }
629
- // Handle the command backup from Settings
630
501
  if (command === 'backup') {
631
502
  this.log.notice(`Prepairing the backup...`);
632
503
  await createZip(path.join(os.tmpdir(), `matterbridge.backup.zip`), path.join(this.matterbridge.matterbridgeDirectory), path.join(this.matterbridge.matterbridgePluginDirectory));
@@ -635,33 +506,31 @@ export class Frontend {
635
506
  res.json({ message: 'Command received' });
636
507
  return;
637
508
  }
638
- // Handle the command setmbloglevel from Settings
639
509
  if (command === 'setmbloglevel') {
640
510
  this.log.debug('Matterbridge log level:', param);
641
511
  if (param === 'Debug') {
642
- this.log.logLevel = "debug" /* LogLevel.DEBUG */;
512
+ this.log.logLevel = "debug";
643
513
  }
644
514
  else if (param === 'Info') {
645
- this.log.logLevel = "info" /* LogLevel.INFO */;
515
+ this.log.logLevel = "info";
646
516
  }
647
517
  else if (param === 'Notice') {
648
- this.log.logLevel = "notice" /* LogLevel.NOTICE */;
518
+ this.log.logLevel = "notice";
649
519
  }
650
520
  else if (param === 'Warn') {
651
- this.log.logLevel = "warn" /* LogLevel.WARN */;
521
+ this.log.logLevel = "warn";
652
522
  }
653
523
  else if (param === 'Error') {
654
- this.log.logLevel = "error" /* LogLevel.ERROR */;
524
+ this.log.logLevel = "error";
655
525
  }
656
526
  else if (param === 'Fatal') {
657
- this.log.logLevel = "fatal" /* LogLevel.FATAL */;
527
+ this.log.logLevel = "fatal";
658
528
  }
659
529
  await this.matterbridge.nodeContext?.set('matterbridgeLogLevel', this.log.logLevel);
660
530
  await this.matterbridge.setLogLevel(this.log.logLevel);
661
531
  res.json({ message: 'Command received' });
662
532
  return;
663
533
  }
664
- // Handle the command setmbloglevel from Settings
665
534
  if (command === 'setmjloglevel') {
666
535
  this.log.debug('Matter.js log level:', param);
667
536
  if (param === 'Debug') {
@@ -686,34 +555,30 @@ export class Frontend {
686
555
  res.json({ message: 'Command received' });
687
556
  return;
688
557
  }
689
- // Handle the command setmdnsinterface from Settings
690
558
  if (command === 'setmdnsinterface') {
691
- param = param.slice(1, -1); // Remove the first and last characters *mdns*
559
+ param = param.slice(1, -1);
692
560
  this.matterbridge.matterbridgeInformation.mattermdnsinterface = param;
693
561
  this.log.debug('Matter.js mdns interface:', param === '' ? 'All interfaces' : param);
694
562
  await this.matterbridge.nodeContext?.set('mattermdnsinterface', param);
695
563
  res.json({ message: 'Command received' });
696
564
  return;
697
565
  }
698
- // Handle the command setipv4address from Settings
699
566
  if (command === 'setipv4address') {
700
- param = param.slice(1, -1); // Remove the first and last characters *ip*
567
+ param = param.slice(1, -1);
701
568
  this.matterbridge.matterbridgeInformation.matteripv4address = param;
702
569
  this.log.debug('Matter.js ipv4 address:', param === '' ? 'All ipv4 addresses' : param);
703
570
  await this.matterbridge.nodeContext?.set('matteripv4address', param);
704
571
  res.json({ message: 'Command received' });
705
572
  return;
706
573
  }
707
- // Handle the command setipv6address from Settings
708
574
  if (command === 'setipv6address') {
709
- param = param.slice(1, -1); // Remove the first and last characters *ip*
575
+ param = param.slice(1, -1);
710
576
  this.matterbridge.matterbridgeInformation.matteripv6address = param;
711
577
  this.log.debug('Matter.js ipv6 address:', param === '' ? 'All ipv6 addresses' : param);
712
578
  await this.matterbridge.nodeContext?.set('matteripv6address', param);
713
579
  res.json({ message: 'Command received' });
714
580
  return;
715
581
  }
716
- // Handle the command setmatterport from Settings
717
582
  if (command === 'setmatterport') {
718
583
  const port = Math.min(Math.max(parseInt(param), 5540), 5560);
719
584
  this.matterbridge.matterbridgeInformation.matterPort = port;
@@ -722,7 +587,6 @@ export class Frontend {
722
587
  res.json({ message: 'Command received' });
723
588
  return;
724
589
  }
725
- // Handle the command setmatterdiscriminator from Settings
726
590
  if (command === 'setmatterdiscriminator') {
727
591
  const discriminator = Math.min(Math.max(parseInt(param), 1000), 4095);
728
592
  this.matterbridge.matterbridgeInformation.matterDiscriminator = discriminator;
@@ -731,7 +595,6 @@ export class Frontend {
731
595
  res.json({ message: 'Command received' });
732
596
  return;
733
597
  }
734
- // Handle the command setmatterpasscode from Settings
735
598
  if (command === 'setmatterpasscode') {
736
599
  const passcode = Math.min(Math.max(parseInt(param), 10000000), 90000000);
737
600
  this.matterbridge.matterbridgeInformation.matterPasscode = passcode;
@@ -740,20 +603,17 @@ export class Frontend {
740
603
  res.json({ message: 'Command received' });
741
604
  return;
742
605
  }
743
- // Handle the command setmbloglevel from Settings
744
606
  if (command === 'setmblogfile') {
745
607
  this.log.debug('Matterbridge file log:', param);
746
608
  this.matterbridge.matterbridgeInformation.fileLogger = param === 'true';
747
609
  await this.matterbridge.nodeContext?.set('matterbridgeFileLog', param === 'true');
748
- // Create the file logger for matterbridge
749
610
  if (param === 'true')
750
- AnsiLogger.setGlobalLogfile(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterbrideLoggerFile), "debug" /* LogLevel.DEBUG */, true);
611
+ AnsiLogger.setGlobalLogfile(path.join(this.matterbridge.matterbridgeDirectory, this.matterbridge.matterbrideLoggerFile), "debug", true);
751
612
  else
752
613
  AnsiLogger.setGlobalLogfile(undefined);
753
614
  res.json({ message: 'Command received' });
754
615
  return;
755
616
  }
756
- // Handle the command setmbloglevel from Settings
757
617
  if (command === 'setmjlogfile') {
758
618
  this.log.debug('Matter file log:', param);
759
619
  this.matterbridge.matterbridgeInformation.matterFileLogger = param === 'true';
@@ -780,48 +640,40 @@ export class Frontend {
780
640
  res.json({ message: 'Command received' });
781
641
  return;
782
642
  }
783
- // Handle the command unregister from Settings
784
643
  if (command === 'unregister') {
785
644
  await this.matterbridge.unregisterAndShutdownProcess();
786
645
  res.json({ message: 'Command received' });
787
646
  return;
788
647
  }
789
- // Handle the command reset from Settings
790
648
  if (command === 'reset') {
791
649
  await this.matterbridge.shutdownProcessAndReset();
792
650
  res.json({ message: 'Command received' });
793
651
  return;
794
652
  }
795
- // Handle the command factoryreset from Settings
796
653
  if (command === 'factoryreset') {
797
654
  await this.matterbridge.shutdownProcessAndFactoryReset();
798
655
  res.json({ message: 'Command received' });
799
656
  return;
800
657
  }
801
- // Handle the command shutdown from Header
802
658
  if (command === 'shutdown') {
803
659
  await this.matterbridge.shutdownProcess();
804
660
  res.json({ message: 'Command received' });
805
661
  return;
806
662
  }
807
- // Handle the command restart from Header
808
663
  if (command === 'restart') {
809
664
  await this.matterbridge.restartProcess();
810
665
  res.json({ message: 'Command received' });
811
666
  return;
812
667
  }
813
- // Handle the command update from Header
814
668
  if (command === 'update') {
815
669
  await this.matterbridge.updateProcess();
816
670
  this.wssSendRestartRequired();
817
671
  res.json({ message: 'Command received' });
818
672
  return;
819
673
  }
820
- // Handle the command saveconfig from Home
821
674
  if (command === 'saveconfig') {
822
675
  param = param.replace(/\*/g, '\\');
823
676
  this.log.info(`Saving config for plugin ${plg}${param}${nf}...`);
824
- // console.log('Req.body:', JSON.stringify(req.body, null, 2));
825
677
  if (!this.matterbridge.plugins.has(param)) {
826
678
  this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
827
679
  }
@@ -836,7 +688,6 @@ export class Frontend {
836
688
  res.json({ message: 'Command received' });
837
689
  return;
838
690
  }
839
- // Handle the command installplugin from Home
840
691
  if (command === 'installplugin') {
841
692
  param = param.replace(/\*/g, '\\');
842
693
  this.log.info(`Installing plugin ${plg}${param}${nf}...`);
@@ -845,7 +696,6 @@ export class Frontend {
845
696
  await this.matterbridge.spawnCommand('npm', ['install', '-g', param, '--omit=dev', '--verbose']);
846
697
  this.log.info(`Plugin ${plg}${param}${nf} installed. Full restart required.`);
847
698
  this.wssSendSnackbarMessage(`Installed package ${param}`, 10, 'success');
848
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
849
699
  }
850
700
  catch (error) {
851
701
  this.log.error(`Error installing plugin ${plg}${param}${er}`);
@@ -853,22 +703,17 @@ export class Frontend {
853
703
  }
854
704
  this.wssSendRestartRequired();
855
705
  param = param.split('@')[0];
856
- // Also add the plugin to matterbridge so no return!
857
706
  if (param === 'matterbridge') {
858
- // If we used the command installplugin to install a dev or a specific version of matterbridge we don't want to add it to matterbridge
859
707
  res.json({ message: 'Command received' });
860
708
  return;
861
709
  }
862
710
  }
863
- // Handle the command addplugin from Home
864
711
  if (command === 'addplugin' || command === 'installplugin') {
865
712
  param = param.replace(/\*/g, '\\');
866
713
  const plugin = await this.matterbridge.plugins.add(param);
867
714
  if (plugin) {
868
715
  this.wssSendSnackbarMessage(`Added plugin ${param}`);
869
716
  if (this.matterbridge.bridgeMode === 'childbridge') {
870
- // We don't know now if the plugin is a dynamic platform or an accessory platform so we create the server node and the aggregator node
871
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
872
717
  this.matterbridge.createDynamicPlugin(plugin, true);
873
718
  }
874
719
  this.matterbridge.plugins.load(plugin, true, 'The plugin has been added', true).then(() => {
@@ -878,14 +723,13 @@ export class Frontend {
878
723
  res.json({ message: 'Command received' });
879
724
  return;
880
725
  }
881
- // Handle the command removeplugin from Home
882
726
  if (command === 'removeplugin') {
883
727
  if (!this.matterbridge.plugins.has(param)) {
884
728
  this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
885
729
  }
886
730
  else {
887
731
  const plugin = this.matterbridge.plugins.get(param);
888
- await this.matterbridge.plugins.shutdown(plugin, 'The plugin has been removed.', true); // This will also close the server node in childbridge mode
732
+ await this.matterbridge.plugins.shutdown(plugin, 'The plugin has been removed.', true);
889
733
  await this.matterbridge.plugins.remove(param);
890
734
  this.wssSendSnackbarMessage(`Removed plugin ${param}`);
891
735
  this.wssSendRefreshRequired('plugins');
@@ -893,7 +737,6 @@ export class Frontend {
893
737
  res.json({ message: 'Command received' });
894
738
  return;
895
739
  }
896
- // Handle the command enableplugin from Home
897
740
  if (command === 'enableplugin') {
898
741
  if (!this.matterbridge.plugins.has(param)) {
899
742
  this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
@@ -912,7 +755,6 @@ export class Frontend {
912
755
  await this.matterbridge.plugins.enable(param);
913
756
  this.wssSendSnackbarMessage(`Enabled plugin ${param}`);
914
757
  if (this.matterbridge.bridgeMode === 'childbridge' && plugin.type === 'DynamicPlatform') {
915
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
916
758
  this.matterbridge.createDynamicPlugin(plugin, true);
917
759
  }
918
760
  this.matterbridge.plugins.load(plugin, true, 'The plugin has been enabled', true).then(() => {
@@ -923,7 +765,6 @@ export class Frontend {
923
765
  res.json({ message: 'Command received' });
924
766
  return;
925
767
  }
926
- // Handle the command disableplugin from Home
927
768
  if (command === 'disableplugin') {
928
769
  if (!this.matterbridge.plugins.has(param)) {
929
770
  this.log.warn(`Plugin ${plg}${param}${wr} not found in matterbridge`);
@@ -931,7 +772,7 @@ export class Frontend {
931
772
  else {
932
773
  const plugin = this.matterbridge.plugins.get(param);
933
774
  if (plugin && plugin.enabled) {
934
- await this.matterbridge.plugins.shutdown(plugin, 'The plugin has been disabled.', true); // This will also close the server node in childbridge mode
775
+ await this.matterbridge.plugins.shutdown(plugin, 'The plugin has been disabled.', true);
935
776
  await this.matterbridge.plugins.disable(param);
936
777
  this.wssSendSnackbarMessage(`Disabled plugin ${param}`);
937
778
  this.wssSendRefreshRequired('plugins');
@@ -950,13 +791,10 @@ export class Frontend {
950
791
  return;
951
792
  }
952
793
  this.wssSendSnackbarMessage(`Installing package ${filename}. Please wait...`);
953
- // Define the path where the plugin file will be saved
954
794
  const filePath = path.join(this.matterbridge.matterbridgeDirectory, 'uploads', filename);
955
795
  try {
956
- // Move the uploaded file to the specified path
957
796
  await fs.rename(file.path, filePath);
958
797
  this.log.info(`File ${plg}${filename}${nf} uploaded successfully`);
959
- // Install the plugin package
960
798
  if (filename.endsWith('.tgz')) {
961
799
  await this.matterbridge.spawnCommand('npm', ['install', '-g', filePath, '--omit=dev', '--verbose']);
962
800
  this.log.info(`Plugin package ${plg}${filename}${nf} installed successfully. Full restart required.`);
@@ -973,7 +811,6 @@ export class Frontend {
973
811
  res.status(500).send(`Error uploading or installing plugin package ${filename}`);
974
812
  }
975
813
  });
976
- // Fallback for routing (must be the last route)
977
814
  this.expressApp.get('*', (req, res) => {
978
815
  this.log.debug('The frontend sent:', req.url);
979
816
  this.log.debug('Response send file:', path.join(this.matterbridge.rootDirectory, 'frontend/build/index.html'));
@@ -982,31 +819,24 @@ export class Frontend {
982
819
  this.log.debug(`Frontend initialized on port ${YELLOW}${this.port}${db} static ${UNDERLINE}${path.join(this.matterbridge.rootDirectory, 'frontend/build')}${UNDERLINEOFF}${rs}`);
983
820
  }
984
821
  async stop() {
985
- // Remove all listeners from the cliEmitter
986
- // cliEmitter.removeAllListeners();
987
- // Close the http server
988
822
  if (this.httpServer) {
989
823
  this.httpServer.close();
990
824
  this.httpServer.removeAllListeners();
991
825
  this.httpServer = undefined;
992
826
  this.log.debug('Frontend http server closed successfully');
993
827
  }
994
- // Close the https server
995
828
  if (this.httpsServer) {
996
829
  this.httpsServer.close();
997
830
  this.httpsServer.removeAllListeners();
998
831
  this.httpsServer = undefined;
999
832
  this.log.debug('Frontend https server closed successfully');
1000
833
  }
1001
- // Remove listeners from the express app
1002
834
  if (this.expressApp) {
1003
835
  this.expressApp.removeAllListeners();
1004
836
  this.expressApp = undefined;
1005
837
  this.log.debug('Frontend app closed successfully');
1006
838
  }
1007
- // Close the WebSocket server
1008
839
  if (this.webSocketServer) {
1009
- // Close all active connections
1010
840
  this.webSocketServer.clients.forEach((client) => {
1011
841
  if (client.readyState === WebSocket.OPEN) {
1012
842
  client.close();
@@ -1023,7 +853,6 @@ export class Frontend {
1023
853
  this.webSocketServer = undefined;
1024
854
  }
1025
855
  }
1026
- // Function to format bytes to KB, MB, or GB
1027
856
  formatMemoryUsage = (bytes) => {
1028
857
  if (bytes >= 1024 ** 3) {
1029
858
  return `${(bytes / 1024 ** 3).toFixed(2)} GB`;
@@ -1035,7 +864,6 @@ export class Frontend {
1035
864
  return `${(bytes / 1024).toFixed(2)} KB`;
1036
865
  }
1037
866
  };
1038
- // Function to format system uptime with only the most significant unit
1039
867
  formatOsUpTime = (seconds) => {
1040
868
  if (seconds >= 86400) {
1041
869
  const days = Math.floor(seconds / 86400);
@@ -1051,13 +879,8 @@ export class Frontend {
1051
879
  }
1052
880
  return `${seconds} second${seconds !== 1 ? 's' : ''}`;
1053
881
  };
1054
- /**
1055
- * Retrieves the api settings data.
1056
- * @returns {Promise<object>} A promise that resolve in the api settings object.
1057
- */
1058
882
  async getApiSettings() {
1059
883
  const { lastCpuUsage } = await import('./cli.js');
1060
- // Update the system information
1061
884
  this.matterbridge.systemInformation.totalMemory = this.formatMemoryUsage(os.totalmem());
1062
885
  this.matterbridge.systemInformation.freeMemory = this.formatMemoryUsage(os.freemem());
1063
886
  this.matterbridge.systemInformation.systemUptime = this.formatOsUpTime(os.uptime());
@@ -1066,7 +889,6 @@ export class Frontend {
1066
889
  this.matterbridge.systemInformation.rss = this.formatMemoryUsage(process.memoryUsage().rss);
1067
890
  this.matterbridge.systemInformation.heapTotal = this.formatMemoryUsage(process.memoryUsage().heapTotal);
1068
891
  this.matterbridge.systemInformation.heapUsed = this.formatMemoryUsage(process.memoryUsage().heapUsed);
1069
- // Update the matterbridge information
1070
892
  this.matterbridge.matterbridgeInformation.bridgeMode = this.matterbridge.bridgeMode;
1071
893
  this.matterbridge.matterbridgeInformation.restartMode = this.matterbridge.restartMode;
1072
894
  this.matterbridge.matterbridgeInformation.loggerLevel = this.matterbridge.log.logLevel;
@@ -1085,11 +907,6 @@ export class Frontend {
1085
907
  this.matterbridge.matterbridgeInformation.profile = this.matterbridge.profile;
1086
908
  return { systemInformation: this.matterbridge.systemInformation, matterbridgeInformation: this.matterbridge.matterbridgeInformation };
1087
909
  }
1088
- /**
1089
- * Retrieves the reachable attribute.
1090
- * @param {MatterbridgeDevice} device - The MatterbridgeDevice object.
1091
- * @returns {boolean} The reachable attribute.
1092
- */
1093
910
  getReachability(device) {
1094
911
  if (!device.lifecycle.isReady || device.construction.status !== Lifecycle.Status.Active)
1095
912
  return false;
@@ -1099,11 +916,6 @@ export class Frontend {
1099
916
  return true;
1100
917
  return false;
1101
918
  }
1102
- /**
1103
- * Retrieves the cluster text description from a given device.
1104
- * @param {MatterbridgeDevice} device - The MatterbridgeDevice object.
1105
- * @returns {string} The attributes description of the cluster servers in the device.
1106
- */
1107
919
  getClusterTextFromDevice(device) {
1108
920
  if (!device.lifecycle.isReady || device.construction.status !== Lifecycle.Status.Active)
1109
921
  return '';
@@ -1144,7 +956,6 @@ export class Frontend {
1144
956
  };
1145
957
  let attributes = '';
1146
958
  device.forEachAttribute((clusterName, clusterId, attributeName, attributeId, attributeValue) => {
1147
- // console.log(`${device.deviceName} => Cluster: ${clusterName}-${clusterId} Attribute: ${attributeName}-${attributeId} Value(${typeof attributeValue}): ${attributeValue}`);
1148
959
  if (typeof attributeValue === 'undefined')
1149
960
  return;
1150
961
  if (clusterName === 'onOff' && attributeName === 'onOff')
@@ -1222,13 +1033,8 @@ export class Frontend {
1222
1033
  if (clusterName === 'userLabel' && attributeName === 'labelList')
1223
1034
  attributes += `${getUserLabel(device)} `;
1224
1035
  });
1225
- // console.log(`${device.deviceName}.forEachAttribute: ${attributes}`);
1226
1036
  return attributes.trimStart().trimEnd();
1227
1037
  }
1228
- /**
1229
- * Retrieves the base registered plugins sanitized for res.json().
1230
- * @returns {BaseRegisteredPlugin[]} An array of BaseRegisteredPlugin.
1231
- */
1232
1038
  getBaseRegisteredPlugins() {
1233
1039
  const baseRegisteredPlugins = [];
1234
1040
  for (const plugin of this.matterbridge.plugins) {
@@ -1261,13 +1067,6 @@ export class Frontend {
1261
1067
  }
1262
1068
  return baseRegisteredPlugins;
1263
1069
  }
1264
- /**
1265
- * Handles incoming websocket messages for the Matterbridge frontend.
1266
- *
1267
- * @param {WebSocket} client - The websocket client that sent the message.
1268
- * @param {WebSocket.RawData} message - The raw data of the message received from the client.
1269
- * @returns {Promise<void>} A promise that resolves when the message has been handled.
1270
- */
1271
1070
  async wsMessageHandler(client, message) {
1272
1071
  let data;
1273
1072
  try {
@@ -1413,10 +1212,8 @@ export class Frontend {
1413
1212
  else if (data.method === '/api/devices') {
1414
1213
  const devices = [];
1415
1214
  this.matterbridge.devices.forEach(async (device) => {
1416
- // Filter by pluginName if provided
1417
1215
  if (data.params.pluginName && data.params.pluginName !== device.plugin)
1418
1216
  return;
1419
- // Check if the device has the required properties
1420
1217
  if (!device.plugin || !device.name || !device.deviceName || !device.serialNumber || !device.uniqueId || !device.lifecycle.isReady)
1421
1218
  return;
1422
1219
  const cluster = this.getClusterTextFromDevice(device);
@@ -1500,7 +1297,6 @@ export class Frontend {
1500
1297
  });
1501
1298
  endpointServer.getChildEndpoints().forEach((childEndpoint) => {
1502
1299
  deviceTypes = [];
1503
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1504
1300
  const name = childEndpoint.endpoint?.id;
1505
1301
  const clusterServers = childEndpoint.getAllClusterServers();
1506
1302
  clusterServers.forEach((clusterServer) => {
@@ -1554,7 +1350,6 @@ export class Frontend {
1554
1350
  client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Plugin not found in /api/select' }));
1555
1351
  return;
1556
1352
  }
1557
- // const selectDeviceValues = plugin.platform?.selectDevice ? Array.from(plugin.platform.selectDevice.values()).sort((keyA, keyB) => keyA.name.localeCompare(keyB.name)) : [];
1558
1353
  const selectDeviceValues = plugin.platform?.getSelectDevices().sort((keyA, keyB) => keyA.name.localeCompare(keyB.name));
1559
1354
  client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, plugin: data.params.plugin, response: selectDeviceValues }));
1560
1355
  return;
@@ -1569,38 +1364,62 @@ export class Frontend {
1569
1364
  client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Plugin not found in /api/select/entities' }));
1570
1365
  return;
1571
1366
  }
1572
- // const selectEntityValues = plugin.platform?.selectDevice ? Array.from(plugin.platform.selectEntity.values()).sort((keyA, keyB) => keyA.name.localeCompare(keyB.name)) : [];
1573
1367
  const selectEntityValues = plugin.platform?.getSelectEntities().sort((keyA, keyB) => keyA.name.localeCompare(keyB.name));
1574
1368
  client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, plugin: data.params.plugin, response: selectEntityValues }));
1575
1369
  return;
1576
1370
  }
1371
+ else if (data.method === '/api/action') {
1372
+ if (!isValidString(data.params.plugin, 5) || !isValidString(data.params.action, 1)) {
1373
+ client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Wrong parameter command in /api/action' }));
1374
+ return;
1375
+ }
1376
+ const plugin = this.matterbridge.plugins.get(data.params.plugin);
1377
+ if (!plugin) {
1378
+ client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Plugin not found in /api/action' }));
1379
+ return;
1380
+ }
1381
+ plugin.platform?.onAction(data.params.action, data.params.value).catch((error) => {
1382
+ this.log.error(`Error in plugin ${plugin.name} action ${data.params.action}: ${error}`);
1383
+ });
1384
+ this.log.notice(`Action ${CYAN}${data.params.action}${nt}${data.params.value ? ' with ' + CYAN + data.params.value + nt : ''} for plugin ${CYAN}${plugin.name}${nt}`);
1385
+ }
1577
1386
  else if (data.method === '/api/command') {
1578
1387
  if (!isValidString(data.params.command, 5)) {
1579
1388
  client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Wrong parameter command in /api/command' }));
1580
1389
  return;
1581
1390
  }
1582
- if (data.params.command === 'selectdevice' && isValidString(data.params.plugin, 10) && isValidString(data.params.serial, 1)) {
1391
+ if (data.params.command === 'selectdevice' && isValidString(data.params.plugin, 10) && isValidString(data.params.serial, 1) && isValidString(data.params.name, 1)) {
1583
1392
  const plugin = this.matterbridge.plugins.get(data.params.plugin);
1584
1393
  if (!plugin) {
1585
1394
  client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Plugin not found in /api/command' }));
1586
1395
  return;
1587
1396
  }
1588
1397
  const config = plugin.configJson;
1589
- if (config) {
1398
+ const select = plugin.schemaJson?.properties?.blackList?.selectFrom;
1399
+ this.log.debug(`SelectDevice(selectMode ${select}) data ${debugStringify(data)}`);
1400
+ if (select === 'serial')
1401
+ this.log.info(`Selected device serial ${data.params.serial}`);
1402
+ if (select === 'name')
1403
+ this.log.info(`Selected device name ${data.params.name}`);
1404
+ if (config && select && (select === 'serial' || select === 'name')) {
1590
1405
  if (config.postfix) {
1591
1406
  data.params.serial = data.params.serial.replace('-' + config.postfix, '');
1592
1407
  }
1593
- // Add the serial to the whiteList if the whiteList exists and the serial is not already in it
1594
1408
  if (isValidArray(config.whiteList, 1)) {
1595
- if (!config.whiteList.includes(data.params.serial)) {
1409
+ if (select === 'serial' && !config.whiteList.includes(data.params.serial)) {
1596
1410
  config.whiteList.push(data.params.serial);
1597
1411
  }
1412
+ else if (select === 'name' && !config.whiteList.includes(data.params.name)) {
1413
+ config.whiteList.push(data.params.name);
1414
+ }
1598
1415
  }
1599
- // Remove the serial from the blackList if the blackList exists and the serial is in it
1600
1416
  if (isValidArray(config.blackList, 1)) {
1601
- if (config.blackList.includes(data.params.serial)) {
1417
+ if (select === 'serial' && config.blackList.includes(data.params.serial)) {
1602
1418
  config.blackList = config.blackList.filter((serial) => serial !== data.params.serial);
1603
1419
  }
1420
+ else if (select === 'name' && config.blackList.includes(data.params.name)) {
1421
+ config.blackList = config.blackList.filter((name) => name !== data.params.name);
1422
+ }
1604
1423
  }
1605
1424
  if (plugin.platform)
1606
1425
  plugin.platform.config = config;
@@ -1608,28 +1427,38 @@ export class Frontend {
1608
1427
  this.wssSendRestartRequired(false);
1609
1428
  }
1610
1429
  }
1611
- else if (data.params.command === 'unselectdevice' && isValidString(data.params.plugin, 10) && isValidString(data.params.serial, 1)) {
1430
+ else if (data.params.command === 'unselectdevice' && isValidString(data.params.plugin, 10) && isValidString(data.params.serial, 1) && isValidString(data.params.name, 1)) {
1612
1431
  const plugin = this.matterbridge.plugins.get(data.params.plugin);
1613
1432
  if (!plugin) {
1614
1433
  client.send(JSON.stringify({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Plugin not found in /api/command' }));
1615
1434
  return;
1616
1435
  }
1617
1436
  const config = plugin.configJson;
1618
- if (config) {
1437
+ const select = plugin.schemaJson?.properties?.blackList?.selectFrom;
1438
+ this.log.debug(`UnselectDevice(selectMode ${select}) data ${debugStringify(data)}`);
1439
+ if (select === 'serial')
1440
+ this.log.info(`Unselected device serial ${data.params.serial}`);
1441
+ if (select === 'name')
1442
+ this.log.info(`Unselected device name ${data.params.name}`);
1443
+ if (config && select && (select === 'serial' || select === 'name')) {
1619
1444
  if (config.postfix) {
1620
1445
  data.params.serial = data.params.serial.replace('-' + config.postfix, '');
1621
1446
  }
1622
- // Remove the serial from the whiteList if the whiteList exists and the serial is in it
1623
1447
  if (isValidArray(config.whiteList, 1)) {
1624
- if (config.whiteList.includes(data.params.serial)) {
1448
+ if (select === 'serial' && config.whiteList.includes(data.params.serial)) {
1625
1449
  config.whiteList = config.whiteList.filter((serial) => serial !== data.params.serial);
1626
1450
  }
1451
+ else if (select === 'name' && config.whiteList.includes(data.params.name)) {
1452
+ config.whiteList = config.whiteList.filter((name) => name !== data.params.name);
1453
+ }
1627
1454
  }
1628
- // Add the serial to the blackList
1629
1455
  if (isValidArray(config.blackList)) {
1630
- if (!config.blackList.includes(data.params.serial)) {
1456
+ if (select === 'serial' && !config.blackList.includes(data.params.serial)) {
1631
1457
  config.blackList.push(data.params.serial);
1632
1458
  }
1459
+ else if (select === 'name' && !config.blackList.includes(data.params.name)) {
1460
+ config.blackList.push(data.params.name);
1461
+ }
1633
1462
  }
1634
1463
  if (plugin.platform)
1635
1464
  plugin.platform.config = config;
@@ -1649,194 +1478,102 @@ export class Frontend {
1649
1478
  return;
1650
1479
  }
1651
1480
  }
1652
- /**
1653
- * Sends a WebSocket message to all connected clients. The function is called by AnsiLogger.setGlobalCallback.
1654
- *
1655
- * @param {string} level - The logger level of the message: debug info notice warn error fatal...
1656
- * @param {string} time - The time string of the message
1657
- * @param {string} name - The logger name of the message
1658
- * @param {string} message - The content of the message.
1659
- */
1660
1481
  wssSendMessage(level, time, name, message) {
1661
1482
  if (!level || !time || !name || !message)
1662
1483
  return;
1663
- // Remove ANSI escape codes from the message
1664
- // eslint-disable-next-line no-control-regex
1665
1484
  message = message.replace(/\x1B\[[0-9;]*[m|s|u|K]/g, '');
1666
- // Remove leading asterisks from the message
1667
1485
  message = message.replace(/^\*+/, '');
1668
- // Replace all occurrences of \t and \n
1669
1486
  message = message.replace(/[\t\n]/g, '');
1670
- // Remove non-printable characters
1671
- // eslint-disable-next-line no-control-regex
1672
1487
  message = message.replace(/[\x00-\x1F\x7F]/g, '');
1673
- // Replace all occurrences of \" with "
1674
1488
  message = message.replace(/\\"/g, '"');
1675
- // Define the maximum allowed length for continuous characters without a space
1676
1489
  const maxContinuousLength = 100;
1677
1490
  const keepStartLength = 20;
1678
1491
  const keepEndLength = 20;
1679
- // Split the message into words
1680
1492
  message = message
1681
1493
  .split(' ')
1682
1494
  .map((word) => {
1683
- // If the word length exceeds the max continuous length, insert spaces and truncate
1684
1495
  if (word.length > maxContinuousLength) {
1685
1496
  return word.slice(0, keepStartLength) + ' ... ' + word.slice(-keepEndLength);
1686
1497
  }
1687
1498
  return word;
1688
1499
  })
1689
1500
  .join(' ');
1690
- // Send the message to all connected clients
1691
1501
  this.webSocketServer?.clients.forEach((client) => {
1692
1502
  if (client.readyState === WebSocket.OPEN) {
1693
1503
  client.send(JSON.stringify({ id: WS_ID_LOG, src: 'Matterbridge', level, time, name, message }));
1694
1504
  }
1695
1505
  });
1696
1506
  }
1697
- /**
1698
- * Sends a need to refresh WebSocket message to all connected clients.
1699
- *
1700
- * @param {string} changed - The changed value. If null, the whole page will be refreshed.
1701
- * possible values:
1702
- * - 'matterbridgeLatestVersion'
1703
- * - 'matterbridgeAdvertise'
1704
- * - 'online'
1705
- * - 'offline'
1706
- * - 'reachability'
1707
- * - 'settings'
1708
- * - 'plugins'
1709
- * - 'devices'
1710
- * - 'fabrics'
1711
- * - 'sessions'
1712
- */
1713
1507
  wssSendRefreshRequired(changed = null) {
1714
1508
  this.log.debug('Sending a refresh required message to all connected clients');
1715
- // Send the message to all connected clients
1716
1509
  this.webSocketServer?.clients.forEach((client) => {
1717
1510
  if (client.readyState === WebSocket.OPEN) {
1718
1511
  client.send(JSON.stringify({ id: WS_ID_REFRESH_NEEDED, src: 'Matterbridge', dst: 'Frontend', method: 'refresh_required', params: { changed: changed } }));
1719
1512
  }
1720
1513
  });
1721
1514
  }
1722
- /**
1723
- * Sends a need to restart WebSocket message to all connected clients.
1724
- *
1725
- */
1726
1515
  wssSendRestartRequired(snackbar = true) {
1727
1516
  this.log.debug('Sending a restart required message to all connected clients');
1728
1517
  this.matterbridge.matterbridgeInformation.restartRequired = true;
1729
1518
  if (snackbar === true)
1730
1519
  this.wssSendSnackbarMessage(`Restart required`, 0);
1731
- // Send the message to all connected clients
1732
1520
  this.webSocketServer?.clients.forEach((client) => {
1733
1521
  if (client.readyState === WebSocket.OPEN) {
1734
1522
  client.send(JSON.stringify({ id: WS_ID_RESTART_NEEDED, src: 'Matterbridge', dst: 'Frontend', method: 'restart_required', params: {} }));
1735
1523
  }
1736
1524
  });
1737
1525
  }
1738
- /**
1739
- * Sends a need to update WebSocket message to all connected clients.
1740
- *
1741
- */
1742
1526
  wssSendUpdateRequired() {
1743
1527
  this.log.debug('Sending an update required message to all connected clients');
1744
1528
  this.matterbridge.matterbridgeInformation.updateRequired = true;
1745
- // Send the message to all connected clients
1746
1529
  this.webSocketServer?.clients.forEach((client) => {
1747
1530
  if (client.readyState === WebSocket.OPEN) {
1748
1531
  client.send(JSON.stringify({ id: WS_ID_UPDATE_NEEDED, src: 'Matterbridge', dst: 'Frontend', method: 'update_required', params: {} }));
1749
1532
  }
1750
1533
  });
1751
1534
  }
1752
- /**
1753
- * Sends a memory update message to all connected clients.
1754
- *
1755
- */
1756
1535
  wssSendCpuUpdate(cpuUsage) {
1757
1536
  this.log.debug('Sending a cpu update message to all connected clients');
1758
- // Send the message to all connected clients
1759
1537
  this.webSocketServer?.clients.forEach((client) => {
1760
1538
  if (client.readyState === WebSocket.OPEN) {
1761
1539
  client.send(JSON.stringify({ id: WS_ID_CPU_UPDATE, src: 'Matterbridge', dst: 'Frontend', method: 'cpu_update', params: { cpuUsage } }));
1762
1540
  }
1763
1541
  });
1764
1542
  }
1765
- /**
1766
- * Sends a cpu update message to all connected clients.
1767
- *
1768
- */
1769
1543
  wssSendMemoryUpdate(totalMemory, freeMemory, rss, heapTotal, heapUsed, external, arrayBuffers) {
1770
1544
  this.log.debug('Sending a memory update message to all connected clients');
1771
- // Send the message to all connected clients
1772
1545
  this.webSocketServer?.clients.forEach((client) => {
1773
1546
  if (client.readyState === WebSocket.OPEN) {
1774
1547
  client.send(JSON.stringify({ id: WS_ID_MEMORY_UPDATE, src: 'Matterbridge', dst: 'Frontend', method: 'memory_update', params: { totalMemory, freeMemory, rss, heapTotal, heapUsed, external, arrayBuffers } }));
1775
1548
  }
1776
1549
  });
1777
1550
  }
1778
- /**
1779
- * Sends a memory update message to all connected clients.
1780
- *
1781
- */
1782
1551
  wssSendUptimeUpdate(systemUptime, processUptime) {
1783
1552
  this.log.debug('Sending a uptime update message to all connected clients');
1784
- // Send the message to all connected clients
1785
1553
  this.webSocketServer?.clients.forEach((client) => {
1786
1554
  if (client.readyState === WebSocket.OPEN) {
1787
1555
  client.send(JSON.stringify({ id: WS_ID_UPTIME_UPDATE, src: 'Matterbridge', dst: 'Frontend', method: 'uptime_update', params: { systemUptime, processUptime } }));
1788
1556
  }
1789
1557
  });
1790
1558
  }
1791
- /**
1792
- * Sends a cpu update message to all connected clients.
1793
- * @param {string} message - The message to send.
1794
- * @param {number} timeout - The timeout in seconds for the snackbar message.
1795
- * @param {'info' | 'warning' | 'error' | 'success'} severity - The severity of the snackbar message (default info).
1796
- *
1797
- */
1798
1559
  wssSendSnackbarMessage(message, timeout = 5, severity = 'info') {
1799
1560
  this.log.debug('Sending a snackbar message to all connected clients');
1800
- // Send the message to all connected clients
1801
1561
  this.webSocketServer?.clients.forEach((client) => {
1802
1562
  if (client.readyState === WebSocket.OPEN) {
1803
1563
  client.send(JSON.stringify({ id: WS_ID_SNACKBAR, src: 'Matterbridge', dst: 'Frontend', method: 'memory_update', params: { message, timeout, severity } }));
1804
1564
  }
1805
1565
  });
1806
1566
  }
1807
- /**
1808
- * Sends an attribute update message to all connected WebSocket clients.
1809
- *
1810
- * @param {string | undefined} plugin - The name of the plugin.
1811
- * @param {string | undefined} serialNumber - The serial number of the device.
1812
- * @param {string | undefined} uniqueId - The unique identifier of the device.
1813
- * @param {string} cluster - The cluster name where the attribute belongs.
1814
- * @param {string} attribute - The name of the attribute that changed.
1815
- * @param {number | string | boolean} value - The new value of the attribute.
1816
- *
1817
- * @remarks
1818
- * This method logs a debug message and sends a JSON-formatted message to all connected WebSocket clients
1819
- * with the updated attribute information.
1820
- */
1821
1567
  wssSendAttributeChangedMessage(plugin, serialNumber, uniqueId, cluster, attribute, value) {
1822
1568
  this.log.debug('Sending an attribute update message to all connected clients');
1823
- // Send the message to all connected clients
1824
1569
  this.webSocketServer?.clients.forEach((client) => {
1825
1570
  if (client.readyState === WebSocket.OPEN) {
1826
1571
  client.send(JSON.stringify({ id: WS_ID_STATEUPDATE, src: 'Matterbridge', dst: 'Frontend', method: 'state_update', params: { plugin, serialNumber, uniqueId, cluster, attribute, value } }));
1827
1572
  }
1828
1573
  });
1829
1574
  }
1830
- /**
1831
- * Sends a message to all connected clients.
1832
- * @param {number} id - The message id.
1833
- * @param {string} method - The message method.
1834
- * @param {Record<string, string | number | boolean>} params - The message parameters.
1835
- *
1836
- */
1837
1575
  wssBroadcastMessage(id, method, params) {
1838
1576
  this.log.debug(`Sending a broadcast message id ${id} method ${method} params ${debugStringify(params ?? {})} to all connected clients`);
1839
- // Send the message to all connected clients
1840
1577
  this.webSocketServer?.clients.forEach((client) => {
1841
1578
  if (client.readyState === WebSocket.OPEN) {
1842
1579
  client.send(JSON.stringify({ id, src: 'Matterbridge', dst: 'Frontend', method, params }));
@@ -1844,4 +1581,3 @@ export class Frontend {
1844
1581
  });
1845
1582
  }
1846
1583
  }
1847
- //# sourceMappingURL=frontend.js.map