matterbridge 2.2.6-dev.1 → 2.2.6-dev.3

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
@@ -29,7 +29,7 @@ Features:
29
29
  - It is possible to choose the method: GET or POST.
30
30
  - The webhook can be tested directly in the frontend.
31
31
 
32
- ## [2.2.6] - 2025-03-29
32
+ ## [2.2.6] - 2025-03-31
33
33
 
34
34
  ### Added
35
35
 
@@ -39,13 +39,14 @@ Features:
39
39
 
40
40
  ### Changed
41
41
 
42
+ - [commissionig]: If the bridge is not paired, when the advertising stops (after 15 minutes from start) the QR code is hidden and a notification is displayed.
42
43
  - [package]: Update dependencies.
43
44
  - [package]: Update matter.js to 0.12.6.
44
45
 
45
46
  ### Fixed
46
47
 
47
48
  - [ipv6address]: The ipv6address can be entered in the frontend with the scopeid. On Windows the format is ipv6%scopeid (i.e. fe80::5a71:b2f6:7bc8:d00b%8). On Linux the format is ipv6%interfaceName (i.e. fe80::5a71:b2f6:7bc8:d00b%eth0)
48
- - [onOff]: The onOff cluster created from createOnOffClusterServer() is not correct (no Lighting feature).
49
+ - [onOff]: The onOff cluster created from createOnOffClusterServer() is now correct (no Lighting feature).
49
50
 
50
51
  <a href="https://www.buymeacoffee.com/luligugithub">
51
52
  <img src="bmc-button.svg" alt="Buy me a coffee" width="80">
package/dist/frontend.js CHANGED
@@ -1170,6 +1170,16 @@ export class Frontend {
1170
1170
  triggerShellyChangeNet(this.matterbridge, data.params);
1171
1171
  return;
1172
1172
  }
1173
+ else if (data.method === '/api/softreset') {
1174
+ const { triggerShellySoftReset } = await import('./shelly.js');
1175
+ triggerShellySoftReset(this.matterbridge);
1176
+ return;
1177
+ }
1178
+ else if (data.method === '/api/hardreset') {
1179
+ const { triggerShellyHardReset } = await import('./shelly.js');
1180
+ triggerShellyHardReset(this.matterbridge);
1181
+ return;
1182
+ }
1173
1183
  else if (data.method === '/api/reboot') {
1174
1184
  const { triggerShellyReboot } = await import('./shelly.js');
1175
1185
  triggerShellyReboot(this.matterbridge);
@@ -46,6 +46,7 @@ export class Matterbridge extends EventEmitter {
46
46
  rootDirectory: '',
47
47
  matterbridgeDirectory: '',
48
48
  matterbridgePluginDirectory: '',
49
+ matterbridgeCertDirectory: '',
49
50
  globalModulesDirectory: '',
50
51
  matterbridgeVersion: '',
51
52
  matterbridgeLatestVersion: '',
@@ -79,6 +80,7 @@ export class Matterbridge extends EventEmitter {
79
80
  rootDirectory = '';
80
81
  matterbridgeDirectory = '';
81
82
  matterbridgePluginDirectory = '';
83
+ matterbridgeCertDirectory = '';
82
84
  globalModulesDirectory = '';
83
85
  matterbridgeVersion = '';
84
86
  matterbridgeLatestVersion = '';
@@ -845,6 +847,29 @@ export class Matterbridge extends EventEmitter {
845
847
  }
846
848
  }
847
849
  this.log.debug(`Matterbridge Plugin Directory: ${this.matterbridgePluginDirectory}`);
850
+ this.matterbridgeCertDirectory = path.join(this.homeDirectory, '.mattercert');
851
+ this.matterbridgeInformation.matterbridgeCertDirectory = this.matterbridgeCertDirectory;
852
+ try {
853
+ await fs.access(this.matterbridgeCertDirectory);
854
+ }
855
+ catch (err) {
856
+ if (err instanceof Error) {
857
+ const nodeErr = err;
858
+ if (nodeErr.code === 'ENOENT') {
859
+ try {
860
+ await fs.mkdir(this.matterbridgeCertDirectory, { recursive: true });
861
+ this.log.info(`Created .mattercert directory: ${this.matterbridgeCertDirectory}`);
862
+ }
863
+ catch (err) {
864
+ this.log.error(`Error creating .mattercert directory: ${err}`);
865
+ }
866
+ }
867
+ else {
868
+ this.log.error(`Error accessing .mattercert directory: ${err}`);
869
+ }
870
+ }
871
+ }
872
+ this.log.debug(`Matterbridge Matter Cert Directory: ${this.matterbridgeCertDirectory}`);
848
873
  const packageJson = JSON.parse(await fs.readFile(path.join(this.rootDirectory, 'package.json'), 'utf-8'));
849
874
  this.matterbridgeVersion = this.matterbridgeLatestVersion = packageJson.version;
850
875
  this.matterbridgeInformation.matterbridgeVersion = this.matterbridgeInformation.matterbridgeLatestVersion = this.matterbridgeVersion;
@@ -1464,6 +1489,23 @@ export class Matterbridge extends EventEmitter {
1464
1489
  }
1465
1490
  }
1466
1491
  }
