@matterbridge/core 3.9.1-dev-20260614-18d1a2e → 3.9.1-dev-20260617-b1e1b99

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 (80) hide show
  1. package/README.md +5 -3
  2. package/dist/backend.js +17 -6
  3. package/dist/backendExpress.d.ts +1 -1
  4. package/dist/backendExpress.js +12 -12
  5. package/dist/backendWsServer.d.ts +1 -1
  6. package/dist/backendWsServer.js +3 -3
  7. package/dist/behaviors/activatedCarbonFilterMonitoringServer.d.ts +1 -1
  8. package/dist/behaviors/bindingServer.d.ts +4 -4
  9. package/dist/behaviors/bindingServer.js +2 -2
  10. package/dist/behaviors/booleanStateConfigurationServer.js +2 -1
  11. package/dist/behaviors/doorLockServer.d.ts +1 -1
  12. package/dist/behaviors/doorLockServer.js +2 -2
  13. package/dist/behaviors/hepaFilterMonitoringServer.d.ts +1 -1
  14. package/dist/behaviors/identifyServer.d.ts +1 -1
  15. package/dist/behaviors/levelControlServer.d.ts +1 -1
  16. package/dist/behaviors/matterbridgeServer.d.ts +2 -2
  17. package/dist/behaviors/modeSelectServer.d.ts +1 -1
  18. package/dist/behaviors/operationalStateServer.d.ts +1 -1
  19. package/dist/behaviors/serviceAreaServer.d.ts +1 -1
  20. package/dist/behaviors/windowCoveringServer.d.ts +2 -2
  21. package/dist/behaviors/windowCoveringServer.js +3 -3
  22. package/dist/cli.js +9 -9
  23. package/dist/cliEmitter.js +2 -2
  24. package/dist/cliHistory.js +2 -2
  25. package/dist/clusters/export.d.ts +1 -1
  26. package/dist/clusters/export.js +1 -1
  27. package/dist/deviceManager.d.ts +1 -1
  28. package/dist/deviceManager.js +3 -4
  29. package/dist/devices/batteryStorage.js +2 -1
  30. package/dist/devices/cooktop.d.ts +1 -1
  31. package/dist/devices/cooktop.js +2 -1
  32. package/dist/devices/dishwasher.d.ts +1 -1
  33. package/dist/devices/evse.d.ts +1 -1
  34. package/dist/devices/evse.js +4 -2
  35. package/dist/devices/extractorHood.js +2 -1
  36. package/dist/devices/heatPump.js +7 -8
  37. package/dist/devices/irrigationSystem.d.ts +1 -1
  38. package/dist/devices/laundryDryer.d.ts +1 -1
  39. package/dist/devices/laundryWasher.d.ts +1 -1
  40. package/dist/devices/oven.d.ts +2 -2
  41. package/dist/devices/oven.js +4 -3
  42. package/dist/devices/refrigerator.d.ts +2 -2
  43. package/dist/devices/refrigerator.js +2 -1
  44. package/dist/devices/solarPower.d.ts +1 -1
  45. package/dist/devices/solarPower.js +2 -1
  46. package/dist/devices/temperatureControl.d.ts +1 -1
  47. package/dist/devices/waterHeater.js +2 -1
  48. package/dist/export.js +2 -2
  49. package/dist/frontend.js +39 -39
  50. package/dist/helpers.d.ts +1 -1
  51. package/dist/helpers.js +6 -4
  52. package/dist/jestutils/jestMatterTest.js +1 -1
  53. package/dist/jestutils/jestMatterbridgeTest.d.ts +2 -2
  54. package/dist/jestutils/jestMatterbridgeTest.js +1 -1
  55. package/dist/jestutils/jestSetupTest.js +13 -12
  56. package/dist/jestutils/matterRequest.d.ts +1 -1
  57. package/dist/matterNode.js +8 -6
  58. package/dist/matterbridge.js +11 -21
  59. package/dist/matterbridgeAccessoryPlatform.d.ts +1 -1
  60. package/dist/matterbridgeAccessoryPlatform.js +2 -2
  61. package/dist/matterbridgeDeviceTypes.js +2 -2
  62. package/dist/matterbridgeDynamicPlatform.d.ts +1 -1
  63. package/dist/matterbridgeDynamicPlatform.js +2 -2
  64. package/dist/matterbridgeEndpoint.d.ts +9 -9
  65. package/dist/matterbridgeEndpoint.js +9 -8
  66. package/dist/matterbridgeEndpointCommandHandler.d.ts +40 -40
  67. package/dist/matterbridgeEndpointCommandHandler.js +2 -2
  68. package/dist/matterbridgeEndpointHelpers.d.ts +2 -2
  69. package/dist/matterbridgeEndpointHelpers.js +2 -2
  70. package/dist/matterbridgeEndpointTypes.js +2 -3
  71. package/dist/matterbridgeFactory.d.ts +1 -1
  72. package/dist/matterbridgeFactory.js +2 -2
  73. package/dist/matterbridgePlatform.d.ts +1 -1
  74. package/dist/matterbridgePlatform.js +2 -2
  75. package/dist/mb_coap.js +3 -1
  76. package/dist/mb_health.js +3 -1
  77. package/dist/mb_mdns.js +10 -7
  78. package/dist/pluginManager.d.ts +1 -1
  79. package/dist/pluginManager.js +11 -6
  80. package/package.json +7 -7
