matterbridge 3.2.10-dev-20250928-30c21de → 3.3.0-dev-20250928-3d2b558
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 +67 -2
- package/dist/frontend.js +2 -1
- package/dist/index.js +1 -1
- package/dist/matterbridgePlatform.js +32 -22
- package/frontend/build/assets/index.js +7 -7
- package/frontend/build/assets/vendor_mui.js +23 -31
- package/frontend/build/assets/vendor_node_modules.js +32 -24
- package/frontend/build/assets/vendor_notistack.js +2 -2
- package/frontend/build/assets/vendor_qrcode.js +1 -1
- package/frontend/build/assets/vendor_rjsf.js +7 -7
- package/frontend/package-lock.json +287 -211
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,9 +8,74 @@ If you like this project and find it useful, please consider giving it a star on
|
|
|
8
8
|
<img src="bmc-button.svg" alt="Buy me a coffee" width="120">
|
|
9
9
|
</a>
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## Project evolution
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
The project will evolve to multi thread (the cli will become the threads manager) with these initial threads:
|
|
14
|
+
|
|
15
|
+
- matterbridge;
|
|
16
|
+
- frontend;
|
|
17
|
+
- all plugins in bridge mode;
|
|
18
|
+
- each plugin in childbridge mode;
|
|
19
|
+
|
|
20
|
+
Advantages:
|
|
21
|
+
|
|
22
|
+
- real concurrency outside the Node.js main loop;
|
|
23
|
+
- isolation between threads;
|
|
24
|
+
- single plugin isolation in childbridge mode;
|
|
25
|
+
|
|
26
|
+
## [3.3.0] - Not released
|
|
27
|
+
|
|
28
|
+
### Development Breaking Changes
|
|
29
|
+
|
|
30
|
+
- [platform]: Now, internal use only properties are private readonly and internal use only methods are private. This prepares the road to plugin isolation.
|
|
31
|
+
- [platform]: The signature of the matterbridge param in the platform constructor has changed from Matterbridge to `PlatformMatterbridge` that has only the approriate readonly properties from matterbridge. This prepares the road to plugin isolation.
|
|
32
|
+
|
|
33
|
+
This change will require to adapt all plugins in two steps.
|
|
34
|
+
|
|
35
|
+
1. `After` matterbridge `3.3.0` will be published as latest:
|
|
36
|
+
|
|
37
|
+
- update the plugin platform constructor with the new signature:
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
constructor(matterbridge: PlatformMatterbridge, log: AnsiLogger, config: PlatformConfig)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
- require matterbridge 3.3.0:
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
if (this.verifyMatterbridgeVersion === undefined || typeof this.verifyMatterbridgeVersion !== 'function' || !this.verifyMatterbridgeVersion('3.3.0')) {
|
|
47
|
+
throw new Error(
|
|
48
|
+
`This plugin requires Matterbridge version >= "3.3.0". Please update Matterbridge from ${this.matterbridge.matterbridgeVersion} to the latest version."`,
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
- check that you didn't used any matterbridge calls.
|
|
54
|
+
|
|
55
|
+
In this phase (matterbridge 3.3.x) all plugins will continue to build and run even without updates.
|
|
56
|
+
|
|
57
|
+
2. `After` matterbridge `3.4.0` will be published as latest, the new signature `PlatformMatterbridge` with the plugin isolation will be effective.
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
export type PlatformMatterbridge = {
|
|
61
|
+
readonly homeDirectory: string;
|
|
62
|
+
readonly rootDirectory: string;
|
|
63
|
+
readonly matterbridgeDirectory: string;
|
|
64
|
+
readonly matterbridgePluginDirectory: string;
|
|
65
|
+
readonly globalModulesDirectory: string;
|
|
66
|
+
readonly matterbridgeVersion: string;
|
|
67
|
+
readonly matterbridgeLatestVersion: string;
|
|
68
|
+
readonly matterbridgeDevVersion: string;
|
|
69
|
+
readonly bridgeMode: 'bridge' | 'childbridge' | 'controller' | '';
|
|
70
|
+
readonly restartMode: 'service' | 'docker' | '';
|
|
71
|
+
readonly aggregatorVendorId: VendorId;
|
|
72
|
+
readonly aggregatorVendorName: string;
|
|
73
|
+
readonly aggregatorProductId: number;
|
|
74
|
+
readonly aggregatorProductName: string;
|
|
75
|
+
};
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
In this phase (matterbridge 3.4.x) all plugins will not build and will not run without updates.
|
|
14
79
|
|
|
15
80
|
### Added
|
|
16
81
|
|
package/dist/frontend.js
CHANGED
|
@@ -643,7 +643,7 @@ export class Frontend extends EventEmitter {
|
|
|
643
643
|
this.matterbridge.matterbridgeInformation.restartMode = this.matterbridge.restartMode;
|
|
644
644
|
this.matterbridge.matterbridgeInformation.profile = this.matterbridge.profile;
|
|
645
645
|
this.matterbridge.matterbridgeInformation.loggerLevel = this.matterbridge.log.logLevel;
|
|
646
|
-
this.matterbridge.matterbridgeInformation.matterLoggerLevel = Logger.
|
|
646
|
+
this.matterbridge.matterbridgeInformation.matterLoggerLevel = Logger.level;
|
|
647
647
|
this.matterbridge.matterbridgeInformation.matterMdnsInterface = this.matterbridge.mdnsInterface;
|
|
648
648
|
this.matterbridge.matterbridgeInformation.matterIpv4Address = this.matterbridge.ipv4address;
|
|
649
649
|
this.matterbridge.matterbridgeInformation.matterIpv6Address = this.matterbridge.ipv6address;
|
|
@@ -997,6 +997,7 @@ export class Frontend extends EventEmitter {
|
|
|
997
997
|
.then(() => {
|
|
998
998
|
this.wssSendSnackbarMessage(`Started plugin ${packageName}`, 5, 'success');
|
|
999
999
|
this.wssSendRefreshRequired('plugins');
|
|
1000
|
+
this.wssSendRefreshRequired('devices');
|
|
1000
1001
|
return;
|
|
1001
1002
|
})
|
|
1002
1003
|
.catch((_error) => {
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AnsiLogger } from 'node-ansi-logger';
|
|
2
2
|
import { Matterbridge } from './matterbridge.js';
|
|
3
|
-
import { hasParameter } from './utils/
|
|
3
|
+
import { hasParameter } from './utils/commandLine.js';
|
|
4
4
|
export * from './matterbridge.js';
|
|
5
5
|
export * from './matterbridgeTypes.js';
|
|
6
6
|
export * from './matterbridgeEndpoint.js';
|
|
@@ -5,7 +5,7 @@ import { CYAN, db, er, nf, wr } from 'node-ansi-logger';
|
|
|
5
5
|
import { NodeStorageManager } from 'node-persist-manager';
|
|
6
6
|
import { checkNotLatinCharacters } from './matterbridgeEndpointHelpers.js';
|
|
7
7
|
import { bridgedNode } from './matterbridgeDeviceTypes.js';
|
|
8
|
-
import { isValidArray, isValidObject, isValidString } from './utils/
|
|
8
|
+
import { isValidArray, isValidObject, isValidString } from './utils/isvalid.js';
|
|
9
9
|
export class MatterbridgePlatform {
|
|
10
10
|
matterbridge;
|
|
11
11
|
log;
|
|
@@ -17,12 +17,12 @@ export class MatterbridgePlatform {
|
|
|
17
17
|
context;
|
|
18
18
|
selectDevice = new Map();
|
|
19
19
|
selectEntity = new Map();
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
contextReady;
|
|
21
|
+
selectDeviceContextReady;
|
|
22
|
+
selectEntityContextReady;
|
|
23
23
|
ready;
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
registeredEndpointsByUniqueId = new Map();
|
|
25
|
+
registeredEndpointsByName = new Map();
|
|
26
26
|
constructor(matterbridge, log, config) {
|
|
27
27
|
this.matterbridge = matterbridge;
|
|
28
28
|
this.log = log;
|
|
@@ -38,13 +38,13 @@ export class MatterbridgePlatform {
|
|
|
38
38
|
forgiveParseErrors: true,
|
|
39
39
|
});
|
|
40
40
|
this.log.debug(`Creating context for plugin ${this.config.name}`);
|
|
41
|
-
this.
|
|
41
|
+
this.contextReady = this.storage.createStorage('context').then((context) => {
|
|
42
42
|
this.context = context;
|
|
43
43
|
this.log.debug(`Created context for plugin ${this.config.name}`);
|
|
44
44
|
return;
|
|
45
45
|
});
|
|
46
46
|
this.log.debug(`Loading selectDevice for plugin ${this.config.name}`);
|
|
47
|
-
this.
|
|
47
|
+
this.selectDeviceContextReady = this.storage.createStorage('selectDevice').then(async (context) => {
|
|
48
48
|
const selectDevice = await context.get('selectDevice', []);
|
|
49
49
|
for (const device of selectDevice)
|
|
50
50
|
this.selectDevice.set(device.serial, device);
|
|
@@ -52,14 +52,14 @@ export class MatterbridgePlatform {
|
|
|
52
52
|
return;
|
|
53
53
|
});
|
|
54
54
|
this.log.debug(`Loading selectEntity for plugin ${this.config.name}`);
|
|
55
|
-
this.
|
|
55
|
+
this.selectEntityContextReady = this.storage.createStorage('selectEntity').then(async (context) => {
|
|
56
56
|
const selectEntity = await context.get('selectEntity', []);
|
|
57
57
|
for (const entity of selectEntity)
|
|
58
58
|
this.selectEntity.set(entity.name, entity);
|
|
59
59
|
this.log.debug(`Loaded ${this.selectEntity.size} selectEntity for plugin ${this.config.name}`);
|
|
60
60
|
return;
|
|
61
61
|
});
|
|
62
|
-
this.ready = Promise.all([this.
|
|
62
|
+
this.ready = Promise.all([this.contextReady, this.selectDeviceContextReady, this.selectEntityContextReady]).then(() => {
|
|
63
63
|
this.log.debug(`MatterbridgePlatform for plugin ${this.config.name} is fully initialized`);
|
|
64
64
|
return;
|
|
65
65
|
});
|
|
@@ -79,8 +79,8 @@ export class MatterbridgePlatform {
|
|
|
79
79
|
await this.checkEndpointNumbers();
|
|
80
80
|
this.selectDevice.clear();
|
|
81
81
|
this.selectEntity.clear();
|
|
82
|
-
this.
|
|
83
|
-
this.
|
|
82
|
+
this.registeredEndpointsByUniqueId.clear();
|
|
83
|
+
this.registeredEndpointsByName.clear();
|
|
84
84
|
await this.context?.close();
|
|
85
85
|
this.context = undefined;
|
|
86
86
|
await this.storage?.close();
|
|
@@ -94,11 +94,21 @@ export class MatterbridgePlatform {
|
|
|
94
94
|
async onConfigChanged(config) {
|
|
95
95
|
this.log.debug(`The plugin ${CYAN}${config.name}${db} doesn't override onConfigChanged. Received new config.`);
|
|
96
96
|
}
|
|
97
|
+
saveConfig(config) {
|
|
98
|
+
const plugin = this.matterbridge.plugins.get(this.name);
|
|
99
|
+
if (!plugin) {
|
|
100
|
+
throw new Error(`Plugin ${this.name} not found`);
|
|
101
|
+
}
|
|
102
|
+
this.matterbridge.plugins.saveConfigFromJson(plugin, config);
|
|
103
|
+
}
|
|
104
|
+
wssSendRestartRequired(snackbar = true, fixed = false) {
|
|
105
|
+
this.matterbridge.frontend.wssSendRestartRequired(snackbar, fixed);
|
|
106
|
+
}
|
|
97
107
|
getDevices() {
|
|
98
|
-
return Array.from(this.
|
|
108
|
+
return Array.from(this.registeredEndpointsByUniqueId.values());
|
|
99
109
|
}
|
|
100
110
|
hasDeviceName(deviceName) {
|
|
101
|
-
return this.
|
|
111
|
+
return this.registeredEndpointsByName.has(deviceName);
|
|
102
112
|
}
|
|
103
113
|
async registerDevice(device) {
|
|
104
114
|
device.plugin = this.name;
|
|
@@ -114,7 +124,7 @@ export class MatterbridgePlatform {
|
|
|
114
124
|
this.log.error(`Device with uniqueId ${CYAN}${device.uniqueId}${er} has no serialNumber. The device will not be added.`);
|
|
115
125
|
return;
|
|
116
126
|
}
|
|
117
|
-
if (this.
|
|
127
|
+
if (this.registeredEndpointsByName.has(device.deviceName)) {
|
|
118
128
|
this.log.error(`Device with name ${CYAN}${device.deviceName}${er} is already registered. The device will not be added. Please change the device name.`);
|
|
119
129
|
return;
|
|
120
130
|
}
|
|
@@ -139,20 +149,20 @@ export class MatterbridgePlatform {
|
|
|
139
149
|
}
|
|
140
150
|
}
|
|
141
151
|
await this.matterbridge.addBridgedEndpoint(this.name, device);
|
|
142
|
-
this.
|
|
143
|
-
this.
|
|
152
|
+
this.registeredEndpointsByUniqueId.set(device.uniqueId, device);
|
|
153
|
+
this.registeredEndpointsByName.set(device.deviceName, device);
|
|
144
154
|
}
|
|
145
155
|
async unregisterDevice(device) {
|
|
146
156
|
await this.matterbridge.removeBridgedEndpoint(this.name, device);
|
|
147
157
|
if (device.uniqueId)
|
|
148
|
-
this.
|
|
158
|
+
this.registeredEndpointsByUniqueId.delete(device.uniqueId);
|
|
149
159
|
if (device.deviceName)
|
|
150
|
-
this.
|
|
160
|
+
this.registeredEndpointsByName.delete(device.deviceName);
|
|
151
161
|
}
|
|
152
162
|
async unregisterAllDevices(delay = 0) {
|
|
153
163
|
await this.matterbridge.removeAllBridgedEndpoints(this.name, delay);
|
|
154
|
-
this.
|
|
155
|
-
this.
|
|
164
|
+
this.registeredEndpointsByUniqueId.clear();
|
|
165
|
+
this.registeredEndpointsByName.clear();
|
|
156
166
|
}
|
|
157
167
|
async saveSelects() {
|
|
158
168
|
if (this.storage) {
|
|
@@ -299,7 +309,7 @@ export class MatterbridgePlatform {
|
|
|
299
309
|
const context = await this.storage.createStorage('endpointNumbers');
|
|
300
310
|
const separator = '|.|';
|
|
301
311
|
const endpointMap = new Map(await context.get('endpointMap', []));
|
|
302
|
-
for (const device of this.
|
|
312
|
+
for (const device of this.getDevices()) {
|
|
303
313
|
if (device.uniqueId === undefined || device.maybeNumber === undefined) {
|
|
304
314
|
this.log.debug(`Not checking device ${device.deviceName} without uniqueId or maybeNumber`);
|
|
305
315
|
continue;
|