matterbridge 1.2.8 → 1.2.9

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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,19 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [1.2.9] - 2024-04-19
6
+
7
+ ### Added
8
+
9
+ - [Matterbridge]: Added call to set reachability at start.
10
+ - [frontend]: Added filter for log level and search criteria in the Logs page.
11
+ - [frontend]: Added colors to the logs in the Home page and in the Logs page.
12
+ - [frontend]: Frontend updated to 0.8.7.
13
+
14
+ ### Fixed
15
+
16
+ - [logs]: Fixed wss for some browser that didn't connect to wss.
17
+
5
18
  ## [1.2.8] - 2024-04-16
6
19
 
7
20
  ### Changed
@@ -10,7 +23,7 @@ All notable changes to this project will be documented in this file.
10
23
  ### Added
11
24
 
12
25
  - [frontend]: Added logs in the Home page and in the Log page.
13
- - [frontend]: Frontend got updated to 0.8.5.
26
+ - [frontend]: Frontend got updated to 0.8.6.
14
27
  - [frontend]: Added log for update and plugin install.
15
28
  - [extension]: Started implementation of zigbee2MQTT internal extension.
16
29
 
package/README.md CHANGED
@@ -104,6 +104,9 @@ Home page:
104
104
  Devices page:
105
105
  ![See the screenshot here](https://github.com/Luligu/matterbridge/blob/main/Screenshot%20devices.jpg)
106
106
 
107
+ Logs page:
108
+ ![See the screenshot here](https://github.com/Luligu/matterbridge/blob/main/Screenshot%20logs.jpg)
109
+
107
110
  ## Plugins
108
111
 
109
112
  ### Accessory platform example
@@ -40,22 +40,23 @@ interface SystemInformation {
40
40
  freeMemory: string;
41
41
  systemUptime: string;
42
42
  }
43
+ interface MatterbridgeInformation {
44
+ homeDirectory: string;
45
+ rootDirectory: string;
46
+ matterbridgeDirectory: string;
47
+ matterbridgePluginDirectory: string;
48
+ globalModulesDirectory: string;
49
+ matterbridgeVersion: string;
50
+ matterbridgeLatestVersion: string;
51
+ bridgeMode: string;
52
+ debugEnabled: boolean;
53
+ }
43
54
  /**
44
55
  * Represents the Matterbridge application.
45
56
  */
46
57
  export declare class Matterbridge extends EventEmitter {
47
58
  systemInformation: SystemInformation;
48
- matterbridgeInformation: {
49
- homeDirectory: string;
50
- rootDirectory: string;
51
- matterbridgeDirectory: string;
52
- matterbridgePluginDirectory: string;
53
- globalModulesDirectory: string;
54
- matterbridgeVersion: string;
55
- matterbridgeLatestVersion: string;
56
- bridgeMode: string;
57
- debugEnabled: boolean;
58
- };
59
+ matterbridgeInformation: MatterbridgeInformation;
59
60
  homeDirectory: string;
60
61
  rootDirectory: string;
61
62
  matterbridgeDirectory: string;
@@ -158,13 +159,6 @@ export declare class Matterbridge extends EventEmitter {
158
159
  * @returns A promise that resolves when the cleanup is completed.
159
160
  */
160
161
  private cleanup;
161
- /**
162
- * Sets the reachable attribute of a device.
163
- *
164
- * @param device - The device for which to set the reachable attribute.
165
- * @param reachable - The value to set for the reachable attribute.
166
- */
167
- private setReachableAttribute;
168
162
  /**
169
163
  * Adds a device to the Matterbridge.
170
164
  * @param pluginName - The name of the plugin.
@@ -327,6 +321,26 @@ export declare class Matterbridge extends EventEmitter {
327
321
  * @returns The found plugin, or undefined if not found.
328
322
  */
329
323
  private findPlugin;
324
+ /**
325
+ * Sets the reachability of a commissioning server and trigger.
326
+ *
327
+ * @param {CommissioningServer} commissioningServer - The commissioning server to set the reachability for.
328
+ * @param {boolean} reachable - The new reachability status.
329
+ */
330
+ private setCommissioningServerReachability;
331
+ /**
332
+ * Sets the reachability of the specified matter aggregator and its bridged devices and trigger.
333
+ * @param {Aggregator} matterAggregator - The matter aggregator to set the reachability for.
334
+ * @param {boolean} reachable - A boolean indicating the reachability status to set.
335
+ */
336
+ private setAggregatorReachability;
337
+ /**
338
+ * Sets the reachability of a device and trigger.
339
+ *
340
+ * @param {MatterbridgeDevice} device - The device to set the reachability for.
341
+ * @param {boolean} reachable - The new reachability status of the device.
342
+ */
343
+ private setDeviceReachability;
330
344
  /**
331
345
  * Creates a matter commissioning server.
332
346
  *
@@ -384,6 +398,13 @@ export declare class Matterbridge extends EventEmitter {
384
398
  * @returns A promise that resolves when the child process exits successfully, or rejects if there is an error.
385
399
  */
386
400
  private spawnCommand;
401
+ /**
402
+ * Sends a WebSocket message to all connected clients.
403
+ *
404
+ * @param {string} type - The type of the message: Matterbridge, Plugin, Device, ...
405
+ * @param {string} subType - The subtype of the message: debug info warn error ....
406
+ * @param {string} message - The content of the message.
407
+ */
387
408
  private wssSendMessage;
388
409
  /**
389
410
  * Initializes the frontend of Matterbridge.
@@ -1 +1 @@
1
- {"version":3,"file":"matterbridge.d.ts","sourceRoot":"","sources":["../src/matterbridge.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"matterbridge.d.ts","sourceRoot":"","sources":["../src/matterbridge.ts"],"names":[],"mappings":"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"}
@@ -26,6 +26,7 @@ import { AnsiLogger, BRIGHT, RESET, UNDERLINE, UNDERLINEOFF, YELLOW, db, debugSt
26
26
  import { fileURLToPath, pathToFileURL } from 'url';
27
27
  import { promises as fs } from 'fs';
28
28
  import { exec, spawn } from 'child_process';
29
+ import https from 'https';
29
30
  import EventEmitter from 'events';
30
31
  import express from 'express';
31
32
  import os from 'os';
@@ -128,6 +129,8 @@ export class Matterbridge extends EventEmitter {
128
129
  * @returns A Promise that resolves when the initialization is complete.
129
130
  */
130
131
  async initializeAsExtension(dataPath, debugEnabled) {
132
+ // Set the bridge mode
133
+ this.bridgeMode = 'bridge';
131
134
  // Set the first port to use
132
135
  this.port = 5560;
133
136
  // Set Matterbridge logger
@@ -140,6 +143,19 @@ export class Matterbridge extends EventEmitter {
140
143
  this.nodeStorage = new NodeStorageManager({ dir: path.join(this.matterbridgeDirectory, 'node_storage'), logging: false });
141
144
  this.log.debug('Creating node storage context for matterbridge: matterbridge');
142
145
  this.nodeContext = await this.nodeStorage.createStorage('matterbridge');
146
+ const plugin = {
147
+ path: '',
148
+ type: 'DynamicPlatform',
149
+ name: 'MatterbridgeExtension',
150
+ version: '1.0.0',
151
+ description: 'Matterbridge extension',
152
+ author: 'https://github.com/Luligu',
153
+ enabled: false,
154
+ registeredDevices: 0,
155
+ addedDevices: 0,
156
+ };
157
+ this.registeredPlugins.push(plugin);
158
+ await this.nodeContext?.set('plugins', this.getBaseRegisteredPlugins());
143
159
  // Log system info and create .matterbridge directory
144
160
  await this.logNodeAndSystemInfo();
145
161
  this.matterbridgeDirectory = dataPath;
@@ -154,7 +170,7 @@ export class Matterbridge extends EventEmitter {
154
170
  await this.matterbridgeContext.set('softwareVersion', 1);
155
171
  await this.matterbridgeContext.set('softwareVersionString', this.matterbridgeVersion);
156
172
  await this.matterbridgeContext.set('hardwareVersion', 0);
157
- await this.matterbridgeContext.set('hardwareVersionString', '0.0.1');
173
+ await this.matterbridgeContext.set('hardwareVersionString', '1.0.0'); // Update with the extension version
158
174
  this.createMatterServer(this.storageManager);
159
175
  this.log.debug(`Creating commissioning server for ${plg}Matterbridge${db}`);
160
176
  this.commissioningServer = await this.createCommisioningServer(this.matterbridgeContext, 'Matterbridge');
@@ -166,10 +182,17 @@ export class Matterbridge extends EventEmitter {
166
182
  await this.matterServer?.addCommissioningServer(this.commissioningServer, { uniqueStorageKey: 'Matterbridge' });
167
183
  this.log.debug(`Setting reachability to true for ${plg}Matterbridge${db}`);
168
184
  this.commissioningServer.setReachability(true);
169
- this.log.debug('Starting matter server...');
170
185
  await this.startMatterServer();
171
186
  this.log.info('Matter server started');
172
187
  await this.showCommissioningQRCode(this.commissioningServer, this.matterbridgeContext, this.nodeContext, 'Matterbridge');
188
+ // Set reachability to true and trigger event after 60 seconds
189
+ setTimeout(() => {
190
+ this.log.info(`*Setting reachability to true for ${plg}Matterbridge${db}`);
191
+ if (this.commissioningServer)
192
+ this.setCommissioningServerReachability(this.commissioningServer, true);
193
+ if (this.matterAggregator)
194
+ this.setAggregatorReachability(this.matterAggregator, true);
195
+ }, 60 * 1000);
173
196
  }
174
197
  /**
175
198
  * Close the Matterbridge instance as extension for zigbee2mqtt.
@@ -582,6 +605,7 @@ export class Matterbridge extends EventEmitter {
582
605
  this.log.info(message);
583
606
  process.removeAllListeners('SIGINT');
584
607
  process.removeAllListeners('SIGTERM');
608
+ this.log.debug('All listeners removed');
585
609
  // Calling the shutdown functions with a reason
586
610
  for (const plugin of this.registeredPlugins) {
587
611
  if (!plugin.enabled)
@@ -637,11 +661,13 @@ export class Matterbridge extends EventEmitter {
637
661
  if (this.expressServer) {
638
662
  this.expressServer.close();
639
663
  this.expressServer = undefined;
664
+ this.log.debug('Express server closed successfully');
640
665
  }
641
666
  // Remove listeners
642
667
  if (this.expressApp) {
643
668
  this.expressApp.removeAllListeners();
644
669
  this.expressApp = undefined;
670
+ this.log.debug('Frontend closed successfully');
645
671
  }
646
672
  // Close the WebSocket server
647
673
  if (this.webSocketServer) {
@@ -715,20 +741,6 @@ export class Matterbridge extends EventEmitter {
715
741
  //cleanupTimeout1.unref();
716
742
  }
717
743
  }
718
- /**
719
- * Sets the reachable attribute of a device.
720
- *
721
- * @param device - The device for which to set the reachable attribute.
722
- * @param reachable - The value to set for the reachable attribute.
723
- */
724
- setReachableAttribute(device, reachable) {
725
- const basicInformationCluster = device.getClusterServer(BasicInformationCluster);
726
- if (!basicInformationCluster) {
727
- this.log.error('setReachableAttribute BasicInformationCluster needs to be set!');
728
- return;
729
- }
730
- basicInformationCluster.setReachableAttribute(reachable);
731
- }
732
744
  /**
733
745
  * Adds a device to the Matterbridge.
734
746
  * @param pluginName - The name of the plugin.
@@ -824,7 +836,7 @@ export class Matterbridge extends EventEmitter {
824
836
  return;
825
837
  }
826
838
  if (this.bridgeMode === 'childbridge' && !plugin.connected) {
827
- this.log.warn(`Removing bridged device ${dev}${device.deviceName}${wr} (${dev}${device.name}${wr}) plugin ${plg}${pluginName}${wr} not connected`);
839
+ this.log.info(`Removing bridged device ${dev}${device.deviceName}${wr} (${dev}${device.name}${wr}) plugin ${plg}${pluginName}${wr} not connected`);
828
840
  return;
829
841
  }
830
842
  // Remove the device from matterbridge aggregator in bridge mode
@@ -1505,20 +1517,17 @@ export class Matterbridge extends EventEmitter {
1505
1517
  await this.matterServer?.addCommissioningServer(this.commissioningServer, { uniqueStorageKey: 'Matterbridge' });
1506
1518
  this.log.debug(`Setting reachability to true for ${plg}Matterbridge${db}`);
1507
1519
  this.commissioningServer.setReachability(true);
1508
- this.log.debug('Starting matter server...');
1509
1520
  await this.startMatterServer();
1510
1521
  this.log.info('Matter server started');
1511
1522
  await this.showCommissioningQRCode(this.commissioningServer, this.matterbridgeContext, this.nodeContext, 'Matterbridge');
1512
1523
  //if (hasParameter('advertise')) await this.commissioningServer.advertise();
1513
- /*
1514
- setInterval(() => {
1515
- this.matterAggregator?.getBridgedDevices().forEach((device) => {
1516
- this.log.info(`Bridged device: ${dev}${device.name}${nf}`);
1517
- device.getClusterServer(BridgedDeviceBasicInformationCluster)?.setReachableAttribute(true);
1518
- device.getClusterServer(BridgedDeviceBasicInformationCluster)?.triggerReachableChangedEvent({ reachableNewValue: true });
1519
- });
1520
- }, 30 * 1000);
1521
- */
1524
+ setTimeout(() => {
1525
+ this.log.info(`*Setting reachability to true for ${plg}Matterbridge${db}`);
1526
+ if (this.commissioningServer)
1527
+ this.setCommissioningServerReachability(this.commissioningServer, true);
1528
+ if (this.matterAggregator)
1529
+ this.setAggregatorReachability(this.matterAggregator, true);
1530
+ }, 60 * 1000);
1522
1531
  }, 1000);
1523
1532
  }
1524
1533
  if (this.bridgeMode === 'childbridge') {
@@ -1555,6 +1564,8 @@ export class Matterbridge extends EventEmitter {
1555
1564
  plugin.commissioningServer = await this.createCommisioningServer(plugin.storageContext, plugin.name);
1556
1565
  this.log.debug(`Adding device ${dev}${registeredDevice.device.name}${db} to commissioning server for plugin ${plg}${plugin.name}${db}`);
1557
1566
  plugin.commissioningServer.addDevice(registeredDevice.device);
1567
+ if (!plugin.device)
1568
+ plugin.device = registeredDevice.device;
1558
1569
  }
1559
1570
  this.log.debug(`Adding commissioning server to matter server for plugin ${plg}${plugin.name}${db}`);
1560
1571
  await this.matterServer?.addCommissioningServer(plugin.commissioningServer, { uniqueStorageKey: plugin.name });
@@ -1595,21 +1606,6 @@ export class Matterbridge extends EventEmitter {
1595
1606
  return;
1596
1607
  clearInterval(startMatterInterval);
1597
1608
  this.log.info('Starting matter server...');
1598
- // Setting reachability to true
1599
- this.registeredPlugins.forEach((plugin) => {
1600
- if (!plugin.enabled)
1601
- return;
1602
- this.log.debug(`Setting reachability to true for ${plg}${plugin.name}${db}`);
1603
- plugin.commissioningServer?.setReachability(true);
1604
- this.registeredDevices.forEach((registeredDevice) => {
1605
- if (registeredDevice.plugin === plugin.name) {
1606
- if (plugin.type === 'AccessoryPlatform')
1607
- this.setReachableAttribute(registeredDevice.device, true);
1608
- if (plugin.type === 'DynamicPlatform')
1609
- registeredDevice.device.setBridgedDeviceReachability(true);
1610
- }
1611
- });
1612
- });
1613
1609
  await this.startMatterServer();
1614
1610
  this.log.info('Matter server started');
1615
1611
  for (const plugin of this.registeredPlugins) {
@@ -1628,6 +1624,14 @@ export class Matterbridge extends EventEmitter {
1628
1624
  continue;
1629
1625
  }
1630
1626
  await this.showCommissioningQRCode(plugin.commissioningServer, plugin.storageContext, plugin.nodeContext, plugin.name);
1627
+ // Setting reachability to true
1628
+ this.log.info(`*Setting reachability to true for ${plg}${plugin.name}${db}`);
1629
+ if (plugin.commissioningServer)
1630
+ this.setCommissioningServerReachability(plugin.commissioningServer, true);
1631
+ if (plugin.type === 'AccessoryPlatform' && plugin.device)
1632
+ this.setDeviceReachability(plugin.device, true);
1633
+ if (plugin.type === 'DynamicPlatform' && plugin.aggregator)
1634
+ this.setAggregatorReachability(plugin.aggregator, true);
1631
1635
  }
1632
1636
  Logger.defaultLogLevel = this.debugEnabled ? Level.DEBUG : Level.INFO;
1633
1637
  //clearInterval(startMatterInterval);
@@ -1644,7 +1648,7 @@ export class Matterbridge extends EventEmitter {
1644
1648
  await this.cleanup('No matter server initialized');
1645
1649
  return;
1646
1650
  }
1647
- this.log.debug('Starting matter server');
1651
+ this.log.debug('Starting matter server...');
1648
1652
  await this.matterServer.start();
1649
1653
  this.log.debug('Started matter server');
1650
1654
  }
@@ -1764,6 +1768,49 @@ export class Matterbridge extends EventEmitter {
1764
1768
  }
1765
1769
  return plugin;
1766
1770
  }
1771
+ /**
1772
+ * Sets the reachability of a commissioning server and trigger.
1773
+ *
1774
+ * @param {CommissioningServer} commissioningServer - The commissioning server to set the reachability for.
1775
+ * @param {boolean} reachable - The new reachability status.
1776
+ */
1777
+ setCommissioningServerReachability(commissioningServer, reachable) {
1778
+ const basicInformationCluster = commissioningServer?.getRootClusterServer(BasicInformationCluster);
1779
+ if (basicInformationCluster && basicInformationCluster.attributes.reachable !== undefined)
1780
+ basicInformationCluster.setReachableAttribute(reachable);
1781
+ if (basicInformationCluster && basicInformationCluster.triggerReachableChangedEvent)
1782
+ basicInformationCluster.triggerReachableChangedEvent({ reachableNewValue: reachable });
1783
+ }
1784
+ /**
1785
+ * Sets the reachability of the specified matter aggregator and its bridged devices and trigger.
1786
+ * @param {Aggregator} matterAggregator - The matter aggregator to set the reachability for.
1787
+ * @param {boolean} reachable - A boolean indicating the reachability status to set.
1788
+ */
1789
+ setAggregatorReachability(matterAggregator, reachable) {
1790
+ const basicInformationCluster = matterAggregator.getClusterServer(BasicInformationCluster);
1791
+ if (basicInformationCluster && basicInformationCluster.attributes.reachable !== undefined)
1792
+ basicInformationCluster.setReachableAttribute(reachable);
1793
+ if (basicInformationCluster && basicInformationCluster.triggerReachableChangedEvent)
1794
+ basicInformationCluster.triggerReachableChangedEvent({ reachableNewValue: reachable });
1795
+ matterAggregator.getBridgedDevices().forEach((device) => {
1796
+ this.log.debug(`*Setting reachability to true for bridged device: ${dev}${device.name}${nf}`);
1797
+ device.getClusterServer(BridgedDeviceBasicInformationCluster)?.setReachableAttribute(reachable);
1798
+ device.getClusterServer(BridgedDeviceBasicInformationCluster)?.triggerReachableChangedEvent({ reachableNewValue: reachable });
1799
+ });
1800
+ }
1801
+ /**
1802
+ * Sets the reachability of a device and trigger.
1803
+ *
1804
+ * @param {MatterbridgeDevice} device - The device to set the reachability for.
1805
+ * @param {boolean} reachable - The new reachability status of the device.
1806
+ */
1807
+ setDeviceReachability(device, reachable) {
1808
+ const basicInformationCluster = device.getClusterServer(BasicInformationCluster);
1809
+ if (basicInformationCluster && basicInformationCluster.attributes.reachable !== undefined)
1810
+ basicInformationCluster.setReachableAttribute(reachable);
1811
+ if (basicInformationCluster && basicInformationCluster.triggerReachableChangedEvent)
1812
+ basicInformationCluster.triggerReachableChangedEvent({ reachableNewValue: reachable });
1813
+ }
1767
1814
  /**
1768
1815
  * Creates a matter commissioning server.
1769
1816
  *
@@ -1816,7 +1863,14 @@ export class Matterbridge extends EventEmitter {
1816
1863
  info.forEach((session) => {
1817
1864
  this.log.debug(`***Active session changed on fabric ${fabricIndex} ${session.fabric?.rootVendorId}/${session.fabric?.label} for ${plg}${pluginName}${nf}`, debugStringify(session));
1818
1865
  if (session.isPeerActive === true && session.secure === true && session.numberOfActiveSubscriptions >= 1) {
1819
- this.log.info(`***Controller ${session.fabric?.rootVendorId}/${session.fabric?.label} connected to ${plg}${pluginName}${nf}`);
1866
+ let controllerName = '';
1867
+ if (session.fabric?.rootVendorId === 4937)
1868
+ controllerName = 'AppleHome';
1869
+ if (session.fabric?.rootVendorId === 4362)
1870
+ controllerName = 'SmartThings';
1871
+ if (session.fabric?.rootVendorId === 4939)
1872
+ controllerName = 'HomeAssistant';
1873
+ this.log.info(`***Controller ${session.fabric?.rootVendorId}${controllerName !== '' ? '(' + controllerName + ')' : ''}/${session.fabric?.label} connected to ${plg}${pluginName}${nf}`);
1820
1874
  connected = true;
1821
1875
  }
1822
1876
  });
@@ -2249,18 +2303,25 @@ export class Matterbridge extends EventEmitter {
2249
2303
  childProcess.stdout.on('data', (data) => {
2250
2304
  const message = data.toString().trim();
2251
2305
  //this.log.info('\n' + message);
2252
- this.wssSendMessage('spawn', 'stdout', message);
2306
+ this.wssSendMessage('Matterbridge:spawn', 'spawn', message);
2253
2307
  });
2254
2308
  }
2255
2309
  if (childProcess.stderr) {
2256
2310
  childProcess.stderr.on('data', (data) => {
2257
2311
  const message = data.toString().trim();
2258
2312
  //this.log.debug('\n' + message);
2259
- this.wssSendMessage('spawn', 'stderr', message);
2313
+ this.wssSendMessage('Matterbridge:spawn', 'spawn', message);
2260
2314
  });
2261
2315
  }
2262
2316
  });
2263
2317
  }
2318
+ /**
2319
+ * Sends a WebSocket message to all connected clients.
2320
+ *
2321
+ * @param {string} type - The type of the message: Matterbridge, Plugin, Device, ...
2322
+ * @param {string} subType - The subtype of the message: debug info warn error ....
2323
+ * @param {string} message - The content of the message.
2324
+ */
2264
2325
  wssSendMessage(type, subType, message) {
2265
2326
  // Remove ANSI escape codes from the message
2266
2327
  // eslint-disable-next-line no-control-regex
@@ -2280,17 +2341,44 @@ export class Matterbridge extends EventEmitter {
2280
2341
  */
2281
2342
  async initializeFrontend(port = 8283) {
2282
2343
  this.log.debug(`Initializing the frontend on port ${YELLOW}${port}${db} static ${UNDERLINE}${path.join(this.rootDirectory, 'frontend/build')}${UNDERLINEOFF}${rs}`);
2283
- // Create a WebSocket server
2284
- this.webSocketServer = new WebSocketServer({ port: 8284 });
2344
+ const wssPort = 8284;
2345
+ const useHttps = false;
2346
+ //const wssHost = (useHttps ? 'wss://' : 'ws://') + `${os.hostname().toLowerCase()}:${wssPort}`;
2347
+ const wssHost = (useHttps ? 'wss://' : 'ws://') + `${this.systemInformation.ipv4Address}:${wssPort}`;
2348
+ if (!useHttps) {
2349
+ // Create a WebSocket server no certificate required
2350
+ this.webSocketServer = new WebSocketServer({ port: wssPort });
2351
+ this.log.info(`WebSocket server listening on ${UNDERLINE}${wssHost}${UNDERLINEOFF}${rs}`);
2352
+ }
2353
+ else {
2354
+ // Define the options for HTTPS server
2355
+ // openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout mykey.key -out mycert.pem -config openssl.cnf
2356
+ // For wss connect the browser to https://laptop5_luca:8284/ https://192.168.1.189/log and accept the certificate
2357
+ const serverOptions = {
2358
+ cert: await fs.readFile(path.join(this.rootDirectory, 'frontend/certificates/mycert.pem')), // Ensure the path is correct
2359
+ key: await fs.readFile(path.join(this.rootDirectory, 'frontend/certificates/mykey.key')), // Ensure the path is correct
2360
+ // cert: await fs.readFile(path.join(this.rootDirectory, 'frontend/certificates/laptop5_luca.pem')), // Ensure the path is correct
2361
+ // key: await fs.readFile(path.join(this.rootDirectory, 'frontend/certificates/laptop5_luca.key')), // Ensure the path is correct
2362
+ };
2363
+ // Create an HTTPS server
2364
+ const httpsServer = https.createServer(serverOptions);
2365
+ // Attach WebSocket server to HTTPS server
2366
+ this.webSocketServer = new WebSocketServer({ server: httpsServer });
2367
+ // Listen on a specific port
2368
+ httpsServer.listen(wssPort, () => {
2369
+ this.log.info(`WebSocket server listening on ${UNDERLINE}${wssHost}${UNDERLINEOFF}${rs}`);
2370
+ });
2371
+ }
2285
2372
  this.webSocketServer.on('connection', (ws) => {
2286
- this.log.debug('WebSocketServer client connected');
2373
+ this.log.info('WebSocketServer client connected');
2287
2374
  this.log.setGlobalCallback(this.wssSendMessage.bind(this));
2288
2375
  this.log.debug('WebSocketServer activated logger callback');
2376
+ this.wssSendMessage('Matterbridge', 'info', 'WebSocketServer client connected to Matterbridge');
2289
2377
  ws.on('message', (message) => {
2290
- this.log.debug(`WebSocketServer received message => ${message}`);
2378
+ this.log.info(`WebSocketServer received message => ${message}`);
2291
2379
  });
2292
2380
  ws.on('close', () => {
2293
- this.log.debug('WebSocketServer client disconnected');
2381
+ this.log.info('WebSocketServer client disconnected');
2294
2382
  if (this.webSocketServer?.clients.size === 0) {
2295
2383
  this.log.setGlobalCallback(undefined);
2296
2384
  this.log.debug('WebSocketServer deactivated logger callback');
@@ -2303,7 +2391,7 @@ export class Matterbridge extends EventEmitter {
2303
2391
  // Serve React build directory
2304
2392
  this.expressApp = express();
2305
2393
  this.expressApp.use(express.static(path.join(this.rootDirectory, 'frontend/build')));
2306
- // Endpoint to provide login code
2394
+ // Endpoint to validate login code
2307
2395
  this.expressApp.post('/api/login', express.json(), async (req, res) => {
2308
2396
  const { password } = req.body;
2309
2397
  this.log.debug('The frontend sent /api/login', password);
@@ -2323,63 +2411,30 @@ export class Matterbridge extends EventEmitter {
2323
2411
  res.json({ valid: false });
2324
2412
  }
2325
2413
  });
2326
- // Endpoint to provide host
2327
- this.expressApp.get('/api/wsshost', express.json(), async (req, res) => {
2328
- this.log.debug('The frontend sent /api/wsshost');
2329
- res.json({ host: os.hostname() });
2330
- });
2331
- // Endpoint to provide port
2332
- this.expressApp.get('/api/wssport', express.json(), async (req, res) => {
2333
- this.log.debug('The frontend sent /api/wssport');
2334
- res.json({ port: 8284 });
2335
- });
2336
- // Endpoint to provide manual pairing code
2337
- this.expressApp.get('/api/pairing-code', (req, res) => {
2338
- this.log.debug('The frontend sent /api/pairing-code');
2414
+ // Endpoint to provide settings
2415
+ this.expressApp.get('/api/settings', express.json(), async (req, res) => {
2339
2416
  if (!this.matterbridgeContext) {
2340
- this.log.error('/api/pairing-code matterbridgeContext not found');
2341
- res.json([]);
2342
- return;
2343
- }
2344
- try {
2345
- const qrData = { qrPairingCode: this.matterbridgeContext.get('qrPairingCode'), manualPairingCode: this.matterbridgeContext.get('manualPairingCode') };
2346
- res.json(qrData);
2347
- }
2348
- catch (error) {
2349
- if (this.bridgeMode === 'bridge')
2350
- this.log.error('qrPairingCode for /api/qr-code not found');
2417
+ this.log.error('/api/settings matterbridgeContext not found');
2351
2418
  res.json({});
2352
- }
2353
- });
2354
- // Endpoint to provide QR pairing code
2355
- this.expressApp.get('/api/qr-code', (req, res) => {
2356
- this.log.debug('The frontend sent /api/qr-code');
2357
- if (!this.matterbridgeContext) {
2358
- this.log.error('/api/qr-code matterbridgeContext not found');
2359
- res.json([]);
2360
2419
  return;
2361
2420
  }
2421
+ let qrPairingCode = '';
2422
+ let manualPairingCode = '';
2362
2423
  try {
2363
- const qrData = { qrPairingCode: this.matterbridgeContext.get('qrPairingCode'), manualPairingCode: this.matterbridgeContext.get('manualPairingCode') };
2364
- res.json(qrData);
2424
+ qrPairingCode = await this.matterbridgeContext.get('qrPairingCode');
2425
+ manualPairingCode = await this.matterbridgeContext.get('manualPairingCode');
2365
2426
  }
2366
2427
  catch (error) {
2367
2428
  if (this.bridgeMode === 'bridge')
2368
- this.log.error('qrPairingCode for /api/qr-code not found');
2429
+ this.log.error('pairingCode for /api/settings not found');
2369
2430
  res.json({});
2370
2431
  }
2371
- });
2372
- // Endpoint to provide system information
2373
- this.expressApp.get('/api/system-info', (req, res) => {
2374
- this.log.debug('The frontend sent /api/system-info');
2375
- res.json(this.systemInformation);
2376
- });
2377
- // Endpoint to provide matterbridge information
2378
- this.expressApp.get('/api/matterbridge-info', (req, res) => {
2379
- this.log.debug('The frontend sent /api/matterbridge-info');
2380
2432
  this.matterbridgeInformation.bridgeMode = this.bridgeMode;
2381
2433
  this.matterbridgeInformation.debugEnabled = this.debugEnabled;
2382
- res.json(this.matterbridgeInformation);
2434
+ const response = { wssHost, qrPairingCode, manualPairingCode, systemInformation: this.systemInformation, matterbridgeInformation: this.matterbridgeInformation };
2435
+ this.log.debug('The frontend sent /api/settings');
2436
+ this.log.debug('Response:', debugStringify(response));
2437
+ res.json(response);
2383
2438
  });
2384
2439
  // Endpoint to provide plugins
2385
2440
  this.expressApp.get('/api/plugins', (req, res) => {
@@ -2469,7 +2524,7 @@ export class Matterbridge extends EventEmitter {
2469
2524
  // Handle the command setpassword from Settings
2470
2525
  if (command === 'setpassword') {
2471
2526
  const password = param.slice(1, -1); // Remove the first and last characters
2472
- this.log.info('setpassword', param, password);
2527
+ this.log.debug('setpassword', param, password);
2473
2528
  await this.nodeContext?.set('password', password);
2474
2529
  }
2475
2530
  // Handle the command debugLevel from Settings
@@ -2504,15 +2559,12 @@ export class Matterbridge extends EventEmitter {
2504
2559
  // Handle the command update from Header
2505
2560
  if (command === 'update') {
2506
2561
  this.log.info('Updating matterbridge...');
2507
- //this.wssSendMessage('cmd', 'update', 'Updating matterbridge');
2508
2562
  try {
2509
2563
  await this.spawnCommand('npm', ['install', '-g', 'matterbridge', '--loglevel=verbose']);
2510
2564
  this.log.info('Matterbridge has been updated. Full restart required.');
2511
- //this.wssSendMessage('cmd', 'update', 'Matterbridge has been updated. Full restart required.');
2512
2565
  }
2513
2566
  catch (error) {
2514
2567
  this.log.error('Error updating matterbridge');
2515
- //this.wssSendMessage('cmd', 'update', 'Error updating matterbridge');
2516
2568
  res.json({ message: 'Command received' });
2517
2569
  return;
2518
2570
  }
@@ -2522,15 +2574,12 @@ export class Matterbridge extends EventEmitter {
2522
2574
  if (command === 'installplugin') {
2523
2575
  param = param.replace(/\*/g, '\\');
2524
2576
  this.log.info(`Installing plugin ${plg}${param}${db}...`);
2525
- //this.wssSendMessage('cmd', 'installplugin', `Installing plugin ${param}`);
2526
2577
  try {
2527
2578
  await this.spawnCommand('npm', ['install', '-g', param, '--loglevel=verbose']);
2528
2579
  this.log.info(`Plugin ${plg}${param}${nf} installed. Full restart required.`);
2529
- //this.wssSendMessage('cmd', 'installplugin', `Plugin ${param} installed. Full restart required.`);
2530
2580
  }
2531
2581
  catch (error) {
2532
2582
  this.log.error(`Error installing plugin ${plg}${param}${er}`);
2533
- //this.wssSendMessage('cmd', 'installplugin', `Error installing plugin${param}`);
2534
2583
  res.json({ message: 'Command received' });
2535
2584
  return;
2536
2585
  }
@@ -2653,9 +2702,26 @@ export class Matterbridge extends EventEmitter {
2653
2702
  this.log.debug('The frontend sent *', req.url);
2654
2703
  res.sendFile(path.join(this.rootDirectory, 'frontend/build/index.html'));
2655
2704
  });
2656
- this.expressServer = this.expressApp.listen(port, () => {
2657
- this.log.info(`The frontend is running on ${UNDERLINE}http://localhost:${port}${UNDERLINEOFF}${rs}`);
2658
- });
2705
+ if (!useHttps) {
2706
+ // Listen on HTTP
2707
+ this.expressServer = this.expressApp.listen(port, () => {
2708
+ this.log.info(`The frontend is running on ${UNDERLINE}http://localhost:${port}${UNDERLINEOFF}${rs}`);
2709
+ });
2710
+ }
2711
+ else {
2712
+ // SSL certificate and private key paths
2713
+ const options = {
2714
+ cert: await fs.readFile(path.join(this.rootDirectory, 'frontend/certificates/laptop5_luca.pem')), // Ensure the path is correct
2715
+ key: await fs.readFile(path.join(this.rootDirectory, 'frontend/certificates/laptop5_luca.key')), // Ensure the path is correct
2716
+ };
2717
+ // Create HTTPS server
2718
+ const httpsServer = https.createServer(options, this.expressApp);
2719
+ // Specify the port to listen on, for example 443 for default HTTPS
2720
+ const PORT = 443;
2721
+ httpsServer.listen(PORT, () => {
2722
+ this.log.info(`The frontend is running on ${UNDERLINE}https://localhost:${PORT}${UNDERLINEOFF}${rs}`);
2723
+ });
2724
+ }
2659
2725
  this.log.debug(`Frontend initialized on port ${YELLOW}${port}${db} static ${UNDERLINE}${path.join(this.rootDirectory, 'frontend/build')}${UNDERLINEOFF}${rs}`);
2660
2726
  }
2661
2727
  /**