package/README.md CHANGED
@@ -6,10 +6,12 @@
6
6
  [![Docker Pulls](https://img.shields.io/docker/pulls/luligu/matterbridge?label=docker%20pulls)](https://hub.docker.com/r/luligu/matterbridge)
7
7
  ![Node.js CI](https://github.com/Luligu/matterbridge/actions/workflows/build.yml/badge.svg)
8
8
  ![CodeQL](https://github.com/Luligu/matterbridge/actions/workflows/codeql.yml/badge.svg)
9
- [![codecov](https://codecov.io/gh/Luligu/matterbridge/branch/main/graph/badge.svg)](https://codecov.io/gh/Luligu/matterbridge)
10
- [![styled with prettier](https://img.shields.io/badge/styled_with-Prettier-f8bc45.svg?logo=prettier)](https://prettier.io/)
11
- [![linted with eslint](https://img.shields.io/badge/linted_with-ES_Lint-4B32C3.svg?logo=eslint)](https://eslint.org/)
9
+ [![Codecov](https://codecov.io/gh/Luligu/matterbridge/branch/main/graph/badge.svg)](https://codecov.io/gh/Luligu/matterbridge)
10
+ [![tested with Vitest](https://img.shields.io/badge/tested_with-Vitest-6E9F18.svg?logo=vitest&logoColor=white)](https://vitest.dev)
11
+ [![styled with Oxc](https://img.shields.io/badge/styled_with-Oxc-9BE4E0.svg?logo=oxc&logoColor=white)](https://oxc.rs/docs/guide/usage/formatter.html)
12
+ [![linted with Oxc](https://img.shields.io/badge/linted_with-Oxc-9BE4E0.svg?logo=oxc&logoColor=white)](https://oxc.rs/docs/guide/usage/linter.html)
12
13
  [![TypeScript](https://img.shields.io/badge/TypeScript-3178C6?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
14
+ [![TypeScript Native](https://img.shields.io/badge/TypeScript_Native-3178C6?logo=typescript&logoColor=white)](https://github.com/microsoft/typescript-go)
13
15
  [![ESM](https://img.shields.io/badge/ESM-Node.js-339933?logo=node.js&logoColor=white)](https://nodejs.org/)
14
16
  [![matterbridge.io](https://img.shields.io/badge/matterbridge.io-online-brightgreen)](https://matterbridge.io)
15
17
 
package/dist/backend.js CHANGED
@@ -3,9 +3,9 @@ import path from 'node:path';
3
3
  import { BroadcastServer } from '@matterbridge/thread';
4
4
  import { getParameter, hasParameter } from '@matterbridge/utils/cli';
5
5
  import { getErrorMessage, inspectError, logError } from '@matterbridge/utils/error';
6
+ import { logModuleLoaded } from '@matterbridge/utils/loader';
6
7
  import { AnsiLogger, rs, UNDERLINE, UNDERLINEOFF } from 'node-ansi-logger';
7
- if (hasParameter('loader'))
8
- console.log('\u001B[32m[' + new Date().toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit', fractionalSecondDigits: 3 }) + '] Backend loaded.\u001B[40;0m');
8
+ logModuleLoaded('Backend');
9
9
  export class Backend extends EventEmitter {
10
10
  debug;
11
11
  verbose;
@@ -36,7 +36,6 @@ export class Backend extends EventEmitter {
36
36
  this.server.on('broadcast_message', this.broadcastMsgHandler.bind(this));
37
37
  }
38
38
  destroy() {
39
- this.server.off('broadcast_message', this.broadcastMsgHandler.bind(this));
40
39
  this.server.close();
41
40
  }
42
41
  async broadcastMsgHandler(msg) {
@@ -61,6 +60,7 @@ export class Backend extends EventEmitter {
61
60
  this.backendWsServer = new BackendWsServer(this.matterbridge, this);
62
61
  if (!hasParameter('ssl')) {
63
62
  const http = await import('node:http');
63
+ await this.backendExpress.start();
64
64
  try {
65
65
  this.log.debug(`Creating HTTP server...`);
66
66
  this.httpServer = http.createServer(this.backendExpress.expressApp);
@@ -68,8 +68,10 @@ export class Backend extends EventEmitter {
68
68
  catch (error) {
69
69
  logError(this.log, `Failed to create HTTP server`, error);
70
70
  this.emit('server_error', error);
71
+ await this.backendExpress.stop();
71
72
  return;
72
73
  }
74
+ await this.backendWsServer.start();
73
75
  this.httpServer.listen(this.port, getParameter('bind'), () => {
74
76
  const addr = this.httpServer?.address();
75
77
  if (addr && typeof addr !== 'string') {
@@ -110,7 +112,7 @@ export class Backend extends EventEmitter {
110
112
  socket.destroy();
111
113
  }
112
114
  }
113
- return;
115
+ return undefined;
114
116
  });
115
117
  this.httpServer.on('error', (error) => {
116
118
  this.log.error(`Frontend http server error listening on ${this.port}`);
@@ -123,7 +125,7 @@ export class Backend extends EventEmitter {
123
125
  break;
124
126
  }
125
127
  this.emit('server_error', error);
126
- return;
128
+ return undefined;
127
129
  });
128
130
  }
129
131
  else {
@@ -191,6 +193,7 @@ export class Backend extends EventEmitter {
191
193
  httpsServerOptions.rejectUnauthorized = true;
192
194
  }
193
195
  const https = await import('node:https');
196
+ await this.backendExpress.start();
194
197
  try {
195
198
  this.log.debug(`Creating HTTPS server...`);
196
199
  this.httpsServer = https.createServer(httpsServerOptions, this.backendExpress.expressApp);
@@ -198,8 +201,10 @@ export class Backend extends EventEmitter {
198
201
  catch (error) {
199
202
  logError(this.log, `Failed to create HTTPS server`, error);
200
203
  this.emit('server_error', error);
204
+ await this.backendExpress.stop();
201
205
  return;
202
206
  }
207
+ await this.backendWsServer.start();
203
208
  this.httpsServer.listen(this.port, getParameter('bind'), () => {
204
209
  const addr = this.httpsServer?.address();
205
210
  if (addr && typeof addr !== 'string') {
@@ -239,7 +244,7 @@ export class Backend extends EventEmitter {
239
244
  socket.destroy();
240
245
  }
241
246
  }
242
- return;
247
+ return undefined;
243
248
  });
244
249
  this.httpsServer.on('error', (error) => {
245
250
  this.log.error(`Frontend https server error listening on ${this.port}`);
@@ -259,6 +264,7 @@ export class Backend extends EventEmitter {
259
264
  }
260
265
  async stop() {
261
266
  this.log.debug('Stopping backend...');
267
+ await this.backendWsServer?.stop();
262
268
  if (this.httpServer) {
263
269
  this.log.debug('Closing http server...');
264
270
  this.httpServer.close();
@@ -279,6 +285,11 @@ export class Backend extends EventEmitter {
279
285
  this.httpsServer = undefined;
280
286
  this.log.debug('Backend https server closed successfully');
281
287
  }
288
+ await this.backendExpress?.stop();
289
+ this.backendWsServer?.destroy();
290
+ this.backendExpress?.destroy();
291
+ this.backendWsServer = undefined;
292
+ this.backendExpress = undefined;
282
293
  this.log.debug('Backend stopped');
283
294
  }
284
295
  getApiSettings() {
@@ -1,6 +1,6 @@
1
1
  import { type SharedMatterbridge } from '@matterbridge/types';
2
2
  import express from 'express';
3
- import { type Backend } from './backend.js';
3
+ import type { Backend } from './backend.js';
4
4
  export declare class BackendExpress {
5
5
  private debug;
6
6
  private verbose;
@@ -5,13 +5,13 @@ import { MATTER_LOGGER_FILE, MATTER_STORAGE_DIR, MATTERBRIDGE_BACKUP_FILE, MATTE
5
5
  import { hasParameter } from '@matterbridge/utils/cli';
6
6
  import { getErrorMessage } from '@matterbridge/utils/error';
7
7
  import { formatBytes } from '@matterbridge/utils/format';
8
+ import { logModuleLoaded } from '@matterbridge/utils/loader';
8
9
  import escapeHtml from 'escape-html';
9
10
  import express from 'express';
10
11
  import { rateLimit } from 'express-rate-limit';
11
12
  import multer from 'multer';
12
13
  import { AnsiLogger, er, nf } from 'node-ansi-logger';
13
- if (hasParameter('loader'))
14
- console.log('\u001B[32m[' + new Date().toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit', fractionalSecondDigits: 3 }) + '] BackendExpress loaded.\u001B[40;0m');
14
+ logModuleLoaded('BackendExpress');
15
15
  export class BackendExpress {
16
16
  debug;
17
17
  verbose;
@@ -40,7 +40,6 @@ export class BackendExpress {
40
40
  this.server.on('broadcast_message', this.broadcastMsgHandler.bind(this));
41
41
  }
42
42
  destroy() {
43
- this.server.off('broadcast_message', this.broadcastMsgHandler.bind(this));
44
43
  this.server.close();
45
44
  }
46
45
  async broadcastMsgHandler(msg) {
@@ -53,6 +52,7 @@ export class BackendExpress {
53
52
  this.log.logLevel = msg.params.logLevel;
54
53
  this.server.respond({ ...msg, result: { logLevel: this.log.logLevel } });
55
54
  break;
55
+ default:
56
56
  }
57
57
  }
58
58
  }
@@ -76,7 +76,7 @@ export class BackendExpress {
76
76
  });
77
77
  }
78
78
  this.expressApp.use(express.static(path.join(this.matterbridge.rootDirectory, 'apps', 'frontend', 'build')));
79
- this.expressApp.post('/api/login', express.json(), async (req, res) => {
79
+ this.expressApp.post('/api/login', express.json(), (req, res) => {
80
80
  const { password } = req.body;
81
81
  this.log.debug(`The frontend sent /api/login with password ${password ? '[redacted]' : '(empty)'}`);
82
82
  if (this.backend.storedPassword === '' || password === this.backend.storedPassword) {
@@ -131,19 +131,19 @@ export class BackendExpress {
131
131
  };
132
132
  res.status(200).json(memoryReport);
133
133
  });
134
- this.expressApp.get('/api/settings', async (req, res) => {
134
+ this.expressApp.get('/api/settings', (req, res) => {
135
135
  this.log.debug('The frontend sent /api/settings');
136
136
  if (!this.validateReq(req, res))
137
137
  return;
138
138
  res.json(this.backend.getApiSettings());
139
139
  });
140
- this.expressApp.get('/api/plugins', async (req, res) => {
140
+ this.expressApp.get('/api/plugins', (req, res) => {
141
141
  this.log.debug('The frontend sent /api/plugins');
142
142
  if (!this.validateReq(req, res))
143
143
  return;
144
144
  res.json(this.backend.getApiPlugins());
145
145
  });
146
- this.expressApp.get('/api/devices', async (req, res) => {
146
+ this.expressApp.get('/api/devices', (req, res) => {
147
147
  this.log.debug('The frontend sent /api/devices');
148
148
  if (!this.validateReq(req, res))
149
149
  return;
@@ -310,7 +310,7 @@ export class BackendExpress {
310
310
  res.status(500).send('Error reading history file.');
311
311
  }
312
312
  });
313
- this.expressApp.get('/api/download-backup', this.fileLimiter, async (req, res) => {
313
+ this.expressApp.get('/api/download-backup', this.fileLimiter, (req, res) => {
314
314
  this.log.debug('The frontend sent /api/download-backup');
315
315
  if (!this.validateReq(req, res))
316
316
  return;
@@ -325,7 +325,7 @@ export class BackendExpress {
325
325
  }
326
326
  });
327
327
  });
328
- this.expressApp.get('/api/download-mbstorage', this.fileLimiter, async (req, res) => {
328
+ this.expressApp.get('/api/download-mbstorage', this.fileLimiter, (req, res) => {
329
329
  this.log.debug('The frontend sent /api/download-mbstorage');
330
330
  if (!this.validateReq(req, res))
331
331
  return;
@@ -340,7 +340,7 @@ export class BackendExpress {
340
340
  }
341
341
  });
342
342
  });
343
- this.expressApp.get('/api/download-mjstorage', this.fileLimiter, async (req, res) => {
343
+ this.expressApp.get('/api/download-mjstorage', this.fileLimiter, (req, res) => {
344
344
  this.log.debug('The frontend sent /api/download-mjstorage');
345
345
  if (!this.validateReq(req, res))
346
346
  return;
@@ -355,7 +355,7 @@ export class BackendExpress {
355
355
  }
356
356
  });
357
357
  });
358
- this.expressApp.get('/api/download-pluginstorage', this.fileLimiter, async (req, res) => {
358
+ this.expressApp.get('/api/download-pluginstorage', this.fileLimiter, (req, res) => {
359
359
  this.log.debug('The frontend sent /api/download-pluginstorage');
360
360
  if (!this.validateReq(req, res))
361
361
  return;
@@ -370,7 +370,7 @@ export class BackendExpress {
370
370
  }
371
371
  });
372
372
  });
373
- this.expressApp.get('/api/download-pluginconfig', this.fileLimiter, async (req, res) => {
373
+ this.expressApp.get('/api/download-pluginconfig', this.fileLimiter, (req, res) => {
374
374
  this.log.debug('The frontend sent /api/download-pluginconfig');
375
375
  if (!this.validateReq(req, res))
376
376
  return;
@@ -1,7 +1,7 @@
1
1
  import type { EndpointNumber } from '@matter/types/datatype';
2
2
  import type { ApiMatter, RefreshRequiredChanged, SharedMatterbridge, WsMessageBroadcast } from '@matterbridge/types';
3
3
  import { WebSocketServer } from 'ws';
4
- import { type Backend } from './backend.js';
4
+ import type { Backend } from './backend.js';
5
5
  export declare class BackendWsServer {
6
6
  private debug;
7
7
  private verbose;
@@ -2,12 +2,12 @@ import { Logger, LogLevel as MatterLogLevel } from '@matter/general';
2
2
  import { BroadcastServer } from '@matterbridge/thread';
3
3
  import { hasParameter } from '@matterbridge/utils/cli';
4
4
  import { inspectError } from '@matterbridge/utils/error';
5
+ import { logModuleLoaded } from '@matterbridge/utils/loader';
5
6
  import { isValidNumber, isValidString } from '@matterbridge/utils/validate';
6
7
  import { fireAndForget, withTimeout } from '@matterbridge/utils/wait';
7
8
  import { AnsiLogger, CYAN, debugStringify, nf } from 'node-ansi-logger';
8
9
  import { WebSocket, WebSocketServer } from 'ws';
9
- if (hasParameter('loader'))
10
- console.log('\u001B[32m[' + new Date().toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit', fractionalSecondDigits: 3 }) + '] BackendWsServer loaded.\u001B[40;0m');
10
+ logModuleLoaded('BackendWsServer');
11
11
  export class BackendWsServer {
12
12
  debug;
13
13
  verbose;
@@ -31,7 +31,6 @@ export class BackendWsServer {
31
31
  this.server.on('broadcast_message', this.broadcastMsgHandler.bind(this));
32
32
  }
33
33
  destroy() {
34
- this.server.off('broadcast_message', this.broadcastMsgHandler.bind(this));
35
34
  this.server.close();
36
35
  }
37
36
  broadcastMsgHandler(msg) {
@@ -44,6 +43,7 @@ export class BackendWsServer {
44
43
  this.log.logLevel = msg.params.logLevel;
45
44
  this.server.respond({ ...msg, result: { logLevel: this.log.logLevel } });
46
45
  break;
46
+ default:
47
47
  }
48
48
  }
49
49
  }
@@ -1,5 +1,5 @@
1
1
  import { ActivatedCarbonFilterMonitoringServer } from '@matter/node/behaviors/activated-carbon-filter-monitoring';
2
- import { type ActivatedCarbonFilterMonitoring } from '@matter/types/clusters/activated-carbon-filter-monitoring';
2
+ import type { ActivatedCarbonFilterMonitoring } from '@matter/types/clusters/activated-carbon-filter-monitoring';
3
3
  declare const MatterbridgeActivatedCarbonFilterMonitoringServer_base: import("@matter/node").ClusterBehavior.Type<typeof ActivatedCarbonFilterMonitoringServer, import("@matter/types").ClusterType.WithSupportedFeatures<ActivatedCarbonFilterMonitoring, {
4
4
  warning: false;
5
5
  condition: true;
@@ -1,11 +1,11 @@
1
- import { type Endpoint } from '@matter/main/node';
1
+ import type { Endpoint } from '@matter/main/node';
2
2
  import { BindingBehavior, BindingServer } from '@matter/node/behaviors/binding';
3
- import { type ClusterId } from '@matter/types';
4
- import { type Binding } from '@matter/types/clusters/binding';
3
+ import type { ClusterId } from '@matter/types';
4
+ import type { Binding } from '@matter/types/clusters/binding';
5
5
  export declare class MatterbridgeBindingServer extends BindingServer {
6
6
  protected internal: MatterbridgeBindingServer.Internal;
7
7
  state: MatterbridgeBindingServer.State;
8
- initialize(): Promise<void>;
8
+ initialize(): void;
9
9
  [Symbol.asyncDispose](): Promise<void>;
10
10
  getEndpoint(clusterId: ClusterId): Endpoint | undefined;
11
11
  }
@@ -3,7 +3,7 @@ import { DescriptorServer } from '@matter/node/behaviors/descriptor';
3
3
  import { debugStringify, nt } from 'node-ansi-logger';
4
4
  import { MatterbridgeServer } from './matterbridgeServer.js';
5
5
  export class MatterbridgeBindingServer extends BindingServer {
6
- async initialize() {
6
+ initialize() {
7
7
  super.initialize();
8
8
  const device = this.endpoint.stateOf(MatterbridgeServer);
9
9
  device.log.info(`Initializing MatterbridgeBindingServer (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber}) with clientList: ${this.state.clientList.join(', ')}`);
@@ -31,7 +31,7 @@ export class MatterbridgeBindingServer extends BindingServer {
31
31
  return;
32
32
  await resolution.node.set({ network: { autoSubscribe: true } });
33
33
  });
34
- this.reactTo(this.events.removed, async (resolution) => {
34
+ this.reactTo(this.events.removed, (resolution) => {
35
35
  device.log.notice(`MatterbridgeBindingServer (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber}) binding removed: kind ${resolution.kind} entry ${debugStringify(resolution.entry)}${nt}`);
36
36
  this.internal.boundEndpoints.delete(resolution.entry);
37
37
  });
@@ -1,10 +1,11 @@
1
1
  import { BooleanStateConfigurationServer } from '@matter/node/behaviors/boolean-state-configuration';
2
2
  import { BooleanStateConfiguration } from '@matter/types/clusters/boolean-state-configuration';
3
+ import { debugStringify } from 'node-ansi-logger';
3
4
  import { MatterbridgeServer } from './matterbridgeServer.js';
4
5
  export class MatterbridgeBooleanStateConfigurationServer extends BooleanStateConfigurationServer.with(BooleanStateConfiguration.Feature.Visual, BooleanStateConfiguration.Feature.Audible, BooleanStateConfiguration.Feature.SensitivityLevel) {
5
6
  async enableDisableAlarm(request) {
6
7
  const device = this.endpoint.stateOf(MatterbridgeServer);
7
- device.log.info(`Enabling/disabling alarm ${request.alarmsToEnableDisable} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
8
+ device.log.info(`Enabling/disabling alarm ${debugStringify(request.alarmsToEnableDisable)} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
8
9
  await device.commandHandler.executeHandler('BooleanStateConfiguration.enableDisableAlarm', {
9
10
  command: 'enableDisableAlarm',
10
11
  request,
@@ -30,7 +30,7 @@ declare const MatterbridgeDoorLockServer_base: import("@matter/node").ClusterBeh
30
30
  aliroBleuwb: false;
31
31
  }>, "doorLockAlarm" | "lockOperation" | "lockOperationError">, never>, import("@matter/types").ClusterType.Concrete, typeof import("@matter/node/behaviors/door-lock").DoorLockBaseServer.Internal, "doorLock">;
32
32
  export declare class MatterbridgeDoorLockServer extends MatterbridgeDoorLockServer_base {
33
- initialize(): Promise<void>;
33
+ initialize(): void;
34
34
  lockDoor(request: DoorLock.LockDoorRequest): Promise<void>;
35
35
  unlockDoor(request: DoorLock.UnlockDoorRequest): Promise<void>;
36
36
  unlockWithTimeout(request: DoorLock.UnlockWithTimeoutRequest): Promise<void>;
@@ -6,10 +6,10 @@ export class MatterbridgeDoorLockServer extends DoorLockServer.with(DoorLock.Fea
6
6
  events: { doorLockAlarm: true, lockOperation: true, lockOperationError: true },
7
7
  commands: { lockDoor: true, unlockDoor: true, unlockWithTimeout: true },
8
8
  }) {
9
- async initialize() {
9
+ initialize() {
10
10
  const device = this.endpoint.stateOf(MatterbridgeServer);
11
11
  device.log.info(`Initializing MatterbridgeDoorLockServer (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
12
- await super.initialize();
12
+ super.initialize();
13
13
  }
14
14
  async lockDoor(request) {
15
15
  const device = this.endpoint.stateOf(MatterbridgeServer);
@@ -1,5 +1,5 @@
1
1
  import { HepaFilterMonitoringServer } from '@matter/node/behaviors/hepa-filter-monitoring';
2
- import { type HepaFilterMonitoring } from '@matter/types/clusters/hepa-filter-monitoring';
2
+ import type { HepaFilterMonitoring } from '@matter/types/clusters/hepa-filter-monitoring';
3
3
  declare const MatterbridgeHepaFilterMonitoringServer_base: import("@matter/node").ClusterBehavior.Type<typeof HepaFilterMonitoringServer, import("@matter/types").ClusterType.WithSupportedFeatures<HepaFilterMonitoring, {
4
4
  warning: false;
5
5
  condition: true;
@@ -1,5 +1,5 @@
1
1
  import { IdentifyServer } from '@matter/node/behaviors/identify';
2
- import { type Identify } from '@matter/types/clusters/identify';
2
+ import type { Identify } from '@matter/types/clusters/identify';
3
3
  export declare class MatterbridgeIdentifyServer extends IdentifyServer {
4
4
  identify(request: Identify.IdentifyRequest): Promise<void>;
5
5
  triggerEffect(request: Identify.TriggerEffectRequest): Promise<void>;
@@ -1,5 +1,5 @@
1
1
  import { LevelControlServer } from '@matter/node/behaviors/level-control';
2
- import { type LevelControl } from '@matter/types/clusters/level-control';
2
+ import type { LevelControl } from '@matter/types/clusters/level-control';
3
3
  export declare class MatterbridgeLevelControlServer extends LevelControlServer {
4
4
  moveToLevel(request: LevelControl.MoveToLevelRequest): Promise<void>;
5
5
  moveToLevelWithOnOff(request: LevelControl.MoveToLevelRequest): Promise<void>;
@@ -1,6 +1,6 @@
1
1
  import { Behavior } from '@matter/node';
2
- import { type AnsiLogger } from 'node-ansi-logger';
3
- import { type CommandHandler } from '../matterbridgeEndpointCommandHandler.js';
2
+ import type { AnsiLogger } from 'node-ansi-logger';
3
+ import type { CommandHandler } from '../matterbridgeEndpointCommandHandler.js';
4
4
  export declare class MatterbridgeServer extends Behavior {
5
5
  static readonly id = "matterbridge";
6
6
  state: MatterbridgeServer.State;
@@ -1,5 +1,5 @@
1
1
  import { ModeSelectServer } from '@matter/node/behaviors/mode-select';
2
- import { type ModeSelect } from '@matter/types/clusters/mode-select';
2
+ import type { ModeSelect } from '@matter/types/clusters/mode-select';
3
3
  export declare class MatterbridgeModeSelectServer extends ModeSelectServer {
4
4
  changeToMode(request: ModeSelect.ChangeToModeRequest): Promise<void>;
5
5
  }
@@ -1,4 +1,4 @@
1
- import { type MaybePromise } from '@matter/general';
1
+ import type { MaybePromise } from '@matter/general';
2
2
  import { OperationalStateServer } from '@matter/node/behaviors/operational-state';
3
3
  import { OperationalState } from '@matter/types/clusters/operational-state';
4
4
  export declare class MatterbridgeOperationalStateServer extends OperationalStateServer {
@@ -1,5 +1,5 @@
1
1
  import { ServiceAreaServer } from '@matter/node/behaviors/service-area';
2
- import { type ServiceArea } from '@matter/types/clusters/service-area';
2
+ import type { ServiceArea } from '@matter/types/clusters/service-area';
3
3
  export declare class MatterbridgeServiceAreaServer extends ServiceAreaServer {
4
4
  selectAreas(request: ServiceArea.SelectAreasRequest): Promise<ServiceArea.SelectAreasResponse>;
5
5
  }
@@ -10,13 +10,13 @@ export declare class MatterbridgeWindowCoveringServer extends MatterbridgeWindow
10
10
  protected internal: WindowCoveringBaseServer.Internal;
11
11
  lookupMovementStatus: string[];
12
12
  private getMovementStatusLabel;
13
- initialize(): Promise<void>;
13
+ initialize(): void;
14
14
  upOrOpen(): Promise<void>;
15
15
  downOrClose(): Promise<void>;
16
16
  stopMotion(): Promise<void>;
17
17
  goToLiftPercentage(request: WindowCovering.GoToLiftPercentageRequest): Promise<void>;
18
18
  goToTiltPercentage(request: WindowCovering.GoToTiltPercentageRequest): Promise<void>;
19
- handleMovement(): Promise<void>;
19
+ handleMovement(): void;
20
20
  }
21
21
  declare const MatterbridgeLiftWindowCoveringServer_base: import("@matter/node").ClusterBehavior.Type<typeof MatterbridgeWindowCoveringServer, import("@matter/types").ClusterType.WithSupportedFeatures<import("@matter/types").ClusterType.WithSupportedFeatures<WindowCovering, {
22
22
  lift: true;
@@ -6,11 +6,11 @@ export class MatterbridgeWindowCoveringServer extends WindowCoveringServer.with(
6
6
  getMovementStatusLabel(status) {
7
7
  return this.lookupMovementStatus[status ?? 3];
8
8
  }
9
- async initialize() {
9
+ initialize() {
10
10
  const device = this.endpoint.stateOf(MatterbridgeServer);
11
11
  device.log.info(`Initializing MatterbridgeWindowCoveringServer (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
12
12
  this.internal.disableOperationalModeHandling = true;
13
- await super.initialize();
13
+ super.initialize();
14
14
  }
15
15
  async upOrOpen() {
16
16
  const device = this.endpoint.stateOf(MatterbridgeServer);
@@ -87,7 +87,7 @@ export class MatterbridgeWindowCoveringServer extends WindowCoveringServer.with(
87
87
  await super.goToTiltPercentage(request);
88
88
  device.log.debug(`MatterbridgeWindowCoveringServer: goToTiltPercentage result target ${this.state.targetPositionTiltPercent100ths} current ${this.state.currentPositionTiltPercent100ths} status global ${this.getMovementStatusLabel(this.state.operationalStatus.global)} lift ${this.getMovementStatusLabel(this.state.operationalStatus.lift)} tilt ${this.getMovementStatusLabel(this.state.operationalStatus.tilt)}`);
89
89
  }
90
- async handleMovement() {
90
+ handleMovement() {
91
91
  }
92
92
  }
93
93
  export class MatterbridgeLiftWindowCoveringServer extends MatterbridgeWindowCoveringServer.with(WindowCovering.Feature.Lift, WindowCovering.Feature.PositionAwareLift) {
package/dist/cli.js CHANGED
@@ -1,18 +1,18 @@
1
- if (process.argv.includes('--loader'))
2
- console.log('\u001B[32m[' + new Date().toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit', fractionalSecondDigits: 3 }) + '] Cli loaded.\u001B[40;0m');
3
1
  import { ThreadsManager } from '@matterbridge/thread/manager';
4
2
  import { hasAnyParameter, hasParameter } from '@matterbridge/utils/cli';
5
3
  import { inspectError } from '@matterbridge/utils/error';
6
4
  import { formatBytes, formatUptime } from '@matterbridge/utils/format';
7
5
  import { Inspector } from '@matterbridge/utils/inspector';
6
+ import { logModuleLoaded } from '@matterbridge/utils/loader';
8
7
  import { Tracker } from '@matterbridge/utils/tracker';
9
8
  import { AnsiLogger } from 'node-ansi-logger';
10
9
  import { cliEmitter } from './cliEmitter.js';
10
+ logModuleLoaded('Cli');
11
11
  export let instance;
12
12
  export const tracker = new Tracker('Cli', false, false);
13
13
  export const inspector = new Inspector('Cli', false, false);
14
14
  const manager = new ThreadsManager();
15
- const colorEnabled = Boolean(!process.env.NO_COLOR && process.env.TERM !== 'dumb' && process.env.FORCE_COLOR !== '0' && !hasParameter('no-ansi'));
15
+ const colorEnabled = !process.env.NO_COLOR && process.env.TERM !== 'dumb' && process.env.FORCE_COLOR !== '0' && !hasParameter('no-ansi');
16
16
  if (!colorEnabled)
17
17
  process.env.NO_COLOR = '1';
18
18
  const log = new AnsiLogger({ logName: 'Cli', logTimestampFormat: 4, logLevel: hasParameter('debug') ? "debug" : "info" });
@@ -50,14 +50,14 @@ function registerHandlers() {
50
50
  log.debug('Registering event handlers...');
51
51
  if (!instance)
52
52
  return;
53
- instance.on('shutdown', async () => shutdown());
54
- instance.on('restart', async () => restart());
55
- instance.on('update', async () => update());
53
+ instance.on('shutdown', () => void shutdown().catch((error) => inspectError(log, 'Failed to shutdown', error)));
54
+ instance.on('restart', () => void restart().catch((error) => inspectError(log, 'Failed to restart', error)));
55
+ instance.on('update', () => void update().catch((error) => inspectError(log, 'Failed to update', error)));
56
56
  instance.on('startmemorycheck', () => start());
57
57
  instance.on('stopmemorycheck', () => stop());
58
- instance.on('startinspector', async () => startInspector());
59
- instance.on('stopinspector', async () => stopInspector());
60
- instance.on('takeheapsnapshot', async () => takeHeapSnapshot());
58
+ instance.on('startinspector', () => void startInspector().catch((error) => inspectError(log, 'Failed to start inspector', error)));
59
+ instance.on('stopinspector', () => void stopInspector().catch((error) => inspectError(log, 'Failed to stop inspector', error)));
60
+ instance.on('takeheapsnapshot', () => void takeHeapSnapshot().catch((error) => inspectError(log, 'Failed to take heap snapshot', error)));
61
61
  instance.on('triggergarbagecollection', () => triggerGarbageCollection());
62
62
  log.debug('Registered event handlers');
63
63
  }
@@ -1,6 +1,6 @@
1
- if (process.argv.includes('--loader'))
2
- console.log('\u001B[32m[' + new Date().toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit', fractionalSecondDigits: 3 }) + '] Cli emitter loaded.\u001B[40;0m');
3
1
  import { EventEmitter } from 'node:events';
2
+ import { logModuleLoaded } from '@matterbridge/utils/loader';
3
+ logModuleLoaded('CliEmitter');
4
4
  export const cliEmitter = new EventEmitter();
5
5
  export let lastOsCpuUsage = 0;
6
6
  export let lastProcessCpuUsage = 0;
@@ -1,9 +1,9 @@
1
- if (process.argv.includes('--loader'))
2
- console.log('\u001B[32m[' + new Date().toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit', fractionalSecondDigits: 3 }) + '] Cli history loaded.\u001B[40;0m');
3
1
  import { writeFileSync } from 'node:fs';
4
2
  import os from 'node:os';
5
3
  import path from 'node:path';
4
+ import { logModuleLoaded } from '@matterbridge/utils/loader';
6
5
  import { Tracker } from '@matterbridge/utils/tracker';
6
+ logModuleLoaded('CliHistory');
7
7
  export function generateHistoryPage(options = {}) {
8
8
  const pageTitle = options.pageTitle ?? 'Matterbridge CPU & Memory History';
9
9
  const hostname = options.hostname ?? os.hostname();
@@ -1 +1 @@
1
- export {};
1
+ export declare const noop: () => void;
@@ -1 +1 @@
1
- export {};
1
+ export const noop = () => undefined;
@@ -21,7 +21,7 @@ export declare class DeviceManager {
21
21
  private toBaseDevice;
22
22
  array(): MatterbridgeEndpoint[];
23
23
  baseArray(pluginName?: string): BaseDevice[];
24
- [Symbol.iterator](): MapIterator<MatterbridgeEndpoint>;
24
+ [Symbol.iterator](): IterableIterator<MatterbridgeEndpoint>;
25
25
  forEach(callback: (device: MatterbridgeEndpoint) => Promise<void>): Promise<void>;
26
26
  set logLevel(logLevel: LogLevel);
27
27
  }
@@ -1,9 +1,9 @@
1
- if (process.argv.includes('--loader'))
2
- console.log('\u001B[32m[' + new Date().toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit', fractionalSecondDigits: 3 }) + '] Device Manager loaded.\u001B[40;0m');
3
1
  import { BroadcastServer } from '@matterbridge/thread/server';
4
2
  import { dev } from '@matterbridge/types';
5
3
  import { hasParameter } from '@matterbridge/utils/cli';
4
+ import { logModuleLoaded } from '@matterbridge/utils/loader';
6
5
  import { AnsiLogger, BLUE, CYAN, db, debugStringify, er } from 'node-ansi-logger';
6
+ logModuleLoaded('Device Manager');
7
7
  export function toBaseDevice(device) {
8
8
  return {
9
9
  mode: device.mode,
@@ -43,10 +43,9 @@ export class DeviceManager {
43
43
  this.log.debug('Matterbridge device manager started');
44
44
  }
45
45
  destroy() {
46
- this.server.off('broadcast_message', this.msgHandler.bind(this));
47
46
  this.server.close();
48
47
  }
49
- async msgHandler(msg) {
48
+ msgHandler(msg) {
50
49
  if (this.server.isWorkerRequest(msg)) {
51
50
  if (this.verbose)
52
51
  this.log.debug(`Received request message ${CYAN}${msg.type}${db} from ${CYAN}${msg.src}${db}: ${debugStringify(msg)}${db}`);
@@ -3,6 +3,7 @@ import { ElectricalPowerMeasurementServer } from '@matter/node/behaviors/electri
3
3
  import { DeviceEnergyManagement } from '@matter/types/clusters/device-energy-management';
4
4
  import { ElectricalPowerMeasurement } from '@matter/types/clusters/electrical-power-measurement';
5
5
  import { PowerSource } from '@matter/types/clusters/power-source';
6
+ import { fireAndForget } from '@matterbridge/utils/wait';
6
7
  import { batteryStorage, deviceEnergyManagement, electricalSensor, powerSource } from '../matterbridgeDeviceTypes.js';
7
8
  import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
8
9
  import { getDefaultElectricalPowerMeasurementClusterServer, getSemtag } from '../matterbridgeEndpointHelpers.js';
@@ -21,7 +22,7 @@ export class BatteryStorage extends MatterbridgeEndpoint {
21
22
  .createDefaultDeviceEnergyManagementClusterServer(DeviceEnergyManagement.EsaType.BatteryStorage, true, DeviceEnergyManagement.EsaState.Online, absMinPower, absMaxPower)
22
23
  .createDefaultDeviceEnergyManagementModeClusterServer()
23
24
  .addRequiredClusterServers();
24
- void this.addFixedLabel('composed', 'Battery Storage').catch(() => { });
25
+ fireAndForget(this.addFixedLabel('composed', 'Battery Storage'), this.log, 'BatteryStorage addFixedLabel');
25
26
  const battery = this.addChildDeviceType('Battery', [powerSource, electricalSensor], {
26
27
  tagList: [getSemtag(PowerSourceTag.Battery)],
27
28
  })
@@ -1,4 +1,4 @@
1
- import { type Semtag } from '@matter/types';
1
+ import type { Semtag } from '@matter/types';
2
2
  import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
3
3
  export declare class Cooktop extends MatterbridgeEndpoint {
4
4
  constructor(name: string, serial: string);
@@ -1,3 +1,4 @@
1
+ import { fireAndForget } from '@matterbridge/utils/wait';
1
2
  import { cookSurface, cooktop, powerSource } from '../matterbridgeDeviceTypes.js';
2
3
  import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
3
4
  import { createLevelTemperatureControlClusterServer } from './temperatureControl.js';
@@ -8,7 +9,7 @@ export class Cooktop extends MatterbridgeEndpoint {
8
9
  this.createDefaultBasicInformationClusterServer(name, serial, 0xfff1, 'Matterbridge', 0x8000, 'Cooktop');
9
10
  this.createDefaultPowerSourceWiredClusterServer();
10
11
  this.createOffOnlyOnOffClusterServer(true);
11
- void this.addFixedLabel('composed', 'Cooktop').catch(() => { });
12
+ fireAndForget(this.addFixedLabel('composed', 'Cooktop'), this.log, 'Error adding composed label to cooktop');
12
13
  }
13
14
  addSurface(name, tagList, selectedTemperatureLevel = 2, supportedTemperatureLevels = ['Level 1', 'Level 2', 'Level 3', 'Level 4', 'Level 5']) {
14
15
  const surface = this.addChildDeviceType(name, cookSurface, { tagList });
@@ -1,7 +1,7 @@
1
1
  import { DishwasherModeServer } from '@matter/node/behaviors/dishwasher-mode';
2
2
  import { DishwasherMode } from '@matter/types/clusters/dishwasher-mode';
3
3
  import { ModeBase } from '@matter/types/clusters/mode-base';
4
- import { type OperationalState } from '@matter/types/clusters/operational-state';
4
+ import type { OperationalState } from '@matter/types/clusters/operational-state';
5
5
  import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
6
6
  export declare class Dishwasher extends MatterbridgeEndpoint {
7
7
  constructor(name: string, serial: string, currentMode?: number, supportedModes?: DishwasherMode.ModeOption[], selectedTemperatureLevel?: number, supportedTemperatureLevels?: string[], temperatureSetpoint?: number, minTemperature?: number, maxTemperature?: number, step?: number, operationalState?: OperationalState.OperationalStateEnum);