matterbridge 1.1.11 → 1.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,13 +2,24 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
- ## [1.1.11] - 2024-03-15
5
+ ## [1.1.12] - 2024-03-22
6
+
7
+ ### Added
8
+
9
+ - [platform]: Added async loadConfig() and async saveConfig() to store plugin config.
10
+ - [platform]: Added a config: Config (JSON) property to platforms to store plugin config.
11
+
12
+ ### Changed
13
+
14
+ - [dependencies]: Updated dependencies.
15
+
16
+ ## [1.1.11] - 2024-03-19
6
17
 
7
18
  ### Added
8
19
 
9
20
  - [frontend]: Frontend got updated to 0.8.3.
10
21
 
11
- ## [1.1.10] - 2024-03-15
22
+ ## [1.1.10] - 2024-03-17
12
23
 
13
24
  ### Added
14
25
 
@@ -17,7 +28,7 @@ All notable changes to this project will be documented in this file.
17
28
  - [frontend]: Enable and disable plugin are now available. Restart Matteerbridge after.
18
29
  - [frontend]: Frontend got updated to 0.8.2.
19
30
 
20
- ## [1.1.9] - 2024-03-15
31
+ ## [1.1.9] - 2024-03-16
21
32
 
22
33
  ### Added
23
34
 
package/README.md CHANGED
@@ -96,9 +96,11 @@ Devices page:
96
96
 
97
97
  ### Accessory platform example
98
98
 
99
- This an example of an accessory platform plugin.
99
+ This an example of an accessory platform plugin.
100
100
 
101
- Accessory platform plugins only expose one device.
101
+ It exposes a cover device that continouosly moves position and shows how to use the command handlers (you can control the device).
102
+
103
+ An Accessory platform plugin only exposes one device.
102
104
 
