matterbridge 1.6.6-dev.9 → 1.6.6

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 +20 -9
  2. package/README-DEV.md +3 -3
  3. package/README.md +4 -0
  4. package/dist/cli.d.ts +25 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +26 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/cluster/export.d.ts +2 -0
  9. package/dist/cluster/export.d.ts.map +1 -0
  10. package/dist/cluster/export.js +2 -0
  11. package/dist/cluster/export.js.map +1 -0
  12. package/dist/defaultConfigSchema.d.ts +27 -0
  13. package/dist/defaultConfigSchema.d.ts.map +1 -0
  14. package/dist/defaultConfigSchema.js +23 -0
  15. package/dist/defaultConfigSchema.js.map +1 -0
  16. package/dist/deviceManager.d.ts +46 -0
  17. package/dist/deviceManager.d.ts.map +1 -0
  18. package/dist/deviceManager.js +26 -1
  19. package/dist/deviceManager.js.map +1 -0
  20. package/dist/index.d.ts +40 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +30 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/logger/export.d.ts +2 -0
  25. package/dist/logger/export.d.ts.map +1 -0
  26. package/dist/logger/export.js +1 -0
  27. package/dist/logger/export.js.map +1 -0
  28. package/dist/matter/export.d.ts +5 -0
  29. package/dist/matter/export.d.ts.map +1 -0
  30. package/dist/matter/export.js +1 -0
  31. package/dist/matter/export.js.map +1 -0
  32. package/dist/matterbridge.d.ts +466 -0
  33. package/dist/matterbridge.d.ts.map +1 -0
  34. package/dist/matterbridge.js +712 -65
  35. package/dist/matterbridge.js.map +1 -0
  36. package/dist/matterbridgeAccessoryPlatform.d.ts +39 -0
  37. package/dist/matterbridgeAccessoryPlatform.d.ts.map +1 -0
  38. package/dist/matterbridgeAccessoryPlatform.js +33 -0
  39. package/dist/matterbridgeAccessoryPlatform.js.map +1 -0
  40. package/dist/matterbridgeBehaviors.d.ts +942 -0
  41. package/dist/matterbridgeBehaviors.d.ts.map +1 -0
  42. package/dist/matterbridgeBehaviors.js +38 -1
  43. package/dist/matterbridgeBehaviors.js.map +1 -0
  44. package/dist/matterbridgeDevice.d.ts +6674 -0
  45. package/dist/matterbridgeDevice.d.ts.map +1 -0
  46. package/dist/matterbridgeDevice.js +1001 -26
  47. package/dist/matterbridgeDevice.js.map +1 -0
  48. package/dist/matterbridgeDeviceTypes.d.ts +82 -0
  49. package/dist/matterbridgeDeviceTypes.d.ts.map +1 -0
  50. package/dist/matterbridgeDeviceTypes.js +59 -13
  51. package/dist/matterbridgeDeviceTypes.js.map +1 -0
  52. package/dist/matterbridgeDynamicPlatform.d.ts +39 -0
  53. package/dist/matterbridgeDynamicPlatform.d.ts.map +1 -0
  54. package/dist/matterbridgeDynamicPlatform.js +33 -0
  55. package/dist/matterbridgeDynamicPlatform.js.map +1 -0
  56. package/dist/matterbridgeEdge.d.ts +89 -0
  57. package/dist/matterbridgeEdge.d.ts.map +1 -0
  58. package/dist/matterbridgeEdge.js +528 -0
  59. package/dist/matterbridgeEdge.js.map +1 -0
  60. package/dist/matterbridgeEndpoint.d.ts +9774 -0
  61. package/dist/matterbridgeEndpoint.d.ts.map +1 -0
  62. package/dist/matterbridgeEndpoint.js +1113 -94
  63. package/dist/matterbridgeEndpoint.js.map +1 -0
  64. package/dist/matterbridgePlatform.d.ts +114 -0
  65. package/dist/matterbridgePlatform.d.ts.map +1 -0
  66. package/dist/matterbridgePlatform.js +115 -10
  67. package/dist/matterbridgePlatform.js.map +1 -0
  68. package/dist/matterbridgeTypes.d.ts +161 -0
  69. package/dist/matterbridgeTypes.d.ts.map +1 -0
  70. package/dist/matterbridgeTypes.js +24 -0
  71. package/dist/matterbridgeTypes.js.map +1 -0
  72. package/dist/matterbridgeWebsocket.d.ts +49 -0
  73. package/dist/matterbridgeWebsocket.d.ts.map +1 -0
  74. package/dist/matterbridgeWebsocket.js +50 -0
  75. package/dist/matterbridgeWebsocket.js.map +1 -0
  76. package/dist/pluginManager.d.ts +238 -0
  77. package/dist/pluginManager.d.ts.map +1 -0
  78. package/dist/pluginManager.js +238 -3
  79. package/dist/pluginManager.js.map +1 -0
  80. package/dist/storage/export.d.ts +2 -0
  81. package/dist/storage/export.d.ts.map +1 -0
  82. package/dist/storage/export.js +1 -0
  83. package/dist/storage/export.js.map +1 -0
  84. package/dist/utils/colorUtils.d.ts +61 -0
  85. package/dist/utils/colorUtils.d.ts.map +1 -0
  86. package/dist/utils/colorUtils.js +236 -89
  87. package/dist/utils/colorUtils.js.map +1 -0
  88. package/dist/utils/export.d.ts +3 -0
  89. package/dist/utils/export.d.ts.map +1 -0
  90. package/dist/utils/export.js +1 -0
  91. package/dist/utils/export.js.map +1 -0
  92. package/dist/utils/utils.d.ts +221 -0
  93. package/dist/utils/utils.d.ts.map +1 -0
  94. package/dist/utils/utils.js +252 -7
  95. package/dist/utils/utils.js.map +1 -0
  96. package/frontend/build/asset-manifest.json +3 -3
  97. package/frontend/build/index.html +1 -1
  98. package/frontend/build/static/js/{main.565ff6ba.js → main.a742de4e.js} +9 -9
  99. package/frontend/build/static/js/{main.565ff6ba.js.map → main.a742de4e.js.map} +1 -1
  100. package/npm-shrinkwrap.json +161 -68
  101. package/package.json +4 -4
  102. /package/frontend/build/static/js/{main.565ff6ba.js.LICENSE.txt → main.a742de4e.js.LICENSE.txt} +0 -0
