matterbridge 3.4.2 → 3.4.3-dev-20251207-3ce5a0e

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 (332) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README-SERVICE-LOCAL.md +3 -3
  3. package/README-SERVICE-OPT.md +3 -5
  4. package/README.md +8 -14
  5. package/dist/broadcastServer.js +0 -119
  6. package/dist/broadcastServerTypes.js +0 -24
  7. package/dist/cli.js +3 -97
  8. package/dist/cliEmitter.js +0 -37
  9. package/dist/cliHistory.js +0 -38
  10. package/dist/clusters/export.js +0 -2
  11. package/dist/deviceManager.js +1 -113
  12. package/dist/devices/airConditioner.js +0 -57
  13. package/dist/devices/batteryStorage.js +1 -48
  14. package/dist/devices/cooktop.js +0 -56
  15. package/dist/devices/dishwasher.js +0 -57
  16. package/dist/devices/evse.js +10 -74
  17. package/dist/devices/export.js +0 -5
  18. package/dist/devices/extractorHood.js +0 -43
  19. package/dist/devices/heatPump.js +2 -50
  20. package/dist/devices/laundryDryer.js +3 -62
  21. package/dist/devices/laundryWasher.js +4 -70
  22. package/dist/devices/microwaveOven.js +5 -88
  23. package/dist/devices/oven.js +0 -85
  24. package/dist/devices/refrigerator.js +0 -102
  25. package/dist/devices/roboticVacuumCleaner.js +9 -100
  26. package/dist/devices/solarPower.js +0 -38
  27. package/dist/devices/speaker.js +0 -84
  28. package/dist/devices/temperatureControl.js +3 -24
  29. package/dist/devices/waterHeater.js +2 -82
  30. package/dist/dgram/coap.js +13 -126
  31. package/dist/dgram/dgram.js +2 -114
  32. package/dist/dgram/mb_coap.js +3 -41
  33. package/dist/dgram/mb_mdns.js +15 -80
  34. package/dist/dgram/mdns.js +137 -299
  35. package/dist/dgram/multicast.js +1 -62
  36. package/dist/dgram/unicast.js +0 -54
  37. package/dist/frontend.js +35 -455
  38. package/dist/frontendTypes.js +0 -45
  39. package/dist/helpers.js +0 -53
  40. package/dist/index.js +0 -25
  41. package/dist/jestutils/export.js +0 -1
  42. package/dist/jestutils/jestHelpers.js +14 -371
  43. package/dist/logger/export.js +0 -1
  44. package/dist/matter/behaviors.js +0 -2
  45. package/dist/matter/clusters.js +0 -2
  46. package/dist/matter/devices.js +0 -2
  47. package/dist/matter/endpoints.js +0 -2
  48. package/dist/matter/export.js +0 -3
  49. package/dist/matter/types.js +0 -3
  50. package/dist/matterNode.js +8 -369
  51. package/dist/matterbridge.js +54 -817
  52. package/dist/matterbridgeAccessoryPlatform.js +0 -38
  53. package/dist/matterbridgeBehaviors.js +5 -68
  54. package/dist/matterbridgeDeviceTypes.js +14 -635
  55. package/dist/matterbridgeDynamicPlatform.js +0 -38
  56. package/dist/matterbridgeEndpoint.js +53 -1444
  57. package/dist/matterbridgeEndpointHelpers.js +20 -483
  58. package/dist/matterbridgeEndpointTypes.js +0 -25
  59. package/dist/matterbridgePlatform.js +1 -451
  60. package/dist/matterbridgeTypes.js +0 -26
  61. package/dist/pluginManager.js +5 -341
  62. package/dist/shelly.js +7 -178
  63. package/dist/storage/export.js +0 -1
  64. package/dist/update.js +1 -93
  65. package/dist/utils/colorUtils.js +2 -97
  66. package/dist/utils/commandLine.js +0 -60
  67. package/dist/utils/copyDirectory.js +0 -37
  68. package/dist/utils/createDirectory.js +0 -33
  69. package/dist/utils/createZip.js +2 -47
  70. package/dist/utils/deepCopy.js +0 -39
  71. package/dist/utils/deepEqual.js +1 -72
  72. package/dist/utils/error.js +0 -42
  73. package/dist/utils/export.js +0 -1
  74. package/dist/utils/format.js +0 -49
  75. package/dist/utils/hex.js +0 -124
  76. package/dist/utils/inspector.js +1 -69
  77. package/dist/utils/isvalid.js +0 -101
  78. package/dist/utils/network.js +5 -96
  79. package/dist/utils/spawn.js +1 -71
  80. package/dist/utils/tracker.js +1 -64
  81. package/dist/utils/wait.js +8 -60
  82. package/dist/workerGlobalPrefix.js +5 -37
  83. package/dist/workerTypes.js +0 -24
  84. package/dist/workers.js +4 -68
  85. package/frontend/build/assets/index.js +4 -4
  86. package/frontend/build/assets/vendor_mui.js +1 -1
  87. package/frontend/package.json +1 -1
  88. package/npm-shrinkwrap.json +8 -7
  89. package/package.json +3 -4
  90. package/scripts/marked.mjs +132 -0
  91. package/scripts/markedFooter.html +42 -0
  92. package/scripts/markedHeader.html +78 -0
  93. package/dist/broadcastServer.d.ts +0 -144
  94. package/dist/broadcastServer.d.ts.map +0 -1
  95. package/dist/broadcastServer.js.map +0 -1
  96. package/dist/broadcastServerTypes.d.ts +0 -841
  97. package/dist/broadcastServerTypes.d.ts.map +0 -1
  98. package/dist/broadcastServerTypes.js.map +0 -1
  99. package/dist/cli.d.ts +0 -30
  100. package/dist/cli.d.ts.map +0 -1
  101. package/dist/cli.js.map +0 -1
  102. package/dist/cliEmitter.d.ts +0 -50
  103. package/dist/cliEmitter.d.ts.map +0 -1
  104. package/dist/cliEmitter.js.map +0 -1
  105. package/dist/cliHistory.d.ts +0 -48
  106. package/dist/cliHistory.d.ts.map +0 -1
  107. package/dist/cliHistory.js.map +0 -1
  108. package/dist/clusters/export.d.ts +0 -2
  109. package/dist/clusters/export.d.ts.map +0 -1
  110. package/dist/clusters/export.js.map +0 -1
  111. package/dist/deviceManager.d.ts +0 -135
  112. package/dist/deviceManager.d.ts.map +0 -1
  113. package/dist/deviceManager.js.map +0 -1
  114. package/dist/devices/airConditioner.d.ts +0 -98
  115. package/dist/devices/airConditioner.d.ts.map +0 -1
  116. package/dist/devices/airConditioner.js.map +0 -1
  117. package/dist/devices/batteryStorage.d.ts +0 -48
  118. package/dist/devices/batteryStorage.d.ts.map +0 -1
  119. package/dist/devices/batteryStorage.js.map +0 -1
  120. package/dist/devices/cooktop.d.ts +0 -61
  121. package/dist/devices/cooktop.d.ts.map +0 -1
  122. package/dist/devices/cooktop.js.map +0 -1
  123. package/dist/devices/dishwasher.d.ts +0 -71
  124. package/dist/devices/dishwasher.d.ts.map +0 -1
  125. package/dist/devices/dishwasher.js.map +0 -1
  126. package/dist/devices/evse.d.ts +0 -76
  127. package/dist/devices/evse.d.ts.map +0 -1
  128. package/dist/devices/evse.js.map +0 -1
  129. package/dist/devices/export.d.ts +0 -17
  130. package/dist/devices/export.d.ts.map +0 -1
  131. package/dist/devices/export.js.map +0 -1
  132. package/dist/devices/extractorHood.d.ts +0 -46
  133. package/dist/devices/extractorHood.d.ts.map +0 -1
  134. package/dist/devices/extractorHood.js.map +0 -1
  135. package/dist/devices/heatPump.d.ts +0 -47
  136. package/dist/devices/heatPump.d.ts.map +0 -1
  137. package/dist/devices/heatPump.js.map +0 -1
  138. package/dist/devices/laundryDryer.d.ts +0 -67
  139. package/dist/devices/laundryDryer.d.ts.map +0 -1
  140. package/dist/devices/laundryDryer.js.map +0 -1
  141. package/dist/devices/laundryWasher.d.ts +0 -81
  142. package/dist/devices/laundryWasher.d.ts.map +0 -1
  143. package/dist/devices/laundryWasher.js.map +0 -1
  144. package/dist/devices/microwaveOven.d.ts +0 -168
  145. package/dist/devices/microwaveOven.d.ts.map +0 -1
  146. package/dist/devices/microwaveOven.js.map +0 -1
  147. package/dist/devices/oven.d.ts +0 -105
  148. package/dist/devices/oven.d.ts.map +0 -1
  149. package/dist/devices/oven.js.map +0 -1
  150. package/dist/devices/refrigerator.d.ts +0 -118
  151. package/dist/devices/refrigerator.d.ts.map +0 -1
  152. package/dist/devices/refrigerator.js.map +0 -1
  153. package/dist/devices/roboticVacuumCleaner.d.ts +0 -112
  154. package/dist/devices/roboticVacuumCleaner.d.ts.map +0 -1
  155. package/dist/devices/roboticVacuumCleaner.js.map +0 -1
  156. package/dist/devices/solarPower.d.ts +0 -40
  157. package/dist/devices/solarPower.d.ts.map +0 -1
  158. package/dist/devices/solarPower.js.map +0 -1
  159. package/dist/devices/speaker.d.ts +0 -87
  160. package/dist/devices/speaker.d.ts.map +0 -1
  161. package/dist/devices/speaker.js.map +0 -1
  162. package/dist/devices/temperatureControl.d.ts +0 -166
  163. package/dist/devices/temperatureControl.d.ts.map +0 -1
  164. package/dist/devices/temperatureControl.js.map +0 -1
  165. package/dist/devices/waterHeater.d.ts +0 -111
  166. package/dist/devices/waterHeater.d.ts.map +0 -1
  167. package/dist/devices/waterHeater.js.map +0 -1
  168. package/dist/dgram/coap.d.ts +0 -205
  169. package/dist/dgram/coap.d.ts.map +0 -1
  170. package/dist/dgram/coap.js.map +0 -1
  171. package/dist/dgram/dgram.d.ts +0 -141
  172. package/dist/dgram/dgram.d.ts.map +0 -1
  173. package/dist/dgram/dgram.js.map +0 -1
  174. package/dist/dgram/mb_coap.d.ts +0 -24
  175. package/dist/dgram/mb_coap.d.ts.map +0 -1
  176. package/dist/dgram/mb_coap.js.map +0 -1
  177. package/dist/dgram/mb_mdns.d.ts +0 -24
  178. package/dist/dgram/mb_mdns.d.ts.map +0 -1
  179. package/dist/dgram/mb_mdns.js.map +0 -1
  180. package/dist/dgram/mdns.d.ts +0 -290
  181. package/dist/dgram/mdns.d.ts.map +0 -1
  182. package/dist/dgram/mdns.js.map +0 -1
  183. package/dist/dgram/multicast.d.ts +0 -67
  184. package/dist/dgram/multicast.d.ts.map +0 -1
  185. package/dist/dgram/multicast.js.map +0 -1
  186. package/dist/dgram/unicast.d.ts +0 -56
  187. package/dist/dgram/unicast.d.ts.map +0 -1
  188. package/dist/dgram/unicast.js.map +0 -1
  189. package/dist/frontend.d.ts +0 -238
  190. package/dist/frontend.d.ts.map +0 -1
  191. package/dist/frontend.js.map +0 -1
  192. package/dist/frontendTypes.d.ts +0 -529
  193. package/dist/frontendTypes.d.ts.map +0 -1
  194. package/dist/frontendTypes.js.map +0 -1
  195. package/dist/helpers.d.ts +0 -48
  196. package/dist/helpers.d.ts.map +0 -1
  197. package/dist/helpers.js.map +0 -1
  198. package/dist/index.d.ts +0 -34
  199. package/dist/index.d.ts.map +0 -1
  200. package/dist/index.js.map +0 -1
  201. package/dist/jestutils/export.d.ts +0 -2
  202. package/dist/jestutils/export.d.ts.map +0 -1
  203. package/dist/jestutils/export.js.map +0 -1
  204. package/dist/jestutils/jestHelpers.d.ts +0 -345
  205. package/dist/jestutils/jestHelpers.d.ts.map +0 -1
  206. package/dist/jestutils/jestHelpers.js.map +0 -1
  207. package/dist/logger/export.d.ts +0 -2
  208. package/dist/logger/export.d.ts.map +0 -1
  209. package/dist/logger/export.js.map +0 -1
  210. package/dist/matter/behaviors.d.ts +0 -2
  211. package/dist/matter/behaviors.d.ts.map +0 -1
  212. package/dist/matter/behaviors.js.map +0 -1
  213. package/dist/matter/clusters.d.ts +0 -2
  214. package/dist/matter/clusters.d.ts.map +0 -1
  215. package/dist/matter/clusters.js.map +0 -1
  216. package/dist/matter/devices.d.ts +0 -2
  217. package/dist/matter/devices.d.ts.map +0 -1
  218. package/dist/matter/devices.js.map +0 -1
  219. package/dist/matter/endpoints.d.ts +0 -2
  220. package/dist/matter/endpoints.d.ts.map +0 -1
  221. package/dist/matter/endpoints.js.map +0 -1
  222. package/dist/matter/export.d.ts +0 -5
  223. package/dist/matter/export.d.ts.map +0 -1
  224. package/dist/matter/export.js.map +0 -1
  225. package/dist/matter/types.d.ts +0 -3
  226. package/dist/matter/types.d.ts.map +0 -1
  227. package/dist/matter/types.js.map +0 -1
  228. package/dist/matterNode.d.ts +0 -342
  229. package/dist/matterNode.d.ts.map +0 -1
  230. package/dist/matterNode.js.map +0 -1
  231. package/dist/matterbridge.d.ts +0 -492
  232. package/dist/matterbridge.d.ts.map +0 -1
  233. package/dist/matterbridge.js.map +0 -1
  234. package/dist/matterbridgeAccessoryPlatform.d.ts +0 -41
  235. package/dist/matterbridgeAccessoryPlatform.d.ts.map +0 -1
  236. package/dist/matterbridgeAccessoryPlatform.js.map +0 -1
  237. package/dist/matterbridgeBehaviors.d.ts +0 -2404
  238. package/dist/matterbridgeBehaviors.d.ts.map +0 -1
  239. package/dist/matterbridgeBehaviors.js.map +0 -1
  240. package/dist/matterbridgeDeviceTypes.d.ts +0 -698
  241. package/dist/matterbridgeDeviceTypes.d.ts.map +0 -1
  242. package/dist/matterbridgeDeviceTypes.js.map +0 -1
  243. package/dist/matterbridgeDynamicPlatform.d.ts +0 -41
  244. package/dist/matterbridgeDynamicPlatform.d.ts.map +0 -1
  245. package/dist/matterbridgeDynamicPlatform.js.map +0 -1
  246. package/dist/matterbridgeEndpoint.d.ts +0 -1507
  247. package/dist/matterbridgeEndpoint.d.ts.map +0 -1
  248. package/dist/matterbridgeEndpoint.js.map +0 -1
  249. package/dist/matterbridgeEndpointHelpers.d.ts +0 -787
  250. package/dist/matterbridgeEndpointHelpers.d.ts.map +0 -1
  251. package/dist/matterbridgeEndpointHelpers.js.map +0 -1
  252. package/dist/matterbridgeEndpointTypes.d.ts +0 -166
  253. package/dist/matterbridgeEndpointTypes.d.ts.map +0 -1
  254. package/dist/matterbridgeEndpointTypes.js.map +0 -1
  255. package/dist/matterbridgePlatform.d.ts +0 -539
  256. package/dist/matterbridgePlatform.d.ts.map +0 -1
  257. package/dist/matterbridgePlatform.js.map +0 -1
  258. package/dist/matterbridgeTypes.d.ts +0 -251
  259. package/dist/matterbridgeTypes.d.ts.map +0 -1
  260. package/dist/matterbridgeTypes.js.map +0 -1
  261. package/dist/pluginManager.d.ts +0 -372
  262. package/dist/pluginManager.d.ts.map +0 -1
  263. package/dist/pluginManager.js.map +0 -1
  264. package/dist/shelly.d.ts +0 -181
  265. package/dist/shelly.d.ts.map +0 -1
  266. package/dist/shelly.js.map +0 -1
  267. package/dist/storage/export.d.ts +0 -2
  268. package/dist/storage/export.d.ts.map +0 -1
  269. package/dist/storage/export.js.map +0 -1
  270. package/dist/update.d.ts +0 -84
  271. package/dist/update.d.ts.map +0 -1
  272. package/dist/update.js.map +0 -1
  273. package/dist/utils/colorUtils.d.ts +0 -101
  274. package/dist/utils/colorUtils.d.ts.map +0 -1
  275. package/dist/utils/colorUtils.js.map +0 -1
  276. package/dist/utils/commandLine.d.ts +0 -66
  277. package/dist/utils/commandLine.d.ts.map +0 -1
  278. package/dist/utils/commandLine.js.map +0 -1
  279. package/dist/utils/copyDirectory.d.ts +0 -35
  280. package/dist/utils/copyDirectory.d.ts.map +0 -1
  281. package/dist/utils/copyDirectory.js.map +0 -1
  282. package/dist/utils/createDirectory.d.ts +0 -34
  283. package/dist/utils/createDirectory.d.ts.map +0 -1
  284. package/dist/utils/createDirectory.js.map +0 -1
  285. package/dist/utils/createZip.d.ts +0 -39
  286. package/dist/utils/createZip.d.ts.map +0 -1
  287. package/dist/utils/createZip.js.map +0 -1
  288. package/dist/utils/deepCopy.d.ts +0 -32
  289. package/dist/utils/deepCopy.d.ts.map +0 -1
  290. package/dist/utils/deepCopy.js.map +0 -1
  291. package/dist/utils/deepEqual.d.ts +0 -54
  292. package/dist/utils/deepEqual.d.ts.map +0 -1
  293. package/dist/utils/deepEqual.js.map +0 -1
  294. package/dist/utils/error.d.ts +0 -45
  295. package/dist/utils/error.d.ts.map +0 -1
  296. package/dist/utils/error.js.map +0 -1
  297. package/dist/utils/export.d.ts +0 -13
  298. package/dist/utils/export.d.ts.map +0 -1
  299. package/dist/utils/export.js.map +0 -1
  300. package/dist/utils/format.d.ts +0 -53
  301. package/dist/utils/format.d.ts.map +0 -1
  302. package/dist/utils/format.js.map +0 -1
  303. package/dist/utils/hex.d.ts +0 -89
  304. package/dist/utils/hex.d.ts.map +0 -1
  305. package/dist/utils/hex.js.map +0 -1
  306. package/dist/utils/inspector.d.ts +0 -87
  307. package/dist/utils/inspector.d.ts.map +0 -1
  308. package/dist/utils/inspector.js.map +0 -1
  309. package/dist/utils/isvalid.d.ts +0 -103
  310. package/dist/utils/isvalid.d.ts.map +0 -1
  311. package/dist/utils/isvalid.js.map +0 -1
  312. package/dist/utils/network.d.ts +0 -111
  313. package/dist/utils/network.d.ts.map +0 -1
  314. package/dist/utils/network.js.map +0 -1
  315. package/dist/utils/spawn.d.ts +0 -33
  316. package/dist/utils/spawn.d.ts.map +0 -1
  317. package/dist/utils/spawn.js.map +0 -1
  318. package/dist/utils/tracker.d.ts +0 -108
  319. package/dist/utils/tracker.d.ts.map +0 -1
  320. package/dist/utils/tracker.js.map +0 -1
  321. package/dist/utils/wait.d.ts +0 -54
  322. package/dist/utils/wait.d.ts.map +0 -1
  323. package/dist/utils/wait.js.map +0 -1
  324. package/dist/workerGlobalPrefix.d.ts +0 -25
  325. package/dist/workerGlobalPrefix.d.ts.map +0 -1
  326. package/dist/workerGlobalPrefix.js.map +0 -1
  327. package/dist/workerTypes.d.ts +0 -52
  328. package/dist/workerTypes.d.ts.map +0 -1
  329. package/dist/workerTypes.js.map +0 -1
  330. package/dist/workers.d.ts +0 -69
  331. package/dist/workers.d.ts.map +0 -1
  332. package/dist/workers.js.map +0 -1