103
105
  [See the plugin homepage here](https://github.com/Luligu/matterbridge-example-accessory-platform)
104
106
 
@@ -106,7 +108,11 @@ Accessory platform plugins only expose one device.
106
108
 
107
109
  This an example of a dynamic platform plugin.
108
110
 
109
- Dynamic platform plugins expose as many devices as you need (the limit for the Home app is 150 accessories for bridge).
111
+ It exposes a switch with onOff, a light with onOff-levelControl-colorControl, an outlet with onOff and a cover device.
112
+
113
+ All these devices continouosly change state and position. The plugin also shows how to use all the command handlers (you can control all the devices).
114
+
115
+ A Dynamic platform plugin exposes as many devices as you need (the limit for the Home app is 150 accessories for bridge).
110
116
 
111
117
  Matterbridge can run as many plugins as you want.
112
118
 
@@ -124,10 +130,40 @@ Matterbridge can run as many plugins as you want.
124
130
 
125
131
  [Room plugin with history](https://github.com/Luligu/matterbridge-eve-room)
126
132
 
127
- ## How to install a plugin
133
+ ## How to install and register a production-level plugin (from npm)
134
+
135
+ To install i.e. https://github.com/Luligu/matterbridge-zigbee2mqtt
136
+
137
+ On windows:
138
+ ```
139
+ cd $HOME\Matterbridge
140
+ npm install -g matterbridge-zigbee2mqtt
141
+ matterbridge -add matterbridge-zigbee2mqtt
142
+ ```
143
+
144
+ On linux:
145
+ ```
146
+ cd ~/Matterbridge
147
+ sudo npm install -g matterbridge-zigbee2mqtt
148
+ matterbridge -add matterbridge-zigbee2mqtt
149
+ ```
150
+
151
+ ## How to install and register a plugin for development (from git)
128
152
 
129
153
  To install i.e. https://github.com/Luligu/matterbridge-example-accessory-platform
130
154
 
155
+ On windows:
156
+ ```
157
+ cd $HOME\Matterbridge
158
+ ```
159
+
160
+ On linux:
161
+ ```
162
+ cd ~/Matterbridge
163
+ ```
164
+
165
+ then
166
+
131
167
  ```
132
168
  git clone https://github.com/Luligu/matterbridge-example-accessory-platform
133
169
  cd matterbridge-example-accessory-platform
@@ -139,28 +175,28 @@ Then add the plugin to Matterbridge
139
175
  matterbridge -add .\
140
176
  ```
141
177
 
142
- ### How to add a plugin to Matterbridge
178
+ ## How to add a plugin to Matterbridge
143
179
 
144
180
  ```
145
- matterbridge -add .\
181
+ matterbridge -add [plugin path]
146
182
  ```
147
183
 
148
- ### How to remove a plugin from Matterbridge
184
+ ## How to remove a plugin from Matterbridge
149
185
 
150
186
  ```
151
- matterbridge -remove .\
187
+ matterbridge -remove [plugin path]
152
188
  ```
153
189
 
154
- ### How to disable a registerd plugin
190
+ ## How to disable a registered plugin
155
191
 
156
192
  ```
157
- matterbridge -disable .\
193
+ matterbridge -disable [plugin path]
158
194
  ```
159
195
 
160
- ### How to enable a registerd plugin
196
+ ## How to enable a registered plugin
161
197
 
162
198
  ```
163
- matterbridge -enable .\
199
+ matterbridge -enable [plugin path]
164
200
  ```
165
201
 
166
202
  ## How to create your plugin
@@ -178,6 +214,15 @@ Add your plugin logic in platform.ts.
178
214
 
179
215
  ## MatterbridgeDynamicPlatform and MatterbridgeAccessoryPlatform api
180
216
 
217
+ ### name: string
218
+ The plugin name.
219
+
220
+ ### type: string
221
+ The plugin platform type.
222
+
223
+ ### config: object
224
+ The plugin config (loaded before onStart() is called and save after onShutdown() is called).
225
+
181
226
  ### async onStart(reason?: string)
182
227
  The method onStart() is where you have to create your MatterbridgeDevice and add all needed clusters and command handlers.
183
228
 
@@ -204,7 +249,7 @@ You can unregister one or more device.
204
249
  ### async unregisterAllDevices()
205
250
  You can unregister all devices you added.
206
251
 
207
- It can me be useful to call this method from onShutdown if you don't want to keep all the devices.
252
+ It can be useful to call this method from onShutdown() if you don't want to keep all the devices during development.
208
253
 
209
254
  ## MatterbridgeDevice api
210
255
 
@@ -243,7 +243,7 @@ export declare class Matterbridge extends EventEmitter {
243
243
  * Creates a matter commissioning server.
244
244
  *
245
245
  * @param {StorageContext} context - The storage context.
246
- * @param {string} name - The name of the commissioning server.
246
+ * @param {string} pluginName - The name of the commissioning server.
247
247
  * @returns {CommissioningServer} The created commissioning server.
248
248
  */
249
249
  private createCommisioningServer;
@@ -1 +1 @@
1
- {"version":3,"file":"matterbridge.d.ts","sourceRoot":"","sources":["../src/matterbridge.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"matterbridge.d.ts","sourceRoot":"","sources":["../src/matterbridge.ts"],"names":[],"mappings":"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"}
@@ -470,6 +470,8 @@ export class Matterbridge extends EventEmitter {
470
470
  for (const plugin of this.registeredPlugins) {
471
471
  if (plugin.platform)
472
472
  await plugin.platform.onShutdown('Matterbridge is closing: ' + message);
473
+ if (plugin.platform)
474
+ await plugin.platform.saveConfig();
473
475
  }
474
476
  // Set reachability to false
475
477
  /*
@@ -565,14 +567,14 @@ export class Matterbridge extends EventEmitter {
565
567
  */
566
568
  async addDevice(pluginName, device) {
567
569
  if (this.bridgeMode === 'bridge' && !this.matterAggregator) {
568
- this.log.error(`Adding device ${dev}${device.name}-${device.deviceName}${er} for plugin ${plg}${pluginName}${er} error: matterAggregator not found`);
570
+ this.log.error(`Adding device ${dev}${device.deviceName}${er} (${dev}${device.name}${er}) for plugin ${plg}${pluginName}${er} error: matterAggregator not found`);
569
571
  return;
570
572
  }
571
- this.log.debug(`Adding device ${dev}${device.name}-${device.deviceName}${db} for plugin ${plg}${pluginName}${db}`);
573
+ this.log.debug(`Adding device ${dev}${device.deviceName}${db} (${dev}${device.name}${db}) for plugin ${plg}${pluginName}${db}`);
572
574
  // Check if the plugin is registered
573
575
  const plugin = this.registeredPlugins.find((plugin) => plugin.name === pluginName);
574
576
  if (!plugin) {
575
- this.log.error(`Error adding device ${dev}${device.name}-${device.deviceName}${er} plugin ${plg}${pluginName}${er} not found`);
577
+ this.log.error(`Error adding device ${dev}${device.deviceName}${er} (${dev}${device.name}${er}) plugin ${plg}${pluginName}${er} not found`);
576
578
  return;
577
579
  }
578
580
  // Register and add the device to matterbridge aggregator in bridge mode
@@ -583,14 +585,14 @@ export class Matterbridge extends EventEmitter {
583
585
  plugin.registeredDevices++;
584
586
  if (plugin.addedDevices !== undefined)
585
587
  plugin.addedDevices++;
586
- this.log.info(`Added and registered device(${plugin.registeredDevices}/${plugin.addedDevices}) ${dev}${device.name}-${device.deviceName}${nf} for plugin ${plg}${pluginName}${nf}`);
588
+ this.log.info(`Added and registered device (${plugin.registeredDevices}/${plugin.addedDevices}) ${dev}${device.deviceName}${nf} (${dev}${device.name}${nf}) for plugin ${plg}${pluginName}${nf}`);
587
589
  }
588
590
  // Only register the device in childbridge mode
589
591
  if (this.bridgeMode === 'childbridge') {
590
592
  this.registeredDevices.push({ plugin: pluginName, device, added: false });
591
593
  if (plugin.registeredDevices !== undefined)
592
594
  plugin.registeredDevices++;
593
- this.log.info(`Registered device ${dev}${device.name}-${device.deviceName}${nf} for plugin ${plg}${pluginName}${nf}`);
595
+ this.log.info(`Registered device ${dev}${device.deviceName}${nf} (${dev}${device.name}${nf}) for plugin ${plg}${pluginName}${nf}`);
594
596
  }
595
597
  }
596
598
  /**
@@ -601,14 +603,14 @@ export class Matterbridge extends EventEmitter {
601
603
  */
602
604
  async addBridgedDevice(pluginName, device) {
603
605
  if (this.bridgeMode === 'bridge' && !this.matterAggregator) {
604
- this.log.error(`Adding bridged device ${dev}${device.name}-${device.deviceName}${er} for plugin ${plg}${pluginName}${er} error: matterAggregator not found`);
606
+ this.log.error(`Adding bridged device ${dev}${device.deviceName}${er} (${dev}${device.name}${er}) for plugin ${plg}${pluginName}${er} error: matterAggregator not found`);
605
607
  return;
606
608
  }
607
- this.log.debug(`Adding bridged device ${db}${device.name}-${device.deviceName}${nf} for plugin ${plg}${pluginName}${db}`);
609
+ this.log.debug(`Adding bridged device ${dev}${device.deviceName}${db} (${dev}${device.name}${db}) for plugin ${plg}${pluginName}${db}`);
608
610
  // Check if the plugin is registered
609
611
  const plugin = this.registeredPlugins.find((plugin) => plugin.name === pluginName);
610
612
  if (!plugin) {
611
- this.log.error(`Error adding bridged device ${dev}${device.name}-${device.deviceName}${er} plugin ${plg}${pluginName}${er} not found`);
613
+ this.log.error(`Error adding bridged device ${dev}${device.deviceName}${er} (${dev}${device.name}${er}) plugin ${plg}${pluginName}${er} not found`);
612
614
  return;
613
615
  }
614
616
  // Register and add the device to matterbridge aggregator in bridge mode
@@ -619,36 +621,38 @@ export class Matterbridge extends EventEmitter {
619
621
  plugin.registeredDevices++;
620
622
  if (plugin.addedDevices !== undefined)
621
623
  plugin.addedDevices++;
622
- this.log.info(`Added and registered bridged device(${plugin.registeredDevices}/${plugin.addedDevices}) ${dev}${device.name}-${device.deviceName}${nf} for plugin ${plg}${pluginName}${nf}`);
624
+ this.log.info(`Added and registered bridged device (${plugin.registeredDevices}/${plugin.addedDevices}) ${dev}${device.deviceName}${nf} (${dev}${device.name}${nf}) for plugin ${plg}${pluginName}${nf}`);
623
625
  }
624
626
  // Only register the device in childbridge mode
625
627
  if (this.bridgeMode === 'childbridge') {
626
628
  this.registeredDevices.push({ plugin: pluginName, device, added: false });
627
629
  if (plugin.registeredDevices !== undefined)
628
630
  plugin.registeredDevices++;
629
- this.log.info(`Registered bridged device ${dev}${device.name}-${device.deviceName}${nf} for plugin ${plg}${pluginName}${nf}`);
631
+ this.log.info(`Registered bridged device ${dev}${device.deviceName}${nf} (${dev}${device.name}${nf}) for plugin ${plg}${pluginName}${nf}`);
630
632
  }
631
633
  }
632
634
  async removeBridgedDevice(pluginName, device) {
633
635
  if (this.bridgeMode === 'bridge' && !this.matterAggregator) {
634
- this.log.error(`Removing bridged device ${dev}${device.name}-${device.deviceName}${er} for plugin ${plg}${pluginName}${er} error: matterAggregator not found`);
636
+ this.log.error(`Removing bridged device ${dev}${device.deviceName}${er} (${dev}${device.name}${er}) for plugin ${plg}${pluginName}${er} error: matterAggregator not found`);
635
637
  return;
636
638
  }
637
- this.log.debug(`Removing bridged device ${db}${device.name}-${device.deviceName}${nf} for plugin ${plg}${pluginName}${db}`);
639
+ this.log.debug(`Removing bridged device ${dev}${device.deviceName}${db} (${dev}${device.name}${db}) for plugin ${plg}${pluginName}${db}`);
638
640
  // Check if the plugin is registered
639
641
  const plugin = this.findPlugin(pluginName);
640
642
  if (!plugin) {
641
- this.log.error(`Error removing bridged device ${dev}${device.name}-${device.deviceName}${er} plugin ${plg}${pluginName}${er} not found`);
643
+ this.log.error(`Error removing bridged device ${dev}${device.deviceName}${er} (${dev}${device.name}${er}) plugin ${plg}${pluginName}${er} not found`);
642
644
  return;
643
645
  }
644
646
  if (this.bridgeMode === 'childbridge' && !plugin.aggregator) {
645
- this.log.error(`Error removing bridged device ${dev}${device.name}-${device.deviceName}${er} plugin ${plg}${pluginName}${er} aggregator not found`);
647
+ this.log.error(`Error removing bridged device ${dev}${device.deviceName}${er} (${dev}${device.name}${er}) plugin ${plg}${pluginName}${er} aggregator not found`);
646
648
  return;
647
649
  }
650
+ /*
648
651
  if (this.bridgeMode === 'childbridge' && !plugin.connected) {
649
- this.log.error(`Error removing bridged device ${dev}${device.name}-${device.deviceName}${er} plugin ${plg}${pluginName}${er} not connected`);
650
- return;
652
+ this.log.error(`Error removing bridged device ${dev}${device.deviceName}${er} (${dev}${device.name}${er}) plugin ${plg}${pluginName}${er} not connected`);
653
+ return;
651
654
  }
655
+ */
652
656
  // Register and add the device to matterbridge aggregator in bridge mode
653
657
  if (this.bridgeMode === 'bridge') {
654
658
  this.matterAggregator.removeBridgedDevice(device);
@@ -662,12 +666,12 @@ export class Matterbridge extends EventEmitter {
662
666
  plugin.registeredDevices--;
663
667
  if (plugin.addedDevices !== undefined)
664
668
  plugin.addedDevices--;
665
- this.log.info(`Rmoved bridged device(${plugin.registeredDevices}/${plugin.addedDevices}) ${dev}${device.name}-${device.deviceName}${nf} for plugin ${plg}${pluginName}${nf}`);
669
+ this.log.info(`Removed bridged device(${plugin.registeredDevices}/${plugin.addedDevices}) ${dev}${device.deviceName}${nf} (${dev}${device.name}${nf}) for plugin ${plg}${pluginName}${nf}`);
666
670
  }
667
671
  // Only register the device in childbridge mode
668
672
  if (this.bridgeMode === 'childbridge') {
669
673
  if (plugin.type === 'AccessoryPlatform') {
670
- this.log.warn(`Removing bridged device ${dev}${device.name}-${device.deviceName}${wr} for plugin ${plg}${pluginName}${wr} error: AccessoryPlatform not supported in childbridge mode`);
674
+ this.log.warn(`Removing bridged device ${dev}${device.deviceName}${wr} (${dev}${device.name}${wr}) for plugin ${plg}${pluginName}${wr} error: AccessoryPlatform not supported in childbridge mode`);
671
675
  }
672
676
  else if (plugin.type === 'DynamicPlatform') {
673
677
  this.registeredDevices.forEach((registeredDevice, index) => {
@@ -678,11 +682,11 @@ export class Matterbridge extends EventEmitter {
678
682
  });
679
683
  plugin.aggregator.removeBridgedDevice(device);
680
684
  }
685
+ this.log.info(`Removed bridged device(${plugin.registeredDevices}/${plugin.addedDevices}) ${dev}${device.deviceName}${nf} (${dev}${device.name}${nf}) for plugin ${plg}${pluginName}${nf}`);
681
686
  if (plugin.registeredDevices !== undefined)
682
687
  plugin.registeredDevices--;
683
688
  if (plugin.addedDevices !== undefined)
684
689
  plugin.addedDevices--;
685
- this.log.info(`Removed bridged device(${plugin.registeredDevices}/${plugin.addedDevices}) ${dev}${device.name}-${device.deviceName}${nf} for plugin ${plg}${pluginName}${nf}`);
686
690
  }
687
691
  }
688
692
  /**
@@ -918,6 +922,7 @@ export class Matterbridge extends EventEmitter {
918
922
  plugin.registeredDevices = 0;
919
923
  plugin.addedDevices = 0;
920
924
  await this.nodeContext?.set('plugins', this.getBaseRegisteredPlugins());
925
+ await platform.loadConfig();
921
926
  this.log.info(`Loaded plugin ${plg}${plugin.name}${db} type ${typ}${platform.type}${db} (entrypoint ${UNDERLINE}${pluginEntry}${UNDERLINEOFF})`);
922
927
  if (start)
923
928
  this.startPlugin(plugin, message); // No await do it asyncronously
@@ -966,8 +971,8 @@ export class Matterbridge extends EventEmitter {
966
971
  await this.matterServer.start();
967
972
  this.log.info('Matter server started');
968
973
  if (hasParameter('discover')) {
969
- const discover = await this.commissioningController.discoverCommissionableDevices({ productId: 0x8000, deviceType: 0xfff1 });
970
- console.log(discover);
974
+ //const discover = await this.commissioningController.discoverCommissionableDevices({ productId: 0x8000, deviceType: 0xfff1 });
975
+ //console.log(discover);
971
976
  }
972
977
  this.log.info(`Commissioning controller is already commisioned: ${this.commissioningController.isCommissioned()}`);
973
978
  const nodes = this.commissioningController.getCommissionedNodes();
@@ -979,11 +984,17 @@ export class Matterbridge extends EventEmitter {
979
984
  // Plugins are loaded by loadPlugin on startup and plugin.loaded is set to true
980
985
  // Plugins are started and configured by callback when Matterbridge is commissioned
981
986
  this.log.debug(`Creating commissioning server context for ${plg}Matterbridge${db}`);
982
- this.matterbridgeContext = this.createCommissioningServerContext('Matterbridge', 'Matterbridge', DeviceTypes.AGGREGATOR.code, 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge aggregator');
987
+ this.matterbridgeContext = this.createCommissioningServerContext('Matterbridge', 'Matterbridge', DeviceTypes.AGGREGATOR.code, 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge Aggregator');
983
988
  if (!this.matterbridgeContext) {
984
989
  this.log.error(`Error creating storage context for ${plg}Matterbridge${er}`);
985
990
  return;
986
991
  }
992
+ if (!this.nodeContext) {
993
+ this.log.error(`Node storage context undefined for ${plg}Matterbridge${er}`);
994
+ return;
995
+ }
996
+ this.matterbridgeContext.set('softwareVersion', 1);
997
+ this.matterbridgeContext.set('softwareVersionString', this.matterbridgeVersion);
987
998
  this.log.debug(`Creating commissioning server for ${plg}Matterbridge${db}`);
988
999
  this.commissioningServer = this.createCommisioningServer(this.matterbridgeContext, 'Matterbridge');
989
1000
  this.log.debug(`Creating matter aggregator for ${plg}Matterbridge${db}`);
@@ -995,7 +1006,7 @@ export class Matterbridge extends EventEmitter {
995
1006
  this.log.debug('Starting matter server...');
996
1007
  await this.startMatterServer();
997
1008
  this.log.info('Matter server started');
998
- this.showCommissioningQRCode(this.commissioningServer, this.matterbridgeContext, 'Matterbridge');
1009
+ await this.showCommissioningQRCode(this.commissioningServer, this.matterbridgeContext, this.nodeContext, 'Matterbridge');
999
1010
  }
1000
1011
  if (this.bridgeMode === 'childbridge') {
1001
1012
  // Plugins are loaded and started by loadPlugin on startup
@@ -1033,7 +1044,9 @@ export class Matterbridge extends EventEmitter {
1033
1044
  await this.matterServer.addCommissioningServer(plugin.commissioningServer, { uniqueStorageKey: plugin.name });
1034
1045
  }
1035
1046
  if (plugin.type === 'DynamicPlatform') {
1036
- plugin.storageContext = this.createCommissioningServerContext(plugin.name, 'Matterbridge Dynamic Platform', DeviceTypes.AGGREGATOR.code, 0xfff1, 'Matterbridge', 0x8000, 'Dynamic Platform');
1047
+ plugin.storageContext = this.createCommissioningServerContext(plugin.name, 'Matterbridge', DeviceTypes.AGGREGATOR.code, 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge Dynamic Platform');
1048
+ plugin.storageContext.set('softwareVersion', 1);
1049
+ plugin.storageContext.set('softwareVersionString', this.matterbridgeVersion);
1037
1050
  plugin.commissioningServer = this.createCommisioningServer(plugin.storageContext, plugin.name);
1038
1051
  this.log.debug(`Creating aggregator for plugin ${plg}${plugin.name}${db}`);
1039
1052
  plugin.aggregator = this.createMatterAggregator(plugin.storageContext); // Generate serialNumber and uniqueId
@@ -1079,7 +1092,21 @@ export class Matterbridge extends EventEmitter {
1079
1092
  await this.startMatterServer();
1080
1093
  this.log.info('Matter server started');
1081
1094
  for (const plugin of this.registeredPlugins) {
1082
- this.showCommissioningQRCode(plugin.commissioningServer, plugin.storageContext, plugin.name);
1095
+ if (!plugin.enabled)
1096
+ continue;
1097
+ if (!plugin.commissioningServer) {
1098
+ this.log.error(`Commissioning server not found for plugin ${plg}${plugin.name}${er}`);
1099
+ continue;
1100
+ }
1101
+ if (!plugin.storageContext) {
1102
+ this.log.error(`Storage context not found for plugin ${plg}${plugin.name}${er}`);
1103
+ continue;
1104
+ }
1105
+ if (!plugin.nodeContext) {
1106
+ this.log.error(`Node storage context not found for plugin ${plg}${plugin.name}${er}`);
1107
+ continue;
1108
+ }
1109
+ await this.showCommissioningQRCode(plugin.commissioningServer, plugin.storageContext, plugin.nodeContext, plugin.name);
1083
1110
  }
1084
1111
  Logger.defaultLogLevel = this.debugEnabled ? Level.DEBUG : Level.INFO;
1085
1112
  clearInterval(startMatterInterval);
@@ -1165,7 +1192,7 @@ export class Matterbridge extends EventEmitter {
1165
1192
  * @param storageContext - The storage context to store the pairing codes.
1166
1193
  * @param pluginName - The name of the commissioning server.
1167
1194
  */
1168
- async showCommissioningQRCode(commissioningServer, storageContext, pluginName) {
1195
+ async showCommissioningQRCode(commissioningServer, storageContext, nodeContext, pluginName) {
1169
1196
  if (!commissioningServer || !storageContext || !pluginName)
1170
1197
  return;
1171
1198
  if (!commissioningServer.isCommissioned()) {
@@ -1173,41 +1200,27 @@ export class Matterbridge extends EventEmitter {
1173
1200
  const { qrPairingCode, manualPairingCode } = commissioningServer.getPairingCode();
1174
1201
  storageContext.set('qrPairingCode', qrPairingCode);
1175
1202
  storageContext.set('manualPairingCode', manualPairingCode);
1203
+ await nodeContext.set('qrPairingCode', qrPairingCode);
1204
+ await nodeContext.set('manualPairingCode', manualPairingCode);
1176
1205
  const QrCode = new QrCodeSchema();
1177
- this.log.info(`Pairing code:\n\n${QrCode.encode(qrPairingCode)}\nManual pairing code: ${manualPairingCode}\n`);
1178
- if (this.bridgeMode === 'bridge') {
1179
- await this.nodeContext?.set('qrPairingCode', qrPairingCode);
1180
- await this.nodeContext?.set('manualPairingCode', manualPairingCode);
1181
- }
1182
- if (this.bridgeMode === 'childbridge') {
1206
+ this.log.info(`Pairing code:\n\n${QrCode.encode(qrPairingCode)}\n${plg}${pluginName}${nf}\n\nqrPairingCode: ${qrPairingCode}\n\nManual pairing code: ${manualPairingCode}\n`);
1207
+ if (pluginName !== 'Matterbridge') {
1183
1208
  const plugin = this.findPlugin(pluginName);
1184
1209
  if (plugin) {
1185
- await plugin.nodeContext?.set('qrPairingCode', qrPairingCode);
1186
- await plugin.nodeContext?.set('manualPairingCode', manualPairingCode);
1187
- await this.nodeContext?.set('plugins', this.getBaseRegisteredPlugins());
1188
1210
  plugin.paired = false;
1189
1211
  }
1190
1212
  }
1213
+ await this.nodeContext?.set('plugins', this.getBaseRegisteredPlugins());
1191
1214
  }
1192
1215
  else {
1193
1216
  this.log.info(`***The commissioning server for ${plg}${pluginName}${nf} is already commissioned. Waiting for controllers to connect ...`);
1194
- if (this.bridgeMode === 'bridge') {
1195
- const qrPairingCode = storageContext.get('qrPairingCode', '');
1196
- const manualPairingCode = storageContext.get('manualPairingCode', '');
1197
- await this.nodeContext?.set('qrPairingCode', qrPairingCode);
1198
- await this.nodeContext?.set('manualPairingCode', manualPairingCode);
1199
- }
1200
- if (this.bridgeMode === 'childbridge') {
1217
+ if (pluginName !== 'Matterbridge') {
1201
1218
  const plugin = this.findPlugin(pluginName);
1202
- if (plugin && plugin.storageContext && plugin.nodeContext) {
1203
- plugin.qrPairingCode = plugin.storageContext.get('qrPairingCode', '');
1204
- plugin.manualPairingCode = plugin.storageContext.get('manualPairingCode', '');
1205
- await plugin.nodeContext.set('qrPairingCode', plugin.qrPairingCode);
1206
- await plugin.nodeContext.set('manualPairingCode', plugin.manualPairingCode);
1207
- await this.nodeContext?.set('plugins', this.getBaseRegisteredPlugins());
1219
+ if (plugin) {
1208
1220
  plugin.paired = true;
1209
1221
  }
1210
1222
  }
1223
+ await this.nodeContext?.set('plugins', this.getBaseRegisteredPlugins());
1211
1224
  }
1212
1225
  }
1213
1226
  /**
@@ -1228,11 +1241,11 @@ export class Matterbridge extends EventEmitter {
1228
1241
  * Creates a matter commissioning server.
1229
1242
  *
1230
1243
  * @param {StorageContext} context - The storage context.
1231
- * @param {string} name - The name of the commissioning server.
1244
+ * @param {string} pluginName - The name of the commissioning server.
1232
1245
  * @returns {CommissioningServer} The created commissioning server.
1233
1246
  */
1234
- createCommisioningServer(context, name) {
1235
- this.log.debug(`Creating matter commissioning server for plugin ${plg}${name}${db}`);
1247
+ createCommisioningServer(context, pluginName) {
1248
+ this.log.debug(`Creating matter commissioning server for plugin ${plg}${pluginName}${db}`);
1236
1249
  const deviceName = context.get('deviceName');
1237
1250
  const deviceType = context.get('deviceType');
1238
1251
  const vendorId = context.get('vendorId');
@@ -1241,9 +1254,14 @@ export class Matterbridge extends EventEmitter {
1241
1254
  const productName = context.get('productName'); // Home app = Model
1242
1255
  const serialNumber = context.get('serialNumber');
1243
1256
  const uniqueId = context.get('uniqueId');
1244
- this.log.debug(
1245
- // eslint-disable-next-line max-len
1246
- `Creating matter commissioning server for plugin ${plg}${name}${db} with deviceName ${deviceName} deviceType ${deviceType}(0x${deviceType.toString(16).padStart(4, '0')}) uniqueId ${uniqueId} serialNumber ${serialNumber}`);
1257
+ const softwareVersion = context.get('softwareVersion', 1);
1258
+ const softwareVersionString = context.get('softwareVersionString', '1.0.0'); // Home app = Firmware Revision
1259
+ const hardwareVersion = context.get('hardwareVersion', 1);
1260
+ const hardwareVersionString = context.get('hardwareVersionString', '1.0.0');
1261
+ this.log.debug(`Creating matter commissioning server for plugin ${plg}${pluginName}${db} with deviceName ${deviceName} deviceType ${deviceType}(0x${deviceType.toString(16).padStart(4, '0')})`);
1262
+ this.log.debug(`Creating matter commissioning server for plugin ${plg}${pluginName}${db} with uniqueId ${uniqueId} serialNumber ${serialNumber}`);
1263
+ this.log.debug(`Creating matter commissioning server for plugin ${plg}${pluginName}${db} with softwareVersion ${softwareVersion} softwareVersionString ${softwareVersionString}`);
1264
+ this.log.debug(`Creating matter commissioning server for plugin ${plg}${pluginName}${db} with hardwareVersion ${hardwareVersion} hardwareVersionString ${hardwareVersionString}`);
1247
1265
  const commissioningServer = new CommissioningServer({
1248
1266
  port: undefined,
1249
1267
  passcode: undefined,
@@ -1257,10 +1275,10 @@ export class Matterbridge extends EventEmitter {
1257
1275
  productName,
1258
1276
  nodeLabel: productName,
1259
1277
  productLabel: productName,
1260
- softwareVersion: context.get('softwareVersion', 1),
1261
- softwareVersionString: context.get('softwareVersionString', '1.0.0'), // Home app = Firmware Revision
1262
- hardwareVersion: context.get('hardwareVersion', 1),
1263
- hardwareVersionString: context.get('hardwareVersionString', '1.0.0'),
1278
+ softwareVersion,
1279
+ softwareVersionString, // Home app = Firmware Revision
1280
+ hardwareVersion,
1281
+ hardwareVersionString,
1264
1282
  uniqueId,
1265
1283
  serialNumber,
1266
1284
  reachable: true,
@@ -1269,15 +1287,15 @@ export class Matterbridge extends EventEmitter {
1269
1287
  const info = commissioningServer.getActiveSessionInformation(fabricIndex);
1270
1288
  let connected = false;
1271
1289
  info.forEach((session) => {
1272
- this.log.debug(`***Active session changed on fabric ${fabricIndex} ${session.fabric?.rootVendorId}/${session.fabric?.label} for ${plg}${name}${nf}`, debugStringify(session));
1290
+ this.log.debug(`***Active session changed on fabric ${fabricIndex} ${session.fabric?.rootVendorId}/${session.fabric?.label} for ${plg}${pluginName}${nf}`, debugStringify(session));
1273
1291
  if (session.isPeerActive === true && session.secure === true && session.numberOfActiveSubscriptions >= 1) {
1274
- this.log.info(`***Controller ${session.fabric?.rootVendorId}/${session.fabric?.label} connected to ${plg}${name}${nf}`);
1292
+ this.log.info(`***Controller ${session.fabric?.rootVendorId}/${session.fabric?.label} connected to ${plg}${pluginName}${nf}`);
1275
1293
  connected = true;
1276
1294
  }
1277
1295
  });
1278
1296
  if (connected) {
1279
1297
  if (this.bridgeMode === 'childbridge') {
1280
- const plugin = this.findPlugin(name);
1298
+ const plugin = this.findPlugin(pluginName);
1281
1299
  if (plugin) {
1282
1300
  plugin.paired = true;
1283
1301
  plugin.connected = true;
@@ -1290,16 +1308,15 @@ export class Matterbridge extends EventEmitter {
1290
1308
  if (!plugin.enabled)
1291
1309
  continue;
1292
1310
  this.startPlugin(plugin, 'Matterbridge is commissioned and controllers are connected', true); // No await do it asyncronously with also configurePlugin
1293
- //this.configurePlugin(plugin); // No await do it asyncronously
1294
1311
  }
1295
1312
  Logger.defaultLogLevel = this.debugEnabled ? Level.DEBUG : Level.INFO;
1296
1313
  }
1297
1314
  if (this.bridgeMode === 'childbridge') {
1298
1315
  //Logger.defaultLogLevel = Level.INFO;
1299
- const plugin = this.findPlugin(name);
1316
+ const plugin = this.findPlugin(pluginName);
1300
1317
  if (plugin && plugin.type === 'DynamicPlatform' && plugin.configured !== true) {
1301
1318
  for (const registeredDevice of this.registeredDevices) {
1302
- if (registeredDevice.plugin === name) {
1319
+ if (registeredDevice.plugin === pluginName) {
1303
1320
  this.log.info(`Adding bridged device ${dev}${registeredDevice.device.name}-${registeredDevice.device.deviceName}${nf} to aggregator for plugin ${plg}${plugin.name}${db}`);
1304
1321
  if (!plugin.aggregator) {
1305
1322
  this.log.error(`****Aggregator not found for plugin ${plg}${plugin.name}${er}`);
@@ -1316,7 +1333,7 @@ export class Matterbridge extends EventEmitter {
1316
1333
  }
1317
1334
  }
1318
1335
  for (const plugin of this.registeredPlugins) {
1319
- if (plugin.name === name && plugin.platform && plugin.configured !== true) {
1336
+ if (plugin.name === pluginName && plugin.platform && plugin.configured !== true) {
1320
1337
  this.configurePlugin(plugin); // No await do it asyncronously
1321
1338
  }
1322
1339
  }
@@ -1326,12 +1343,29 @@ export class Matterbridge extends EventEmitter {
1326
1343
  }, 2000);
1327
1344
  }
1328
1345
  },
1329
- commissioningChangedCallback: (fabricIndex) => {
1346
+ commissioningChangedCallback: async (fabricIndex) => {
1330
1347
  const info = commissioningServer.getCommissionedFabricInformation(fabricIndex);
1331
- this.log.debug(`***Commissioning changed on fabric ${fabricIndex} for ${plg}${name}${nf}`, debugStringify(info));
1348
+ this.log.debug(`***Commissioning changed on fabric ${fabricIndex} for ${plg}${pluginName}${nf}`, debugStringify(info));
1332
1349
  if (info.length === 0) {
1333
- this.log.warn(`***Commissioning removed from fabric ${fabricIndex} for ${plg}${name}${nf}. Resetting the commissioning server ...`);
1334
- commissioningServer.factoryReset(); // TODO delete from storage also "matterbridge-eve-weather.EndpointStructure"
1350
+ this.log.warn(`***Commissioning removed from fabric ${fabricIndex} for ${plg}${pluginName}${nf}. Resetting the commissioning server ...`);
1351
+ await commissioningServer.factoryReset();
1352
+ if (pluginName === 'Matterbridge') {
1353
+ this.matterbridgeContext?.delete(`${pluginName}.EndpointStructure`);
1354
+ this.matterbridgeContext?.delete(`${pluginName}.EventHandler`);
1355
+ this.matterbridgeContext?.delete(`${pluginName}.SessionManager`);
1356
+ }
1357
+ else {
1358
+ for (const plugin of this.registeredPlugins) {
1359
+ if (plugin.name === pluginName) {
1360
+ await plugin.platform?.onShutdown('Commissioning removed by the controller');
1361
+ plugin.paired = false;
1362
+ plugin.connected = false;
1363
+ plugin.storageContext?.delete(`${pluginName}.EndpointStructure`);
1364
+ plugin.storageContext?.delete(`${pluginName}.EventHandler`);
1365
+ plugin.storageContext?.delete(`${pluginName}.SessionManager`);
1366
+ }
1367
+ }
1368
+ }
1335
1369
  }
1336
1370
  },
1337
1371
  });