matterbridge 3.2.6 → 3.2.7-dev-20250908-3bb699e

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 (279) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/cli.js +2 -91
  3. package/dist/cliEmitter.js +0 -30
  4. package/dist/clusters/export.js +0 -2
  5. package/dist/defaultConfigSchema.js +3 -24
  6. package/dist/deviceManager.js +1 -94
  7. package/dist/devices/airConditioner.js +0 -57
  8. package/dist/devices/batteryStorage.js +1 -48
  9. package/dist/devices/cooktop.js +0 -55
  10. package/dist/devices/dishwasher.js +0 -57
  11. package/dist/devices/evse.js +10 -74
  12. package/dist/devices/export.js +0 -5
  13. package/dist/devices/extractorHood.js +0 -42
  14. package/dist/devices/heatPump.js +2 -50
  15. package/dist/devices/laundryDryer.js +3 -62
  16. package/dist/devices/laundryWasher.js +4 -70
  17. package/dist/devices/microwaveOven.js +5 -88
  18. package/dist/devices/oven.js +0 -85
  19. package/dist/devices/refrigerator.js +0 -102
  20. package/dist/devices/roboticVacuumCleaner.js +9 -100
  21. package/dist/devices/solarPower.js +0 -38
  22. package/dist/devices/speaker.js +0 -80
  23. package/dist/devices/temperatureControl.js +3 -25
  24. package/dist/devices/waterHeater.js +2 -82
  25. package/dist/dgram/coap.js +13 -126
  26. package/dist/dgram/dgram.js +2 -114
  27. package/dist/dgram/mb_coap.js +3 -41
  28. package/dist/dgram/mb_mdns.js +15 -80
  29. package/dist/dgram/mdns.js +137 -299
  30. package/dist/dgram/multicast.js +1 -62
  31. package/dist/dgram/unicast.js +0 -54
  32. package/dist/frontend.js +24 -450
  33. package/dist/globalMatterbridge.js +0 -47
  34. package/dist/helpers.js +0 -53
  35. package/dist/index.js +1 -30
  36. package/dist/jest-utils/jestHelpers.js +2 -124
  37. package/dist/logger/export.js +0 -1
  38. package/dist/matter/behaviors.js +0 -2
  39. package/dist/matter/clusters.js +0 -2
  40. package/dist/matter/devices.js +0 -2
  41. package/dist/matter/endpoints.js +0 -2
  42. package/dist/matter/export.js +0 -3
  43. package/dist/matter/types.js +0 -3
  44. package/dist/matterbridge.js +49 -780
  45. package/dist/matterbridgeAccessoryPlatform.js +0 -36
  46. package/dist/matterbridgeBehaviors.js +5 -65
  47. package/dist/matterbridgeDeviceTypes.js +17 -630
  48. package/dist/matterbridgeDynamicPlatform.js +0 -36
  49. package/dist/matterbridgeEndpoint.js +54 -1301
  50. package/dist/matterbridgeEndpointHelpers.js +12 -345
  51. package/dist/matterbridgePlatform.js +1 -305
  52. package/dist/matterbridgeTypes.js +0 -25
  53. package/dist/pluginManager.js +5 -251
  54. package/dist/shelly.js +7 -168
  55. package/dist/storage/export.js +0 -1
  56. package/dist/update.js +0 -69
  57. package/dist/utils/colorUtils.js +2 -97
  58. package/dist/utils/commandLine.js +0 -54
  59. package/dist/utils/copyDirectory.js +1 -38
  60. package/dist/utils/createDirectory.js +0 -33
  61. package/dist/utils/createZip.js +2 -47
  62. package/dist/utils/deepCopy.js +0 -39
  63. package/dist/utils/deepEqual.js +1 -72
  64. package/dist/utils/error.js +0 -41
  65. package/dist/utils/export.js +0 -1
  66. package/dist/utils/hex.js +0 -124
  67. package/dist/utils/isvalid.js +0 -101
  68. package/dist/utils/network.js +6 -92
  69. package/dist/utils/spawn.js +0 -40
  70. package/dist/utils/wait.js +8 -60
  71. package/npm-shrinkwrap.json +2 -2
  72. package/package.json +1 -2
  73. package/dist/cli.d.ts +0 -26
  74. package/dist/cli.d.ts.map +0 -1
  75. package/dist/cli.js.map +0 -1
  76. package/dist/cliEmitter.d.ts +0 -34
  77. package/dist/cliEmitter.d.ts.map +0 -1
  78. package/dist/cliEmitter.js.map +0 -1
  79. package/dist/clusters/export.d.ts +0 -2
  80. package/dist/clusters/export.d.ts.map +0 -1
  81. package/dist/clusters/export.js.map +0 -1
  82. package/dist/defaultConfigSchema.d.ts +0 -28
  83. package/dist/defaultConfigSchema.d.ts.map +0 -1
  84. package/dist/defaultConfigSchema.js.map +0 -1
  85. package/dist/deviceManager.d.ts +0 -112
  86. package/dist/deviceManager.d.ts.map +0 -1
  87. package/dist/deviceManager.js.map +0 -1
  88. package/dist/devices/airConditioner.d.ts +0 -98
  89. package/dist/devices/airConditioner.d.ts.map +0 -1
  90. package/dist/devices/airConditioner.js.map +0 -1
  91. package/dist/devices/batteryStorage.d.ts +0 -48
  92. package/dist/devices/batteryStorage.d.ts.map +0 -1
  93. package/dist/devices/batteryStorage.js.map +0 -1
  94. package/dist/devices/cooktop.d.ts +0 -60
  95. package/dist/devices/cooktop.d.ts.map +0 -1
  96. package/dist/devices/cooktop.js.map +0 -1
  97. package/dist/devices/dishwasher.d.ts +0 -71
  98. package/dist/devices/dishwasher.d.ts.map +0 -1
  99. package/dist/devices/dishwasher.js.map +0 -1
  100. package/dist/devices/evse.d.ts +0 -75
  101. package/dist/devices/evse.d.ts.map +0 -1
  102. package/dist/devices/evse.js.map +0 -1
  103. package/dist/devices/export.d.ts +0 -17
  104. package/dist/devices/export.d.ts.map +0 -1
  105. package/dist/devices/export.js.map +0 -1
  106. package/dist/devices/extractorHood.d.ts +0 -46
  107. package/dist/devices/extractorHood.d.ts.map +0 -1
  108. package/dist/devices/extractorHood.js.map +0 -1
  109. package/dist/devices/heatPump.d.ts +0 -47
  110. package/dist/devices/heatPump.d.ts.map +0 -1
  111. package/dist/devices/heatPump.js.map +0 -1
  112. package/dist/devices/laundryDryer.d.ts +0 -67
  113. package/dist/devices/laundryDryer.d.ts.map +0 -1
  114. package/dist/devices/laundryDryer.js.map +0 -1
  115. package/dist/devices/laundryWasher.d.ts +0 -81
  116. package/dist/devices/laundryWasher.d.ts.map +0 -1
  117. package/dist/devices/laundryWasher.js.map +0 -1
  118. package/dist/devices/microwaveOven.d.ts +0 -168
  119. package/dist/devices/microwaveOven.d.ts.map +0 -1
  120. package/dist/devices/microwaveOven.js.map +0 -1
  121. package/dist/devices/oven.d.ts +0 -105
  122. package/dist/devices/oven.d.ts.map +0 -1
  123. package/dist/devices/oven.js.map +0 -1
  124. package/dist/devices/refrigerator.d.ts +0 -118
  125. package/dist/devices/refrigerator.d.ts.map +0 -1
  126. package/dist/devices/refrigerator.js.map +0 -1
  127. package/dist/devices/roboticVacuumCleaner.d.ts +0 -112
  128. package/dist/devices/roboticVacuumCleaner.d.ts.map +0 -1
  129. package/dist/devices/roboticVacuumCleaner.js.map +0 -1
  130. package/dist/devices/solarPower.d.ts +0 -40
  131. package/dist/devices/solarPower.d.ts.map +0 -1
  132. package/dist/devices/solarPower.js.map +0 -1
  133. package/dist/devices/speaker.d.ts +0 -83
  134. package/dist/devices/speaker.d.ts.map +0 -1
  135. package/dist/devices/speaker.js.map +0 -1
  136. package/dist/devices/temperatureControl.d.ts +0 -166
  137. package/dist/devices/temperatureControl.d.ts.map +0 -1
  138. package/dist/devices/temperatureControl.js.map +0 -1
  139. package/dist/devices/waterHeater.d.ts +0 -111
  140. package/dist/devices/waterHeater.d.ts.map +0 -1
  141. package/dist/devices/waterHeater.js.map +0 -1
  142. package/dist/dgram/coap.d.ts +0 -205
  143. package/dist/dgram/coap.d.ts.map +0 -1
  144. package/dist/dgram/coap.js.map +0 -1
  145. package/dist/dgram/dgram.d.ts +0 -141
  146. package/dist/dgram/dgram.d.ts.map +0 -1
  147. package/dist/dgram/dgram.js.map +0 -1
  148. package/dist/dgram/mb_coap.d.ts +0 -24
  149. package/dist/dgram/mb_coap.d.ts.map +0 -1
  150. package/dist/dgram/mb_coap.js.map +0 -1
  151. package/dist/dgram/mb_mdns.d.ts +0 -24
  152. package/dist/dgram/mb_mdns.d.ts.map +0 -1
  153. package/dist/dgram/mb_mdns.js.map +0 -1
  154. package/dist/dgram/mdns.d.ts +0 -290
  155. package/dist/dgram/mdns.d.ts.map +0 -1
  156. package/dist/dgram/mdns.js.map +0 -1
  157. package/dist/dgram/multicast.d.ts +0 -67
  158. package/dist/dgram/multicast.d.ts.map +0 -1
  159. package/dist/dgram/multicast.js.map +0 -1
  160. package/dist/dgram/unicast.d.ts +0 -56
  161. package/dist/dgram/unicast.d.ts.map +0 -1
  162. package/dist/dgram/unicast.js.map +0 -1
  163. package/dist/frontend.d.ts +0 -313
  164. package/dist/frontend.d.ts.map +0 -1
  165. package/dist/frontend.js.map +0 -1
  166. package/dist/globalMatterbridge.d.ts +0 -59
  167. package/dist/globalMatterbridge.d.ts.map +0 -1
  168. package/dist/globalMatterbridge.js.map +0 -1
  169. package/dist/helpers.d.ts +0 -48
  170. package/dist/helpers.d.ts.map +0 -1
  171. package/dist/helpers.js.map +0 -1
  172. package/dist/index.d.ts +0 -33
  173. package/dist/index.d.ts.map +0 -1
  174. package/dist/index.js.map +0 -1
  175. package/dist/jest-utils/jestHelpers.d.ts +0 -103
  176. package/dist/jest-utils/jestHelpers.d.ts.map +0 -1
  177. package/dist/jest-utils/jestHelpers.js.map +0 -1
  178. package/dist/logger/export.d.ts +0 -2
  179. package/dist/logger/export.d.ts.map +0 -1
  180. package/dist/logger/export.js.map +0 -1
  181. package/dist/matter/behaviors.d.ts +0 -2
  182. package/dist/matter/behaviors.d.ts.map +0 -1
  183. package/dist/matter/behaviors.js.map +0 -1
  184. package/dist/matter/clusters.d.ts +0 -2
  185. package/dist/matter/clusters.d.ts.map +0 -1
  186. package/dist/matter/clusters.js.map +0 -1
  187. package/dist/matter/devices.d.ts +0 -2
  188. package/dist/matter/devices.d.ts.map +0 -1
  189. package/dist/matter/devices.js.map +0 -1
  190. package/dist/matter/endpoints.d.ts +0 -2
  191. package/dist/matter/endpoints.d.ts.map +0 -1
  192. package/dist/matter/endpoints.js.map +0 -1
  193. package/dist/matter/export.d.ts +0 -5
  194. package/dist/matter/export.d.ts.map +0 -1
  195. package/dist/matter/export.js.map +0 -1
  196. package/dist/matter/types.d.ts +0 -3
  197. package/dist/matter/types.d.ts.map +0 -1
  198. package/dist/matter/types.js.map +0 -1
  199. package/dist/matterbridge.d.ts +0 -457
  200. package/dist/matterbridge.d.ts.map +0 -1
  201. package/dist/matterbridge.js.map +0 -1
  202. package/dist/matterbridgeAccessoryPlatform.d.ts +0 -42
  203. package/dist/matterbridgeAccessoryPlatform.d.ts.map +0 -1
  204. package/dist/matterbridgeAccessoryPlatform.js.map +0 -1
  205. package/dist/matterbridgeBehaviors.d.ts +0 -1351
  206. package/dist/matterbridgeBehaviors.d.ts.map +0 -1
  207. package/dist/matterbridgeBehaviors.js.map +0 -1
  208. package/dist/matterbridgeDeviceTypes.d.ts +0 -761
  209. package/dist/matterbridgeDeviceTypes.d.ts.map +0 -1
  210. package/dist/matterbridgeDeviceTypes.js.map +0 -1
  211. package/dist/matterbridgeDynamicPlatform.d.ts +0 -42
  212. package/dist/matterbridgeDynamicPlatform.d.ts.map +0 -1
  213. package/dist/matterbridgeDynamicPlatform.js.map +0 -1
  214. package/dist/matterbridgeEndpoint.d.ts +0 -1438
  215. package/dist/matterbridgeEndpoint.d.ts.map +0 -1
  216. package/dist/matterbridgeEndpoint.js.map +0 -1
  217. package/dist/matterbridgeEndpointHelpers.d.ts +0 -407
  218. package/dist/matterbridgeEndpointHelpers.d.ts.map +0 -1
  219. package/dist/matterbridgeEndpointHelpers.js.map +0 -1
  220. package/dist/matterbridgePlatform.d.ts +0 -379
  221. package/dist/matterbridgePlatform.d.ts.map +0 -1
  222. package/dist/matterbridgePlatform.js.map +0 -1
  223. package/dist/matterbridgeTypes.d.ts +0 -198
  224. package/dist/matterbridgeTypes.d.ts.map +0 -1
  225. package/dist/matterbridgeTypes.js.map +0 -1
  226. package/dist/pluginManager.d.ts +0 -270
  227. package/dist/pluginManager.d.ts.map +0 -1
  228. package/dist/pluginManager.js.map +0 -1
  229. package/dist/shelly.d.ts +0 -174
  230. package/dist/shelly.d.ts.map +0 -1
  231. package/dist/shelly.js.map +0 -1
  232. package/dist/storage/export.d.ts +0 -2
  233. package/dist/storage/export.d.ts.map +0 -1
  234. package/dist/storage/export.js.map +0 -1
  235. package/dist/update.d.ts +0 -75
  236. package/dist/update.d.ts.map +0 -1
  237. package/dist/update.js.map +0 -1
  238. package/dist/utils/colorUtils.d.ts +0 -99
  239. package/dist/utils/colorUtils.d.ts.map +0 -1
  240. package/dist/utils/colorUtils.js.map +0 -1
  241. package/dist/utils/commandLine.d.ts +0 -59
  242. package/dist/utils/commandLine.d.ts.map +0 -1
  243. package/dist/utils/commandLine.js.map +0 -1
  244. package/dist/utils/copyDirectory.d.ts +0 -33
  245. package/dist/utils/copyDirectory.d.ts.map +0 -1
  246. package/dist/utils/copyDirectory.js.map +0 -1
  247. package/dist/utils/createDirectory.d.ts +0 -34
  248. package/dist/utils/createDirectory.d.ts.map +0 -1
  249. package/dist/utils/createDirectory.js.map +0 -1
  250. package/dist/utils/createZip.d.ts +0 -39
  251. package/dist/utils/createZip.d.ts.map +0 -1
  252. package/dist/utils/createZip.js.map +0 -1
  253. package/dist/utils/deepCopy.d.ts +0 -32
  254. package/dist/utils/deepCopy.d.ts.map +0 -1
  255. package/dist/utils/deepCopy.js.map +0 -1
  256. package/dist/utils/deepEqual.d.ts +0 -54
  257. package/dist/utils/deepEqual.d.ts.map +0 -1
  258. package/dist/utils/deepEqual.js.map +0 -1
  259. package/dist/utils/error.d.ts +0 -44
  260. package/dist/utils/error.d.ts.map +0 -1
  261. package/dist/utils/error.js.map +0 -1
  262. package/dist/utils/export.d.ts +0 -13
  263. package/dist/utils/export.d.ts.map +0 -1
  264. package/dist/utils/export.js.map +0 -1
  265. package/dist/utils/hex.d.ts +0 -89
  266. package/dist/utils/hex.d.ts.map +0 -1
  267. package/dist/utils/hex.js.map +0 -1
  268. package/dist/utils/isvalid.d.ts +0 -103
  269. package/dist/utils/isvalid.d.ts.map +0 -1
  270. package/dist/utils/isvalid.js.map +0 -1
  271. package/dist/utils/network.d.ts +0 -84
  272. package/dist/utils/network.d.ts.map +0 -1
  273. package/dist/utils/network.js.map +0 -1
  274. package/dist/utils/spawn.d.ts +0 -33
  275. package/dist/utils/spawn.d.ts.map +0 -1
  276. package/dist/utils/spawn.js.map +0 -1
  277. package/dist/utils/wait.d.ts +0 -54
  278. package/dist/utils/wait.d.ts.map +0 -1
  279. package/dist/utils/wait.js.map +0 -1