1492
+ setTimeout(() => {
1493
+ if (this.bridgeMode === 'bridge') {
1494
+ this.matterbridgeQrPairingCode = undefined;
1495
+ this.matterbridgeManualPairingCode = undefined;
1496
+ }
1497
+ if (this.bridgeMode === 'childbridge') {
1498
+ const plugin = this.plugins.get(storeId);
1499
+ if (plugin) {
1500
+ plugin.qrPairingCode = undefined;
1501
+ plugin.manualPairingCode = undefined;
1502
+ this.frontend.wssSendRefreshRequired('plugins');
1503
+ }
1504
+ }
1505
+ this.frontend.wssSendRefreshRequired('settings');
1506
+ this.frontend.wssSendSnackbarMessage(`Advertising on server node for ${storeId} stopped. Restart to commission.`, 0);
1507
+ this.log.notice(`Advertising on server node for ${storeId} stopped. Restart to commission.`);
1508
+ }, 15 * 60 * 1000).unref();
1467
1509
  }
1468
1510
  else {
1469
1511
  this.log.notice(`Server node for ${storeId} is already commissioned. Waiting for controllers to connect ...`);
@@ -843,34 +843,34 @@ export class MatterbridgeEndpoint extends Endpoint {
843
843
  return false;
844
844
  }
845
845
  if (event === 'Single') {
846
+ log?.info(`${db}Trigger endpoint ${or}${this.id}:${this.number}${db} event ${hk}Switch.SinglePress${db}`);
846
847
  await this.setAttribute(Switch.Cluster.id, 'currentPosition', 1, log);
847
- this.triggerEvent(Switch.Cluster.id, 'initialPress', { newPosition: 1 }, log);
848
+ await this.triggerEvent(Switch.Cluster.id, 'initialPress', { newPosition: 1 }, log);
848
849
  await this.setAttribute(Switch.Cluster.id, 'currentPosition', 0, log);
849
- this.triggerEvent(Switch.Cluster.id, 'shortRelease', { previousPosition: 1 }, log);
850
+ await this.triggerEvent(Switch.Cluster.id, 'shortRelease', { previousPosition: 1 }, log);
850
851
  await this.setAttribute(Switch.Cluster.id, 'currentPosition', 0, log);
851
- this.triggerEvent(Switch.Cluster.id, 'multiPressComplete', { previousPosition: 1, totalNumberOfPressesCounted: 1 }, log);
852
- log?.info(`${db}Trigger endpoint ${or}${this.id}:${this.number}${db} event ${hk}Switch.SinglePress${db}`);
852
+ await this.triggerEvent(Switch.Cluster.id, 'multiPressComplete', { previousPosition: 1, totalNumberOfPressesCounted: 1 }, log);
853
853
  }
854
854
  if (event === 'Double') {
855
+ log?.info(`${db}Trigger endpoint ${or}${this.id}:${this.number}${db} event ${hk}Switch.DoublePress${db}`);
855
856
  await this.setAttribute(Switch.Cluster.id, 'currentPosition', 1, log);
856
- this.triggerEvent(Switch.Cluster.id, 'initialPress', { newPosition: 1 }, log);
857
+ await this.triggerEvent(Switch.Cluster.id, 'initialPress', { newPosition: 1 }, log);
857
858
  await this.setAttribute(Switch.Cluster.id, 'currentPosition', 0, log);
858
- this.triggerEvent(Switch.Cluster.id, 'shortRelease', { previousPosition: 1 }, log);
859
+ await this.triggerEvent(Switch.Cluster.id, 'shortRelease', { previousPosition: 1 }, log);
859
860
  await this.setAttribute(Switch.Cluster.id, 'currentPosition', 1, log);
860
- this.triggerEvent(Switch.Cluster.id, 'initialPress', { newPosition: 1 }, log);
861
- this.triggerEvent(Switch.Cluster.id, 'multiPressOngoing', { newPosition: 1, currentNumberOfPressesCounted: 2 }, log);
861
+ await this.triggerEvent(Switch.Cluster.id, 'initialPress', { newPosition: 1 }, log);
862
+ await this.triggerEvent(Switch.Cluster.id, 'multiPressOngoing', { newPosition: 1, currentNumberOfPressesCounted: 2 }, log);
862
863
  await this.setAttribute(Switch.Cluster.id, 'currentPosition', 0, log);
863
- this.triggerEvent(Switch.Cluster.id, 'shortRelease', { previousPosition: 1 }, log);
864
- this.triggerEvent(Switch.Cluster.id, 'multiPressComplete', { previousPosition: 1, totalNumberOfPressesCounted: 2 }, log);
865
- log?.info(`${db}Trigger endpoint ${or}${this.id}:${this.number}${db} event ${hk}Switch.DoublePress${db}`);
864
+ await this.triggerEvent(Switch.Cluster.id, 'shortRelease', { previousPosition: 1 }, log);
865
+ await this.triggerEvent(Switch.Cluster.id, 'multiPressComplete', { previousPosition: 1, totalNumberOfPressesCounted: 2 }, log);
866
866
  }
867
867
  if (event === 'Long') {
868
+ log?.info(`${db}Trigger endpoint ${or}${this.id}:${this.number}${db} event ${hk}Switch.LongPress${db}`);
868
869
  await this.setAttribute(Switch.Cluster.id, 'currentPosition', 1, log);
869
- this.triggerEvent(Switch.Cluster.id, 'initialPress', { newPosition: 1 }, log);
870
- this.triggerEvent(Switch.Cluster.id, 'longPress', { newPosition: 1 }, log);
870
+ await this.triggerEvent(Switch.Cluster.id, 'initialPress', { newPosition: 1 }, log);
871
+ await this.triggerEvent(Switch.Cluster.id, 'longPress', { newPosition: 1 }, log);
871
872
  await this.setAttribute(Switch.Cluster.id, 'currentPosition', 0, log);
872
- this.triggerEvent(Switch.Cluster.id, 'longRelease', { previousPosition: 1 }, log);
873
- log?.info(`${db}Trigger endpoint ${or}${this.id}:${this.number}${db} event ${hk}Switch.LongPress${db}`);
873
+ await this.triggerEvent(Switch.Cluster.id, 'longRelease', { previousPosition: 1 }, log);
874
874
  }
875
875
  }
