@matterbridge/core 3.5.3 → 3.5.4-edge-20260211-1ea4e31

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 (294) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.d.ts +0 -24
  3. package/dist/cli.js +1 -97
  4. package/dist/cliEmitter.d.ts +0 -36
  5. package/dist/cliEmitter.js +0 -37
  6. package/dist/cliHistory.d.ts +0 -42
  7. package/dist/cliHistory.js +0 -38
  8. package/dist/clusters/export.d.ts +0 -1
  9. package/dist/clusters/export.js +0 -2
  10. package/dist/deviceManager.d.ts +0 -108
  11. package/dist/deviceManager.js +1 -114
  12. package/dist/devices/airConditioner.d.ts +0 -75
  13. package/dist/devices/airConditioner.js +0 -57
  14. package/dist/devices/basicVideoPlayer.d.ts +0 -58
  15. package/dist/devices/basicVideoPlayer.js +1 -56
  16. package/dist/devices/batteryStorage.d.ts +0 -43
  17. package/dist/devices/batteryStorage.js +1 -48
  18. package/dist/devices/castingVideoPlayer.d.ts +0 -63
  19. package/dist/devices/castingVideoPlayer.js +2 -65
  20. package/dist/devices/cooktop.d.ts +0 -55
  21. package/dist/devices/cooktop.js +0 -56
  22. package/dist/devices/dishwasher.d.ts +0 -55
  23. package/dist/devices/dishwasher.js +0 -57
  24. package/dist/devices/evse.d.ts +0 -57
  25. package/dist/devices/evse.js +10 -74
  26. package/dist/devices/export.d.ts +0 -1
  27. package/dist/devices/export.js +0 -5
  28. package/dist/devices/extractorHood.d.ts +0 -41
  29. package/dist/devices/extractorHood.js +0 -43
  30. package/dist/devices/heatPump.d.ts +0 -43
  31. package/dist/devices/heatPump.js +2 -50
  32. package/dist/devices/laundryDryer.d.ts +0 -58
  33. package/dist/devices/laundryDryer.js +3 -62
  34. package/dist/devices/laundryWasher.d.ts +0 -64
  35. package/dist/devices/laundryWasher.js +4 -70
  36. package/dist/devices/microwaveOven.d.ts +1 -77
  37. package/dist/devices/microwaveOven.js +5 -88
  38. package/dist/devices/oven.d.ts +0 -82
  39. package/dist/devices/oven.js +0 -85
  40. package/dist/devices/refrigerator.d.ts +0 -100
  41. package/dist/devices/refrigerator.js +0 -102
  42. package/dist/devices/roboticVacuumCleaner.d.ts +0 -83
  43. package/dist/devices/roboticVacuumCleaner.js +9 -100
  44. package/dist/devices/solarPower.d.ts +0 -36
  45. package/dist/devices/solarPower.js +0 -38
  46. package/dist/devices/speaker.d.ts +0 -79
  47. package/dist/devices/speaker.js +0 -84
  48. package/dist/devices/temperatureControl.d.ts +0 -21
  49. package/dist/devices/temperatureControl.js +3 -24
  50. package/dist/devices/waterHeater.d.ts +0 -74
  51. package/dist/devices/waterHeater.js +2 -82
  52. package/dist/dgram/export.d.ts +0 -1
  53. package/dist/dgram/export.js +0 -1
  54. package/dist/export.d.ts +0 -23
  55. package/dist/export.js +0 -28
  56. package/dist/frontend.d.ts +0 -187
  57. package/dist/frontend.js +38 -539
  58. package/dist/helpers.d.ts +0 -43
  59. package/dist/helpers.js +0 -86
  60. package/dist/jestutils/export.d.ts +0 -1
  61. package/dist/jestutils/export.js +0 -1
  62. package/dist/jestutils/jestHelpers.d.ts +0 -259
  63. package/dist/jestutils/jestHelpers.js +14 -395
  64. package/dist/matter/behaviors.d.ts +0 -1
  65. package/dist/matter/behaviors.js +0 -2
  66. package/dist/matter/clusters.d.ts +0 -1
  67. package/dist/matter/clusters.js +0 -2
  68. package/dist/matter/devices.d.ts +0 -1
  69. package/dist/matter/devices.js +0 -2
  70. package/dist/matter/endpoints.d.ts +0 -1
  71. package/dist/matter/endpoints.js +0 -2
  72. package/dist/matter/export.d.ts +0 -1
  73. package/dist/matter/export.js +0 -2
  74. package/dist/matter/types.d.ts +0 -1
  75. package/dist/matter/types.js +0 -2
  76. package/dist/matterNode.d.ts +0 -258
  77. package/dist/matterNode.js +8 -356
  78. package/dist/matterbridge.d.ts +0 -389
  79. package/dist/matterbridge.js +48 -878
  80. package/dist/matterbridgeAccessoryPlatform.d.ts +0 -42
  81. package/dist/matterbridgeAccessoryPlatform.js +0 -50
  82. package/dist/matterbridgeBehaviors.d.ts +0 -24
  83. package/dist/matterbridgeBehaviors.js +5 -65
  84. package/dist/matterbridgeDeviceTypes.d.ts +0 -649
  85. package/dist/matterbridgeDeviceTypes.js +6 -673
  86. package/dist/matterbridgeDynamicPlatform.d.ts +0 -42
  87. package/dist/matterbridgeDynamicPlatform.js +0 -50
  88. package/dist/matterbridgeEndpoint.d.ts +0 -1369
  89. package/dist/matterbridgeEndpoint.js +56 -1514
  90. package/dist/matterbridgeEndpointHelpers.d.ts +0 -425
  91. package/dist/matterbridgeEndpointHelpers.js +20 -483
  92. package/dist/matterbridgeEndpointTypes.d.ts +0 -70
  93. package/dist/matterbridgeEndpointTypes.js +0 -25
  94. package/dist/matterbridgePlatform.d.ts +0 -434
  95. package/dist/matterbridgePlatform.js +1 -473
  96. package/dist/mb_coap.d.ts +0 -23
  97. package/dist/mb_coap.js +3 -41
  98. package/dist/mb_health.d.ts +0 -67
  99. package/dist/mb_health.js +0 -70
  100. package/dist/mb_mdns.d.ts +0 -23
  101. package/dist/mb_mdns.js +36 -94
  102. package/dist/pluginManager.d.ts +0 -307
  103. package/dist/pluginManager.js +6 -346
  104. package/dist/spawn.d.ts +0 -32
  105. package/dist/spawn.js +1 -71
  106. package/dist/utils/export.d.ts +0 -1
  107. package/dist/utils/export.js +0 -1
  108. package/package.json +27 -6
  109. package/dist/cli.d.ts.map +0 -1
  110. package/dist/cli.js.map +0 -1
  111. package/dist/cliEmitter.d.ts.map +0 -1
  112. package/dist/cliEmitter.js.map +0 -1
  113. package/dist/cliHistory.d.ts.map +0 -1
  114. package/dist/cliHistory.js.map +0 -1
  115. package/dist/clusters/export.d.ts.map +0 -1
  116. package/dist/clusters/export.js.map +0 -1
  117. package/dist/crypto/attestationDecoder.d.ts +0 -180
  118. package/dist/crypto/attestationDecoder.d.ts.map +0 -1
  119. package/dist/crypto/attestationDecoder.js +0 -176
  120. package/dist/crypto/attestationDecoder.js.map +0 -1
  121. package/dist/crypto/declarationDecoder.d.ts +0 -72
  122. package/dist/crypto/declarationDecoder.d.ts.map +0 -1
  123. package/dist/crypto/declarationDecoder.js +0 -241
  124. package/dist/crypto/declarationDecoder.js.map +0 -1
  125. package/dist/crypto/extract/342/200/220cert/342/200/220extensions.d.ts +0 -9
  126. package/dist/crypto/extract/342/200/220cert/342/200/220extensions.d.ts.map +0 -1
  127. package/dist/crypto/extract/342/200/220cert/342/200/220extensions.js +0 -120
  128. package/dist/crypto/extract/342/200/220cert/342/200/220extensions.js.map +0 -1
  129. package/dist/crypto/read-extensions.d.ts +0 -2
  130. package/dist/crypto/read-extensions.d.ts.map +0 -1
  131. package/dist/crypto/read-extensions.js +0 -81
  132. package/dist/crypto/read-extensions.js.map +0 -1
  133. package/dist/crypto/testData.d.ts +0 -31
  134. package/dist/crypto/testData.d.ts.map +0 -1
  135. package/dist/crypto/testData.js +0 -131
  136. package/dist/crypto/testData.js.map +0 -1
  137. package/dist/crypto/walk-der.d.ts +0 -2
  138. package/dist/crypto/walk-der.d.ts.map +0 -1
  139. package/dist/crypto/walk-der.js +0 -165
  140. package/dist/crypto/walk-der.js.map +0 -1
  141. package/dist/deviceManager.d.ts.map +0 -1
  142. package/dist/deviceManager.js.map +0 -1
  143. package/dist/devices/airConditioner.d.ts.map +0 -1
  144. package/dist/devices/airConditioner.js.map +0 -1
  145. package/dist/devices/basicVideoPlayer.d.ts.map +0 -1
  146. package/dist/devices/basicVideoPlayer.js.map +0 -1
  147. package/dist/devices/batteryStorage.d.ts.map +0 -1
  148. package/dist/devices/batteryStorage.js.map +0 -1
  149. package/dist/devices/castingVideoPlayer.d.ts.map +0 -1
  150. package/dist/devices/castingVideoPlayer.js.map +0 -1
  151. package/dist/devices/cooktop.d.ts.map +0 -1
  152. package/dist/devices/cooktop.js.map +0 -1
  153. package/dist/devices/dishwasher.d.ts.map +0 -1
  154. package/dist/devices/dishwasher.js.map +0 -1
  155. package/dist/devices/evse.d.ts.map +0 -1
  156. package/dist/devices/evse.js.map +0 -1
  157. package/dist/devices/export.d.ts.map +0 -1
  158. package/dist/devices/export.js.map +0 -1
  159. package/dist/devices/extractorHood.d.ts.map +0 -1
  160. package/dist/devices/extractorHood.js.map +0 -1
  161. package/dist/devices/heatPump.d.ts.map +0 -1
  162. package/dist/devices/heatPump.js.map +0 -1
  163. package/dist/devices/laundryDryer.d.ts.map +0 -1
  164. package/dist/devices/laundryDryer.js.map +0 -1
  165. package/dist/devices/laundryWasher.d.ts.map +0 -1
  166. package/dist/devices/laundryWasher.js.map +0 -1
  167. package/dist/devices/microwaveOven.d.ts.map +0 -1
  168. package/dist/devices/microwaveOven.js.map +0 -1
  169. package/dist/devices/oven.d.ts.map +0 -1
  170. package/dist/devices/oven.js.map +0 -1
  171. package/dist/devices/refrigerator.d.ts.map +0 -1
  172. package/dist/devices/refrigerator.js.map +0 -1
  173. package/dist/devices/roboticVacuumCleaner.d.ts.map +0 -1
  174. package/dist/devices/roboticVacuumCleaner.js.map +0 -1
  175. package/dist/devices/solarPower.d.ts.map +0 -1
  176. package/dist/devices/solarPower.js.map +0 -1
  177. package/dist/devices/speaker.d.ts.map +0 -1
  178. package/dist/devices/speaker.js.map +0 -1
  179. package/dist/devices/temperatureControl.d.ts.map +0 -1
  180. package/dist/devices/temperatureControl.js.map +0 -1
  181. package/dist/devices/waterHeater.d.ts.map +0 -1
  182. package/dist/devices/waterHeater.js.map +0 -1
  183. package/dist/dgram/export.d.ts.map +0 -1
  184. package/dist/dgram/export.js.map +0 -1
  185. package/dist/export.d.ts.map +0 -1
  186. package/dist/export.js.map +0 -1
  187. package/dist/frontend.d.ts.map +0 -1
  188. package/dist/frontend.js.map +0 -1
  189. package/dist/helpers.d.ts.map +0 -1
  190. package/dist/helpers.js.map +0 -1
  191. package/dist/jestutils/export.d.ts.map +0 -1
  192. package/dist/jestutils/export.js.map +0 -1
  193. package/dist/jestutils/jestHelpers.d.ts.map +0 -1
  194. package/dist/jestutils/jestHelpers.js.map +0 -1
  195. package/dist/matter/behaviors.d.ts.map +0 -1
  196. package/dist/matter/behaviors.js.map +0 -1
  197. package/dist/matter/clusters.d.ts.map +0 -1
  198. package/dist/matter/clusters.js.map +0 -1
  199. package/dist/matter/devices.d.ts.map +0 -1
  200. package/dist/matter/devices.js.map +0 -1
  201. package/dist/matter/endpoints.d.ts.map +0 -1
  202. package/dist/matter/endpoints.js.map +0 -1
  203. package/dist/matter/export.d.ts.map +0 -1
  204. package/dist/matter/export.js.map +0 -1
  205. package/dist/matter/types.d.ts.map +0 -1
  206. package/dist/matter/types.js.map +0 -1
  207. package/dist/matterNode.d.ts.map +0 -1
  208. package/dist/matterNode.js.map +0 -1
  209. package/dist/matterbridge.d.ts.map +0 -1
  210. package/dist/matterbridge.js.map +0 -1
  211. package/dist/matterbridgeAccessoryPlatform.d.ts.map +0 -1
  212. package/dist/matterbridgeAccessoryPlatform.js.map +0 -1
  213. package/dist/matterbridgeBehaviors.d.ts.map +0 -1
  214. package/dist/matterbridgeBehaviors.js.map +0 -1
  215. package/dist/matterbridgeDeviceTypes.d.ts.map +0 -1
  216. package/dist/matterbridgeDeviceTypes.js.map +0 -1
  217. package/dist/matterbridgeDynamicPlatform.d.ts.map +0 -1
  218. package/dist/matterbridgeDynamicPlatform.js.map +0 -1
  219. package/dist/matterbridgeEndpoint.d.ts.map +0 -1
  220. package/dist/matterbridgeEndpoint.js.map +0 -1
  221. package/dist/matterbridgeEndpointHelpers.d.ts.map +0 -1
  222. package/dist/matterbridgeEndpointHelpers.js.map +0 -1
  223. package/dist/matterbridgeEndpointTypes.d.ts.map +0 -1
  224. package/dist/matterbridgeEndpointTypes.js.map +0 -1
  225. package/dist/matterbridgePlatform.d.ts.map +0 -1
  226. package/dist/matterbridgePlatform.js.map +0 -1
  227. package/dist/mb_coap.d.ts.map +0 -1
  228. package/dist/mb_coap.js.map +0 -1
  229. package/dist/mb_health.d.ts.map +0 -1
  230. package/dist/mb_health.js.map +0 -1
  231. package/dist/mb_mdns.d.ts.map +0 -1
  232. package/dist/mb_mdns.js.map +0 -1
  233. package/dist/pluginManager.d.ts.map +0 -1
  234. package/dist/pluginManager.js.map +0 -1
  235. package/dist/spawn.d.ts.map +0 -1
  236. package/dist/spawn.js.map +0 -1
  237. package/dist/utils/export.d.ts.map +0 -1
  238. package/dist/utils/export.js.map +0 -1
  239. package/dist/workers/brand.d.ts +0 -25
  240. package/dist/workers/brand.d.ts.map +0 -1
  241. package/dist/workers/brand.extend.d.ts +0 -10
  242. package/dist/workers/brand.extend.d.ts.map +0 -1
  243. package/dist/workers/brand.extend.js +0 -15
  244. package/dist/workers/brand.extend.js.map +0 -1
  245. package/dist/workers/brand.invalid.d.ts +0 -9
  246. package/dist/workers/brand.invalid.d.ts.map +0 -1
  247. package/dist/workers/brand.invalid.js +0 -19
  248. package/dist/workers/brand.invalid.js.map +0 -1
  249. package/dist/workers/brand.js +0 -67
  250. package/dist/workers/brand.js.map +0 -1
  251. package/dist/workers/clusterTypes.d.ts +0 -47
  252. package/dist/workers/clusterTypes.d.ts.map +0 -1
  253. package/dist/workers/clusterTypes.js +0 -57
  254. package/dist/workers/clusterTypes.js.map +0 -1
  255. package/dist/workers/frontendWorker.d.ts +0 -2
  256. package/dist/workers/frontendWorker.d.ts.map +0 -1
  257. package/dist/workers/frontendWorker.js +0 -90
  258. package/dist/workers/frontendWorker.js.map +0 -1
  259. package/dist/workers/helloWorld.d.ts +0 -2
  260. package/dist/workers/helloWorld.d.ts.map +0 -1
  261. package/dist/workers/helloWorld.js +0 -135
  262. package/dist/workers/helloWorld.js.map +0 -1
  263. package/dist/workers/matterWorker.d.ts +0 -2
  264. package/dist/workers/matterWorker.d.ts.map +0 -1
  265. package/dist/workers/matterWorker.js +0 -104
  266. package/dist/workers/matterWorker.js.map +0 -1
  267. package/dist/workers/matterbridgeWorker.d.ts +0 -2
  268. package/dist/workers/matterbridgeWorker.d.ts.map +0 -1
  269. package/dist/workers/matterbridgeWorker.js +0 -75
  270. package/dist/workers/matterbridgeWorker.js.map +0 -1
  271. package/dist/workers/messageLab.d.ts +0 -134
  272. package/dist/workers/messageLab.d.ts.map +0 -1
  273. package/dist/workers/messageLab.js +0 -129
  274. package/dist/workers/messageLab.js.map +0 -1
  275. package/dist/workers/testWorker.d.ts +0 -2
  276. package/dist/workers/testWorker.d.ts.map +0 -1
  277. package/dist/workers/testWorker.js +0 -45
  278. package/dist/workers/testWorker.js.map +0 -1
  279. package/dist/workers/usage.d.ts +0 -19
  280. package/dist/workers/usage.d.ts.map +0 -1
  281. package/dist/workers/usage.js +0 -140
  282. package/dist/workers/usage.js.map +0 -1
  283. package/dist/workers/workerManager.d.ts +0 -115
  284. package/dist/workers/workerManager.d.ts.map +0 -1
  285. package/dist/workers/workerManager.js +0 -464
  286. package/dist/workers/workerManager.js.map +0 -1
  287. package/dist/workers/workerServer.d.ts +0 -126
  288. package/dist/workers/workerServer.d.ts.map +0 -1
  289. package/dist/workers/workerServer.js +0 -340
  290. package/dist/workers/workerServer.js.map +0 -1
  291. package/dist/workers/workerTypes.d.ts +0 -23
  292. package/dist/workers/workerTypes.d.ts.map +0 -1
  293. package/dist/workers/workerTypes.js +0 -3
  294. package/dist/workers/workerTypes.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 { MdnsService } from '@matter/protocol';