@@ -1,35 +1,8 @@
1
- /**
2
- * This file contains the class MatterNode.
3
- *
4
- * @file matterNode.ts
5
- * @author Luca Liguori
6
- * @created 2025-10-01
7
- * @version 1.0.0
8
- * @license Apache-2.0
9
- *
10
- * Copyright 2025, 2026, 2027 Luca Liguori.
11
- *
12
- * Licensed under the Apache License, Version 2.0 (the "License");
13
- * you may not use this file except in compliance with the License.
14
- * You may obtain a copy of the License at
15
- *
16
- * http://www.apache.org/licenses/LICENSE-2.0
17
- *
18
- * Unless required by applicable law or agreed to in writing, software
19
- * distributed under the License is distributed on an "AS IS" BASIS,
20
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21
- * See the License for the specific language governing permissions and
22
- * limitations under the License.
23
- */
24
- // Node modules
25
1
  import path from 'node:path';
26
2
  import fs from 'node:fs';
27
3
  import EventEmitter from 'node:events';
28
- // AnsiLogger module
29
4
  import { AnsiLogger, BLUE, CYAN, db, debugStringify, er, nf, or, zb } from 'node-ansi-logger';
30
- // Node persist manager module
31
5
  import { NodeStorageManager } from 'node-persist-manager';