876
876
  if (['Press', 'Release'].includes(event)) {
@@ -879,14 +879,14 @@ export class MatterbridgeEndpoint extends Endpoint {
879
879
  return false;
880
880
  }
881
881
  if (event === 'Press') {
882
- await this.setAttribute(Switch.Cluster.id, 'currentPosition', 1, log);
883
- this.triggerEvent(Switch.Cluster.id, 'switchLatched', { newPosition: 1 }, log);
884
882
  log?.info(`${db}Trigger endpoint ${or}${this.id}:${this.number}${db} event ${hk}Switch.Press${db}`);
883
+ await this.setAttribute(Switch.Cluster.id, 'currentPosition', 1, log);
884
+ await this.triggerEvent(Switch.Cluster.id, 'switchLatched', { newPosition: 1 }, log);
885
885
  }
886
886
  if (event === 'Release') {
887
- await this.setAttribute(Switch.Cluster.id, 'currentPosition', 0, log);
888
- this.triggerEvent(Switch.Cluster.id, 'switchLatched', { newPosition: 0 }, log);
889
887
  log?.info(`${db}Trigger endpoint ${or}${this.id}:${this.number}${db} event ${hk}Switch.Release${db}`);
888
+ await this.setAttribute(Switch.Cluster.id, 'currentPosition', 0, log);
889
+ await this.triggerEvent(Switch.Cluster.id, 'switchLatched', { newPosition: 0 }, log);
890
890
  }
891
891
  }