@@ -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 } 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,12 +42,20 @@ 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();
58
+ // Mapping of sessions
23
59
  activeSessions = new Map();
24
60
  constructor() {
25
61
  super();
@@ -37,19 +73,28 @@ export class MatterbridgeEdge extends Matterbridge {
37
73
  async initialize() {
38
74
  if (hasParameter('debug'))
39
75
  console.log('Initializing MatterbridgeEdge...');
76
+ // Set the matterbridge directory
40
77
  this.homeDirectory = getParameter('homedir') ?? os.homedir();
41
78
  this.matterbridgeDirectory = path.join(this.homeDirectory, '.matterbridge');
42
79
  this.matterStorageName = 'matterstorage' + (getParameter('profile') ? '.' + getParameter('profile') : '');
80
+ // Setup matter environment
43
81
  this.environment.vars.set('log.level', MatterLogLevel.INFO);
44
82
  this.environment.vars.set('log.format', MatterLogFormat.ANSI);
45
83
  this.environment.vars.set('path.root', path.join(this.matterbridgeDirectory, this.matterStorageName));
46
84
  this.environment.vars.set('runtime.signals', false);
47
85
  this.environment.vars.set('runtime.exitcode', false);
86
+ // Initialize the base Matterbridge class
48
87
  await super.initialize();
88
+ // Setup Matter mdnsInterface
49
89
  if (this.mdnsInterface)
50
90
  this.environment.vars.set('mdns.networkInterface', this.mdnsInterface);
91
+ // Setup Matter commissioning server
92
+ // this.port = 5540;
93
+ // this.passcode = PaseClient.generateRandomPasscode();
94
+ // this.discriminator = PaseClient.generateRandomDiscriminator();
51
95
  }
52
96
  async startMatterStorage(storageType, storageName) {
97
+ // Setup Matter storage
53
98
  this.log.info(`Starting matter node storage...`);
54
99
  this.matterStorageService = this.environment.get(StorageService);
55
100
  this.log.info(`Matter node storage service created: ${this.matterStorageService.location}`);
@@ -57,6 +102,7 @@ export class MatterbridgeEdge extends Matterbridge {
57
102
  this.log.info('Matter node storage manager "Matterbridge" created');
58
103
  this.matterbridgeContext = await this.createServerNodeContext('Matterbridge', 'Matterbridge', bridge.code, this.aggregatorVendorId, 'Matterbridge', this.aggregatorProductId, 'Matterbridge aggregator');
59
104
  this.log.info('Matter node storage started');
105
+ // Backup matter storage since it is created/opened correctly
60
106
  await this.backupMatterStorage(path.join(this.matterbridgeDirectory, this.matterStorageName), path.join(this.matterbridgeDirectory, this.matterStorageName + '.backup'));
61
107
  }
62
108
  async backupMatterStorage(storageName, backupName) {
@@ -109,6 +155,24 @@ export class MatterbridgeEdge extends Matterbridge {
109
155
  await this.environment.get(MdnsService)[Symbol.asyncDispose]();
110
156
  this.log.info('Stopped MdnsService');
111
157
  }
158
+ /**
159
+ * Creates a server node storage context.
160
+ *
161
+ * @param pluginName - The name of the plugin.
162
+ * @param deviceName - The name of the device.
163
+ * @param deviceType - The deviceType of the device.
164
+ * @param vendorId - The vendor ID.
165
+ * @param vendorName - The vendor name.
166
+ * @param productId - The product ID.
167
+ * @param productName - The product name.
168
+ * @param serialNumber - The serial number of the device (optional).
169
+ * @param uniqueId - The unique ID of the device (optional).
170
+ * @param softwareVersion - The software version of the device (optional).
171
+ * @param softwareVersionString - The software version string of the device (optional).
172
+ * @param hardwareVersion - The hardware version of the device (optional).
173
+ * @param hardwareVersionString - The hardware version string of the device (optional).
174
+ * @returns The storage context for the commissioning server.
175
+ */
112
176
  async createServerNodeContext(pluginName, deviceName, deviceType, vendorId, vendorName, productId, productName, serialNumber) {
113
177
  if (!this.matterStorageService)
114
178
  throw new Error('No storage service initialized');
@@ -150,21 +214,33 @@ export class MatterbridgeEdge extends Matterbridge {
150
214
  this.log.debug(`- uniqueId: ${await storageContext.get('uniqueId')}`);
151
215
  this.log.debug(`- softwareVersion: ${await storageContext.get('softwareVersion')} softwareVersionString: ${await storageContext.get('softwareVersionString')}`);
152
216
  this.log.debug(`- hardwareVersion: ${await storageContext.get('hardwareVersion')} hardwareVersionString: ${await storageContext.get('hardwareVersionString')}`);
217
+ /**
218
+ * Create a Matter ServerNode, which contains the Root Endpoint and all relevant data and configuration
219
+ */
153
220
  const serverNode = await ServerNode.create({
221
+ // Required: Give the Node a unique ID which is used to store the state of this node
154
222
  id: storeId,
223
+ // Provide Network relevant configuration like the port
224
+ // Optional when operating only one device on a host, Default port is 5540
155
225
  network: {
156
226
  listeningAddressIpv4: this.ipv4address,
157
227
  listeningAddressIpv6: this.ipv6address,
158
228
  port,
159
229
  },
230
+ // Provide Commissioning relevant settings
231
+ // Optional for development/testing purposes
160
232
  commissioning: {
161
233
  passcode,
162
234
  discriminator,
163
235
  },
236
+ // Provide Node announcement settings
237
+ // Optional: If Ommitted some development defaults are used
164
238
  productDescription: {
165
239
  name: await storageContext.get('deviceName'),
166
240
  deviceType: DeviceTypeId(await storageContext.get('deviceType')),
167
241
  },
242
+ // Provide defaults for the BasicInformation cluster on the Root endpoint
243
+ // Optional: If Omitted some development defaults are used
168
244
  basicInformation: {
169
245
  vendorId: VendorId(await storageContext.get('vendorId')),
170
246
  vendorName: await storageContext.get('vendorName'),
@@ -181,6 +257,7 @@ export class MatterbridgeEdge extends Matterbridge {
181
257
  },
182
258
  });
183
259
  const sanitizeFabrics = (fabrics) => {
260
+ // New type of fabric information: Record<FabricIndex, ExposedFabricInformation>
184
261
  const sanitizedFabrics = this.sanitizeFabricInformations(Array.from(Object.values(serverNode.state.commissioning.fabrics)));
185
262
  this.log.info(`Fabrics: ${debugStringify(sanitizedFabrics)}`);
186
263
  if (this.bridgeMode === 'bridge') {
@@ -189,8 +266,14 @@ export class MatterbridgeEdge extends Matterbridge {
189
266
  this.matterbridgePaired = true;
190
267
  }
191
268
  };
269
+ /**
270
+ * This event is triggered when the device is initially commissioned successfully.
271
+ * This means: It is added to the first fabric.
272
+ */
192
273
  serverNode.lifecycle.commissioned.on(() => this.log.notice(`Server node for ${storeId} was initially commissioned successfully!`));
274
+ /** This event is triggered when all fabrics are removed from the device, usually it also does a factory reset then. */
193
275
  serverNode.lifecycle.decommissioned.on(() => this.log.notice(`Server node for ${storeId} was fully decommissioned successfully!`));
276
+ /** This event is triggered when the device went online. This means that it is discoverable in the network. */
194
277
  serverNode.lifecycle.online.on(() => {
195
278
  this.log.notice(`Server node for ${storeId} is online`);
196
279
  if (!serverNode.lifecycle.isCommissioned) {
@@ -212,6 +295,7 @@ export class MatterbridgeEdge extends Matterbridge {
212
295
  sanitizeFabrics(serverNode.state.commissioning.fabrics);
213
296
  }
214
297
  });
298
+ /** This event is triggered when the device went offline. it is not longer discoverable or connectable in the network. */
215
299
  serverNode.lifecycle.offline.on(() => {
216
300
  this.log.notice(`Server node for ${storeId} is offline`);
217
301
  if (this.bridgeMode === 'bridge') {
@@ -223,6 +307,10 @@ export class MatterbridgeEdge extends Matterbridge {
223
307
  this.matterbridgeConnected = false;
224
308
  }
225
309
  });
310
+ /**
311
+ * This event is triggered when a fabric is added, removed or updated on the device. Use this if more granular
312
+ * information is needed.
313
+ */
226
314
  serverNode.events.commissioning.fabricsChanged.on((fabricIndex, fabricAction) => {
227
315
  let action = '';
228
316
  switch (fabricAction) {
@@ -249,14 +337,22 @@ export class MatterbridgeEdge extends Matterbridge {
249
337
  this.matterbridgeSessionInformations = sanitizedSessions;
250
338
  }
251
339
  };
340
+ /**
341
+ * This event is triggered when an operative new session was opened by a Controller.
342
+ * It is not triggered for the initial commissioning process, just afterwards for real connections.
343
+ */
252
344
  serverNode.events.sessions.opened.on((session) => {
253
345
  this.log.notice(`Session opened on server node for ${storeId}: ${debugStringify(session)}`);
254
346
  sanitizeSessions(Object.values(serverNode.state.sessions.sessions));
255
347
  });
348
+ /**
349
+ * This event is triggered when an operative session is closed by a Controller or because the Device goes offline.
350
+ */
256
351
  serverNode.events.sessions.closed.on((session) => {
257
352
  this.log.notice(`Session closed on server node for ${storeId}: ${debugStringify(session)}`);
258
353
  sanitizeSessions(Object.values(serverNode.state.sessions.sessions));
259
354
  });
355
+ /** This event is triggered when a subscription gets added or removed on an operative session. */
260
356
  serverNode.events.sessions.subscriptionsChanged.on((session) => {
261
357
  this.log.notice(`Session subscriptions changed on server node for ${storeId}: ${debugStringify(session)}`);
262
358
  sanitizeSessions(Object.values(serverNode.state.sessions.sessions));
@@ -282,11 +378,13 @@ export class MatterbridgeEdge extends Matterbridge {
282
378
  return aggregator;
283
379
  }
284
380
  async addBridgedEndpoint(pluginName, device) {
381
+ // Check if the plugin is registered
285
382
  const plugin = this.plugins.get(pluginName);
286
383
  if (!plugin) {
287
384
  this.log.error(`Error adding bridged device ${dev}${device.deviceName}${er} (${zb}${device.id}${er}) plugin ${plg}${pluginName}${er} not found`);
288
385
  return;
289
386
  }
387
+ // Register and add the device to the matterbridge aggregator node
290
388
  if (this.bridgeMode === 'bridge') {
291
389
  this.log.info(`Adding ${pluginName}:${device.deviceName} to Matterbridge aggregator node`);
292
390
  const aggregatorNode = this.agToAggregatorEndpoint.get('Matterbridge')?.aggregatorNode;
@@ -299,16 +397,20 @@ export class MatterbridgeEdge extends Matterbridge {
299
397
  await aggregatorNode?.add(device);
300
398
  }
301
399
  }
400
+ // TODO: Implement plugins and devices
302
401
  if (plugin.registeredDevices !== undefined)
303
402
  plugin.registeredDevices++;
304
403
  if (plugin.addedDevices !== undefined)
305
404
  plugin.addedDevices++;
405
+ // Add the device to the DeviceManager
306
406
  this.devices.set(device);
307
407
  this.log.info(`Added and registered bridged device (${plugin.registeredDevices}/${plugin.addedDevices}) ${dev}${device.deviceName}${nf} (${dev}${device.id}${nf}) for plugin ${plg}${pluginName}${nf}`);
308
408
  }
309
409
  async removeBridgedEndpoint(pluginName, device) {
410
+ // TODO: Implement removeBridgedEndpoint
310
411
  }
311
412
  async removeAllBridgedEndpoints(pluginName) {
413
+ // TODO: Implement removeAllBridgedEndpoints
312
414
  }
313
415
  async createCommissioningServerContext(pluginName, deviceName, deviceType, vendorId, vendorName, productId, productName) {
314
416
  if (hasParameter('debug'))
@@ -334,6 +436,7 @@ export class MatterbridgeEdge extends Matterbridge {
334
436
  const commissioningServer = {
335
437
  getPort: () => port,
336
438
  addDevice: async (device) => {
439
+ // if (hasParameter('debug')) this.log.warn('CommissioningServer.addDevice()', device.name);
337
440
  if (device instanceof Device) {
338
441
  if (hasParameter('debug'))
339
442
  this.log.warn('CommissioningServer.addDevice() => Device');
@@ -348,6 +451,7 @@ export class MatterbridgeEdge extends Matterbridge {
348
451
  await serverNode.add(aggregatorNode);
349
452
  if (!this.test) {
350
453
  this.test = true;
454
+ // await this.testEndpoints();
351
455
  }
352
456
  }
353
457
  },
@@ -404,6 +508,37 @@ export class MatterbridgeEdge extends Matterbridge {
404
508
  const aggregatorNode = this.agToAggregatorEndpoint.get('Matterbridge')?.aggregatorNode;
405
509
  if (!aggregatorNode)
406
510
  return;
511
+ /*
512
+ this.log.notice(`Creating OnOffLight1`);
513
+ const lightEndpoint = new MatterbridgeEndpoint(onOffLight, { uniqueStorageKey: 'OnOffLight1' }, true);
514
+ lightEndpoint.addDeviceType(bridgedNode);
515
+ lightEndpoint.createDefaultBridgedDeviceBasicInformationClusterServer('OnOffLight 1', '123456789', 0xfff1, 'Matterbridge', 'Light');
516
+ lightEndpoint.addDeviceType(powerSource);
517
+ lightEndpoint.createDefaultPowerSourceWiredClusterServer();
518
+ lightEndpoint.addDeviceType(electricalSensor);
519
+ lightEndpoint.addClusterServer(lightEndpoint.getDefaultElectricalEnergyMeasurementClusterServer());
520
+ lightEndpoint.addClusterServer(lightEndpoint.getDefaultElectricalPowerMeasurementClusterServer());
521
+ lightEndpoint.addRequiredClusterServers(lightEndpoint);
522
+ this.log.notice(`Adding OnOffLight1 to ${await this.matterbridgeContext.get<string>('storeId')} aggregator`);
523
+ await aggregatorNode.add(lightEndpoint);
524
+ logEndpoint(EndpointServer.forEndpoint(lightEndpoint));
525
+
526
+ this.log.notice(`Creating Outlet1`);
527
+ const outletEndpoint = new MatterbridgeEndpoint(onOffOutlet, { uniqueStorageKey: 'OnOffOutlet1' }, true);
528
+ outletEndpoint.addDeviceType(bridgedNode);
529
+ outletEndpoint.createDefaultBridgedDeviceBasicInformationClusterServer('OnOffOutlet 1', '123456789', 0xfff1, 'Matterbridge', 'Outlet');
530
+ outletEndpoint.addDeviceType(powerSource);
531
+ outletEndpoint.createDefaultPowerSourceReplaceableBatteryClusterServer();
532
+ outletEndpoint.addDeviceType(electricalSensor);
533
+ outletEndpoint.addClusterServer(outletEndpoint.getDefaultElectricalEnergyMeasurementClusterServer());
534
+ outletEndpoint.addClusterServer(outletEndpoint.getDefaultElectricalPowerMeasurementClusterServer());
535
+ outletEndpoint.addRequiredClusterServers(outletEndpoint);
536
+ const input0 = outletEndpoint.addChildDeviceTypeWithClusterServer('Input:0', [genericSwitch], undefined, undefined, true);
537
+ const input1 = outletEndpoint.addChildDeviceTypeWithClusterServer('Input:1', [genericSwitch], undefined, undefined, true);
538
+ this.log.notice(`Adding OnOffOutlet1 to ${await this.matterbridgeContext.get<string>('storeId')} aggregator`);
539
+ await aggregatorNode.add(outletEndpoint);
540
+ logEndpoint(EndpointServer.forEndpoint(outletEndpoint));
541
+ */
407
542
  this.log.notice(`Creating switchEnpoint1`);
408
543
  const switchEnpoint1 = new EndpointNode(GenericSwitchDevice.with(BridgedDeviceBasicInformationServer, SwitchServer.with('MomentarySwitch', 'MomentarySwitchLongPress', 'MomentarySwitchMultiPress', 'MomentarySwitchRelease')), {
409
544
  id: 'GenericSwitch',
@@ -426,5 +561,398 @@ export class MatterbridgeEdge extends Matterbridge {
426
561
  this.log.notice(`Adding switchEnpoint1 to ${await this.matterbridgeContext.get('storeId')} aggregator`);
427
562
  await aggregatorNode.add(switchEnpoint1);
428
563
  logEndpoint(EndpointServer.forEndpoint(switchEnpoint1), { logNotSupportedClusterAttributes: true, logNotSupportedClusterEvents: true, logNotSupportedClusterCommands: true });
564
+ // if (switchEnpoint2.behaviors.has(SwitchServer)) this.log.notice(`SwitchServer found`);
565
+ // switchEnpoint2.act((agent) => agent['switch'].events['initialPress'].emit({ newPosition: 1 }, agent.context));
566
+ /*
567
+ const device = new MatterbridgeEndpoint(genericSwitch, { uniqueStorageKey: 'GenericSwitch 2' }, true);
568
+ device.createDefaultSwitchClusterServer();
569
+ device.addRequiredClusterServers(device);
570
+ await aggregatorNode.add(device);
571
+ logEndpoint(EndpointServer.forEndpoint(device));
572
+ await device.triggerSwitchEvent('Single', this.log);
573
+ await device.triggerSwitchEvent('Double', this.log);
574
+ await device.triggerSwitchEvent('Long', this.log);
575
+
576
+ const device1 = new MatterbridgeEndpoint(genericSwitch, { uniqueStorageKey: 'GenericSwitch 3' }, true);
577
+ device1.createDefaultLatchingSwitchClusterServer();
578
+ device1.addRequiredClusterServers(device1);
579
+ await aggregatorNode.add(device1);
580
+ logEndpoint(EndpointServer.forEndpoint(device1));
581
+ await device1.triggerSwitchEvent('Press', this.log);
582
+ await device1.triggerSwitchEvent('Release', this.log);
583
+
584
+ this.log.notice(`Creating TestLight`);
585
+ const matterbridgeDevice = new MatterbridgeEndpoint(onOffLight, { uniqueStorageKey: 'Test .Light:2' }, true);
586
+ matterbridgeDevice.behaviors.require(MatterbridgeIdentifyServer, {
587
+ identifyTime: 0,
588
+ identifyType: Identify.IdentifyType.None,
589
+ });
590
+ matterbridgeDevice.behaviors.require(GroupsServer);
591
+ matterbridgeDevice.behaviors.require(MatterbridgeOnOffServer, {
592
+ onOff: false,
593
+ });
594
+ matterbridgeDevice.behaviors.require(MatterbridgeLevelControlServer, {
595
+ currentLevel: 0,
596
+ options: { executeIfOff: false },
597
+ });
598
+ matterbridgeDevice.behaviors.require(MatterbridgeColorControlServer.with(ColorControl.Feature.HueSaturation, ColorControl.Feature.Xy, ColorControl.Feature.ColorTemperature), {
599
+ colorCapabilities: { xy: true, hueSaturation: true, colorLoop: false, enhancedHue: false, colorTemperature: true },
600
+ colorMode: ColorControl.ColorMode.ColorTemperatureMireds,
601
+ enhancedColorMode: ColorControl.EnhancedColorMode.ColorTemperatureMireds,
602
+ options: { executeIfOff: false },
603
+ numberOfPrimaries: null,
604
+ currentX: 24939,
605
+ currentY: 24701,
606
+ currentHue: 0,
607
+ currentSaturation: 0,
608
+ colorTemperatureMireds: 450,
609
+ colorTempPhysicalMinMireds: 150,
610
+ colorTempPhysicalMaxMireds: 450,
611
+ coupleColorTempToLevelMinMireds: 150,
612
+ startUpColorTemperatureMireds: null,
613
+ });
614
+ matterbridgeDevice.behaviors.require(BridgedDeviceBasicInformationServer, {
615
+ vendorId: VendorId(await this.matterbridgeContext.get<number>('vendorId')),
616
+ vendorName: await this.matterbridgeContext.get<string>('vendorName'),
617
+ productName: 'TestLight2',
618
+ productLabel: 'TestLight2',
619
+ nodeLabel: 'TestLight2',
620
+ serialNumber: 'SN 0x123456789',
621
+ uniqueId: '0x123456789',
622
+ reachable: true,
623
+ });
624
+
625
+ // await matterbridgeDevice.setTagList(null, 0x07, 1, 'endpoint 2');
626
+ // await matterbridgeDevice.configureColorControlCluster(false, false, true, ColorControl.ColorMode.ColorTemperatureMireds);
627
+
628
+ this.log.notice(`Adding TestLight`);
629
+ await aggregatorNode?.add(matterbridgeDevice);
630
+
631
+ this.log.notice(`Creating switchEnpoint1`);
632
+ const switchEnpoint2 = new EndpointNode(
633
+ GenericSwitchDevice.with(DescriptorServer.with(Descriptor.Feature.TagList), BridgedDeviceBasicInformationServer, SwitchServer.with('MomentarySwitch', 'MomentarySwitchLongPress', 'MomentarySwitchMultiPress', 'MomentarySwitchRelease')),
634
+ {
635
+ id: 'GenericSwitch1',
636
+ descriptor: {
637
+ tagList: [{ mfgCode: null, namespaceId: 0x07, tag: 1, label: 'Switch1' }],
638
+ },
639
+ bridgedDeviceBasicInformation: {
640
+ vendorId: VendorId(await this.matterbridgeContext.get<number>('vendorId')),
641
+ vendorName: await this.matterbridgeContext.get<string>('vendorName'),
642
+
643
+ productName: 'GenericSwitch',
644
+ productLabel: 'GenericSwitch',
645
+ nodeLabel: 'GenericSwitch',
646
+
647
+ serialNumber: 'SN 0x1234567397',
648
+ uniqueId: '0x1234567397',
649
+ reachable: true,
650
+ },
651
+ switch: {
652
+ numberOfPositions: 2,
653
+ currentPosition: 0,
654
+ multiPressMax: 2,
655
+ },
656
+ },
657
+ );
658
+ this.log.notice(`Creating switchEnpoint2`);
659
+ await aggregatorNode?.add(switchEnpoint2);
660
+ */
661
+ /*
662
+ const lightEndpoint1 = new EndpointNode(ColorTemperatureLightDevice.with(BridgedDeviceBasicInformationServer), {
663
+ // }, MatterbridgeIdentifyServer, MatterbridgeOnOffServer, MatterbridgeLevelControlServer, MatterbridgeColorControlServer), {
664
+ id: 'OnOffLight',
665
+ bridgedDeviceBasicInformation: {
666
+ vendorId: VendorId(await this.matterbridgeContext.get<number>('vendorId')),
667
+ vendorName: await this.matterbridgeContext.get<string>('vendorName'),
668
+
669
+ productName: 'Light',
670
+ productLabel: 'Light',
671
+ nodeLabel: 'Light',
672
+
673
+ serialNumber: 'SN 0x123456789',
674
+ uniqueId: '0x123456789',
675
+ reachable: true,
676
+ },
677
+ levelControl: {
678
+ currentLevel: 0,
679
+ options: { executeIfOff: false, coupleColorTempToLevel: false },
680
+ },
681
+ colorControl: {
682
+ colorTemperatureMireds: 450,
683
+ colorMode: ColorControl.ColorMode.ColorTemperatureMireds,
684
+ colorTempPhysicalMinMireds: 150,
685
+ colorTempPhysicalMaxMireds: 450,
686
+ coupleColorTempToLevelMinMireds: 150,
687
+ startUpColorTemperatureMireds: 450,
688
+ },
689
+ });
690
+ lightEndpoint1.behaviors.require(ColorControlServer.with('ColorTemperature'), {
691
+ colorTemperatureMireds: 450,
692
+ colorMode: ColorControl.ColorMode.ColorTemperatureMireds,
693
+ colorTempPhysicalMinMireds: 150,
694
+ colorTempPhysicalMaxMireds: 450,
695
+ coupleColorTempToLevelMinMireds: 150,
696
+ startUpColorTemperatureMireds: 450,
697
+ });
698
+ await aggregatorNode?.add(lightEndpoint1);
699
+
700
+ /*
701
+ lightEndpoint1.behaviors.require(MatterbridgeIdentifyServer);
702
+ lightEndpoint1.behaviors.require(MatterbridgeOnOffServer);
703
+ lightEndpoint1.behaviors.require(MatterbridgeLevelControlServer);
704
+ lightEndpoint1.behaviors.require(MatterbridgeColorControlServer, {
705
+ colorTemperatureMireds: 250,
706
+ colorMode: ColorControl.ColorMode.ColorTemperatureMireds,
707
+ colorTempPhysicalMinMireds: 150,
708
+ colorTempPhysicalMaxMireds: 450,
709
+ coupleColorTempToLevelMinMireds: 150,
710
+ startUpColorTemperatureMireds: 450,
711
+ });
712
+ await aggregatorNode?.add(lightEndpoint1);
713
+
714
+ this.log.notice(`Creating switchEnpoint2`);
715
+ const switchEnpoint2 = new EndpointNode(GenericSwitchDevice.with(BridgedDeviceBasicInformationServer, SwitchServer.with('MomentarySwitch', 'MomentarySwitchLongPress', 'MomentarySwitchMultiPress', 'MomentarySwitchRelease')), {
716
+ id: 'GenericSwitch',
717
+ bridgedDeviceBasicInformation: {
718
+ vendorId: VendorId(await this.matterbridgeContext.get<number>('vendorId')),
719
+ vendorName: await this.matterbridgeContext.get<string>('vendorName'),
720
+
721
+ productName: 'GenericSwitch',
722
+ productLabel: 'GenericSwitch',
723
+ nodeLabel: 'GenericSwitch',
724
+
725
+ serialNumber: 'SN 0x123456739',
726
+ uniqueId: '0x123456739',
727
+ reachable: true,
728
+ },
729
+ switch: {
730
+ numberOfPositions: 2,
731
+ currentPosition: 0,
732
+ multiPressMax: 2,
733
+ },
734
+ });
735
+ await aggregatorNode?.add(switchEnpoint2);
736
+ */
737
+ /*
738
+ for (let i = 1; i <= max; i++) {
739
+ this.log.notice(`Creating lightEndpoint${i}`);
740
+ const lightEndpoint = new MatterbridgeEndpoint(onOffLight, { uniqueStorageKey: 'OnOffLight' + i });
741
+ lightEndpoint.addClusterServer(lightEndpoint.getDefaultBridgedDeviceBasicInformationClusterServer('OnOffLight' + i, '123456789', 0xfff1, 'Matterbridge', 'Light'));
742
+ this.log.notice(`Adding lightEndpoint${i} to ${await this.matterbridgeContext.get<string>('storeId')} aggregator`);
743
+ await aggregatorNode?.add(lightEndpoint);
744
+ setInterval(async () => {
745
+ const state = lightEndpoint.getAttribute(OnOffCluster.id, 'onOff');
746
+ lightEndpoint.setAttribute(OnOffCluster.id, 'onOff', !state);
747
+ this.log.notice(`Setting state for lightEndpoint${i} from:`, state, 'to:', !state);
748
+ }, 10000);
749
+ }
750
+ for (let i = 1; i <= max; i++) {
751
+ this.log.notice(`Creating outletEndpoint${i}`);
752
+ const lightEndpoint = new MatterbridgeEndpoint(onOffOutlet, { uniqueStorageKey: 'OnOffOutlet' + i });
753
+ lightEndpoint.addClusterServer(lightEndpoint.getDefaultBridgedDeviceBasicInformationClusterServer('OnOffOutlet' + i, '123456789', 0xfff1, 'Matterbridge', 'Outlet'));
754
+ this.log.notice(`Adding outletEndpoint${i} to ${await this.matterbridgeContext.get<string>('storeId')} aggregator`);
755
+ await aggregatorNode?.add(lightEndpoint);
756
+ setInterval(async () => {
757
+ const state = lightEndpoint.getAttribute(OnOffCluster.id, 'onOff');
758
+ lightEndpoint.setAttribute(OnOffCluster.id, 'onOff', !state);
759
+ this.log.notice(`Setting state for outletEndpoint${i} from:`, state, 'to:', !state);
760
+ }, 10000);
761
+ }
762
+ */
429
763
  }
430
764
  }
765
+ /*
766
+ /*
767
+ matterbridgeDevice.behaviors.require(MatterbridgeColorControlServer.with(ColorControl.Feature.HueSaturation, ColorControl.Feature.Xy, ColorControl.Feature.ColorTemperature), {
768
+ colorCapabilities: { xy: true, hueSaturation: true, colorLoop: false, enhancedHue: false, colorTemperature: true },
769
+ colorMode: ColorControl.ColorMode.ColorTemperatureMireds,
770
+ enhancedColorMode: ColorControl.EnhancedColorMode.ColorTemperatureMireds,
771
+ options: { executeIfOff: false },
772
+ numberOfPrimaries: null,
773
+ currentX: 24939,
774
+ currentY: 24701,
775
+ currentHue: 0,
776
+ currentSaturation: 0,
777
+ colorTemperatureMireds: 450,
778
+ colorTempPhysicalMinMireds: 150,
779
+ colorTempPhysicalMaxMireds: 450,
780
+ coupleColorTempToLevelMinMireds: 150,
781
+ startUpColorTemperatureMireds: null,
782
+ });
783
+ matterbridgeDevice.behaviors.require(MatterbridgeColorControlServer.with(ColorControl.Feature.ColorTemperature), {
784
+ colorCapabilities: { xy: false, hueSaturation: false, colorLoop: false, enhancedHue: false, colorTemperature: true },
785
+ colorMode: ColorControl.ColorMode.ColorTemperatureMireds,
786
+ enhancedColorMode: ColorControl.EnhancedColorMode.ColorTemperatureMireds,
787
+ options: { executeIfOff: false },
788
+ numberOfPrimaries: null,
789
+ colorTemperatureMireds: 450,
790
+ colorTempPhysicalMinMireds: 150,
791
+ colorTempPhysicalMaxMireds: 450,
792
+ coupleColorTempToLevelMinMireds: 150,
793
+ startUpColorTemperatureMireds: null,
794
+ });
795
+ */
796
+ /*
797
+ matterbridgeDevice.behaviors.require(MatterbridgeColorControlServer.with(ColorControl.Feature.HueSaturation, ColorControl.Feature.Xy), {
798
+ colorCapabilities: { xy: true, hueSaturation: true, colorLoop: false, enhancedHue: false, colorTemperature: false },
799
+ colorMode: ColorControl.ColorMode.CurrentHueAndCurrentSaturation,
800
+ enhancedColorMode: ColorControl.EnhancedColorMode.CurrentHueAndCurrentSaturation,
801
+ options: { executeIfOff: false },
802
+ numberOfPrimaries: null,
803
+ currentX: 24939,
804
+ currentY: 24701,
805
+ currentHue: 0,
806
+ currentSaturation: 0,
807
+ });
808
+ // node dist/matterbridgeEdge.js MatterbridgeEdge -debug -ssl -frontend 443
809
+ if (process.argv.includes('MatterbridgeEdge')) {
810
+ const matterbridge = await MatterbridgeEdge.loadInstance(true);
811
+
812
+ process.on('SIGINT', async function () {
813
+ // eslint-disable-next-line no-console
814
+ console.log('Caught interrupt signal');
815
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
816
+ if (matterbridge) await (matterbridge as any).cleanup('shutting down...', false);
817
+ // if (matterbridge && matterbridge.matterServerNode && matterbridge.matterServerNodeContext) await matterbridge.stopServerNode(matterbridge.matterServerNode, matterbridge.matterServerNodeContext);
818
+ const exit = setTimeout(() => {
819
+ // eslint-disable-next-line no-console
820
+ console.log('Exiting after caught interrupt signal');
821
+ process.exit();
822
+ }, 10000);
823
+ exit.unref();
824
+ });
825
+ }
826
+ */
827
+ /*
828
+ async startBridgeNode(): Promise<void> {
829
+ this.log.notice(`Creating lightEndpoint1`);
830
+ const lightEndpoint1 = new Endpoint(OnOffLightDevice.with(BridgedDeviceBasicInformationServer), {
831
+ id: 'OnOffLight',
832
+ bridgedDeviceBasicInformation: {
833
+ vendorId: VendorId(await storageContext.get<number>('vendorId')),
834
+ vendorName: await storageContext.get<string>('vendorName'),
835
+
836
+ productName: 'Light',
837
+ productLabel: 'Light',
838
+ nodeLabel: 'Light',
839
+
840
+ serialNumber: 'SN 0x123456789',
841
+ uniqueId: '0x123456789',
842
+ reachable: true,
843
+ },
844
+ });
845
+ this.log.notice(`Adding lightEndpoint1 to ${await storageContext.get<string>('storeId')} aggregator`);
846
+ await this.matterAggregatorNode.add(lightEndpoint1);
847
+ // logEndpoint(EndpointServer.forEndpoint(lightEndpoint1));
848
+
849
+ this.log.notice(`Creating switchEnpoint2`);
850
+ const switchEnpoint2 = new Endpoint(GenericSwitchDevice.with(BridgedDeviceBasicInformationServer, SwitchServer.with('MomentarySwitch', 'MomentarySwitchLongPress', 'MomentarySwitchMultiPress', 'MomentarySwitchRelease')), {
851
+ id: 'GenericSwitch',
852
+ bridgedDeviceBasicInformation: {
853
+ vendorId: VendorId(await storageContext.get<number>('vendorId')),
854
+ vendorName: await storageContext.get<string>('vendorName'),
855
+
856
+ productName: 'GenericSwitch',
857
+ productLabel: 'GenericSwitch',
858
+ nodeLabel: 'GenericSwitch',
859
+
860
+ serialNumber: 'SN 0x123456739',
861
+ uniqueId: '0x123456739',
862
+ reachable: true,
863
+ },
864
+ switch: {
865
+ numberOfPositions: 2,
866
+ currentPosition: 0,
867
+ multiPressMax: 2,
868
+ },
869
+ });
870
+ this.log.notice(`Adding switchEnpoint2 to ${await storageContext.get<string>('storeId')} aggregator`);
871
+ await this.matterAggregatorNode.add(switchEnpoint2);
872
+ // logEndpoint(EndpointServer.forEndpoint(switchEnpoint2));
873
+
874
+ // switchEnpoint2.events.identify.startIdentifying.on(() => this.log.notice('GenericSwitch.identify logic, ideally blink a light every 0.5s ...'));
875
+ // switchEnpoint2.events.switch.currentPosition$Changed.on(() => this.log.notice('GenericSwitch.currentPosition changed ...'));
876
+ // switchEnpoint2.act((agent) => agent.switch.events.initialPress.emit({ newPosition: 1 }, agent.context));
877
+ // switchEnpoint2.events.switch.emit('initialPress', { newPosition: 1 }, switchEnpoint2.events.switch.context);
878
+ */
879
+ /*
880
+ log.notice(`Creating matterbridge device ClimateSensor`);
881
+ const matterbridgeDevice3 = new MatterbridgeDeviceV8(DeviceTypes.TEMPERATURE_SENSOR, { uniqueStorageKey: 'ClimateSensor' });
882
+ matterbridgeDevice3.addDeviceTypeWithClusterServer([DeviceTypes.TEMPERATURE_SENSOR], [TemperatureMeasurement.Cluster.id]);
883
+ matterbridgeDevice3.addDeviceTypeWithClusterServer([DeviceTypes.HUMIDITY_SENSOR], [RelativeHumidityMeasurement.Cluster.id]);
884
+ matterbridgeDevice3.addDeviceTypeWithClusterServer([DeviceTypes.PRESSURE_SENSOR], [PressureMeasurement.Cluster.id]);
885
+ matterbridgeDevice3.behaviors.require(IdentifyServer, {
886
+ identifyTime: 5,
887
+ });
888
+ matterbridgeDevice3.behaviors.require(TemperatureMeasurementServer, {
889
+ measuredValue: 25.0,
890
+ minMeasuredValue: null,
891
+ maxMeasuredValue: null,
892
+ });
893
+ */
894
+ /*
895
+ log.notice(`Adding BridgedDeviceBasicInformationServer to ClimateSensor`);
896
+ matterbridgeDevice3.behaviors.require(BridgedDeviceBasicInformationServer, {
897
+ vendorId: VendorId(await storageContext.get<number>('vendorId')),
898
+ vendorName: await storageContext.get<string>('vendorName'),
899
+
900
+ productName: 'ClimateSensor',
901
+ productLabel: 'ClimateSensor',
902
+ nodeLabel: 'ClimateSensor',
903
+
904
+ serialNumber: '0x145433356739',
905
+ uniqueId: '0x1254446739',
906
+ reachable: true,
907
+ });
908
+
909
+ log.notice(`Adding DescriptorServer to ClimateSensor`);
910
+ matterbridgeDevice3.behaviors.require(DescriptorServer, {
911
+ deviceTypeList: [
912
+ { deviceType: 0x0302, revision: 2 },
913
+ { deviceType: 0x0307, revision: 2 },
914
+ { deviceType: 0x0305, revision: 2 },
915
+ ],
916
+ });
917
+
918
+ this.log.notice(`Adding ClimateSensor to ${await storageContext.get<string>('storeId')} aggregator`);
919
+ await this.matterAggregator.add(matterbridgeDevice3);
920
+ logEndpoint(EndpointServer.forEndpoint(matterbridgeDevice3));
921
+ */
922
+ /*
923
+ await lightEndpoint1.set({
924
+ onOff: {
925
+ onOff: true,
926
+ },
927
+ });
928
+ await switchEnpoint2.set({
929
+ switch: {
930
+ currentPosition: 1,
931
+ },
932
+ });
933
+ switchEnpoint2.act((agent) => agent.switch.events.initialPress.emit({ newPosition: 1 }, agent.context));
934
+ */
935
+ /*
936
+ await matterbridgeDevice3.set({
937
+ temperatureMeasurement: {
938
+ measuredValue: 20 * 100,
939
+ },
940
+ relativeHumidityMeasurement: {
941
+ measuredValue: 50 * 100,
942
+ },
943
+ });
944
+ */
945
+ // logEndpoint(EndpointServer.forEndpoint(this.matterServerNode));
946
+ /*
947
+ logEndpoint(EndpointServer.forEndpoint(this.matterServerNode));
948
+ logEndpoint(EndpointServer.forEndpoint(matterbridgeDevice3));
949
+ console.log('matterbridgeDevice3\n', matterbridgeDevice3);
950
+ console.log('matterbridgeDevice3.events\n', matterbridgeDevice3.events);
951
+ console.log('matterbridgeDevice3.events.identify\n', matterbridgeDevice3.eventsOf(IdentifyServer));
952
+ console.log('matterbridgeDevice3.state\n', matterbridgeDevice3.state);
953
+ console.log('matterbridgeDevice3.state.temperatureMeasurement\n', matterbridgeDevice3.stateOf(TemperatureMeasurementServer));
954
+ // matterbridgeDevice3.eventsOf(IdentifyServer);
955
+ // matterbridgeDevice3.events.identify.startIdentifying.on(() => log.notice('Run identify logic, ideally blink a light every 0.5s ...'));
956
+ }
957
+ */
958
+ //# sourceMappingURL=matterbridgeEdge.js.map