matterbridge 3.4.4-dev-20251216-3e9ec5b → 3.4.4-dev-20251217-8b8b1cd

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
@@ -32,12 +32,13 @@ Advantages:
32
32
 
33
33
  ### Added
34
34
 
35
- - [frontend]: Set autoScroll to false in mobileMode.
35
+ - [frontend]: Set automatically autoScroll to false in mobileMode.
36
36
  - [frontend]: Added Log length: 100, 200, 500, 1000.
37
- - [frontend]: Added Log search with case-insensitive regex: use /text/ in the search field.
37
+ - [frontend]: Added Log search with case-insensitive regex: use /regex/ in the search field to activate the regex search mode (i.e. /Frontend/). See [Regex](https://github.com/Luligu/matterbridge/tree/dev?tab=readme-ov-file#how-to-use-the-regex-search-in-the-log-page).
38
38
  - [frontend]: Differentiated update icon color: primary color for latest and secondary color for dev.
39
- - [frontend]: Added `Reset the frontend UI` in the Reset menu. It will reset the frontend local storage to the default.
40
- - [MbfTable]: Added ConditionalTooltip to show clipped column cells. Used in the Cluster table.
39
+ - [frontend]: Added `Reset the frontend UI` in the Reset menu. It will reset the frontend local storage to the default and reload the page.
40
+ - [MbfTable]: Added ConditionalTooltip to show clipped column cells. Used in the Cluster table for a better user experience.
41
+ - [frontend]: Added battery level to Devices panel in the Home page. Thanks [Tamer Salah](https://github.com/tammeryousef1006).
41
42
 
42
43
  ### Changed
43
44
 
@@ -48,6 +49,7 @@ Advantages:
48
49
 
49
50
  - [doorLock]: Fixed DoorLock.supportedOperatingModes. Thanks Ludovic BOUÉ (https://github.com/Luligu/matterbridge/issues/454).
50
51
  - [frontend]: Fixed mobileMode menu navigation. Thanks Calimerorulez (https://github.com/Luligu/matterbridge/issues/457).
52
+ - [matterbridge]: Fixed debug level of matter logger.
51
53
 
52
54
  <a href="https://www.buymeacoffee.com/luligugithub"><img src="https://matterbridge.io/bmc-button.svg" alt="Buy me a coffee" width="80"></a>
53
55
 
package/README.md CHANGED
@@ -520,6 +520,19 @@ To solve the race condition on blackout, use the --delay parameter. There is no
520
520
 
521
521
  To solve the race condition on docker compose, use the --fixed_delay parameter. The start will always be delayed so use it only if strictly necessary.
522
522
 
523
+ ## How to use the regex search in the Log page
524
+
525
+ The regex search is activated when the search string starts with `/` and ends with `/`.
526
+
527
+ Examples:
528
+
529
+ ```text
530
+ /^error/ -> match log names (the part with [...]) or lines that start with "error"
531
+ /timeout/ -> match "timeout" anywhere in the line (beginning/middle/end)
532
+ /disconnected$/ -> match lines that end with "disconnected"
533
+ /error|warning/ -> match either "error" OR "warning" (double search)
534
+ ```
535
+
523
536
  # Known general issues
524
537
 
525
538
  ## Session XYZ does not exist or Cannot find a session for ID XYZ
package/dist/frontend.js CHANGED
@@ -163,11 +163,11 @@ export class Frontend extends EventEmitter {
163
163
  this.wsMessageHandler(ws, message);
164
164
  });
165
165
  ws.on('ping', () => {
166
- this.log.debug('WebSocket client ping');
166
+ this.log.debug('WebSocket client ping received');
167
167
  ws.pong();
168
168
  });
169
169
  ws.on('pong', () => {
170
- this.log.debug('WebSocket client pong');
170
+ this.log.debug('WebSocket client pong received');
171
171
  });
172
172
  ws.on('close', () => {
173
173
  this.log.info('WebSocket client disconnected');
@@ -836,7 +836,7 @@ export class Frontend extends EventEmitter {
836
836
  }
837
837
  getPowerSource(endpoint) {
838
838
  if (this.matterbridge.hasCleanupStarted)
839
- return;
839
+ return undefined;
840
840
  if (!endpoint.lifecycle.isReady || endpoint.construction.status !== Lifecycle.Status.Active)
841
841
  return undefined;
842
842
  const powerSource = (device) => {
@@ -858,6 +858,26 @@ export class Frontend extends EventEmitter {
858
858
  return powerSource(child);
859
859
  }
860
860
  }
861
+ getBatteryLevel(endpoint) {
862
+ if (this.matterbridge.hasCleanupStarted)
863
+ return undefined;
864
+ if (!endpoint.lifecycle.isReady || endpoint.construction.status !== Lifecycle.Status.Active)
865
+ return undefined;
866
+ const batteryLevel = (device) => {
867
+ const featureMap = device.getAttribute(PowerSource.Cluster.id, 'featureMap');
868
+ if (featureMap.battery) {
869
+ const batChargeLevel = device.getAttribute(PowerSource.Cluster.id, 'batPercentRemaining');
870
+ return isValidNumber(batChargeLevel) ? batChargeLevel / 2 : undefined;
871
+ }
872
+ return undefined;
873
+ };
874
+ if (endpoint.hasClusterServer(PowerSource.Cluster.id))
875
+ return batteryLevel(endpoint);
876
+ for (const child of endpoint.getChildEndpoints()) {
877
+ if (child.hasClusterServer(PowerSource.Cluster.id))
878
+ return batteryLevel(child);
879
+ }
880
+ }
861
881
  getClusterTextFromDevice(device) {
862
882
  if (this.matterbridge.hasCleanupStarted)
863
883
  return '';
@@ -1030,6 +1050,7 @@ export class Frontend extends EventEmitter {
1030
1050
  uniqueId: device.uniqueId,
1031
1051
  reachable: this.getReachability(device),
1032
1052
  powerSource: this.getPowerSource(device),
1053
+ batteryLevel: this.getBatteryLevel(device),
1033
1054
  matter: device.mode === 'server' && device.serverNode ? this.matterbridge.getServerNodeData(device.serverNode) : undefined,
1034
1055
  cluster: this.getClusterTextFromDevice(device),
1035
1056
  });
@@ -1228,8 +1249,7 @@ export class Frontend extends EventEmitter {
1228
1249
  this.wssSendSnackbarMessage(`Loaded plugin ${localData.params.pluginNameOrPath}`, 5, 'success');
1229
1250
  return;
1230
1251
  })
1231
- .catch((_error) => {
1232
- });
1252
+ .catch((_error) => { });
1233
1253
  }
1234
1254
  else {
1235
1255
  sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: `Plugin ${data.params.pluginNameOrPath} not added` });
@@ -1277,8 +1297,7 @@ export class Frontend extends EventEmitter {
1277
1297
  this.wssSendSnackbarMessage(`Started plugin ${localData.params.pluginName}`, 5, 'success');
1278
1298
  return;
1279
1299
  })
1280
- .catch((_error) => {
1281
- });
1300
+ .catch((_error) => { });
1282
1301
  }
1283
1302
  sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
1284
1303
  }