@@ -38,7 +11,6 @@ import { ServerNode, Endpoint } from '@matter/node';
38
11
  import { AggregatorEndpoint } from '@matter/node/endpoints/aggregator';
39
12
  import { BasicInformationServer } from '@matter/node/behaviors/basic-information';
40
13
  import { BridgedDeviceBasicInformationServer } from '@matter/node/behaviors/bridged-device-basic-information';
41
- // Matterbridge
42
14
  import { copyDirectory, getIntParameter, getParameter, hasParameter, inspectError, isValidNumber, isValidString, parseVersionString, wait, withTimeout } from '@matterbridge/utils';
43
15
  import { dev, MATTER_LOGGER_FILE, MATTER_STORAGE_NAME, plg, NODE_STORAGE_DIR, MATTERBRIDGE_LOGGER_FILE } from '@matterbridge/types';
44
16
  import { BroadcastServer } from '@matterbridge/thread';
@@ -46,48 +18,27 @@ import { bridge } from './matterbridgeDeviceTypes.js';
46
18
  import { toBaseDevice } from './deviceManager.js';
47
19
  import { PluginManager } from './pluginManager.js';
48
20
  import { addVirtualDevice } from './helpers.js';
49
- /**
50
- * Represents the Matter class.
51
- */
52
21
  export class MatterNode extends EventEmitter {
53
22
  matterbridge;
54
23
  pluginName;
55
24
  device;
56
- /** Matterbridge logger */
57
- log = new AnsiLogger({ logName: 'MatterNode', logTimestampFormat: 4 /* TimestampFormat.TIME_MILLIS */, logLevel: "debug" /* LogLevel.DEBUG */ });
58
- /** Matter logger */
59
- matterLog = new AnsiLogger({ logName: 'MatterNode', logTimestampFormat: 4 /* TimestampFormat.TIME_MILLIS */, logLevel: "debug" /* LogLevel.DEBUG */ });
60
- /** Matter environment default */
25
+ log = new AnsiLogger({ logName: 'MatterNode', logTimestampFormat: 4, logLevel: "debug" });
26
+ matterLog = new AnsiLogger({ logName: 'MatterNode', logTimestampFormat: 4, logLevel: "debug" });
61
27
  environment = Environment.default;
62
- /** Matter storage id */
63
28
  storeId;
64
- /** Matter mdns service from environment default */
65
29
  matterMdnsService;
66
- /** Matter storage service from environment default */
67
30
  matterStorageService;
68
- /** Matter storage manager created with name 'Matterbridge' */
69
31
  matterStorageManager;
70
- /** Matter storage context created in the storage manager with name 'persist' */
71
32
  matterStorageContext;
72
- /** Matter mdns interface name e.g. 'eth0' or 'wlan0' or 'Wi-Fi' */
73
33
  mdnsInterface;
74
- /** Matter listeningAddressIpv4 address */
75
34
  ipv4Address;
76
- /** Matter listeningAddressIpv6 address */
77
35
  ipv6Address;
78
- /** Matter commissioning port It is incremented in childbridge mode. */
79
36
  port;
80
- /** Matter commissioning passcode. It is incremented in childbridge mode. */
81
37
  passcode;
82
- /** Matter commissioning discriminator. It is incremented in childbridge mode. */
83
38
  discriminator;
84
- /** Matter device certification */
85
39
  certification;
86
- /** Matter server node */
87
40
  serverNode;
88
- /** Matter aggregator node */
89
41
  aggregatorNode;
90
- // Default values for the aggregator node
91
42
  aggregatorVendorId = VendorId(getIntParameter('vendorId') ?? 0xfff1);
92
43
  aggregatorVendorName = getParameter('vendorName') ?? 'Matterbridge';
93
44
  aggregatorProductId = getIntParameter('productId') ?? 0x8000;
@@ -95,23 +46,12 @@ export class MatterNode extends EventEmitter {
95
46
  aggregatorDeviceType = DeviceTypeId(getIntParameter('deviceType') ?? bridge.code);
96
47
  aggregatorSerialNumber = getParameter('serialNumber');
97
48
  aggregatorUniqueId = getParameter('uniqueId');
98
- /** Advertising nodes map: time advertising started keyed by storeId */
99
49
  advertisingNodes = new Map();
100
- /** Plugins */
101
50
  pluginManager;
102
- /** Dependant MatterNodes keyed by device id */
103
51
  dependantMatterNodes = new Map();
104
- /** Broadcast server */
105
52
  server;
106
53
  debug = hasParameter('debug') || hasParameter('verbose');
107
54
  verbose = hasParameter('verbose');
108
- /**
109
- * Creates an instance of the Matter class.
110
- *
111
- * @param {SharedMatterbridge} matterbridge - The shared matterbridge instance.
112
- * @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.
113
- * @param {MatterbridgeEndpoint} [device] - The matterbridge endpoint device (optional). It is used to create a server mode device.
114
- */
115
55
  constructor(matterbridge, pluginName, device) {
116
56
  super();
117
57
  this.matterbridge = matterbridge;
@@ -120,25 +60,19 @@ export class MatterNode extends EventEmitter {
120
60
  this.log.logNameColor = '\x1b[38;5;65m';
121
61
  if (this.debug)
122
62
  this.log.debug(`MatterNode ${this.pluginName ? 'for plugin ' + this.pluginName : 'bridge'} loading...`);
123
- // Setup Matter parameters
124
63
  this.port = matterbridge.port;
125
64
  this.passcode = matterbridge.passcode;
126
65
  this.discriminator = matterbridge.discriminator;
127
- // Setup the broadcast server
128
66
  this.server = new BroadcastServer('matter', this.log);
129
67
  this.server.on('broadcast_message', this.msgHandler.bind(this));
130
68
  if (this.verbose)
131
69
  this.log.debug(`BroadcastServer is ready`);
132
- // Ensure the matterbridge directory exists
133
70
  fs.mkdirSync(matterbridge.matterbridgeDirectory, { recursive: true });
134
- // Setup the plugin manager with thread server closed
135
71
  this.pluginManager = new PluginManager(this.matterbridge);
136
- this.pluginManager.logLevel = this.debug ? "debug" /* LogLevel.DEBUG */ : "info" /* LogLevel.INFO */;
137
- // @ts-expect-error access private property
72
+ this.pluginManager.logLevel = this.debug ? "debug" : "info";
138
73
  this.pluginManager.server.close();
139
74
  if (this.verbose)
140
75
  this.log.debug(`PluginManager is ready`);
141
- // Setup the matter environment
142
76
  this.environment.vars.set('log.level', MatterLogLevel.DEBUG);
143
77
  this.environment.vars.set('log.format', MatterLogFormat.ANSI);
144
78
  this.environment.vars.set('path.root', path.join(matterbridge.matterbridgeDirectory, MATTER_STORAGE_NAME));
@@ -146,18 +80,15 @@ export class MatterNode extends EventEmitter {
146
80
  this.environment.vars.set('runtime.exitcode', false);
147
81
  if (this.verbose)
148
82
  this.log.debug(`Matter Environment is ready`);
149
- // Ensure MdnsService is registered in the default environment
150
83
  this.matterMdnsService = new MdnsService(this.environment);
151
84
  setImmediate(async () => {
152
85
  await this.matterMdnsService?.construction.ready;
153
86
  if (this.verbose)
154
87
  this.log.debug(`Matter MdnsService is ready`);
155
88
  });
156
- // Setup the matterbridge logger
157
89
  if (this.matterbridge.fileLogger) {
158
90
  AnsiLogger.setGlobalLogfile(path.join(this.matterbridge.matterbridgeDirectory, MATTERBRIDGE_LOGGER_FILE), this.matterbridge.logLevel);
159
91
  }
160
- // Setup the matter logger
161
92
  Logger.destinations.default.write = this.createDestinationMatterLogger();
162
93
  const levels = ['debug', 'info', 'notice', 'warn', 'error', 'fatal'];
163
94
  if (this.verbose)
@@ -165,11 +96,6 @@ export class MatterNode extends EventEmitter {
165
96
  if (this.debug)
166
97
  this.log.debug(`MatterNode ${this.pluginName ? 'for plugin ' + this.pluginName : 'bridge'} loaded`);
167
98
  }
168
- /**
169
- * Handles incoming messages from the broadcast server.
170
- *
171
- * @param {WorkerMessage} msg - The incoming message.
172
- */
173
99
  async msgHandler(msg) {
174
100
  if (this.server.isWorkerRequest(msg) && (msg.dst === 'all' || msg.dst === 'matter')) {
175
101
  if (this.verbose)
@@ -200,17 +126,9 @@ export class MatterNode extends EventEmitter {
200
126
  }
201
127
  }
202
128
  }
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
129
  async destroy(closeMdns = true) {
211
130
  if (this.verbose)
212
131
  this.log.debug(`Destroying MatterNode instance for ${this.storeId}...`);
213
- // Close mDNS service
214
132
  if (closeMdns) {
215
133
  if (this.verbose)
216
134
  this.log.debug(`Closing Matter MdnsService for ${this.storeId}...`);
@@ -218,31 +136,23 @@ export class MatterNode extends EventEmitter {
218
136
  if (this.verbose)
219
137
  this.log.debug(`Closed Matter MdnsService for ${this.storeId}`);
220
138
  }
221
- // Close the plugin manager
222
139
  this.pluginManager.destroy();
223
- // Close the broadcast server
224
140
  this.server.close();
225
- // Yield to the Node.js event loop to allow all resources to be released
226
141
  await this.yieldToNode();
227
142
  if (this.verbose)
228
143
  this.log.debug(`Destroyed MatterNode instance for ${this.storeId}`);
229
144
  }
230
145
  async create() {
231
146
  this.log.info('Creating Matter node...');
232
- // Start matter storage
233
147
  await this.startMatterStorage();
234
- // Load plugins from storage
235
- // @ts-expect-error access private property
236
148
  this.pluginManager.matterbridge.nodeStorage = new NodeStorageManager({
237
149
  dir: path.join(this.matterbridge.matterbridgeDirectory, NODE_STORAGE_DIR),
238
150
  writeQueue: false,
239
151
  expiredInterval: undefined,
240
152
  logging: false,
241
153
  });
242
- // @ts-expect-error access private property
243
154
  this.pluginManager.matterbridge.nodeContext = await this.pluginManager.matterbridge.nodeStorage.createStorage('matterbridge');
244
155
  await this.pluginManager.loadFromStorage();
245
- // Create Matter node for a server mode device
246
156
  if (this.pluginName && this.device && this.device.deviceName) {
247
157
  this.log.debug(`Creating MatterNode instance for server node device ${CYAN}${this.device.deviceName}${db}...`);
248
158
  await this.createDeviceServerNode(this.pluginName, this.device);
@@ -253,7 +163,6 @@ export class MatterNode extends EventEmitter {
253
163
  if (!this.pluginName) {
254
164
  this.log.debug('Creating MatterNode instance for all plugins...');
255
165
  await this.createMatterbridgeServerNode();
256
- // Load all enabled plugins
257
166
  this.log.debug('Loading all plugins...');
258
167
  const loadPromises = [];
259
168
  for (const plugin of this.pluginManager.array().filter((p) => p.enabled)) {
@@ -266,7 +175,6 @@ export class MatterNode extends EventEmitter {
266
175
  }
267
176
  else {
268
177
  this.log.debug(`Creating MatterNode instance for plugin ${CYAN}${this.pluginName}${db}...`);
269
- // Load only the specified plugin
270
178
  this.log.debug(`Loading plugin ${CYAN}${this.pluginName}${db}...`);
271
179
  await this.pluginManager.load(this.pluginName);
272
180
  this.log.debug(`Loaded plugin ${CYAN}${this.pluginName}${db}`);
@@ -280,16 +188,13 @@ export class MatterNode extends EventEmitter {
280
188
  if (!this.serverNode && !this.pluginName)
281
189
  throw new Error('Matter server node not created yet. Call create() first.');
282
190
  this.log.info('Starting MatterNode...');
283
- // Start Matter node for a server mode device
284
191
  if (this.pluginName && this.device && this.device.deviceName) {
285
- // Start the server node
286
192
  this.log.debug(`Starting MatterNode for server device ${this.pluginName}:${this.device.deviceName}...`);
287
193
  await this.startServerNode();
288
194
  this.log.debug(`Started MatterNode for server device ${this.pluginName}:${this.device.deviceName}`);
289
195
  return;
290
196
  }
291
197
  if (!this.pluginName) {
292
- // Start all loaded plugins
293
198
  this.log.debug('Starting all plugins...');
294
199
  const startPromises = [];
295
200
  for (const plugin of this.pluginManager.array().filter((p) => p.enabled && p.loaded)) {
@@ -297,11 +202,9 @@ export class MatterNode extends EventEmitter {
297
202
  }
298
203
  await Promise.all(startPromises);
299
204
  this.log.debug('Started all plugins');
300
- // Start the server node
301
205
  this.log.debug('Starting MatterNode for all plugins...');
302
206
  await this.startServerNode();
303
207
  this.log.debug('Started MatterNode for all plugins');
304
- // Configure all loaded plugins
305
208
  this.log.debug('Configuring all plugins...');
306
209
  const configurePromises = [];
307
210
  for (const plugin of this.pluginManager.array().filter((p) => p.enabled && p.started)) {
@@ -311,16 +214,12 @@ export class MatterNode extends EventEmitter {
311
214
  this.log.debug('Configured all plugins');
312
215
  }
313
216
  else {
314
- // Start the loaded plugin
315
217
  await this.pluginManager.start(this.pluginName, 'Starting MatterNode');
316
- // Start the server node
317
218
  this.log.debug(`Starting MatterNode for plugin ${this.pluginName}...`);
318
219
  await this.startServerNode();
319
220
  this.log.debug(`Started MatterNode for plugin ${this.pluginName}`);
320
- // Configure the plugin
321
221
  await this.pluginManager.configure(this.pluginName);
322
222
  }
323
- // Start the dependant MatterNodes
324
223
  this.log.debug(`Starting dependant MatterNodes...`);
325
224
  for (const dependantMatterNode of this.dependantMatterNodes.values()) {
326
225
  await dependantMatterNode.start();
@@ -333,15 +232,13 @@ export class MatterNode extends EventEmitter {
333
232
  if (!this.serverNode)
334
233
  throw new Error('Matter server node not created yet. Call create() first.');
335
234
  this.log.info('Stopping MatterNode...');
336
- // Stop Matter node for a server mode device
337
235
  if (this.pluginName && this.device && this.device.deviceName) {
338
- // Stop the server node
339
236
  this.log.debug(`Stopping MatterNode for server device ${this.pluginName}:${this.device.deviceName}...`);
340
237
  await this.stopServerNode();
341
238
  this.serverNode = undefined;
342
239
  this.aggregatorNode = undefined;
343
240
  await this.stopMatterStorage();
344
- await this.destroy(false); // Do not close mDNS since it is shared
241
+ await this.destroy(false);
345
242
  this.log.debug(`Stopped MatterNode for server device ${this.pluginName}:${this.device.deviceName}`);
346
243
  this.log.info('Stopped MatterNode');
347
244
  await this.yieldToNode();
@@ -361,7 +258,6 @@ export class MatterNode extends EventEmitter {
361
258
  await this.pluginManager.shutdown(this.pluginName, 'Stopping MatterNode');
362
259
  this.log.debug(`Stopped plugin ${this.pluginName}`);
363
260
  }
364
- // Stop the dependant MatterNodes
365
261
  this.log.debug(`Stopping dependant MatterNodes...`);
366
262
  for (const dependantMatterNode of this.dependantMatterNodes.values()) {
367
263
  await dependantMatterNode.stop();
@@ -374,46 +270,24 @@ export class MatterNode extends EventEmitter {
374
270
  this.log.info('Stopped MatterNode');
375
271
  await this.yieldToNode();
376
272
  }
377
- /**
378
- * Creates a MatterLogger function to show the matter.js log messages in AnsiLogger (console and frontend).
379
- * It also logs to file (matter.log) if fileLogger is true.
380
- *
381
- * @returns {(text: string, message: Diagnostic.Message) => void} The MatterLogger function to be used in Logger.destinations.default.write.
382
- */
383
273
  createDestinationMatterLogger() {
384
- this.matterLog.logNameColor = '\x1b[34m'; // Blue matter.js Logger
274
+ this.matterLog.logNameColor = '\x1b[34m';
385
275
  if (this.matterbridge.matterFileLogger) {
386
276
  this.matterLog.logFilePath = path.join(this.matterbridge.matterbridgeDirectory, MATTER_LOGGER_FILE);
387
277
  }
388
278
  return (text, message) => {
389
- // 2024-08-21 08:55:19.488 DEBUG InteractionMessenger Sending DataReport chunk with 28 attributes and 0 events: 1004 bytes
390
279
  const logger = text.slice(44, 44 + 20).trim();
391
280
  const msg = text.slice(65);
392
281
  this.matterLog.logName = logger;
393
282
  this.matterLog.log(MatterLogLevel.names[message.level], msg);
394
283
  };
395
284
  }
396
- /**
397
- * Starts the matter storage with name Matterbridge and performs a backup.
398
- *
399
- * @returns {Promise<void>} - A promise that resolves when the storage is started.
400
- */
401
285
  async startMatterStorage() {
402
- // Setup Matter storage
403
286
  this.log.info(`Starting matter node storage...`);
404
287
  this.matterStorageService = this.environment.get(StorageService);
405
288
  this.log.info(`Started matter node storage in ${CYAN}${this.matterStorageService.location}${nf}`);
406
- // Backup matter storage since it is created/opened correctly
407
289
  await this.backupMatterStorage(path.join(this.matterbridge.matterbridgeDirectory, MATTER_STORAGE_NAME), path.join(this.matterbridge.matterbridgeDirectory, MATTER_STORAGE_NAME + '.backup'));
408
290
  }
409
- /**
410
- * Makes a backup copy of the specified matter storage directory.
411
- *
412
- * @param {string} storageName - The name of the storage directory to be backed up.
413
- * @param {string} backupName - The name of the backup directory to be created.
414
- * @private
415
- * @returns {Promise<void>} A promise that resolves when the has been done.
416
- */
417
291
  async backupMatterStorage(storageName, backupName) {
418
292
  this.log.info(`Creating matter node storage backup from ${CYAN}${storageName}${nf} to ${CYAN}${backupName}${nf}...`);
419
293
  try {
@@ -421,7 +295,6 @@ export class MatterNode extends EventEmitter {
421
295
  this.log.info('Created matter node storage backup');
422
296
  }
423
297
  catch (error) {
424
- // istanbul ignore next if
425
298
  if (error instanceof Error && error?.code === 'ENOENT') {
426
299
  this.log.info(`No matter node storage found to backup from ${CYAN}${storageName}${nf} to ${CYAN}${backupName}${nf}`);
427
300
  }
@@ -430,11 +303,6 @@ export class MatterNode extends EventEmitter {
430
303
  }
431
304
  }
432
305
  }
433
- /**
434
- * Stops the matter storage.
435
- *
436
- * @returns {Promise<void>} A promise that resolves when the storage is stopped.
437
- */
438
306
  async stopMatterStorage() {
439
307
  this.log.info('Closing matter node storage...');
440
308
  await this.matterStorageManager?.close();
@@ -444,21 +312,6 @@ export class MatterNode extends EventEmitter {
444
312
  this.log.info('Closed matter node storage');
445
313
  this.emit('closed');
446
314
  }
447
- /**
448
- * Creates a server node storage context.
449
- *
450
- * @param {string} storeId - The storeId.
451
- * @param {string} deviceName - The name of the device.
452
- * @param {DeviceTypeId} deviceType - The device type of the device.
453
- * @param {VendorId} vendorId - The vendor ID.
454
- * @param {string} vendorName - The vendor name.
455
- * @param {number} productId - The product ID.
456
- * @param {string} productName - The product name.
457
- * @param {string} [serialNumber] - The serial number of the device (optional).
458
- * @param {string} [uniqueId] - The unique ID of the device (optional).
459
- * @returns {Promise<StorageContext>} The storage context for the commissioning server.
460
- * @throws {Error} If the storage service is not initialized.
461
- */
462
315
  async createServerNodeContext(storeId, deviceName, deviceType, vendorId, vendorName, productId, productName, serialNumber, uniqueId) {
463
316
  if (!this.matterStorageService) {
464
317
  throw new Error('No storage service initialized');
@@ -501,52 +354,33 @@ export class MatterNode extends EventEmitter {
501
354
  this.log.debug(`- hardwareVersionString: ${await storageContext.get('hardwareVersionString')}`);
502
355
  return storageContext;
503
356
  }
504
- /**
505
- * Creates a server node.
506
- *
507
- * @param {number} [port] - The port number for the server node. Defaults to 5540.
508
- * @param {number} [passcode] - The passcode for the server node. Defaults to 20242025.
509
- * @param {number} [discriminator] - The discriminator for the server node. Defaults to 3850.
510
- * @returns {Promise<ServerNode<ServerNode.RootEndpoint>>} A promise that resolves to the created server node.
511
- * @throws {Error} If the matter storage context is not created yet.
512
- */
513
357
  async createServerNode(port = 5540, passcode = 20252026, discriminator = 3850) {
514
358
  if (!this.matterStorageContext) {
515
359
  throw new Error('Matter server node context not created yet. Call createServerNodeContext() first.');
516
360
  }
517
361
  const storeId = await this.matterStorageContext.get('storeId');
518
362
  this.log.notice(`Creating server node for ${storeId} on port ${port} with passcode ${passcode} and discriminator ${discriminator}...`);
519
- /**
520
- * Create a Matter ServerNode, which contains the Root Endpoint and all relevant data and configuration
521
- */
522
363
  const serverNode = await ServerNode.create({
523
- // Required: Give the Node a unique ID which is used to store the state of this node
524
364
  id: storeId,
525
- // Provide the environment to run this node in
526
365
  environment: this.environment,
527
- // Provide Network relevant configuration like the port
528
366
  network: {
529
367
  listeningAddressIpv4: this.ipv4Address,
530
368
  listeningAddressIpv6: this.ipv6Address,
531
369
  port,
532
370
  },
533
- // Provide the certificate for the device
534
371
  operationalCredentials: {
535
372
  certification: this.certification,
536
373
  },
537
- // Provide Commissioning relevant settings
538
374
  commissioning: {
539
375
  passcode,
540
376
  discriminator,
541
377
  },
542
- // Provide Node announcement settings
543
378
  productDescription: {
544
379
  name: await this.matterStorageContext.get('deviceName'),
545
380
  deviceType: DeviceTypeId(await this.matterStorageContext.get('deviceType')),
546
381
  vendorId: VendorId(await this.matterStorageContext.get('vendorId')),
547
382
  productId: await this.matterStorageContext.get('productId'),
548
383
  },
549
- // Provide defaults for the BasicInformation cluster on the Root endpoint
550
384
  basicInformation: {
551
385
  vendorId: VendorId(await this.matterStorageContext.get('vendorId')),
552
386
  vendorName: await this.matterStorageContext.get('vendorName'),
@@ -563,23 +397,17 @@ export class MatterNode extends EventEmitter {
563
397
  reachable: true,
564
398
  },
565
399
  });
566
- /**
567
- * This event is triggered when the device is initially commissioned successfully.
568
- * This means: It is added to the first fabric.
569
- */
570
400
  serverNode.lifecycle.commissioned.on(() => {
571
401
  this.log.notice(`Server node for ${storeId} was initially commissioned successfully!`);
572
402
  this.advertisingNodes.delete(storeId);
573
403
  this.server.request({ type: 'frontend_refreshrequired', src: 'matter', dst: 'frontend', params: { changed: 'matter', matter: { ...this.getServerNodeData(serverNode) } } });
574
404
  });
575
- /** This event is triggered when all fabrics are removed from the device, usually it also does a factory reset then. */
576
405
  serverNode.lifecycle.decommissioned.on(() => {
577
406
  this.log.notice(`Server node for ${storeId} was fully decommissioned successfully!`);
578
407
  this.advertisingNodes.delete(storeId);
579
408
  this.server.request({ type: 'frontend_refreshrequired', src: 'matter', dst: 'frontend', params: { changed: 'matter', matter: { ...this.getServerNodeData(serverNode) } } });
580
409
  this.server.request({ type: 'frontend_snackbarmessage', src: 'matter', dst: 'frontend', params: { message: `${storeId} is offline`, timeout: 5, severity: 'warning' } });
581
410
  });
582
- /** This event is triggered when the device went online. This means that it is discoverable in the network. */
583
411
  serverNode.lifecycle.online.on(async () => {
584
412
  this.log.notice(`Server node for ${storeId} is online`);
585
413
  if (!serverNode.lifecycle.isCommissioned) {
@@ -597,7 +425,6 @@ export class MatterNode extends EventEmitter {
597
425
  this.server.request({ type: 'frontend_snackbarmessage', src: 'matter', dst: 'frontend', params: { message: `${storeId} is online`, timeout: 5, severity: 'success' } });
598
426
  this.emit('online', storeId);
599
427
  });
600
- /** This event is triggered when the device went offline. it is not longer discoverable or connectable in the network. */
601
428
  serverNode.lifecycle.offline.on(() => {
602
429
  this.log.notice(`Server node for ${storeId} is offline`);
603
430
  this.advertisingNodes.delete(storeId);
@@ -605,15 +432,11 @@ export class MatterNode extends EventEmitter {
605
432
  this.server.request({ type: 'frontend_snackbarmessage', src: 'matter', dst: 'frontend', params: { message: `${storeId} is offline`, timeout: 5, severity: 'warning' } });
606
433
  this.emit('offline', storeId);
607
434
  });
608
- /**
609
- * This event is triggered when a fabric is added, removed or updated on the device. Use this if more granular
610
- * information is needed.
611
- */
612
435
  serverNode.events.commissioning.fabricsChanged.on((fabricIndex, fabricAction) => {
613
436
  let action = '';
614
437
  switch (fabricAction) {
615
438
  case 'added':
616
- this.advertisingNodes.delete(storeId); // The advertising stops when a fabric is added
439
+ this.advertisingNodes.delete(storeId);
617
440
  action = 'added';
618
441
  break;
619
442
  case 'deleted':
@@ -626,22 +449,14 @@ export class MatterNode extends EventEmitter {
626
449
  this.log.notice(`Commissioned fabric index ${fabricIndex} ${action} on server node for ${storeId}: ${debugStringify(serverNode.state.commissioning.fabrics[fabricIndex])}`);
627
450
  this.server.request({ type: 'frontend_refreshrequired', src: 'matter', dst: 'frontend', params: { changed: 'matter', matter: { ...this.getServerNodeData(serverNode) } } });
628
451
  });
629
- /**
630
- * This event is triggered when an operative new session was opened by a Controller.
631
- * It is not triggered for the initial commissioning process, just afterwards for real connections.
632
- */
633
452
  serverNode.events.sessions.opened.on((session) => {
634
453
  this.log.notice(`Session opened on server node for ${storeId}: ${debugStringify(session)}`);
635
454
  this.server.request({ type: 'frontend_refreshrequired', src: 'matter', dst: 'frontend', params: { changed: 'matter', matter: { ...this.getServerNodeData(serverNode) } } });
636
455
  });
637
- /**
638
- * This event is triggered when an operative session is closed by a Controller or because the Device goes offline.
639
- */
640
456
  serverNode.events.sessions.closed.on((session) => {
641
457
  this.log.notice(`Session closed on server node for ${storeId}: ${debugStringify(session)}`);
642
458
  this.server.request({ type: 'frontend_refreshrequired', src: 'matter', dst: 'frontend', params: { changed: 'matter', matter: { ...this.getServerNodeData(serverNode) } } });
643
459
  });
644
- /** This event is triggered when a subscription gets added or removed on an operative session. */
645
460
  serverNode.events.sessions.subscriptionsChanged.on((session) => {
646
461
  this.log.notice(`Session subscriptions changed on server node for ${storeId}: ${debugStringify(session)}`);
647
462
  this.server.request({ type: 'frontend_refreshrequired', src: 'matter', dst: 'frontend', params: { changed: 'matter', matter: { ...this.getServerNodeData(serverNode) } } });
@@ -650,12 +465,6 @@ export class MatterNode extends EventEmitter {
650
465
  this.log.info(`Created server node for ${this.storeId}`);
651
466
  return serverNode;
652
467
  }
653
- /**
654
- * Gets the matter serializable data of the specified server node.
655
- *
656
- * @param {ServerNode} [serverNode] - The server node to start.
657
- * @returns {ApiMatter} The serializable data of the server node.
658
- */
659
468
  getServerNodeData(serverNode) {
660
469
  const advertiseTime = this.advertisingNodes.get(serverNode.id) || 0;
661
470
  return {
@@ -672,13 +481,6 @@ export class MatterNode extends EventEmitter {
672
481
  serialNumber: serverNode.state.basicInformation.serialNumber,
673
482
  };
674
483
  }
675
- /**
676
- * Starts the specified server node.
677
- *
678
- * @param {number} [timeout] - The timeout in milliseconds for starting the server node. Defaults to 30 seconds.
679
- * @returns {Promise<void>} A promise that resolves when the server node has started.
680
- * @throws {Error} If the server node is not created yet.
681
- */
682
484
  async startServerNode(timeout = 30000) {
683
485
  if (!this.serverNode) {
684
486
  throw new Error('Matter server node not created yet. Call create() first.');
@@ -689,17 +491,9 @@ export class MatterNode extends EventEmitter {
689
491
  this.log.notice(`Started ${this.serverNode.id} server node`);
690
492
  }
691
493
  catch (error) {
692
- // istanbul ignore next
693
494
  this.log.error(`Failed to start ${this.serverNode.id} server node: ${error instanceof Error ? error.message : error}`);
694
495
  }
695
496
  }
696
- /**
697
- * Stops the specified server node.
698
- *
699
- * @param {number} [timeout] - The timeout in milliseconds for stopping the server node. Defaults to 30 seconds.
700
- * @returns {Promise<void>} A promise that resolves when the server node has stopped.
701
- * @throws {Error} If the server node is not created yet.
702
- */
703
497
  async stopServerNode(timeout = 30000) {
704
498
  if (!this.serverNode) {
705
499
  throw new Error('Matter server node not created yet. Call create() first.');
@@ -710,16 +504,9 @@ export class MatterNode extends EventEmitter {
710
504
  this.log.info(`Closed ${this.serverNode.id} server node`);
711
505
  }
712
506
  catch (error) {
713
- // istanbul ignore next
714
507
  this.log.error(`Failed to close ${this.serverNode.id} server node: ${error instanceof Error ? error.message : error}`);
715
508
  }
716
509
  }
717
- /**
718
- * Creates an aggregator node with the specified storage context.
719
- *
720
- * @returns {Promise<Endpoint<AggregatorEndpoint>>} A promise that resolves to the created aggregator node.
721
- * @throws {Error} If the matter storage context is not created yet.
722
- */
723
510
  async createAggregatorNode() {
724
511
  if (!this.matterStorageContext) {
725
512
  throw new Error('Matter server node context not created yet. Call createServerNodeContext() first.');
@@ -729,16 +516,9 @@ export class MatterNode extends EventEmitter {
729
516
  this.log.info(`Created ${await this.matterStorageContext.get('storeId')} aggregator`);
730
517
  return aggregatorNode;
731
518
  }
732
- /**
733
- * Creates the matterbridge server node.
734
- *
735
- * @returns {Promise<ServerNode<ServerNode.RootEndpoint>>} A promise that resolves to the created matterbridge server node.
736
- */
737
519
  async createMatterbridgeServerNode() {
738
520
  this.log.debug(`Creating ${plg}Matterbridge${db} server node...`);
739
- this.matterStorageContext = await this.createServerNodeContext('Matterbridge', // storeId
740
- 'Matterbridge', // deviceName
741
- this.aggregatorDeviceType, this.aggregatorVendorId, this.aggregatorVendorName, this.aggregatorProductId, this.aggregatorProductName, this.aggregatorSerialNumber, this.aggregatorUniqueId);
521
+ this.matterStorageContext = await this.createServerNodeContext('Matterbridge', 'Matterbridge', this.aggregatorDeviceType, this.aggregatorVendorId, this.aggregatorVendorName, this.aggregatorProductId, this.aggregatorProductName, this.aggregatorSerialNumber, this.aggregatorUniqueId);
742
522
  this.serverNode = await this.createServerNode(this.port ? this.port++ : undefined, this.passcode ? this.passcode++ : undefined, this.discriminator ? this.discriminator++ : undefined);
743
523
  this.aggregatorNode = await this.createAggregatorNode();
744
524
  this.log.debug(`Adding ${plg}Matterbridge${db} aggregator node...`);
@@ -749,13 +529,6 @@ export class MatterNode extends EventEmitter {
749
529
  this.log.debug(`Created ${plg}Matterbridge${db} server node`);
750
530
  return this.serverNode;
751
531
  }
752
- /**
753
- * Creates and configures the server node for an accessory plugin for a given device.
754
- *
755
- * @param {Plugin | PluginName} plugin - The plugin to configure.
756
- * @param {MatterbridgeEndpoint} device - The device to associate with the plugin.
757
- * @returns {Promise<ServerNode<ServerNode.RootEndpoint> | undefined>} A promise that resolves to the server node for the accessory plugin.
758
- */
759
532
  async createAccessoryPlugin(plugin, device) {
760
533
  if (typeof plugin === 'string') {
761
534
  const _plugin = this.pluginManager.get(plugin);
@@ -777,12 +550,6 @@ export class MatterNode extends EventEmitter {
777
550
  }
778
551
  return this.serverNode;
779
552
  }
780
- /**
781
- * Creates and configures the server node and the aggregator node for a dynamic plugin.
782
- *
783
- * @param {Plugin | PluginName} plugin - The plugin to configure.
784
- * @returns {Promise<ServerNode<ServerNode.RootEndpoint> | undefined>} A promise that resolves to the server node for the dynamic plugin.
785
- */
786
553
  async createDynamicPlugin(plugin) {
787
554
  if (typeof plugin === 'string') {
788
555
  const _plugin = this.pluginManager.get(plugin);
@@ -806,13 +573,6 @@ export class MatterNode extends EventEmitter {
806
573
  }
807
574
  return this.serverNode;
808
575
  }
809
- /**
810
- * Creates and configures the server node for a single not bridged device.
811
- *
812
- * @param {Plugin | PluginName} plugin - The plugin to configure.
813
- * @param {MatterbridgeEndpoint} device - The device to associate with the plugin.
814
- * @returns {Promise<ServerNode<ServerNode.RootEndpoint> | undefined>} A promise that resolves to the server node for the device with mode server.
815
- */
816
576
  async createDeviceServerNode(plugin, device) {
817
577
  if (typeof plugin === 'string') {
818
578
  const _plugin = this.pluginManager.get(plugin);
@@ -833,22 +593,13 @@ export class MatterNode extends EventEmitter {
833
593
  }
834
594
  return this.serverNode;
835
595
  }
836
- /**
837
- * Adds a MatterbridgeEndpoint to the specified plugin.
838
- *
839
- * @param {string} pluginName - The name of the plugin.
840
- * @param {MatterbridgeEndpoint} device - The device to add as a bridged endpoint.
841
- * @returns {Promise<MatterbridgeEndpoint | undefined>} A promise that resolves to the added bridged endpoint, or undefined if there was an error.
842
- */
843
596
  async addBridgedEndpoint(pluginName, device) {
844
- // Check if the plugin is registered
845
597
  const plugin = this.pluginManager.get(pluginName);
846
598
  if (!plugin)
847
599
  throw new Error(`Error adding bridged endpoint ${plg}${pluginName}${er}:${dev}${device.deviceName}${er} (${zb}${device.name}${er}): plugin not found`);
848
600
  if (device.mode === 'server') {
849
601
  try {
850
602
  this.log.debug(`Creating MatterNode for device ${plg}${pluginName}${db}:${dev}${device.deviceName}${db} (${zb}${device.name}${db})...`);
851
- // Create the MatterNode to manage the device
852
603
  const matterNode = new MatterNode(this.matterbridge, pluginName, device);
853
604
  matterNode.port = this.port ? this.port++ : undefined;
854
605
  matterNode.passcode = this.passcode ? this.passcode++ : undefined;
@@ -864,7 +615,6 @@ export class MatterNode extends EventEmitter {
864
615
  }
865
616
  else if (this.matterbridge.bridgeMode === 'bridge') {
866
617
  if (device.mode === 'matter') {
867
- // Register and add the device to the Matter server node
868
618
  this.log.debug(`Adding matter endpoint ${plg}${pluginName}${db}:${dev}${device.deviceName}${db} (${zb}${device.name}${db})...`);
869
619
  if (!this.serverNode)
870
620
  throw new Error(`Server node not found for matter endpoint ${plg}${pluginName}${er}:${dev}${device.deviceName}${er} (${zb}${device.name}${er})`);
@@ -877,7 +627,6 @@ export class MatterNode extends EventEmitter {
877
627
  }
878
628
  }
879
629
  else {
880
- // Register and add the device to the Matter aggregator node
881
630
  this.log.debug(`Adding bridged endpoint ${plg}${pluginName}${db}:${dev}${device.deviceName}${db} (${zb}${device.name}${db})...`);
882
631
  if (!this.aggregatorNode)
883
632
  throw new Error(`Aggregator node not found for endpoint ${plg}${pluginName}${er}:${dev}${device.deviceName}${er} (${zb}${device.name}${er})`);
@@ -891,7 +640,6 @@ export class MatterNode extends EventEmitter {
891
640
  }
892
641
  }
893
642
  else if (this.matterbridge.bridgeMode === 'childbridge') {
894
- // Register and add the device to the plugin server node
895
643
  if (plugin.type === 'AccessoryPlatform') {
896
644
  try {
897
645
  this.log.debug(`Adding accessory endpoint ${plg}${pluginName}${db}:${dev}${device.deviceName}${db} (${zb}${device.name}${db})...`);
@@ -907,12 +655,10 @@ export class MatterNode extends EventEmitter {
907
655
  return;
908
656
  }
909
657
  }
910
- // Register and add the device to the plugin aggregator node
911
658
  if (plugin.type === 'DynamicPlatform') {
912
659
  try {
913
660
  this.log.debug(`Adding bridged endpoint ${plg}${pluginName}${db}:${dev}${device.deviceName}${db} (${zb}${device.name}${db})...`);
914
661
  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
662
  await this.createDynamicPlugin(plugin);
917
663
  }
918
664
  if (device.mode === 'matter')
@@ -928,30 +674,19 @@ export class MatterNode extends EventEmitter {
928
674
  }
929
675
  if (plugin.registeredDevices !== undefined)
930
676
  plugin.registeredDevices++;
931
- // Add the device to the DeviceManager
932
677
  await device.construction.ready;
933
678
  await this.server.fetch({ type: 'devices_set', src: this.server.name, dst: 'devices', params: { device: toBaseDevice(device) } });
934
- // Subscribe to the attributes changed event
935
679
  await this.subscribeAttributeChanged(plugin, device);
936
680
  this.log.info(`Added endpoint #${plugin.registeredDevices} ${plg}${pluginName}${nf}:${dev}${device.deviceName}${nf} (${zb}${device.name}${nf})`);
937
681
  await this.yieldToNode(10);
938
682
  return device;
939
683
  }
940
- /**
941
- * Removes a MatterbridgeEndpoint from the specified plugin.
942
- *
943
- * @param {string} pluginName - The name of the plugin.
944
- * @param {MatterbridgeEndpoint} device - The device to remove as a bridged endpoint.
945
- * @returns {Promise<MatterbridgeEndpoint | undefined>} A promise that resolves to the removed bridged endpoint, or undefined if there was an error.
946
- */
947
684
  async removeBridgedEndpoint(pluginName, device) {
948
685
  this.log.debug(`Removing bridged endpoint ${plg}${pluginName}${db}:${dev}${device.deviceName}${db} (${zb}${device.name}${db})...`);
949
- // Check if the plugin is registered
950
686
  const plugin = this.pluginManager.get(pluginName);
951
687
  if (!plugin)
952
688
  throw new Error(`Error removing bridged endpoint ${plg}${pluginName}${er}:${dev}${device.deviceName}${er} (${zb}${device.name}${er}): plugin not found`);
953
689
  if (device.serverNode) {
954
- // TODO: Close and remove the MatterNode managing the device
955
690
  }
956
691
  else if (this.matterbridge.bridgeMode === 'bridge') {
957
692
  if (!this.aggregatorNode)
@@ -973,25 +708,11 @@ export class MatterNode extends EventEmitter {
973
708
  this.log.info(`Removed bridged endpoint #${plugin.registeredDevices} ${plg}${pluginName}${nf}:${dev}${device.deviceName}${nf} (${zb}${device.name}${nf})`);
974
709
  if (plugin.registeredDevices !== undefined)
975
710
  plugin.registeredDevices--;
976
- // Remove the device from the DeviceManager
977
711
  await this.server.fetch({ type: 'devices_remove', src: this.server.name, dst: 'devices', params: { device: toBaseDevice(device) } });
978
712
  await this.yieldToNode(10);
979
713
  return device;
980
714
  }
981
- /**
982
- * Removes all bridged endpoints from the specified plugin.
983
- *
984
- * @param {string} pluginName - The name of the plugin.
985
- * @param {number} [delay] - The delay in milliseconds between removing each bridged endpoint (default: 0).
986
- * @returns {Promise<void>} A promise that resolves when all bridged endpoints have been removed.
987
- *
988
- * @remarks
989
- * This method iterates through all devices in the DeviceManager and removes each bridged endpoint associated with the specified plugin.
990
- * It also applies a delay between each removal if specified.
991
- * The delay is useful to allow the controllers to receive a single subscription for each device removed.
992
- */
993
715
  async removeAllBridgedEndpoints(pluginName, delay = 0) {
994
- // Check if the plugin is registered
995
716
  const plugin = this.pluginManager.get(pluginName);
996
717
  if (!plugin)
997
718
  throw new Error(`Error removing all bridged endpoints for plugin ${plg}${pluginName}${er}: plugin not found`);
@@ -1006,7 +727,6 @@ export class MatterNode extends EventEmitter {
1006
727
  this.log.info(`Removed bridged endpoint #${plugin.registeredDevices} ${plg}${pluginName}${nf}:${dev}${device.deviceName}${nf} (${zb}${endpoint?.name}${nf})`);
1007
728
  if (plugin.registeredDevices !== undefined)
1008
729
  plugin.registeredDevices--;
1009
- // Remove the device from the DeviceManager
1010
730
  await this.server.fetch({ type: 'devices_remove', src: this.server.name, dst: 'devices', params: { device: toBaseDevice(device) } });
1011
731
  await this.yieldToNode(10);
1012
732
  if (delay > 0)
@@ -1015,25 +735,6 @@ export class MatterNode extends EventEmitter {
1015
735
  if (delay > 0)
1016
736
  await wait(Number(process.env['MATTERBRIDGE_REMOVE_ALL_ENDPOINT_TIMEOUT_MS']) || 2000);
1017
737
  }
1018
- /**
1019
- * Registers a virtual device with the Matterbridge platform.
1020
- * Virtual devices are only supported in bridge mode and childbridge mode with a DynamicPlatform.
1021
- *
1022
- * The virtual device is created as an instance of `Endpoint` with the provided device type.
1023
- * When the virtual device is turned on, the provided callback function is executed.
1024
- * The onOff state of the virtual device always reverts to false when the device is turned on.
1025
- *
1026
- * @param {string} pluginName - The name of the plugin.
1027
- * @param { string } name - The name of the virtual device.
1028
- * @param { 'light' | 'outlet' | 'switch' | 'mounted_switch' } type - The type of the virtual device.
1029
- * @param { () => Promise<void> } callback - The callback to call when the virtual device is turned on.
1030
- *
1031
- * @returns {Promise<boolean>} A promise that resolves to true if the virtual device was successfully registered, false otherwise.
1032
- *
1033
- * @remarks
1034
- * The virtual devices don't show up in the device list of the frontend.
1035
- * Type 'switch' is not supported by Alexa and 'mounted_switch' is not supported by Apple Home.
1036
- */
1037
738
  async addVirtualEndpoint(pluginName, name, type, callback) {
1038
739
  this.log.debug(`Creating virtual device ${plg}${pluginName}${db}:${dev}${name}${db}...`);
1039
740
  const plugin = this.pluginManager.get(pluginName);
@@ -1058,20 +759,10 @@ export class MatterNode extends EventEmitter {
1058
759
  await this.yieldToNode(10);
1059
760
  return true;
1060
761
  }
1061
- /**
1062
- * Subscribes to the attribute change event for the given device and plugin.
1063
- * Specifically, it listens for changes in the 'reachable' attribute of the
1064
- * BridgedDeviceBasicInformationServer cluster server of the bridged device or BasicInformationServer cluster server of server node.
1065
- *
1066
- * @param {Plugin} plugin - The plugin associated with the device.
1067
- * @param {MatterbridgeEndpoint} device - The device to subscribe to attribute changes for.
1068
- * @returns {Promise<void>} A promise that resolves when the subscription is set up.
1069
- */
1070
762
  async subscribeAttributeChanged(plugin, device) {
1071
763
  if (!plugin || !device || !device.plugin || !device.serialNumber || !device.uniqueId || !device.maybeNumber)
1072
764
  return;
1073
765
  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})`);
1074
- // Subscribe to the reachable$Changed event of the BasicInformationServer cluster server of the server node in childbridge mode
1075
766
  if (this.matterbridge.bridgeMode === 'childbridge' && plugin.type === 'AccessoryPlatform' && this.serverNode) {
1076
767
  this.serverNode.eventsOf(BasicInformationServer).reachable$Changed?.on((reachable) => {
1077
768
  if (!device.plugin || !device.serialNumber || !device.uniqueId)
@@ -1184,12 +875,6 @@ export class MatterNode extends EventEmitter {
1184
875
  }
1185
876
  }
1186
877
  }
1187
- /**
1188
- * Sanitizes the fabric information by converting bigint properties to strings because `res.json` doesn't support bigint.
1189
- *
1190
- * @param {ExposedFabricInformation[]} fabricInfo - The array of exposed fabric information objects.
1191
- * @returns {SanitizedExposedFabricInformation[]} An array of sanitized exposed fabric information objects.
1192
- */
1193
878
  sanitizeFabricInformations(fabricInfo) {
1194
879
  return fabricInfo.map((info) => {
1195
880
  return {
@@ -1203,12 +888,6 @@ export class MatterNode extends EventEmitter {
1203
888
  };
1204
889
  });
1205
890
  }
1206
- /**
1207
- * Sanitizes the session information by converting bigint properties to strings because `res.json` doesn't support bigint.
1208
- *
1209
- * @param {SessionsBehavior.Session[]} sessions - The array of session information objects.
1210
- * @returns {SanitizedSession[]} An array of sanitized session information objects.
1211
- */
1212
891
  sanitizeSessionInformation(sessions) {
1213
892
  return sessions
1214
893
  .filter((session) => session.isPeerActive)
@@ -1235,21 +914,10 @@ export class MatterNode extends EventEmitter {
1235
914
  };
1236
915
  });
1237
916
  }
1238
- /**
1239
- * Sets the reachability of the specified server node and trigger the corresponding event.
1240
- *
1241
- * @param {boolean} reachable - A boolean indicating the reachability status to set.
1242
- */
1243
917
  async setServerReachability(reachable) {
1244
918
  await this.serverNode?.setStateOf(BasicInformationServer, { reachable });
1245
919
  this.serverNode?.act((agent) => this.serverNode?.eventsOf(BasicInformationServer).reachableChanged?.emit({ reachableNewValue: reachable }, agent.context));
1246
920
  }
1247
- /**
1248
- * Sets the reachability of the specified aggregator node bridged devices and trigger.
1249
- *
1250
- * @param {Endpoint<AggregatorEndpoint>} aggregatorNode - The aggregator node to set the reachability for.
1251
- * @param {boolean} reachable - A boolean indicating the reachability status to set.
1252
- */
1253
921
  async setAggregatorReachability(aggregatorNode, reachable) {
1254
922
  for (const child of aggregatorNode.parts) {
1255
923
  this.log.debug(`Setting reachability of ${child?.deviceName} to ${reachable}`);
@@ -1295,35 +963,19 @@ export class MatterNode extends EventEmitter {
1295
963
  case 0x1488:
1296
964
  vendorName = '(ShortcutLabsFlic)';
1297
965
  break;
1298
- case 65521: // 0xFFF1
966
+ case 65521:
1299
967
  vendorName = '(MatterTest)';
1300
968
  break;
1301
969
  }
1302
970
  return vendorName;
1303
971
  };
1304
- /**
1305
- * Yield to the Node.js event loop:
1306
- * 1. Flushes the current microtask queue (Promise/async continuations queued so far).
1307
- * 2. Yields one macrotask turn (setImmediate) and then its microtasks.
1308
- * 3. Waits a bit (setTimeout) to allow other macrotasks to run.
1309
- *
1310
- * This does **not** guarantee that every promise in the process is settled,
1311
- * but it gives all already-scheduled work a very good chance to run before continuing.
1312
- *
1313
- * @param {number} [timeout] - Optional timeout in milliseconds to wait after yielding. Default is 100 ms (minimum 10 ms).
1314
- * @returns {Promise<void>}
1315
- */
1316
972
  async yieldToNode(timeout = 100) {
1317
- // 1. Let all currently queued microtasks run
1318
973
  await Promise.resolve();
1319
- // 2. Yield to the next event-loop turn (macrotask + its microtasks)
1320
974
  await new Promise((resolve) => {
1321
975
  setImmediate(resolve);
1322
976
  });
1323
- // 3. Pause a bit to allow other macrotasks to run
1324
977
  await new Promise((resolve) => {
1325
978
  setTimeout(resolve, Math.min(timeout, 10));
1326
979
  });
1327
980
  }
1328
981
  }
1329
- //# sourceMappingURL=matterNode.js.map