matterbridge 1.7.3 → 2.0.0-edge.2

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.
Files changed (102) hide show
  1. package/CHANGELOG.md +25 -1
  2. package/dist/cli.js +3 -39
  3. package/dist/cluster/export.js +0 -2
  4. package/dist/defaultConfigSchema.js +0 -23
  5. package/dist/deviceManager.js +1 -26
  6. package/dist/frontend.js +1203 -0
  7. package/dist/index.js +1 -36
  8. package/dist/logger/export.js +0 -1
  9. package/dist/matter/export.js +0 -5
  10. package/dist/matterbridge.js +516 -2678
  11. package/dist/matterbridgeAccessoryPlatform.js +0 -33
  12. package/dist/matterbridgeBehaviors.js +23 -31
  13. package/dist/matterbridgeDeviceTypes.js +11 -82
  14. package/dist/matterbridgeDynamicPlatform.js +0 -33
  15. package/dist/matterbridgeEndpoint.js +45 -1145
  16. package/dist/matterbridgePlatform.js +14 -145
  17. package/dist/matterbridgeTypes.js +3 -24
  18. package/dist/pluginManager.js +5 -246
  19. package/dist/storage/export.js +0 -1
  20. package/dist/utils/colorUtils.js +2 -205
  21. package/dist/utils/export.js +0 -1
  22. package/dist/utils/utils.js +7 -252
  23. package/frontend/build/asset-manifest.json +3 -3
  24. package/frontend/build/index.html +1 -1
  25. package/frontend/build/static/js/{main.6bbd1772.js → main.6204ae54.js} +3 -3
  26. package/frontend/build/static/js/main.6204ae54.js.map +1 -0
  27. package/npm-shrinkwrap.json +9 -9
  28. package/package.json +2 -3
  29. package/dist/cli.d.ts +0 -25
  30. package/dist/cli.d.ts.map +0 -1
  31. package/dist/cli.js.map +0 -1
  32. package/dist/cluster/export.d.ts +0 -2
  33. package/dist/cluster/export.d.ts.map +0 -1
  34. package/dist/cluster/export.js.map +0 -1
  35. package/dist/defaultConfigSchema.d.ts +0 -27
  36. package/dist/defaultConfigSchema.d.ts.map +0 -1
  37. package/dist/defaultConfigSchema.js.map +0 -1
  38. package/dist/deviceManager.d.ts +0 -46
  39. package/dist/deviceManager.d.ts.map +0 -1
  40. package/dist/deviceManager.js.map +0 -1
  41. package/dist/index.d.ts +0 -40
  42. package/dist/index.d.ts.map +0 -1
  43. package/dist/index.js.map +0 -1
  44. package/dist/logger/export.d.ts +0 -2
  45. package/dist/logger/export.d.ts.map +0 -1
  46. package/dist/logger/export.js.map +0 -1
  47. package/dist/matter/export.d.ts +0 -11
  48. package/dist/matter/export.d.ts.map +0 -1
  49. package/dist/matter/export.js.map +0 -1
  50. package/dist/matterbridge.d.ts +0 -483
  51. package/dist/matterbridge.d.ts.map +0 -1
  52. package/dist/matterbridge.js.map +0 -1
  53. package/dist/matterbridgeAccessoryPlatform.d.ts +0 -39
  54. package/dist/matterbridgeAccessoryPlatform.d.ts.map +0 -1
  55. package/dist/matterbridgeAccessoryPlatform.js.map +0 -1
  56. package/dist/matterbridgeBehaviors.d.ts +0 -942
  57. package/dist/matterbridgeBehaviors.d.ts.map +0 -1
  58. package/dist/matterbridgeBehaviors.js.map +0 -1
  59. package/dist/matterbridgeDevice.d.ts +0 -7077
  60. package/dist/matterbridgeDevice.d.ts.map +0 -1
  61. package/dist/matterbridgeDevice.js +0 -2736
  62. package/dist/matterbridgeDevice.js.map +0 -1
  63. package/dist/matterbridgeDeviceTypes.d.ts +0 -109
  64. package/dist/matterbridgeDeviceTypes.d.ts.map +0 -1
  65. package/dist/matterbridgeDeviceTypes.js.map +0 -1
  66. package/dist/matterbridgeDynamicPlatform.d.ts +0 -39
  67. package/dist/matterbridgeDynamicPlatform.d.ts.map +0 -1
  68. package/dist/matterbridgeDynamicPlatform.js.map +0 -1
  69. package/dist/matterbridgeEdge.d.ts +0 -91
  70. package/dist/matterbridgeEdge.d.ts.map +0 -1
  71. package/dist/matterbridgeEdge.js +0 -1077
  72. package/dist/matterbridgeEdge.js.map +0 -1
  73. package/dist/matterbridgeEndpoint.d.ts +0 -10156
  74. package/dist/matterbridgeEndpoint.d.ts.map +0 -1
  75. package/dist/matterbridgeEndpoint.js.map +0 -1
  76. package/dist/matterbridgePlatform.d.ts +0 -168
  77. package/dist/matterbridgePlatform.d.ts.map +0 -1
  78. package/dist/matterbridgePlatform.js.map +0 -1
  79. package/dist/matterbridgeTypes.d.ts +0 -172
  80. package/dist/matterbridgeTypes.d.ts.map +0 -1
  81. package/dist/matterbridgeTypes.js.map +0 -1
  82. package/dist/matterbridgeWebsocket.d.ts +0 -49
  83. package/dist/matterbridgeWebsocket.d.ts.map +0 -1
  84. package/dist/matterbridgeWebsocket.js +0 -325
  85. package/dist/matterbridgeWebsocket.js.map +0 -1
  86. package/dist/pluginManager.d.ts +0 -238
  87. package/dist/pluginManager.d.ts.map +0 -1
  88. package/dist/pluginManager.js.map +0 -1
  89. package/dist/storage/export.d.ts +0 -2
  90. package/dist/storage/export.d.ts.map +0 -1
  91. package/dist/storage/export.js.map +0 -1
  92. package/dist/utils/colorUtils.d.ts +0 -61
  93. package/dist/utils/colorUtils.d.ts.map +0 -1
  94. package/dist/utils/colorUtils.js.map +0 -1
  95. package/dist/utils/export.d.ts +0 -3
  96. package/dist/utils/export.d.ts.map +0 -1
  97. package/dist/utils/export.js.map +0 -1
  98. package/dist/utils/utils.d.ts +0 -221
  99. package/dist/utils/utils.d.ts.map +0 -1
  100. package/dist/utils/utils.js.map +0 -1
  101. package/frontend/build/static/js/main.6bbd1772.js.map +0 -1
  102. /package/frontend/build/static/js/{main.6bbd1772.js.LICENSE.txt → main.6204ae54.js.LICENSE.txt} +0 -0
