matterbridge 1.6.8-dev.9 → 1.7.1
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 +46 -3
- package/README-DOCKER.md +8 -6
- package/README-EDGE.md +74 -0
- package/README-SERVICE.md +3 -3
- package/README.md +6 -3
- package/dist/cli.d.ts +25 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +26 -0
- package/dist/cli.js.map +1 -0
- package/dist/cluster/export.d.ts +2 -0
- package/dist/cluster/export.d.ts.map +1 -0
- package/dist/cluster/export.js +2 -0
- package/dist/cluster/export.js.map +1 -0
- package/dist/defaultConfigSchema.d.ts +27 -0
- package/dist/defaultConfigSchema.d.ts.map +1 -0
- package/dist/defaultConfigSchema.js +23 -0
- package/dist/defaultConfigSchema.js.map +1 -0
- package/dist/deviceManager.d.ts +46 -0
- package/dist/deviceManager.d.ts.map +1 -0
- package/dist/deviceManager.js +26 -1
- package/dist/deviceManager.js.map +1 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/logger/export.d.ts +2 -0
- package/dist/logger/export.d.ts.map +1 -0
- package/dist/logger/export.js +1 -0
- package/dist/logger/export.js.map +1 -0
- package/dist/matter/export.d.ts +11 -0
- package/dist/matter/export.d.ts.map +1 -0
- package/dist/matter/export.js +4 -0
- package/dist/matter/export.js.map +1 -0
- package/dist/matterbridge.d.ts +483 -0
- package/dist/matterbridge.d.ts.map +1 -0
- package/dist/matterbridge.js +818 -110
- package/dist/matterbridge.js.map +1 -0
- package/dist/matterbridgeAccessoryPlatform.d.ts +39 -0
- package/dist/matterbridgeAccessoryPlatform.d.ts.map +1 -0
- package/dist/matterbridgeAccessoryPlatform.js +33 -0
- package/dist/matterbridgeAccessoryPlatform.js.map +1 -0
- package/dist/matterbridgeBehaviors.d.ts +942 -0
- package/dist/matterbridgeBehaviors.d.ts.map +1 -0
- package/dist/matterbridgeBehaviors.js +29 -1
- package/dist/matterbridgeBehaviors.js.map +1 -0
- package/dist/matterbridgeDevice.d.ts +7077 -0
- package/dist/matterbridgeDevice.d.ts.map +1 -0
- package/dist/matterbridgeDevice.js +996 -9
- package/dist/matterbridgeDevice.js.map +1 -0
- package/dist/matterbridgeDeviceTypes.d.ts +109 -0
- package/dist/matterbridgeDeviceTypes.d.ts.map +1 -0
- package/dist/matterbridgeDeviceTypes.js +82 -11
- package/dist/matterbridgeDeviceTypes.js.map +1 -0
- package/dist/matterbridgeDynamicPlatform.d.ts +39 -0
- package/dist/matterbridgeDynamicPlatform.d.ts.map +1 -0
- package/dist/matterbridgeDynamicPlatform.js +33 -0
- package/dist/matterbridgeDynamicPlatform.js.map +1 -0
- package/dist/matterbridgeEdge.d.ts +91 -0
- package/dist/matterbridgeEdge.d.ts.map +1 -0
- package/dist/matterbridgeEdge.js +558 -11
- package/dist/matterbridgeEdge.js.map +1 -0
- package/dist/matterbridgeEndpoint.d.ts +10151 -0
- package/dist/matterbridgeEndpoint.d.ts.map +1 -0
- package/dist/matterbridgeEndpoint.js +1120 -11
- package/dist/matterbridgeEndpoint.js.map +1 -0
- package/dist/matterbridgePlatform.d.ts +145 -0
- package/dist/matterbridgePlatform.d.ts.map +1 -0
- package/dist/matterbridgePlatform.js +127 -4
- package/dist/matterbridgePlatform.js.map +1 -0
- package/dist/matterbridgeTypes.d.ts +172 -0
- package/dist/matterbridgeTypes.d.ts.map +1 -0
- package/dist/matterbridgeTypes.js +24 -0
- package/dist/matterbridgeTypes.js.map +1 -0
- package/dist/matterbridgeWebsocket.d.ts +49 -0
- package/dist/matterbridgeWebsocket.d.ts.map +1 -0
- package/dist/matterbridgeWebsocket.js +182 -17
- package/dist/matterbridgeWebsocket.js.map +1 -0
- package/dist/pluginManager.d.ts +238 -0
- package/dist/pluginManager.d.ts.map +1 -0
- package/dist/pluginManager.js +238 -3
- package/dist/pluginManager.js.map +1 -0
- package/dist/storage/export.d.ts +2 -0
- package/dist/storage/export.d.ts.map +1 -0
- package/dist/storage/export.js +1 -0
- package/dist/storage/export.js.map +1 -0
- package/dist/utils/colorUtils.d.ts +61 -0
- package/dist/utils/colorUtils.d.ts.map +1 -0
- package/dist/utils/colorUtils.js +205 -2
- package/dist/utils/colorUtils.js.map +1 -0
- package/dist/utils/export.d.ts +3 -0
- package/dist/utils/export.d.ts.map +1 -0
- package/dist/utils/export.js +1 -0
- package/dist/utils/export.js.map +1 -0
- package/dist/utils/utils.d.ts +221 -0
- package/dist/utils/utils.d.ts.map +1 -0
- package/dist/utils/utils.js +252 -7
- package/dist/utils/utils.js.map +1 -0
- package/frontend/build/asset-manifest.json +6 -6
- package/frontend/build/index.html +1 -1
- package/frontend/build/static/css/{main.823e08b6.css → main.b1a621ee.css} +2 -2
- package/frontend/build/static/css/main.b1a621ee.css.map +1 -0
- package/frontend/build/static/js/{main.4dd7e165.js → main.ecd94d17.js} +15 -15
- package/frontend/build/static/js/main.ecd94d17.js.map +1 -0
- package/npm-shrinkwrap.json +33 -20
- package/package.json +2 -1
- package/frontend/build/static/css/main.823e08b6.css.map +0 -1
- package/frontend/build/static/js/main.4dd7e165.js.map +0 -1
- /package/frontend/build/static/js/{main.4dd7e165.js.LICENSE.txt → main.ecd94d17.js.LICENSE.txt} +0 -0
package/dist/matterbridgeEdge.js
CHANGED
|
@@ -1,11 +1,39 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
/**
|
|
3
|
+
* This file contains the class MatterbridgeEdge that extends the Matterbridge class.
|
|
4
|
+
*
|
|
5
|
+
* @file matterbridgeEdge.ts
|
|
6
|
+
* @author Luca Liguori
|
|
7
|
+
* @date 2024-10-01
|
|
8
|
+
* @version 1.0.0
|
|
9
|
+
*
|
|
10
|
+
* Copyright 2024, 2025, 2026 Luca Liguori.
|
|
11
|
+
*
|
|
12
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
13
|
+
* you may not use this file except in compliance with the License.
|
|
14
|
+
* You may obtain a copy of the License at
|
|
15
|
+
*
|
|
16
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
17
|
+
*
|
|
18
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
19
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
20
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
21
|
+
* See the License for the specific language governing permissions and
|
|
22
|
+
* limitations under the License. *
|
|
23
|
+
*/
|
|
24
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
25
|
+
// Node.js modules
|
|
1
26
|
import path from 'path';
|
|
2
27
|
import os from 'os';
|
|
3
28
|
import { randomBytes } from 'crypto';
|
|
29
|
+
// NodeStorage and AnsiLogger modules
|
|
4
30
|
import { rs, GREEN, debugStringify, er, zb, nf, db } from 'node-ansi-logger';
|
|
31
|
+
// Matterbridge
|
|
5
32
|
import { Matterbridge } from './matterbridge.js';
|
|
6
33
|
import { bridge } from './matterbridgeDeviceTypes.js';
|
|
7
34
|
import { dev, plg } from './matterbridgeTypes.js';
|
|
8
35
|
import { copyDirectory, getParameter, hasParameter } from './utils/utils.js';
|
|
36
|
+
// @matter
|
|
9
37
|
import { DeviceTypeId, LogLevel as MatterLogLevel, LogFormat as MatterLogFormat, VendorId, EndpointServer } from '@matter/main';
|
|
10
38
|
import { ServerNode, Endpoint as EndpointNode, Environment, StorageService } from '@matter/main';
|
|
11
39
|
import { BasicInformationCluster } from '@matter/main/clusters';
|
|
@@ -14,11 +42,18 @@ import { GenericSwitchDevice } from '@matter/main/devices';
|
|
|
14
42
|
import { AggregatorEndpoint } from '@matter/main/endpoints';
|
|
15
43
|
import { BridgedDeviceBasicInformationServer, SwitchServer } from '@matter/main/behaviors';
|
|
16
44
|
import { Device, logEndpoint } from '@project-chip/matter.js/device';
|
|
45
|
+
/**
|
|
46
|
+
* Represents the MatterbridgeEdge application.
|
|
47
|
+
*/
|
|
17
48
|
export class MatterbridgeEdge extends Matterbridge {
|
|
18
49
|
static instance;
|
|
50
|
+
// Matter environment
|
|
19
51
|
environment = Environment.default;
|
|
52
|
+
// Matter storage
|
|
20
53
|
matterStorageService;
|
|
54
|
+
// Mapping of CommissioningServer to ServerNode
|
|
21
55
|
csToServerNode = new Map();
|
|
56
|
+
// Mapping of Aggregator to AggregatorEndpoint
|
|
22
57
|
agToAggregatorEndpoint = new Map();
|
|
23
58
|
constructor() {
|
|
24
59
|
super();
|
|
@@ -36,24 +71,30 @@ export class MatterbridgeEdge extends Matterbridge {
|
|
|
36
71
|
async initialize() {
|
|
37
72
|
if (hasParameter('debug'))
|
|
38
73
|
console.log('Initializing MatterbridgeEdge...');
|
|
74
|
+
// Set the matterbridge directory
|
|
39
75
|
this.homeDirectory = getParameter('homedir') ?? os.homedir();
|
|
40
76
|
this.matterbridgeDirectory = path.join(this.homeDirectory, '.matterbridge');
|
|
41
77
|
this.matterStorageName = 'matterstorage' + (getParameter('profile') ? '.' + getParameter('profile') : '');
|
|
78
|
+
// Setup matter environment
|
|
42
79
|
this.environment.vars.set('log.level', MatterLogLevel.INFO);
|
|
43
80
|
this.environment.vars.set('log.format', MatterLogFormat.ANSI);
|
|
44
81
|
this.environment.vars.set('path.root', path.join(this.matterbridgeDirectory, this.matterStorageName));
|
|
45
82
|
this.environment.vars.set('runtime.signals', false);
|
|
46
83
|
this.environment.vars.set('runtime.exitcode', false);
|
|
84
|
+
// Setup Matter commissioning server
|
|
47
85
|
this.port = 5540;
|
|
48
86
|
this.passcode = PaseClient.generateRandomPasscode();
|
|
49
87
|
this.discriminator = PaseClient.generateRandomDiscriminator();
|
|
50
88
|
if (hasParameter('debug'))
|
|
51
89
|
console.log(`Initializing server node for Matterbridge... on port ${this.port} with passcode ${this.passcode} and discriminator ${this.discriminator}`);
|
|
90
|
+
// Initialize the base Matterbridge class
|
|
52
91
|
await super.initialize();
|
|
92
|
+
// Setup Matter mdnsInterface
|
|
53
93
|
if (this.mdnsInterface)
|
|
54
94
|
this.environment.vars.set('mdns.networkInterface', this.mdnsInterface);
|
|
55
95
|
}
|
|
56
96
|
async startMatterStorage(storageType, storageName) {
|
|
97
|
+
// Setup Matter storage
|
|
57
98
|
this.log.info(`Starting matter node storage...`);
|
|
58
99
|
this.matterStorageService = this.environment.get(StorageService);
|
|
59
100
|
this.log.info(`Matter node storage service created: ${this.matterStorageService.location}`);
|
|
@@ -61,6 +102,7 @@ export class MatterbridgeEdge extends Matterbridge {
|
|
|
61
102
|
this.log.info('Matter node storage manager "Matterbridge" created');
|
|
62
103
|
this.matterbridgeContext = await this.createServerNodeContext('Matterbridge', 'Matterbridge', bridge.code, this.aggregatorVendorId, 'Matterbridge', this.aggregatorProductId, 'Matterbridge aggregator');
|
|
63
104
|
this.log.info('Matter node storage started');
|
|
105
|
+
// Backup matter storage since it is created/opened correctly
|
|
64
106
|
await this.backupMatterStorage(path.join(this.matterbridgeDirectory, this.matterStorageName), path.join(this.matterbridgeDirectory, this.matterStorageName + '.backup'));
|
|
65
107
|
}
|
|
66
108
|
async backupMatterStorage(storageName, backupName) {
|
|
@@ -76,6 +118,24 @@ export class MatterbridgeEdge extends Matterbridge {
|
|
|
76
118
|
this.matterbridgeContext = undefined;
|
|
77
119
|
this.log.info('Matter node storage closed');
|
|
78
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* Creates a server node storage context.
|
|
123
|
+
*
|
|
124
|
+
* @param pluginName - The name of the plugin.
|
|
125
|
+
* @param deviceName - The name of the device.
|
|
126
|
+
* @param deviceType - The deviceType of the device.
|
|
127
|
+
* @param vendorId - The vendor ID.
|
|
128
|
+
* @param vendorName - The vendor name.
|
|
129
|
+
* @param productId - The product ID.
|
|
130
|
+
* @param productName - The product name.
|
|
131
|
+
* @param serialNumber - The serial number of the device (optional).
|
|
132
|
+
* @param uniqueId - The unique ID of the device (optional).
|
|
133
|
+
* @param softwareVersion - The software version of the device (optional).
|
|
134
|
+
* @param softwareVersionString - The software version string of the device (optional).
|
|
135
|
+
* @param hardwareVersion - The hardware version of the device (optional).
|
|
136
|
+
* @param hardwareVersionString - The hardware version string of the device (optional).
|
|
137
|
+
* @returns The storage context for the commissioning server.
|
|
138
|
+
*/
|
|
79
139
|
async createServerNodeContext(pluginName, deviceName, deviceType, vendorId, vendorName, productId, productName, serialNumber) {
|
|
80
140
|
if (!this.matterStorageService)
|
|
81
141
|
throw new Error('No storage service initialized');
|
|
@@ -117,21 +177,33 @@ export class MatterbridgeEdge extends Matterbridge {
|
|
|
117
177
|
this.log.debug(`- uniqueId: ${await storageContext.get('uniqueId')}`);
|
|
118
178
|
this.log.debug(`- softwareVersion: ${await storageContext.get('softwareVersion')} softwareVersionString: ${await storageContext.get('softwareVersionString')}`);
|
|
119
179
|
this.log.debug(`- hardwareVersion: ${await storageContext.get('hardwareVersion')} hardwareVersionString: ${await storageContext.get('hardwareVersionString')}`);
|
|
180
|
+
/**
|
|
181
|
+
* Create a Matter ServerNode, which contains the Root Endpoint and all relevant data and configuration
|
|
182
|
+
*/
|
|
120
183
|
const serverNode = await ServerNode.create({
|
|
184
|
+
// Required: Give the Node a unique ID which is used to store the state of this node
|
|
121
185
|
id: storeId,
|
|
186
|
+
// Provide Network relevant configuration like the port
|
|
187
|
+
// Optional when operating only one device on a host, Default port is 5540
|
|
122
188
|
network: {
|
|
123
189
|
listeningAddressIpv4: this.ipv4address,
|
|
124
190
|
listeningAddressIpv6: this.ipv6address,
|
|
125
191
|
port,
|
|
126
192
|
},
|
|
193
|
+
// Provide Commissioning relevant settings
|
|
194
|
+
// Optional for development/testing purposes
|
|
127
195
|
commissioning: {
|
|
128
196
|
passcode,
|
|
129
197
|
discriminator,
|
|
130
198
|
},
|
|
199
|
+
// Provide Node announcement settings
|
|
200
|
+
// Optional: If Ommitted some development defaults are used
|
|
131
201
|
productDescription: {
|
|
132
202
|
name: await storageContext.get('deviceName'),
|
|
133
203
|
deviceType: DeviceTypeId(await storageContext.get('deviceType')),
|
|
134
204
|
},
|
|
205
|
+
// Provide defaults for the BasicInformation cluster on the Root endpoint
|
|
206
|
+
// Optional: If Omitted some development defaults are used
|
|
135
207
|
basicInformation: {
|
|
136
208
|
vendorId: VendorId(await storageContext.get('vendorId')),
|
|
137
209
|
vendorName: await storageContext.get('vendorName'),
|
|
@@ -148,6 +220,7 @@ export class MatterbridgeEdge extends Matterbridge {
|
|
|
148
220
|
},
|
|
149
221
|
});
|
|
150
222
|
const sanitizeFabrics = (fabrics) => {
|
|
223
|
+
// New type of fabric information: Record<FabricIndex, ExposedFabricInformation>
|
|
151
224
|
const sanitizedFabrics = this.sanitizeFabricInformations(Array.from(Object.values(fabrics)));
|
|
152
225
|
this.log.info(`Fabrics: ${debugStringify(sanitizedFabrics)}`);
|
|
153
226
|
if (this.bridgeMode === 'bridge') {
|
|
@@ -164,8 +237,14 @@ export class MatterbridgeEdge extends Matterbridge {
|
|
|
164
237
|
}
|
|
165
238
|
}
|
|
166
239
|
};
|
|
240
|
+
/**
|
|
241
|
+
* This event is triggered when the device is initially commissioned successfully.
|
|
242
|
+
* This means: It is added to the first fabric.
|
|
243
|
+
*/
|
|
167
244
|
serverNode.lifecycle.commissioned.on(() => this.log.notice(`Server node for ${storeId} was initially commissioned successfully!`));
|
|
245
|
+
/** This event is triggered when all fabrics are removed from the device, usually it also does a factory reset then. */
|
|
168
246
|
serverNode.lifecycle.decommissioned.on(() => this.log.notice(`Server node for ${storeId} was fully decommissioned successfully!`));
|
|
247
|
+
/** This event is triggered when the device went online. This means that it is discoverable in the network. */
|
|
169
248
|
serverNode.lifecycle.online.on(() => {
|
|
170
249
|
this.log.notice(`Server node for ${storeId} is online`);
|
|
171
250
|
if (!serverNode.lifecycle.isCommissioned) {
|
|
@@ -199,7 +278,9 @@ export class MatterbridgeEdge extends Matterbridge {
|
|
|
199
278
|
this.log.notice(`Server node for ${storeId} is already commissioned. Waiting for controllers to connect ...`);
|
|
200
279
|
sanitizeFabrics(serverNode.state.commissioning.fabrics);
|
|
201
280
|
}
|
|
281
|
+
this.wssSendRefreshRequired();
|
|
202
282
|
});
|
|
283
|
+
/** This event is triggered when the device went offline. it is not longer discoverable or connectable in the network. */
|
|
203
284
|
serverNode.lifecycle.offline.on(() => {
|
|
204
285
|
this.log.notice(`Server node for ${storeId} is offline`);
|
|
205
286
|
if (this.bridgeMode === 'bridge') {
|
|
@@ -210,7 +291,12 @@ export class MatterbridgeEdge extends Matterbridge {
|
|
|
210
291
|
this.matterbridgePaired = false;
|
|
211
292
|
this.matterbridgeConnected = false;
|
|
212
293
|
}
|
|
294
|
+
this.wssSendRefreshRequired();
|
|
213
295
|
});
|
|
296
|
+
/**
|
|
297
|
+
* This event is triggered when a fabric is added, removed or updated on the device. Use this if more granular
|
|
298
|
+
* information is needed.
|
|
299
|
+
*/
|
|
214
300
|
serverNode.events.commissioning.fabricsChanged.on((fabricIndex, fabricAction) => {
|
|
215
301
|
let action = '';
|
|
216
302
|
switch (fabricAction) {
|
|
@@ -226,6 +312,7 @@ export class MatterbridgeEdge extends Matterbridge {
|
|
|
226
312
|
}
|
|
227
313
|
this.log.notice(`Commissioned fabric index ${fabricIndex} ${action} on server node for ${storeId}: ${debugStringify(serverNode.state.commissioning.fabrics[fabricIndex])}`);
|
|
228
314
|
sanitizeFabrics(serverNode.state.commissioning.fabrics);
|
|
315
|
+
this.wssSendRefreshRequired();
|
|
229
316
|
});
|
|
230
317
|
const sanitizeSessions = (sessions) => {
|
|
231
318
|
const sanitizedSessions = this.sanitizeSessionInformation(sessions.map((session) => ({
|
|
@@ -242,15 +329,24 @@ export class MatterbridgeEdge extends Matterbridge {
|
|
|
242
329
|
plugin.sessionInformations = sanitizedSessions;
|
|
243
330
|
}
|
|
244
331
|
}
|
|
332
|
+
this.wssSendRefreshRequired();
|
|
245
333
|
};
|
|
334
|
+
/**
|
|
335
|
+
* This event is triggered when an operative new session was opened by a Controller.
|
|
336
|
+
* It is not triggered for the initial commissioning process, just afterwards for real connections.
|
|
337
|
+
*/
|
|
246
338
|
serverNode.events.sessions.opened.on((session) => {
|
|
247
339
|
this.log.notice(`Session opened on server node for ${storeId}: ${debugStringify(session)}`);
|
|
248
340
|
sanitizeSessions(Object.values(serverNode.state.sessions.sessions));
|
|
249
341
|
});
|
|
342
|
+
/**
|
|
343
|
+
* This event is triggered when an operative session is closed by a Controller or because the Device goes offline.
|
|
344
|
+
*/
|
|
250
345
|
serverNode.events.sessions.closed.on((session) => {
|
|
251
346
|
this.log.notice(`Session closed on server node for ${storeId}: ${debugStringify(session)}`);
|
|
252
347
|
sanitizeSessions(Object.values(serverNode.state.sessions.sessions));
|
|
253
348
|
});
|
|
349
|
+
/** This event is triggered when a subscription gets added or removed on an operative session. */
|
|
254
350
|
serverNode.events.sessions.subscriptionsChanged.on((session) => {
|
|
255
351
|
this.log.notice(`Session subscriptions changed on server node for ${storeId}: ${debugStringify(session)}`);
|
|
256
352
|
sanitizeSessions(Object.values(serverNode.state.sessions.sessions));
|
|
@@ -276,11 +372,13 @@ export class MatterbridgeEdge extends Matterbridge {
|
|
|
276
372
|
return aggregatorNode;
|
|
277
373
|
}
|
|
278
374
|
async addBridgedEndpoint(pluginName, device) {
|
|
375
|
+
// Check if the plugin is registered
|
|
279
376
|
const plugin = this.plugins.get(pluginName);
|
|
280
377
|
if (!plugin) {
|
|
281
378
|
this.log.error(`Error adding bridged endpoint ${dev}${device.deviceName}${er} (${zb}${device.id}${er}) plugin ${plg}${pluginName}${er} not found`);
|
|
282
379
|
return;
|
|
283
380
|
}
|
|
381
|
+
// Register and add the device to the matterbridge aggregator node
|
|
284
382
|
if (this.bridgeMode === 'bridge') {
|
|
285
383
|
this.log.info(`Adding ${pluginName}:${device.deviceName} to Matterbridge aggregator node`);
|
|
286
384
|
const aggregatorNode = this.agToAggregatorEndpoint.get('Matterbridge')?.aggregatorNode;
|
|
@@ -298,17 +396,10 @@ export class MatterbridgeEdge extends Matterbridge {
|
|
|
298
396
|
}
|
|
299
397
|
}
|
|
300
398
|
if (plugin.type === 'DynamicPlatform') {
|
|
301
|
-
|
|
302
|
-
plugin.locked = true;
|
|
303
|
-
plugin.storageContext = await this.createServerNodeContext(plugin.name, 'Matterbridge', bridge.code, this.aggregatorVendorId, 'Matterbridge', this.aggregatorProductId, plugin.description);
|
|
304
|
-
plugin.commissioningServer = (await this.createServerNode(plugin.storageContext, this.port++, this.passcode ? this.passcode++ : undefined, this.discriminator ? this.discriminator++ : undefined));
|
|
305
|
-
plugin.aggregator = (await this.createAggregatorNode(plugin.storageContext));
|
|
306
|
-
this.log.debug(`Adding matter aggregator node to server node for plugin ${plg}${plugin.name}${db}`);
|
|
307
|
-
await plugin.commissioningServer.add(plugin.aggregator);
|
|
308
|
-
this.csToServerNode.set(plugin.name, { commissioningServer: plugin.commissioningServer, serverNode: plugin.commissioningServer });
|
|
309
|
-
this.agToAggregatorEndpoint.set(plugin.name, { aggregator: plugin.aggregator, aggregatorNode: plugin.aggregator });
|
|
310
|
-
}
|
|
399
|
+
plugin.locked = true;
|
|
311
400
|
const aggregatorNode = this.agToAggregatorEndpoint.get(pluginName)?.aggregatorNode;
|
|
401
|
+
if (hasParameter('debug') && !aggregatorNode)
|
|
402
|
+
this.log.warn('***aggregator node not found for plugin', plugin.name);
|
|
312
403
|
await aggregatorNode?.add(device);
|
|
313
404
|
}
|
|
314
405
|
}
|
|
@@ -316,16 +407,19 @@ export class MatterbridgeEdge extends Matterbridge {
|
|
|
316
407
|
plugin.registeredDevices++;
|
|
317
408
|
if (plugin.addedDevices !== undefined)
|
|
318
409
|
plugin.addedDevices++;
|
|
410
|
+
// Add the device to the DeviceManager
|
|
319
411
|
this.devices.set(device);
|
|
320
412
|
this.log.info(`Added and registered bridged endpoint (${plugin.registeredDevices}/${plugin.addedDevices}) ${dev}${device.deviceName}${nf} (${dev}${device.id}${nf}) for plugin ${plg}${pluginName}${nf}`);
|
|
321
413
|
}
|
|
322
414
|
async removeBridgedEndpoint(pluginName, device) {
|
|
323
415
|
this.log.debug(`Removing bridged endpoint ${dev}${device.deviceName}${db} (${zb}${device.name}${db}) for plugin ${plg}${pluginName}${db}`);
|
|
416
|
+
// Check if the plugin is registered
|
|
324
417
|
const plugin = this.plugins.get(pluginName);
|
|
325
418
|
if (!plugin) {
|
|
326
419
|
this.log.error(`Error removing bridged endpoint ${dev}${device.deviceName}${er} (${zb}${device.name}${er}) for plugin ${plg}${pluginName}${er}: plugin not found`);
|
|
327
420
|
return;
|
|
328
421
|
}
|
|
422
|
+
// Register and add the device to the matterbridge aggregator node
|
|
329
423
|
if (this.bridgeMode === 'bridge') {
|
|
330
424
|
const aggregatoreNode = this.agToAggregatorEndpoint.get('Matterbridge')?.aggregatorNode;
|
|
331
425
|
if (!aggregatoreNode) {
|
|
@@ -341,6 +435,7 @@ export class MatterbridgeEdge extends Matterbridge {
|
|
|
341
435
|
}
|
|
342
436
|
else if (this.bridgeMode === 'childbridge') {
|
|
343
437
|
if (plugin.type === 'AccessoryPlatform') {
|
|
438
|
+
// Nothing to do
|
|
344
439
|
}
|
|
345
440
|
else if (plugin.type === 'DynamicPlatform') {
|
|
346
441
|
const aggregatoreNode = this.agToAggregatorEndpoint.get(pluginName)?.aggregatorNode;
|
|
@@ -355,6 +450,7 @@ export class MatterbridgeEdge extends Matterbridge {
|
|
|
355
450
|
plugin.registeredDevices--;
|
|
356
451
|
if (plugin.addedDevices !== undefined)
|
|
357
452
|
plugin.addedDevices--;
|
|
453
|
+
// Close the server node
|
|
358
454
|
if (plugin.registeredDevices === 0 && plugin.addedDevices === 0) {
|
|
359
455
|
const serverNode = this.csToServerNode.get(pluginName)?.serverNode;
|
|
360
456
|
if (serverNode)
|
|
@@ -363,6 +459,7 @@ export class MatterbridgeEdge extends Matterbridge {
|
|
|
363
459
|
this.log.info(`Removed server node for plugin ${plg}${pluginName}${nf}`);
|
|
364
460
|
}
|
|
365
461
|
}
|
|
462
|
+
// Remove the device from the DeviceManager
|
|
366
463
|
this.devices.remove(device);
|
|
367
464
|
}
|
|
368
465
|
async removeAllBridgedEndpoints(pluginName) {
|
|
@@ -371,7 +468,31 @@ export class MatterbridgeEdge extends Matterbridge {
|
|
|
371
468
|
await this.removeBridgedEndpoint(pluginName, device);
|
|
372
469
|
}
|
|
373
470
|
}
|
|
374
|
-
|
|
471
|
+
/**
|
|
472
|
+
* temporary override from Matterbridge: will be moved in Matterbridge in 2.0.0
|
|
473
|
+
*/
|
|
474
|
+
async createMatterServer(storageManager) {
|
|
475
|
+
// Create the server node and aggregator node for the Matterbridge plugin
|
|
476
|
+
if (this.bridgeMode === 'childbridge') {
|
|
477
|
+
for (const plugin of this.plugins) {
|
|
478
|
+
if (!plugin.enabled)
|
|
479
|
+
continue;
|
|
480
|
+
if (plugin.type === 'DynamicPlatform') {
|
|
481
|
+
if (hasParameter('debug'))
|
|
482
|
+
this.log.warn(`createMatterServer() => creating server node and aggregator node for plugin ${plugin.name} type ${plugin.type}`);
|
|
483
|
+
plugin.locked = true;
|
|
484
|
+
plugin.storageContext = await this.createServerNodeContext(plugin.name, 'Matterbridge', bridge.code, this.aggregatorVendorId, 'Matterbridge', this.aggregatorProductId, plugin.description);
|
|
485
|
+
plugin.commissioningServer = (await this.createServerNode(plugin.storageContext, this.port++, this.passcode ? this.passcode++ : undefined, this.discriminator ? this.discriminator++ : undefined));
|
|
486
|
+
plugin.aggregator = (await this.createAggregatorNode(plugin.storageContext));
|
|
487
|
+
this.log.debug(`Adding matter aggregator node to server node for plugin ${plg}${plugin.name}${db}`);
|
|
488
|
+
await plugin.commissioningServer.add(plugin.aggregator);
|
|
489
|
+
this.csToServerNode.set(plugin.name, { commissioningServer: plugin.commissioningServer, serverNode: plugin.commissioningServer });
|
|
490
|
+
this.agToAggregatorEndpoint.set(plugin.name, { aggregator: plugin.aggregator, aggregatorNode: plugin.aggregator });
|
|
491
|
+
if (hasParameter('debug'))
|
|
492
|
+
this.log.warn(`createMatterServer() => created server node and aggregator node for plugin ${plugin.name} type ${plugin.type}`);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
375
496
|
if (hasParameter('debug'))
|
|
376
497
|
this.log.warn('createMatterServer() => mock MatterServer.addCommissioningServer()');
|
|
377
498
|
const matterServer = {
|
|
@@ -434,6 +555,7 @@ export class MatterbridgeEdge extends Matterbridge {
|
|
|
434
555
|
const commissioningServer = {
|
|
435
556
|
getPort: () => port,
|
|
436
557
|
addDevice: async (device) => {
|
|
558
|
+
// if (hasParameter('debug')) this.log.warn('CommissioningServer.addDevice()', device.name);
|
|
437
559
|
if (device instanceof Device) {
|
|
438
560
|
if (hasParameter('debug'))
|
|
439
561
|
this.log.warn('CommissioningServer.addDevice() => Device');
|
|
@@ -448,6 +570,7 @@ export class MatterbridgeEdge extends Matterbridge {
|
|
|
448
570
|
await serverNode.add(aggregatorNode);
|
|
449
571
|
if (!this.test) {
|
|
450
572
|
this.test = true;
|
|
573
|
+
// await this.testEndpoints();
|
|
451
574
|
}
|
|
452
575
|
}
|
|
453
576
|
},
|
|
@@ -504,6 +627,37 @@ export class MatterbridgeEdge extends Matterbridge {
|
|
|
504
627
|
const aggregatorNode = this.agToAggregatorEndpoint.get('Matterbridge')?.aggregatorNode;
|
|
505
628
|
if (!aggregatorNode)
|
|
506
629
|
return;
|
|
630
|
+
/*
|
|
631
|
+
this.log.notice(`Creating OnOffLight1`);
|
|
632
|
+
const lightEndpoint = new MatterbridgeEndpoint(onOffLight, { uniqueStorageKey: 'OnOffLight1' }, true);
|
|
633
|
+
lightEndpoint.addDeviceType(bridgedNode);
|
|
634
|
+
lightEndpoint.createDefaultBridgedDeviceBasicInformationClusterServer('OnOffLight 1', '123456789', 0xfff1, 'Matterbridge', 'Light');
|
|
635
|
+
lightEndpoint.addDeviceType(powerSource);
|
|
636
|
+
lightEndpoint.createDefaultPowerSourceWiredClusterServer();
|
|
637
|
+
lightEndpoint.addDeviceType(electricalSensor);
|
|
638
|
+
lightEndpoint.addClusterServer(lightEndpoint.getDefaultElectricalEnergyMeasurementClusterServer());
|
|
639
|
+
lightEndpoint.addClusterServer(lightEndpoint.getDefaultElectricalPowerMeasurementClusterServer());
|
|
640
|
+
lightEndpoint.addRequiredClusterServers(lightEndpoint);
|
|
641
|
+
this.log.notice(`Adding OnOffLight1 to ${await this.matterbridgeContext.get<string>('storeId')} aggregator`);
|
|
642
|
+
await aggregatorNode.add(lightEndpoint);
|
|
643
|
+
logEndpoint(EndpointServer.forEndpoint(lightEndpoint));
|
|
644
|
+
|
|
645
|
+
this.log.notice(`Creating Outlet1`);
|
|
646
|
+
const outletEndpoint = new MatterbridgeEndpoint(onOffOutlet, { uniqueStorageKey: 'OnOffOutlet1' }, true);
|
|
647
|
+
outletEndpoint.addDeviceType(bridgedNode);
|
|
648
|
+
outletEndpoint.createDefaultBridgedDeviceBasicInformationClusterServer('OnOffOutlet 1', '123456789', 0xfff1, 'Matterbridge', 'Outlet');
|
|
649
|
+
outletEndpoint.addDeviceType(powerSource);
|
|
650
|
+
outletEndpoint.createDefaultPowerSourceReplaceableBatteryClusterServer();
|
|
651
|
+
outletEndpoint.addDeviceType(electricalSensor);
|
|
652
|
+
outletEndpoint.addClusterServer(outletEndpoint.getDefaultElectricalEnergyMeasurementClusterServer());
|
|
653
|
+
outletEndpoint.addClusterServer(outletEndpoint.getDefaultElectricalPowerMeasurementClusterServer());
|
|
654
|
+
outletEndpoint.addRequiredClusterServers(outletEndpoint);
|
|
655
|
+
const input0 = outletEndpoint.addChildDeviceTypeWithClusterServer('Input:0', [genericSwitch], undefined, undefined, true);
|
|
656
|
+
const input1 = outletEndpoint.addChildDeviceTypeWithClusterServer('Input:1', [genericSwitch], undefined, undefined, true);
|
|
657
|
+
this.log.notice(`Adding OnOffOutlet1 to ${await this.matterbridgeContext.get<string>('storeId')} aggregator`);
|
|
658
|
+
await aggregatorNode.add(outletEndpoint);
|
|
659
|
+
logEndpoint(EndpointServer.forEndpoint(outletEndpoint));
|
|
660
|
+
*/
|
|
507
661
|
this.log.notice(`Creating switchEnpoint1`);
|
|
508
662
|
const switchEnpoint1 = new EndpointNode(GenericSwitchDevice.with(BridgedDeviceBasicInformationServer, SwitchServer.with('MomentarySwitch', 'MomentarySwitchLongPress', 'MomentarySwitchMultiPress', 'MomentarySwitchRelease')), {
|
|
509
663
|
id: 'GenericSwitch',
|
|
@@ -526,5 +680,398 @@ export class MatterbridgeEdge extends Matterbridge {
|
|
|
526
680
|
this.log.notice(`Adding switchEnpoint1 to ${await this.matterbridgeContext.get('storeId')} aggregator`);
|
|
527
681
|
await aggregatorNode.add(switchEnpoint1);
|
|
528
682
|
logEndpoint(EndpointServer.forEndpoint(switchEnpoint1), { logNotSupportedClusterAttributes: true, logNotSupportedClusterEvents: true, logNotSupportedClusterCommands: true });
|
|
683
|
+
// if (switchEnpoint2.behaviors.has(SwitchServer)) this.log.notice(`SwitchServer found`);
|
|
684
|
+
// switchEnpoint2.act((agent) => agent['switch'].events['initialPress'].emit({ newPosition: 1 }, agent.context));
|
|
685
|
+
/*
|
|
686
|
+
const device = new MatterbridgeEndpoint(genericSwitch, { uniqueStorageKey: 'GenericSwitch 2' }, true);
|
|
687
|
+
device.createDefaultSwitchClusterServer();
|
|
688
|
+
device.addRequiredClusterServers(device);
|
|
689
|
+
await aggregatorNode.add(device);
|
|
690
|
+
logEndpoint(EndpointServer.forEndpoint(device));
|
|
691
|
+
await device.triggerSwitchEvent('Single', this.log);
|
|
692
|
+
await device.triggerSwitchEvent('Double', this.log);
|
|
693
|
+
await device.triggerSwitchEvent('Long', this.log);
|
|
694
|
+
|
|
695
|
+
const device1 = new MatterbridgeEndpoint(genericSwitch, { uniqueStorageKey: 'GenericSwitch 3' }, true);
|
|
696
|
+
device1.createDefaultLatchingSwitchClusterServer();
|
|
697
|
+
device1.addRequiredClusterServers(device1);
|
|
698
|
+
await aggregatorNode.add(device1);
|
|
699
|
+
logEndpoint(EndpointServer.forEndpoint(device1));
|
|
700
|
+
await device1.triggerSwitchEvent('Press', this.log);
|
|
701
|
+
await device1.triggerSwitchEvent('Release', this.log);
|
|
702
|
+
|
|
703
|
+
this.log.notice(`Creating TestLight`);
|
|
704
|
+
const matterbridgeDevice = new MatterbridgeEndpoint(onOffLight, { uniqueStorageKey: 'Test .Light:2' }, true);
|
|
705
|
+
matterbridgeDevice.behaviors.require(MatterbridgeIdentifyServer, {
|
|
706
|
+
identifyTime: 0,
|
|
707
|
+
identifyType: Identify.IdentifyType.None,
|
|
708
|
+
});
|
|
709
|
+
matterbridgeDevice.behaviors.require(GroupsServer);
|
|
710
|
+
matterbridgeDevice.behaviors.require(MatterbridgeOnOffServer, {
|
|
711
|
+
onOff: false,
|
|
712
|
+
});
|
|
713
|
+
matterbridgeDevice.behaviors.require(MatterbridgeLevelControlServer, {
|
|
714
|
+
currentLevel: 0,
|
|
715
|
+
options: { executeIfOff: false },
|
|
716
|
+
});
|
|
717
|
+
matterbridgeDevice.behaviors.require(MatterbridgeColorControlServer.with(ColorControl.Feature.HueSaturation, ColorControl.Feature.Xy, ColorControl.Feature.ColorTemperature), {
|
|
718
|
+
colorCapabilities: { xy: true, hueSaturation: true, colorLoop: false, enhancedHue: false, colorTemperature: true },
|
|
719
|
+
colorMode: ColorControl.ColorMode.ColorTemperatureMireds,
|
|
720
|
+
enhancedColorMode: ColorControl.EnhancedColorMode.ColorTemperatureMireds,
|
|
721
|
+
options: { executeIfOff: false },
|
|
722
|
+
numberOfPrimaries: null,
|
|
723
|
+
currentX: 24939,
|
|
724
|
+
currentY: 24701,
|
|
725
|
+
currentHue: 0,
|
|
726
|
+
currentSaturation: 0,
|
|
727
|
+
colorTemperatureMireds: 450,
|
|
728
|
+
colorTempPhysicalMinMireds: 150,
|
|
729
|
+
colorTempPhysicalMaxMireds: 450,
|
|
730
|
+
coupleColorTempToLevelMinMireds: 150,
|
|
731
|
+
startUpColorTemperatureMireds: null,
|
|
732
|
+
});
|
|
733
|
+
matterbridgeDevice.behaviors.require(BridgedDeviceBasicInformationServer, {
|
|
734
|
+
vendorId: VendorId(await this.matterbridgeContext.get<number>('vendorId')),
|
|
735
|
+
vendorName: await this.matterbridgeContext.get<string>('vendorName'),
|
|
736
|
+
productName: 'TestLight2',
|
|
737
|
+
productLabel: 'TestLight2',
|
|
738
|
+
nodeLabel: 'TestLight2',
|
|
739
|
+
serialNumber: 'SN 0x123456789',
|
|
740
|
+
uniqueId: '0x123456789',
|
|
741
|
+
reachable: true,
|
|
742
|
+
});
|
|
743
|
+
|
|
744
|
+
// await matterbridgeDevice.setTagList(null, 0x07, 1, 'endpoint 2');
|
|
745
|
+
// await matterbridgeDevice.configureColorControlCluster(false, false, true, ColorControl.ColorMode.ColorTemperatureMireds);
|
|
746
|
+
|
|
747
|
+
this.log.notice(`Adding TestLight`);
|
|
748
|
+
await aggregatorNode?.add(matterbridgeDevice);
|
|
749
|
+
|
|
750
|
+
this.log.notice(`Creating switchEnpoint1`);
|
|
751
|
+
const switchEnpoint2 = new EndpointNode(
|
|
752
|
+
GenericSwitchDevice.with(DescriptorServer.with(Descriptor.Feature.TagList), BridgedDeviceBasicInformationServer, SwitchServer.with('MomentarySwitch', 'MomentarySwitchLongPress', 'MomentarySwitchMultiPress', 'MomentarySwitchRelease')),
|
|
753
|
+
{
|
|
754
|
+
id: 'GenericSwitch1',
|
|
755
|
+
descriptor: {
|
|
756
|
+
tagList: [{ mfgCode: null, namespaceId: 0x07, tag: 1, label: 'Switch1' }],
|
|
757
|
+
},
|
|
758
|
+
bridgedDeviceBasicInformation: {
|
|
759
|
+
vendorId: VendorId(await this.matterbridgeContext.get<number>('vendorId')),
|
|
760
|
+
vendorName: await this.matterbridgeContext.get<string>('vendorName'),
|
|
761
|
+
|
|
762
|
+
productName: 'GenericSwitch',
|
|
763
|
+
productLabel: 'GenericSwitch',
|
|
764
|
+
nodeLabel: 'GenericSwitch',
|
|
765
|
+
|
|
766
|
+
serialNumber: 'SN 0x1234567397',
|
|
767
|
+
uniqueId: '0x1234567397',
|
|
768
|
+
reachable: true,
|
|
769
|
+
},
|
|
770
|
+
switch: {
|
|
771
|
+
numberOfPositions: 2,
|
|
772
|
+
currentPosition: 0,
|
|
773
|
+
multiPressMax: 2,
|
|
774
|
+
},
|
|
775
|
+
},
|
|
776
|
+
);
|
|
777
|
+
this.log.notice(`Creating switchEnpoint2`);
|
|
778
|
+
await aggregatorNode?.add(switchEnpoint2);
|
|
779
|
+
*/
|
|
780
|
+
/*
|
|
781
|
+
const lightEndpoint1 = new EndpointNode(ColorTemperatureLightDevice.with(BridgedDeviceBasicInformationServer), {
|
|
782
|
+
// }, MatterbridgeIdentifyServer, MatterbridgeOnOffServer, MatterbridgeLevelControlServer, MatterbridgeColorControlServer), {
|
|
783
|
+
id: 'OnOffLight',
|
|
784
|
+
bridgedDeviceBasicInformation: {
|
|
785
|
+
vendorId: VendorId(await this.matterbridgeContext.get<number>('vendorId')),
|
|
786
|
+
vendorName: await this.matterbridgeContext.get<string>('vendorName'),
|
|
787
|
+
|
|
788
|
+
productName: 'Light',
|
|
789
|
+
productLabel: 'Light',
|
|
790
|
+
nodeLabel: 'Light',
|
|
791
|
+
|
|
792
|
+
serialNumber: 'SN 0x123456789',
|
|
793
|
+
uniqueId: '0x123456789',
|
|
794
|
+
reachable: true,
|
|
795
|
+
},
|
|
796
|
+
levelControl: {
|
|
797
|
+
currentLevel: 0,
|
|
798
|
+
options: { executeIfOff: false, coupleColorTempToLevel: false },
|
|
799
|
+
},
|
|
800
|
+
colorControl: {
|
|
801
|
+
colorTemperatureMireds: 450,
|
|
802
|
+
colorMode: ColorControl.ColorMode.ColorTemperatureMireds,
|
|
803
|
+
colorTempPhysicalMinMireds: 150,
|
|
804
|
+
colorTempPhysicalMaxMireds: 450,
|
|
805
|
+
coupleColorTempToLevelMinMireds: 150,
|
|
806
|
+
startUpColorTemperatureMireds: 450,
|
|
807
|
+
},
|
|
808
|
+
});
|
|
809
|
+
lightEndpoint1.behaviors.require(ColorControlServer.with('ColorTemperature'), {
|
|
810
|
+
colorTemperatureMireds: 450,
|
|
811
|
+
colorMode: ColorControl.ColorMode.ColorTemperatureMireds,
|
|
812
|
+
colorTempPhysicalMinMireds: 150,
|
|
813
|
+
colorTempPhysicalMaxMireds: 450,
|
|
814
|
+
coupleColorTempToLevelMinMireds: 150,
|
|
815
|
+
startUpColorTemperatureMireds: 450,
|
|
816
|
+
});
|
|
817
|
+
await aggregatorNode?.add(lightEndpoint1);
|
|
818
|
+
|
|
819
|
+
/*
|
|
820
|
+
lightEndpoint1.behaviors.require(MatterbridgeIdentifyServer);
|
|
821
|
+
lightEndpoint1.behaviors.require(MatterbridgeOnOffServer);
|
|
822
|
+
lightEndpoint1.behaviors.require(MatterbridgeLevelControlServer);
|
|
823
|
+
lightEndpoint1.behaviors.require(MatterbridgeColorControlServer, {
|
|
824
|
+
colorTemperatureMireds: 250,
|
|
825
|
+
colorMode: ColorControl.ColorMode.ColorTemperatureMireds,
|
|
826
|
+
colorTempPhysicalMinMireds: 150,
|
|
827
|
+
colorTempPhysicalMaxMireds: 450,
|
|
828
|
+
coupleColorTempToLevelMinMireds: 150,
|
|
829
|
+
startUpColorTemperatureMireds: 450,
|
|
830
|
+
});
|
|
831
|
+
await aggregatorNode?.add(lightEndpoint1);
|
|
832
|
+
|
|
833
|
+
this.log.notice(`Creating switchEnpoint2`);
|
|
834
|
+
const switchEnpoint2 = new EndpointNode(GenericSwitchDevice.with(BridgedDeviceBasicInformationServer, SwitchServer.with('MomentarySwitch', 'MomentarySwitchLongPress', 'MomentarySwitchMultiPress', 'MomentarySwitchRelease')), {
|
|
835
|
+
id: 'GenericSwitch',
|
|
836
|
+
bridgedDeviceBasicInformation: {
|
|
837
|
+
vendorId: VendorId(await this.matterbridgeContext.get<number>('vendorId')),
|
|
838
|
+
vendorName: await this.matterbridgeContext.get<string>('vendorName'),
|
|
839
|
+
|
|
840
|
+
productName: 'GenericSwitch',
|
|
841
|
+
productLabel: 'GenericSwitch',
|
|
842
|
+
nodeLabel: 'GenericSwitch',
|
|
843
|
+
|
|
844
|
+
serialNumber: 'SN 0x123456739',
|
|
845
|
+
uniqueId: '0x123456739',
|
|
846
|
+
reachable: true,
|
|
847
|
+
},
|
|
848
|
+
switch: {
|
|
849
|
+
numberOfPositions: 2,
|
|
850
|
+
currentPosition: 0,
|
|
851
|
+
multiPressMax: 2,
|
|
852
|
+
},
|
|
853
|
+
});
|
|
854
|
+
await aggregatorNode?.add(switchEnpoint2);
|
|
855
|
+
*/
|
|
856
|
+
/*
|
|
857
|
+
for (let i = 1; i <= max; i++) {
|
|
858
|
+
this.log.notice(`Creating lightEndpoint${i}`);
|
|
859
|
+
const lightEndpoint = new MatterbridgeEndpoint(onOffLight, { uniqueStorageKey: 'OnOffLight' + i });
|
|
860
|
+
lightEndpoint.addClusterServer(lightEndpoint.getDefaultBridgedDeviceBasicInformationClusterServer('OnOffLight' + i, '123456789', 0xfff1, 'Matterbridge', 'Light'));
|
|
861
|
+
this.log.notice(`Adding lightEndpoint${i} to ${await this.matterbridgeContext.get<string>('storeId')} aggregator`);
|
|
862
|
+
await aggregatorNode?.add(lightEndpoint);
|
|
863
|
+
setInterval(async () => {
|
|
864
|
+
const state = lightEndpoint.getAttribute(OnOffCluster.id, 'onOff');
|
|
865
|
+
lightEndpoint.setAttribute(OnOffCluster.id, 'onOff', !state);
|
|
866
|
+
this.log.notice(`Setting state for lightEndpoint${i} from:`, state, 'to:', !state);
|
|
867
|
+
}, 10000);
|
|
868
|
+
}
|
|
869
|
+
for (let i = 1; i <= max; i++) {
|
|
870
|
+
this.log.notice(`Creating outletEndpoint${i}`);
|
|
871
|
+
const lightEndpoint = new MatterbridgeEndpoint(onOffOutlet, { uniqueStorageKey: 'OnOffOutlet' + i });
|
|
872
|
+
lightEndpoint.addClusterServer(lightEndpoint.getDefaultBridgedDeviceBasicInformationClusterServer('OnOffOutlet' + i, '123456789', 0xfff1, 'Matterbridge', 'Outlet'));
|
|
873
|
+
this.log.notice(`Adding outletEndpoint${i} to ${await this.matterbridgeContext.get<string>('storeId')} aggregator`);
|
|
874
|
+
await aggregatorNode?.add(lightEndpoint);
|
|
875
|
+
setInterval(async () => {
|
|
876
|
+
const state = lightEndpoint.getAttribute(OnOffCluster.id, 'onOff');
|
|
877
|
+
lightEndpoint.setAttribute(OnOffCluster.id, 'onOff', !state);
|
|
878
|
+
this.log.notice(`Setting state for outletEndpoint${i} from:`, state, 'to:', !state);
|
|
879
|
+
}, 10000);
|
|
880
|
+
}
|
|
881
|
+
*/
|
|
529
882
|
}
|
|
530
883
|
}
|
|
884
|
+
/*
|
|
885
|
+
/*
|
|
886
|
+
matterbridgeDevice.behaviors.require(MatterbridgeColorControlServer.with(ColorControl.Feature.HueSaturation, ColorControl.Feature.Xy, ColorControl.Feature.ColorTemperature), {
|
|
887
|
+
colorCapabilities: { xy: true, hueSaturation: true, colorLoop: false, enhancedHue: false, colorTemperature: true },
|
|
888
|
+
colorMode: ColorControl.ColorMode.ColorTemperatureMireds,
|
|
889
|
+
enhancedColorMode: ColorControl.EnhancedColorMode.ColorTemperatureMireds,
|
|
890
|
+
options: { executeIfOff: false },
|
|
891
|
+
numberOfPrimaries: null,
|
|
892
|
+
currentX: 24939,
|
|
893
|
+
currentY: 24701,
|
|
894
|
+
currentHue: 0,
|
|
895
|
+
currentSaturation: 0,
|
|
896
|
+
colorTemperatureMireds: 450,
|
|
897
|
+
colorTempPhysicalMinMireds: 150,
|
|
898
|
+
colorTempPhysicalMaxMireds: 450,
|
|
899
|
+
coupleColorTempToLevelMinMireds: 150,
|
|
900
|
+
startUpColorTemperatureMireds: null,
|
|
901
|
+
});
|
|
902
|
+
matterbridgeDevice.behaviors.require(MatterbridgeColorControlServer.with(ColorControl.Feature.ColorTemperature), {
|
|
903
|
+
colorCapabilities: { xy: false, hueSaturation: false, colorLoop: false, enhancedHue: false, colorTemperature: true },
|
|
904
|
+
colorMode: ColorControl.ColorMode.ColorTemperatureMireds,
|
|
905
|
+
enhancedColorMode: ColorControl.EnhancedColorMode.ColorTemperatureMireds,
|
|
906
|
+
options: { executeIfOff: false },
|
|
907
|
+
numberOfPrimaries: null,
|
|
908
|
+
colorTemperatureMireds: 450,
|
|
909
|
+
colorTempPhysicalMinMireds: 150,
|
|
910
|
+
colorTempPhysicalMaxMireds: 450,
|
|
911
|
+
coupleColorTempToLevelMinMireds: 150,
|
|
912
|
+
startUpColorTemperatureMireds: null,
|
|
913
|
+
});
|
|
914
|
+
*/
|
|
915
|
+
/*
|
|
916
|
+
matterbridgeDevice.behaviors.require(MatterbridgeColorControlServer.with(ColorControl.Feature.HueSaturation, ColorControl.Feature.Xy), {
|
|
917
|
+
colorCapabilities: { xy: true, hueSaturation: true, colorLoop: false, enhancedHue: false, colorTemperature: false },
|
|
918
|
+
colorMode: ColorControl.ColorMode.CurrentHueAndCurrentSaturation,
|
|
919
|
+
enhancedColorMode: ColorControl.EnhancedColorMode.CurrentHueAndCurrentSaturation,
|
|
920
|
+
options: { executeIfOff: false },
|
|
921
|
+
numberOfPrimaries: null,
|
|
922
|
+
currentX: 24939,
|
|
923
|
+
currentY: 24701,
|
|
924
|
+
currentHue: 0,
|
|
925
|
+
currentSaturation: 0,
|
|
926
|
+
});
|
|
927
|
+
// node dist/matterbridgeEdge.js MatterbridgeEdge -debug -ssl -frontend 443
|
|
928
|
+
if (process.argv.includes('MatterbridgeEdge')) {
|
|
929
|
+
const matterbridge = await MatterbridgeEdge.loadInstance(true);
|
|
930
|
+
|
|
931
|
+
process.on('SIGINT', async function () {
|
|
932
|
+
// eslint-disable-next-line no-console
|
|
933
|
+
console.log('Caught interrupt signal');
|
|
934
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
935
|
+
if (matterbridge) await (matterbridge as any).cleanup('shutting down...', false);
|
|
936
|
+
// if (matterbridge && matterbridge.matterServerNode && matterbridge.matterServerNodeContext) await matterbridge.stopServerNode(matterbridge.matterServerNode, matterbridge.matterServerNodeContext);
|
|
937
|
+
const exit = setTimeout(() => {
|
|
938
|
+
// eslint-disable-next-line no-console
|
|
939
|
+
console.log('Exiting after caught interrupt signal');
|
|
940
|
+
process.exit();
|
|
941
|
+
}, 10000);
|
|
942
|
+
exit.unref();
|
|
943
|
+
});
|
|
944
|
+
}
|
|
945
|
+
*/
|
|
946
|
+
/*
|
|
947
|
+
async startBridgeNode(): Promise<void> {
|
|
948
|
+
this.log.notice(`Creating lightEndpoint1`);
|
|
949
|
+
const lightEndpoint1 = new Endpoint(OnOffLightDevice.with(BridgedDeviceBasicInformationServer), {
|
|
950
|
+
id: 'OnOffLight',
|
|
951
|
+
bridgedDeviceBasicInformation: {
|
|
952
|
+
vendorId: VendorId(await storageContext.get<number>('vendorId')),
|
|
953
|
+
vendorName: await storageContext.get<string>('vendorName'),
|
|
954
|
+
|
|
955
|
+
productName: 'Light',
|
|
956
|
+
productLabel: 'Light',
|
|
957
|
+
nodeLabel: 'Light',
|
|
958
|
+
|
|
959
|
+
serialNumber: 'SN 0x123456789',
|
|
960
|
+
uniqueId: '0x123456789',
|
|
961
|
+
reachable: true,
|
|
962
|
+
},
|
|
963
|
+
});
|
|
964
|
+
this.log.notice(`Adding lightEndpoint1 to ${await storageContext.get<string>('storeId')} aggregator`);
|
|
965
|
+
await this.matterAggregatorNode.add(lightEndpoint1);
|
|
966
|
+
// logEndpoint(EndpointServer.forEndpoint(lightEndpoint1));
|
|
967
|
+
|
|
968
|
+
this.log.notice(`Creating switchEnpoint2`);
|
|
969
|
+
const switchEnpoint2 = new Endpoint(GenericSwitchDevice.with(BridgedDeviceBasicInformationServer, SwitchServer.with('MomentarySwitch', 'MomentarySwitchLongPress', 'MomentarySwitchMultiPress', 'MomentarySwitchRelease')), {
|
|
970
|
+
id: 'GenericSwitch',
|
|
971
|
+
bridgedDeviceBasicInformation: {
|
|
972
|
+
vendorId: VendorId(await storageContext.get<number>('vendorId')),
|
|
973
|
+
vendorName: await storageContext.get<string>('vendorName'),
|
|
974
|
+
|
|
975
|
+
productName: 'GenericSwitch',
|
|
976
|
+
productLabel: 'GenericSwitch',
|
|
977
|
+
nodeLabel: 'GenericSwitch',
|
|
978
|
+
|
|
979
|
+
serialNumber: 'SN 0x123456739',
|
|
980
|
+
uniqueId: '0x123456739',
|
|
981
|
+
reachable: true,
|
|
982
|
+
},
|
|
983
|
+
switch: {
|
|
984
|
+
numberOfPositions: 2,
|
|
985
|
+
currentPosition: 0,
|
|
986
|
+
multiPressMax: 2,
|
|
987
|
+
},
|
|
988
|
+
});
|
|
989
|
+
this.log.notice(`Adding switchEnpoint2 to ${await storageContext.get<string>('storeId')} aggregator`);
|
|
990
|
+
await this.matterAggregatorNode.add(switchEnpoint2);
|
|
991
|
+
// logEndpoint(EndpointServer.forEndpoint(switchEnpoint2));
|
|
992
|
+
|
|
993
|
+
// switchEnpoint2.events.identify.startIdentifying.on(() => this.log.notice('GenericSwitch.identify logic, ideally blink a light every 0.5s ...'));
|
|
994
|
+
// switchEnpoint2.events.switch.currentPosition$Changed.on(() => this.log.notice('GenericSwitch.currentPosition changed ...'));
|
|
995
|
+
// switchEnpoint2.act((agent) => agent.switch.events.initialPress.emit({ newPosition: 1 }, agent.context));
|
|
996
|
+
// switchEnpoint2.events.switch.emit('initialPress', { newPosition: 1 }, switchEnpoint2.events.switch.context);
|
|
997
|
+
*/
|
|
998
|
+
/*
|
|
999
|
+
log.notice(`Creating matterbridge device ClimateSensor`);
|
|
1000
|
+
const matterbridgeDevice3 = new MatterbridgeDeviceV8(DeviceTypes.TEMPERATURE_SENSOR, { uniqueStorageKey: 'ClimateSensor' });
|
|
1001
|
+
matterbridgeDevice3.addDeviceTypeWithClusterServer([DeviceTypes.TEMPERATURE_SENSOR], [TemperatureMeasurement.Cluster.id]);
|
|
1002
|
+
matterbridgeDevice3.addDeviceTypeWithClusterServer([DeviceTypes.HUMIDITY_SENSOR], [RelativeHumidityMeasurement.Cluster.id]);
|
|
1003
|
+
matterbridgeDevice3.addDeviceTypeWithClusterServer([DeviceTypes.PRESSURE_SENSOR], [PressureMeasurement.Cluster.id]);
|
|
1004
|
+
matterbridgeDevice3.behaviors.require(IdentifyServer, {
|
|
1005
|
+
identifyTime: 5,
|
|
1006
|
+
});
|
|
1007
|
+
matterbridgeDevice3.behaviors.require(TemperatureMeasurementServer, {
|
|
1008
|
+
measuredValue: 25.0,
|
|
1009
|
+
minMeasuredValue: null,
|
|
1010
|
+
maxMeasuredValue: null,
|
|
1011
|
+
});
|
|
1012
|
+
*/
|
|
1013
|
+
/*
|
|
1014
|
+
log.notice(`Adding BridgedDeviceBasicInformationServer to ClimateSensor`);
|
|
1015
|
+
matterbridgeDevice3.behaviors.require(BridgedDeviceBasicInformationServer, {
|
|
1016
|
+
vendorId: VendorId(await storageContext.get<number>('vendorId')),
|
|
1017
|
+
vendorName: await storageContext.get<string>('vendorName'),
|
|
1018
|
+
|
|
1019
|
+
productName: 'ClimateSensor',
|
|
1020
|
+
productLabel: 'ClimateSensor',
|
|
1021
|
+
nodeLabel: 'ClimateSensor',
|
|
1022
|
+
|
|
1023
|
+
serialNumber: '0x145433356739',
|
|
1024
|
+
uniqueId: '0x1254446739',
|
|
1025
|
+
reachable: true,
|
|
1026
|
+
});
|
|
1027
|
+
|
|
1028
|
+
log.notice(`Adding DescriptorServer to ClimateSensor`);
|
|
1029
|
+
matterbridgeDevice3.behaviors.require(DescriptorServer, {
|
|
1030
|
+
deviceTypeList: [
|
|
1031
|
+
{ deviceType: 0x0302, revision: 2 },
|
|
1032
|
+
{ deviceType: 0x0307, revision: 2 },
|
|
1033
|
+
{ deviceType: 0x0305, revision: 2 },
|
|
1034
|
+
],
|
|
1035
|
+
});
|
|
1036
|
+
|
|
1037
|
+
this.log.notice(`Adding ClimateSensor to ${await storageContext.get<string>('storeId')} aggregator`);
|
|
1038
|
+
await this.matterAggregator.add(matterbridgeDevice3);
|
|
1039
|
+
logEndpoint(EndpointServer.forEndpoint(matterbridgeDevice3));
|
|
1040
|
+
*/
|
|
1041
|
+
/*
|
|
1042
|
+
await lightEndpoint1.set({
|
|
1043
|
+
onOff: {
|
|
1044
|
+
onOff: true,
|
|
1045
|
+
},
|
|
1046
|
+
});
|
|
1047
|
+
await switchEnpoint2.set({
|
|
1048
|
+
switch: {
|
|
1049
|
+
currentPosition: 1,
|
|
1050
|
+
},
|
|
1051
|
+
});
|
|
1052
|
+
switchEnpoint2.act((agent) => agent.switch.events.initialPress.emit({ newPosition: 1 }, agent.context));
|
|
1053
|
+
*/
|
|
1054
|
+
/*
|
|
1055
|
+
await matterbridgeDevice3.set({
|
|
1056
|
+
temperatureMeasurement: {
|
|
1057
|
+
measuredValue: 20 * 100,
|
|
1058
|
+
},
|
|
1059
|
+
relativeHumidityMeasurement: {
|
|
1060
|
+
measuredValue: 50 * 100,
|
|
1061
|
+
},
|
|
1062
|
+
});
|
|
1063
|
+
*/
|
|
1064
|
+
// logEndpoint(EndpointServer.forEndpoint(this.matterServerNode));
|
|
1065
|
+
/*
|
|
1066
|
+
logEndpoint(EndpointServer.forEndpoint(this.matterServerNode));
|
|
1067
|
+
logEndpoint(EndpointServer.forEndpoint(matterbridgeDevice3));
|
|
1068
|
+
console.log('matterbridgeDevice3\n', matterbridgeDevice3);
|
|
1069
|
+
console.log('matterbridgeDevice3.events\n', matterbridgeDevice3.events);
|
|
1070
|
+
console.log('matterbridgeDevice3.events.identify\n', matterbridgeDevice3.eventsOf(IdentifyServer));
|
|
1071
|
+
console.log('matterbridgeDevice3.state\n', matterbridgeDevice3.state);
|
|
1072
|
+
console.log('matterbridgeDevice3.state.temperatureMeasurement\n', matterbridgeDevice3.stateOf(TemperatureMeasurementServer));
|
|
1073
|
+
// matterbridgeDevice3.eventsOf(IdentifyServer);
|
|
1074
|
+
// matterbridgeDevice3.events.identify.startIdentifying.on(() => log.notice('Run identify logic, ideally blink a light every 0.5s ...'));
|
|
1075
|
+
}
|
|
1076
|
+
*/
|
|
1077
|
+
//# sourceMappingURL=matterbridgeEdge.js.map
|