matterbridge 3.2.4 → 3.2.5-dev-20250831-732330c

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