matterbridge 1.2.0 → 1.2.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.
- package/CHANGELOG.md +21 -0
- package/README.md +51 -8
- package/dist/matterbridge.d.ts.map +1 -1
- package/dist/matterbridge.js +260 -38
- package/dist/matterbridge.js.map +1 -1
- package/dist/matterbridgeDevice.d.ts +15 -1
- package/dist/matterbridgeDevice.d.ts.map +1 -1
- package/dist/matterbridgeDevice.js +36 -1
- package/dist/matterbridgeDevice.js.map +1 -1
- package/frontend/build/asset-manifest.json +6 -6
- package/frontend/build/index.html +1 -1
- package/frontend/build/static/css/{main.b996bc4e.css → main.61f6cf42.css} +2 -2
- package/frontend/build/static/css/main.61f6cf42.css.map +1 -0
- package/frontend/build/static/js/main.e3553a4d.js +3 -0
- package/frontend/build/static/js/main.e3553a4d.js.map +1 -0
- package/package.json +10 -7
- package/Screenshot devices page.png +0 -0
- package/Screenshot home page.png +0 -0
- package/frontend/build/static/css/main.b996bc4e.css.map +0 -1
- package/frontend/build/static/js/main.657bca15.js +0 -3
- package/frontend/build/static/js/main.657bca15.js.map +0 -1
- /package/frontend/build/static/js/{main.657bca15.js.LICENSE.txt → main.e3553a4d.js.LICENSE.txt} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [1.2.2] - 2024-03-26
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- [MatterbridgeDevice]: Added Cluster DoorLock and command handler.
|
|
10
|
+
|
|
11
|
+
## [1.2.1] - 2024-03-25
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- [frontend]: Remove plugin from frontend.
|
|
16
|
+
- [frontend]: Add plugin from frontend.
|
|
17
|
+
- [workflow]: All packages now have a workflow on GitHub.
|
|
18
|
+
- [frontend]: Frontend got updated to 0.8.4.
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- [frontend]: Fixed the restart needed message.
|
|
23
|
+
- [matterbridge]: Fixed the delay of loading from the cli.
|
|
24
|
+
- [matterbridge]: Fixed the count of devices removed.
|
|
25
|
+
|
|
5
26
|
## [1.2.0] - 2024-03-23
|
|
6
27
|
|
|
7
28
|
### Breaking change on plugin default entry point and platform constructor!
|
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/matterbridge)
|
|
4
4
|
[](https://www.npmjs.com/package/matterbridge)
|
|
5
|
+

|
|
6
|
+
|
|
5
7
|
|
|
6
8
|
[](https://www.npmjs.com/package/matter-history)
|
|
7
9
|
[](https://www.npmjs.com/package/node-ansi-logger)
|
|
@@ -33,12 +35,12 @@ A special thank to Apollon77 for his incredible work.
|
|
|
33
35
|
Follow these steps to install Matterbridge:
|
|
34
36
|
|
|
35
37
|
on Windows:
|
|
36
|
-
```
|
|
38
|
+
```
|
|
37
39
|
npm install -g matterbridge
|
|
38
40
|
```
|
|
39
41
|
|
|
40
42
|
on Linux (you need the necessary permissions):
|
|
41
|
-
```
|
|
43
|
+
```
|
|
42
44
|
sudo npm install -g matterbridge
|
|
43
45
|
```
|
|
44
46
|
|
|
@@ -46,6 +48,7 @@ Test the installation with:
|
|
|
46
48
|
```
|
|
47
49
|
matterbridge -bridge
|
|
48
50
|
```
|
|
51
|
+
|
|
49
52
|
Now it is possible to open the frontend at the link provided (default: http://localhost:3000)
|
|
50
53
|
|
|
51
54
|
## Usage
|
|
@@ -87,10 +90,10 @@ matterbridge -childbridge -frontend [port number]
|
|
|
87
90
|
```
|
|
88
91
|
|
|
89
92
|
Home page:
|
|
90
|
-

|
|
91
94
|
|
|
92
95
|
Devices page:
|
|
93
|
-

|
|
94
97
|
|
|
95
98
|
## Plugins
|
|
96
99
|
|
|
@@ -130,6 +133,10 @@ Matterbridge can run as many plugins as you want.
|
|
|
130
133
|
|
|
131
134
|
[Room plugin with history](https://github.com/Luligu/matterbridge-eve-room)
|
|
132
135
|
|
|
136
|
+
### Production-level plugins
|
|
137
|
+
|
|
138
|
+
[zigbee2mqtt](https://github.com/Luligu/matterbridge-zigbee2mqtt)
|
|
139
|
+
|
|
133
140
|
## How to install and register a production-level plugin (from npm)
|
|
134
141
|
|
|
135
142
|
To install i.e. https://github.com/Luligu/matterbridge-zigbee2mqtt
|
|
@@ -148,7 +155,7 @@ sudo npm install -g matterbridge-zigbee2mqtt
|
|
|
148
155
|
matterbridge -add matterbridge-zigbee2mqtt
|
|
149
156
|
```
|
|
150
157
|
|
|
151
|
-
## How to install and register a plugin for development (from
|
|
158
|
+
## How to install and register a plugin for development (from github)
|
|
152
159
|
|
|
153
160
|
To install i.e. https://github.com/Luligu/matterbridge-example-accessory-platform
|
|
154
161
|
|
|
@@ -162,15 +169,16 @@ On linux:
|
|
|
162
169
|
cd ~/Matterbridge
|
|
163
170
|
```
|
|
164
171
|
|
|
165
|
-
then
|
|
172
|
+
then clone the plugin
|
|
166
173
|
|
|
167
174
|
```
|
|
168
175
|
git clone https://github.com/Luligu/matterbridge-example-accessory-platform
|
|
169
176
|
cd matterbridge-example-accessory-platform
|
|
170
177
|
npm install
|
|
178
|
+
npm run build
|
|
171
179
|
```
|
|
172
180
|
|
|
173
|
-
|
|
181
|
+
then add the plugin to Matterbridge
|
|
174
182
|
```
|
|
175
183
|
matterbridge -add .\
|
|
176
184
|
```
|
|
@@ -221,7 +229,8 @@ The plugin name.
|
|
|
221
229
|
The plugin platform type.
|
|
222
230
|
|
|
223
231
|
### config: object
|
|
224
|
-
The plugin config (loaded before
|
|
232
|
+
The plugin config (loaded before the platform constructor is called and saved after onShutdown() is called).
|
|
233
|
+
Here you can store your plugin configuration (see matterbridge-zigbee2mqtt for example)
|
|
225
234
|
|
|
226
235
|
### async onStart(reason?: string)
|
|
227
236
|
The method onStart() is where you have to create your MatterbridgeDevice and add all needed clusters and command handlers.
|
|
@@ -253,3 +262,37 @@ It can be useful to call this method from onShutdown() if you don't want to keep
|
|
|
253
262
|
|
|
254
263
|
## MatterbridgeDevice api
|
|
255
264
|
|
|
265
|
+
|
|
266
|
+
# Contribution Guidelines
|
|
267
|
+
|
|
268
|
+
Thank you for your interest in contributing to my project!
|
|
269
|
+
|
|
270
|
+
I warmly welcome contributions to this project! Whether it's reporting bugs, proposing new features, updating documentation, or writing code, your help is greatly appreciated.
|
|
271
|
+
|
|
272
|
+
## Getting Started
|
|
273
|
+
|
|
274
|
+
- Fork this repository to your own GitHub account and clone it to your local device.
|
|
275
|
+
- Make the necessary changes and test them out
|
|
276
|
+
- Commit your changes and push to your forked repository
|
|
277
|
+
|
|
278
|
+
## Submitting Changes
|
|
279
|
+
|
|
280
|
+
- Create a new pull request from my repository and I'll be glad to check it out
|
|
281
|
+
- Be sure to follow the existing code style
|
|
282
|
+
- Add unit tests for any new or changed functionality if possible
|
|
283
|
+
- In your pull request, do describe what your changes do and how they work
|
|
284
|
+
|
|
285
|
+
## Code of Conduct
|
|
286
|
+
|
|
287
|
+
We believe in a welcoming and respectful community for all. Please make sure to follow our [Code of Conduct](LINK_TO_CODE_OF_CONDUCT) in all your interactions with the project.
|
|
288
|
+
|
|
289
|
+
## Support
|
|
290
|
+
|
|
291
|
+
If you find this project helpful and you wish to support the ongoing development, you can do so by buying me a coffee.
|
|
292
|
+
Click on the badge below to get started:
|
|
293
|
+
|
|
294
|
+
<a href="https://www.buymeacoffee.com/luligugithub">
|
|
295
|
+
<img src="./yellow-button.png" alt="Buy me a coffee" width="120">
|
|
296
|
+
</a>
|
|
297
|
+
|
|
298
|
+
Thank you for your support!
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"matterbridge.d.ts","sourceRoot":"","sources":["../src/matterbridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;;AAEH,OAAO,EAAE,kBAAkB,EAAgC,MAAM,yBAAyB,CAAC;AAQ3F,OAAO,YAAY,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"matterbridge.d.ts","sourceRoot":"","sources":["../src/matterbridge.ts"],"names":[],"mappings":"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"}
|
package/dist/matterbridge.js
CHANGED
|
@@ -31,11 +31,11 @@ import express from 'express';
|
|
|
31
31
|
import os from 'os';
|
|
32
32
|
import path from 'path';
|
|
33
33
|
import { CommissioningController, CommissioningServer, MatterServer } from '@project-chip/matter-node.js';
|
|
34
|
-
import { BasicInformationCluster, BridgedDeviceBasicInformationCluster, ClusterServer } from '@project-chip/matter-node.js/cluster';
|
|
34
|
+
import { BasicInformationCluster, BridgedDeviceBasicInformationCluster, ClusterServer, GeneralCommissioning, PowerSourceCluster, ThreadNetworkDiagnosticsCluster, } from '@project-chip/matter-node.js/cluster';
|
|
35
35
|
import { DeviceTypeId, VendorId } from '@project-chip/matter-node.js/datatype';
|
|
36
|
-
import { Aggregator, DeviceTypes } from '@project-chip/matter-node.js/device';
|
|
36
|
+
import { Aggregator, DeviceTypes, NodeStateInformation } from '@project-chip/matter-node.js/device';
|
|
37
37
|
import { Format, Level, Logger } from '@project-chip/matter-node.js/log';
|
|
38
|
-
import { QrCodeSchema } from '@project-chip/matter-node.js/schema';
|
|
38
|
+
import { ManualPairingCodeCodec, QrCodeSchema } from '@project-chip/matter-node.js/schema';
|
|
39
39
|
import { StorageBackendDisk, StorageBackendJsonFile, StorageManager } from '@project-chip/matter-node.js/storage';
|
|
40
40
|
import { requireMinNodeVersion, getParameter, getIntParameter, hasParameter } from '@project-chip/matter-node.js/util';
|
|
41
41
|
import { CryptoNode } from '@project-chip/matter-node.js/crypto';
|
|
@@ -109,15 +109,11 @@ export class Matterbridge extends EventEmitter {
|
|
|
109
109
|
static async loadInstance(initialize = false) {
|
|
110
110
|
if (!Matterbridge.instance) {
|
|
111
111
|
// eslint-disable-next-line no-console
|
|
112
|
-
console.log('Matterbridge instance does not exists');
|
|
112
|
+
console.log(wr + 'Matterbridge instance does not exists!', initialize ? 'Initializing...' : 'Not initializing...', rs);
|
|
113
113
|
Matterbridge.instance = new Matterbridge();
|
|
114
114
|
if (initialize)
|
|
115
115
|
await Matterbridge.instance.initialize();
|
|
116
116
|
}
|
|
117
|
-
else {
|
|
118
|
-
// eslint-disable-next-line no-console
|
|
119
|
-
console.log('Matterbridge instance already exists');
|
|
120
|
-
}
|
|
121
117
|
return Matterbridge.instance;
|
|
122
118
|
}
|
|
123
119
|
/**
|
|
@@ -152,28 +148,19 @@ export class Matterbridge extends EventEmitter {
|
|
|
152
148
|
- disable [plugin name]: disable the globally installed plugin with the given name\n`);
|
|
153
149
|
process.exit(0);
|
|
154
150
|
}
|
|
155
|
-
//
|
|
151
|
+
// Set Matterbridge logger
|
|
156
152
|
if (hasParameter('debug'))
|
|
157
153
|
this.debugEnabled = true;
|
|
158
154
|
this.log = new AnsiLogger({ logName: 'Matterbridge', logTimestampFormat: 4 /* TimestampFormat.TIME_MILLIS */, logDebug: this.debugEnabled });
|
|
159
155
|
this.log.debug('Matterbridge is starting...');
|
|
160
|
-
// log system info and create .matterbridge directory
|
|
161
|
-
await this.logNodeAndSystemInfo();
|
|
162
|
-
this.log.info(
|
|
163
|
-
// eslint-disable-next-line max-len
|
|
164
|
-
`Matterbridge version ${this.matterbridgeVersion} mode ${hasParameter('bridge') ? 'bridge' : ''}${hasParameter('childbridge') ? 'childbridge' : ''}${hasParameter('controller') ? 'controller' : ''} running on ${this.systemInformation.osType} ${this.systemInformation.osRelease} ${this.systemInformation.osPlatform} ${this.systemInformation.osArch}`);
|
|
165
|
-
// check node version and throw error
|
|
166
|
-
requireMinNodeVersion(18);
|
|
167
|
-
// register SIGINT SIGTERM signal handlers
|
|
168
|
-
this.registerSignalHandlers();
|
|
169
|
-
// set matter.js logger level and format
|
|
170
|
-
Logger.defaultLogLevel = this.debugEnabled ? Level.DEBUG : Level.INFO;
|
|
171
|
-
Logger.format = Format.ANSI;
|
|
172
156
|
// Initialize NodeStorage
|
|
157
|
+
this.homeDirectory = os.homedir();
|
|
158
|
+
this.matterbridgeDirectory = path.join(this.homeDirectory, '.matterbridge');
|
|
173
159
|
this.log.debug('Creating node storage manager');
|
|
174
160
|
this.nodeStorage = new NodeStorageManager({ dir: path.join(this.matterbridgeDirectory, 'storage'), logging: false });
|
|
175
161
|
this.log.debug('Creating node storage context for matterbridge');
|
|
176
162
|
this.nodeContext = await this.nodeStorage.createStorage('matterbridge');
|
|
163
|
+
// Get the plugins from node storage
|
|
177
164
|
this.registeredPlugins = await this.nodeContext.get('plugins', []);
|
|
178
165
|
for (const plugin of this.registeredPlugins) {
|
|
179
166
|
this.log.debug(`Creating node storage context for plugin ${plugin.name}`);
|
|
@@ -185,6 +172,43 @@ export class Matterbridge extends EventEmitter {
|
|
|
185
172
|
await plugin.nodeContext.set('description', plugin.description);
|
|
186
173
|
await plugin.nodeContext.set('author', plugin.author);
|
|
187
174
|
}
|
|
175
|
+
if (hasParameter('logstorage')) {
|
|
176
|
+
await this.nodeContext.logStorage();
|
|
177
|
+
for (const plugin of this.registeredPlugins) {
|
|
178
|
+
await plugin.nodeContext?.logStorage();
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// Log system info and create .matterbridge directory
|
|
182
|
+
await this.logNodeAndSystemInfo();
|
|
183
|
+
this.log.info(
|
|
184
|
+
// eslint-disable-next-line max-len
|
|
185
|
+
`Matterbridge version ${this.matterbridgeVersion} mode ${hasParameter('bridge') ? 'bridge' : ''}${hasParameter('childbridge') ? 'childbridge' : ''}${hasParameter('controller') ? 'controller' : ''} running on ${this.systemInformation.osType} ${this.systemInformation.osRelease} ${this.systemInformation.osPlatform} ${this.systemInformation.osArch}`);
|
|
186
|
+
// Check node version and throw error
|
|
187
|
+
requireMinNodeVersion(18);
|
|
188
|
+
// Register SIGINT SIGTERM signal handlers
|
|
189
|
+
this.registerSignalHandlers();
|
|
190
|
+
// Set matter.js logger level and format
|
|
191
|
+
Logger.defaultLogLevel = this.debugEnabled ? Level.DEBUG : Level.INFO;
|
|
192
|
+
Logger.format = Format.ANSI;
|
|
193
|
+
// Initialize NodeStorage
|
|
194
|
+
/*
|
|
195
|
+
this.log.debug('Creating node storage manager');
|
|
196
|
+
this.nodeStorage = new NodeStorageManager({ dir: path.join(this.matterbridgeDirectory, 'storage'), logging: false });
|
|
197
|
+
this.log.debug('Creating node storage context for matterbridge');
|
|
198
|
+
this.nodeContext = await this.nodeStorage.createStorage('matterbridge');
|
|
199
|
+
// Get the plugins from node storage
|
|
200
|
+
this.registeredPlugins = await this.nodeContext.get<RegisteredPlugin[]>('plugins', []);
|
|
201
|
+
for (const plugin of this.registeredPlugins) {
|
|
202
|
+
this.log.debug(`Creating node storage context for plugin ${plugin.name}`);
|
|
203
|
+
plugin.nodeContext = await this.nodeStorage.createStorage(plugin.name);
|
|
204
|
+
await plugin.nodeContext.set<string>('name', plugin.name);
|
|
205
|
+
await plugin.nodeContext.set<string>('type', plugin.type);
|
|
206
|
+
await plugin.nodeContext.set<string>('path', plugin.path);
|
|
207
|
+
await plugin.nodeContext.set<string>('version', plugin.version);
|
|
208
|
+
await plugin.nodeContext.set<string>('description', plugin.description);
|
|
209
|
+
await plugin.nodeContext.set<string>('author', plugin.author);
|
|
210
|
+
}
|
|
211
|
+
*/
|
|
188
212
|
// Parse command line
|
|
189
213
|
this.parseCommandLine();
|
|
190
214
|
}
|
|
@@ -475,10 +499,16 @@ export class Matterbridge extends EventEmitter {
|
|
|
475
499
|
process.removeAllListeners('SIGTERM');
|
|
476
500
|
// Calling the shutdown functions with a reason
|
|
477
501
|
for (const plugin of this.registeredPlugins) {
|
|
502
|
+
if (!plugin.enabled)
|
|
503
|
+
continue;
|
|
504
|
+
this.log.info(`*Shutting down plugin ${plg}${plugin.name}${nf}`);
|
|
478
505
|
if (plugin.platform) {
|
|
479
506
|
await plugin.platform.onShutdown('Matterbridge is closing: ' + message);
|
|
480
507
|
await this.savePluginConfig(plugin);
|
|
481
508
|
}
|
|
509
|
+
else {
|
|
510
|
+
this.log.warn(`Plugin ${plg}${plugin.name}${er} platform not found`);
|
|
511
|
+
}
|
|
482
512
|
}
|
|
483
513
|
// Set reachability to false
|
|
484
514
|
/*
|
|
@@ -491,7 +521,6 @@ export class Matterbridge extends EventEmitter {
|
|
|
491
521
|
}
|
|
492
522
|
this.log.debug(`*-- device: ${dev}${registeredDevice.device.name}${db} plugin ${plg}${registeredDevice.plugin}${db} type ${GREEN}${plugin.type}${db}`);
|
|
493
523
|
if (this.bridgeMode === 'bridge') registeredDevice.device.setBridgedDeviceReachability(false);
|
|
494
|
-
if (this.bridgeMode === 'childbridge' && plugin.type === 'DynamicPlatform') plugin.aggregator?.removeBridgedDevice(registeredDevice.device);
|
|
495
524
|
if (this.bridgeMode === 'childbridge') plugin.commissioningServer?.setReachability(false);
|
|
496
525
|
if (this.bridgeMode === 'childbridge' && plugin.type === 'AccessoryPlatform') this.setReachableAttribute(registeredDevice.device, false);
|
|
497
526
|
if (this.bridgeMode === 'childbridge' && plugin.type === 'DynamicPlatform') registeredDevice.device.setBridgedDeviceReachability(false);
|
|
@@ -599,7 +628,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
599
628
|
this.registeredDevices.push({ plugin: pluginName, device, added: false });
|
|
600
629
|
if (plugin.registeredDevices !== undefined)
|
|
601
630
|
plugin.registeredDevices++;
|
|
602
|
-
this.log.info(`Registered device ${dev}${device.deviceName}${nf} (${dev}${device.name}${nf}) for plugin ${plg}${pluginName}${nf}`);
|
|
631
|
+
this.log.info(`Registered device (${plugin.registeredDevices}) ${dev}${device.deviceName}${nf} (${dev}${device.name}${nf}) for plugin ${plg}${pluginName}${nf}`);
|
|
603
632
|
}
|
|
604
633
|
}
|
|
605
634
|
/**
|
|
@@ -635,7 +664,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
635
664
|
this.registeredDevices.push({ plugin: pluginName, device, added: false });
|
|
636
665
|
if (plugin.registeredDevices !== undefined)
|
|
637
666
|
plugin.registeredDevices++;
|
|
638
|
-
this.log.info(`Registered bridged device ${dev}${device.deviceName}${nf} (${dev}${device.name}${nf}) for plugin ${plg}${pluginName}${nf}`);
|
|
667
|
+
this.log.info(`Registered bridged device (${plugin.registeredDevices}) ${dev}${device.deviceName}${nf} (${dev}${device.name}${nf}) for plugin ${plg}${pluginName}${nf}`);
|
|
639
668
|
}
|
|
640
669
|
}
|
|
641
670
|
/**
|
|
@@ -661,7 +690,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
661
690
|
return;
|
|
662
691
|
}
|
|
663
692
|
if (this.bridgeMode === 'childbridge' && !plugin.connected) {
|
|
664
|
-
this.log.warn(`
|
|
693
|
+
this.log.warn(`Removing bridged device ${dev}${device.deviceName}${wr} (${dev}${device.name}${wr}) plugin ${plg}${pluginName}${wr} not connected`);
|
|
665
694
|
return;
|
|
666
695
|
}
|
|
667
696
|
// Register and add the device to matterbridge aggregator in bridge mode
|
|
@@ -673,11 +702,11 @@ export class Matterbridge extends EventEmitter {
|
|
|
673
702
|
return;
|
|
674
703
|
}
|
|
675
704
|
});
|
|
705
|
+
this.log.info(`Removed bridged device(${plugin.registeredDevices}/${plugin.addedDevices}) ${dev}${device.deviceName}${nf} (${dev}${device.name}${nf}) for plugin ${plg}${pluginName}${nf}`);
|
|
676
706
|
if (plugin.registeredDevices !== undefined)
|
|
677
707
|
plugin.registeredDevices--;
|
|
678
708
|
if (plugin.addedDevices !== undefined)
|
|
679
709
|
plugin.addedDevices--;
|
|
680
|
-
this.log.info(`Removed bridged device(${plugin.registeredDevices}/${plugin.addedDevices}) ${dev}${device.deviceName}${nf} (${dev}${device.name}${nf}) for plugin ${plg}${pluginName}${nf}`);
|
|
681
710
|
}
|
|
682
711
|
// Only register the device in childbridge mode
|
|
683
712
|
if (this.bridgeMode === 'childbridge') {
|
|
@@ -1073,6 +1102,11 @@ export class Matterbridge extends EventEmitter {
|
|
|
1073
1102
|
return;
|
|
1074
1103
|
}
|
|
1075
1104
|
if (this.bridgeMode === 'controller') {
|
|
1105
|
+
if (!this.mattercontrollerContext) {
|
|
1106
|
+
this.log.error('No matter controller context initialized');
|
|
1107
|
+
await this.cleanup('No matter controller context initialized');
|
|
1108
|
+
return;
|
|
1109
|
+
}
|
|
1076
1110
|
this.log.info('Creating matter commissioning controller');
|
|
1077
1111
|
this.commissioningController = new CommissioningController({
|
|
1078
1112
|
autoConnect: false,
|
|
@@ -1082,15 +1116,124 @@ export class Matterbridge extends EventEmitter {
|
|
|
1082
1116
|
this.log.info('Starting matter server');
|
|
1083
1117
|
await this.matterServer.start();
|
|
1084
1118
|
this.log.info('Matter server started');
|
|
1119
|
+
if (hasParameter('pairingcode')) {
|
|
1120
|
+
const pairingCode = getParameter('pairingcode');
|
|
1121
|
+
const ip = this.mattercontrollerContext.has('ip') ? this.mattercontrollerContext.get('ip') : undefined;
|
|
1122
|
+
const port = this.mattercontrollerContext.has('port') ? this.mattercontrollerContext.get('port') : undefined;
|
|
1123
|
+
let longDiscriminator, setupPin, shortDiscriminator;
|
|
1124
|
+
if (pairingCode !== undefined) {
|
|
1125
|
+
const pairingCodeCodec = ManualPairingCodeCodec.decode(pairingCode);
|
|
1126
|
+
shortDiscriminator = pairingCodeCodec.shortDiscriminator;
|
|
1127
|
+
longDiscriminator = undefined;
|
|
1128
|
+
setupPin = pairingCodeCodec.passcode;
|
|
1129
|
+
this.log.info(`Data extracted from pairing code: ${Logger.toJSON(pairingCodeCodec)}`);
|
|
1130
|
+
}
|
|
1131
|
+
else {
|
|
1132
|
+
longDiscriminator = this.mattercontrollerContext.get('longDiscriminator', 3840);
|
|
1133
|
+
if (longDiscriminator > 4095)
|
|
1134
|
+
throw new Error('Discriminator value must be less than 4096');
|
|
1135
|
+
setupPin = this.mattercontrollerContext.get('pin', 20202021);
|
|
1136
|
+
}
|
|
1137
|
+
if ((shortDiscriminator === undefined && longDiscriminator === undefined) || setupPin === undefined) {
|
|
1138
|
+
throw new Error('Please specify the longDiscriminator of the device to commission with -longDiscriminator or provide a valid passcode with -passcode');
|
|
1139
|
+
}
|
|
1140
|
+
const commissioningOptions = {
|
|
1141
|
+
regulatoryLocation: GeneralCommissioning.RegulatoryLocationType.IndoorOutdoor,
|
|
1142
|
+
regulatoryCountryCode: 'XX',
|
|
1143
|
+
};
|
|
1144
|
+
const options = {
|
|
1145
|
+
commissioning: commissioningOptions,
|
|
1146
|
+
discovery: {
|
|
1147
|
+
knownAddress: ip !== undefined && port !== undefined ? { ip, port, type: 'udp' } : undefined,
|
|
1148
|
+
identifierData: longDiscriminator !== undefined ? { longDiscriminator } : shortDiscriminator !== undefined ? { shortDiscriminator } : {},
|
|
1149
|
+
},
|
|
1150
|
+
passcode: setupPin,
|
|
1151
|
+
};
|
|
1152
|
+
//this.log.info(`Commissioning ... ${JSON.stringify(options)}`);
|
|
1153
|
+
this.log.info('Commissioning ...', options);
|
|
1154
|
+
const nodeId = await this.commissioningController.commissionNode(options);
|
|
1155
|
+
this.mattercontrollerContext.set('nodeId', nodeId.nodeId);
|
|
1156
|
+
this.log.info(`Commissioning successfully done with nodeId: ${nodeId.nodeId}`);
|
|
1157
|
+
// eslint-disable-next-line no-console
|
|
1158
|
+
this.log.info('ActiveSessionInformation:', this.commissioningController.getActiveSessionInformation());
|
|
1159
|
+
} // (hasParameter('pairingcode'))
|
|
1085
1160
|
if (hasParameter('discover')) {
|
|
1086
1161
|
//const discover = await this.commissioningController.discoverCommissionableDevices({ productId: 0x8000, deviceType: 0xfff1 });
|
|
1087
1162
|
//console.log(discover);
|
|
1088
1163
|
}
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
this.log.
|
|
1093
|
-
|
|
1164
|
+
const nodeIds = this.commissioningController.getCommissionedNodes();
|
|
1165
|
+
this.log.info(`***Commissioning controller has ${nodeIds.length} nodes commisioned: ${this.commissioningController.isCommissioned()}`);
|
|
1166
|
+
for (const nodeId of nodeIds) {
|
|
1167
|
+
this.log.info(`***Connecting to commissioned node: ${nodeId}`);
|
|
1168
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1169
|
+
const node = await this.commissioningController.connectNode(nodeId, {
|
|
1170
|
+
attributeChangedCallback: (peerNodeId, { path: { nodeId, clusterId, endpointId, attributeName }, value }) => this.log.info(`***mattributeChangedCallback ${peerNodeId}: Attribute ${nodeId}/${endpointId}/${clusterId}/${attributeName} changed to ${Logger.toJSON(value)}`),
|
|
1171
|
+
eventTriggeredCallback: (peerNodeId, { path: { nodeId, clusterId, endpointId, eventName }, events }) => this.log.info(`***eventTriggeredCallback ${peerNodeId}: Event ${nodeId}/${endpointId}/${clusterId}/${eventName} triggered with ${Logger.toJSON(events)}`),
|
|
1172
|
+
stateInformationCallback: (peerNodeId, info) => {
|
|
1173
|
+
switch (info) {
|
|
1174
|
+
case NodeStateInformation.Connected:
|
|
1175
|
+
this.log.info(`***stateInformationCallback ${peerNodeId}: Node ${nodeId} connected`);
|
|
1176
|
+
break;
|
|
1177
|
+
case NodeStateInformation.Disconnected:
|
|
1178
|
+
this.log.info(`***stateInformationCallback ${peerNodeId}: Node ${nodeId} disconnected`);
|
|
1179
|
+
break;
|
|
1180
|
+
case NodeStateInformation.Reconnecting:
|
|
1181
|
+
this.log.info(`***stateInformationCallback ${peerNodeId}: Node ${nodeId} reconnecting`);
|
|
1182
|
+
break;
|
|
1183
|
+
case NodeStateInformation.WaitingForDeviceDiscovery:
|
|
1184
|
+
this.log.info(`***stateInformationCallback ${peerNodeId}: Node ${nodeId} waiting for device discovery`);
|
|
1185
|
+
break;
|
|
1186
|
+
case NodeStateInformation.StructureChanged:
|
|
1187
|
+
this.log.info(`***stateInformationCallback ${peerNodeId}: Node ${nodeId} structure changed`);
|
|
1188
|
+
break;
|
|
1189
|
+
case NodeStateInformation.Decommissioned:
|
|
1190
|
+
this.log.info(`***stateInformationCallback ${peerNodeId}: Node ${nodeId} decommissioned`);
|
|
1191
|
+
break;
|
|
1192
|
+
default:
|
|
1193
|
+
this.log.info(`***stateInformationCallback ${peerNodeId}: Node ${nodeId} NodeStateInformation.${info}`);
|
|
1194
|
+
break;
|
|
1195
|
+
}
|
|
1196
|
+
},
|
|
1197
|
+
});
|
|
1198
|
+
node.logStructure();
|
|
1199
|
+
// Get the interaction client
|
|
1200
|
+
const interactionClient = await node.getInteractionClient();
|
|
1201
|
+
let cluster;
|
|
1202
|
+
let attributes;
|
|
1203
|
+
// Log BasicInformationCluster
|
|
1204
|
+
cluster = BasicInformationCluster;
|
|
1205
|
+
attributes = await interactionClient.getMultipleAttributes({
|
|
1206
|
+
attributes: [{ clusterId: cluster.id }],
|
|
1207
|
+
});
|
|
1208
|
+
this.log.warn(`Cluster: ${cluster.name} attributes:`);
|
|
1209
|
+
attributes.forEach((attribute) => {
|
|
1210
|
+
this.log.info(
|
|
1211
|
+
// eslint-disable-next-line max-len
|
|
1212
|
+
`- endpoint: ${attribute.path.endpointId} clusterId: ${attribute.path.clusterId} id: ${attribute.path.attributeId} name: ${attribute.path.attributeName}: ${typeof attribute.value === 'object' ? stringify(attribute.value) : attribute.value}`);
|
|
1213
|
+
});
|
|
1214
|
+
// Log PowerSourceCluster
|
|
1215
|
+
cluster = PowerSourceCluster;
|
|
1216
|
+
attributes = await interactionClient.getMultipleAttributes({
|
|
1217
|
+
attributes: [{ clusterId: cluster.id }],
|
|
1218
|
+
});
|
|
1219
|
+
this.log.warn(`Cluster: ${cluster.name} attributes:`);
|
|
1220
|
+
attributes.forEach((attribute) => {
|
|
1221
|
+
this.log.info(
|
|
1222
|
+
// eslint-disable-next-line max-len
|
|
1223
|
+
`- endpoint: ${attribute.path.endpointId} clusterId: ${attribute.path.clusterId} id: ${attribute.path.attributeId} name: ${attribute.path.attributeName}: ${typeof attribute.value === 'object' ? stringify(attribute.value) : attribute.value}`);
|
|
1224
|
+
});
|
|
1225
|
+
// Log ThreadNetworkDiagnostics
|
|
1226
|
+
cluster = ThreadNetworkDiagnosticsCluster;
|
|
1227
|
+
attributes = await interactionClient.getMultipleAttributes({
|
|
1228
|
+
attributes: [{ clusterId: cluster.id }],
|
|
1229
|
+
});
|
|
1230
|
+
this.log.warn(`Cluster: ${cluster.name} attributes:`);
|
|
1231
|
+
attributes.forEach((attribute) => {
|
|
1232
|
+
this.log.info(
|
|
1233
|
+
// eslint-disable-next-line max-len
|
|
1234
|
+
`- endpoint: ${attribute.path.endpointId} clusterId: ${attribute.path.clusterId} id: ${attribute.path.attributeId} name: ${attribute.path.attributeName}: ${typeof attribute.value === 'object' ? stringify(attribute.value) : attribute.value}`);
|
|
1235
|
+
});
|
|
1236
|
+
}
|
|
1094
1237
|
}
|
|
1095
1238
|
if (this.bridgeMode === 'bridge') {
|
|
1096
1239
|
// Plugins are loaded by loadPlugin on startup and plugin.loaded is set to true
|
|
@@ -1643,9 +1786,24 @@ export class Matterbridge extends EventEmitter {
|
|
|
1643
1786
|
this.matterbridgeInformation.rootDirectory = this.rootDirectory;
|
|
1644
1787
|
this.log.debug(`Root Directory: ${this.rootDirectory}`);
|
|
1645
1788
|
// Global node_modules directory
|
|
1789
|
+
/*
|
|
1646
1790
|
this.globalModulesDirectory = await this.getGlobalNodeModules();
|
|
1647
1791
|
this.matterbridgeInformation.globalModulesDirectory = this.globalModulesDirectory;
|
|
1648
1792
|
this.log.debug(`Global node_modules Directory: ${this.globalModulesDirectory}`);
|
|
1793
|
+
*/
|
|
1794
|
+
if (this.nodeContext)
|
|
1795
|
+
this.globalModulesDirectory = await this.nodeContext.get('globalModulesDirectory', '');
|
|
1796
|
+
this.log.debug(`Global node_modules Directory: ${this.globalModulesDirectory}`);
|
|
1797
|
+
this.getGlobalNodeModules()
|
|
1798
|
+
.then(async (globalModulesDirectory) => {
|
|
1799
|
+
this.globalModulesDirectory = globalModulesDirectory;
|
|
1800
|
+
this.matterbridgeInformation.globalModulesDirectory = this.globalModulesDirectory;
|
|
1801
|
+
this.log.debug(`Global node_modules Directory: ${this.globalModulesDirectory}`);
|
|
1802
|
+
await this.nodeContext?.set('globalModulesDirectory', this.globalModulesDirectory);
|
|
1803
|
+
})
|
|
1804
|
+
.catch((error) => {
|
|
1805
|
+
this.log.error(`Error getting global node_modules directory: ${error}`);
|
|
1806
|
+
});
|
|
1649
1807
|
// Create the data directory .matterbridge in the home directory
|
|
1650
1808
|
this.matterbridgeDirectory = path.join(this.homeDirectory, '.matterbridge');
|
|
1651
1809
|
this.matterbridgeInformation.matterbridgeDirectory = this.matterbridgeDirectory;
|
|
@@ -1699,12 +1857,28 @@ export class Matterbridge extends EventEmitter {
|
|
|
1699
1857
|
this.matterbridgeVersion = packageJson.version;
|
|
1700
1858
|
this.matterbridgeInformation.matterbridgeVersion = this.matterbridgeVersion;
|
|
1701
1859
|
this.log.debug(`Matterbridge Version: ${this.matterbridgeVersion}`);
|
|
1860
|
+
// Matterbridge latest version
|
|
1861
|
+
/*
|
|
1702
1862
|
this.matterbridgeLatestVersion = await this.getLatestVersion('matterbridge');
|
|
1703
1863
|
this.matterbridgeInformation.matterbridgeLatestVersion = this.matterbridgeLatestVersion;
|
|
1704
1864
|
this.log.debug(`Matterbridge Latest Version: ${this.matterbridgeLatestVersion}`);
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1865
|
+
*/
|
|
1866
|
+
if (this.nodeContext)
|
|
1867
|
+
this.matterbridgeLatestVersion = await this.nodeContext.get('matterbridgeLatestVersion', '');
|
|
1868
|
+
this.log.debug(`Matterbridge Latest Version: ${this.matterbridgeLatestVersion}`);
|
|
1869
|
+
this.getLatestVersion('matterbridge')
|
|
1870
|
+
.then(async (matterbridgeLatestVersion) => {
|
|
1871
|
+
this.matterbridgeLatestVersion = matterbridgeLatestVersion;
|
|
1872
|
+
this.matterbridgeInformation.matterbridgeLatestVersion = this.matterbridgeLatestVersion;
|
|
1873
|
+
this.log.debug(`Matterbridge Latest Version: ${this.matterbridgeLatestVersion}`);
|
|
1874
|
+
await this.nodeContext?.set('matterbridgeLatestVersion', this.matterbridgeLatestVersion);
|
|
1875
|
+
if (this.matterbridgeVersion !== this.matterbridgeLatestVersion) {
|
|
1876
|
+
this.log.warn(`Matterbridge is out of date. Current version: ${this.matterbridgeVersion}, Latest version: ${this.matterbridgeLatestVersion}`);
|
|
1877
|
+
}
|
|
1878
|
+
})
|
|
1879
|
+
.catch((error) => {
|
|
1880
|
+
this.log.error(`Error getting Matterbridge latest version: ${error}`);
|
|
1881
|
+
});
|
|
1708
1882
|
// Current working directory
|
|
1709
1883
|
const currentDir = process.cwd();
|
|
1710
1884
|
this.log.debug(`Current Working Directory: ${currentDir}`);
|
|
@@ -1876,7 +2050,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
1876
2050
|
// Endpoint to receive commands
|
|
1877
2051
|
this.expressApp.post('/api/command/:command/:param', async (req, res) => {
|
|
1878
2052
|
const command = req.params.command;
|
|
1879
|
-
|
|
2053
|
+
let param = req.params.param;
|
|
1880
2054
|
this.log.debug(`The frontend sent /api/command/${command}/${param}`);
|
|
1881
2055
|
if (!command) {
|
|
1882
2056
|
res.status(400).json({ error: 'No command provided' });
|
|
@@ -1912,9 +2086,55 @@ export class Matterbridge extends EventEmitter {
|
|
|
1912
2086
|
if (command === 'update') {
|
|
1913
2087
|
this.log.warn(`The /api/command/${command} is not yet implemented`);
|
|
1914
2088
|
}
|
|
1915
|
-
// Handle the command addplugin from
|
|
2089
|
+
// Handle the command addplugin from Home C:\Users\lligu\GitHub\matterbridge-example-accessory-platform
|
|
1916
2090
|
if (command === 'addplugin') {
|
|
1917
|
-
|
|
2091
|
+
param = param.replace(/\*/g, '\\');
|
|
2092
|
+
if (this.registeredPlugins.find((plugin) => plugin.name === param)) {
|
|
2093
|
+
this.log.warn(`Plugin ${plg}${param}${wr} already added to matterbridge`);
|
|
2094
|
+
res.json({ message: 'Command received' });
|
|
2095
|
+
return;
|
|
2096
|
+
}
|
|
2097
|
+
const packageJsonPath = await this.resolvePluginName(param);
|
|
2098
|
+
if (!packageJsonPath) {
|
|
2099
|
+
this.log.error(`Error resolving plugin ${plg}${param}${er}`);
|
|
2100
|
+
res.json({ message: 'Command received' });
|
|
2101
|
+
return;
|
|
2102
|
+
}
|
|
2103
|
+
this.log.debug(`Loading plugin from ${plg}${packageJsonPath}${db}`);
|
|
2104
|
+
try {
|
|
2105
|
+
// Load the package.json of the plugin
|
|
2106
|
+
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
|
|
2107
|
+
const plugin = { path: packageJsonPath, type: '', name: packageJson.name, version: packageJson.version, description: packageJson.description, author: packageJson.author, enabled: true };
|
|
2108
|
+
if (await this.loadPlugin(plugin)) {
|
|
2109
|
+
this.registeredPlugins.push(plugin);
|
|
2110
|
+
await this.nodeContext?.set('plugins', this.getBaseRegisteredPlugins());
|
|
2111
|
+
this.log.info(`Plugin ${plg}${packageJsonPath}${nf} type ${plugin.type} added to matterbridge. Restart required.`);
|
|
2112
|
+
}
|
|
2113
|
+
else {
|
|
2114
|
+
this.log.error(`Error adding plugin ${plg}${packageJsonPath}${er}`);
|
|
2115
|
+
}
|
|
2116
|
+
}
|
|
2117
|
+
catch (error) {
|
|
2118
|
+
this.log.error(`Error adding plugin ${plg}${packageJsonPath}${er}`);
|
|
2119
|
+
res.json({ message: 'Command received' });
|
|
2120
|
+
return;
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2123
|
+
// Handle the command removeplugin from Home
|
|
2124
|
+
if (command === 'removeplugin') {
|
|
2125
|
+
const index = this.registeredPlugins.findIndex((registeredPlugin) => registeredPlugin.name === param);
|
|
2126
|
+
if (index !== -1) {
|
|
2127
|
+
if (this.registeredPlugins[index].platform) {
|
|
2128
|
+
await this.registeredPlugins[index].platform?.onShutdown('The plugin has been removed.');
|
|
2129
|
+
await this.savePluginConfig(this.registeredPlugins[index]);
|
|
2130
|
+
}
|
|
2131
|
+
this.registeredPlugins.splice(index, 1);
|
|
2132
|
+
await this.nodeContext?.set('plugins', this.getBaseRegisteredPlugins());
|
|
2133
|
+
this.log.info(`Plugin ${plg}${param}${nf} removed from matterbridge`);
|
|
2134
|
+
}
|
|
2135
|
+
else {
|
|
2136
|
+
this.log.warn(`Plugin ${plg}${param}${wr} not registered in matterbridge`);
|
|
2137
|
+
}
|
|
1918
2138
|
}
|
|
1919
2139
|
// Handle the command enableplugin from Home
|
|
1920
2140
|
if (command === 'enableplugin') {
|
|
@@ -1977,10 +2197,12 @@ export class Matterbridge extends EventEmitter {
|
|
|
1977
2197
|
attributes += `Position: ${clusterServer.getCurrentPositionAttribute()} `;
|
|
1978
2198
|
if (clusterServer.name === 'WindowCovering')
|
|
1979
2199
|
attributes += `Cover position: ${clusterServer.attributes.currentPositionLiftPercent100ths.getLocal() / 100}% `;
|
|
2200
|
+
if (clusterServer.name === 'DoorLock')
|
|
2201
|
+
attributes += `State: ${clusterServer.attributes.lockState.getLocal() === 1 ? 'Locked' : 'Not locked'} `;
|
|
1980
2202
|
if (clusterServer.name === 'LevelControl')
|
|
1981
2203
|
attributes += `Level: ${clusterServer.getCurrentLevelAttribute()}% `;
|
|
1982
2204
|
if (clusterServer.name === 'ColorControl')
|
|
1983
|
-
attributes += `Hue: ${clusterServer.getCurrentHueAttribute()} Saturation: ${clusterServer.getCurrentSaturationAttribute()}% `;
|
|
2205
|
+
attributes += `Hue: ${Math.round(clusterServer.getCurrentHueAttribute())} Saturation: ${Math.round(clusterServer.getCurrentSaturationAttribute())}% `;
|
|
1984
2206
|
if (clusterServer.name === 'BooleanState')
|
|
1985
2207
|
attributes += `Contact: ${clusterServer.getStateValueAttribute()} `;
|
|
1986
2208
|
if (clusterServer.name === 'OccupancySensing')
|