892
892
  return true;
@@ -137,6 +137,10 @@ export class MatterbridgePlatform {
137
137
  this.selectEntity.clear();
138
138
  await this.saveSelects();
139
139
  }
140
+ async clearDeviceSelect(device) {
141
+ this.selectDevice.delete(device);
142
+ await this.saveSelects();
143
+ }
140
144
  setSelectDevice(serial, name, configUrl, icon, entities) {
141
145
  const device = this.selectDevice.get(serial);
142
146
  if (device) {
package/dist/shelly.js CHANGED
@@ -112,13 +112,15 @@ export async function triggerShellyChangeIp(matterbridge, config) {
112
112
  postShelly(api, data, 60 * 1000)
113
113
  .then(async () => {
114
114
  matterbridge.log.debug(`Triggered Shelly network configuration change: ${debugStringify(config)}`);
115
+ matterbridge.log.notice(`Changed Shelly network configuration`);
116
+ matterbridge.frontend.wssSendSnackbarMessage('Changed Shelly network configuration');
115
117
  })
116
118
  .catch((error) => {
117
119
  matterbridge.log.debug(`****Error triggering Shelly network configuration change: ${error instanceof Error ? error.message : error}`);
120
+ matterbridge.log.error(`Error changing Shelly network configuration: ${error instanceof Error ? error.message : error}`);
121
+ matterbridge.frontend.wssSendSnackbarMessage('Error changing Shelly network configuration', 10, 'error');
118
122
  })
119
123
  .finally(() => {
120
- matterbridge.log.notice(`Changed Shelly network configuration`);
121
- matterbridge.frontend.wssSendSnackbarMessage('Changed Shelly network configuration');
122
124
  });
123
125
  }
124
126
  export async function triggerShellyReboot(matterbridge) {
@@ -126,13 +128,47 @@ export async function triggerShellyReboot(matterbridge) {
126
128
  postShelly('/api/system/reboot', {}, 60 * 1000)
127
129
  .then(async () => {
128
130
  matterbridge.log.debug(`Triggered Shelly system reboot`);
131
+ matterbridge.log.notice(`Rebooting Shelly board...`);
132
+ matterbridge.frontend.wssSendSnackbarMessage('Rebooting Shelly board...');
129
133
  })
130
134
  .catch((error) => {
131
135
  matterbridge.log.debug(`****Error triggering Shelly system reboot: ${error instanceof Error ? error.message : error}`);
136
+ matterbridge.log.error(`Error rebooting Shelly board: ${error instanceof Error ? error.message : error}`);
137
+ matterbridge.frontend.wssSendSnackbarMessage('Error rebooting Shelly board', 10, 'error');
138
+ })
139
+ .finally(() => {
140
+ });
141
+ }
142
+ export async function triggerShellySoftReset(matterbridge) {
143
+ matterbridge.log.debug(`Triggering Shelly soft reset`);
144
+ postShelly('/api/reset/soft', {}, 60 * 1000)
145
+ .then(async () => {
146
+ matterbridge.log.debug(`Triggered Shelly soft reset`);
147
+ matterbridge.log.notice(`Resetting the network parameters on Shelly board...`);
148
+ matterbridge.frontend.wssSendSnackbarMessage('Resetting the network parameters on Shelly board...');
149
+ })
150
+ .catch((error) => {
151
+ matterbridge.log.debug(`****Error triggering Shelly soft reset: ${error instanceof Error ? error.message : error}`);
152
+ matterbridge.log.error(`Error resetting the network parameters on Shelly board: ${error instanceof Error ? error.message : error}`);
153
+ matterbridge.frontend.wssSendSnackbarMessage('Error resetting the network parameters on Shelly board', 10, 'error');
154
+ })
155
+ .finally(() => {
156
+ });
157
+ }
158
+ export async function triggerShellyHardReset(matterbridge) {
159
+ matterbridge.log.debug(`Triggering Shelly hard reset`);
160
+ postShelly('/api/reset/hard', {}, 60 * 1000)
161
+ .then(async () => {
162
+ matterbridge.log.debug(`Triggered Shelly hard reset`);
163
+ matterbridge.log.notice(`Factory resetting Shelly board...`);
164
+ matterbridge.frontend.wssSendSnackbarMessage('Factory resetting Shelly board...');
165
+ })
166
+ .catch((error) => {
167
+ matterbridge.log.debug(`****Error triggering Shelly hard reset: ${error instanceof Error ? error.message : error}`);
168
+ matterbridge.log.error(`Error while factory resetting the Shelly board: ${error instanceof Error ? error.message : error}`);
169
+ matterbridge.frontend.wssSendSnackbarMessage('Error while factory resetting the Shelly board', 10, 'error');
132
170
  })
133
171
  .finally(() => {
134
- matterbridge.log.notice(`Rebooting Shelly board...`);
135
- matterbridge.frontend.wssSendSnackbarMessage('Rebooting Shelly board...');
136
172
  });
137
173
  }
138
174
  export async function createShellySystemLog(matterbridge) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "files": {
3
3
  "main.css": "./static/css/main.ea7910e9.css",
4
- "main.js": "./static/js/main.a45801ac.js",
4
+ "main.js": "./static/js/main.f00179ca.js",
5
5
  "static/js/453.d855a71b.chunk.js": "./static/js/453.d855a71b.chunk.js",
6
6
  "static/media/roboto-latin-700-normal.woff2": "./static/media/roboto-latin-700-normal.c4d6cab43bec89049809.woff2",
7
7
  "static/media/roboto-latin-500-normal.woff2": "./static/media/roboto-latin-500-normal.599f66a60bdf974e578e.woff2",
@@ -77,11 +77,11 @@
77
77
  "static/media/roboto-greek-ext-300-normal.woff": "./static/media/roboto-greek-ext-300-normal.60729cafbded24073dfb.woff",
78
78
  "index.html": "./index.html",
79
79
  "main.ea7910e9.css.map": "./static/css/main.ea7910e9.css.map",
80
- "main.a45801ac.js.map": "./static/js/main.a45801ac.js.map",
80
+ "main.f00179ca.js.map": "./static/js/main.f00179ca.js.map",
81
81
  "453.d855a71b.chunk.js.map": "./static/js/453.d855a71b.chunk.js.map"
82
82
  },
83
83
  "entrypoints": [
84
84
  "static/css/main.ea7910e9.css",
85
- "static/js/main.a45801ac.js"
85
+ "static/js/main.f00179ca.js"
86
86
  ]
87
87
  }
@@ -1 +1 @@
1
- <!doctype html><html lang="en"><head><meta charset="utf-8"/><base href="./"><link rel="icon" href="./matterbridge 32x32.png"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><title>Matterbridge</title><link rel="manifest" href="./manifest.json"/><script defer="defer" src="./static/js/main.a45801ac.js"></script><link href="./static/css/main.ea7910e9.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
1
+ <!doctype html><html lang="en"><head><meta charset="utf-8"/><base href="./"><link rel="icon" href="./matterbridge 32x32.png"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><title>Matterbridge</title><link rel="manifest" href="./manifest.json"/><script defer="defer" src="./static/js/main.f00179ca.js"></script><link href="./static/css/main.ea7910e9.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>