matterbridge 1.6.8-dev.8 → 1.6.8-dev.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 +3 -1
- package/dist/matterbridge.js +43 -6
- package/dist/matterbridgePlatform.js +54 -4
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -13,12 +13,14 @@ It is also available the official Matterbridge Home Assistant plugin https://git
|
|
|
13
13
|
|
|
14
14
|
Tamer (https://github.com/tammeryousef1006) has created the Matterbridge Discord group: https://discord.gg/QX58CDe6hd.
|
|
15
15
|
|
|
16
|
-
## [1.6.8-dev.
|
|
16
|
+
## [1.6.8-dev.9] - 2024-12-21
|
|
17
17
|
|
|
18
18
|
### Added
|
|
19
19
|
|
|
20
20
|
- [storage]: Added conversion from old matter storage to the new api format with fabrics, resumptionRecords, network, commissioning, operationalCredentials, acl and parts number. The conversion is triggered every time you shutdown or restart matterbridge till the new storage has been used with matterbridge edge.
|
|
21
|
+
- [storage]: Added conversion for child endpoint numbers.
|
|
21
22
|
- [package]: Update README.md and README-SERVICE.md to include instructions for using SSL on port 443.
|
|
23
|
+
- [platform]: Added checkEndpointNumbers() to detect endpoint numbers changes.
|
|
22
24
|
|
|
23
25
|
### Changed
|
|
24
26
|
|
package/dist/matterbridge.js
CHANGED
|
@@ -137,6 +137,12 @@ export class Matterbridge extends EventEmitter {
|
|
|
137
137
|
super();
|
|
138
138
|
this.matterbridgeMessageHandler = wsMessageHandler.bind(this);
|
|
139
139
|
}
|
|
140
|
+
getDevices() {
|
|
141
|
+
return this.devices.array();
|
|
142
|
+
}
|
|
143
|
+
getPlugins() {
|
|
144
|
+
return this.plugins.array();
|
|
145
|
+
}
|
|
140
146
|
matterbridgeMessageHandler;
|
|
141
147
|
static async loadInstance(initialize = false) {
|
|
142
148
|
if (!Matterbridge.instance) {
|
|
@@ -1553,7 +1559,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
1553
1559
|
const storageService = Environment.default.get(StorageService);
|
|
1554
1560
|
Environment.default.vars.set('path.root', path.join(this.matterbridgeDirectory, 'matterstorage' + (this.profile ? '.' + this.profile : '')));
|
|
1555
1561
|
const nodeStorage = await storageService.open('Matterbridge');
|
|
1556
|
-
if ((await nodeStorage.createContext('root').createContext('generalDiagnostics').get('rebootCount',
|
|
1562
|
+
if ((await nodeStorage.createContext('root').createContext('generalDiagnostics').get('rebootCount', -1)) >= 0) {
|
|
1557
1563
|
this.log.info(`Matter node storage already converted to Matterbridge edge for ${plg}${pluginName}${nf}`);
|
|
1558
1564
|
return;
|
|
1559
1565
|
}
|
|
@@ -1562,7 +1568,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
1562
1568
|
}
|
|
1563
1569
|
const fabricManagerContext = context.createContext('FabricManager');
|
|
1564
1570
|
const fabrics = (await fabricManagerContext.get('fabrics', []));
|
|
1565
|
-
const nextFabricIndex = await fabricManagerContext.get('nextFabricIndex',
|
|
1571
|
+
const nextFabricIndex = await fabricManagerContext.get('nextFabricIndex', 0);
|
|
1566
1572
|
const eventHandlerContext = context.createContext('EventHandler');
|
|
1567
1573
|
const sessionManagerContext = context.createContext('SessionManager');
|
|
1568
1574
|
const endpointStructureContext = context.createContext('EndpointStructure');
|
|
@@ -1574,6 +1580,10 @@ export class Matterbridge extends EventEmitter {
|
|
|
1574
1580
|
const trcArray = [];
|
|
1575
1581
|
const aclArray = [];
|
|
1576
1582
|
this.log.info(`Found ${CYAN}${fabrics.length}${nf} fabrics (nextFabricIndex ${CYAN}${nextFabricIndex}${nf}) for ${plg}${pluginName}${nf}:`);
|
|
1583
|
+
if (fabrics.length === 0 || nextFabricIndex === 0) {
|
|
1584
|
+
this.log.notice(`If you want to try out matterbridge edge (beta) add -edge to the command line and pair it to your controller(s).`);
|
|
1585
|
+
return;
|
|
1586
|
+
}
|
|
1577
1587
|
for (const fabric of fabrics) {
|
|
1578
1588
|
this.log.info(`- fabricIndex ${CYAN}${fabric.fabricIndex}${nf} fabricId ${CYAN}${fabric.fabricId}${nf} nodeId ${CYAN}${fabric.nodeId}${nf} rootNodeId ${CYAN}${fabric.rootNodeId}${nf} rootVendorId ${CYAN}${fabric.rootVendorId}${nf} label ${CYAN}${fabric.label}${nf}`);
|
|
1579
1589
|
fabricInfo[fabric.fabricIndex] = {
|
|
@@ -1640,20 +1650,47 @@ export class Matterbridge extends EventEmitter {
|
|
|
1640
1650
|
const parts = key.split('-');
|
|
1641
1651
|
const number = await endpointStructureContext.get(key);
|
|
1642
1652
|
if (parts.length === 2) {
|
|
1643
|
-
this.log.debug(`Converting Matterbridge.EndpointStructure:${key}:${number} to root.parts.Matterbridge.__number__:${number}`);
|
|
1653
|
+
this.log.debug(`Converting bridge Matterbridge.EndpointStructure:${key}:${number} to root.parts.Matterbridge.__number__:${number}`);
|
|
1644
1654
|
await nodeStorage.createContext('root').createContext('parts').createContext('Matterbridge').set('__number__', number);
|
|
1645
1655
|
}
|
|
1646
1656
|
else if (parts.length === 3 && parts[2].startsWith('custom_')) {
|
|
1647
|
-
this.log.debug(`Converting Matterbridge.EndpointStructure:${key}:${number} to root.parts.Matterbridge.parts.${parts[2].replace('custom_', '')}.__number__:${number}`);
|
|
1648
|
-
await nodeStorage.createContext('root').createContext('parts').createContext('Matterbridge').createContext('parts').createContext(parts[2].replace('custom_', '')).set('__number__', number);
|
|
1657
|
+
this.log.debug(`Converting custom Matterbridge.EndpointStructure:${key}:${number} to root.parts.Matterbridge.parts.${parts[2].replace('custom_', '').replace(/[ .]/g, '')}.__number__:${number}`);
|
|
1658
|
+
await nodeStorage.createContext('root').createContext('parts').createContext('Matterbridge').createContext('parts').createContext(parts[2].replace('custom_', '').replace(/[ .]/g, '')).set('__number__', number);
|
|
1649
1659
|
}
|
|
1650
1660
|
else if (parts.length === 3 && parts[2].startsWith('unique_')) {
|
|
1651
1661
|
const device = this.devices.get(parts[2].replace('unique_', ''));
|
|
1652
1662
|
if (device && device.deviceName && device.maybeNumber) {
|
|
1653
|
-
this.log.debug(`Converting Matterbridge.EndpointStructure:${key}:${number} to root.parts.Matterbridge.parts.${device.deviceName.replace(/[ .]/g, '')}.__number__:${device.maybeNumber}`);
|
|
1663
|
+
this.log.debug(`Converting unique Matterbridge.EndpointStructure:${key}:${number} to root.parts.Matterbridge.parts.${device.deviceName.replace(/[ .]/g, '')}.__number__:${device.maybeNumber}`);
|
|
1654
1664
|
await nodeStorage.createContext('root').createContext('parts').createContext('Matterbridge').createContext('parts').createContext(device.deviceName.replace(/[ .]/g, '')).set('__number__', device.maybeNumber);
|
|
1655
1665
|
}
|
|
1656
1666
|
}
|
|
1667
|
+
else if (parts.length === 4 && parts[2].startsWith('unique_') && parts[3].startsWith('custom_')) {
|
|
1668
|
+
const device = this.devices.get(parts[2].replace('unique_', ''));
|
|
1669
|
+
if (device && device.deviceName && device.maybeNumber) {
|
|
1670
|
+
this.log.debug(`Converting unique Matterbridge.EndpointStructure:${key}:${number} to root.parts.Matterbridge.parts.${device.deviceName.replace(/[ .]/g, '')}.parts.${parts[3].replace('custom_', '').replace(/[ .]/g, '')}.__number__:${device.maybeNumber}`);
|
|
1671
|
+
await nodeStorage
|
|
1672
|
+
.createContext('root')
|
|
1673
|
+
.createContext('parts')
|
|
1674
|
+
.createContext('Matterbridge')
|
|
1675
|
+
.createContext('parts')
|
|
1676
|
+
.createContext(device.deviceName.replace(/[ .]/g, ''))
|
|
1677
|
+
.createContext('parts')
|
|
1678
|
+
.createContext(parts[3].replace('custom_', '').replace(/[ .]/g, ''))
|
|
1679
|
+
.set('__number__', device.maybeNumber);
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1682
|
+
else if (parts.length === 4 && parts[2].startsWith('custom_') && parts[3].startsWith('custom_')) {
|
|
1683
|
+
this.log.debug(`Converting custom Matterbridge.EndpointStructure:${key}:${number} to root.parts.Matterbridge.parts.${parts[2].replace('custom_', '').replace(/[ .]/g, '')}.parts.${parts[3].replace('custom_', '').replace(/[ .]/g, '')}.__number__:${number}`);
|
|
1684
|
+
await nodeStorage
|
|
1685
|
+
.createContext('root')
|
|
1686
|
+
.createContext('parts')
|
|
1687
|
+
.createContext('Matterbridge')
|
|
1688
|
+
.createContext('parts')
|
|
1689
|
+
.createContext(parts[2].replace('custom_', '').replace(/[ .]/g, ''))
|
|
1690
|
+
.createContext('parts')
|
|
1691
|
+
.createContext(parts[3].replace('custom_', '').replace(/[ .]/g, ''))
|
|
1692
|
+
.set('__number__', number);
|
|
1693
|
+
}
|
|
1657
1694
|
}
|
|
1658
1695
|
await nodeStorage.createContext('persist').set('converted', true);
|
|
1659
1696
|
await nodeStorage.createContext('persist').set('deviceName', await context.get('deviceName'));
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { MatterbridgeDevice } from './matterbridgeDevice.js';
|
|
2
|
-
import { CYAN, nf } from 'node-ansi-logger';
|
|
3
2
|
import { MatterbridgeEndpoint } from './matterbridgeEndpoint.js';
|
|
4
|
-
import { isValidArray, isValidObject } from './utils/utils.js';
|
|
3
|
+
import { isValidArray, isValidObject, isValidString } from './utils/utils.js';
|
|
4
|
+
import { CYAN, db, nf, wr } from 'node-ansi-logger';
|
|
5
|
+
import { NodeStorageManager } from 'node-persist-manager';
|
|
6
|
+
import path from 'path';
|
|
5
7
|
export class MatterbridgePlatform {
|
|
6
8
|
matterbridge;
|
|
7
9
|
log;
|
|
@@ -9,20 +11,34 @@ export class MatterbridgePlatform {
|
|
|
9
11
|
name = '';
|
|
10
12
|
type = '';
|
|
11
13
|
version = '';
|
|
14
|
+
storage;
|
|
15
|
+
context;
|
|
12
16
|
constructor(matterbridge, log, config) {
|
|
13
17
|
this.matterbridge = matterbridge;
|
|
14
18
|
this.log = log;
|
|
15
19
|
this.config = config;
|
|
20
|
+
if (!isValidString(this.config.name))
|
|
21
|
+
return;
|
|
22
|
+
this.log.debug(`Creating storage for plugin ${this.config.name} in ${path.join(this.matterbridge.matterbridgeDirectory, this.config.name)}`);
|
|
23
|
+
this.storage = new NodeStorageManager({
|
|
24
|
+
dir: path.join(this.matterbridge.matterbridgeDirectory, this.config.name),
|
|
25
|
+
writeQueue: false,
|
|
26
|
+
expiredInterval: undefined,
|
|
27
|
+
logging: false,
|
|
28
|
+
forgiveParseErrors: true,
|
|
29
|
+
});
|
|
16
30
|
}
|
|
17
31
|
async onStart(reason) {
|
|
18
32
|
this.log.error('Plugins must override onStart.', reason);
|
|
19
33
|
throw new Error('Plugins must override onStart.');
|
|
20
34
|
}
|
|
21
35
|
async onConfigure() {
|
|
22
|
-
this.log.debug(
|
|
36
|
+
this.log.debug(`Configuring platform ${this.name}`);
|
|
37
|
+
await this.checkEndpointNumbers();
|
|
23
38
|
}
|
|
24
39
|
async onShutdown(reason) {
|
|
25
|
-
this.log.debug(
|
|
40
|
+
this.log.debug(`Shutting down platform ${this.name}`, reason);
|
|
41
|
+
await this.checkEndpointNumbers();
|
|
26
42
|
}
|
|
27
43
|
async onChangeLoggerLevel(logLevel) {
|
|
28
44
|
this.log.debug(`The plugin doesn't override onChangeLoggerLevel. Logger level set to: ${logLevel}`);
|
|
@@ -120,4 +136,38 @@ export class MatterbridgePlatform {
|
|
|
120
136
|
}
|
|
121
137
|
return true;
|
|
122
138
|
}
|
|
139
|
+
async checkEndpointNumbers() {
|
|
140
|
+
if (!this.storage)
|
|
141
|
+
return -1;
|
|
142
|
+
this.log.debug('Checking endpoint numbers...');
|
|
143
|
+
const context = await this.storage.createStorage('context');
|
|
144
|
+
const separator = '|.|';
|
|
145
|
+
const endpointMap = new Map(await context.get('endpointMap', []));
|
|
146
|
+
for (const device of this.matterbridge.getDevices().filter((d) => d.plugin === this.name)) {
|
|
147
|
+
if (device.uniqueId === undefined || device.maybeNumber === undefined)
|
|
148
|
+
continue;
|
|
149
|
+
if (endpointMap.has(device.uniqueId) && endpointMap.get(device.uniqueId) !== device.maybeNumber) {
|
|
150
|
+
this.log.warn(`Endpoint number for device ${CYAN}${device.uniqueId}${wr} changed from ${CYAN}${endpointMap.get(device.uniqueId)}${wr} to ${CYAN}${device.maybeNumber}${wr}`);
|
|
151
|
+
endpointMap.set(device.uniqueId, device.maybeNumber);
|
|
152
|
+
}
|
|
153
|
+
if (!endpointMap.has(device.uniqueId)) {
|
|
154
|
+
this.log.debug(`Setting endpoint number for device ${CYAN}${device.uniqueId}${db} to ${CYAN}${device.maybeNumber}${db}`);
|
|
155
|
+
endpointMap.set(device.uniqueId, device.maybeNumber);
|
|
156
|
+
}
|
|
157
|
+
for (const child of device.getChildEndpoints()) {
|
|
158
|
+
const childId = child instanceof MatterbridgeEndpoint ? child.id : child.uniqueStorageKey;
|
|
159
|
+
if (!childId || !child.maybeNumber)
|
|
160
|
+
continue;
|
|
161
|
+
if (endpointMap.has(device.uniqueId + separator + childId) && endpointMap.get(device.uniqueId + separator + childId) !== child.maybeNumber) {
|
|
162
|
+
this.log.warn(`Child endpoint number for device ${CYAN}${device.uniqueId}${wr}.${CYAN}${childId}${wr} changed from ${CYAN}${endpointMap.get(device.uniqueId + separator + childId)}${wr} to ${CYAN}${child.maybeNumber}${wr}`);
|
|
163
|
+
}
|
|
164
|
+
if (!endpointMap.has(device.uniqueId + separator + childId)) {
|
|
165
|
+
this.log.debug(`Setting child endpoint number for device ${CYAN}${device.uniqueId}${db}.${CYAN}${childId}${db} to ${CYAN}${child.maybeNumber}${db}`);
|
|
166
|
+
endpointMap.set(device.uniqueId + separator + childId, child.maybeNumber);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
await context.set('endpointMap', Array.from(endpointMap.entries()));
|
|
171
|
+
return endpointMap.size;
|
|
172
|
+
}
|
|
123
173
|
}
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "matterbridge",
|
|
3
|
-
"version": "1.6.8-dev.
|
|
3
|
+
"version": "1.6.8-dev.9",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "matterbridge",
|
|
9
|
-
"version": "1.6.8-dev.
|
|
9
|
+
"version": "1.6.8-dev.9",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@matter/main": "0.11.9",
|