matterbridge 2.1.4-dev.3 → 2.1.5-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -1
- package/README-DOCKER.md +11 -7
- package/dist/matterbridge.js +16 -12
- package/dist/matterbridgePlatform.js +1 -1
- package/dist/utils/utils.js +47 -3
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -25,13 +25,29 @@ You need to update all plugins you use and Matterbridge in the same moment.
|
|
|
25
25
|
|
|
26
26
|
I suggest to first update all plugins without restarting and then to update Matterbridge so when it restarts, all versions will be the latest.
|
|
27
27
|
|
|
28
|
+
If you use docker, all plugins are already installed in the image so you just need to pull the new image.
|
|
29
|
+
|
|
28
30
|
Compatibility list:
|
|
29
31
|
matterbridge-shelly v. 1.1.5
|
|
30
32
|
matterbridge-zigbee2mqtt v. 2.4.4
|
|
31
33
|
matterbridge-somfy-tahoma v. 1.2.3
|
|
32
34
|
matterbridge-hass v. 0.0.8
|
|
33
35
|
|
|
34
|
-
## [2.1.
|
|
36
|
+
## [2.1.5] - 2025-02-08
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
|
|
40
|
+
### Changed
|
|
41
|
+
|
|
42
|
+
- [matterbridge]: Calls getNpmPackageVersion() instead of npm to get latest version.
|
|
43
|
+
|
|
44
|
+
### Fixed
|
|
45
|
+
|
|
46
|
+
<a href="https://www.buymeacoffee.com/luligugithub">
|
|
47
|
+
<img src="./yellow-button.png" alt="Buy me a coffee" width="120">
|
|
48
|
+
</a>
|
|
49
|
+
|
|
50
|
+
## [2.1.4] - 2025-02-07
|
|
35
51
|
|
|
36
52
|
### Added
|
|
37
53
|
|
|
@@ -42,6 +58,7 @@ matterbridge-hass v. 0.0.8
|
|
|
42
58
|
### Changed
|
|
43
59
|
|
|
44
60
|
- [package]: Update matter.js to 0.12.3.
|
|
61
|
+
- [matter.js]: Since matter.js storage cannot properly encode non latin names, they are encoded before passing them to matter.js.
|
|
45
62
|
|
|
46
63
|
<a href="https://www.buymeacoffee.com/luligugithub">
|
|
47
64
|
<img src="./yellow-button.png" alt="Buy me a coffee" width="120">
|
package/README-DOCKER.md
CHANGED
|
@@ -48,11 +48,13 @@ The container must have full access to the host network (needed for mdns).
|
|
|
48
48
|
|
|
49
49
|
```
|
|
50
50
|
sudo docker run --name matterbridge \
|
|
51
|
-
-v
|
|
52
|
-
-v
|
|
51
|
+
-v /home/<USER>/Matterbridge:/root/Matterbridge \
|
|
52
|
+
-v /home/<USER>/.matterbridge:/root/.matterbridge \
|
|
53
53
|
--network host --restart always -d luligu/matterbridge:latest
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
+
Replace USER with your user name (i.e. ubuntu or pi).
|
|
57
|
+
|
|
56
58
|
You may need to adapt the script to your setup.
|
|
57
59
|
|
|
58
60
|
### Run with docker compose
|
|
@@ -63,14 +65,16 @@ The docker-compose.yml file is available in the docker directory of the package
|
|
|
63
65
|
services:
|
|
64
66
|
matterbridge:
|
|
65
67
|
container_name: matterbridge
|
|
66
|
-
image: luligu/matterbridge:latest
|
|
67
|
-
network_mode: host
|
|
68
|
-
restart: always
|
|
68
|
+
image: luligu/matterbridge:latest # Matterbridge image with the tag latest
|
|
69
|
+
network_mode: host # Ensures the Matter mdns works
|
|
70
|
+
restart: always # Ensures the container always restarts automatically
|
|
69
71
|
volumes:
|
|
70
|
-
- "
|
|
71
|
-
- "
|
|
72
|
+
- "/home/<USER>/Matterbridge:/root/Matterbridge" # Mounts the Matterbridge plugin directory
|
|
73
|
+
- "/home/<USER>/.matterbridge:/root/.matterbridge" # Mounts the Matterbridge storage directory
|
|
72
74
|
```
|
|
73
75
|
|
|
76
|
+
Replace USER with your user name (i.e. ubuntu or pi).
|
|
77
|
+
|
|
74
78
|
copy it in the home directory or edit the existing one to add the matterbridge service.
|
|
75
79
|
|
|
76
80
|
Then start docker compose with:
|
package/dist/matterbridge.js
CHANGED
|
@@ -7,7 +7,7 @@ import path from 'path';
|
|
|
7
7
|
import { randomBytes } from 'crypto';
|
|
8
8
|
import { NodeStorageManager } from './storage/export.js';
|
|
9
9
|
import { AnsiLogger, UNDERLINE, UNDERLINEOFF, YELLOW, db, debugStringify, BRIGHT, RESET, er, nf, rs, wr, RED, GREEN, zb, CYAN, nt } from './logger/export.js';
|
|
10
|
-
import { logInterfaces, copyDirectory, getParameter, getIntParameter, hasParameter } from './utils/utils.js';
|
|
10
|
+
import { logInterfaces, copyDirectory, getParameter, getIntParameter, hasParameter, getNpmPackageVersion } from './utils/utils.js';
|
|
11
11
|
import { PluginManager } from './pluginManager.js';
|
|
12
12
|
import { DeviceManager } from './deviceManager.js';
|
|
13
13
|
import { MatterbridgeEndpoint } from './matterbridgeEndpoint.js';
|
|
@@ -518,6 +518,10 @@ export class Matterbridge extends EventEmitter {
|
|
|
518
518
|
if (getIntParameter('frontend') !== 0 || getIntParameter('frontend') === undefined)
|
|
519
519
|
await this.frontend.start(getIntParameter('frontend'));
|
|
520
520
|
this.frontend.logLevel = this.log.logLevel;
|
|
521
|
+
this.getMatterbridgeLatestVersion();
|
|
522
|
+
for (const plugin of this.plugins) {
|
|
523
|
+
this.getPluginLatestVersion(plugin);
|
|
524
|
+
}
|
|
521
525
|
this.checkUpdateInterval = setInterval(() => {
|
|
522
526
|
this.getMatterbridgeLatestVersion();
|
|
523
527
|
for (const plugin of this.plugins) {
|
|
@@ -787,11 +791,10 @@ export class Matterbridge extends EventEmitter {
|
|
|
787
791
|
});
|
|
788
792
|
}
|
|
789
793
|
async getMatterbridgeLatestVersion() {
|
|
790
|
-
|
|
791
|
-
.then(async (
|
|
792
|
-
this.matterbridgeLatestVersion =
|
|
793
|
-
this.matterbridgeInformation.matterbridgeLatestVersion =
|
|
794
|
-
this.log.debug(`Matterbridge Latest Version: ${this.matterbridgeLatestVersion}`);
|
|
794
|
+
getNpmPackageVersion('matterbridge')
|
|
795
|
+
.then(async (version) => {
|
|
796
|
+
this.matterbridgeLatestVersion = version;
|
|
797
|
+
this.matterbridgeInformation.matterbridgeLatestVersion = version;
|
|
795
798
|
await this.nodeContext?.set('matterbridgeLatestVersion', this.matterbridgeLatestVersion);
|
|
796
799
|
if (this.matterbridgeVersion !== this.matterbridgeLatestVersion) {
|
|
797
800
|
this.log.notice(`Matterbridge is out of date. Current version: ${this.matterbridgeVersion}. Latest version: ${this.matterbridgeLatestVersion}.`);
|
|
@@ -799,19 +802,20 @@ export class Matterbridge extends EventEmitter {
|
|
|
799
802
|
else {
|
|
800
803
|
this.log.debug(`Matterbridge is up to date. Current version: ${this.matterbridgeVersion}. Latest version: ${this.matterbridgeLatestVersion}.`);
|
|
801
804
|
}
|
|
805
|
+
this.frontend.wssSendRefreshRequired();
|
|
802
806
|
})
|
|
803
807
|
.catch((error) => {
|
|
804
808
|
this.log.error(`Error getting Matterbridge latest version: ${error.message}`);
|
|
805
809
|
});
|
|
806
810
|
}
|
|
807
811
|
async getPluginLatestVersion(plugin) {
|
|
808
|
-
|
|
809
|
-
.then(
|
|
810
|
-
plugin.latestVersion =
|
|
811
|
-
if (plugin.version !== latestVersion)
|
|
812
|
-
this.log.notice(`The plugin ${plg}${plugin.name}${nt} is out of date. Current version: ${plugin.version}. Latest version: ${latestVersion}.`);
|
|
812
|
+
getNpmPackageVersion(plugin.name)
|
|
813
|
+
.then((version) => {
|
|
814
|
+
plugin.latestVersion = version;
|
|
815
|
+
if (plugin.version !== plugin.latestVersion)
|
|
816
|
+
this.log.notice(`The plugin ${plg}${plugin.name}${nt} is out of date. Current version: ${plugin.version}. Latest version: ${plugin.latestVersion}.`);
|
|
813
817
|
else
|
|
814
|
-
this.log.debug(`The plugin ${plg}${plugin.name}${db} is up to date. Current version: ${plugin.version}. Latest version: ${latestVersion}.`);
|
|
818
|
+
this.log.debug(`The plugin ${plg}${plugin.name}${db} is up to date. Current version: ${plugin.version}. Latest version: ${plugin.latestVersion}.`);
|
|
815
819
|
})
|
|
816
820
|
.catch((error) => {
|
|
817
821
|
this.log.error(`Error getting ${plg}${plugin.name}${er} latest version: ${error.message}`);
|
|
@@ -64,7 +64,7 @@ export class MatterbridgePlatform {
|
|
|
64
64
|
return;
|
|
65
65
|
}
|
|
66
66
|
if (device.deviceName && checkNotLatinCharacters(device.deviceName)) {
|
|
67
|
-
this.log.debug(`Device with name ${CYAN}${device.deviceName}${db} has non latin characters
|
|
67
|
+
this.log.debug(`Device with name ${CYAN}${device.deviceName}${db} has non latin characters.`);
|
|
68
68
|
}
|
|
69
69
|
await this.matterbridge.addBridgedEndpoint(this.name, device);
|
|
70
70
|
if (device.uniqueId)
|
package/dist/utils/utils.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import os from 'os';
|
|
2
|
-
import { createWriteStream, statSync } from 'fs';
|
|
3
2
|
import path from 'path';
|
|
4
|
-
import
|
|
3
|
+
import { createWriteStream, statSync } from 'fs';
|
|
5
4
|
import { promises as fs } from 'fs';
|
|
5
|
+
import * as dns from 'dns';
|
|
6
6
|
import { AnsiLogger, idn, rs } from 'node-ansi-logger';
|
|
7
7
|
const log = new AnsiLogger({ logName: 'MatterbridgeUtils', logTimestampFormat: 4, logLevel: "info" });
|
|
8
8
|
export function deepEqual(a, b, excludeProperties = []) {
|
|
@@ -351,7 +351,7 @@ export async function copyDirectory(srcDir, destDir) {
|
|
|
351
351
|
}
|
|
352
352
|
export async function resolveHostname(hostname, family = 4) {
|
|
353
353
|
try {
|
|
354
|
-
const addresses = await dns.promises.lookup(hostname.toLowerCase()
|
|
354
|
+
const addresses = await dns.promises.lookup(hostname.toLowerCase(), { family });
|
|
355
355
|
return addresses.address;
|
|
356
356
|
}
|
|
357
357
|
catch (error) {
|
|
@@ -383,3 +383,47 @@ export function getIntParameter(name) {
|
|
|
383
383
|
return undefined;
|
|
384
384
|
return intValue;
|
|
385
385
|
}
|
|
386
|
+
export async function getNpmPackageVersion(packageName, tag = 'latest', timeout = 5000) {
|
|
387
|
+
const https = await import('https');
|
|
388
|
+
return new Promise((resolve, reject) => {
|
|
389
|
+
const url = `https://registry.npmjs.org/${packageName}`;
|
|
390
|
+
const controller = new AbortController();
|
|
391
|
+
const timeoutId = setTimeout(() => {
|
|
392
|
+
controller.abort();
|
|
393
|
+
reject(new Error(`Request timed out after ${timeout / 1000} seconds`));
|
|
394
|
+
}, timeout);
|
|
395
|
+
const req = https.get(url, { signal: controller.signal }, (res) => {
|
|
396
|
+
let data = '';
|
|
397
|
+
if (res.statusCode !== 200) {
|
|
398
|
+
clearTimeout(timeoutId);
|
|
399
|
+
res.resume();
|
|
400
|
+
req.destroy();
|
|
401
|
+
reject(new Error(`Failed to fetch data. Status code: ${res.statusCode}`));
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
res.on('data', (chunk) => {
|
|
405
|
+
data += chunk;
|
|
406
|
+
});
|
|
407
|
+
res.on('end', () => {
|
|
408
|
+
clearTimeout(timeoutId);
|
|
409
|
+
try {
|
|
410
|
+
const jsonData = JSON.parse(data);
|
|
411
|
+
const version = jsonData['dist-tags']?.[tag];
|
|
412
|
+
if (version) {
|
|
413
|
+
resolve(version);
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
reject(new Error(`Tag "${tag}" not found for package "${packageName}"`));
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
catch (error) {
|
|
420
|
+
reject(new Error(`Failed to parse response JSON: ${error instanceof Error ? error.message : error}`));
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
});
|
|
424
|
+
req.on('error', (error) => {
|
|
425
|
+
clearTimeout(timeoutId);
|
|
426
|
+
reject(new Error(`Request failed: ${error instanceof Error ? error.message : error}`));
|
|
427
|
+
});
|
|
428
|
+
});
|
|
429
|
+
}
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "matterbridge",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.5-dev.1",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "matterbridge",
|
|
9
|
-
"version": "2.1.
|
|
9
|
+
"version": "2.1.5-dev.1",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@matter/main": "0.12.3",
|