32
- // @matter
33
6
  import '@matter/nodejs';
34
7
  import { Logger, LogLevel as MatterLogLevel, LogFormat as MatterLogFormat, StorageService, UINT32_MAX, UINT16_MAX, Environment } from '@matter/general';
35
8
  import { FabricAction, MdnsService } from '@matter/protocol';
@@ -49,48 +22,27 @@ import { BroadcastServer } from './broadcastServer.js';
49
22
  import { toBaseDevice } from './deviceManager.js';
50
23
  import { PluginManager } from './pluginManager.js';
51
24
  import { addVirtualDevice } from './helpers.js';
52
- /**
53
- * Represents the Matter class.
54
- */
55
25
  export class MatterNode extends EventEmitter {
56
26
  matterbridge;
57
27
  pluginName;
58
28
  device;
59
- /** Matterbridge logger */
60
- log = new AnsiLogger({ logName: 'MatterNode', logTimestampFormat: 4 /* TimestampFormat.TIME_MILLIS */, logLevel: "debug" /* LogLevel.DEBUG */ });
61
- /** Matter logger */
62
- matterLog = new AnsiLogger({ logName: 'MatterNode', logTimestampFormat: 4 /* TimestampFormat.TIME_MILLIS */, logLevel: "debug" /* LogLevel.DEBUG */ });
63
- /** Matter environment default */
29
+ log = new AnsiLogger({ logName: 'MatterNode', logTimestampFormat: 4, logLevel: "debug" });
30
+ matterLog = new AnsiLogger({ logName: 'MatterNode', logTimestampFormat: 4, logLevel: "debug" });
64
31
  environment = Environment.default;
65
- /** Matter storage id */
66
32
  storeId;
67
- /** Matter mdns service from environment default */
68
33
  matterMdnsService;
69
- /** Matter storage service from environment default */
70
34
  matterStorageService;
71
- /** Matter storage manager created with name 'Matterbridge' */
72
35
  matterStorageManager;
73
- /** Matter storage context created in the storage manager with name 'persist' */
74
36
  matterStorageContext;
75
- /** Matter mdns interface name e.g. 'eth0' or 'wlan0' or 'Wi-Fi' */
76
37
  mdnsInterface;
77
- /** Matter listeningAddressIpv4 address */
78
38
  ipv4Address;
79
- /** Matter listeningAddressIpv6 address */
80
39
  ipv6Address;
81
- /** Matter commissioning port It is incremented in childbridge mode. */
82
40
  port;
83
- /** Matter commissioning passcode. It is incremented in childbridge mode. */
84
41
  passcode;
85
- /** Matter commissioning discriminator. It is incremented in childbridge mode. */
86
42
  discriminator;
87
- /** Matter device certification */
88
43
  certification;
89
- /** Matter server node */
90
44
  serverNode;
91
- /** Matter aggregator node */
92
45
  aggregatorNode;
93
- // Default values for the aggregator node
94
46
  aggregatorVendorId = VendorId(getIntParameter('vendorId') ?? 0xfff1);
95
47
  aggregatorVendorName = getParameter('vendorName') ?? 'Matterbridge';
96
48
  aggregatorProductId = getIntParameter('productId') ?? 0x8000;
@@ -98,23 +50,12 @@ export class MatterNode extends EventEmitter {
98
50
  aggregatorDeviceType = DeviceTypeId(getIntParameter('deviceType') ?? bridge.code);
99
51
  aggregatorSerialNumber = getParameter('serialNumber');
100
52
  aggregatorUniqueId = getParameter('uniqueId');
101
- /** Advertising nodes map: time advertising started keyed by storeId */
102
53
  advertisingNodes = new Map();
103
- /** Plugins */
104
54
  pluginManager;
105
- /** Dependant MatterNodes keyed by device id */
106
55
  dependantMatterNodes = new Map();
107
- /** Broadcast server */
108
56
  server;
109
57
  debug = hasParameter('debug') || hasParameter('verbose');
110
58
  verbose = hasParameter('verbose');
111
- /**
112
- * Creates an instance of the Matter class.
113
- *
114
- * @param {SharedMatterbridge} matterbridge - The shared matterbridge instance.
115
- * @param {PluginName} [pluginName] - The plugin name (optional). If not provided, it is assumed to be the main matter node instance and all plugins are included.
116
- * @param {MatterbridgeEndpoint} [device] - The matterbridge endpoint device (optional). It is used to create a server mode device.
117
- */
118
59
  constructor(matterbridge, pluginName, device) {
119
60
  super();
120
61
  this.matterbridge = matterbridge;
@@ -127,16 +68,12 @@ export class MatterNode extends EventEmitter {
127
68
  this.server.on('broadcast_message', this.msgHandler.bind(this));
128
69
  if (this.verbose)
129
70
  this.log.debug(`BroadcastServer is ready`);
130
- // Ensure the matterbridge directory exists
131
71
  fs.mkdirSync(matterbridge.matterbridgeDirectory, { recursive: true });
132
- // Setup the plugin manager with thread server closed
133
72
  this.pluginManager = new PluginManager(this.matterbridge);
134
- this.pluginManager.logLevel = this.debug ? "debug" /* LogLevel.DEBUG */ : "info" /* LogLevel.INFO */;
135
- // @ts-expect-error access private property
73
+ this.pluginManager.logLevel = this.debug ? "debug" : "info";
136
74
  this.pluginManager.server.close();
137
75
  if (this.verbose)
138
76
  this.log.debug(`PluginManager is ready`);
139
- // Setup the matter environment
140
77
  this.environment.vars.set('log.level', MatterLogLevel.DEBUG);
141
78
  this.environment.vars.set('log.format', MatterLogFormat.ANSI);
142
79
  this.environment.vars.set('path.root', path.join(matterbridge.matterbridgeDirectory, MATTER_STORAGE_NAME));
@@ -144,20 +81,9 @@ export class MatterNode extends EventEmitter {
144
81
  this.environment.vars.set('runtime.exitcode', false);
145
82
  if (this.verbose)
146
83
  this.log.debug(`Matter Environment is ready`);
147
- // Ensure MdnsService is registered in the default environment
148
- // this.matterMdnsService = this.environment.get(MdnsService);
149
- /*
150
- this.matterMdnsService = new MdnsService(this.environment);
151
- setImmediate(async () => {
152
- await this.matterMdnsService?.construction.ready;
153
- if (this.verbose) this.log.debug(`Matter MdnsService is ready`);
154
- });
155
- */
156
- // Setup the matterbridge logger
157
84
  if (this.matterbridge.fileLogger) {
158
85
  AnsiLogger.setGlobalLogfile(path.join(this.matterbridge.matterbridgeDirectory, MATTERBRIDGE_LOGGER_FILE), this.matterbridge.logLevel);
159
86
  }
160
- // Setup the matter logger
161
87
  Logger.destinations.default.write = this.createDestinationMatterLogger();
162
88
  const levels = ['debug', 'info', 'notice', 'warn', 'error', 'fatal'];
163
89
  if (this.verbose)
@@ -165,11 +91,6 @@ export class MatterNode extends EventEmitter {
165
91
  if (this.debug)
166
92
  this.log.debug(`MatterNode ${this.pluginName ? 'for plugin ' + this.pluginName : 'bridge'} loaded`);
167
93
  }
168
- /**
169
- * Handles incoming messages from the broadcast server.
170
- *
171
- * @param {WorkerMessage} msg - The incoming message.
172
- */
173
94
  async msgHandler(msg) {
174
95
  if (this.server.isWorkerRequest(msg) && (msg.dst === 'all' || msg.dst === 'matter')) {
175
96
  if (this.verbose)
@@ -200,52 +121,32 @@ export class MatterNode extends EventEmitter {
200
121
  }
201
122
  }
202
123
  }
203
- /**
204
- * Destroys the Matter instance.
205
- * It closes the mDNS service and the broadcast server.
206
- *
207
- * @param {boolean} closeMdns - Whether to close the mDNS service. Default is true.
208
- * @returns {Promise<void>} A promise that resolves when the instance is destroyed.
209
- */
210
124
  async destroy(closeMdns = true) {
211
125
  if (this.verbose)
212
126
  this.log.debug(`Destroying MatterNode instance for ${this.storeId}...`);
213
- // Close mDNS service
214
127
  if (closeMdns) {
215
128
  if (this.verbose)
216
129
  this.log.debug(`Closing Matter MdnsService for ${this.storeId}...`);
217
130
  this.matterMdnsService = this.environment.get(MdnsService);
218
- // istanbul ignore next
219
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
220
131
  if (typeof this.matterMdnsService[Symbol.asyncDispose] === 'function')
221
132
  await this.matterMdnsService[Symbol.asyncDispose]();
222
- // istanbul ignore next
223
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
224
133
  else
225
134
  await this.matterMdnsService.close();
226
135
  if (this.verbose)
227
136
  this.log.debug(`Closed Matter MdnsService for ${this.storeId}`);
228
137
  }
229
- // Close the plugin manager
230
138
  this.pluginManager.destroy();
231
- // Close the broadcast server
232
139
  this.server.close();
233
- // Yield to the Node.js event loop to allow all resources to be released
234
140
  await this.yieldToNode();
235
141
  if (this.verbose)
236
142
  this.log.debug(`Destroyed MatterNode instance for ${this.storeId}`);
237
143
  }
238
144
  async create() {
239
145
  this.log.info('Creating Matter node...');
240
- // Start matter storage
241
146
  await this.startMatterStorage();
242
- // Load plugins from storage
243
- // @ts-expect-error access private property
244
147
  this.pluginManager.matterbridge.nodeStorage = new NodeStorageManager({ dir: path.join(this.matterbridge.matterbridgeDirectory, NODE_STORAGE_DIR), writeQueue: false, expiredInterval: undefined, logging: false });
245
- // @ts-expect-error access private property
246
148
  this.pluginManager.matterbridge.nodeContext = await this.pluginManager.matterbridge.nodeStorage.createStorage('matterbridge');
247
149
  await this.pluginManager.loadFromStorage();
248
- // Create Matter node for a server mode device
249
150
  if (this.pluginName && this.device && this.device.deviceName) {
250
151
  this.log.debug(`Creating MatterNode instance for server node device ${CYAN}${this.device.deviceName}${db}...`);
251
152
  await this.createDeviceServerNode(this.pluginName, this.device);
@@ -256,7 +157,6 @@ export class MatterNode extends EventEmitter {
256
157
  if (!this.pluginName) {
257
158
  this.log.debug('Creating MatterNode instance for all plugins...');
258
159
  await this.createMatterbridgeServerNode();
259
- // Load all enabled plugins
260
160
  this.log.debug('Loading all plugins...');
261
161
  const loadPromises = [];
262
162
  for (const plugin of this.pluginManager.array().filter((p) => p.enabled)) {
@@ -269,7 +169,6 @@ export class MatterNode extends EventEmitter {
269
169
  }
270
170
  else {
271
171
  this.log.debug(`Creating MatterNode instance for plugin ${CYAN}${this.pluginName}${db}...`);
272
- // Load only the specified plugin
273
172
  this.log.debug(`Loading plugin ${CYAN}${this.pluginName}${db}...`);
274
173
  await this.pluginManager.load(this.pluginName);
275
174
  this.log.debug(`Loaded plugin ${CYAN}${this.pluginName}${db}`);
@@ -283,16 +182,13 @@ export class MatterNode extends EventEmitter {
283
182
  if (!this.serverNode && !this.pluginName)
284
183
  throw new Error('Matter server node not created yet. Call create() first.');
285
184
  this.log.info('Starting MatterNode...');
286
- // Start Matter node for a server mode device
287
185
  if (this.pluginName && this.device && this.device.deviceName) {
288
- // Start the server node
289
186
  this.log.debug(`Starting MatterNode for server device ${this.pluginName}:${this.device.deviceName}...`);
290
187
  await this.startServerNode();
291
188
  this.log.debug(`Started MatterNode for server device ${this.pluginName}:${this.device.deviceName}`);
292
189
  return;
293
190
  }
294
191
  if (!this.pluginName) {
295
- // Start all loaded plugins
296
192
  this.log.debug('Starting all plugins...');
297
193
  const startPromises = [];
298
194
  for (const plugin of this.pluginManager.array().filter((p) => p.enabled && p.loaded)) {
@@ -300,11 +196,9 @@ export class MatterNode extends EventEmitter {
300
196
  }
301
197
  await Promise.all(startPromises);
302
198
  this.log.debug('Started all plugins');
303
- // Start the server node
304
199
  this.log.debug('Starting MatterNode for all plugins...');
305
200
  await this.startServerNode();
306
201
  this.log.debug('Started MatterNode for all plugins');
307
- // Configure all loaded plugins
308
202
  this.log.debug('Configuring all plugins...');
309
203
  const configurePromises = [];
310
204
  for (const plugin of this.pluginManager.array().filter((p) => p.enabled && p.started)) {
@@ -314,16 +208,12 @@ export class MatterNode extends EventEmitter {
314
208
  this.log.debug('Configured all plugins');
315
209
  }
316
210
  else {
317
- // Start the loaded plugin
318
211
  await this.pluginManager.start(this.pluginName, 'Starting MatterNode');
319
- // Start the server node
320
212
  this.log.debug(`Starting MatterNode for plugin ${this.pluginName}...`);
321
213
  await this.startServerNode();
322
214
  this.log.debug(`Started MatterNode for plugin ${this.pluginName}`);
323
- // Configure the plugin
324
215
  await this.pluginManager.configure(this.pluginName);
325
216
  }
326
- // Start the dependant MatterNodes
327
217
  this.log.debug(`Starting dependant MatterNodes...`);
328
218
  for (const dependantMatterNode of this.dependantMatterNodes.values()) {
329
219
  await dependantMatterNode.start();
@@ -336,15 +226,13 @@ export class MatterNode extends EventEmitter {
336
226
  if (!this.serverNode)
337
227
  throw new Error('Matter server node not created yet. Call create() first.');
338
228
  this.log.info('Stopping MatterNode...');
339
- // Stop Matter node for a server mode device
340
229
  if (this.pluginName && this.device && this.device.deviceName) {
341
- // Stop the server node
342
230
  this.log.debug(`Stopping MatterNode for server device ${this.pluginName}:${this.device.deviceName}...`);
343
231
  await this.stopServerNode();
344
232
  this.serverNode = undefined;
345
233
  this.aggregatorNode = undefined;
346
234
  await this.stopMatterStorage();
347
- await this.destroy(false); // Do not close mDNS since it is shared
235
+ await this.destroy(false);
348
236
  this.log.debug(`Stopped MatterNode for server device ${this.pluginName}:${this.device.deviceName}`);
349
237
  this.log.info('Stopped MatterNode');
350
238
  await this.yieldToNode();
@@ -364,7 +252,6 @@ export class MatterNode extends EventEmitter {
364
252
  await this.pluginManager.shutdown(this.pluginName, 'Stopping MatterNode');
365
253
  this.log.debug(`Stopped plugin ${this.pluginName}`);
366
254
  }
367
- // Stop the dependant MatterNodes
368
255
  this.log.debug(`Stopping dependant MatterNodes...`);
369
256
  for (const dependantMatterNode of this.dependantMatterNodes.values()) {
370
257
  await dependantMatterNode.stop();
@@ -377,46 +264,24 @@ export class MatterNode extends EventEmitter {
377
264
  this.log.info('Stopped MatterNode');
378
265
  await this.yieldToNode();
379
266
  }
380
- /**
381
- * Creates a MatterLogger function to show the matter.js log messages in AnsiLogger (console and frontend).
382
- * It also logs to file (matter.log) if fileLogger is true.
383
- *
384
- * @returns {Function} The MatterLogger function. \x1b[35m for violet \x1b[34m is blue
385
- */
386
267
  createDestinationMatterLogger() {
387
- this.matterLog.logNameColor = '\x1b[34m'; // Blue matter.js Logger
268
+ this.matterLog.logNameColor = '\x1b[34m';
388
269
  if (this.matterbridge.matterFileLogger) {
389
270
  this.matterLog.logFilePath = path.join(this.matterbridge.matterbridgeDirectory, MATTER_LOGGER_FILE);
390
271
  }
391
272
  return (text, message) => {
392
- // 2024-08-21 08:55:19.488 DEBUG InteractionMessenger Sending DataReport chunk with 28 attributes and 0 events: 1004 bytes
393
273
  const logger = text.slice(44, 44 + 20).trim();
394
274
  const msg = text.slice(65);
395
275
  this.matterLog.logName = logger;
396
276
  this.matterLog.log(MatterLogLevel.names[message.level], msg);
397
277
  };
398
278
  }
399
- /**
400
- * Starts the matter storage with name Matterbridge and performs a backup.
401
- *
402
- * @returns {Promise<void>} - A promise that resolves when the storage is started.
403
- */
404
279
  async startMatterStorage() {
405
- // Setup Matter storage
406
280
  this.log.info(`Starting matter node storage...`);
407
281
  this.matterStorageService = this.environment.get(StorageService);
408
282
  this.log.info(`Started matter node storage in ${CYAN}${this.matterStorageService.location}${nf}`);
409
- // Backup matter storage since it is created/opened correctly
410
283
  await this.backupMatterStorage(path.join(this.matterbridge.matterbridgeDirectory, MATTER_STORAGE_NAME), path.join(this.matterbridge.matterbridgeDirectory, MATTER_STORAGE_NAME + '.backup'));
411
284
  }
412
- /**
413
- * Makes a backup copy of the specified matter storage directory.
414
- *
415
- * @param {string} storageName - The name of the storage directory to be backed up.
416
- * @param {string} backupName - The name of the backup directory to be created.
417
- * @private
418
- * @returns {Promise<void>} A promise that resolves when the has been done.
419
- */
420
285
  async backupMatterStorage(storageName, backupName) {
421
286
  this.log.info(`Creating matter node storage backup from ${CYAN}${storageName}${nf} to ${CYAN}${backupName}${nf}...`);
422
287
  try {
@@ -424,7 +289,6 @@ export class MatterNode extends EventEmitter {
424
289
  this.log.info('Created matter node storage backup');
425
290
  }
426
291
  catch (error) {
427
- // istanbul ignore next if
428
292
  if (error instanceof Error && error?.code === 'ENOENT') {
429
293
  this.log.info(`No matter node storage found to backup from ${CYAN}${storageName}${nf} to ${CYAN}${backupName}${nf}`);
430
294
  }
@@ -433,11 +297,6 @@ export class MatterNode extends EventEmitter {
433
297
  }
434
298
  }
435
299
  }
436
- /**
437
- * Stops the matter storage.
438
- *
439
- * @returns {Promise<void>} A promise that resolves when the storage is stopped.
440
- */
441
300
  async stopMatterStorage() {
442
301
  this.log.info('Closing matter node storage...');
443
302
  await this.matterStorageManager?.close();
@@ -447,21 +306,6 @@ export class MatterNode extends EventEmitter {
447
306
  this.log.info('Closed matter node storage');
448
307
  this.emit('closed');
449
308
  }
450
- /**
451
- * Creates a server node storage context.
452
- *
453
- * @param {string} storeId - The storeId.
454
- * @param {string} deviceName - The name of the device.
455
- * @param {DeviceTypeId} deviceType - The device type of the device.
456
- * @param {VendorId} vendorId - The vendor ID.
457
- * @param {string} vendorName - The vendor name.
458
- * @param {number} productId - The product ID.
459
- * @param {string} productName - The product name.
460
- * @param {string} [serialNumber] - The serial number of the device (optional).
461
- * @param {string} [uniqueId] - The unique ID of the device (optional).
462
- * @returns {Promise<StorageContext>} The storage context for the commissioning server.
463
- * @throws {Error} If the storage service is not initialized.
464
- */
465
309
  async createServerNodeContext(storeId, deviceName, deviceType, vendorId, vendorName, productId, productName, serialNumber, uniqueId) {
466
310
  if (!this.matterStorageService) {
467
311
  throw new Error('No storage service initialized');
@@ -504,52 +348,33 @@ export class MatterNode extends EventEmitter {
504
348
  this.log.debug(`- hardwareVersionString: ${await storageContext.get('hardwareVersionString')}`);
505
349
  return storageContext;
506
350
  }
507
- /**
508
- * Creates a server node.
509
- *
510
- * @param {number} [port] - The port number for the server node. Defaults to 5540.
511
- * @param {number} [passcode] - The passcode for the server node. Defaults to 20242025.
512
- * @param {number} [discriminator] - The discriminator for the server node. Defaults to 3850.
513
- * @returns {Promise<ServerNode<ServerNode.RootEndpoint>>} A promise that resolves to the created server node.
514
- * @throws {Error} If the matter storage context is not created yet.
515
- */
516
351
  async createServerNode(port = 5540, passcode = 20252026, discriminator = 3850) {
517
352
  if (!this.matterStorageContext) {
518
353
  throw new Error('Matter server node context not created yet. Call createServerNodeContext() first.');
519
354
  }
520
355
  const storeId = await this.matterStorageContext.get('storeId');
521
356
  this.log.notice(`Creating server node for ${storeId} on port ${port} with passcode ${passcode} and discriminator ${discriminator}...`);
522
- /**
523
- * Create a Matter ServerNode, which contains the Root Endpoint and all relevant data and configuration
524
- */
525
357
  const serverNode = await ServerNode.create({
526
- // Required: Give the Node a unique ID which is used to store the state of this node
527
358
  id: storeId,
528
- // Provide the environment to run this node in
529
359
  environment: this.environment,
530
- // Provide Network relevant configuration like the port
531
360
  network: {
532
361
  listeningAddressIpv4: this.ipv4Address,
533
362
  listeningAddressIpv6: this.ipv6Address,
534
363
  port,
535
364
  },
536
- // Provide the certificate for the device
537
365
  operationalCredentials: {
538
366
  certification: this.certification,
539
367
  },
540
- // Provide Commissioning relevant settings
541
368
  commissioning: {
542
369
  passcode,
543
370
  discriminator,
544
371
  },
545
- // Provide Node announcement settings
546
372
  productDescription: {
547
373
  name: await this.matterStorageContext.get('deviceName'),
548
374
  deviceType: DeviceTypeId(await this.matterStorageContext.get('deviceType')),
549
375
  vendorId: VendorId(await this.matterStorageContext.get('vendorId')),
550
376
  productId: await this.matterStorageContext.get('productId'),
551
377
  },
552
- // Provide defaults for the BasicInformation cluster on the Root endpoint
553
378
  basicInformation: {
554
379
  vendorId: VendorId(await this.matterStorageContext.get('vendorId')),
555
380
  vendorName: await this.matterStorageContext.get('vendorName'),
@@ -566,23 +391,17 @@ export class MatterNode extends EventEmitter {
566
391
  reachable: true,
567
392
  },
568
393
  });
569
- /**
570
- * This event is triggered when the device is initially commissioned successfully.
571
- * This means: It is added to the first fabric.
572
- */
573
394
  serverNode.lifecycle.commissioned.on(() => {
574
395
  this.log.notice(`Server node for ${storeId} was initially commissioned successfully!`);
575
396
  this.advertisingNodes.delete(storeId);
576
397
  this.server.request({ type: 'frontend_refreshrequired', src: 'matter', dst: 'frontend', params: { changed: 'matter', matter: { ...this.getServerNodeData(serverNode) } } });
577
398
  });
578
- /** This event is triggered when all fabrics are removed from the device, usually it also does a factory reset then. */
579
399
  serverNode.lifecycle.decommissioned.on(() => {
580
400
  this.log.notice(`Server node for ${storeId} was fully decommissioned successfully!`);
581
401
  this.advertisingNodes.delete(storeId);
582
402
  this.server.request({ type: 'frontend_refreshrequired', src: 'matter', dst: 'frontend', params: { changed: 'matter', matter: { ...this.getServerNodeData(serverNode) } } });
583
403
  this.server.request({ type: 'frontend_snackbarmessage', src: 'matter', dst: 'frontend', params: { message: `${storeId} is offline`, timeout: 5, severity: 'warning' } });
584
404
  });
585
- /** This event is triggered when the device went online. This means that it is discoverable in the network. */
586
405
  serverNode.lifecycle.online.on(async () => {
587
406
  this.log.notice(`Server node for ${storeId} is online`);
588
407
  if (!serverNode.lifecycle.isCommissioned) {
@@ -600,7 +419,6 @@ export class MatterNode extends EventEmitter {
600
419
  this.server.request({ type: 'frontend_snackbarmessage', src: 'matter', dst: 'frontend', params: { message: `${storeId} is online`, timeout: 5, severity: 'success' } });
601
420
  this.emit('online', storeId);
602
421
  });
603
- /** This event is triggered when the device went offline. it is not longer discoverable or connectable in the network. */
604
422
  serverNode.lifecycle.offline.on(() => {
605
423
  this.log.notice(`Server node for ${storeId} is offline`);
606
424
  this.advertisingNodes.delete(storeId);
@@ -608,15 +426,11 @@ export class MatterNode extends EventEmitter {
608
426
  this.server.request({ type: 'frontend_snackbarmessage', src: 'matter', dst: 'frontend', params: { message: `${storeId} is offline`, timeout: 5, severity: 'warning' } });
609
427
  this.emit('offline', storeId);
610
428
  });
611
- /**
612
- * This event is triggered when a fabric is added, removed or updated on the device. Use this if more granular
613
- * information is needed.
614
- */
615
429
  serverNode.events.commissioning.fabricsChanged.on((fabricIndex, fabricAction) => {
616
430
  let action = '';
617
431
  switch (fabricAction) {
618
432
  case FabricAction.Added:
619
- this.advertisingNodes.delete(storeId); // The advertising stops when a fabric is added
433
+ this.advertisingNodes.delete(storeId);
620
434
  action = 'added';
621
435
  break;
622
436
  case FabricAction.Removed:
@@ -629,22 +443,14 @@ export class MatterNode extends EventEmitter {
629
443
  this.log.notice(`Commissioned fabric index ${fabricIndex} ${action} on server node for ${storeId}: ${debugStringify(serverNode.state.commissioning.fabrics[fabricIndex])}`);
630
444
  this.server.request({ type: 'frontend_refreshrequired', src: 'matter', dst: 'frontend', params: { changed: 'matter', matter: { ...this.getServerNodeData(serverNode) } } });
631
445
  });
632
- /**
633
- * This event is triggered when an operative new session was opened by a Controller.
634
- * It is not triggered for the initial commissioning process, just afterwards for real connections.
635
- */
636
446
  serverNode.events.sessions.opened.on((session) => {
637
447
  this.log.notice(`Session opened on server node for ${storeId}: ${debugStringify(session)}`);
638
448
  this.server.request({ type: 'frontend_refreshrequired', src: 'matter', dst: 'frontend', params: { changed: 'matter', matter: { ...this.getServerNodeData(serverNode) } } });
639
449
  });
640
- /**
641
- * This event is triggered when an operative session is closed by a Controller or because the Device goes offline.
642
- */
643
450
  serverNode.events.sessions.closed.on((session) => {
644
451
  this.log.notice(`Session closed on server node for ${storeId}: ${debugStringify(session)}`);
645
452
  this.server.request({ type: 'frontend_refreshrequired', src: 'matter', dst: 'frontend', params: { changed: 'matter', matter: { ...this.getServerNodeData(serverNode) } } });
646
453
  });
647
- /** This event is triggered when a subscription gets added or removed on an operative session. */
648
454
  serverNode.events.sessions.subscriptionsChanged.on((session) => {
649
455
  this.log.notice(`Session subscriptions changed on server node for ${storeId}: ${debugStringify(session)}`);
650
456
  this.server.request({ type: 'frontend_refreshrequired', src: 'matter', dst: 'frontend', params: { changed: 'matter', matter: { ...this.getServerNodeData(serverNode) } } });
@@ -653,12 +459,6 @@ export class MatterNode extends EventEmitter {
653
459
  this.log.info(`Created server node for ${this.storeId}`);
654
460
  return serverNode;
655
461
  }
656
- /**
657
- * Gets the matter serializable data of the specified server node.
658
- *
659
- * @param {ServerNode} [serverNode] - The server node to start.
660
- * @returns {ApiMatter} The serializable data of the server node.
661
- */
662
462
  getServerNodeData(serverNode) {
663
463
  const advertiseTime = this.advertisingNodes.get(serverNode.id) || 0;
664
464
  return {
@@ -675,13 +475,6 @@ export class MatterNode extends EventEmitter {
675
475
  serialNumber: serverNode.state.basicInformation.serialNumber,
676
476
  };
677
477
  }
678
- /**
679
- * Starts the specified server node.
680
- *
681
- * @param {number} [timeout] - The timeout in milliseconds for starting the server node. Defaults to 30 seconds.
682
- * @returns {Promise<void>} A promise that resolves when the server node has started.
683
- * @throws {Error} If the server node is not created yet.
684
- */
685
478
  async startServerNode(timeout = 30000) {
686
479
  if (!this.serverNode) {
687
480
  throw new Error('Matter server node not created yet. Call create() first.');
@@ -692,17 +485,9 @@ export class MatterNode extends EventEmitter {
692
485
  this.log.notice(`Started ${this.serverNode.id} server node`);
693
486
  }
694
487
  catch (error) {
695
- // istanbul ignore next
696
488
  this.log.error(`Failed to start ${this.serverNode.id} server node: ${error instanceof Error ? error.message : error}`);
697
489
  }
698
490
  }
699
- /**
700
- * Stops the specified server node.
701
- *
702
- * @param {number} [timeout] - The timeout in milliseconds for stopping the server node. Defaults to 30 seconds.
703
- * @returns {Promise<void>} A promise that resolves when the server node has stopped.
704
- * @throws {Error} If the server node is not created yet.
705
- */
706
491
  async stopServerNode(timeout = 30000) {
707
492
  if (!this.serverNode) {
708
493
  throw new Error('Matter server node not created yet. Call create() first.');
@@ -713,16 +498,9 @@ export class MatterNode extends EventEmitter {
713
498
  this.log.info(`Closed ${this.serverNode.id} server node`);
714
499
  }
715
500
  catch (error) {
716
- // istanbul ignore next
717
501
  this.log.error(`Failed to close ${this.serverNode.id} server node: ${error instanceof Error ? error.message : error}`);
718
502
  }
719
503
  }
720
- /**
721
- * Creates an aggregator node with the specified storage context.
722
- *
723
- * @returns {Promise<Endpoint<AggregatorEndpoint>>} A promise that resolves to the created aggregator node.
724
- * @throws {Error} If the matter storage context is not created yet.
725
- */
726
504
  async createAggregatorNode() {
727
505
  if (!this.matterStorageContext) {
728
506
  throw new Error('Matter server node context not created yet. Call createServerNodeContext() first.');
@@ -732,16 +510,9 @@ export class MatterNode extends EventEmitter {
732
510
  this.log.info(`Created ${await this.matterStorageContext.get('storeId')} aggregator`);
733
511
  return aggregatorNode;
734
512
  }
735
- /**
736
- * Creates the matterbridge server node.
737
- *
738
- * @returns {Promise<ServerNode<ServerNode.RootEndpoint>>} A promise that resolves to the created matterbridge server node.
739
- */
740
513
  async createMatterbridgeServerNode() {
741
514
  this.log.debug(`Creating ${plg}Matterbridge${db} server node...`);
742
- this.matterStorageContext = await this.createServerNodeContext('Matterbridge', // storeId
743
- 'Matterbridge', // deviceName
744
- this.aggregatorDeviceType, this.aggregatorVendorId, this.aggregatorVendorName, this.aggregatorProductId, this.aggregatorProductName, this.aggregatorSerialNumber, this.aggregatorUniqueId);
515
+ this.matterStorageContext = await this.createServerNodeContext('Matterbridge', 'Matterbridge', this.aggregatorDeviceType, this.aggregatorVendorId, this.aggregatorVendorName, this.aggregatorProductId, this.aggregatorProductName, this.aggregatorSerialNumber, this.aggregatorUniqueId);
745
516
  this.serverNode = await this.createServerNode(this.port ? this.port++ : undefined, this.passcode ? this.passcode++ : undefined, this.discriminator ? this.discriminator++ : undefined);
746
517
  this.aggregatorNode = await this.createAggregatorNode();
747
518
  this.log.debug(`Adding ${plg}Matterbridge${db} aggregator node...`);
@@ -752,13 +523,6 @@ export class MatterNode extends EventEmitter {
752
523
  this.log.debug(`Created ${plg}Matterbridge${db} server node`);
753
524
  return this.serverNode;
754
525
  }
755
- /**
756
- * Creates and configures the server node for an accessory plugin for a given device.
757
- *
758
- * @param {Plugin | PluginName} plugin - The plugin to configure.
759
- * @param {MatterbridgeEndpoint} device - The device to associate with the plugin.
760
- * @returns {Promise<ServerNode<ServerNode.RootEndpoint> | undefined>} A promise that resolves to the server node for the accessory plugin.
761
- */
762
526
  async createAccessoryPlugin(plugin, device) {
763
527
  if (typeof plugin === 'string') {
764
528
  const _plugin = this.pluginManager.get(plugin);
@@ -780,12 +544,6 @@ export class MatterNode extends EventEmitter {
780
544
  }
781
545
  return this.serverNode;
782
546
  }
783
- /**
784
- * Creates and configures the server node and the aggregator node for a dynamic plugin.
785
- *
786
- * @param {Plugin | PluginName} plugin - The plugin to configure.
787
- * @returns {Promise<ServerNode<ServerNode.RootEndpoint> | undefined>} A promise that resolves to the server node for the dynamic plugin.
788
- */
789
547
  async createDynamicPlugin(plugin) {
790
548
  if (typeof plugin === 'string') {
791
549
  const _plugin = this.pluginManager.get(plugin);
@@ -809,13 +567,6 @@ export class MatterNode extends EventEmitter {
809
567
  }
810
568
  return this.serverNode;
811
569
  }
812
- /**
813
- * Creates and configures the server node for a single not bridged device.
814
- *
815
- * @param {Plugin | PluginName} plugin - The plugin to configure.
816
- * @param {MatterbridgeEndpoint} device - The device to associate with the plugin.
817
- * @returns {Promise<ServerNode<ServerNode.RootEndpoint> | undefined>} A promise that resolves to the server node for the device with mode server.
818
- */
819
570
  async createDeviceServerNode(plugin, device) {
820
571
  if (typeof plugin === 'string') {
821
572
  const _plugin = this.pluginManager.get(plugin);
@@ -836,22 +587,13 @@ export class MatterNode extends EventEmitter {
836
587
  }
837
588
  return this.serverNode;
838
589
  }
839
- /**
840
- * Adds a MatterbridgeEndpoint to the specified plugin.
841
- *
842
- * @param {string} pluginName - The name of the plugin.
843
- * @param {MatterbridgeEndpoint} device - The device to add as a bridged endpoint.
844
- * @returns {Promise<MatterbridgeEndpoint | undefined>} A promise that resolves to the added bridged endpoint, or undefined if there was an error.
845
- */
846
590
  async addBridgedEndpoint(pluginName, device) {
847
- // Check if the plugin is registered
848
591
  const plugin = this.pluginManager.get(pluginName);
849
592
  if (!plugin)
850
593
  throw new Error(`Error adding bridged endpoint ${plg}${pluginName}${er}:${dev}${device.deviceName}${er} (${zb}${device.name}${er}): plugin not found`);
851
594
  if (device.mode === 'server') {
852
595
  try {
853
596
  this.log.debug(`Creating MatterNode for device ${plg}${pluginName}${db}:${dev}${device.deviceName}${db} (${zb}${device.name}${db})...`);
854
- // Create the MatterNode to manage the device
855
597
  const matterNode = new MatterNode(this.matterbridge, pluginName, device);
856
598
  this.dependantMatterNodes.set(device.id, matterNode);
857
599
  await matterNode.create();
@@ -864,7 +606,6 @@ export class MatterNode extends EventEmitter {
864
606
  }
865
607
  else if (this.matterbridge.bridgeMode === 'bridge') {
866
608
  if (device.mode === 'matter') {
867
- // Register and add the device to the Matter server node
868
609
  this.log.debug(`Adding matter endpoint ${plg}${pluginName}${db}:${dev}${device.deviceName}${db} (${zb}${device.name}${db})...`);
869
610
  if (!this.serverNode)
870
611
  throw new Error(`Server node not found for matter endpoint ${plg}${pluginName}${er}:${dev}${device.deviceName}${er} (${zb}${device.name}${er})`);
@@ -877,7 +618,6 @@ export class MatterNode extends EventEmitter {
877
618
  }
878
619
  }
879
620
  else {
880
- // Register and add the device to the Matter aggregator node
881
621
  this.log.debug(`Adding bridged endpoint ${plg}${pluginName}${db}:${dev}${device.deviceName}${db} (${zb}${device.name}${db})...`);
882
622
  if (!this.aggregatorNode)
883
623
  throw new Error(`Aggregator node not found for endpoint ${plg}${pluginName}${er}:${dev}${device.deviceName}${er} (${zb}${device.name}${er})`);
@@ -891,7 +631,6 @@ export class MatterNode extends EventEmitter {
891
631
  }
892
632
  }
893
633
  else if (this.matterbridge.bridgeMode === 'childbridge') {
894
- // Register and add the device to the plugin server node
895
634
  if (plugin.type === 'AccessoryPlatform') {
896
635
  try {
897
636
  this.log.debug(`Adding accessory endpoint ${plg}${pluginName}${db}:${dev}${device.deviceName}${db} (${zb}${device.name}${db})...`);
@@ -907,12 +646,10 @@ export class MatterNode extends EventEmitter {
907
646
  return;
908
647
  }
909
648
  }
910
- // Register and add the device to the plugin aggregator node
911
649
  if (plugin.type === 'DynamicPlatform') {
912
650
  try {
913
651
  this.log.debug(`Adding bridged endpoint ${plg}${pluginName}${db}:${dev}${device.deviceName}${db} (${zb}${device.name}${db})...`);
914
652
  if (!this.serverNode) {
915
- // Fast plugins can add another device before the server node is ready, so we wait for the server node to be ready
916
653
  await this.createDynamicPlugin(plugin);
917
654
  }
918
655
  if (device.mode === 'matter')
@@ -928,30 +665,18 @@ export class MatterNode extends EventEmitter {
928
665
  }
929
666
  if (plugin.registeredDevices !== undefined)
930
667
  plugin.registeredDevices++;
931
- // Add the device to the DeviceManager
932
668
  await this.server.fetch({ type: 'devices_set', src: this.server.name, dst: 'devices', params: { device: toBaseDevice(device) } });
933
- // Add the device to the DeviceManager
934
669
  await device.construction.ready;
935
- // Subscribe to the attributes changed event
936
670
  await this.subscribeAttributeChanged(plugin, device);
937
671
  this.log.info(`Added endpoint #${plugin.registeredDevices} ${plg}${pluginName}${nf}:${dev}${device.deviceName}${nf} (${zb}${device.name}${nf})`);
938
672
  await this.yieldToNode(10);
939
673
  return device;
940
674
  }
941
- /**
942
- * Removes a MatterbridgeEndpoint from the specified plugin.
943
- *
944
- * @param {string} pluginName - The name of the plugin.
945
- * @param {MatterbridgeEndpoint} device - The device to remove as a bridged endpoint.
946
- * @returns {Promise<MatterbridgeEndpoint | undefined>} A promise that resolves to the removed bridged endpoint, or undefined if there was an error.
947
- */
948
675
  async removeBridgedEndpoint(pluginName, device) {
949
676
  this.log.debug(`Removing bridged endpoint ${plg}${pluginName}${db}:${dev}${device.deviceName}${db} (${zb}${device.name}${db})...`);
950
- // Check if the plugin is registered
951
677
  const plugin = this.pluginManager.get(pluginName);
952
678
  if (!plugin)
953
679
  throw new Error(`Error removing bridged endpoint ${plg}${pluginName}${er}:${dev}${device.deviceName}${er} (${zb}${device.name}${er}): plugin not found`);
954
- // Remove the device from the Matter aggregator node
955
680
  if (this.matterbridge.bridgeMode === 'bridge') {
956
681
  if (!this.aggregatorNode)
957
682
  throw new Error(`Error removing bridged endpoint ${plg}${pluginName}${er}:${dev}${device.deviceName}${er} (${zb}${device.name}${er}): aggregator node not found`);
@@ -972,25 +697,11 @@ export class MatterNode extends EventEmitter {
972
697
  this.log.info(`Removed bridged endpoint #${plugin.registeredDevices} ${plg}${pluginName}${nf}:${dev}${device.deviceName}${nf} (${zb}${device.name}${nf})`);
973
698
  if (plugin.registeredDevices !== undefined)
974
699
  plugin.registeredDevices--;
975
- // Remove the device from the DeviceManager
976
700
  await this.server.fetch({ type: 'devices_remove', src: this.server.name, dst: 'devices', params: { device: toBaseDevice(device) } });
977
701
  await this.yieldToNode(10);
978
702
  return device;
979
703
  }
980
- /**
981
- * Removes all bridged endpoints from the specified plugin.
982
- *
983
- * @param {string} pluginName - The name of the plugin.
984
- * @param {number} [delay] - The delay in milliseconds between removing each bridged endpoint (default: 0).
985
- * @returns {Promise<void>} A promise that resolves when all bridged endpoints have been removed.
986
- *
987
- * @remarks
988
- * This method iterates through all devices in the DeviceManager and removes each bridged endpoint associated with the specified plugin.
989
- * It also applies a delay between each removal if specified.
990
- * The delay is useful to allow the controllers to receive a single subscription for each device removed.
991
- */
992
704
  async removeAllBridgedEndpoints(pluginName, delay = 0) {
993
- // Check if the plugin is registered
994
705
  const plugin = this.pluginManager.get(pluginName);
995
706
  if (!plugin)
996
707
  throw new Error(`Error removing all bridged endpoints for plugin ${plg}${pluginName}${er}: plugin not found`);
@@ -1005,7 +716,6 @@ export class MatterNode extends EventEmitter {
1005
716
  this.log.info(`Removed bridged endpoint #${plugin.registeredDevices} ${plg}${pluginName}${nf}:${dev}${device.deviceName}${nf} (${zb}${endpoint?.name}${nf})`);
1006
717
  if (plugin.registeredDevices !== undefined)
1007
718
  plugin.registeredDevices--;
1008
- // Remove the device from the DeviceManager
1009
719
  await this.server.fetch({ type: 'devices_remove', src: this.server.name, dst: 'devices', params: { device: toBaseDevice(device) } });
1010
720
  await this.yieldToNode(10);
1011
721
  if (delay > 0)
@@ -1014,25 +724,6 @@ export class MatterNode extends EventEmitter {
1014
724
  if (delay > 0)
1015
725
  await wait(Number(process.env['MATTERBRIDGE_REMOVE_ALL_ENDPOINT_TIMEOUT_MS']) || 2000);
1016
726
  }
1017
- /**
1018
- * Registers a virtual device with the Matterbridge platform.
1019
- * Virtual devices are only supported in bridge mode and childbridge mode with a DynamicPlatform.
1020
- *
1021
- * The virtual device is created as an instance of `Endpoint` with the provided device type.
1022
- * When the virtual device is turned on, the provided callback function is executed.
1023
- * The onOff state of the virtual device always reverts to false when the device is turned on.
1024
- *
1025
- * @param {string} pluginName - The name of the plugin.
1026
- * @param { string } name - The name of the virtual device.
1027
- * @param { 'light' | 'outlet' | 'switch' | 'mounted_switch' } type - The type of the virtual device.
1028
- * @param { () => Promise<void> } callback - The callback to call when the virtual device is turned on.
1029
- *
1030
- * @returns {Promise<boolean>} A promise that resolves to true if the virtual device was successfully registered, false otherwise.
1031
- *
1032
- * @remarks
1033
- * The virtual devices don't show up in the device list of the frontend.
1034
- * Type 'switch' is not supported by Alexa and 'mounted_switch' is not supported by Apple Home.
1035
- */
1036
727
  async addVirtualEndpoint(pluginName, name, type, callback) {
1037
728
  this.log.debug(`Creating virtual device ${plg}${pluginName}${db}:${dev}${name}${db}...`);
1038
729
  const plugin = this.pluginManager.get(pluginName);
@@ -1057,20 +748,10 @@ export class MatterNode extends EventEmitter {
1057
748
  await this.yieldToNode(10);
1058
749
  return true;
1059
750
  }
1060
- /**
1061
- * Subscribes to the attribute change event for the given device and plugin.
1062
- * Specifically, it listens for changes in the 'reachable' attribute of the
1063
- * BridgedDeviceBasicInformationServer cluster server of the bridged device or BasicInformationServer cluster server of server node.
1064
- *
1065
- * @param {Plugin} plugin - The plugin associated with the device.
1066
- * @param {MatterbridgeEndpoint} device - The device to subscribe to attribute changes for.
1067
- * @returns {Promise<void>} A promise that resolves when the subscription is set up.
1068
- */
1069
751
  async subscribeAttributeChanged(plugin, device) {
1070
752
  if (!plugin || !device || !device.plugin || !device.serialNumber || !device.uniqueId || !device.maybeNumber)
1071
753
  return;
1072
754
  this.log.debug(`Subscribing attributes for endpoint ${plg}${plugin.name}${db}:${dev}${device.deviceName}${db}:${or}${device.id}${db}:${or}${device.number}${db} (${zb}${device.name}${db})`);
1073
- // Subscribe to the reachable$Changed event of the BasicInformationServer cluster server of the server node in childbridge mode
1074
755
  if (this.matterbridge.bridgeMode === 'childbridge' && plugin.type === 'AccessoryPlatform' && this.serverNode) {
1075
756
  this.serverNode.eventsOf(BasicInformationServer).reachable$Changed?.on((reachable) => {
1076
757
  this.log.debug(`Accessory endpoint ${plg}${plugin.name}${nf}:${dev}${device.deviceName}${nf}:${or}${device.id}${nf}:${or}${device.number}${nf} is ${reachable ? 'reachable' : 'unreachable'}`);
@@ -1078,7 +759,6 @@ export class MatterNode extends EventEmitter {
1078
759
  type: 'frontend_attributechanged',
1079
760
  src: 'matter',
1080
761
  dst: 'frontend',
1081
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1082
762
  params: { plugin: device.plugin, serialNumber: device.serialNumber, uniqueId: device.uniqueId, number: device.number, id: device.id, cluster: 'BasicInformation', attribute: 'reachable', value: reachable },
1083
763
  });
1084
764
  });
@@ -1131,7 +811,6 @@ export class MatterNode extends EventEmitter {
1131
811
  type: 'frontend_attributechanged',
1132
812
  src: 'matter',
1133
813
  dst: 'frontend',
1134
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1135
814
  params: { plugin: device.plugin, serialNumber: device.serialNumber, uniqueId: device.uniqueId, number: device.number, id: device.id, cluster: sub.cluster, attribute: sub.attribute, value: value },
1136
815
  });
1137
816
  });
@@ -1145,7 +824,6 @@ export class MatterNode extends EventEmitter {
1145
824
  type: 'frontend_attributechanged',
1146
825
  src: 'matter',
1147
826
  dst: 'frontend',
1148
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1149
827
  params: { plugin: device.plugin, serialNumber: device.serialNumber, uniqueId: device.uniqueId, number: child.number, id: child.id, cluster: sub.cluster, attribute: sub.attribute, value: value },
1150
828
  });
1151
829
  });
@@ -1153,12 +831,6 @@ export class MatterNode extends EventEmitter {
1153
831
  }
1154
832
  }
1155
833
  }
1156
- /**
1157
- * Sanitizes the fabric information by converting bigint properties to strings because `res.json` doesn't support bigint.
1158
- *
1159
- * @param {ExposedFabricInformation[]} fabricInfo - The array of exposed fabric information objects.
1160
- * @returns {SanitizedExposedFabricInformation[]} An array of sanitized exposed fabric information objects.
1161
- */
1162
834
  sanitizeFabricInformations(fabricInfo) {
1163
835
  return fabricInfo.map((info) => {
1164
836
  return {
@@ -1172,12 +844,6 @@ export class MatterNode extends EventEmitter {
1172
844
  };
1173
845
  });
1174
846
  }
1175
- /**
1176
- * Sanitizes the session information by converting bigint properties to strings because `res.json` doesn't support bigint.
1177
- *
1178
- * @param {SessionsBehavior.Session[]} sessions - The array of session information objects.
1179
- * @returns {SanitizedSession[]} An array of sanitized session information objects.
1180
- */
1181
847
  sanitizeSessionInformation(sessions) {
1182
848
  return sessions
1183
849
  .filter((session) => session.isPeerActive)
@@ -1204,21 +870,10 @@ export class MatterNode extends EventEmitter {
1204
870
  };
1205
871
  });
1206
872
  }
1207
- /**
1208
- * Sets the reachability of the specified server node and trigger the corresponding event.
1209
- *
1210
- * @param {boolean} reachable - A boolean indicating the reachability status to set.
1211
- */
1212
873
  async setServerReachability(reachable) {
1213
874
  await this.serverNode?.setStateOf(BasicInformationServer, { reachable });
1214
875
  this.serverNode?.act((agent) => this.serverNode?.eventsOf(BasicInformationServer).reachableChanged?.emit({ reachableNewValue: reachable }, agent.context));
1215
876
  }
1216
- /**
1217
- * Sets the reachability of the specified aggregator node bridged devices and trigger.
1218
- *
1219
- * @param {Endpoint<AggregatorEndpoint>} aggregatorNode - The aggregator node to set the reachability for.
1220
- * @param {boolean} reachable - A boolean indicating the reachability status to set.
1221
- */
1222
877
  async setAggregatorReachability(aggregatorNode, reachable) {
1223
878
  for (const child of aggregatorNode.parts) {
1224
879
  this.log.debug(`Setting reachability of ${child?.deviceName} to ${reachable}`);
@@ -1264,35 +919,19 @@ export class MatterNode extends EventEmitter {
1264
919
  case 0x1488:
1265
920
  vendorName = '(ShortcutLabsFlic)';
1266
921
  break;
1267
- case 65521: // 0xFFF1
922
+ case 65521:
1268
923
  vendorName = '(MatterTest)';
1269
924
  break;
1270
925
  }
1271
926
  return vendorName;
1272
927
  };
1273
- /**
1274
- * Yield to the Node.js event loop:
1275
- * 1. Flushes the current microtask queue (Promise/async continuations queued so far).
1276
- * 2. Yields one macrotask turn (setImmediate) and then its microtasks.
1277
- * 3. Waits a bit (setTimeout) to allow other macrotasks to run.
1278
- *
1279
- * This does **not** guarantee that every promise in the process is settled,
1280
- * but it gives all already-scheduled work a very good chance to run before continuing.
1281
- *
1282
- * @param {number} [timeout] - Optional timeout in milliseconds to wait after yielding. Default is 100 ms (minimum 10 ms).
1283
- * @returns {Promise<void>}
1284
- */
1285
928
  async yieldToNode(timeout = 100) {
1286
- // 1. Let all currently queued microtasks run
1287
929
  await Promise.resolve();
1288
- // 2. Yield to the next event-loop turn (macrotask + its microtasks)
1289
930
  await new Promise((resolve) => {
1290
931
  setImmediate(resolve);
1291
932
  });
1292
- // 3. Pause a bit to allow other macrotasks to run
1293
933
  await new Promise((resolve) => {
1294
934
  setTimeout(resolve, Math.min(timeout, 10));
1295
935
  });
1296
936
  }
1297
937
  }
1298
- //# sourceMappingURL=matterNode.js.map