@@ -1,43 +1,15 @@
1
- /**
2
- * This file contains the class Matterbridge.
3
- *
4
- * @file matterbridge.ts
5
- * @author Luca Liguori
6
- * @created 2023-12-29
7
- * @version 1.6.0
8
- * @license Apache-2.0
9
- *
10
- * Copyright 2023, 2024, 2025 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.js modules
25
1
  import os from 'node:os';
26
2
  import path from 'node:path';
27
3
  import { promises as fs } from 'node:fs';
28
4
  import EventEmitter from 'node:events';
29
5
  import { inspect } from 'node:util';
30
- // AnsiLogger module
31
6
  import { AnsiLogger, UNDERLINE, UNDERLINEOFF, db, debugStringify, BRIGHT, RESET, er, nf, rs, wr, RED, GREEN, zb, CYAN, nt, BLUE } from 'node-ansi-logger';
32
- // NodeStorage module
33
7
  import { NodeStorageManager } from 'node-persist-manager';
34
- // @matter
35
8
  import { DeviceTypeId, Endpoint, Logger, LogLevel as MatterLogLevel, LogFormat as MatterLogFormat, VendorId, StorageService, Environment, ServerNode, UINT32_MAX, UINT16_MAX, Crypto, } from '@matter/main';
36
9
  import { DeviceCommissioner, FabricAction, MdnsService, PaseClient } from '@matter/main/protocol';
37
10
  import { AggregatorEndpoint } from '@matter/main/endpoints';
38
11
  import { BasicInformationServer } from '@matter/main/behaviors/basic-information';
39
12
  import { BridgedDeviceBasicInformationServer } from '@matter/main/behaviors/bridged-device-basic-information';
40
- // Matterbridge
41
13
  import { getParameter, getIntParameter, hasParameter, copyDirectory, isValidString, parseVersionString, isValidNumber, createDirectory } from './utils/export.js';
42
14
  import { withTimeout, waiter, wait } from './utils/wait.js';
43
15
  import { dev, plg, typ } from './matterbridgeTypes.js';
@@ -47,9 +19,6 @@ import { MatterbridgeEndpoint } from './matterbridgeEndpoint.js';
47
19
  import { bridge } from './matterbridgeDeviceTypes.js';
48
20
  import { Frontend } from './frontend.js';
49
21
  import { addVirtualDevices } from './helpers.js';
50
- /**
51
- * Represents the Matterbridge application.
52
- */
53
22
  export class Matterbridge extends EventEmitter {
54
23
  systemInformation = {
55
24
  interfaceName: '',
@@ -98,7 +67,7 @@ export class Matterbridge extends EventEmitter {
98
67
  shellySysUpdate: false,
99
68
  shellyMainUpdate: false,
100
69
  profile: getParameter('profile'),
101
- loggerLevel: "info" /* LogLevel.INFO */,
70
+ loggerLevel: "info",
102
71
  fileLogger: false,
103
72
  matterLoggerLevel: MatterLogLevel.INFO,
104
73
  matterFileLogger: false,
@@ -126,18 +95,15 @@ export class Matterbridge extends EventEmitter {
126
95
  profile = getParameter('profile');
127
96
  shutdown = false;
128
97
  failCountLimit = hasParameter('shelly') ? 600 : 120;
129
- // Matterbridge log files
130
- log = new AnsiLogger({ logName: 'Matterbridge', logTimestampFormat: 4 /* TimestampFormat.TIME_MILLIS */, logLevel: hasParameter('debug') ? "debug" /* LogLevel.DEBUG */ : "info" /* LogLevel.INFO */ });
98
+ log = new AnsiLogger({ logName: 'Matterbridge', logTimestampFormat: 4, logLevel: hasParameter('debug') ? "debug" : "info" });
131
99
  matterbridgeLoggerFile = 'matterbridge' + (getParameter('profile') ? '.' + getParameter('profile') : '') + '.log';
132
100
  matterLoggerFile = 'matter' + (getParameter('profile') ? '.' + getParameter('profile') : '') + '.log';
133
101
  plugins = new PluginManager(this);
134
102
  devices = new DeviceManager(this);
135
103
  frontend = new Frontend(this);
136
- // Matterbridge storage
137
104
  nodeStorageName = 'storage' + (getParameter('profile') ? '.' + getParameter('profile') : '');
138
105
  nodeStorage;
139
106
  nodeContext;
140
- // Cleanup
141
107
  hasCleanupStarted = false;
142
108
  initialized = false;
143
109
  startMatterInterval;
@@ -151,25 +117,20 @@ export class Matterbridge extends EventEmitter {
151
117
  sigtermHandler;
152
118
  exceptionHandler;
153
119
  rejectionHandler;
154
- // Matter logger
155
- matterLog = new AnsiLogger({ logName: 'Matter', logTimestampFormat: 4 /* TimestampFormat.TIME_MILLIS */, logLevel: "debug" /* LogLevel.DEBUG */ });
156
- // Matter environment
120
+ matterLog = new AnsiLogger({ logName: 'Matter', logTimestampFormat: 4, logLevel: "debug" });
157
121
  environment = Environment.default;
158
- // Matter storage
159
122
  matterStorageName = 'matterstorage' + (getParameter('profile') ? '.' + getParameter('profile') : '');
160
123
  matterStorageService;
161
124
  matterStorageManager;
162
125
  matterbridgeContext;
163
126
  controllerContext;
164
- // Matter parameters
165
- mdnsInterface; // matter server node mdnsInterface: e.g. 'eth0' or 'wlan0' or 'WiFi'
166
- ipv4address; // matter server node listeningAddressIpv4
167
- ipv6address; // matter server node listeningAddressIpv6
168
- port; // first server node port
169
- passcode; // first server node passcode
170
- discriminator; // first server node discriminator
171
- certification; // device certification
172
- // Matter nodes
127
+ mdnsInterface;
128
+ ipv4address;
129
+ ipv6address;
130
+ port;
131
+ passcode;
132
+ discriminator;
133
+ certification;
173
134
  serverNode;
174
135
  aggregatorNode;
175
136
  aggregatorVendorId = VendorId(getIntParameter('vendorId') ?? 0xfff1);
@@ -180,31 +141,15 @@ export class Matterbridge extends EventEmitter {
180
141
  aggregatorSerialNumber = getParameter('serialNumber');
181
142
  aggregatorUniqueId = getParameter('uniqueId');
182
143
  static instance;
183
- // We load asyncronously so is private
184
144
  constructor() {
185
145
  super();
186
146
  }
187
- /**
188
- * Retrieves the list of Matterbridge devices.
189
- *
190
- * @returns {MatterbridgeEndpoint[]} An array of MatterbridgeDevice objects.
191
- */
192
147
  getDevices() {
193
148
  return this.devices.array();
194
149
  }
195
- /**
196
- * Retrieves the list of registered plugins.
197
- *
198
- * @returns {RegisteredPlugin[]} An array of RegisteredPlugin objects.
199
- */
200
150
  getPlugins() {
201
151
  return this.plugins.array();
202
152
  }
203
- /**
204
- * Set the logger logLevel for the Matterbridge classes and call onChangeLoggerLevel() for each plugin.
205
- *
206
- * @param {LogLevel} logLevel The logger logLevel to set.
207
- */
208
153
  async setLogLevel(logLevel) {
209
154
  if (this.log)
210
155
  this.log.logLevel = logLevel;
@@ -218,31 +163,19 @@ export class Matterbridge extends EventEmitter {
218
163
  for (const plugin of this.plugins) {
219
164
  if (!plugin.platform || !plugin.platform.log || !plugin.platform.config)
220
165
  continue;
221
- plugin.platform.log.logLevel = plugin.platform.config.debug === true ? "debug" /* LogLevel.DEBUG */ : this.log.logLevel;
222
- await plugin.platform.onChangeLoggerLevel(plugin.platform.config.debug === true ? "debug" /* LogLevel.DEBUG */ : this.log.logLevel);
223
- }
224
- // Set the global logger callback for the WebSocketServer to the common minimum logLevel
225
- let callbackLogLevel = "notice" /* LogLevel.NOTICE */;
226
- if (this.matterbridgeInformation.loggerLevel === "info" /* LogLevel.INFO */ || this.matterbridgeInformation.matterLoggerLevel === MatterLogLevel.INFO)
227
- callbackLogLevel = "info" /* LogLevel.INFO */;
228
- if (this.matterbridgeInformation.loggerLevel === "debug" /* LogLevel.DEBUG */ || this.matterbridgeInformation.matterLoggerLevel === MatterLogLevel.DEBUG)
229
- callbackLogLevel = "debug" /* LogLevel.DEBUG */;
166
+ plugin.platform.log.logLevel = plugin.platform.config.debug === true ? "debug" : this.log.logLevel;
167
+ await plugin.platform.onChangeLoggerLevel(plugin.platform.config.debug === true ? "debug" : this.log.logLevel);
168
+ }
169
+ let callbackLogLevel = "notice";
170
+ if (this.matterbridgeInformation.loggerLevel === "info" || this.matterbridgeInformation.matterLoggerLevel === MatterLogLevel.INFO)
171
+ callbackLogLevel = "info";
172
+ if (this.matterbridgeInformation.loggerLevel === "debug" || this.matterbridgeInformation.matterLoggerLevel === MatterLogLevel.DEBUG)
173
+ callbackLogLevel = "debug";
230
174
  AnsiLogger.setGlobalCallback(this.frontend.wssSendMessage.bind(this.frontend), callbackLogLevel);
231
175
  this.log.debug(`WebSocketServer logger global callback set to ${callbackLogLevel}`);
232
176
  }
233
- //* ************************************************************************************************************************************ */
234
- // loadInstance() and cleanup() methods */
235
- //* ************************************************************************************************************************************ */
236
- /**
237
- * Loads an instance of the Matterbridge class.
238
- * If an instance already exists, return that instance.
239
- *
240
- * @param {boolean} initialize - Whether to initialize the Matterbridge instance after loading. Defaults to false.
241
- * @returns {Matterbridge} A promise that resolves to the Matterbridge instance.
242
- */
243
177
  static async loadInstance(initialize = false) {
244
178
  if (!Matterbridge.instance) {
245
- // eslint-disable-next-line no-console
246
179
  if (hasParameter('debug'))
247
180
  console.log(GREEN + 'Creating a new instance of Matterbridge.', initialize ? 'Initializing...' : 'Not initializing...', rs);
248
181
  Matterbridge.instance = new Matterbridge();
@@ -251,17 +184,8 @@ export class Matterbridge extends EventEmitter {
251
184
  }
252
185
  return Matterbridge.instance;
253
186
  }
254
- /**
255
- * Call cleanup() and dispose MdnsService.
256
- *
257
- * @param {number} [timeout] - The timeout duration to wait for the cleanup to complete in milliseconds. Default is 1000.
258
- * @param {number} [pause] - The pause duration after the cleanup in milliseconds. Default is 250.
259
- *
260
- * @deprecated This method is deprecated and is ONLY used for jest tests.
261
- */
262
187
  async destroyInstance(timeout = 1000, pause = 250) {
263
188
  this.log.info(`Destroy instance...`);
264
- // Save server nodes to close
265
189
  const servers = [];
266
190
  if (this.bridgeMode === 'bridge') {
267
191
  if (this.serverNode)
@@ -279,105 +203,72 @@ export class Matterbridge extends EventEmitter {
279
203
  servers.push(device.serverNode);
280
204
  }
281
205
  }
282
- // Let any already‐queued microtasks run first
283
206
  await Promise.resolve();
284
- // Wait for the cleanup to finish
285
207
  await wait(pause, 'destroyInstance start', true);
286
- // Cleanup
287
208
  await this.cleanup('destroying instance...', false, timeout);
288
- // Close servers mdns service
289
209
  this.log.info(`Dispose ${servers.length} MdnsService...`);
290
210
  for (const server of servers) {
291
211
  await server.env.get(MdnsService)[Symbol.asyncDispose]();
292
212
  this.log.info(`Closed ${server.id} MdnsService`);
293
213
  }
294
- // Let any already‐queued microtasks run first
295
214
  await Promise.resolve();
296
- // Wait for the cleanup to finish
297
215
  await wait(pause, 'destroyInstance stop', true);
298
216
  }
299
- /**
300
- * Initializes the Matterbridge application.
301
- *
302
- * @remarks
303
- * This method performs the necessary setup and initialization steps for the Matterbridge application.
304
- * It displays the help information if the 'help' parameter is provided, sets up the logger, checks the
305
- * node version, registers signal handlers, initializes storage, and parses the command line.
306
- *
307
- * @returns {Promise<void>} A Promise that resolves when the initialization is complete.
308
- */
309
217
  async initialize() {
310
- // Emit the initialize_started event
311
218
  this.emit('initialize_started');
312
- // Set the restart mode
313
219
  if (hasParameter('service'))
314
220
  this.restartMode = 'service';
315
221
  if (hasParameter('docker'))
316
222
  this.restartMode = 'docker';
317
- // Set the matterbridge home directory
318
223
  this.homeDirectory = getParameter('homedir') ?? os.homedir();
319
224
  this.matterbridgeInformation.homeDirectory = this.homeDirectory;
320
225
  await createDirectory(this.homeDirectory, 'Matterbridge Home Directory', this.log);
321
- // Set the matterbridge directory
322
226
  this.matterbridgeDirectory = path.join(this.homeDirectory, '.matterbridge');
323
227
  this.matterbridgeInformation.matterbridgeDirectory = this.matterbridgeDirectory;
324
228
  await createDirectory(this.matterbridgeDirectory, 'Matterbridge Directory', this.log);
325
229
  await createDirectory(path.join(this.matterbridgeDirectory, 'certs'), 'Matterbridge Frontend Certificate Directory', this.log);
326
230
  await createDirectory(path.join(this.matterbridgeDirectory, 'uploads'), 'Matterbridge Frontend Uploads Directory', this.log);
327
- // Set the matterbridge plugin directory
328
231
  this.matterbridgePluginDirectory = path.join(this.homeDirectory, 'Matterbridge');
329
232
  this.matterbridgeInformation.matterbridgePluginDirectory = this.matterbridgePluginDirectory;
330
233
  await createDirectory(this.matterbridgePluginDirectory, 'Matterbridge Plugin Directory', this.log);
331
- // Set the matterbridge cert directory
332
234
  this.matterbridgeCertDirectory = path.join(this.homeDirectory, '.mattercert');
333
235
  this.matterbridgeInformation.matterbridgeCertDirectory = this.matterbridgeCertDirectory;
334
236
  await createDirectory(this.matterbridgeCertDirectory, 'Matterbridge Matter Certificate Directory', this.log);
335
- // Set the matterbridge root directory
336
237
  const { fileURLToPath } = await import('node:url');
337
238
  const currentFileDirectory = path.dirname(fileURLToPath(import.meta.url));
338
239
  this.rootDirectory = path.resolve(currentFileDirectory, '../');
339
240
  this.matterbridgeInformation.rootDirectory = this.rootDirectory;
340
- // Setup the matter environment
341
241
  this.environment.vars.set('log.level', MatterLogLevel.INFO);
342
242
  this.environment.vars.set('log.format', MatterLogFormat.ANSI);
343
243
  this.environment.vars.set('path.root', path.join(this.matterbridgeDirectory, this.matterStorageName));
344
244
  this.environment.vars.set('runtime.signals', false);
345
245
  this.environment.vars.set('runtime.exitcode', false);
346
- // Register process handlers
347
246
  this.registerProcessHandlers();
348
- // Initialize nodeStorage and nodeContext
349
247
  try {
350
248
  this.log.debug(`Creating node storage manager: ${CYAN}${this.nodeStorageName}${db}`);
351
249
  this.nodeStorage = new NodeStorageManager({ dir: path.join(this.matterbridgeDirectory, this.nodeStorageName), writeQueue: false, expiredInterval: undefined, logging: false });
352
250
  this.log.debug('Creating node storage context for matterbridge');
353
251
  this.nodeContext = await this.nodeStorage.createStorage('matterbridge');
354
- // TODO: Remove this code when node-persist-manager is updated
355
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
356
252
  const keys = (await this.nodeStorage?.storage.keys());
357
253
  for (const key of keys) {
358
254
  this.log.debug(`Checking node storage manager key: ${CYAN}${key}${db}`);
359
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
360
255
  await this.nodeStorage?.storage.get(key);
361
256
  }
362
257
  const storages = await this.nodeStorage.getStorageNames();
363
258
  for (const storage of storages) {
364
259
  this.log.debug(`Checking storage: ${CYAN}${storage}${db}`);
365
260
  const nodeContext = await this.nodeStorage?.createStorage(storage);
366
- // TODO: Remove this code when node-persist-manager is updated
367
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
368
261
  const keys = (await nodeContext?.storage.keys());
369
262
  keys.forEach(async (key) => {
370
263
  this.log.debug(`Checking key: ${CYAN}${storage}:${key}${db}`);
371
264
  await nodeContext?.get(key);
372
265
  });
373
266
  }
374
- // Creating a backup of the node storage since it is not corrupted
375
267
  this.log.debug('Creating node storage backup...');
376
268
  await copyDirectory(path.join(this.matterbridgeDirectory, this.nodeStorageName), path.join(this.matterbridgeDirectory, this.nodeStorageName + '.backup'));
377
269
  this.log.debug('Created node storage backup');
378
270
  }
379
271
  catch (error) {
380
- // Restoring the backup of the node storage since it is corrupted
381
272
  this.log.error(`Error creating node storage manager and context: ${error instanceof Error ? error.message : error}`);
382
273
  if (hasParameter('norestore')) {
383
274
  this.log.fatal(`The matterbridge storage is corrupted. Found -norestore parameter: exiting...`);
@@ -391,19 +282,14 @@ export class Matterbridge extends EventEmitter {
391
282
  if (!this.nodeStorage || !this.nodeContext) {
392
283
  throw new Error('Fatal error creating node storage manager and context for matterbridge');
393
284
  }
394
- // Set the first port to use for the commissioning server (will be incremented in childbridge mode)
395
285
  this.port = getIntParameter('port') ?? (await this.nodeContext.get('matterport', 5540)) ?? 5540;
396
- // Set the first passcode to use for the commissioning server (will be incremented in childbridge mode)
397
286
  this.passcode = getIntParameter('passcode') ?? (await this.nodeContext.get('matterpasscode')) ?? PaseClient.generateRandomPasscode(this.environment.get(Crypto));
398
- // Set the first discriminator to use for the commissioning server (will be incremented in childbridge mode)
399
287
  this.discriminator = getIntParameter('discriminator') ?? (await this.nodeContext.get('matterdiscriminator')) ?? PaseClient.generateRandomDiscriminator(this.environment.get(Crypto));
400
- // Certificate management
401
288
  const pairingFilePath = path.join(this.matterbridgeCertDirectory, 'pairing.json');
402
289
  try {
403
290
  await fs.access(pairingFilePath, fs.constants.R_OK);
404
291
  const pairingFileContent = await fs.readFile(pairingFilePath, 'utf8');
405
292
  const pairingFileJson = JSON.parse(pairingFileContent);
406
- // Set the vendorId, vendorName, productId, productName, deviceType, serialNumber, uniqueId if they are present in the pairing file
407
293
  if (isValidNumber(pairingFileJson.vendorId)) {
408
294
  this.aggregatorVendorId = VendorId(pairingFileJson.vendorId);
409
295
  this.log.info(`Pairing file ${CYAN}${pairingFilePath}${nf} found. Using vendorId ${CYAN}${this.aggregatorVendorId}${nf} from pairing file.`);
@@ -432,13 +318,11 @@ export class Matterbridge extends EventEmitter {
432
318
  this.aggregatorUniqueId = pairingFileJson.uniqueId;
433
319
  this.log.info(`Pairing file ${CYAN}${pairingFilePath}${nf} found. Using uniqueId ${CYAN}${this.aggregatorUniqueId}${nf} from pairing file.`);
434
320
  }
435
- // Override the passcode and discriminator if they are present in the pairing file
436
321
  if (isValidNumber(pairingFileJson.passcode) && isValidNumber(pairingFileJson.discriminator)) {
437
322
  this.passcode = pairingFileJson.passcode;
438
323
  this.discriminator = pairingFileJson.discriminator;
439
324
  this.log.info(`Pairing file ${CYAN}${pairingFilePath}${nf} found. Using passcode ${CYAN}${this.passcode}${nf} and discriminator ${CYAN}${this.discriminator}${nf} from pairing file.`);
440
325
  }
441
- // Set the certification for matter.js if it is present in the pairing file
442
326
  if (pairingFileJson.privateKey && pairingFileJson.certificate && pairingFileJson.intermediateCertificate && pairingFileJson.declaration) {
443
327
  const { hexToBuffer } = await import('./utils/hex.js');
444
328
  this.certification = {
@@ -453,44 +337,41 @@ export class Matterbridge extends EventEmitter {
453
337
  catch (error) {
454
338
  this.log.debug(`Pairing file ${CYAN}${pairingFilePath}${db} not found: ${error instanceof Error ? error.message : error}`);
455
339
  }
456
- // Store the passcode, discriminator and port in the node context
457
340
  await this.nodeContext.set('matterport', this.port);
458
341
  await this.nodeContext.set('matterpasscode', this.passcode);
459
342
  await this.nodeContext.set('matterdiscriminator', this.discriminator);
460
343
  this.log.debug(`Initializing server node for Matterbridge on port ${this.port} with passcode ${this.passcode} and discriminator ${this.discriminator}`);
461
- // Set matterbridge logger level (context: matterbridgeLogLevel)
462
344
  if (hasParameter('logger')) {
463
345
  const level = getParameter('logger');
464
346
  if (level === 'debug') {
465
- this.log.logLevel = "debug" /* LogLevel.DEBUG */;
347
+ this.log.logLevel = "debug";
466
348
  }
467
349
  else if (level === 'info') {
468
- this.log.logLevel = "info" /* LogLevel.INFO */;
350
+ this.log.logLevel = "info";
469
351
  }
470
352
  else if (level === 'notice') {
471
- this.log.logLevel = "notice" /* LogLevel.NOTICE */;
353
+ this.log.logLevel = "notice";
472
354
  }
473
355
  else if (level === 'warn') {
474
- this.log.logLevel = "warn" /* LogLevel.WARN */;
356
+ this.log.logLevel = "warn";
475
357
  }
476
358
  else if (level === 'error') {
477
- this.log.logLevel = "error" /* LogLevel.ERROR */;
359
+ this.log.logLevel = "error";
478
360
  }
479
361
  else if (level === 'fatal') {
480
- this.log.logLevel = "fatal" /* LogLevel.FATAL */;
362
+ this.log.logLevel = "fatal";
481
363
  }
482
364
  else {
483
365
  this.log.warn(`Invalid matterbridge logger level: ${level}. Using default level "info".`);
484
- this.log.logLevel = "info" /* LogLevel.INFO */;
366
+ this.log.logLevel = "info";
485
367
  }
486
368
  }
487
369
  else {
488
- this.log.logLevel = await this.nodeContext.get('matterbridgeLogLevel', this.matterbridgeInformation.shellyBoard ? "notice" /* LogLevel.NOTICE */ : "info" /* LogLevel.INFO */);
370
+ this.log.logLevel = await this.nodeContext.get('matterbridgeLogLevel', this.matterbridgeInformation.shellyBoard ? "notice" : "info");
489
371
  }
490
372
  this.frontend.logLevel = this.log.logLevel;
491
373
  MatterbridgeEndpoint.logLevel = this.log.logLevel;
492
374
  this.matterbridgeInformation.loggerLevel = this.log.logLevel;
493
- // Create the file logger for matterbridge (context: matterbridgeFileLog)
494
375
  if (hasParameter('filelogger') || (await this.nodeContext.get('matterbridgeFileLog', false))) {
495
376
  AnsiLogger.setGlobalLogfile(path.join(this.matterbridgeDirectory, this.matterbridgeLoggerFile), this.log.logLevel, true);
496
377
  this.matterbridgeInformation.fileLogger = true;
@@ -499,7 +380,6 @@ export class Matterbridge extends EventEmitter {
499
380
  this.log.debug(`Matterbridge logLevel: ${this.log.logLevel} fileLoger: ${this.matterbridgeInformation.fileLogger}.`);
500
381
  if (this.profile !== undefined)
501
382
  this.log.debug(`Matterbridge profile: ${this.profile}.`);
502
- // Set matter.js logger level, format and logger (context: matterLogLevel)
503
383
  if (hasParameter('matterlogger')) {
504
384
  const level = getParameter('matterlogger');
505
385
  if (level === 'debug') {
@@ -529,14 +409,12 @@ export class Matterbridge extends EventEmitter {
529
409
  Logger.level = (await this.nodeContext.get('matterLogLevel', this.matterbridgeInformation.shellyBoard ? MatterLogLevel.NOTICE : MatterLogLevel.INFO));
530
410
  }
531
411
  Logger.format = MatterLogFormat.ANSI;
532
- // Create the logger for matter.js with file logging (context: matterFileLog)
533
412
  if (hasParameter('matterfilelogger') || (await this.nodeContext.get('matterFileLog', false))) {
534
413
  this.matterbridgeInformation.matterFileLogger = true;
535
414
  }
536
415
  Logger.destinations.default.write = this.createDestinationMatterLogger(this.matterbridgeInformation.matterFileLogger);
537
416
  this.matterbridgeInformation.matterLoggerLevel = Logger.level;
538
417
  this.log.debug(`Matter logLevel: ${Logger.level} fileLoger: ${this.matterbridgeInformation.matterFileLogger}.`);
539
- // Log network interfaces
540
418
  const networkInterfaces = os.networkInterfaces();
541
419
  const availableAddresses = Object.entries(networkInterfaces);
542
420
  const availableInterfaces = Object.keys(networkInterfaces);
@@ -549,7 +427,6 @@ export class Matterbridge extends EventEmitter {
549
427
  });
550
428
  }
551
429
  }
552
- // Set the interface to use for matter server node mdnsInterface
553
430
  if (hasParameter('mdnsinterface')) {
554
431
  this.mdnsInterface = getParameter('mdnsinterface');
555
432
  }
@@ -558,7 +435,6 @@ export class Matterbridge extends EventEmitter {
558
435
  if (this.mdnsInterface === '')
559
436
  this.mdnsInterface = undefined;
560
437
  }
561
- // Validate mdnsInterface
562
438
  if (this.mdnsInterface) {
563
439
  if (!availableInterfaces.includes(this.mdnsInterface)) {
564
440
  this.log.error(`Invalid mdnsinterface: ${this.mdnsInterface}. Available interfaces are: ${availableInterfaces.join(', ')}. Using all available interfaces.`);
@@ -571,7 +447,6 @@ export class Matterbridge extends EventEmitter {
571
447
  }
572
448
  if (this.mdnsInterface)
573
449
  this.environment.vars.set('mdns.networkInterface', this.mdnsInterface);
574
- // Set the listeningAddressIpv4 for the matter commissioning server
575
450
  if (hasParameter('ipv4address')) {
576
451
  this.ipv4address = getParameter('ipv4address');
577
452
  }
@@ -580,7 +455,6 @@ export class Matterbridge extends EventEmitter {
580
455
  if (this.ipv4address === '')
581
456
  this.ipv4address = undefined;
582
457
  }
583
- // Validate ipv4address
584
458
  if (this.ipv4address) {
585
459
  let isValid = false;
586
460
  for (const [ifaceName, ifaces] of availableAddresses) {
@@ -596,7 +470,6 @@ export class Matterbridge extends EventEmitter {
596
470
  await this.nodeContext.remove('matteripv4address');
597
471
  }
598
472
  }
599
- // Set the listeningAddressIpv6 for the matter commissioning server
600
473
  if (hasParameter('ipv6address')) {
601
474
  this.ipv6address = getParameter('ipv6address');
602
475
  }
@@ -605,7 +478,6 @@ export class Matterbridge extends EventEmitter {
605
478
  if (this.ipv6address === '')
606
479
  this.ipv6address = undefined;
607
480
  }
608
- // Validate ipv6address
609
481
  if (this.ipv6address) {
610
482
  let isValid = false;
611
483
  for (const [ifaceName, ifaces] of availableAddresses) {
@@ -614,7 +486,6 @@ export class Matterbridge extends EventEmitter {
614
486
  isValid = true;
615
487
  break;
616
488
  }
617
- /* istanbul ignore next */
618
489
  if (ifaces && ifaces.find((iface) => iface.scopeid && iface.scopeid > 0 && iface.address + '%' + (process.platform === 'win32' ? iface.scopeid : ifaceName) === this.ipv6address)) {
619
490
  this.log.info(`Using ipv6address ${CYAN}${this.ipv6address}${nf} on interface ${CYAN}${ifaceName}${nf} for the Matter server node.`);
620
491
  isValid = true;
@@ -627,7 +498,6 @@ export class Matterbridge extends EventEmitter {
627
498
  await this.nodeContext.remove('matteripv6address');
628
499
  }
629
500
  }
630
- // Initialize the virtual mode
631
501
  if (hasParameter('novirtual')) {
632
502
  this.matterbridgeInformation.virtualMode = 'disabled';
633
503
  await this.nodeContext.set('virtualmode', 'disabled');
@@ -636,17 +506,12 @@ export class Matterbridge extends EventEmitter {
636
506
  this.matterbridgeInformation.virtualMode = (await this.nodeContext.get('virtualmode', 'outlet'));
637
507
  }
638
508
  this.log.debug(`Virtual mode ${this.matterbridgeInformation.virtualMode}.`);
639
- // Initialize PluginManager
640
509
  this.plugins.logLevel = this.log.logLevel;
641
510
  await this.plugins.loadFromStorage();
642
- // Initialize DeviceManager
643
511
  this.devices.logLevel = this.log.logLevel;
644
- // Get the plugins from node storage and create the plugins node storage contexts
645
512
  for (const plugin of this.plugins) {
646
513
  const packageJson = await this.plugins.parse(plugin);
647
514
  if (packageJson === null && !hasParameter('add') && !hasParameter('remove') && !hasParameter('enable') && !hasParameter('disable') && !hasParameter('reset') && !hasParameter('factoryreset')) {
648
- // Try to reinstall the plugin from npm (for Docker pull and external plugins)
649
- // We don't do this when the add and other parameters are set because we shut down the process after adding the plugin
650
515
  this.log.info(`Error parsing plugin ${plg}${plugin.name}${nf}. Trying to reinstall it from npm.`);
651
516
  try {
652
517
  const { spawnCommand } = await import('./utils/spawn.js');
@@ -669,7 +534,6 @@ export class Matterbridge extends EventEmitter {
669
534
  await plugin.nodeContext.set('description', plugin.description);
670
535
  await plugin.nodeContext.set('author', plugin.author);
671
536
  }
672
- // Log system info and create .matterbridge directory
673
537
  await this.logNodeAndSystemInfo();
674
538
  this.log.notice(`Matterbridge version ${this.matterbridgeVersion} ` +
675
539
  `${hasParameter('bridge') || (!hasParameter('childbridge') && (await this.nodeContext?.get('bridgeMode', '')) === 'bridge') ? 'mode bridge ' : ''}` +
@@ -677,7 +541,6 @@ export class Matterbridge extends EventEmitter {
677
541
  `${hasParameter('controller') ? 'mode controller ' : ''}` +
678
542
  `${this.restartMode !== '' ? 'restart mode ' + this.restartMode + ' ' : ''}` +
679
543
  `running on ${this.systemInformation.osType} (v.${this.systemInformation.osRelease}) platform ${this.systemInformation.osPlatform} arch ${this.systemInformation.osArch}`);
680
- // Check node version and throw error
681
544
  const minNodeVersion = 18;
682
545
  const nodeVersion = process.versions.node;
683
546
  const versionMajor = parseInt(nodeVersion.split('.')[0]);
@@ -685,18 +548,10 @@ export class Matterbridge extends EventEmitter {
685
548
  this.log.error(`Node version ${versionMajor} is not supported. Please upgrade to ${minNodeVersion} or above.`);
686
549
  throw new Error(`Node version ${versionMajor} is not supported. Please upgrade to ${minNodeVersion} or above.`);
687
550
  }
688
- // Parse command line
689
551
  await this.parseCommandLine();
690
- // Emit the initialize_completed event
691
552
  this.emit('initialize_completed');
692
553
  this.initialized = true;
693
554
  }
694
- /**
695
- * Parses the command line arguments and performs the corresponding actions.
696
- *
697
- * @private
698
- * @returns {Promise<void>} A promise that resolves when the command line arguments have been processed, or the process exits.
699
- */
700
555
  async parseCommandLine() {
701
556
  if (hasParameter('help')) {
702
557
  this.log.info(`\nUsage: matterbridge [options]\n
@@ -758,19 +613,6 @@ export class Matterbridge extends EventEmitter {
758
613
  }
759
614
  index++;
760
615
  }
761
- /*
762
- const serializedRegisteredDevices = await this.nodeContext?.get<SerializedMatterbridgeEndpoint[]>('devices', []);
763
- this.log.info(`│ Registered devices (${serializedRegisteredDevices?.length})`);
764
- serializedRegisteredDevices?.forEach((device, index) => {
765
- if (index !== serializedRegisteredDevices.length - 1) {
766
- this.log.info(`├─┬─ plugin ${plg}${device.pluginName}${nf} device: ${dev}${device.deviceName}${nf} uniqueId: ${YELLOW}${device.uniqueId}${nf}`);
767
- this.log.info(`│ └─ endpoint ${RED}${device.endpoint}${nf} ${typ}${device.endpointName}${nf} ${debugStringify(device.clusterServersId)}`);
768
- } else {
769
- this.log.info(`└─┬─ plugin ${plg}${device.pluginName}${nf} device: ${dev}${device.deviceName}${nf} uniqueId: ${YELLOW}${device.uniqueId}${nf}`);
770
- this.log.info(` └─ endpoint ${RED}${device.endpoint}${nf} ${typ}${device.endpointName}${nf} ${debugStringify(device.clusterServersId)}`);
771
- }
772
- });
773
- */
774
616
  this.shutdown = true;
775
617
  return;
776
618
  }
@@ -820,7 +662,6 @@ export class Matterbridge extends EventEmitter {
820
662
  this.shutdown = true;
821
663
  return;
822
664
  }
823
- // Start the matter storage and create the matterbridge context
824
665
  try {
825
666
  await this.startMatterStorage();
826
667
  if (this.aggregatorSerialNumber && this.aggregatorUniqueId && this.matterStorageService) {
@@ -837,21 +678,18 @@ export class Matterbridge extends EventEmitter {
837
678
  this.log.fatal(`Fatal error creating matter storage: ${error instanceof Error ? error.message : error}`);
838
679
  throw new Error(`Fatal error creating matter storage: ${error instanceof Error ? error.message : error}`);
839
680
  }
840
- // Clear the matterbridge context if the reset parameter is set
841
681
  if (hasParameter('reset') && getParameter('reset') === undefined) {
842
682
  this.initialized = true;
843
683
  await this.shutdownProcessAndReset();
844
684
  this.shutdown = true;
845
685
  return;
846
686
  }
847
- // Clear matterbridge plugin context if the reset parameter is set
848
687
  if (hasParameter('reset') && getParameter('reset') !== undefined) {
849
688
  this.log.debug(`Reset plugin ${getParameter('reset')}`);
850
689
  const plugin = this.plugins.get(getParameter('reset'));
851
690
  if (plugin) {
852
691
  const matterStorageManager = await this.matterStorageService?.open(plugin.name);
853
692
  if (!matterStorageManager) {
854
- /* istanbul ignore next */
855
693
  this.log.error(`Plugin ${plg}${plugin.name}${er} storageManager not found`);
856
694
  }
857
695
  else {
@@ -870,45 +708,37 @@ export class Matterbridge extends EventEmitter {
870
708
  this.shutdown = true;
871
709
  return;
872
710
  }
873
- // Initialize frontend
874
711
  if (getIntParameter('frontend') !== 0 || getIntParameter('frontend') === undefined)
875
712
  await this.frontend.start(getIntParameter('frontend'));
876
- // Check in 30 seconds the latest and dev versions of matterbridge and the plugins
877
713
  clearTimeout(this.checkUpdateTimeout);
878
714
  this.checkUpdateTimeout = setTimeout(async () => {
879
715
  const { checkUpdates } = await import('./update.js');
880
716
  checkUpdates(this);
881
717
  }, 30 * 1000).unref();
882
- // Check each 12 hours the latest and dev versions of matterbridge and the plugins
883
718
  clearInterval(this.checkUpdateInterval);
884
719
  this.checkUpdateInterval = setInterval(async () => {
885
720
  const { checkUpdates } = await import('./update.js');
886
721
  checkUpdates(this);
887
722
  }, 12 * 60 * 60 * 1000).unref();
888
- // Start the matterbridge in mode test
889
723
  if (hasParameter('test')) {
890
724
  this.bridgeMode = 'bridge';
891
725
  return;
892
726
  }
893
- // Start the matterbridge in mode controller
894
727
  if (hasParameter('controller')) {
895
728
  this.bridgeMode = 'controller';
896
729
  await this.startController();
897
730
  return;
898
731
  }
899
- // Check if the bridge mode is set and start matterbridge in bridge mode if not set
900
732
  if (!hasParameter('bridge') && !hasParameter('childbridge') && (await this.nodeContext?.get('bridgeMode', '')) === '') {
901
733
  this.log.info('Setting default matterbridge start mode to bridge');
902
734
  await this.nodeContext?.set('bridgeMode', 'bridge');
903
735
  }
904
- // Start matterbridge in bridge mode
905
736
  if (hasParameter('bridge') || (!hasParameter('childbridge') && (await this.nodeContext?.get('bridgeMode', '')) === 'bridge')) {
906
737
  this.bridgeMode = 'bridge';
907
738
  this.log.debug(`Starting matterbridge in mode ${this.bridgeMode}`);
908
739
  await this.startBridge();
909
740
  return;
910
741
  }
911
- // Start matterbridge in childbridge mode
912
742
  if (hasParameter('childbridge') || (!hasParameter('bridge') && (await this.nodeContext?.get('bridgeMode', '')) === 'childbridge')) {
913
743
  this.bridgeMode = 'childbridge';
914
744
  this.log.debug(`Starting matterbridge in mode ${this.bridgeMode}`);
@@ -916,20 +746,10 @@ export class Matterbridge extends EventEmitter {
916
746
  return;
917
747
  }
918
748
  }
919
- /**
920
- * Asynchronously loads and starts the registered plugins.
921
- *
922
- * This method is responsible for initializing and starting all enabled plugins.
923
- * It ensures that each plugin is properly loaded and started before the bridge starts.
924
- *
925
- * @returns {Promise<void>} A promise that resolves when all plugins have been loaded and started.
926
- */
927
749
  async startPlugins() {
928
- // Check, load and start the plugins
929
750
  for (const plugin of this.plugins) {
930
751
  plugin.configJson = await this.plugins.loadConfig(plugin);
931
752
  plugin.schemaJson = await this.plugins.loadSchema(plugin);
932
- // Check if the plugin is available
933
753
  if (!(await this.plugins.resolve(plugin.path))) {
934
754
  this.log.error(`Plugin ${plg}${plugin.name}${er} not found or not validated. Disabling it.`);
935
755
  plugin.enabled = false;
@@ -947,14 +767,10 @@ export class Matterbridge extends EventEmitter {
947
767
  plugin.configured = false;
948
768
  plugin.registeredDevices = undefined;
949
769
  plugin.addedDevices = undefined;
950
- this.plugins.load(plugin, true, 'Matterbridge is starting'); // No await do it asyncronously
770
+ this.plugins.load(plugin, true, 'Matterbridge is starting');
951
771
  }
952
772
  this.frontend.wssSendRefreshRequired('plugins');
953
773
  }
954
- /**
955
- * Registers the process handlers for uncaughtException, unhandledRejection, SIGINT and SIGTERM.
956
- * When either of these signals are received, the cleanup method is called with an appropriate message.
957
- */
958
774
  registerProcessHandlers() {
959
775
  this.log.debug(`Registering uncaughtException and unhandledRejection handlers...`);
960
776
  process.removeAllListeners('uncaughtException');
@@ -981,9 +797,6 @@ export class Matterbridge extends EventEmitter {
981
797
  };
982
798
  process.on('SIGTERM', this.sigtermHandler);
983
799
  }
984
- /**
985
- * Deregisters the process uncaughtException, unhandledRejection, SIGINT and SIGTERM signal handlers.
986
- */
987
800
  deregisterProcessHandlers() {
988
801
  this.log.debug(`Deregistering uncaughtException and unhandledRejection handlers...`);
989
802
  if (this.exceptionHandler)
@@ -1000,17 +813,12 @@ export class Matterbridge extends EventEmitter {
1000
813
  process.off('SIGTERM', this.sigtermHandler);
1001
814
  this.sigtermHandler = undefined;
1002
815
  }
1003
- /**
1004
- * Logs the node and system information.
1005
- */
1006
816
  async logNodeAndSystemInfo() {
1007
- // IP address information
1008
817
  const networkInterfaces = os.networkInterfaces();
1009
818
  this.systemInformation.interfaceName = '';
1010
819
  this.systemInformation.ipv4Address = '';
1011
820
  this.systemInformation.ipv6Address = '';
1012
821
  for (const [interfaceName, interfaceDetails] of Object.entries(networkInterfaces)) {
1013
- // this.log.debug(`Checking interface: '${interfaceName}' for '${this.mdnsInterface}'`);
1014
822
  if (this.mdnsInterface && interfaceName !== this.mdnsInterface)
1015
823
  continue;
1016
824
  if (!interfaceDetails) {
@@ -1036,22 +844,19 @@ export class Matterbridge extends EventEmitter {
1036
844
  break;
1037
845
  }
1038
846
  }
1039
- // Node information
1040
847
  this.systemInformation.nodeVersion = process.versions.node;
1041
848
  const versionMajor = parseInt(this.systemInformation.nodeVersion.split('.')[0]);
1042
849
  const versionMinor = parseInt(this.systemInformation.nodeVersion.split('.')[1]);
1043
850
  const versionPatch = parseInt(this.systemInformation.nodeVersion.split('.')[2]);
1044
- // Host system information
1045
851
  this.systemInformation.hostname = os.hostname();
1046
852
  this.systemInformation.user = os.userInfo().username;
1047
- this.systemInformation.osType = os.type(); // "Windows_NT", "Darwin", etc.
1048
- this.systemInformation.osRelease = os.release(); // Kernel version
1049
- this.systemInformation.osPlatform = os.platform(); // "win32", "linux", "darwin", etc.
1050
- this.systemInformation.osArch = os.arch(); // "x64", "arm", etc.
1051
- this.systemInformation.totalMemory = (os.totalmem() / 1024 / 1024 / 1024).toFixed(2) + ' GB'; // Convert to GB
1052
- this.systemInformation.freeMemory = (os.freemem() / 1024 / 1024 / 1024).toFixed(2) + ' GB'; // Convert to GB
1053
- this.systemInformation.systemUptime = (os.uptime() / 60 / 60).toFixed(2) + ' hours'; // Convert to hours
1054
- // Log the system information
853
+ this.systemInformation.osType = os.type();
854
+ this.systemInformation.osRelease = os.release();
855
+ this.systemInformation.osPlatform = os.platform();
856
+ this.systemInformation.osArch = os.arch();
857
+ this.systemInformation.totalMemory = (os.totalmem() / 1024 / 1024 / 1024).toFixed(2) + ' GB';
858
+ this.systemInformation.freeMemory = (os.freemem() / 1024 / 1024 / 1024).toFixed(2) + ' GB';
859
+ this.systemInformation.systemUptime = (os.uptime() / 60 / 60).toFixed(2) + ' hours';
1055
860
  this.log.debug('Host System Information:');
1056
861
  this.log.debug(`- Hostname: ${this.systemInformation.hostname}`);
1057
862
  this.log.debug(`- User: ${this.systemInformation.user}`);
@@ -1067,17 +872,14 @@ export class Matterbridge extends EventEmitter {
1067
872
  this.log.debug(`- Total Memory: ${this.systemInformation.totalMemory}`);
1068
873
  this.log.debug(`- Free Memory: ${this.systemInformation.freeMemory}`);
1069
874
  this.log.debug(`- System Uptime: ${this.systemInformation.systemUptime}`);
1070
- // Log directories
1071
875
  this.log.debug(`Root Directory: ${this.rootDirectory}`);
1072
876
  this.log.debug(`Home Directory: ${this.homeDirectory}`);
1073
877
  this.log.debug(`Matterbridge Directory: ${this.matterbridgeDirectory}`);
1074
878
  this.log.debug(`Matterbridge Plugin Directory: ${this.matterbridgePluginDirectory}`);
1075
879
  this.log.debug(`Matterbridge Matter Certificate Directory: ${this.matterbridgeCertDirectory}`);
1076
- // Global node_modules directory
1077
880
  if (this.nodeContext)
1078
881
  this.globalModulesDirectory = this.matterbridgeInformation.globalModulesDirectory = await this.nodeContext.get('globalModulesDirectory', '');
1079
882
  if (this.globalModulesDirectory === '') {
1080
- // First run of Matterbridge so the node storage is empty
1081
883
  this.log.debug(`Getting global node_modules directory...`);
1082
884
  try {
1083
885
  const { getGlobalNodeModules } = await import('./utils/network.js');
@@ -1090,7 +892,6 @@ export class Matterbridge extends EventEmitter {
1090
892
  }
1091
893
  }
1092
894
  else {
1093
- // The global node_modules directory is already set in the node storage and we check if it is still valid
1094
895
  this.log.debug(`Checking global node_modules directory: ${this.globalModulesDirectory}`);
1095
896
  try {
1096
897
  const { getGlobalNodeModules } = await import('./utils/network.js');
@@ -1102,85 +903,57 @@ export class Matterbridge extends EventEmitter {
1102
903
  this.log.error(`Error checking global node_modules directory: ${error}`);
1103
904
  }
1104
905
  }
1105
- // Matterbridge version
1106
906
  const packageJson = JSON.parse(await fs.readFile(path.join(this.rootDirectory, 'package.json'), 'utf-8'));
1107
907
  this.matterbridgeVersion = this.matterbridgeLatestVersion = this.matterbridgeDevVersion = packageJson.version;
1108
908
  this.matterbridgeInformation.matterbridgeVersion = this.matterbridgeInformation.matterbridgeLatestVersion = this.matterbridgeInformation.matterbridgeDevVersion = packageJson.version;
1109
909
  this.log.debug(`Matterbridge Version: ${this.matterbridgeVersion}`);
1110
- // Matterbridge latest version (will be set in the checkUpdate function)
1111
910
  if (this.nodeContext)
1112
911
  this.matterbridgeLatestVersion = this.matterbridgeInformation.matterbridgeLatestVersion = await this.nodeContext.get('matterbridgeLatestVersion', this.matterbridgeVersion);
1113
912
  this.log.debug(`Matterbridge Latest Version: ${this.matterbridgeLatestVersion}`);
1114
- // Matterbridge dev version (will be set in the checkUpdate function)
1115
913
  if (this.nodeContext)
1116
914
  this.matterbridgeDevVersion = this.matterbridgeInformation.matterbridgeDevVersion = await this.nodeContext.get('matterbridgeDevVersion', this.matterbridgeVersion);
1117
915
  this.log.debug(`Matterbridge Dev Version: ${this.matterbridgeDevVersion}`);
1118
- // Current working directory
1119
916
  const currentDir = process.cwd();
1120
917
  this.log.debug(`Current Working Directory: ${currentDir}`);
1121
- // Command line arguments (excluding 'node' and the script name)
1122
918
  const cmdArgs = process.argv.slice(2).join(' ');
1123
919
  this.log.debug(`Command Line Arguments: ${cmdArgs}`);
1124
920
  }
1125
- /**
1126
- * Creates a MatterLogger function to show the matter.js log messages in AnsiLogger (for the frontend).
1127
- * It also logs to file (matter.log) if fileLogger is true.
1128
- *
1129
- * @param {boolean} fileLogger - Whether to log to file or not.
1130
- * @returns {Function} The MatterLogger function.
1131
- */
1132
921
  createDestinationMatterLogger(fileLogger) {
1133
922
  if (fileLogger) {
1134
923
  this.matterLog.logFilePath = path.join(this.matterbridgeDirectory, this.matterLoggerFile);
1135
924
  }
1136
925
  return (text, message) => {
1137
- // 2024-08-21 08:55:19.488 DEBUG InteractionMessenger Sending DataReport chunk with 28 attributes and 0 events: 1004 bytes
1138
926
  const logger = text.slice(44, 44 + 20).trim();
1139
927
  const msg = text.slice(65);
1140
928
  this.matterLog.logName = logger;
1141
929
  switch (message.level) {
1142
930
  case MatterLogLevel.DEBUG:
1143
- this.matterLog.log("debug" /* LogLevel.DEBUG */, msg);
931
+ this.matterLog.log("debug", msg);
1144
932
  break;
1145
933
  case MatterLogLevel.INFO:
1146
- this.matterLog.log("info" /* LogLevel.INFO */, msg);
934
+ this.matterLog.log("info", msg);
1147
935
  break;
1148
936
  case MatterLogLevel.NOTICE:
1149
- this.matterLog.log("notice" /* LogLevel.NOTICE */, msg);
937
+ this.matterLog.log("notice", msg);
1150
938
  break;
1151
939
  case MatterLogLevel.WARN:
1152
- this.matterLog.log("warn" /* LogLevel.WARN */, msg);
940
+ this.matterLog.log("warn", msg);
1153
941
  break;
1154
942
  case MatterLogLevel.ERROR:
1155
- this.matterLog.log("error" /* LogLevel.ERROR */, msg);
943
+ this.matterLog.log("error", msg);
1156
944
  break;
1157
945
  case MatterLogLevel.FATAL:
1158
- this.matterLog.log("fatal" /* LogLevel.FATAL */, msg);
946
+ this.matterLog.log("fatal", msg);
1159
947
  break;
1160
948
  }
1161
949
  };
1162
950
  }
1163
- /**
1164
- * Restarts the process by exiting the current instance and loading a new instance (/api/restart).
1165
- *
1166
- * @returns {Promise<void>} A promise that resolves when the restart is completed.
1167
- */
1168
951
  async restartProcess() {
1169
952
  await this.cleanup('restarting...', true);
1170
953
  }
1171
- /**
1172
- * Shut down the process (/api/shutdown).
1173
- *
1174
- * @returns {Promise<void>} A promise that resolves when the shutdown is completed.
1175
- */
1176
954
  async shutdownProcess() {
1177
955
  await this.cleanup('shutting down...', false);
1178
956
  }
1179
- /**
1180
- * Update matterbridge and shut down the process (virtual device 'Update Matterbridge').
1181
- *
1182
- * @returns {Promise<void>} A promise that resolves when the update is completed.
1183
- */
1184
957
  async updateProcess() {
1185
958
  this.log.info('Updating matterbridge...');
1186
959
  try {
@@ -1194,13 +967,6 @@ export class Matterbridge extends EventEmitter {
1194
967
  this.frontend.wssSendRestartRequired();
1195
968
  await this.cleanup('updating...', false);
1196
969
  }
1197
- /**
1198
- * Unregister all devices and shut down the process (/api/unregister).
1199
- *
1200
- * @param {number} [timeout] - The timeout duration to wait for the message exchange to complete in milliseconds. Default is 1000.
1201
- *
1202
- * @returns {Promise<void>} A promise that resolves when the cleanup is completed.
1203
- */
1204
970
  async unregisterAndShutdownProcess(timeout = 1000) {
1205
971
  this.log.info('Unregistering all devices and shutting down...');
1206
972
  for (const plugin of this.plugins.array()) {
@@ -1214,71 +980,46 @@ export class Matterbridge extends EventEmitter {
1214
980
  await this.removeAllBridgedEndpoints(plugin.name, 100);
1215
981
  }
1216
982
  this.log.debug('Waiting for the MessageExchange to finish...');
1217
- await wait(timeout); // Wait for MessageExchange to finish
983
+ await wait(timeout);
1218
984
  this.log.debug('Cleaning up and shutting down...');
1219
985
  await this.cleanup('unregistered all devices and shutting down...', false, timeout);
1220
986
  }
1221
- /**
1222
- * Reset commissioning and shut down the process (/api/reset).
1223
- *
1224
- * @returns {Promise<void>} A promise that resolves when the cleanup is completed.
1225
- */
1226
987
  async shutdownProcessAndReset() {
1227
988
  await this.cleanup('shutting down with reset...', false);
1228
989
  }
1229
- /**
1230
- * Factory reset and shut down the process (/api/factory-reset).
1231
- *
1232
- * @returns {Promise<void>} A promise that resolves when the cleanup is completed.
1233
- */
1234
990
  async shutdownProcessAndFactoryReset() {
1235
991
  await this.cleanup('shutting down with factory reset...', false);
1236
992
  }
1237
- /**
1238
- * Cleans up the Matterbridge instance.
1239
- *
1240
- * @param {string} message - The cleanup message.
1241
- * @param {boolean} [restart] - Indicates whether to restart the instance after cleanup. Default is `false`.
1242
- * @param {number} [timeout] - The timeout duration to wait for the message exchange to complete in milliseconds. Default is 1000.
1243
- *
1244
- * @returns {Promise<void>} A promise that resolves when the cleanup is completed.
1245
- */
1246
993
  async cleanup(message, restart = false, timeout = 1000) {
1247
994
  if (this.initialized && !this.hasCleanupStarted) {
1248
995
  this.emit('cleanup_started');
1249
996
  this.hasCleanupStarted = true;
1250
997
  this.log.info(message);
1251
- // Clear the start matter interval
1252
998
  if (this.startMatterInterval) {
1253
999
  clearInterval(this.startMatterInterval);
1254
1000
  this.startMatterInterval = undefined;
1255
1001
  this.log.debug('Start matter interval cleared');
1256
1002
  }
1257
- // Clear the check update timeout
1258
1003
  if (this.checkUpdateTimeout) {
1259
1004
  clearTimeout(this.checkUpdateTimeout);
1260
1005
  this.checkUpdateTimeout = undefined;
1261
1006
  this.log.debug('Check update timeout cleared');
1262
1007
  }
1263
- // Clear the check update interval
1264
1008
  if (this.checkUpdateInterval) {
1265
1009
  clearInterval(this.checkUpdateInterval);
1266
1010
  this.checkUpdateInterval = undefined;
1267
1011
  this.log.debug('Check update interval cleared');
1268
1012
  }
1269
- // Clear the configure timeout
1270
1013
  if (this.configureTimeout) {
1271
1014
  clearTimeout(this.configureTimeout);
1272
1015
  this.configureTimeout = undefined;
1273
1016
  this.log.debug('Matterbridge configure timeout cleared');
1274
1017
  }
1275
- // Clear the reachability timeout
1276
1018
  if (this.reachabilityTimeout) {
1277
1019
  clearTimeout(this.reachabilityTimeout);
1278
1020
  this.reachabilityTimeout = undefined;
1279
1021
  this.log.debug('Matterbridge reachability timeout cleared');
1280
1022
  }
1281
- // Call the shutdown method of each plugin and clear the plugins reachability timeout
1282
1023
  for (const plugin of this.plugins) {
1283
1024
  if (!plugin.enabled || plugin.error)
1284
1025
  continue;
@@ -1289,7 +1030,6 @@ export class Matterbridge extends EventEmitter {
1289
1030
  this.log.debug(`Plugin ${plg}${plugin.name}${db} reachability timeout cleared`);
1290
1031
  }
1291
1032
  }
1292
- // Stop matter server nodes
1293
1033
  this.log.notice(`Stopping matter server nodes in ${this.bridgeMode} mode...`);
1294
1034
  this.log.debug('Waiting for the MessageExchange to finish...');
1295
1035
  await wait(timeout, 'Waiting for the MessageExchange to finish...', true);
@@ -1314,7 +1054,6 @@ export class Matterbridge extends EventEmitter {
1314
1054
  }
1315
1055
  }
1316
1056
  this.log.notice('Stopped matter server nodes');
1317
- // Matter commisioning reset
1318
1057
  if (message === 'shutting down with reset...') {
1319
1058
  this.log.info('Resetting Matterbridge commissioning information...');
1320
1059
  await this.matterStorageManager?.createContext('events')?.clearAll();
@@ -1324,7 +1063,6 @@ export class Matterbridge extends EventEmitter {
1324
1063
  await this.matterbridgeContext?.clearAll();
1325
1064
  this.log.info('Matter storage reset done! Remove the bridge from the controller.');
1326
1065
  }
1327
- // Unregister all devices
1328
1066
  if (message === 'unregistered all devices and shutting down...') {
1329
1067
  if (this.bridgeMode === 'bridge') {
1330
1068
  await this.matterStorageManager?.createContext('root')?.createContext('parts')?.createContext('Matterbridge')?.createContext('parts')?.clearAll();
@@ -1342,36 +1080,18 @@ export class Matterbridge extends EventEmitter {
1342
1080
  }
1343
1081
  this.log.info('Matter storage reset done!');
1344
1082
  }
1345
- // Stop matter storage
1346
1083
  await this.stopMatterStorage();
1347
- // Stop the frontend
1348
1084
  await this.frontend.stop();
1349
- // Remove the matterfilelogger
1350
1085
  try {
1351
1086
  Logger.removeLogger('matterfilelogger');
1352
1087
  }
1353
1088
  catch (error) {
1354
1089
  this.log.debug(`Error removing the matterfilelogger for file ${CYAN}${path.join(this.matterbridgeDirectory, this.matterLoggerFile)}${db}: ${error instanceof Error ? error.message : String(error)}`);
1355
1090
  }
1356
- // Close the matterbridge node storage and context
1357
1091
  if (this.nodeStorage && this.nodeContext) {
1358
- /*
1359
- TODO: Implement serialization of registered devices in edge mode
1360
- this.log.info('Saving registered devices...');
1361
- const serializedRegisteredDevices: SerializedMatterbridgeEndpoint[] = [];
1362
- this.devices.forEach(async (device) => {
1363
- const serializedMatterbridgeDevice = MatterbridgeEndpoint.serialize(device);
1364
- // this.log.info(`- ${serializedMatterbridgeDevice.deviceName}${rs}\n`, serializedMatterbridgeDevice);
1365
- if (serializedMatterbridgeDevice) serializedRegisteredDevices.push(serializedMatterbridgeDevice);
1366
- });
1367
- await this.nodeContext.set<SerializedMatterbridgeEndpoint[]>('devices', serializedRegisteredDevices);
1368
- this.log.info(`Saved registered devices (${serializedRegisteredDevices?.length})`);
1369
- */
1370
- // Clear nodeContext and nodeStorage (they just need 1000ms to write the data to disk)
1371
1092
  this.log.debug(`Closing node storage context for ${plg}Matterbridge${db}...`);
1372
1093
  await this.nodeContext.close();
1373
1094
  this.nodeContext = undefined;
1374
- // Clear nodeContext for each plugin (they just need 1000ms to write the data to disk)
1375
1095
  for (const plugin of this.plugins) {
1376
1096
  if (plugin.nodeContext) {
1377
1097
  this.log.debug(`Closing node storage context for plugin ${plg}${plugin.name}${db}...`);
@@ -1388,10 +1108,8 @@ export class Matterbridge extends EventEmitter {
1388
1108
  }
1389
1109
  this.plugins.clear();
1390
1110
  this.devices.clear();
1391
- // Factory reset
1392
1111
  if (message === 'shutting down with factory reset...') {
1393
1112
  try {
1394
- // Delete matter storage directory with its subdirectories and backup
1395
1113
  const dir = path.join(this.matterbridgeDirectory, this.matterStorageName);
1396
1114
  this.log.info(`Removing matter storage directory: ${dir}`);
1397
1115
  await fs.rm(dir, { recursive: true });
@@ -1400,13 +1118,11 @@ export class Matterbridge extends EventEmitter {
1400
1118
  await fs.rm(backup, { recursive: true });
1401
1119
  }
1402
1120
  catch (error) {
1403
- // istanbul ignore next if
1404
1121
  if (error instanceof Error && error.code !== 'ENOENT') {
1405
1122
  this.log.error(`Error removing matter storage directory: ${error}`);
1406
1123
  }
1407
1124
  }
1408
1125
  try {
1409
- // Delete matterbridge storage directory with its subdirectories and backup
1410
1126
  const dir = path.join(this.matterbridgeDirectory, this.nodeStorageName);
1411
1127
  this.log.info(`Removing matterbridge storage directory: ${dir}`);
1412
1128
  await fs.rm(dir, { recursive: true });
@@ -1415,20 +1131,18 @@ export class Matterbridge extends EventEmitter {
1415
1131
  await fs.rm(backup, { recursive: true });
1416
1132
  }
1417
1133
  catch (error) {
1418
- // istanbul ignore next if
1419
1134
  if (error instanceof Error && error.code !== 'ENOENT') {
1420
1135
  this.log.error(`Error removing matterbridge storage directory: ${error}`);
1421
1136
  }
1422
1137
  }
1423
1138
  this.log.info('Factory reset done! Remove all paired fabrics from the controllers.');
1424
1139
  }
1425
- // Deregisters the process handlers
1426
1140
  this.deregisterProcessHandlers();
1427
1141
  if (restart) {
1428
1142
  if (message === 'updating...') {
1429
1143
  this.log.info('Cleanup completed. Updating...');
1430
1144
  Matterbridge.instance = undefined;
1431
- this.emit('update'); // Restart the process but the update has been done before. TODO move all updates to the cli
1145
+ this.emit('update');
1432
1146
  }
1433
1147
  else if (message === 'restarting...') {
1434
1148
  this.log.info('Cleanup completed. Restarting...');
@@ -1449,13 +1163,6 @@ export class Matterbridge extends EventEmitter {
1449
1163
  this.log.debug('Cleanup already started...');
1450
1164
  }
1451
1165
  }
1452
- /**
1453
- * Creates and configures the server node for a single not bridged device.
1454
- *
1455
- * @param {RegisteredPlugin} plugin - The plugin to configure.
1456
- * @param {MatterbridgeEndpoint} device - The device to associate with the plugin.
1457
- * @returns {Promise<void>} A promise that resolves when the server node for the accessory plugin is created and configured.
1458
- */
1459
1166
  async createDeviceServerNode(plugin, device) {
1460
1167
  if (device.mode === 'server' && !device.serverNode && device.deviceType && device.deviceName && device.vendorId && device.vendorName && device.productId && device.productName) {
1461
1168
  this.log.debug(`Creating device ${plg}${plugin.name}${db}:${dev}${device.deviceName}${db} server node...`);
@@ -1466,13 +1173,6 @@ export class Matterbridge extends EventEmitter {
1466
1173
  this.log.debug(`Added ${plg}${plugin.name}${db}:${dev}${device.deviceName}${db} to server node`);
1467
1174
  }
1468
1175
  }
1469
- /**
1470
- * Creates and configures the server node for an accessory plugin for a given device.
1471
- *
1472
- * @param {RegisteredPlugin} plugin - The plugin to configure.
1473
- * @param {MatterbridgeEndpoint} device - The device to associate with the plugin.
1474
- * @returns {Promise<void>} A promise that resolves when the server node for the accessory plugin is created and configured.
1475
- */
1476
1176
  async createAccessoryPlugin(plugin, device) {
1477
1177
  if (!plugin.locked && device.deviceType && device.deviceName && device.vendorId && device.productId && device.vendorName && device.productName) {
1478
1178
  plugin.locked = true;
@@ -1484,12 +1184,6 @@ export class Matterbridge extends EventEmitter {
1484
1184
  await plugin.serverNode.add(device);
1485
1185
  }
1486
1186
  }
1487
- /**
1488
- * Creates and configures the server node and the aggregator node for a dynamic plugin.
1489
- *
1490
- * @param {RegisteredPlugin} plugin - The plugin to configure.
1491
- * @returns {Promise<void>} A promise that resolves when the server node and the aggregator node for the dynamic plugin is created and configured.
1492
- */
1493
1187
  async createDynamicPlugin(plugin) {
1494
1188
  if (!plugin.locked) {
1495
1189
  plugin.locked = true;
@@ -1500,14 +1194,7 @@ export class Matterbridge extends EventEmitter {
1500
1194
  await plugin.serverNode.add(plugin.aggregatorNode);
1501
1195
  }
1502
1196
  }
1503
- /**
1504
- * Starts the Matterbridge in bridge mode.
1505
- *
1506
- * @private
1507
- * @returns {Promise<void>} A promise that resolves when the Matterbridge is started.
1508
- */
1509
1197
  async startBridge() {
1510
- // Plugins are configured by a timer when matter server is started and plugin.configured is set to true
1511
1198
  if (!this.matterStorageManager)
1512
1199
  throw new Error('No storage manager initialized');
1513
1200
  if (!this.matterbridgeContext)
@@ -1546,16 +1233,13 @@ export class Matterbridge extends EventEmitter {
1546
1233
  clearInterval(this.startMatterInterval);
1547
1234
  this.startMatterInterval = undefined;
1548
1235
  this.log.debug('Cleared startMatterInterval interval for Matterbridge');
1549
- // Start the Matter server node
1550
- this.startServerNode(this.serverNode); // We don't await this, because the server node is started in the background
1551
- // Start the Matter server node of single devices in mode 'server'
1236
+ this.startServerNode(this.serverNode);
1552
1237
  for (const device of this.devices.array()) {
1553
1238
  if (device.mode === 'server' && device.serverNode) {
1554
1239
  this.log.debug(`Starting server node for device ${dev}${device.deviceName}${db} in server mode...`);
1555
- this.startServerNode(device.serverNode); // We don't await this, because the server node is started in the background
1240
+ this.startServerNode(device.serverNode);
1556
1241
  }
1557
1242
  }
1558
- // Configure the plugins
1559
1243
  this.configureTimeout = setTimeout(async () => {
1560
1244
  for (const plugin of this.plugins.array()) {
1561
1245
  if (!plugin.enabled || !plugin.loaded || !plugin.started || plugin.error)
@@ -1573,25 +1257,16 @@ export class Matterbridge extends EventEmitter {
1573
1257
  }
1574
1258
  this.frontend.wssSendRefreshRequired('plugins');
1575
1259
  }, 30 * 1000).unref();
1576
- // Setting reachability to true
1577
1260
  this.reachabilityTimeout = setTimeout(() => {
1578
1261
  this.log.info(`Setting reachability to true for ${plg}Matterbridge${db}`);
1579
1262
  if (this.aggregatorNode)
1580
1263
  this.setAggregatorReachability(this.aggregatorNode, true);
1581
1264
  this.frontend.wssSendRefreshRequired('reachability');
1582
1265
  }, 60 * 1000).unref();
1583
- // Logger.get('LogServerNode').info(this.serverNode);
1584
1266
  this.emit('bridge_started');
1585
1267
  this.log.notice('Matterbridge bridge started successfully');
1586
1268
  }, this.startMatterIntervalMs);
1587
1269
  }
1588
- /**
1589
- * Starts the Matterbridge in childbridge mode.
1590
- *
1591
- * @param {number} [delay] - The delay before starting the childbridge. Default is 1000 milliseconds.
1592
- *
1593
- * @returns {Promise<void>} A promise that resolves when the Matterbridge is started.
1594
- */
1595
1270
  async startChildbridge(delay = 1000) {
1596
1271
  if (!this.matterStorageManager)
1597
1272
  throw new Error('No storage manager initialized');
@@ -1632,9 +1307,8 @@ export class Matterbridge extends EventEmitter {
1632
1307
  clearInterval(this.startMatterInterval);
1633
1308
  this.startMatterInterval = undefined;
1634
1309
  if (delay > 0)
1635
- await wait(delay); // Wait for the specified delay to ensure all plugins server nodes are ready
1310
+ await wait(delay);
1636
1311
  this.log.debug('Cleared startMatterInterval interval in childbridge mode');
1637
- // Configure the plugins
1638
1312
  this.configureTimeout = setTimeout(async () => {
1639
1313
  for (const plugin of this.plugins.array()) {
1640
1314
  if (!plugin.enabled || !plugin.loaded || !plugin.started || plugin.error)
@@ -1671,9 +1345,7 @@ export class Matterbridge extends EventEmitter {
1671
1345
  this.log.error(`Node storage context not found for plugin ${plg}${plugin.name}${er}`);
1672
1346
  continue;
1673
1347
  }
1674
- // Start the Matter server node
1675
- this.startServerNode(plugin.serverNode); // We don't await this, because the server node is started in the background
1676
- // Setting reachability to true
1348
+ this.startServerNode(plugin.serverNode);
1677
1349
  plugin.reachabilityTimeout = setTimeout(() => {
1678
1350
  this.log.info(`Setting reachability to true for ${plg}${plugin.name}${nf} type ${plugin.type} server node ${plugin.serverNode !== undefined} aggregator node ${plugin.aggregatorNode !== undefined} device ${plugin.device !== undefined}`);
1679
1351
  if (plugin.type === 'DynamicPlatform' && plugin.aggregatorNode)
@@ -1681,241 +1353,19 @@ export class Matterbridge extends EventEmitter {
1681
1353
  this.frontend.wssSendRefreshRequired('reachability');
1682
1354
  }, 60 * 1000).unref();
1683
1355
  }
1684
- // Start the Matter server node of single devices in mode 'server'
1685
1356
  for (const device of this.devices.array()) {
1686
1357
  if (device.mode === 'server' && device.serverNode) {
1687
1358
  this.log.debug(`Starting server node for device ${dev}${device.deviceName}${db} in server mode...`);
1688
- this.startServerNode(device.serverNode); // We don't await this, because the server node is started in the background
1359
+ this.startServerNode(device.serverNode);
1689
1360
  }
1690
1361
  }
1691
- // Logger.get('LogServerNode').info(this.serverNode);
1692
1362
  this.emit('childbridge_started');
1693
1363
  this.log.notice('Matterbridge childbridge started successfully');
1694
1364
  }, this.startMatterIntervalMs);
1695
1365
  }
1696
- /**
1697
- * Starts the Matterbridge controller.
1698
- *
1699
- * @private
1700
- * @returns {Promise<void>} A promise that resolves when the Matterbridge is started.
1701
- */
1702
1366
  async startController() {
1703
- /*
1704
- if (!this.matterStorageManager) {
1705
- this.log.error('No storage manager initialized');
1706
- await this.cleanup('No storage manager initialized');
1707
- return;
1708
- }
1709
- this.log.info('Creating context: mattercontrollerContext');
1710
- this.controllerContext = this.matterStorageManager.createContext('mattercontrollerContext');
1711
- if (!this.controllerContext) {
1712
- this.log.error('No storage context mattercontrollerContext initialized');
1713
- await this.cleanup('No storage context mattercontrollerContext initialized');
1714
- return;
1715
- }
1716
-
1717
- this.log.debug('Starting matterbridge in mode', this.bridgeMode);
1718
- this.matterServer = await this.createMatterServer(this.storageManager);
1719
- this.log.info('Creating matter commissioning controller');
1720
- this.commissioningController = new CommissioningController({
1721
- autoConnect: false,
1722
- });
1723
- this.log.info('Adding matter commissioning controller to matter server');
1724
- await this.matterServer.addCommissioningController(this.commissioningController);
1725
-
1726
- this.log.info('Starting matter server');
1727
- await this.matterServer.start();
1728
- this.log.info('Matter server started');
1729
- const commissioningOptions: ControllerCommissioningFlowOptions = {
1730
- regulatoryLocation: GeneralCommissioning.RegulatoryLocationType.IndoorOutdoor,
1731
- regulatoryCountryCode: 'XX',
1732
- };
1733
- const commissioningController = new CommissioningController({
1734
- environment: {
1735
- environment,
1736
- id: uniqueId,
1737
- },
1738
- autoConnect: false, // Do not auto connect to the commissioned nodes
1739
- adminFabricLabel,
1740
- });
1741
-
1742
- if (hasParameter('pairingcode')) {
1743
- this.log.info('Pairing device with pairingcode:', getParameter('pairingcode'));
1744
- const pairingCode = getParameter('pairingcode');
1745
- const ip = this.controllerContext.has('ip') ? this.controllerContext.get<string>('ip') : undefined;
1746
- const port = this.controllerContext.has('port') ? this.controllerContext.get<number>('port') : undefined;
1747
-
1748
- let longDiscriminator, setupPin, shortDiscriminator;
1749
- if (pairingCode !== undefined) {
1750
- const pairingCodeCodec = ManualPairingCodeCodec.decode(pairingCode);
1751
- shortDiscriminator = pairingCodeCodec.shortDiscriminator;
1752
- longDiscriminator = undefined;
1753
- setupPin = pairingCodeCodec.passcode;
1754
- this.log.info(`Data extracted from pairing code: ${Logger.toJSON(pairingCodeCodec)}`);
1755
- } else {
1756
- longDiscriminator = await this.controllerContext.get('longDiscriminator', 3840);
1757
- if (longDiscriminator > 4095) throw new Error('Discriminator value must be less than 4096');
1758
- setupPin = this.controllerContext.get('pin', 20202021);
1759
- }
1760
- if ((shortDiscriminator === undefined && longDiscriminator === undefined) || setupPin === undefined) {
1761
- throw new Error('Please specify the longDiscriminator of the device to commission with -longDiscriminator or provide a valid passcode with -passcode');
1762
- }
1763
-
1764
- const options = {
1765
- commissioning: commissioningOptions,
1766
- discovery: {
1767
- knownAddress: ip !== undefined && port !== undefined ? { ip, port, type: 'udp' } : undefined,
1768
- identifierData: longDiscriminator !== undefined ? { longDiscriminator } : shortDiscriminator !== undefined ? { shortDiscriminator } : {},
1769
- },
1770
- passcode: setupPin,
1771
- } as NodeCommissioningOptions;
1772
- this.log.info('Commissioning with options:', options);
1773
- const nodeId = await this.commissioningController.commissionNode(options);
1774
- this.log.info(`Commissioning successfully done with nodeId: ${nodeId}`);
1775
- this.log.info('ActiveSessionInformation:', this.commissioningController.getActiveSessionInformation());
1776
- } // (hasParameter('pairingcode'))
1777
-
1778
- if (hasParameter('unpairall')) {
1779
- this.log.info('***Commissioning controller unpairing all nodes...');
1780
- const nodeIds = this.commissioningController.getCommissionedNodes();
1781
- for (const nodeId of nodeIds) {
1782
- this.log.info('***Commissioning controller unpairing node:', nodeId);
1783
- await this.commissioningController.removeNode(nodeId);
1784
- }
1785
- return;
1786
- }
1787
-
1788
- if (hasParameter('discover')) {
1789
- // const discover = await this.commissioningController.discoverCommissionableDevices({ productId: 0x8000, deviceType: 0xfff1 });
1790
- // console.log(discover);
1791
- }
1792
-
1793
- if (!this.commissioningController.isCommissioned()) {
1794
- this.log.info('***Commissioning controller is not commissioned: use matterbridge -controller -pairingcode [pairingcode] to commission a device');
1795
- return;
1796
- }
1797
-
1798
- const nodeIds = this.commissioningController.getCommissionedNodes();
1799
- this.log.info(`***Commissioning controller is commissioned ${this.commissioningController.isCommissioned()} and has ${nodeIds.length} nodes commisioned: `);
1800
- for (const nodeId of nodeIds) {
1801
- this.log.info(`***Connecting to commissioned node: ${nodeId}`);
1802
-
1803
- const node = await this.commissioningController.connectNode(nodeId, {
1804
- autoSubscribe: false,
1805
- attributeChangedCallback: (peerNodeId, { path: { nodeId, clusterId, endpointId, attributeName }, value }) =>
1806
- this.log.info(`***Commissioning controller attributeChangedCallback ${peerNodeId}: attribute ${nodeId}/${endpointId}/${clusterId}/${attributeName} changed to ${Logger.toJSON(value)}`),
1807
- eventTriggeredCallback: (peerNodeId, { path: { nodeId, clusterId, endpointId, eventName }, events }) =>
1808
- this.log.info(`***Commissioning controller eventTriggeredCallback ${peerNodeId}: Event ${nodeId}/${endpointId}/${clusterId}/${eventName} triggered with ${Logger.toJSON(events)}`),
1809
- stateInformationCallback: (peerNodeId, info) => {
1810
- switch (info) {
1811
- case NodeStateInformation.Connected:
1812
- this.log.info(`***Commissioning controller stateInformationCallback ${peerNodeId}: Node ${nodeId} connected`);
1813
- break;
1814
- case NodeStateInformation.Disconnected:
1815
- this.log.info(`***Commissioning controller stateInformationCallback ${peerNodeId}: Node ${nodeId} disconnected`);
1816
- break;
1817
- case NodeStateInformation.Reconnecting:
1818
- this.log.info(`***Commissioning controller stateInformationCallback ${peerNodeId}: Node ${nodeId} reconnecting`);
1819
- break;
1820
- case NodeStateInformation.WaitingForDeviceDiscovery:
1821
- this.log.info(`***Commissioning controller stateInformationCallback ${peerNodeId}: Node ${nodeId} waiting for device discovery`);
1822
- break;
1823
- case NodeStateInformation.StructureChanged:
1824
- this.log.info(`***Commissioning controller stateInformationCallback ${peerNodeId}: Node ${nodeId} structure changed`);
1825
- break;
1826
- case NodeStateInformation.Decommissioned:
1827
- this.log.info(`***Commissioning controller stateInformationCallback ${peerNodeId}: Node ${nodeId} decommissioned`);
1828
- break;
1829
- default:
1830
- this.log.info(`***Commissioning controller stateInformationCallback ${peerNodeId}: Node ${nodeId} NodeStateInformation.${info}`);
1831
- break;
1832
- }
1833
- },
1834
- });
1835
-
1836
- node.logStructure();
1837
-
1838
- // Get the interaction client
1839
- this.log.info('Getting the interaction client');
1840
- const interactionClient = await node.getInteractionClient();
1841
- let cluster;
1842
- let attributes;
1843
-
1844
- // Log BasicInformationCluster
1845
- cluster = BasicInformationCluster;
1846
- attributes = await interactionClient.getMultipleAttributes({
1847
- attributes: [{ clusterId: cluster.id }],
1848
- });
1849
- if (attributes.length > 0) this.log.info(`Cluster: ${idn}${cluster.name}${rs}${nf} attributes:`);
1850
- attributes.forEach((attribute) => {
1851
- this.log.info(
1852
- `- endpoint ${or}${attribute.path.endpointId}${nf} cluster ${hk}${getClusterNameById(attribute.path.clusterId)}${nf} (${hk}0x${attribute.path.clusterId.toString(16)}${nf}) attribute ${zb}${attribute.path.attributeName}${nf} (${zb}0x${attribute.path.attributeId.toString(16)}${nf}): ${typeof attribute.value === 'object' ? stringify(attribute.value) : attribute.value}`,
1853
- );
1854
- });
1855
-
1856
- // Log PowerSourceCluster
1857
- cluster = PowerSourceCluster;
1858
- attributes = await interactionClient.getMultipleAttributes({
1859
- attributes: [{ clusterId: cluster.id }],
1860
- });
1861
- if (attributes.length > 0) this.log.info(`Cluster: ${idn}${cluster.name}${rs}${nf} attributes:`);
1862
- attributes.forEach((attribute) => {
1863
- this.log.info(
1864
- `- endpoint ${or}${attribute.path.endpointId}${nf} cluster ${hk}${getClusterNameById(attribute.path.clusterId)}${nf} (${hk}0x${attribute.path.clusterId.toString(16)}${nf}) attribute ${zb}${attribute.path.attributeName}${nf} (${zb}0x${attribute.path.attributeId.toString(16)}${nf}): ${typeof attribute.value === 'object' ? stringify(attribute.value) : attribute.value}`,
1865
- );
1866
- });
1867
-
1868
- // Log ThreadNetworkDiagnostics
1869
- cluster = ThreadNetworkDiagnosticsCluster;
1870
- attributes = await interactionClient.getMultipleAttributes({
1871
- attributes: [{ clusterId: cluster.id }],
1872
- });
1873
- if (attributes.length > 0) this.log.info(`Cluster: ${idn}${cluster.name}${rs}${nf} attributes:`);
1874
- attributes.forEach((attribute) => {
1875
- this.log.info(
1876
- `- endpoint ${or}${attribute.path.endpointId}${nf} cluster ${hk}${getClusterNameById(attribute.path.clusterId)}${nf} (${hk}0x${attribute.path.clusterId.toString(16)}${nf}) attribute ${zb}${attribute.path.attributeName}${nf} (${zb}0x${attribute.path.attributeId.toString(16)}${nf}): ${typeof attribute.value === 'object' ? stringify(attribute.value) : attribute.value}`,
1877
- );
1878
- });
1879
-
1880
- // Log SwitchCluster
1881
- cluster = SwitchCluster;
1882
- attributes = await interactionClient.getMultipleAttributes({
1883
- attributes: [{ clusterId: cluster.id }],
1884
- });
1885
- if (attributes.length > 0) this.log.info(`Cluster: ${idn}${cluster.name}${rs}${nf} attributes:`);
1886
- attributes.forEach((attribute) => {
1887
- this.log.info(
1888
- `- endpoint ${or}${attribute.path.endpointId}${nf} cluster ${hk}${getClusterNameById(attribute.path.clusterId)}${nf} (${hk}0x${attribute.path.clusterId.toString(16)}${nf}) attribute ${zb}${attribute.path.attributeName}${nf} (${zb}0x${attribute.path.attributeId.toString(16)}${nf}): ${typeof attribute.value === 'object' ? stringify(attribute.value) : attribute.value}`,
1889
- );
1890
- });
1891
-
1892
- this.log.info('Subscribing to all attributes and events');
1893
- await node.subscribeAllAttributesAndEvents({
1894
- ignoreInitialTriggers: false,
1895
- attributeChangedCallback: ({ path: { nodeId, clusterId, endpointId, attributeName }, version, value }) =>
1896
- this.log.info(
1897
- `***${db}Commissioning controller attributeChangedCallback version ${version}: attribute ${BLUE}${nodeId}${db}/${or}${endpointId}${db}/${hk}${getClusterNameById(clusterId)}${db}/${zb}${attributeName}${db} changed to ${typeof value === 'object' ? debugStringify(value ?? { none: true }) : value}`,
1898
- ),
1899
- eventTriggeredCallback: ({ path: { nodeId, clusterId, endpointId, eventName }, events }) => {
1900
- this.log.info(
1901
- `***${db}Commissioning controller eventTriggeredCallback: event ${BLUE}${nodeId}${db}/${or}${endpointId}${db}/${hk}${getClusterNameById(clusterId)}${db}/${zb}${eventName}${db} triggered with ${debugStringify(events ?? { none: true })}`,
1902
- );
1903
- },
1904
- });
1905
- this.log.info('Subscribed to all attributes and events');
1906
- }
1907
- */
1908
1367
  }
1909
- /** */
1910
- /** Matter.js methods */
1911
- /** */
1912
- /**
1913
- * Starts the matter storage with name Matterbridge, create the matterbridge context and performs a backup.
1914
- *
1915
- * @returns {Promise<void>} - A promise that resolves when the storage is started.
1916
- */
1917
1368
  async startMatterStorage() {
1918
- // Setup Matter storage
1919
1369
  this.log.info(`Starting matter node storage...`);
1920
1370
  this.matterStorageService = this.environment.get(StorageService);
1921
1371
  this.log.info(`Matter node storage service created: ${this.matterStorageService.location}`);
@@ -1924,17 +1374,8 @@ export class Matterbridge extends EventEmitter {
1924
1374
  this.matterbridgeContext = await this.createServerNodeContext('Matterbridge', 'Matterbridge', this.aggregatorDeviceType, this.aggregatorVendorId, this.aggregatorVendorName, this.aggregatorProductId, this.aggregatorProductName, this.aggregatorSerialNumber, this.aggregatorUniqueId);
1925
1375
  this.matterbridgeInformation.matterbridgeSerialNumber = await this.matterbridgeContext.get('serialNumber', '');
1926
1376
  this.log.info('Matter node storage started');
1927
- // Backup matter storage since it is created/opened correctly
1928
1377
  await this.backupMatterStorage(path.join(this.matterbridgeDirectory, this.matterStorageName), path.join(this.matterbridgeDirectory, this.matterStorageName + '.backup'));
1929
1378
  }
1930
- /**
1931
- * Makes a backup copy of the specified matter storage directory.
1932
- *
1933
- * @param {string} storageName - The name of the storage directory to be backed up.
1934
- * @param {string} backupName - The name of the backup directory to be created.
1935
- * @private
1936
- * @returns {Promise<void>} A promise that resolves when the has been done.
1937
- */
1938
1379
  async backupMatterStorage(storageName, backupName) {
1939
1380
  this.log.info('Creating matter node storage backup...');
1940
1381
  try {
@@ -1945,11 +1386,6 @@ export class Matterbridge extends EventEmitter {
1945
1386
  this.log.error(`Error creating matter node storage backup from ${storageName} to ${backupName}:`, error);
1946
1387
  }
1947
1388
  }
1948
- /**
1949
- * Stops the matter storage.
1950
- *
1951
- * @returns {Promise<void>} A promise that resolves when the storage is stopped.
1952
- */
1953
1389
  async stopMatterStorage() {
1954
1390
  this.log.info('Closing matter node storage...');
1955
1391
  await this.matterStorageManager?.close();
@@ -1958,20 +1394,6 @@ export class Matterbridge extends EventEmitter {
1958
1394
  this.matterbridgeContext = undefined;
1959
1395
  this.log.info('Matter node storage closed');
1960
1396
  }
1961
- /**
1962
- * Creates a server node storage context.
1963
- *
1964
- * @param {string} pluginName - The name of the plugin.
1965
- * @param {string} deviceName - The name of the device.
1966
- * @param {DeviceTypeId} deviceType - The device type of the device.
1967
- * @param {number} vendorId - The vendor ID.
1968
- * @param {string} vendorName - The vendor name.
1969
- * @param {number} productId - The product ID.
1970
- * @param {string} productName - The product name.
1971
- * @param {string} [serialNumber] - The serial number of the device (optional).
1972
- * @param {string} [uniqueId] - The unique ID of the device (optional).
1973
- * @returns {Promise<StorageContext>} The storage context for the commissioning server.
1974
- */
1975
1397
  async createServerNodeContext(pluginName, deviceName, deviceType, vendorId, vendorName, productId, productName, serialNumber, uniqueId) {
1976
1398
  const { randomBytes } = await import('node:crypto');
1977
1399
  if (!this.matterStorageService)
@@ -2005,15 +1427,6 @@ export class Matterbridge extends EventEmitter {
2005
1427
  this.log.debug(`- hardwareVersion: ${await storageContext.get('hardwareVersion')} hardwareVersionString: ${await storageContext.get('hardwareVersionString')}`);
2006
1428
  return storageContext;
2007
1429
  }
2008
- /**
2009
- * Creates a server node.
2010
- *
2011
- * @param {StorageContext} storageContext - The storage context for the server node.
2012
- * @param {number} [port] - The port number for the server node. Defaults to 5540.
2013
- * @param {number} [passcode] - The passcode for the server node. Defaults to 20242025.
2014
- * @param {number} [discriminator] - The discriminator for the server node. Defaults to 3850.
2015
- * @returns {Promise<ServerNode<ServerNode.RootEndpoint>>} A promise that resolves to the created server node.
2016
- */
2017
1430
  async createServerNode(storageContext, port = 5540, passcode = 20242025, discriminator = 3850) {
2018
1431
  const storeId = await storageContext.get('storeId');
2019
1432
  this.log.notice(`Creating server node for ${storeId} on port ${port} with passcode ${passcode} and discriminator ${discriminator}...`);
@@ -2023,37 +1436,24 @@ export class Matterbridge extends EventEmitter {
2023
1436
  this.log.debug(`- uniqueId: ${await storageContext.get('uniqueId')}`);
2024
1437
  this.log.debug(`- softwareVersion: ${await storageContext.get('softwareVersion')} softwareVersionString: ${await storageContext.get('softwareVersionString')}`);
2025
1438
  this.log.debug(`- hardwareVersion: ${await storageContext.get('hardwareVersion')} hardwareVersionString: ${await storageContext.get('hardwareVersionString')}`);
2026
- /**
2027
- * Create a Matter ServerNode, which contains the Root Endpoint and all relevant data and configuration
2028
- */
2029
1439
  const serverNode = await ServerNode.create({
2030
- // Required: Give the Node a unique ID which is used to store the state of this node
2031
1440
  id: storeId,
2032
- // Provide Network relevant configuration like the port
2033
- // Optional when operating only one device on a host, Default port is 5540
2034
1441
  network: {
2035
1442
  listeningAddressIpv4: this.ipv4address,
2036
1443
  listeningAddressIpv6: this.ipv6address,
2037
1444
  port,
2038
1445
  },
2039
- // Provide the certificate for the device
2040
1446
  operationalCredentials: {
2041
1447
  certification: this.certification,
2042
1448
  },
2043
- // Provide Commissioning relevant settings
2044
- // Optional for development/testing purposes
2045
1449
  commissioning: {
2046
1450
  passcode,
2047
1451
  discriminator,
2048
1452
  },
2049
- // Provide Node announcement settings
2050
- // Optional: If Ommitted some development defaults are used
2051
1453
  productDescription: {
2052
1454
  name: await storageContext.get('deviceName'),
2053
1455
  deviceType: DeviceTypeId(await storageContext.get('deviceType')),
2054
1456
  },
2055
- // Provide defaults for the BasicInformation cluster on the Root endpoint
2056
- // Optional: If Omitted some development defaults are used
2057
1457
  basicInformation: {
2058
1458
  vendorId: VendorId(await storageContext.get('vendorId')),
2059
1459
  vendorName: await storageContext.get('vendorName'),
@@ -2070,20 +1470,14 @@ export class Matterbridge extends EventEmitter {
2070
1470
  reachable: true,
2071
1471
  },
2072
1472
  });
2073
- /**
2074
- * This event is triggered when the device is initially commissioned successfully.
2075
- * This means: It is added to the first fabric.
2076
- */
2077
1473
  serverNode.lifecycle.commissioned.on(() => {
2078
1474
  this.log.notice(`Server node for ${storeId} was initially commissioned successfully!`);
2079
1475
  clearTimeout(this.endAdvertiseTimeout);
2080
1476
  });
2081
- /** This event is triggered when all fabrics are removed from the device, usually it also does a factory reset then. */
2082
1477
  serverNode.lifecycle.decommissioned.on(() => {
2083
1478
  this.log.notice(`Server node for ${storeId} was fully decommissioned successfully!`);
2084
1479
  clearTimeout(this.endAdvertiseTimeout);
2085
1480
  });
2086
- /** This event is triggered when the device went online. This means that it is discoverable in the network. */
2087
1481
  serverNode.lifecycle.online.on(async () => {
2088
1482
  this.log.notice(`Server node for ${storeId} is online`);
2089
1483
  if (!serverNode.lifecycle.isCommissioned) {
@@ -2091,11 +1485,9 @@ export class Matterbridge extends EventEmitter {
2091
1485
  const { qrPairingCode, manualPairingCode } = serverNode.state.commissioning.pairingCodes;
2092
1486
  this.log.notice(`QR Code URL: https://project-chip.github.io/connectedhomeip/qrcode.html?data=${qrPairingCode}`);
2093
1487
  this.log.notice(`Manual pairing code: ${manualPairingCode}`);
2094
- // Set a timeout to show that advertising stops after 15 minutes if not commissioned
2095
1488
  this.startEndAdvertiseTimer(serverNode);
2096
1489
  }
2097
1490
  else {
2098
- // istanbul ignore next
2099
1491
  this.log.notice(`Server node for ${storeId} is already commissioned. Waiting for controllers to connect ...`);
2100
1492
  }
2101
1493
  this.frontend.wssSendRefreshRequired('plugins');
@@ -2103,19 +1495,14 @@ export class Matterbridge extends EventEmitter {
2103
1495
  this.frontend.wssSendSnackbarMessage(`${storeId} is online`, 5, 'success');
2104
1496
  this.emit('online', storeId);
2105
1497
  });
2106
- /** This event is triggered when the device went offline. it is not longer discoverable or connectable in the network. */
2107
1498
  serverNode.lifecycle.offline.on(() => {
2108
1499
  this.log.notice(`Server node for ${storeId} is offline`);
2109
- this.matterbridgeInformation.matterbridgeEndAdvertise = true; // Set the end advertise flag to true, so the frontend won't show the QR code anymore
1500
+ this.matterbridgeInformation.matterbridgeEndAdvertise = true;
2110
1501
  this.frontend.wssSendRefreshRequired('plugins');
2111
1502
  this.frontend.wssSendRefreshRequired('settings');
2112
1503
  this.frontend.wssSendSnackbarMessage(`${storeId} is offline`, 5, 'warning');
2113
1504
  this.emit('offline', storeId);
2114
1505
  });
2115
- /**
2116
- * This event is triggered when a fabric is added, removed or updated on the device. Use this if more granular
2117
- * information is needed.
2118
- */
2119
1506
  serverNode.events.commissioning.fabricsChanged.on((fabricIndex, fabricAction) => {
2120
1507
  let action = '';
2121
1508
  switch (fabricAction) {
@@ -2132,22 +1519,14 @@ export class Matterbridge extends EventEmitter {
2132
1519
  this.log.notice(`Commissioned fabric index ${fabricIndex} ${action} on server node for ${storeId}: ${debugStringify(serverNode.state.commissioning.fabrics[fabricIndex])}`);
2133
1520
  this.frontend.wssSendRefreshRequired('fabrics');
2134
1521
  });
2135
- /**
2136
- * This event is triggered when an operative new session was opened by a Controller.
2137
- * It is not triggered for the initial commissioning process, just afterwards for real connections.
2138
- */
2139
1522
  serverNode.events.sessions.opened.on((session) => {
2140
1523
  this.log.notice(`Session opened on server node for ${storeId}: ${debugStringify(session)}`);
2141
1524
  this.frontend.wssSendRefreshRequired('sessions');
2142
1525
  });
2143
- /**
2144
- * This event is triggered when an operative session is closed by a Controller or because the Device goes offline.
2145
- */
2146
1526
  serverNode.events.sessions.closed.on((session) => {
2147
1527
  this.log.notice(`Session closed on server node for ${storeId}: ${debugStringify(session)}`);
2148
1528
  this.frontend.wssSendRefreshRequired('sessions');
2149
1529
  });
2150
- /** This event is triggered when a subscription gets added or removed on an operative session. */
2151
1530
  serverNode.events.sessions.subscriptionsChanged.on((session) => {
2152
1531
  this.log.notice(`Session subscriptions changed on server node for ${storeId}: ${debugStringify(session)}`);
2153
1532
  this.frontend.wssSendRefreshRequired('sessions');
@@ -2155,11 +1534,6 @@ export class Matterbridge extends EventEmitter {
2155
1534
  this.log.info(`Created server node for ${storeId}`);
2156
1535
  return serverNode;
2157
1536
  }
2158
- /**
2159
- * Starts the 15 minutes timer to advice that advertising for the specified server node is ended.
2160
- *
2161
- * @param {ServerNode} [matterServerNode] - The server node to start.
2162
- */
2163
1537
  startEndAdvertiseTimer(matterServerNode) {
2164
1538
  if (this.endAdvertiseTimeout) {
2165
1539
  this.log.debug(`Clear ${matterServerNode.id} server node end advertise timer`);
@@ -2178,25 +1552,12 @@ export class Matterbridge extends EventEmitter {
2178
1552
  this.log.notice(`Advertising stopped. Restart to commission again.`);
2179
1553
  }, 15 * 60 * 1000).unref();
2180
1554
  }
2181
- /**
2182
- * Starts the specified server node.
2183
- *
2184
- * @param {ServerNode} [matterServerNode] - The server node to start.
2185
- * @returns {Promise<void>} A promise that resolves when the server node has started.
2186
- */
2187
1555
  async startServerNode(matterServerNode) {
2188
1556
  if (!matterServerNode)
2189
1557
  return;
2190
1558
  this.log.notice(`Starting ${matterServerNode.id} server node`);
2191
1559
  await matterServerNode.start();
2192
1560
  }
2193
- /**
2194
- * Stops the specified server node.
2195
- *
2196
- * @param {ServerNode} matterServerNode - The server node to stop.
2197
- * @param {number} [timeout] - The timeout in milliseconds for stopping the server node. Defaults to 30 seconds.
2198
- * @returns {Promise<void>} A promise that resolves when the server node has stopped.
2199
- */
2200
1561
  async stopServerNode(matterServerNode, timeout = 30000) {
2201
1562
  if (!matterServerNode)
2202
1563
  return;
@@ -2209,12 +1570,6 @@ export class Matterbridge extends EventEmitter {
2209
1570
  this.log.error(`Failed to close ${matterServerNode.id} server node: ${error instanceof Error ? error.message : error}`);
2210
1571
  }
2211
1572
  }
2212
- /**
2213
- * Advertises the specified server node.
2214
- *
2215
- * @param {ServerNode} [matterServerNode] - The server node to advertise.
2216
- * @returns {Promise<{ qrPairingCode: string, manualPairingCode: string } | undefined>} A promise that resolves to the pairing codes if the server node is advertised, or undefined if not.
2217
- */
2218
1573
  async advertiseServerNode(matterServerNode) {
2219
1574
  if (matterServerNode) {
2220
1575
  await matterServerNode.env.get(DeviceCommissioner)?.allowBasicCommissioning();
@@ -2223,39 +1578,19 @@ export class Matterbridge extends EventEmitter {
2223
1578
  return { qrPairingCode, manualPairingCode };
2224
1579
  }
2225
1580
  }
2226
- /**
2227
- * Stop advertise the specified server node.
2228
- *
2229
- * @param {ServerNode} [matterServerNode] - The server node to advertise.
2230
- * @returns {Promise<void>} A promise that resolves when the server node has stopped advertising.
2231
- */
2232
1581
  async stopAdvertiseServerNode(matterServerNode) {
2233
1582
  if (matterServerNode && matterServerNode.lifecycle.isOnline) {
2234
1583
  await matterServerNode.env.get(DeviceCommissioner)?.endCommissioning();
2235
1584
  this.log.notice(`Stopped advertising for ${matterServerNode.id}`);
2236
1585
  }
2237
1586
  }
2238
- /**
2239
- * Creates an aggregator node with the specified storage context.
2240
- *
2241
- * @param {StorageContext} storageContext - The storage context for the aggregator node.
2242
- * @returns {Promise<Endpoint<AggregatorEndpoint>>} A promise that resolves to the created aggregator node.
2243
- */
2244
1587
  async createAggregatorNode(storageContext) {
2245
1588
  this.log.notice(`Creating ${await storageContext.get('storeId')} aggregator...`);
2246
1589
  const aggregatorNode = new Endpoint(AggregatorEndpoint, { id: `${await storageContext.get('storeId')}` });
2247
1590
  this.log.info(`Created ${await storageContext.get('storeId')} aggregator`);
2248
1591
  return aggregatorNode;
2249
1592
  }
2250
- /**
2251
- * Adds a MatterbridgeEndpoint to the specified plugin.
2252
- *
2253
- * @param {string} pluginName - The name of the plugin.
2254
- * @param {MatterbridgeEndpoint} device - The device to add as a bridged endpoint.
2255
- * @returns {Promise<void>} A promise that resolves when the bridged endpoint has been added.
2256
- */
2257
1593
  async addBridgedEndpoint(pluginName, device) {
2258
- // Check if the plugin is registered
2259
1594
  const plugin = this.plugins.get(pluginName);
2260
1595
  if (!plugin) {
2261
1596
  this.log.error(`Error adding bridged endpoint ${dev}${device.deviceName}${er} (${zb}${device.id}${er}) plugin ${plg}${pluginName}${er} not found`);
@@ -2275,7 +1610,6 @@ export class Matterbridge extends EventEmitter {
2275
1610
  }
2276
1611
  else if (this.bridgeMode === 'bridge') {
2277
1612
  if (device.mode === 'matter') {
2278
- // Register and add the device to the matterbridge server node
2279
1613
  this.log.debug(`Adding matter endpoint ${plg}${pluginName}${db}:${dev}${device.deviceName}${db} to Matterbridge server node...`);
2280
1614
  if (!this.serverNode) {
2281
1615
  this.log.error('Server node not found for Matterbridge');
@@ -2292,7 +1626,6 @@ export class Matterbridge extends EventEmitter {
2292
1626
  }
2293
1627
  }
2294
1628
  else {
2295
- // Register and add the device to the matterbridge aggregator node
2296
1629
  this.log.debug(`Adding bridged endpoint ${plg}${pluginName}${db}:${dev}${device.deviceName}${db} to Matterbridge aggregator node`);
2297
1630
  if (!this.aggregatorNode) {
2298
1631
  this.log.error('Aggregator node not found for Matterbridge');
@@ -2310,7 +1643,6 @@ export class Matterbridge extends EventEmitter {
2310
1643
  }
2311
1644
  }
2312
1645
  else if (this.bridgeMode === 'childbridge') {
2313
- // Register and add the device to the plugin server node
2314
1646
  if (plugin.type === 'AccessoryPlatform') {
2315
1647
  try {
2316
1648
  this.log.debug(`Creating endpoint ${dev}${device.deviceName}${db} for AccessoryPlatform plugin ${plg}${plugin.name}${db} server node`);
@@ -2334,12 +1666,10 @@ export class Matterbridge extends EventEmitter {
2334
1666
  return;
2335
1667
  }
2336
1668
  }
2337
- // Register and add the device to the plugin aggregator node
2338
1669
  if (plugin.type === 'DynamicPlatform') {
2339
1670
  try {
2340
1671
  this.log.debug(`Adding bridged endpoint ${dev}${device.deviceName}${db} for DynamicPlatform plugin ${plg}${plugin.name}${db} aggregator node`);
2341
1672
  await this.createDynamicPlugin(plugin);
2342
- // Fast plugins can add another device before the server node is ready, so we wait for the server node to be ready
2343
1673
  await waiter(`createDynamicPlugin(${plugin.name})`, () => plugin.serverNode?.hasParts === true);
2344
1674
  if (!plugin.aggregatorNode) {
2345
1675
  this.log.error(`Aggregator node not found for plugin ${plg}${plugin.name}${er}`);
@@ -2362,28 +1692,17 @@ export class Matterbridge extends EventEmitter {
2362
1692
  plugin.registeredDevices++;
2363
1693
  if (plugin.addedDevices !== undefined)
2364
1694
  plugin.addedDevices++;
2365
- // Add the device to the DeviceManager
2366
1695
  this.devices.set(device);
2367
- // Subscribe to the reachable$Changed event
2368
1696
  await this.subscribeAttributeChanged(plugin, device);
2369
1697
  this.log.info(`Added and registered bridged endpoint (${plugin.registeredDevices}/${plugin.addedDevices}) ${dev}${device.deviceName}${nf} (${dev}${device.id}${nf}) for plugin ${plg}${pluginName}${nf}`);
2370
1698
  }
2371
- /**
2372
- * Removes a MatterbridgeEndpoint from the specified plugin.
2373
- *
2374
- * @param {string} pluginName - The name of the plugin.
2375
- * @param {MatterbridgeEndpoint} device - The device to remove as a bridged endpoint.
2376
- * @returns {Promise<void>} A promise that resolves when the bridged endpoint has been removed.
2377
- */
2378
1699
  async removeBridgedEndpoint(pluginName, device) {
2379
1700
  this.log.debug(`Removing bridged endpoint ${plg}${pluginName}${db}:${dev}${device.deviceName}${db} (${zb}${device.name}${db}) for plugin ${plg}${pluginName}${db}`);
2380
- // Check if the plugin is registered
2381
1701
  const plugin = this.plugins.get(pluginName);
2382
1702
  if (!plugin) {
2383
1703
  this.log.error(`Error removing bridged endpoint ${dev}${device.deviceName}${er} (${zb}${device.name}${er}) for plugin ${plg}${pluginName}${er}: plugin not found`);
2384
1704
  return;
2385
1705
  }
2386
- // Register and add the device to the matterbridge aggregator node
2387
1706
  if (this.bridgeMode === 'bridge') {
2388
1707
  if (!this.aggregatorNode) {
2389
1708
  this.log.error(`Error removing bridged endpoint ${dev}${device.deviceName}${er} (${zb}${device.name}${er}) for plugin ${plg}${pluginName}${er}: aggregator node not found`);
@@ -2398,7 +1717,6 @@ export class Matterbridge extends EventEmitter {
2398
1717
  }
2399
1718
  else if (this.bridgeMode === 'childbridge') {
2400
1719
  if (plugin.type === 'AccessoryPlatform') {
2401
- // Nothing to do here since the server node has no aggregator node but only the device itself
2402
1720
  }
2403
1721
  else if (plugin.type === 'DynamicPlatform') {
2404
1722
  if (!plugin.aggregatorNode) {
@@ -2413,21 +1731,8 @@ export class Matterbridge extends EventEmitter {
2413
1731
  if (plugin.addedDevices !== undefined)
2414
1732
  plugin.addedDevices--;
2415
1733
  }
2416
- // Remove the device from the DeviceManager
2417
1734
  this.devices.remove(device);
2418
1735
  }
2419
- /**
2420
- * Removes all bridged endpoints from the specified plugin.
2421
- *
2422
- * @param {string} pluginName - The name of the plugin.
2423
- * @param {number} [delay] - The delay in milliseconds between removing each bridged endpoint (default: 0).
2424
- * @returns {Promise<void>} A promise that resolves when all bridged endpoints have been removed.
2425
- *
2426
- * @remarks
2427
- * This method iterates through all devices in the DeviceManager and removes each bridged endpoint associated with the specified plugin.
2428
- * It also applies a delay between each removal if specified.
2429
- * The delay is useful to allow the controllers to receive a single subscription for each device removed.
2430
- */
2431
1736
  async removeAllBridgedEndpoints(pluginName, delay = 0) {
2432
1737
  this.log.debug(`Removing all bridged endpoints for plugin ${plg}${pluginName}${db}${delay > 0 ? ` with delay ${delay} ms` : ''}`);
2433
1738
  for (const device of this.devices.array().filter((device) => device.plugin === pluginName)) {
@@ -2438,15 +1743,6 @@ export class Matterbridge extends EventEmitter {
2438
1743
  if (delay > 0)
2439
1744
  await wait(2000);
2440
1745
  }
2441
- /**
2442
- * Subscribes to the attribute change event for the given device and plugin.
2443
- * Specifically, it listens for changes in the 'reachable' attribute of the
2444
- * BridgedDeviceBasicInformationServer cluster server of the bridged device or BasicInformationServer cluster server of server node.
2445
- *
2446
- * @param {RegisteredPlugin} plugin - The plugin associated with the device.
2447
- * @param {MatterbridgeEndpoint} device - The device to subscribe to attribute changes for.
2448
- * @returns {Promise<void>} A promise that resolves when the subscription is set up.
2449
- */
2450
1746
  async subscribeAttributeChanged(plugin, device) {
2451
1747
  this.log.info(`Subscribing attributes for endpoint ${dev}${device.deviceName}${nf} (${dev}${device.id}${nf}) plugin ${plg}${plugin.name}${nf}`);
2452
1748
  if (this.bridgeMode === 'childbridge' && plugin.type === 'AccessoryPlatform' && plugin.serverNode) {
@@ -2462,12 +1758,6 @@ export class Matterbridge extends EventEmitter {
2462
1758
  });
2463
1759
  }
2464
1760
  }
2465
- /**
2466
- * Sanitizes the fabric information by converting bigint properties to strings because `res.json` doesn't support bigint.
2467
- *
2468
- * @param {ExposedFabricInformation[]} fabricInfo - The array of exposed fabric information objects.
2469
- * @returns {SanitizedExposedFabricInformation[]} An array of sanitized exposed fabric information objects.
2470
- */
2471
1761
  sanitizeFabricInformations(fabricInfo) {
2472
1762
  return fabricInfo.map((info) => {
2473
1763
  return {
@@ -2481,12 +1771,6 @@ export class Matterbridge extends EventEmitter {
2481
1771
  };
2482
1772
  });
2483
1773
  }
2484
- /**
2485
- * Sanitizes the session information by converting bigint properties to strings because `res.json` doesn't support bigint.
2486
- *
2487
- * @param {SessionsBehavior.Session[]} sessions - The array of session information objects.
2488
- * @returns {SanitizedSession[]} An array of sanitized session information objects.
2489
- */
2490
1774
  sanitizeSessionInformation(sessions) {
2491
1775
  return sessions
2492
1776
  .filter((session) => session.isPeerActive)
@@ -2513,21 +1797,7 @@ export class Matterbridge extends EventEmitter {
2513
1797
  };
2514
1798
  });
2515
1799
  }
2516
- /**
2517
- * Sets the reachability of the specified aggregator node bridged devices and trigger.
2518
- *
2519
- * @param {Endpoint<AggregatorEndpoint>} aggregatorNode - The aggregator node to set the reachability for.
2520
- * @param {boolean} reachable - A boolean indicating the reachability status to set.
2521
- */
2522
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
2523
1800
  async setAggregatorReachability(aggregatorNode, reachable) {
2524
- /*
2525
- for (const child of aggregatorNode.parts) {
2526
- this.log.debug(`Setting reachability of ${(child as unknown as MatterbridgeEndpoint)?.deviceName} to ${reachable}`);
2527
- await child.setStateOf(BridgedDeviceBasicInformationServer, { reachable });
2528
- child.act((agent) => child.eventsOf(BridgedDeviceBasicInformationServer).reachableChanged.emit({ reachableNewValue: true }, agent.context));
2529
- }
2530
- */
2531
1801
  }
2532
1802
  getVendorIdName = (vendorId) => {
2533
1803
  if (!vendorId)
@@ -2567,11 +1837,10 @@ export class Matterbridge extends EventEmitter {
2567
1837
  case 0x1488:
2568
1838
  vendorName = '(ShortcutLabsFlic)';
2569
1839
  break;
2570
- case 65521: // 0xFFF1
1840
+ case 65521:
2571
1841
  vendorName = '(MatterTest)';
2572
1842
  break;
2573
1843
  }
2574
1844
  return vendorName;
2575
1845
  };
2576
1846
  }
2577
- //# sourceMappingURL=matterbridge.js.map