@@ -1,1077 +0,0 @@
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
26
- import path from 'path';
27
- import os from 'os';
28
- import { randomBytes } from 'crypto';
29
- // NodeStorage and AnsiLogger modules
30
- import { rs, GREEN, debugStringify, er, zb, nf, db } from 'node-ansi-logger';
31
- // Matterbridge
32
- import { Matterbridge } from './matterbridge.js';
33
- import { bridge } from './matterbridgeDeviceTypes.js';
34
- import { dev, plg } from './matterbridgeTypes.js';
35
- import { copyDirectory, getParameter, hasParameter } from './utils/utils.js';
36
- // @matter
37
- import { DeviceTypeId, LogLevel as MatterLogLevel, LogFormat as MatterLogFormat, VendorId, EndpointServer } from '@matter/main';
38
- import { ServerNode, Endpoint as EndpointNode, Environment, StorageService } from '@matter/main';
39
- import { BasicInformationCluster } from '@matter/main/clusters';
40
- import { FabricAction, MdnsService, PaseClient } from '@matter/main/protocol';
41
- import { GenericSwitchDevice } from '@matter/main/devices';
42
- import { AggregatorEndpoint } from '@matter/main/endpoints';
43
- import { BridgedDeviceBasicInformationServer, SwitchServer } from '@matter/main/behaviors';
44
- import { Device, logEndpoint } from '@project-chip/matter.js/device';
45
- /**
46
- * Represents the MatterbridgeEdge application.
47
- */
48
- export class MatterbridgeEdge extends Matterbridge {
49
- static instance;
50
- // Matter environment
51
- environment = Environment.default;
52
- // Matter storage
53
- matterStorageService;
54
- // Mapping of CommissioningServer to ServerNode
55
- csToServerNode = new Map();
56
- // Mapping of Aggregator to AggregatorEndpoint
57
- agToAggregatorEndpoint = new Map();
58
- constructor() {
59
- super();
60
- }
61
- static async loadInstance(initialize = false) {
62
- if (!MatterbridgeEdge.instance) {
63
- if (hasParameter('debug'))
64
- console.log(GREEN + 'Creating a new instance of MatterbridgeEdge.', initialize ? 'Initializing...' : 'Not initializing...', rs);
65
- MatterbridgeEdge.instance = new MatterbridgeEdge();
66
- if (initialize)
67
- await MatterbridgeEdge.instance.initialize();
68
- }
69
- return MatterbridgeEdge.instance;
70
- }
71
- async initialize() {
72
- if (hasParameter('debug'))
73
- console.log('Initializing MatterbridgeEdge...');
74
- // Set the matterbridge directory
75
- this.homeDirectory = getParameter('homedir') ?? os.homedir();
76
- this.matterbridgeDirectory = path.join(this.homeDirectory, '.matterbridge');
77
- this.matterStorageName = 'matterstorage' + (getParameter('profile') ? '.' + getParameter('profile') : '');
78
- // Setup matter environment
79
- this.environment.vars.set('log.level', MatterLogLevel.INFO);
80
- this.environment.vars.set('log.format', MatterLogFormat.ANSI);
81
- this.environment.vars.set('path.root', path.join(this.matterbridgeDirectory, this.matterStorageName));
82
- this.environment.vars.set('runtime.signals', false);
83
- this.environment.vars.set('runtime.exitcode', false);
84
- // Setup Matter commissioning server
85
- this.port = 5540;
86
- this.passcode = PaseClient.generateRandomPasscode();
87
- this.discriminator = PaseClient.generateRandomDiscriminator();
88
- if (hasParameter('debug'))
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
91
- await super.initialize();
92
- // Setup Matter mdnsInterface
93
- if (this.mdnsInterface)
94
- this.environment.vars.set('mdns.networkInterface', this.mdnsInterface);
95
- }
96
- async startMatterStorage(storageType, storageName) {
97
- // Setup Matter storage
98
- this.log.info(`Starting matter node storage...`);
99
- this.matterStorageService = this.environment.get(StorageService);
100
- this.log.info(`Matter node storage service created: ${this.matterStorageService.location}`);
101
- this.storageManager = await this.matterStorageService.open('Matterbridge');
102
- this.log.info('Matter node storage manager "Matterbridge" created');
103
- this.matterbridgeContext = await this.createServerNodeContext('Matterbridge', 'Matterbridge', bridge.code, this.aggregatorVendorId, 'Matterbridge', this.aggregatorProductId, 'Matterbridge aggregator');
104
- this.log.info('Matter node storage started');
105
- // Backup matter storage since it is created/opened correctly
106
- await this.backupMatterStorage(path.join(this.matterbridgeDirectory, this.matterStorageName), path.join(this.matterbridgeDirectory, this.matterStorageName + '.backup'));
107
- }
108
- async backupMatterStorage(storageName, backupName) {
109
- this.log.info('Creating matter node storage backup...');
110
- await copyDirectory(storageName, backupName);
111
- this.log.info('Created matter node storage backup');
112
- }
113
- async stopMatterStorage() {
114
- this.log.info('Closing matter node storage...');
115
- this.storageManager?.close();
116
- this.matterStorageService = undefined;
117
- this.storageManager = undefined;
118
- this.matterbridgeContext = undefined;
119
- this.log.info('Matter node storage closed');
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
- */
139
- async createServerNodeContext(pluginName, deviceName, deviceType, vendorId, vendorName, productId, productName, serialNumber) {
140
- if (!this.matterStorageService)
141
- throw new Error('No storage service initialized');
142
- this.log.info(`Creating server node storage context "${pluginName}.persist" for ${pluginName}...`);
143
- const storageManager = await this.matterStorageService.open(pluginName);
144
- const storageContext = storageManager.createContext('persist');
145
- const random = randomBytes(8).toString('hex');
146
- await storageContext.set('storeId', pluginName);
147
- await storageContext.set('deviceName', deviceName);
148
- await storageContext.set('deviceType', deviceType);
149
- await storageContext.set('vendorId', vendorId);
150
- await storageContext.set('vendorName', vendorName.slice(0, 32));
151
- await storageContext.set('productId', productId);
152
- await storageContext.set('productName', productName.slice(0, 32));
153
- await storageContext.set('nodeLabel', productName.slice(0, 32));
154
- await storageContext.set('productLabel', productName.slice(0, 32));
155
- await storageContext.set('serialNumber', await storageContext.get('serialNumber', serialNumber ? serialNumber.slice(0, 32) : 'SN' + random));
156
- await storageContext.set('uniqueId', await storageContext.get('uniqueId', 'UI' + random));
157
- await storageContext.set('softwareVersion', this.matterbridgeVersion !== '' && this.matterbridgeVersion.includes('.') ? parseInt(this.matterbridgeVersion.split('.')[0], 10) : 1);
158
- await storageContext.set('softwareVersionString', this.matterbridgeVersion !== '' ? this.matterbridgeVersion : '1.0.0');
159
- await storageContext.set('hardwareVersion', this.systemInformation.osRelease !== '' && this.systemInformation.osRelease.includes('.') ? parseInt(this.systemInformation.osRelease.split('.')[0], 10) : 1);
160
- await storageContext.set('hardwareVersionString', this.systemInformation.osRelease !== '' ? this.systemInformation.osRelease : '1.0.0');
161
- this.log.debug(`Created server node storage context "${pluginName}.persist" for ${pluginName}:`);
162
- this.log.debug(`- storeId: ${await storageContext.get('storeId')}`);
163
- this.log.debug(`- deviceName: ${await storageContext.get('deviceName')}`);
164
- this.log.debug(`- deviceType: ${await storageContext.get('deviceType')}(0x${(await storageContext.get('deviceType'))?.toString(16).padStart(4, '0')})`);
165
- this.log.debug(`- serialNumber: ${await storageContext.get('serialNumber')}`);
166
- this.log.debug(`- uniqueId: ${await storageContext.get('uniqueId')}`);
167
- this.log.debug(`- softwareVersion: ${await storageContext.get('softwareVersion')} softwareVersionString: ${await storageContext.get('softwareVersionString')}`);
168
- this.log.debug(`- hardwareVersion: ${await storageContext.get('hardwareVersion')} hardwareVersionString: ${await storageContext.get('hardwareVersionString')}`);
169
- return storageContext;
170
- }
171
- async createServerNode(storageContext, port = 5540, passcode = 20242025, discriminator = 3850) {
172
- const storeId = await storageContext.get('storeId');
173
- this.log.info(`Creating server node for ${storeId} on port ${port} with passcode ${passcode} and discriminator ${discriminator}...`);
174
- this.log.debug(`- deviceName: ${await storageContext.get('deviceName')}`);
175
- this.log.debug(`- deviceType: ${await storageContext.get('deviceType')}(0x${(await storageContext.get('deviceType'))?.toString(16).padStart(4, '0')})`);
176
- this.log.debug(`- serialNumber: ${await storageContext.get('serialNumber')}`);
177
- this.log.debug(`- uniqueId: ${await storageContext.get('uniqueId')}`);
178
- this.log.debug(`- softwareVersion: ${await storageContext.get('softwareVersion')} softwareVersionString: ${await storageContext.get('softwareVersionString')}`);
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
- */
183
- const serverNode = await ServerNode.create({
184
- // Required: Give the Node a unique ID which is used to store the state of this node
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
188
- network: {
189
- listeningAddressIpv4: this.ipv4address,
190
- listeningAddressIpv6: this.ipv6address,
191
- port,
192
- },
193
- // Provide Commissioning relevant settings
194
- // Optional for development/testing purposes
195
- commissioning: {
196
- passcode,
197
- discriminator,
198
- },
199
- // Provide Node announcement settings
200
- // Optional: If Ommitted some development defaults are used
201
- productDescription: {
202
- name: await storageContext.get('deviceName'),
203
- deviceType: DeviceTypeId(await storageContext.get('deviceType')),
204
- },
205
- // Provide defaults for the BasicInformation cluster on the Root endpoint
206
- // Optional: If Omitted some development defaults are used
207
- basicInformation: {
208
- vendorId: VendorId(await storageContext.get('vendorId')),
209
- vendorName: await storageContext.get('vendorName'),
210
- productId: await storageContext.get('productId'),
211
- productName: await storageContext.get('productName'),
212
- productLabel: await storageContext.get('productName'),
213
- nodeLabel: await storageContext.get('productName'),
214
- serialNumber: await storageContext.get('serialNumber'),
215
- uniqueId: await storageContext.get('uniqueId'),
216
- softwareVersion: await storageContext.get('softwareVersion'),
217
- softwareVersionString: await storageContext.get('softwareVersionString'),
218
- hardwareVersion: await storageContext.get('hardwareVersion'),
219
- hardwareVersionString: await storageContext.get('hardwareVersionString'),
220
- },
221
- });
222
- const sanitizeFabrics = (fabrics) => {
223
- // New type of fabric information: Record<FabricIndex, ExposedFabricInformation>
224
- const sanitizedFabrics = this.sanitizeFabricInformations(Array.from(Object.values(fabrics)));
225
- this.log.info(`Fabrics: ${debugStringify(sanitizedFabrics)}`);
226
- if (this.bridgeMode === 'bridge') {
227
- this.matterbridgeFabricInformations = sanitizedFabrics;
228
- this.matterbridgeSessionInformations = [];
229
- this.matterbridgePaired = true;
230
- }
231
- if (this.bridgeMode === 'childbridge') {
232
- const plugin = this.plugins.get(storeId);
233
- if (plugin) {
234
- plugin.fabricInformations = sanitizedFabrics;
235
- plugin.sessionInformations = [];
236
- plugin.paired = true;
237
- }
238
- }
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
- */
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. */
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. */
248
- serverNode.lifecycle.online.on(() => {
249
- this.log.notice(`Server node for ${storeId} is online`);
250
- if (!serverNode.lifecycle.isCommissioned) {
251
- this.log.notice(`Server node for ${storeId} is not commissioned. Pair to commission ...`);
252
- const { qrPairingCode, manualPairingCode } = serverNode.state.commissioning.pairingCodes;
253
- if (this.bridgeMode === 'bridge') {
254
- this.matterbridgeQrPairingCode = qrPairingCode;
255
- this.matterbridgeManualPairingCode = manualPairingCode;
256
- this.matterbridgeFabricInformations = [];
257
- this.matterbridgeSessionInformations = [];
258
- this.matterbridgePaired = false;
259
- this.matterbridgeConnected = false;
260
- this.log.notice(`QR Code URL: https://project-chip.github.io/connectedhomeip/qrcode.html?data=${qrPairingCode}`);
261
- this.log.notice(`Manual pairing code: ${manualPairingCode}`);
262
- }
263
- if (this.bridgeMode === 'childbridge') {
264
- const plugin = this.plugins.get(storeId);
265
- if (plugin) {
266
- plugin.qrPairingCode = qrPairingCode;
267
- plugin.manualPairingCode = manualPairingCode;
268
- plugin.fabricInformations = [];
269
- plugin.sessionInformations = [];
270
- plugin.paired = false;
271
- plugin.connected = false;
272
- this.log.notice(`QR Code URL: https://project-chip.github.io/connectedhomeip/qrcode.html?data=${qrPairingCode}`);
273
- this.log.notice(`Manual pairing code: ${manualPairingCode}`);
274
- }
275
- }
276
- }
277
- else {
278
- this.log.notice(`Server node for ${storeId} is already commissioned. Waiting for controllers to connect ...`);
279
- sanitizeFabrics(serverNode.state.commissioning.fabrics);
280
- }
281
- this.wssSendRefreshRequired();
282
- });
283
- /** This event is triggered when the device went offline. it is not longer discoverable or connectable in the network. */
284
- serverNode.lifecycle.offline.on(() => {
285
- this.log.notice(`Server node for ${storeId} is offline`);
286
- if (this.bridgeMode === 'bridge') {
287
- this.matterbridgeQrPairingCode = undefined;
288
- this.matterbridgeManualPairingCode = undefined;
289
- this.matterbridgeFabricInformations = [];
290
- this.matterbridgeSessionInformations = [];
291
- this.matterbridgePaired = false;
292
- this.matterbridgeConnected = false;
293
- }
294
- this.wssSendRefreshRequired();
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
- */
300
- serverNode.events.commissioning.fabricsChanged.on((fabricIndex, fabricAction) => {
301
- let action = '';
302
- switch (fabricAction) {
303
- case FabricAction.Added:
304
- action = 'added';
305
- break;
306
- case FabricAction.Removed:
307
- action = 'removed';
308
- break;
309
- case FabricAction.Updated:
310
- action = 'updated';
311
- break;
312
- }
313
- this.log.notice(`Commissioned fabric index ${fabricIndex} ${action} on server node for ${storeId}: ${debugStringify(serverNode.state.commissioning.fabrics[fabricIndex])}`);
314
- sanitizeFabrics(serverNode.state.commissioning.fabrics);
315
- this.wssSendRefreshRequired();
316
- });
317
- const sanitizeSessions = (sessions) => {
318
- const sanitizedSessions = this.sanitizeSessionInformation(sessions.map((session) => ({
319
- ...session,
320
- secure: session.name.startsWith('secure'),
321
- })));
322
- this.log.debug(`Sessions: ${debugStringify(sanitizedSessions)}`);
323
- if (this.bridgeMode === 'bridge') {
324
- this.matterbridgeSessionInformations = sanitizedSessions;
325
- }
326
- if (this.bridgeMode === 'childbridge') {
327
- const plugin = this.plugins.get(storeId);
328
- if (plugin) {
329
- plugin.sessionInformations = sanitizedSessions;
330
- }
331
- }
332
- this.wssSendRefreshRequired();
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
- */
338
- serverNode.events.sessions.opened.on((session) => {
339
- this.log.notice(`Session opened on server node for ${storeId}: ${debugStringify(session)}`);
340
- sanitizeSessions(Object.values(serverNode.state.sessions.sessions));
341
- });
342
- /**
343
- * This event is triggered when an operative session is closed by a Controller or because the Device goes offline.
344
- */
345
- serverNode.events.sessions.closed.on((session) => {
346
- this.log.notice(`Session closed on server node for ${storeId}: ${debugStringify(session)}`);
347
- sanitizeSessions(Object.values(serverNode.state.sessions.sessions));
348
- });
349
- /** This event is triggered when a subscription gets added or removed on an operative session. */
350
- serverNode.events.sessions.subscriptionsChanged.on((session) => {
351
- this.log.notice(`Session subscriptions changed on server node for ${storeId}: ${debugStringify(session)}`);
352
- sanitizeSessions(Object.values(serverNode.state.sessions.sessions));
353
- });
354
- this.log.info(`Created server node for ${storeId}`);
355
- return serverNode;
356
- }
357
- async startServerNode(matterServerNode) {
358
- if (!matterServerNode)
359
- return;
360
- this.log.notice(`Starting ${matterServerNode.id} server node`);
361
- await matterServerNode.start();
362
- }
363
- async stopServerNode(matterServerNode) {
364
- if (!matterServerNode)
365
- return;
366
- this.log.notice(`Closing ${matterServerNode.id} server node`);
367
- await matterServerNode.close();
368
- }
369
- async createAggregatorNode(storageContext) {
370
- this.log.notice(`Creating ${await storageContext.get('storeId')} aggregator `);
371
- const aggregatorNode = new EndpointNode(AggregatorEndpoint, { id: `${await storageContext.get('storeId')}` });
372
- return aggregatorNode;
373
- }
374
- async addBridgedEndpoint(pluginName, device) {
375
- // Check if the plugin is registered
376
- const plugin = this.plugins.get(pluginName);
377
- if (!plugin) {
378
- this.log.error(`Error adding bridged endpoint ${dev}${device.deviceName}${er} (${zb}${device.id}${er}) plugin ${plg}${pluginName}${er} not found`);
379
- return;
380
- }
381
- // Register and add the device to the matterbridge aggregator node
382
- if (this.bridgeMode === 'bridge') {
383
- this.log.info(`Adding ${pluginName}:${device.deviceName} to Matterbridge aggregator node`);
384
- const aggregatorNode = this.agToAggregatorEndpoint.get('Matterbridge')?.aggregatorNode;
385
- await aggregatorNode?.add(device);
386
- }
387
- else if (this.bridgeMode === 'childbridge') {
388
- if (plugin.type === 'AccessoryPlatform') {
389
- if (!plugin.locked && device.deviceName && device.vendorId && device.productId && device.vendorName && device.productName) {
390
- plugin.locked = true;
391
- plugin.storageContext = await this.createServerNodeContext(plugin.name, device.deviceName, DeviceTypeId(device.deviceType), device.vendorId, device.vendorName, device.productId, device.productName);
392
- plugin.commissioningServer = (await this.createServerNode(plugin.storageContext, this.port++, this.passcode ? this.passcode++ : undefined, this.discriminator ? this.discriminator++ : undefined));
393
- this.log.debug(`Adding matterbridge endpoint to server node for plugin ${plg}${plugin.name}${db}`);
394
- await plugin.commissioningServer.add(device);
395
- this.csToServerNode.set(plugin.name, { commissioningServer: plugin.commissioningServer, serverNode: plugin.commissioningServer });
396
- }
397
- }
398
- if (plugin.type === 'DynamicPlatform') {
399
- plugin.locked = true;
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);
403
- await aggregatorNode?.add(device);
404
- }
405
- }
406
- if (plugin.registeredDevices !== undefined)
407
- plugin.registeredDevices++;
408
- if (plugin.addedDevices !== undefined)
409
- plugin.addedDevices++;
410
- // Add the device to the DeviceManager
411
- this.devices.set(device);
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}`);
413
- }
414
- async removeBridgedEndpoint(pluginName, device) {
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
417
- const plugin = this.plugins.get(pluginName);
418
- if (!plugin) {
419
- this.log.error(`Error removing bridged endpoint ${dev}${device.deviceName}${er} (${zb}${device.name}${er}) for plugin ${plg}${pluginName}${er}: plugin not found`);
420
- return;
421
- }
422
- // Register and add the device to the matterbridge aggregator node
423
- if (this.bridgeMode === 'bridge') {
424
- const aggregatoreNode = this.agToAggregatorEndpoint.get('Matterbridge')?.aggregatorNode;
425
- if (!aggregatoreNode) {
426
- this.log.error(`Error removing bridged endpoint ${dev}${device.deviceName}${er} (${zb}${device.name}${er}) for plugin ${plg}${pluginName}${er}: matterAggregator node not found`);
427
- return;
428
- }
429
- await device.delete();
430
- this.log.info(`Removed bridged endpoint(${plugin.registeredDevices}/${plugin.addedDevices}) ${dev}${device.deviceName}${nf} (${zb}${device.name}${nf}) for plugin ${plg}${pluginName}${nf}`);
431
- if (plugin.registeredDevices !== undefined)
432
- plugin.registeredDevices--;
433
- if (plugin.addedDevices !== undefined)
434
- plugin.addedDevices--;
435
- }
436
- else if (this.bridgeMode === 'childbridge') {
437
- if (plugin.type === 'AccessoryPlatform') {
438
- // Nothing to do
439
- }
440
- else if (plugin.type === 'DynamicPlatform') {
441
- const aggregatoreNode = this.agToAggregatorEndpoint.get(pluginName)?.aggregatorNode;
442
- if (!aggregatoreNode) {
443
- this.log.error(`Error removing bridged endpoint ${dev}${device.deviceName}${er} (${zb}${device.name}${er}) for plugin ${plg}${pluginName}${er}: aggregator not found`);
444
- return;
445
- }
446
- await device.delete();
447
- }
448
- this.log.info(`Removed bridged endpoint(${plugin.registeredDevices}/${plugin.addedDevices}) ${dev}${device.deviceName}${nf} (${zb}${device.name}${nf}) for plugin ${plg}${pluginName}${nf}`);
449
- if (plugin.registeredDevices !== undefined)
450
- plugin.registeredDevices--;
451
- if (plugin.addedDevices !== undefined)
452
- plugin.addedDevices--;
453
- // Close the server node
454
- if (plugin.registeredDevices === 0 && plugin.addedDevices === 0) {
455
- const serverNode = this.csToServerNode.get(pluginName)?.serverNode;
456
- if (serverNode)
457
- await this.stopServerNode(serverNode);
458
- this.csToServerNode.delete(pluginName);
459
- this.log.info(`Removed server node for plugin ${plg}${pluginName}${nf}`);
460
- }
461
- }
462
- // Remove the device from the DeviceManager
463
- this.devices.remove(device);
464
- }
465
- async removeAllBridgedEndpoints(pluginName) {
466
- this.log.debug(`Removing all bridged endpoints for plugin ${plg}${pluginName}${db}`);
467
- for (const device of this.devices.array().filter((device) => device.plugin === pluginName)) {
468
- await this.removeBridgedEndpoint(pluginName, device);
469
- }
470
- }
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
- }
496
- if (hasParameter('debug'))
497
- this.log.warn('createMatterServer() => mock MatterServer.addCommissioningServer()');
498
- const matterServer = {
499
- addCommissioningServer: (commissioningServer, nodeOptions) => {
500
- if (hasParameter('debug'))
501
- this.log.warn('MatterServer.addCommissioningServer() => do nothing');
502
- },
503
- };
504
- return matterServer;
505
- }
506
- async startMatterServer() {
507
- if (hasParameter('debug'))
508
- this.log.warn('startMatterServer() => do nothing');
509
- }
510
- async stopMatterServer() {
511
- if (hasParameter('debug'))
512
- this.log.warn('stopMatterServer() => ...');
513
- this.log.info(`Stopping matter server nodes in ${this.bridgeMode} mode...`);
514
- if (this.bridgeMode === 'bridge') {
515
- const serverNode = this.csToServerNode.get('Matterbridge')?.serverNode;
516
- if (serverNode) {
517
- await this.stopServerNode(serverNode);
518
- this.log.info(`Stopped matter server node Matterbridge`);
519
- }
520
- }
521
- if (this.bridgeMode === 'childbridge') {
522
- for (const plugin of this.plugins.array()) {
523
- const serverNode = this.csToServerNode.get(plugin.name)?.serverNode;
524
- if (serverNode) {
525
- await this.stopServerNode(serverNode);
526
- this.log.info(`Stopped matter server node ${plugin.name}`);
527
- }
528
- }
529
- }
530
- this.log.info('Stopped matter server nodes');
531
- await this.environment.get(MdnsService)[Symbol.asyncDispose]();
532
- this.log.info('Stopped MdnsService');
533
- }
534
- async createCommissioningServerContext(pluginName, deviceName, deviceType, vendorId, vendorName, productId, productName) {
535
- if (hasParameter('debug'))
536
- this.log.warn(`createCommissioningServerContext() for ${pluginName} => createServerNodeContext()`);
537
- const storageContext = this.createServerNodeContext(pluginName, deviceName, deviceType, vendorId, vendorName, productId, productName);
538
- return storageContext;
539
- }
540
- async importCommissioningServerContext(pluginName, device) {
541
- if (hasParameter('debug'))
542
- this.log.warn(`importCommissioningServerContext() for ${pluginName} => createServerNodeContext()`);
543
- const basic = device.getClusterServer(BasicInformationCluster);
544
- if (!basic)
545
- throw new Error('BasicInformationCluster not found');
546
- const storageContext = this.createServerNodeContext(pluginName, basic.getNodeLabelAttribute(), DeviceTypeId(device.deviceType), basic.getVendorIdAttribute(), basic.getVendorNameAttribute(), basic.getProductIdAttribute(), basic.getProductNameAttribute(), basic.attributes.serialNumber?.getLocal());
547
- return storageContext;
548
- }
549
- test = false;
550
- async createCommisioningServer(context, pluginName) {
551
- if (hasParameter('debug'))
552
- this.log.warn(`createCommisioningServer() for ${pluginName} => createServerNode()`);
553
- const port = this.port;
554
- const serverNode = await this.createServerNode(context, this.port++, this.passcode ? this.passcode++ : undefined, this.discriminator ? this.discriminator++ : undefined);
555
- const commissioningServer = {
556
- getPort: () => port,
557
- addDevice: async (device) => {
558
- // if (hasParameter('debug')) this.log.warn('CommissioningServer.addDevice()', device.name);
559
- if (device instanceof Device) {
560
- if (hasParameter('debug'))
561
- this.log.warn('CommissioningServer.addDevice() => Device');
562
- }
563
- else if (device.name === 'MA-aggregator') {
564
- if (hasParameter('debug'))
565
- this.log.warn('CommissioningServer.addDevice() => Aggregator');
566
- const serverNode = this.csToServerNode.get(pluginName)?.serverNode;
567
- const aggregatorNode = this.agToAggregatorEndpoint.get(pluginName)?.aggregatorNode;
568
- if (!serverNode || !aggregatorNode)
569
- return;
570
- await serverNode.add(aggregatorNode);
571
- if (!this.test) {
572
- this.test = true;
573
- // await this.testEndpoints();
574
- }
575
- }
576
- },
577
- };
578
- this.csToServerNode.set(pluginName, { commissioningServer, serverNode });
579
- return commissioningServer;
580
- }
581
- async createMatterAggregator(context, pluginName) {
582
- if (hasParameter('debug'))
583
- this.log.warn(`createMatterAggregator() for ${pluginName} => createAggregatorNode()`);
584
- const aggregatorNode = await this.createAggregatorNode(context);
585
- const aggregator = {
586
- name: 'MA-aggregator',
587
- addBridgedDevice: (device) => {
588
- if (hasParameter('debug'))
589
- this.log.error('****Aggregator.addBridgedDevice() => not inplemented');
590
- },
591
- removeBridgedDevice: (device) => {
592
- if (hasParameter('debug'))
593
- this.log.error('****Aggregator.removeBridgedDevice() => not inplemented');
594
- },
595
- };
596
- this.agToAggregatorEndpoint.set(pluginName, { aggregator, aggregatorNode });
597
- return aggregator;
598
- }
599
- async showCommissioningQRCode(commissioningServer, storageContext, nodeContext, pluginName) {
600
- if (hasParameter('debug'))
601
- this.log.warn(`showCommissioningQRCode() for ${pluginName} => startServerNode()`);
602
- const serverNode = this.csToServerNode.get(pluginName)?.serverNode;
603
- if (!commissioningServer || !storageContext || !serverNode)
604
- return;
605
- await this.startServerNode(serverNode);
606
- }
607
- setCommissioningServerReachability(commissioningServer, reachable) {
608
- if (hasParameter('debug'))
609
- this.log.warn(`setCommissioningServerReachability() => do nothing`);
610
- }
611
- setAggregatorReachability(matterAggregator, reachable) {
612
- if (hasParameter('debug'))
613
- this.log.warn(`setAggregatorReachability() => do nothing`);
614
- }
615
- setDeviceReachability(device, reachable) {
616
- if (hasParameter('debug'))
617
- this.log.warn(`setDeviceReachability() => do nothing`);
618
- }
619
- async startController() {
620
- if (hasParameter('debug'))
621
- this.log.warn(`startController() => do nothing`);
622
- }
623
- async testEndpoints() {
624
- const max = 10;
625
- if (!this.matterbridgeContext)
626
- return;
627
- const aggregatorNode = this.agToAggregatorEndpoint.get('Matterbridge')?.aggregatorNode;
628
- if (!aggregatorNode)
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
- */
661
- this.log.notice(`Creating switchEnpoint1`);
662
- const switchEnpoint1 = new EndpointNode(GenericSwitchDevice.with(BridgedDeviceBasicInformationServer, SwitchServer.with('MomentarySwitch', 'MomentarySwitchLongPress', 'MomentarySwitchMultiPress', 'MomentarySwitchRelease')), {
663
- id: 'GenericSwitch',
664
- bridgedDeviceBasicInformation: {
665
- vendorId: VendorId(await this.matterbridgeContext.get('vendorId')),
666
- vendorName: await this.matterbridgeContext.get('vendorName'),
667
- productName: 'GenericSwitch',
668
- productLabel: 'GenericSwitch',
669
- nodeLabel: 'GenericSwitch',
670
- serialNumber: 'SN 0x123456739',
671
- uniqueId: '0x123456739',
672
- reachable: true,
673
- },
674
- switch: {
675
- numberOfPositions: 2,
676
- currentPosition: 0,
677
- multiPressMax: 2,
678
- },
679
- });
680
- this.log.notice(`Adding switchEnpoint1 to ${await this.matterbridgeContext.get('storeId')} aggregator`);
681
- await aggregatorNode.add(switchEnpoint1);
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
- */
882
- }
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