@@ -67,7 +67,7 @@ export class Matterbridge extends EventEmitter {
67
67
  log = new AnsiLogger({ logName: 'Matterbridge', logTimestampFormat: 4, logLevel: hasParameter('debug') ? "debug" : "info" });
68
68
  logLevel = this.log.logLevel;
69
69
  fileLogger = false;
70
- matterLog = new AnsiLogger({ logName: 'Matter', logTimestampFormat: 4, logLevel: hasParameter('debug') ? "debug" : "info" });
70
+ matterLog = new AnsiLogger({ logName: 'Matter', logTimestampFormat: 4, logLevel: "debug" });
71
71
  matterLogLevel = this.matterLog.logLevel;
72
72
  matterFileLogger = false;
73
73
  readOnly = hasParameter('readonly') || hasParameter('shelly');
@@ -1147,6 +1147,7 @@ export class Matterbridge extends EventEmitter {
1147
1147
  await addVirtualDevices(this, this.aggregatorNode);
1148
1148
  await this.startPlugins();
1149
1149
  this.log.debug('Starting start matter interval in bridge mode...');
1150
+ this.frontend.wssSendSnackbarMessage(`The bridge is starting...`, 0, 'info');
1150
1151
  let failCount = 0;
1151
1152
  this.startMatterInterval = setInterval(async () => {
1152
1153
  if (failCount && failCount % 10 === 0) {
@@ -1214,6 +1215,7 @@ export class Matterbridge extends EventEmitter {
1214
1215
  this.log.notice('Matterbridge bridge started successfully');
1215
1216
  this.frontend.wssSendRefreshRequired('settings');
1216
1217
  this.frontend.wssSendRefreshRequired('plugins');
1218
+ this.frontend.wssSendCloseSnackbarMessage(`The bridge is starting...`);
1217
1219
  }, Number(process.env['MATTERBRIDGE_START_MATTER_INTERVAL_MS']) || this.startMatterIntervalMs);
1218
1220
  }
1219
1221
  async startChildbridge(delay = 1000) {
@@ -1229,6 +1231,7 @@ export class Matterbridge extends EventEmitter {
1229
1231
  this.plugins.start(plugin, 'Matterbridge is starting');
1230
1232
  }
1231
1233
  this.log.debug('Starting start matter interval in childbridge mode...');
1234
+ this.frontend.wssSendSnackbarMessage(`The bridge is starting...`, 0, 'info');
1232
1235
  let failCount = 0;
1233
1236
  this.startMatterInterval = setInterval(async () => {
1234
1237
  if (failCount && failCount % 10 === 0) {
@@ -1322,6 +1325,7 @@ export class Matterbridge extends EventEmitter {
1322
1325
  this.log.notice('Matterbridge childbridge started successfully');
1323
1326
  this.frontend.wssSendRefreshRequired('settings');
1324
1327
  this.frontend.wssSendRefreshRequired('plugins');
1328
+ this.frontend.wssSendCloseSnackbarMessage(`The bridge is starting...`);
1325
1329
  }, Number(process.env['MATTERBRIDGE_START_MATTER_INTERVAL_MS']) || this.startMatterIntervalMs);
1326
1330
  }
1327
1331
  async startController() {