From 26bfaa4b4e5e718daceb252e647261860fd562f9 Mon Sep 17 00:00:00 2001 From: Luligu Date: Tue, 26 Nov 2024 17:22:20 +0100 Subject: [PATCH 01/15] Changed default minLevel to 0 in LevelControlCluster --- CHANGELOG.md | 8 +++++++- README.md | 5 +++-- src/matterbridgeDevice.ts | 8 ++++---- src/matterbridgeEndpoint.ts | 8 ++++---- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f1bd9754..b2cbe9f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,12 @@ Tamer (https://github.com/tammeryousef1006) has created the Matterbridge Discord Feel free to join (the link is now permanent)! +## [1.6.3] - 2024-11-xx + +### Changed + +- [matterbridge]: Changed default minLevel to 0 in LevelControlCluster utility methods. + ## [1.6.2] - 2024-11-25 ### Added @@ -30,6 +36,7 @@ Feel free to join (the link is now permanent)! - [config]: Added version to the config. - [frontend]: Added badge "edge" when running in edge mode. - [matterbridge]: Added addTagList method. +- [matterbridge]: Added minLevel, maxLevel and onLevel to LevelControlCluster utility methods. ### Changed @@ -44,7 +51,6 @@ Feel free to join (the link is now permanent)! - [frontend]: Update QRCode package and QRCode level to M. - [frontend]: Added font roboto. - [matterbridge]: Removed BasicInformationCluster from Aggregator. -- [matterbridge]: Added minLevel, maxLevel and onLevel to LevelControlCluster utility methods. ### Fixed diff --git a/README.md b/README.md index f017137d..55b85eb4 100644 --- a/README.md +++ b/README.md @@ -391,6 +391,7 @@ If you have more then one Apple TV or Home Pod, you can herve better results set So far is the only controller supporting some Matter 1.2 and 1.3 device type: - airQualitySensor code 0x002c (Matter 1.2) +- smokesmokeCoAlarm code 0x0076 (Matter 1.2) - waterFreezeDetector code 0x0041 (Matter 1.3 with only BooleanState cluster) - waterLeakDetector code 0x0043 (Matter 1.3 with only BooleanState cluster) - rainSensor code 0x0044 (Matter 1.3 with only BooleanState cluster) @@ -399,11 +400,11 @@ So far is the only controller supporting some Matter 1.2 and 1.3 device type: Electrical measurements: - electrical measurements from EveHistoryCluster (used in Matterbridge plugins) -- electricalSensor code 0x0510 with clusters: ElectricalPowerMeasurement and ElectricalEnergyMeasurement (still in dev but fully working!) +- electricalSensor code 0x0510 with clusters: ElectricalPowerMeasurement and ElectricalEnergyMeasurement Other supported cluster: -- ModeSelect +- modeSelect code 0x27 with ModeSelect cluster ## Home Assistant issues (Matter Server for HA is still in Beta) diff --git a/src/matterbridgeDevice.ts b/src/matterbridgeDevice.ts index c04b6f8a..fed318f9 100644 --- a/src/matterbridgeDevice.ts +++ b/src/matterbridgeDevice.ts @@ -1125,11 +1125,11 @@ export class MatterbridgeDevice extends extendPublicHandlerMethods Date: Tue, 26 Nov 2024 20:02:59 +0100 Subject: [PATCH 02/15] Add triggerEvent to matterbridgeDevice --- package-lock.json | 138 +++++++++++++++++++------------------- package.json | 8 +-- src/matterbridgeDevice.ts | 35 ++++++++++ 3 files changed, 108 insertions(+), 73 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0baa5370..ccb535c0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "matterbridge", - "version": "1.6.2", + "version": "1.6.3-dev.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "matterbridge", - "version": "1.6.2", + "version": "1.6.3-dev.1", "license": "Apache-2.0", "dependencies": { "@matter/main": "^0.11.5", @@ -29,17 +29,17 @@ "@types/eslint__js": "8.42.3", "@types/express": "5.0.0", "@types/jest": "29.5.14", - "@types/node": "22.9.3", + "@types/node": "22.10.0", "@types/ws": "8.5.13", "eslint": "9.15.0", "eslint-config-prettier": "9.1.0", "eslint-plugin-jest": "28.9.0", "eslint-plugin-prettier": "5.2.1", "jest": "29.7.0", - "prettier": "3.3.3", + "prettier": "3.4.1", "ts-jest": "29.2.5", "typescript": "5.7.2", - "typescript-eslint": "8.15.0" + "typescript-eslint": "8.16.0" }, "engines": { "node": ">=18.0.0" @@ -1733,13 +1733,13 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.9.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.3.tgz", - "integrity": "sha512-F3u1fs/fce3FFk+DAxbxc78DF8x0cY09RRL8GnXLmkJ1jvx3TtPdWoTT5/NiYfI5ASqXBmfqJi9dZ3gxMx4lzw==", + "version": "22.10.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.0.tgz", + "integrity": "sha512-XC70cRZVElFHfIUB40FgZOBbgJYFKKMa5nb9lxcwYstFG/Mi+/Y0bGS+rs6Dmhmkpq4pnNiLiuZAbc02YCOnmA==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.19.8" + "undici-types": "~6.20.0" } }, "node_modules/@types/qs": { @@ -1824,17 +1824,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.15.0.tgz", - "integrity": "sha512-+zkm9AR1Ds9uLWN3fkoeXgFppaQ+uEVtfOV62dDmsy9QCNqlRHWNEck4yarvRNrvRcHQLGfqBNui3cimoz8XAg==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.16.0.tgz", + "integrity": "sha512-5YTHKV8MYlyMI6BaEG7crQ9BhSc8RxzshOReKwZwRWN0+XvvTOm+L/UYLCYxFpfwYuAAqhxiq4yae0CMFwbL7Q==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.15.0", - "@typescript-eslint/type-utils": "8.15.0", - "@typescript-eslint/utils": "8.15.0", - "@typescript-eslint/visitor-keys": "8.15.0", + "@typescript-eslint/scope-manager": "8.16.0", + "@typescript-eslint/type-utils": "8.16.0", + "@typescript-eslint/utils": "8.16.0", + "@typescript-eslint/visitor-keys": "8.16.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1858,16 +1858,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.15.0.tgz", - "integrity": "sha512-7n59qFpghG4uazrF9qtGKBZXn7Oz4sOMm8dwNWDQY96Xlm2oX67eipqcblDj+oY1lLCbf1oltMZFpUso66Kl1A==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.16.0.tgz", + "integrity": "sha512-D7DbgGFtsqIPIFMPJwCad9Gfi/hC0PWErRRHFnaCWoEDYi5tQUDiJCTmGUbBiLzjqAck4KcXt9Ayj0CNlIrF+w==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "8.15.0", - "@typescript-eslint/types": "8.15.0", - "@typescript-eslint/typescript-estree": "8.15.0", - "@typescript-eslint/visitor-keys": "8.15.0", + "@typescript-eslint/scope-manager": "8.16.0", + "@typescript-eslint/types": "8.16.0", + "@typescript-eslint/typescript-estree": "8.16.0", + "@typescript-eslint/visitor-keys": "8.16.0", "debug": "^4.3.4" }, "engines": { @@ -1887,14 +1887,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.15.0.tgz", - "integrity": "sha512-QRGy8ADi4J7ii95xz4UoiymmmMd/zuy9azCaamnZ3FM8T5fZcex8UfJcjkiEZjJSztKfEBe3dZ5T/5RHAmw2mA==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.16.0.tgz", + "integrity": "sha512-mwsZWubQvBki2t5565uxF0EYvG+FwdFb8bMtDuGQLdCCnGPrDEDvm1gtfynuKlnpzeBRqdFCkMf9jg1fnAK8sg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.15.0", - "@typescript-eslint/visitor-keys": "8.15.0" + "@typescript-eslint/types": "8.16.0", + "@typescript-eslint/visitor-keys": "8.16.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1905,14 +1905,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.15.0.tgz", - "integrity": "sha512-UU6uwXDoI3JGSXmcdnP5d8Fffa2KayOhUUqr/AiBnG1Gl7+7ut/oyagVeSkh7bxQ0zSXV9ptRh/4N15nkCqnpw==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.16.0.tgz", + "integrity": "sha512-IqZHGG+g1XCWX9NyqnI/0CX5LL8/18awQqmkZSl2ynn8F76j579dByc0jhfVSnSnhf7zv76mKBQv9HQFKvDCgg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.15.0", - "@typescript-eslint/utils": "8.15.0", + "@typescript-eslint/typescript-estree": "8.16.0", + "@typescript-eslint/utils": "8.16.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -1933,9 +1933,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.15.0.tgz", - "integrity": "sha512-n3Gt8Y/KyJNe0S3yDCD2RVKrHBC4gTUcLTebVBXacPy091E6tNspFLKRXlk3hwT4G55nfr1n2AdFqi/XMxzmPQ==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.16.0.tgz", + "integrity": "sha512-NzrHj6thBAOSE4d9bsuRNMvk+BvaQvmY4dDglgkgGC0EW/tB3Kelnp3tAKH87GEwzoxgeQn9fNGRyFJM/xd+GQ==", "dev": true, "license": "MIT", "engines": { @@ -1947,14 +1947,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.15.0.tgz", - "integrity": "sha512-1eMp2JgNec/niZsR7ioFBlsh/Fk0oJbhaqO0jRyQBMgkz7RrFfkqF9lYYmBoGBaSiLnu8TAPQTwoTUiSTUW9dg==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.16.0.tgz", + "integrity": "sha512-E2+9IzzXMc1iaBy9zmo+UYvluE3TW7bCGWSF41hVWUE01o8nzr1rvOQYSxelxr6StUvRcTMe633eY8mXASMaNw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.15.0", - "@typescript-eslint/visitor-keys": "8.15.0", + "@typescript-eslint/types": "8.16.0", + "@typescript-eslint/visitor-keys": "8.16.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2002,16 +2002,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.15.0.tgz", - "integrity": "sha512-k82RI9yGhr0QM3Dnq+egEpz9qB6Un+WLYhmoNcvl8ltMEededhh7otBVVIDDsEEttauwdY/hQoSsOv13lxrFzQ==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.16.0.tgz", + "integrity": "sha512-C1zRy/mOL8Pj157GiX4kaw7iyRLKfJXBR3L82hk5kS/GyHcOFmy4YUq/zfZti72I9wnuQtA/+xzft4wCC8PJdA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.15.0", - "@typescript-eslint/types": "8.15.0", - "@typescript-eslint/typescript-estree": "8.15.0" + "@typescript-eslint/scope-manager": "8.16.0", + "@typescript-eslint/types": "8.16.0", + "@typescript-eslint/typescript-estree": "8.16.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2030,13 +2030,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.15.0.tgz", - "integrity": "sha512-h8vYOulWec9LhpwfAdZf2bjr8xIp0KNKnpgqSz0qqYYKAW/QZKw3ktRndbiAtUz4acH4QLQavwZBYCc0wulA/Q==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.16.0.tgz", + "integrity": "sha512-pq19gbaMOmFE3CbL0ZB8J8BFCo2ckfHBfaIsaOZgBIF4EoISJIdLX5xRhd0FGB0LlHReNRuzoJoMGpTjq8F2CQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.15.0", + "@typescript-eslint/types": "8.16.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -3130,9 +3130,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.64", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.64.tgz", - "integrity": "sha512-IXEuxU+5ClW2IGEYFC2T7szbyVgehupCWQe5GNh+H065CD6U6IFN0s4KeAMFGNmQolRU4IV7zGBWSYMmZ8uuqQ==", + "version": "1.5.65", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.65.tgz", + "integrity": "sha512-PWVzBjghx7/wop6n22vS2MLU8tKGd4Q91aCEGhG/TYmW6PP5OcSXcdnxTe1NNt0T66N8D6jxh4kC8UsdzOGaIw==", "dev": true, "license": "ISC" }, @@ -5909,9 +5909,9 @@ } }, "node_modules/prettier": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", - "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.1.tgz", + "integrity": "sha512-G+YdqtITVZmOJje6QkXQWzl3fSfMxFwm1tjTyo9exhkmWSqC4Yhd1+lug++IlR2mvRVAxEDDWYkQdeSztajqgg==", "dev": true, "license": "MIT", "bin": { @@ -6828,9 +6828,9 @@ } }, "node_modules/ts-api-utils": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.1.tgz", - "integrity": "sha512-5RU2/lxTA3YUZxju61HO2U6EoZLvBLtmV2mbTvqyu4a/7s7RmJPT+1YekhMVsQhznRWk/czIwDUg+V8Q9ZuG4w==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.2.tgz", + "integrity": "sha512-ZF5gQIQa/UmzfvxbHZI3JXN0/Jt+vnAfAviNRAMc491laiK6YCLpCW9ft8oaCRFOTxCZtUTE6XB0ZQAe3olntw==", "dev": true, "license": "MIT", "engines": { @@ -6960,15 +6960,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.15.0.tgz", - "integrity": "sha512-wY4FRGl0ZI+ZU4Jo/yjdBu0lVTSML58pu6PgGtJmCufvzfV565pUF6iACQt092uFOd49iLOTX/sEVmHtbSrS+w==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.16.0.tgz", + "integrity": "sha512-wDkVmlY6O2do4V+lZd0GtRfbtXbeD0q9WygwXXSJnC1xorE8eqyC2L1tJimqpSeFrOzRlYtWnUp/uzgHQOgfBQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.15.0", - "@typescript-eslint/parser": "8.15.0", - "@typescript-eslint/utils": "8.15.0" + "@typescript-eslint/eslint-plugin": "8.16.0", + "@typescript-eslint/parser": "8.16.0", + "@typescript-eslint/utils": "8.16.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6987,9 +6987,9 @@ } }, "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", "dev": true, "license": "MIT" }, diff --git a/package.json b/package.json index c47c0e1f..c7d6e886 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matterbridge", - "version": "1.6.2", + "version": "1.6.3-dev.1", "description": "Matterbridge plugin manager for Matter", "author": "https://github.com/Luligu", "license": "Apache-2.0", @@ -138,16 +138,16 @@ "@types/eslint__js": "8.42.3", "@types/express": "5.0.0", "@types/jest": "29.5.14", - "@types/node": "22.9.3", + "@types/node": "22.10.0", "@types/ws": "8.5.13", "eslint": "9.15.0", "eslint-config-prettier": "9.1.0", "eslint-plugin-jest": "28.9.0", "eslint-plugin-prettier": "5.2.1", "jest": "29.7.0", - "prettier": "3.3.3", + "prettier": "3.4.1", "ts-jest": "29.2.5", "typescript": "5.7.2", - "typescript-eslint": "8.15.0" + "typescript-eslint": "8.16.0" } } diff --git a/src/matterbridgeDevice.ts b/src/matterbridgeDevice.ts index fed318f9..8635dea3 100644 --- a/src/matterbridgeDevice.ts +++ b/src/matterbridgeDevice.ts @@ -540,6 +540,41 @@ export class MatterbridgeDevice extends extendPublicHandlerMethods} payload - The payload of the event to trigger. + * @param {AnsiLogger} [log] - Optional logger for error and info messages. + * @param {Endpoint} [endpoint] - Optional the child endpoint to retrieve the event from. + */ + triggerEvent(clusterId: ClusterId, event: string, payload: Record, log?: AnsiLogger, endpoint?: Endpoint) { + if (!endpoint) endpoint = this as Endpoint; + if (!endpoint.number) return; + + const clusterServer = endpoint.getClusterServerById(clusterId); + if (!clusterServer) { + log?.error(`triggerEvent error: Cluster ${clusterId} not found on endpoint ${endpoint.name}:${endpoint.number}`); + return; + } + const capitalizedEventName = event.charAt(0).toUpperCase() + event.slice(1); + if (!clusterServer.isEventSupportedByName(event) && !clusterServer.isEventSupportedByName(capitalizedEventName)) { + if (log) log.error(`triggerEvent error: Event ${event} not found on Cluster ${clusterServer.name} on endpoint ${endpoint.name}:${endpoint.number}`); + return; + } + // Find the getter method + // eslint-disable-next-line @typescript-eslint/no-explicit-any + if (!(clusterServer as any)[`trigger${capitalizedEventName}Event`]) { + log?.error(`triggerEvent error: Trigger trigger${capitalizedEventName}Event not found on Cluster ${clusterServer.name} on endpoint ${endpoint.name}:${endpoint.number}`); + return; + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-empty-object-type + const trigger = (clusterServer as any)[`trigger${capitalizedEventName}Event`] as (payload: Record) => {}; + trigger(payload); + log?.info(`${db}Trigger event ${hk}${clusterServer.name}.${capitalizedEventName}${db} on endpoint ${or}${endpoint.name}:${endpoint.number}${db}`); + } + /** * Adds a tag to the tag list of the specified endpoint. * From 97ff46633b8d8b1882aa92b1cb7519eafa4eb6e7 Mon Sep 17 00:00:00 2001 From: Luligu Date: Tue, 26 Nov 2024 20:32:50 +0100 Subject: [PATCH 03/15] Log always error on get set substribe trigger --- src/matterbridgeDevice.ts | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/matterbridgeDevice.ts b/src/matterbridgeDevice.ts index 8635dea3..9f916acc 100644 --- a/src/matterbridgeDevice.ts +++ b/src/matterbridgeDevice.ts @@ -432,18 +432,18 @@ export class MatterbridgeDevice extends extendPublicHandlerMethods Date: Tue, 26 Nov 2024 20:50:57 +0100 Subject: [PATCH 04/15] Update jsdoc to get set trigger subscribe --- src/matterbridgeEndpoint.ts | 52 ++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/src/matterbridgeEndpoint.ts b/src/matterbridgeEndpoint.ts index 796e9673..406b4adc 100644 --- a/src/matterbridgeEndpoint.ts +++ b/src/matterbridgeEndpoint.ts @@ -706,7 +706,7 @@ export class MatterbridgeEndpoint extends Endpoint { * @param {ClusterId} clusterId - The ID of the cluster to retrieve the attribute from. * @param {string} attribute - The name of the attribute to retrieve. * @param {AnsiLogger} [log] - Optional logger for error and info messages. - * @param {Endpoint} [endpoint] - Optional the child endpoint to retrieve the attribute from. + * @param {MatterbridgeEndpoint} [endpoint] - Optional the child endpoint to retrieve the attribute from. * @returns {any} The value of the attribute, or undefined if the attribute is not found. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -715,7 +715,7 @@ export class MatterbridgeEndpoint extends Endpoint { const clusterName = this.lowercaseFirstLetter(getClusterNameById(clusterId)); if (endpoint.construction.status !== Lifecycle.Status.Active) { - log?.error(`getAttribute ${hk}${clusterName}.${attribute}${er} error: Endpoint ${or}${endpoint.id}${er} is in the ${BLUE}${endpoint.construction.status}${er} state`); + this.log.error(`getAttribute ${hk}${clusterName}.${attribute}${er} error: Endpoint ${or}${endpoint.id}${er} is in the ${BLUE}${endpoint.construction.status}${er} state`); return undefined; } @@ -723,12 +723,12 @@ export class MatterbridgeEndpoint extends Endpoint { const state = endpoint.state as Record>; if (!(clusterName in state)) { - log?.error(`getAttribute error: Cluster ${'0x' + clusterId.toString(16).padStart(4, '0')}:${clusterName} not found on endpoint ${or}${endpoint.id}${er}:${or}${endpoint.number}${er}`); + this.log.error(`getAttribute error: Cluster ${'0x' + clusterId.toString(16).padStart(4, '0')}:${clusterName} not found on endpoint ${or}${endpoint.id}${er}:${or}${endpoint.number}${er}`); return undefined; } attribute = this.lowercaseFirstLetter(attribute); if (!(attribute in state[clusterName])) { - log?.error(`getAttribute error: Attribute ${hk}${attribute}${er} not found on Cluster ${'0x' + clusterId.toString(16).padStart(4, '0')}:${clusterName} on endpoint ${or}${endpoint.id}${er}:${or}${endpoint.number}${er}`); + this.log.error(`getAttribute error: Attribute ${hk}${attribute}${er} not found on Cluster ${'0x' + clusterId.toString(16).padStart(4, '0')}:${clusterName} on endpoint ${or}${endpoint.id}${er}:${or}${endpoint.number}${er}`); return undefined; } const value = state[clusterName][attribute]; @@ -745,7 +745,8 @@ export class MatterbridgeEndpoint extends Endpoint { * @param {string} attribute - The name of the attribute. * @param {any} value - The value to set for the attribute. * @param {AnsiLogger} [log] - (Optional) The logger to use for logging errors and information. - * @param {Endpoint} [endpoint] - (Optional) The endpoint to set the attribute on. If not provided, the attribute will be set on the current endpoint. + * @param {MatterbridgeEndpoint} [endpoint] - (Optional) The endpoint to set the attribute on. If not provided, the attribute will be set on the current endpoint. + * @returns {Promise} - A promise that resolves to a boolean indicating whether the attribute was successfully set. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any async setAttribute(clusterId: ClusterId, attribute: string, value: any, log?: AnsiLogger, endpoint?: MatterbridgeEndpoint): Promise { @@ -753,7 +754,7 @@ export class MatterbridgeEndpoint extends Endpoint { const clusterName = this.lowercaseFirstLetter(getClusterNameById(clusterId)); if (endpoint.construction.status !== Lifecycle.Status.Active) { - log?.error(`setAttribute ${hk}${clusterName}.${attribute}${er} error: Endpoint ${or}${endpoint.id}${er} is in the ${BLUE}${endpoint.construction.status}${er} state`); + this.log.error(`setAttribute ${hk}${clusterName}.${attribute}${er} error: Endpoint ${or}${endpoint.id}${er} is in the ${BLUE}${endpoint.construction.status}${er} state`); return false; } @@ -761,12 +762,12 @@ export class MatterbridgeEndpoint extends Endpoint { const state = endpoint.state as Record>; if (!(clusterName in state)) { - log?.error(`setAttribute ${hk}${attribute}${er} error: Cluster ${'0x' + clusterId.toString(16).padStart(4, '0')}:${clusterName} not found on endpoint ${or}${endpoint.id}${er}:${or}${endpoint.number}${er}`); + this.log.error(`setAttribute ${hk}${attribute}${er} error: Cluster ${'0x' + clusterId.toString(16).padStart(4, '0')}:${clusterName} not found on endpoint ${or}${endpoint.id}${er}:${or}${endpoint.number}${er}`); return false; } attribute = this.lowercaseFirstLetter(attribute); if (!(attribute in state[clusterName])) { - log?.error(`setAttribute error: Attribute ${hk}${attribute}${er} not found on Cluster ${'0x' + clusterId.toString(16).padStart(4, '0')}:${clusterName} on endpoint ${or}${endpoint.id}${er}:${or}${endpoint.number}${er}`); + this.log.error(`setAttribute error: Attribute ${hk}${attribute}${er} not found on Cluster ${'0x' + clusterId.toString(16).padStart(4, '0')}:${clusterName} on endpoint ${or}${endpoint.id}${er}:${or}${endpoint.number}${er}`); return false; } let oldValue = state[clusterName][attribute]; @@ -787,11 +788,10 @@ export class MatterbridgeEndpoint extends Endpoint { * @param {ClusterId} clusterId - The ID of the cluster. * @param {string} attribute - The name of the attribute to subscribe to. * @param {(newValue: any, oldValue: any) => void} listener - A callback function that will be called when the attribute value changes. - * @param {AnsiLogger} log - (Optional) An AnsiLogger instance for logging errors and information. - * @param {Endpoint} endpoint - (Optional) The endpoint to subscribe the attribute on. If not provided, the current endpoint will be used. - * @returns A boolean indicating whether the subscription was successful. + * @param {AnsiLogger} [log] - Optional logger for logging errors and information. + * @param {MatterbridgeEndpoint} [endpoint] - Optional endpoint to subscribe the attribute on. Defaults to the current endpoint. + * @returns {boolean} - A boolean indicating whether the subscription was successful. */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any subscribeAttribute(clusterId: ClusterId, attribute: string, listener: (newValue: any, oldValue: any) => void, log?: AnsiLogger, endpoint?: MatterbridgeEndpoint): boolean { if (!endpoint) endpoint = this as MatterbridgeEndpoint; @@ -801,12 +801,12 @@ export class MatterbridgeEndpoint extends Endpoint { const events = endpoint.events as Record>; if (!(clusterName in events)) { - log?.error(`subscribeAttribute ${hk}${attribute}${er} error: Cluster ${'0x' + clusterId.toString(16).padStart(4, '0')}:${clusterName} not found on endpoint ${or}${endpoint.id}${er}:${or}${endpoint.number}${er}`); + this.log.error(`subscribeAttribute ${hk}${attribute}${er} error: Cluster ${'0x' + clusterId.toString(16).padStart(4, '0')}:${clusterName} not found on endpoint ${or}${endpoint.id}${er}:${or}${endpoint.number}${er}`); return false; } attribute = this.lowercaseFirstLetter(attribute) + '$Changed'; if (!(attribute in events[clusterName])) { - log?.error(`subscribeAttribute error: Attribute ${hk}${attribute}${er} not found on Cluster ${'0x' + clusterId.toString(16).padStart(4, '0')}:${clusterName} on endpoint ${or}${endpoint.id}${er}:${or}${endpoint.number}${er}`); + this.log.error(`subscribeAttribute error: Attribute ${hk}${attribute}${er} not found on Cluster ${'0x' + clusterId.toString(16).padStart(4, '0')}:${clusterName} on endpoint ${or}${endpoint.id}${er}:${or}${endpoint.number}${er}`); return false; } events[clusterName][attribute].on(listener); @@ -814,21 +814,30 @@ export class MatterbridgeEndpoint extends Endpoint { return true; } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - async triggerEvent(clusterId: ClusterId, event: string, payload: Record, log?: AnsiLogger, endpoint?: MatterbridgeEndpoint): Promise { + /** + * Triggers an event on the specified cluster. + * + * @param {ClusterId} clusterId - The ID of the cluster. + * @param {string} event - The name of the event to trigger. + * @param {Record} payload - The payload to pass to the event. + * @param {AnsiLogger} [log] - Optional logger for logging information. + * @param {MatterbridgeEndpoint} [endpoint] - Optional endpoint to trigger the event on. Defaults to the current endpoint. + * @returns {Promise} - A promise that resolves to a boolean indicating whether the event was successfully triggered. + */ + async triggerEvent(clusterId: ClusterId, event: string, payload: Record, log?: AnsiLogger, endpoint?: MatterbridgeEndpoint): Promise { if (!endpoint) endpoint = this as MatterbridgeEndpoint; const clusterName = this.lowercaseFirstLetter(getClusterNameById(clusterId)); if (endpoint.construction.status !== Lifecycle.Status.Active) { - log?.error(`triggerEvent ${hk}${clusterName}.${event}${er} error: Endpoint ${or}${endpoint.id}${er} is in the ${BLUE}${endpoint.construction.status}${er} state`); + this.log.error(`triggerEvent ${hk}${clusterName}.${event}${er} error: Endpoint ${or}${endpoint.id}${er} is in the ${BLUE}${endpoint.construction.status}${er} state`); return false; } // eslint-disable-next-line @typescript-eslint/no-explicit-any const events = endpoint.events as Record>; if (!(clusterName in events) || !(event in events[clusterName])) { - log?.error(`triggerEvent ${hk}${event}${er} error: Cluster ${'0x' + clusterId.toString(16).padStart(4, '0')}:${clusterName} not found on endpoint ${or}${endpoint.id}${er}:${or}${endpoint.number}${er}`); + this.log.error(`triggerEvent ${hk}${event}${er} error: Cluster ${'0x' + clusterId.toString(16).padStart(4, '0')}:${clusterName} not found on endpoint ${or}${endpoint.id}${er}:${or}${endpoint.number}${er}`); return false; } @@ -839,6 +848,13 @@ export class MatterbridgeEndpoint extends Endpoint { return true; } + /** + * Adds a command handler for the specified command. + * + * @param {keyof MatterbridgeEndpointCommands} command - The command to add the handler for. + * @param {(data: any) => void} handler - The handler function to execute when the command is received. + * @returns {void} + */ // eslint-disable-next-line @typescript-eslint/no-explicit-any addCommandHandler(command: keyof MatterbridgeEndpointCommands, handler: (data: any) => void): void { this.commandHandler.addHandler(command, handler); From db6303763f5fca545224e3d8c1b57548ae12193a Mon Sep 17 00:00:00 2001 From: Luligu Date: Wed, 27 Nov 2024 09:40:58 +0100 Subject: [PATCH 05/15] Temporary fix matter.js 0.11.5 crash on close --- src/matterbridge.ts | 20 +++++++++++++++ src/matterbridgeDevice.ts | 16 ++++++++---- src/matterbridgeDeviceTypes.ts | 8 ++++++ src/matterbridgeEndpoint.ts | 46 ++++++++++++++++++++++------------ 4 files changed, 69 insertions(+), 21 deletions(-) diff --git a/src/matterbridge.ts b/src/matterbridge.ts index 0465ca1c..1268d9c2 100644 --- a/src/matterbridge.ts +++ b/src/matterbridge.ts @@ -531,6 +531,8 @@ export class Matterbridge extends EventEmitter { this.log.info(` └─ endpoint ${RED}${device.endpoint}${nf} ${typ}${device.endpointName}${nf} ${debugStringify(device.clusterServersId)}`); } }); + await this.cleanup('Exiting...'); + process.exit(0); this.emit('shutdown'); return; } @@ -542,6 +544,8 @@ export class Matterbridge extends EventEmitter { this.log.info(`${plg}${plugin.name}${nf} storage log`); await plugin.nodeContext?.logStorage(); } + await this.cleanup('Exiting...'); + process.exit(0); this.emit('shutdown'); return; } @@ -549,6 +553,8 @@ export class Matterbridge extends EventEmitter { if (hasParameter('loginterfaces')) { this.log.info(`${plg}Matterbridge${nf} network interfaces log`); logInterfaces(); + await this.cleanup('Exiting...'); + process.exit(0); this.emit('shutdown'); return; } @@ -556,24 +562,32 @@ export class Matterbridge extends EventEmitter { if (getParameter('add')) { this.log.debug(`Adding plugin ${getParameter('add')}`); await this.plugins.add(getParameter('add') as string); + await this.cleanup('Exiting...'); + process.exit(0); this.emit('shutdown'); return; } if (getParameter('remove')) { this.log.debug(`Removing plugin ${getParameter('remove')}`); await this.plugins.remove(getParameter('remove') as string); + await this.cleanup('Exiting...'); + process.exit(0); this.emit('shutdown'); return; } if (getParameter('enable')) { this.log.debug(`Enabling plugin ${getParameter('enable')}`); await this.plugins.enable(getParameter('enable') as string); + await this.cleanup('Exiting...'); + process.exit(0); this.emit('shutdown'); return; } if (getParameter('disable')) { this.log.debug(`Disabling plugin ${getParameter('disable')}`); await this.plugins.disable(getParameter('disable') as string); + await this.cleanup('Exiting...'); + process.exit(0); this.emit('shutdown'); return; } @@ -596,6 +610,8 @@ export class Matterbridge extends EventEmitter { this.nodeStorage = undefined; this.plugins.clear(); this.devices.clear(); + await this.cleanup('Exiting...'); + process.exit(0); this.emit('shutdown'); return; } @@ -613,6 +629,8 @@ export class Matterbridge extends EventEmitter { await this.matterbridgeContext?.clearAll(); await this.stopMatterStorage(); this.log.info('Reset done! Remove the device from the controller.'); + await this.cleanup('Exiting...'); + process.exit(0); this.emit('shutdown'); return; } @@ -630,6 +648,8 @@ export class Matterbridge extends EventEmitter { this.log.warn(`Plugin ${plg}${getParameter('reset')}${wr} not registerd in matterbridge`); } await this.stopMatterStorage(); + await this.cleanup('Exiting...'); + process.exit(0); this.emit('shutdown'); return; } diff --git a/src/matterbridgeDevice.ts b/src/matterbridgeDevice.ts index 9f916acc..78d787e0 100644 --- a/src/matterbridgeDevice.ts +++ b/src/matterbridgeDevice.ts @@ -110,7 +110,7 @@ import { } from '@matter/main/clusters'; import { Specification } from '@matter/main/model'; import { ClusterId, EndpointNumber, extendPublicHandlerMethods, VendorId, AtLeastOne, MakeMandatory } from '@matter/main'; -import { MeasurementType, getClusterNameById } from '@matter/main/types'; +import { MeasurementType, Semtag, getClusterNameById } from '@matter/main/types'; // @project-chip import { Device, DeviceTypeDefinition, Endpoint, EndpointOptions } from '@project-chip/matter.js/device'; @@ -121,7 +121,7 @@ import { AnsiLogger, LogLevel, TimestampFormat, CYAN, YELLOW, db, hk, or, zb, de // Node.js modules import { createHash } from 'crypto'; -import { bridgedNode } from './matterbridgeDeviceTypes.js'; +import { bridgedNode, MatterbridgeEndpointOptions } from './matterbridgeDeviceTypes.js'; interface MatterbridgeDeviceCommands { identify: MakeMandatory['identify']>; @@ -289,11 +289,17 @@ export class MatterbridgeDevice extends extendPublicHandlerMethods, includeServerList: ClusterId[] = [], options: EndpointOptions = {}, debug = false): Endpoint { + addChildDeviceTypeWithClusterServer(endpointName: string, deviceTypes: AtLeastOne, includeServerList: ClusterId[] = [], options: MatterbridgeEndpointOptions = {}, debug = false): Endpoint { this.log.debug(`addChildDeviceTypeWithClusterServer: ${CYAN}${endpointName}${db}`); let child = this.getChildEndpoints().find((endpoint) => endpoint.uniqueStorageKey === endpointName); if (!child) { child = new Endpoint(deviceTypes, { uniqueStorageKey: endpointName }); + if ('tagList' in options) { + for (const tag of options.tagList as Semtag[]) { + this.log.debug(`- with tagList: mfgCode ${CYAN}${tag.mfgCode}${db} namespaceId ${CYAN}${tag.namespaceId}${db} tag ${CYAN}${tag.tag}${db} label ${CYAN}${tag.label}${db}`); + this.addTagList(child, tag.mfgCode, tag.namespaceId, tag.tag, tag.label); + } + } this.addChildEndpoint(child); } deviceTypes.forEach((deviceType) => { @@ -604,13 +610,13 @@ export class MatterbridgeDevice extends extendPublicHandlerMethods} definition - The DeviceTypeDefinition(s) of the endpoint. - * @param {EndpointOptions} [options={}] - The options for the device. + * @param {MatterbridgeEndpointOptions} [options={}] - The options for the device. */ - constructor(definition: DeviceTypeDefinition | AtLeastOne, options: EndpointOptions = {}, debug = false) { - const { uniqueStorageKey, endpointId, tagList, colorControlFeatures } = options as { uniqueStorageKey?: string; endpointId?: EndpointNumber; tagList?: Semtag[]; colorControlFeatures?: object }; - + constructor(definition: DeviceTypeDefinition | AtLeastOne, options: MatterbridgeEndpointOptions = {}, debug = false) { // Get the first DeviceTypeDefinition let firstDefinition: DeviceTypeDefinition; if (Array.isArray(definition)) firstDefinition = definition[0]; @@ -292,7 +290,7 @@ export class MatterbridgeEndpoint extends Endpoint { optional: SupportedBehaviors(...MatterbridgeEndpoint.getBehaviourTypesFromClusterClientIds(firstDefinition.optionalClientClusters)), }, }, - behaviors: tagList ? SupportedBehaviors(DescriptorServer.with(Descriptor.Feature.TagList)) : {}, + behaviors: options.tagList ? SupportedBehaviors(DescriptorServer.with(Descriptor.Feature.TagList)) : {}, }; const endpointV8 = MutableEndpoint(deviceTypeDefinitionV8); @@ -300,20 +298,21 @@ export class MatterbridgeEndpoint extends Endpoint { // [{ mfgCode: null, namespaceId: 0x07, tag: 1, label: 'Switch1' }] // endpoint = endpoint.enable({features: { tagList: true }}); const optionsV8 = { - // id: uniqueStorageKey, - id: uniqueStorageKey?.replace(/[ .]/g, ''), - // id: uniqueStorageKey?.replace(/[^a-zA-Z0-9_-]/g, ''), - number: endpointId, - descriptor: tagList ? { tagList } : undefined, + id: options.uniqueStorageKey?.replace(/[ .]/g, ''), + number: options.endpointId, + descriptor: options.tagList ? { tagList: options.tagList } : undefined, // eslint-disable-next-line @typescript-eslint/no-explicit-any } as { id?: string; number?: EndpointNumber; descriptor?: Record }; super(endpointV8, optionsV8); - this.uniqueStorageKey = uniqueStorageKey; - this.tagList = tagList; + this.uniqueStorageKey = options.uniqueStorageKey; + this.tagList = options.tagList; // Update the endpoint this.log = new AnsiLogger({ logName: 'MatterbridgeEndpoint', logTimestampFormat: TimestampFormat.TIME_MILLIS, logLevel: debug === true ? LogLevel.DEBUG : MatterbridgeEndpoint.logLevel }); - this.log.debug(`${YELLOW}new${db} MatterbridgeEndpoint: ${zb}${'0x' + firstDefinition.code.toString(16).padStart(4, '0')}${db}-${zb}${firstDefinition.name}${db} id: ${CYAN}${this.id}${db}`); + this.log.debug( + `${YELLOW}new${db} MatterbridgeEndpoint: ${zb}${'0x' + firstDefinition.code.toString(16).padStart(4, '0')}${db}-${zb}${firstDefinition.name}${db} ` + + `id: ${CYAN}${options.uniqueStorageKey}${db} number: ${CYAN}${options.endpointId}${db} taglist: ${CYAN}${options.tagList ? debugStringify(options.tagList) : 'undefined'}${db}`, + ); this.deviceTypes.set(firstDefinition.code, firstDefinition); // Add the other device types to the descriptor server @@ -524,7 +523,14 @@ export class MatterbridgeEndpoint extends Endpoint { this.log.debug(`addChildDeviceTypeWithClusterServer: ${CYAN}${endpointName}${db}`); let child = this.getChildEndpointByName(endpointName); if (!child) { - child = new MatterbridgeEndpoint(deviceTypes[0], { uniqueStorageKey: endpointName }, debug); + if ('tagList' in options) { + for (const tag of options.tagList as Semtag[]) { + this.log.debug(`- with tagList: mfgCode ${CYAN}${tag.mfgCode}${db} namespaceId ${CYAN}${tag.namespaceId}${db} tag ${CYAN}${tag.tag}${db} label ${CYAN}${tag.label}${db}`); + } + child = new MatterbridgeEndpoint(deviceTypes[0], { uniqueStorageKey: endpointName, taglist: options.tagList } as EndpointOptions, debug); + } else { + child = new MatterbridgeEndpoint(deviceTypes[0], { uniqueStorageKey: endpointName }, debug); + } } deviceTypes.forEach((deviceType) => { this.log.debug(`- with deviceType: ${zb}${'0x' + deviceType.code.toString(16).padStart(4, '0')}${db}-${zb}${deviceType.name}${db}`); @@ -574,6 +580,10 @@ export class MatterbridgeEndpoint extends Endpoint { }); } + hasClusterServer, A extends Attributes, C extends Commands, E extends Events>(cluster: Cluster): boolean { + return this.clusterServers.has(cluster.id); + } + getClusterServer(cluster: T): ClusterServerObj | undefined { const clusterServer = this.clusterServers.get(cluster.id); if (clusterServer !== undefined) { @@ -585,6 +595,10 @@ export class MatterbridgeEndpoint extends Endpoint { return this.clusterServers.get(clusterId); } + addTagList(endpoint: Endpoint, mfgCode: VendorId | null, namespaceId: number, tag: number, label?: string | null) { + // Do nothing here + } + addClusterServer(cluster: ClusterServerObj) { // eslint-disable-next-line @typescript-eslint/no-explicit-any const options: Record = {}; From aae508f6edbe7b0dce92a41a4b83857d871607bd Mon Sep 17 00:00:00 2001 From: Luligu Date: Wed, 27 Nov 2024 11:39:59 +0100 Subject: [PATCH 06/15] Add MatterbridgeEndpointOptions type to constructors --- CHANGELOG.md | 6 +++++- src/matterbridgeEndpoint.ts | 15 +++++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b2cbe9f9..7a0a353a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,12 +20,16 @@ Tamer (https://github.com/tammeryousef1006) has created the Matterbridge Discord Feel free to join (the link is now permanent)! -## [1.6.3] - 2024-11-xx +## [1.6.3] - 2024-11-27 ### Changed - [matterbridge]: Changed default minLevel to 0 in LevelControlCluster utility methods. +### Fixed + +- [matter.js]: Temporary fix the crash of matter.js on close when using command line parameters. + ## [1.6.2] - 2024-11-25 ### Added diff --git a/src/matterbridgeEndpoint.ts b/src/matterbridgeEndpoint.ts index d15959bd..edfb9f96 100644 --- a/src/matterbridgeEndpoint.ts +++ b/src/matterbridgeEndpoint.ts @@ -306,6 +306,9 @@ export class MatterbridgeEndpoint extends Endpoint { super(endpointV8, optionsV8); this.uniqueStorageKey = options.uniqueStorageKey; this.tagList = options.tagList; + // console.log('MatterbridgeEndpoint.option', options); + // console.log('MatterbridgeEndpoint.endpointV8', endpointV8); + // console.log('MatterbridgeEndpoint.optionsV8', optionsV8); // Update the endpoint this.log = new AnsiLogger({ logName: 'MatterbridgeEndpoint', logTimestampFormat: TimestampFormat.TIME_MILLIS, logLevel: debug === true ? LogLevel.DEBUG : MatterbridgeEndpoint.logLevel }); @@ -515,11 +518,11 @@ export class MatterbridgeEndpoint extends Endpoint { * @param {string} endpointName - The name of the new enpoint to add. * @param {AtLeastOne} deviceTypes - The device types to add. * @param {ClusterId[]} [includeServerList=[]] - The list of cluster IDs to include. - * @param {EndpointOptions} [options={}] - The options for the device. + * @param {MatterbridgeEndpointOptions} [options={}] - The options for the device. * @param {boolean} [debug=false] - Whether to enable debug logging. * @returns {MatterbridgeEndpoint} - The child endpoint that was found or added. */ - addChildDeviceTypeWithClusterServer(endpointName: string, deviceTypes: AtLeastOne, includeServerList: ClusterId[] = [], options: EndpointOptions = {}, debug = false) { + addChildDeviceTypeWithClusterServer(endpointName: string, deviceTypes: AtLeastOne, includeServerList: ClusterId[] = [], options: MatterbridgeEndpointOptions = {}, debug = false) { this.log.debug(`addChildDeviceTypeWithClusterServer: ${CYAN}${endpointName}${db}`); let child = this.getChildEndpointByName(endpointName); if (!child) { @@ -527,7 +530,7 @@ export class MatterbridgeEndpoint extends Endpoint { for (const tag of options.tagList as Semtag[]) { this.log.debug(`- with tagList: mfgCode ${CYAN}${tag.mfgCode}${db} namespaceId ${CYAN}${tag.namespaceId}${db} tag ${CYAN}${tag.tag}${db} label ${CYAN}${tag.label}${db}`); } - child = new MatterbridgeEndpoint(deviceTypes[0], { uniqueStorageKey: endpointName, taglist: options.tagList } as EndpointOptions, debug); + child = new MatterbridgeEndpoint(deviceTypes[0], { uniqueStorageKey: endpointName, tagList: options.tagList }, debug); } else { child = new MatterbridgeEndpoint(deviceTypes[0], { uniqueStorageKey: endpointName }, debug); } @@ -596,7 +599,7 @@ export class MatterbridgeEndpoint extends Endpoint { } addTagList(endpoint: Endpoint, mfgCode: VendorId | null, namespaceId: number, tag: number, label?: string | null) { - // Do nothing here + // Do nothing here only for old api compatibility } addClusterServer(cluster: ClusterServerObj) { @@ -670,6 +673,7 @@ export class MatterbridgeEndpoint extends Endpoint { async addFixedLabel(label: string, value: string) { if (!this.clusterServers.get(FixedLabelCluster.id)) { + this.log.debug(`addFixedLabel: add cluster ${hk}FixedLabelCluster${db} with label ${CYAN}${label}${db} value ${CYAN}${value}${db}`); this.addClusterServer( ClusterServer( FixedLabelCluster, @@ -681,6 +685,7 @@ export class MatterbridgeEndpoint extends Endpoint { ); return; } + this.log.debug(`addFixedLabel: add label ${CYAN}${label}${db} value ${CYAN}${value}${db}`); const labelList = (this.getAttribute(FixedLabelCluster.id, 'labelList', this.log) ?? []).filter((entryLabel: { label: string; value: string }) => entryLabel.label !== label); labelList.push({ label, value }); await this.setAttribute(FixedLabelCluster.id, 'labelList', labelList, this.log); @@ -688,6 +693,7 @@ export class MatterbridgeEndpoint extends Endpoint { async addUserLabel(label: string, value: string) { if (!this.clusterServers.get(UserLabelCluster.id)) { + this.log.debug(`addUserLabel: add cluster ${hk}UserLabelCluster${db} with label ${CYAN}${label}${db} value ${CYAN}${value}${db}`); this.addClusterServer( ClusterServer( UserLabelCluster, @@ -699,6 +705,7 @@ export class MatterbridgeEndpoint extends Endpoint { ); return; } + this.log.debug(`addUserLabel: add label ${CYAN}${label}${db} value ${CYAN}${value}${db}`); const labelList = (this.getAttribute(UserLabelCluster.id, 'labelList', this.log) ?? []).filter((entryLabel: { label: string; value: string }) => entryLabel.label !== label); labelList.push({ label, value }); await this.setAttribute(UserLabelCluster.id, 'labelList', labelList, this.log); From 990151570fd134610f993eda27c91acaa4a7734d Mon Sep 17 00:00:00 2001 From: Luligu Date: Wed, 27 Nov 2024 12:03:26 +0100 Subject: [PATCH 07/15] Add maybeNumber --- src/matterbridgeDevice.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/matterbridgeDevice.ts b/src/matterbridgeDevice.ts index 78d787e0..08ea3580 100644 --- a/src/matterbridgeDevice.ts +++ b/src/matterbridgeDevice.ts @@ -236,6 +236,11 @@ export class MatterbridgeDevice extends extendPublicHandlerMethods Date: Wed, 27 Nov 2024 13:22:13 +0100 Subject: [PATCH 08/15] Configure ThermostatCluster --- src/matterbridgeEndpoint.ts | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/matterbridgeEndpoint.ts b/src/matterbridgeEndpoint.ts index edfb9f96..ff0e5c4d 100644 --- a/src/matterbridgeEndpoint.ts +++ b/src/matterbridgeEndpoint.ts @@ -365,7 +365,11 @@ export class MatterbridgeEndpoint extends Endpoint { if (clusterId === LevelControl.Cluster.id) return MatterbridgeLevelControlServer; if (clusterId === ColorControl.Cluster.id) return MatterbridgeColorControlServer; if (clusterId === DoorLock.Cluster.id) return MatterbridgeDoorLockServer; - if (clusterId === Thermostat.Cluster.id) return MatterbridgeThermostatServer; + + if (clusterId === Thermostat.Cluster.id && type === 'AutoModeThermostat') return MatterbridgeThermostatServer.with('AutoMode', 'Heating', 'Cooling'); + if (clusterId === Thermostat.Cluster.id && type === 'HeatingThermostat') return MatterbridgeThermostatServer.with('Heating'); + if (clusterId === Thermostat.Cluster.id && type === 'CoolingThermostat') return MatterbridgeThermostatServer.with('Cooling'); + if (clusterId === WindowCovering.Cluster.id) return MatterbridgeWindowCoveringServer; if (clusterId === FanControl.Cluster.id) return MatterbridgeFanControlServer; if (clusterId === Switch.Cluster.id && type === 'MomentarySwitch') return SwitchServer.with('MomentarySwitch', 'MomentarySwitchRelease', 'MomentarySwitchLongPress', 'MomentarySwitchMultiPress'); @@ -378,9 +382,9 @@ export class MatterbridgeEndpoint extends Endpoint { if (clusterId === BooleanStateConfiguration.Cluster.id) return MatterbridgeBooleanStateConfigurationServer; if (clusterId === OccupancySensing.Cluster.id) return OccupancySensingServer; if (clusterId === IlluminanceMeasurement.Cluster.id) return IlluminanceMeasurementServer; - if (clusterId === SmokeCoAlarm.Cluster.id) return SmokeCoAlarmServer.with(SmokeCoAlarm.Feature.SmokeAlarm, SmokeCoAlarm.Feature.CoAlarm); + if (clusterId === SmokeCoAlarm.Cluster.id) return SmokeCoAlarmServer.with('SmokeAlarm', 'CoAlarm'); - if (clusterId === AirQuality.Cluster.id) return AirQualityServer.with(AirQuality.Feature.Fair, AirQuality.Feature.Moderate, AirQuality.Feature.VeryPoor, AirQuality.Feature.ExtremelyPoor); + if (clusterId === AirQuality.Cluster.id) return AirQualityServer.with('Fair', 'Moderate', 'VeryPoor', 'ExtremelyPoor'); if (clusterId === CarbonMonoxideConcentrationMeasurement.Cluster.id) return CarbonMonoxideConcentrationMeasurementServer.with('NumericMeasurement'); if (clusterId === CarbonDioxideConcentrationMeasurement.Cluster.id) return CarbonDioxideConcentrationMeasurementServer.with('NumericMeasurement'); if (clusterId === NitrogenDioxideConcentrationMeasurement.Cluster.id) return NitrogenDioxideConcentrationMeasurementServer.with('NumericMeasurement'); @@ -614,15 +618,28 @@ export class MatterbridgeEndpoint extends Endpoint { } } this.log.debug(`addClusterServer: ${hk}${'0x' + cluster.id.toString(16).padStart(4, '0')}${db}-${hk}${getClusterNameById(cluster.id)}${db} with options: ${debugStringify(options)}${rs}`); + if (this.clusterServers.has(cluster.id)) { + this.log.debug(`****cluster ${hk}${'0x' + cluster.id.toString(16).padStart(4, '0')}${db}-${hk}${getClusterNameById(cluster.id)}${db} already added`); + } let type = undefined; if (cluster.id === SwitchCluster.id && cluster.isEventSupportedByName('multiPressComplete')) type = 'MomentarySwitch'; if (cluster.id === SwitchCluster.id && cluster.isEventSupportedByName('switchLatched')) type = 'LatchingSwitch'; + if (cluster.id === PowerSourceCluster.id && cluster.isAttributeSupportedByName('wiredCurrentType')) type = 'WiredPowerSource'; if (cluster.id === PowerSourceCluster.id && cluster.isAttributeSupportedByName('batReplacementDescription')) type = 'BatteryReplaceablePowerSource'; if (cluster.id === PowerSourceCluster.id && cluster.isAttributeSupportedByName('batChargeState')) type = 'BatteryRechargeablePowerSource'; + + if (cluster.id === ThermostatCluster.id && cluster.isAttributeSupportedByName('occupiedCoolingSetpoint')) type = 'CoolingThermostat'; + if (cluster.id === ThermostatCluster.id && cluster.isAttributeSupportedByName('occupiedHeatingSetpoint')) type = 'HeatingThermostat'; + if (cluster.id === ThermostatCluster.id && cluster.isAttributeSupportedByName('minSetpointDeadBand')) type = 'AutoModeThermostat'; + const behavior = MatterbridgeEndpoint.getBehaviourTypeFromClusterServerId(cluster.id, type); - if (cluster.id !== BasicInformationCluster.id) this.behaviors.require(behavior, options); + if (cluster.id === PowerTopologyCluster.id && this.clusterServers.has(cluster.id)) return; // TODO remove this workaround + if (cluster.id === ElectricalPowerMeasurementCluster.id && this.clusterServers.has(cluster.id)) return; // TODO remove this workaround + if (cluster.id === ElectricalEnergyMeasurementCluster.id && this.clusterServers.has(cluster.id)) return; // TODO remove this workaround this.clusterServers.set(cluster.id, cluster as unknown as ClusterServerObj); + if (cluster.id === BasicInformationCluster.id) return; // Not used in Matterbridge edge for devices. Only on server node. + this.behaviors.require(behavior, options); } /** From 1fe81c8301b330e4a9cc8811c1e2d4e6d05eb090 Mon Sep 17 00:00:00 2001 From: Luligu Date: Wed, 27 Nov 2024 19:42:24 +0100 Subject: [PATCH 09/15] Fix thermostat --- src/matterbridgeEndpoint.ts | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/matterbridgeEndpoint.ts b/src/matterbridgeEndpoint.ts index ff0e5c4d..c916b36a 100644 --- a/src/matterbridgeEndpoint.ts +++ b/src/matterbridgeEndpoint.ts @@ -637,6 +637,7 @@ export class MatterbridgeEndpoint extends Endpoint { if (cluster.id === PowerTopologyCluster.id && this.clusterServers.has(cluster.id)) return; // TODO remove this workaround if (cluster.id === ElectricalPowerMeasurementCluster.id && this.clusterServers.has(cluster.id)) return; // TODO remove this workaround if (cluster.id === ElectricalEnergyMeasurementCluster.id && this.clusterServers.has(cluster.id)) return; // TODO remove this workaround + if (cluster.id === ThermostatCluster.id && this.clusterServers.has(cluster.id)) return; // TODO remove this workaround this.clusterServers.set(cluster.id, cluster as unknown as ClusterServerObj); if (cluster.id === BasicInformationCluster.id) return; // Not used in Matterbridge edge for devices. Only on server node. this.behaviors.require(behavior, options); @@ -703,6 +704,7 @@ export class MatterbridgeEndpoint extends Endpoint { return; } this.log.debug(`addFixedLabel: add label ${CYAN}${label}${db} value ${CYAN}${value}${db}`); + // if (this.construction.status !== Lifecycle.Status.Active) await this.construction.ready; const labelList = (this.getAttribute(FixedLabelCluster.id, 'labelList', this.log) ?? []).filter((entryLabel: { label: string; value: string }) => entryLabel.label !== label); labelList.push({ label, value }); await this.setAttribute(FixedLabelCluster.id, 'labelList', labelList, this.log); @@ -723,6 +725,7 @@ export class MatterbridgeEndpoint extends Endpoint { return; } this.log.debug(`addUserLabel: add label ${CYAN}${label}${db} value ${CYAN}${value}${db}`); + // if (this.construction.status !== Lifecycle.Status.Active) await this.construction.ready; const labelList = (this.getAttribute(UserLabelCluster.id, 'labelList', this.log) ?? []).filter((entryLabel: { label: string; value: string }) => entryLabel.label !== label); labelList.push({ label, value }); await this.setAttribute(UserLabelCluster.id, 'labelList', labelList, this.log); @@ -793,6 +796,7 @@ export class MatterbridgeEndpoint extends Endpoint { if (endpoint.construction.status !== Lifecycle.Status.Active) { this.log.error(`setAttribute ${hk}${clusterName}.${attribute}${er} error: Endpoint ${or}${endpoint.id}${er} is in the ${BLUE}${endpoint.construction.status}${er} state`); + // await endpoint.construction.ready; return false; } @@ -831,10 +835,15 @@ export class MatterbridgeEndpoint extends Endpoint { * @returns {boolean} - A boolean indicating whether the subscription was successful. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any - subscribeAttribute(clusterId: ClusterId, attribute: string, listener: (newValue: any, oldValue: any) => void, log?: AnsiLogger, endpoint?: MatterbridgeEndpoint): boolean { + async subscribeAttribute(clusterId: ClusterId, attribute: string, listener: (newValue: any, oldValue: any) => void, log?: AnsiLogger, endpoint?: MatterbridgeEndpoint): Promise { if (!endpoint) endpoint = this as MatterbridgeEndpoint; const clusterName = this.lowercaseFirstLetter(getClusterNameById(clusterId)); + if (endpoint.construction.status !== Lifecycle.Status.Active) { + // this.log.error(`subscribeAttribute ${hk}${clusterName}.${attribute}${er} error: Endpoint ${or}${endpoint.id}${er} is in the ${BLUE}${endpoint.construction.status}${er} state`); + await endpoint.construction.ready; + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any const events = endpoint.events as Record>; @@ -868,8 +877,9 @@ export class MatterbridgeEndpoint extends Endpoint { const clusterName = this.lowercaseFirstLetter(getClusterNameById(clusterId)); if (endpoint.construction.status !== Lifecycle.Status.Active) { - this.log.error(`triggerEvent ${hk}${clusterName}.${event}${er} error: Endpoint ${or}${endpoint.id}${er} is in the ${BLUE}${endpoint.construction.status}${er} state`); - return false; + // this.log.error(`triggerEvent ${hk}${clusterName}.${event}${er} error: Endpoint ${or}${endpoint.id}${er} is in the ${BLUE}${endpoint.construction.status}${er} state`); + await endpoint.construction.ready; + // return false; } // eslint-disable-next-line @typescript-eslint/no-explicit-any From 91508f4302f6da586e8c236264b00c30362bbf27 Mon Sep 17 00:00:00 2001 From: Luligu Date: Wed, 27 Nov 2024 19:44:08 +0100 Subject: [PATCH 10/15] Update to matter.js 011.6 --- package-lock.json | 118 +++++++++++++++++++++++----------------------- package.json | 6 +-- 2 files changed, 62 insertions(+), 62 deletions(-) diff --git a/package-lock.json b/package-lock.json index ccb535c0..c9bb102d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,9 +9,9 @@ "version": "1.6.3-dev.1", "license": "Apache-2.0", "dependencies": { - "@matter/main": "^0.11.5", - "@matter/nodejs": "^0.11.5", - "@project-chip/matter.js": "^0.11.5", + "@matter/main": "^0.11.6", + "@matter/nodejs": "^0.11.6", + "@project-chip/matter.js": "^0.11.6", "archiver": "7.0.1", "express": "4.21.1", "glob": "11.0.0", @@ -1317,64 +1317,64 @@ } }, "node_modules/@matter/general": { - "version": "0.11.5", - "resolved": "https://registry.npmjs.org/@matter/general/-/general-0.11.5.tgz", - "integrity": "sha512-uYzFDOGpjNtZEPWZDW5NStmXxeuIDQ9t+c4sPp1HwkX4jC3ZP5p96Fqse5Lby0QfBbzO0HVKgJbEYjIYzdLc3w==", + "version": "0.11.6", + "resolved": "https://registry.npmjs.org/@matter/general/-/general-0.11.6.tgz", + "integrity": "sha512-HPFTmaCREFAXPW5JLWwOU5Esbu1fAu2zBnlEbt0+c60vZzoLWbMLxXv0fKz2bSgNuvmly0ccX/1DF4CAlzeDbQ==", "license": "Apache-2.0", "dependencies": { - "@noble/curves": "^1.5.0" + "@noble/curves": "^1.7.0" } }, "node_modules/@matter/main": { - "version": "0.11.5", - "resolved": "https://registry.npmjs.org/@matter/main/-/main-0.11.5.tgz", - "integrity": "sha512-d1N7jQZbyS+PKltLXyYu6faHk2CqtCoS2AlldArjpZSN1OY0F3We5kGTuUhAZj59wSXAqbX/tYNOrOyOGP13/Q==", + "version": "0.11.6", + "resolved": "https://registry.npmjs.org/@matter/main/-/main-0.11.6.tgz", + "integrity": "sha512-NJRFAEF9Pgf2X8oMppAGOUEJdMUzi+evzkLpw4X96f2OpiMjfB3Nvef6C9QmYSzhh8hleCW4PV4ablmBIh9Kig==", "license": "Apache-2.0", "dependencies": { - "@matter/general": "0.11.5", - "@matter/model": "0.11.5", - "@matter/node": "0.11.5", - "@matter/protocol": "0.11.5", - "@matter/types": "0.11.5", - "@noble/curves": "^1.5.0" + "@matter/general": "0.11.6", + "@matter/model": "0.11.6", + "@matter/node": "0.11.6", + "@matter/protocol": "0.11.6", + "@matter/types": "0.11.6", + "@noble/curves": "^1.7.0" }, "optionalDependencies": { - "@matter/nodejs": "0.11.5" + "@matter/nodejs": "0.11.6" } }, "node_modules/@matter/model": { - "version": "0.11.5", - "resolved": "https://registry.npmjs.org/@matter/model/-/model-0.11.5.tgz", - "integrity": "sha512-vBA3Q/X3wT6+1E8xHlQb4jZQW1vmK5u8tJ2e8EuoEmyK3w5VvROPh3KV0OzSqNL0d8QwqPLOljCAWIw78nnJwA==", + "version": "0.11.6", + "resolved": "https://registry.npmjs.org/@matter/model/-/model-0.11.6.tgz", + "integrity": "sha512-D8w2datMmqoSwUejOlm9BONG4vSnc0+MF0GmicTEq1fUnvu1bOcgergtg0IcbyeIkm1n7ngJAAtBxcG5ENh99g==", "license": "Apache-2.0", "dependencies": { - "@matter/general": "0.11.5", - "@noble/curves": "^1.5.0" + "@matter/general": "0.11.6", + "@noble/curves": "^1.7.0" } }, "node_modules/@matter/node": { - "version": "0.11.5", - "resolved": "https://registry.npmjs.org/@matter/node/-/node-0.11.5.tgz", - "integrity": "sha512-7kz+nkNSoSZHycTJw4Noaj5tJSBV/jfmYh/IUyboEHPhYhHV0IAWoeKWNo1o/zLuR27ebcE1eJzoHBvnOJ475g==", + "version": "0.11.6", + "resolved": "https://registry.npmjs.org/@matter/node/-/node-0.11.6.tgz", + "integrity": "sha512-zMNWdEhG9TluKbz2J3yBEwtGPlmLYQQQR7Xg1nr2xzUgLaxSal/GXuyr20VdwMa5RvLcdMeW3zJ+uoVhS1Q9zw==", "license": "Apache-2.0", "dependencies": { - "@matter/general": "0.11.5", - "@matter/model": "0.11.5", - "@matter/protocol": "0.11.5", - "@matter/types": "0.11.5", - "@noble/curves": "^1.5.0" + "@matter/general": "0.11.6", + "@matter/model": "0.11.6", + "@matter/protocol": "0.11.6", + "@matter/types": "0.11.6", + "@noble/curves": "^1.7.0" } }, "node_modules/@matter/nodejs": { - "version": "0.11.5", - "resolved": "https://registry.npmjs.org/@matter/nodejs/-/nodejs-0.11.5.tgz", - "integrity": "sha512-5zNKPxrhpH7hgGUF56P75Se5q6hmqMn6ysai7EdO4XYC8rsYWvc7c6/uR444bJdmEE087eNvovf3S+2CMcRLsQ==", + "version": "0.11.6", + "resolved": "https://registry.npmjs.org/@matter/nodejs/-/nodejs-0.11.6.tgz", + "integrity": "sha512-nJCMh34AEigLM3/GvHJJ/V0n4+6i9rpH0n19PcdkbKW4Yxvo5cE3l/Nq5Yh9ajTIUMx5Wh13s1N0nlM62WuOdw==", "license": "Apache-2.0", "dependencies": { - "@matter/general": "0.11.5", - "@matter/node": "0.11.5", - "@matter/protocol": "0.11.5", - "@matter/types": "0.11.5", + "@matter/general": "0.11.6", + "@matter/node": "0.11.6", + "@matter/protocol": "0.11.6", + "@matter/types": "0.11.6", "node-localstorage": "^3.0.5" }, "engines": { @@ -1382,26 +1382,26 @@ } }, "node_modules/@matter/protocol": { - "version": "0.11.5", - "resolved": "https://registry.npmjs.org/@matter/protocol/-/protocol-0.11.5.tgz", - "integrity": "sha512-U6sBOYIizgsyANTyI4ktZLak9BzjQFZppcxVW7IJrU3ub7LbrAzENQqijT17bu0KCijZkzEs+iRL9oso6yZ/Tw==", + "version": "0.11.6", + "resolved": "https://registry.npmjs.org/@matter/protocol/-/protocol-0.11.6.tgz", + "integrity": "sha512-FA0FUBGhXljzNyevS5hmGfRUYQlHetfpX+9RuPs/WD+Xc5ZG3myjLvXkQWiwDdEkR5m1jHzF9uyex5hpUaDstA==", "license": "Apache-2.0", "dependencies": { - "@matter/general": "0.11.5", - "@matter/model": "0.11.5", - "@matter/types": "0.11.5", - "@noble/curves": "^1.5.0" + "@matter/general": "0.11.6", + "@matter/model": "0.11.6", + "@matter/types": "0.11.6", + "@noble/curves": "^1.7.0" } }, "node_modules/@matter/types": { - "version": "0.11.5", - "resolved": "https://registry.npmjs.org/@matter/types/-/types-0.11.5.tgz", - "integrity": "sha512-e7nFqaQwbLpZMLizYHFE7aqCIE3HvYNpkjkw/wBmTte4mjyjje0rn1EkAyPdBER4Sd5DFxwc4x14mgPsXseBzQ==", + "version": "0.11.6", + "resolved": "https://registry.npmjs.org/@matter/types/-/types-0.11.6.tgz", + "integrity": "sha512-TKaBh1+OFJ1IKuK2x6FG05/udWaNseH8DVJluF5hYIz17rNkkeCBEu6HjRtZpqFpLxOAOlgzrNGmp8BMK+9hJg==", "license": "Apache-2.0", "dependencies": { - "@matter/general": "0.11.5", - "@matter/model": "0.11.5", - "@noble/curves": "^1.5.0" + "@matter/general": "0.11.6", + "@matter/model": "0.11.6", + "@noble/curves": "^1.7.0" } }, "node_modules/@noble/curves": { @@ -1493,17 +1493,17 @@ } }, "node_modules/@project-chip/matter.js": { - "version": "0.11.5", - "resolved": "https://registry.npmjs.org/@project-chip/matter.js/-/matter.js-0.11.5.tgz", - "integrity": "sha512-V6XvQOrqXZhsnS6q3SM8nolzYwrvVIQ5Uwwg4n6+ptuOREoSh03/RhW7EjQbABPzG7Y0/N0iCY6h5kGEuyQFBg==", + "version": "0.11.6", + "resolved": "https://registry.npmjs.org/@project-chip/matter.js/-/matter.js-0.11.6.tgz", + "integrity": "sha512-546FM6h+lKjYkmaW/luB45HLGKlE07MP03/y1peiwy96TMGTcvhbJIUQE0WCGBJM/zBY2XeyR0OVqgw8OmDKzw==", "license": "Apache-2.0", "dependencies": { - "@matter/general": "0.11.5", - "@matter/model": "0.11.5", - "@matter/node": "0.11.5", - "@matter/protocol": "0.11.5", - "@matter/types": "0.11.5", - "@noble/curves": "^1.5.0" + "@matter/general": "0.11.6", + "@matter/model": "0.11.6", + "@matter/node": "0.11.6", + "@matter/protocol": "0.11.6", + "@matter/types": "0.11.6", + "@noble/curves": "^1.7.0" } }, "node_modules/@sinclair/typebox": { diff --git a/package.json b/package.json index c7d6e886..74bb05dd 100644 --- a/package.json +++ b/package.json @@ -121,9 +121,9 @@ "install:jest": "npm install --save-dev jest ts-jest @types/jest eslint-plugin-jest" }, "dependencies": { - "@matter/main": "^0.11.5", - "@matter/nodejs": "^0.11.5", - "@project-chip/matter.js": "^0.11.5", + "@matter/main": "^0.11.6", + "@matter/nodejs": "^0.11.6", + "@project-chip/matter.js": "^0.11.6", "archiver": "7.0.1", "express": "4.21.1", "glob": "11.0.0", From 82b64ed4e5c51093527ae0e074fb8d8f8b223ad3 Mon Sep 17 00:00:00 2001 From: Luligu Date: Wed, 27 Nov 2024 19:49:44 +0100 Subject: [PATCH 11/15] Remove patch for 0.11.5 --- src/matterbridge.ts | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/matterbridge.ts b/src/matterbridge.ts index 1268d9c2..cee85903 100644 --- a/src/matterbridge.ts +++ b/src/matterbridge.ts @@ -532,8 +532,6 @@ export class Matterbridge extends EventEmitter { } }); await this.cleanup('Exiting...'); - process.exit(0); - this.emit('shutdown'); return; } @@ -545,8 +543,6 @@ export class Matterbridge extends EventEmitter { await plugin.nodeContext?.logStorage(); } await this.cleanup('Exiting...'); - process.exit(0); - this.emit('shutdown'); return; } @@ -554,8 +550,6 @@ export class Matterbridge extends EventEmitter { this.log.info(`${plg}Matterbridge${nf} network interfaces log`); logInterfaces(); await this.cleanup('Exiting...'); - process.exit(0); - this.emit('shutdown'); return; } @@ -563,32 +557,24 @@ export class Matterbridge extends EventEmitter { this.log.debug(`Adding plugin ${getParameter('add')}`); await this.plugins.add(getParameter('add') as string); await this.cleanup('Exiting...'); - process.exit(0); - this.emit('shutdown'); return; } if (getParameter('remove')) { this.log.debug(`Removing plugin ${getParameter('remove')}`); await this.plugins.remove(getParameter('remove') as string); await this.cleanup('Exiting...'); - process.exit(0); - this.emit('shutdown'); return; } if (getParameter('enable')) { this.log.debug(`Enabling plugin ${getParameter('enable')}`); await this.plugins.enable(getParameter('enable') as string); await this.cleanup('Exiting...'); - process.exit(0); - this.emit('shutdown'); return; } if (getParameter('disable')) { this.log.debug(`Disabling plugin ${getParameter('disable')}`); await this.plugins.disable(getParameter('disable') as string); await this.cleanup('Exiting...'); - process.exit(0); - this.emit('shutdown'); return; } @@ -611,8 +597,6 @@ export class Matterbridge extends EventEmitter { this.plugins.clear(); this.devices.clear(); await this.cleanup('Exiting...'); - process.exit(0); - this.emit('shutdown'); return; } @@ -630,8 +614,6 @@ export class Matterbridge extends EventEmitter { await this.stopMatterStorage(); this.log.info('Reset done! Remove the device from the controller.'); await this.cleanup('Exiting...'); - process.exit(0); - this.emit('shutdown'); return; } @@ -649,8 +631,6 @@ export class Matterbridge extends EventEmitter { } await this.stopMatterStorage(); await this.cleanup('Exiting...'); - process.exit(0); - this.emit('shutdown'); return; } From 775e80ac2a61d6d1d20b694b31be572b79f12a7d Mon Sep 17 00:00:00 2001 From: Luligu Date: Wed, 27 Nov 2024 19:55:08 +0100 Subject: [PATCH 12/15] Release 1.6.3 --- CHANGELOG.md | 6 +----- src/matterbridge.ts | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a0a353a..9fa74450 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,15 +10,10 @@ The Home Assistant Community Add-ons and plugins are not verified to work with M If you want to run Matterbridge in Home Assistant please use the official add-on https://github.com/Luligu/matterbridge-home-assistant-addon that also has Ingress and side panel. -### New Apple firmware v. 18.x - -Please read this: https://github.com/Luligu/matterbridge/discussions/135 - ### Discord Tamer (https://github.com/tammeryousef1006) has created the Matterbridge Discord group: https://discord.gg/QX58CDe6hd. -Feel free to join (the link is now permanent)! ## [1.6.3] - 2024-11-27 @@ -29,6 +24,7 @@ Feel free to join (the link is now permanent)! ### Fixed - [matter.js]: Temporary fix the crash of matter.js on close when using command line parameters. +- [matter.js]: Update to matter.js 0.11.6. ## [1.6.2] - 2024-11-25 diff --git a/src/matterbridge.ts b/src/matterbridge.ts index cee85903..504ec129 100644 --- a/src/matterbridge.ts +++ b/src/matterbridge.ts @@ -503,7 +503,7 @@ export class Matterbridge extends EventEmitter { - disable [plugin name]: disable the globally installed plugin with the given name - reset [plugin path]: remove the commissioning for the plugin from the given absolute or relative path (childbridge mode). Shutdown Matterbridge before using it! - reset [plugin name]: remove the commissioning for the globally installed plugin (childbridge mode). Shutdown Matterbridge before using it!${rs}`); - this.emit('shutdown'); + await this.cleanup('Exiting...'); return; } From 068b7259ed21959d8dde3a65eb31aef2ccf73024 Mon Sep 17 00:00:00 2001 From: Luligu Date: Wed, 27 Nov 2024 19:58:58 +0100 Subject: [PATCH 13/15] Fix endpoint test for async subscribe --- src/matterbridgeEndpoint.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/matterbridgeEndpoint.test.ts b/src/matterbridgeEndpoint.test.ts index 47010bc4..7a078857 100644 --- a/src/matterbridgeEndpoint.test.ts +++ b/src/matterbridgeEndpoint.test.ts @@ -360,7 +360,7 @@ describe('MatterbridgeEndpoint class', () => { expect(await device.setAttribute(OnOffCluster.id, 'onOff', true, edge.log)).toBe(true); let state = device.getAttribute(OnOffCluster.id, 'onOff', edge.log); - const result = device.subscribeAttribute( + const result = await device.subscribeAttribute( OnOffCluster.id, 'onOff', (newValue: any, oldValue: any) => { From bd55eb13e252c36a71f885d4c62772f60eda726b Mon Sep 17 00:00:00 2001 From: Luligu Date: Wed, 27 Nov 2024 20:08:03 +0100 Subject: [PATCH 14/15] Remove patch for 0.11.5 --- src/matterbridge.ts | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/matterbridge.ts b/src/matterbridge.ts index 504ec129..0465ca1c 100644 --- a/src/matterbridge.ts +++ b/src/matterbridge.ts @@ -503,7 +503,7 @@ export class Matterbridge extends EventEmitter { - disable [plugin name]: disable the globally installed plugin with the given name - reset [plugin path]: remove the commissioning for the plugin from the given absolute or relative path (childbridge mode). Shutdown Matterbridge before using it! - reset [plugin name]: remove the commissioning for the globally installed plugin (childbridge mode). Shutdown Matterbridge before using it!${rs}`); - await this.cleanup('Exiting...'); + this.emit('shutdown'); return; } @@ -531,7 +531,7 @@ export class Matterbridge extends EventEmitter { this.log.info(` └─ endpoint ${RED}${device.endpoint}${nf} ${typ}${device.endpointName}${nf} ${debugStringify(device.clusterServersId)}`); } }); - await this.cleanup('Exiting...'); + this.emit('shutdown'); return; } @@ -542,39 +542,39 @@ export class Matterbridge extends EventEmitter { this.log.info(`${plg}${plugin.name}${nf} storage log`); await plugin.nodeContext?.logStorage(); } - await this.cleanup('Exiting...'); + this.emit('shutdown'); return; } if (hasParameter('loginterfaces')) { this.log.info(`${plg}Matterbridge${nf} network interfaces log`); logInterfaces(); - await this.cleanup('Exiting...'); + this.emit('shutdown'); return; } if (getParameter('add')) { this.log.debug(`Adding plugin ${getParameter('add')}`); await this.plugins.add(getParameter('add') as string); - await this.cleanup('Exiting...'); + this.emit('shutdown'); return; } if (getParameter('remove')) { this.log.debug(`Removing plugin ${getParameter('remove')}`); await this.plugins.remove(getParameter('remove') as string); - await this.cleanup('Exiting...'); + this.emit('shutdown'); return; } if (getParameter('enable')) { this.log.debug(`Enabling plugin ${getParameter('enable')}`); await this.plugins.enable(getParameter('enable') as string); - await this.cleanup('Exiting...'); + this.emit('shutdown'); return; } if (getParameter('disable')) { this.log.debug(`Disabling plugin ${getParameter('disable')}`); await this.plugins.disable(getParameter('disable') as string); - await this.cleanup('Exiting...'); + this.emit('shutdown'); return; } @@ -596,7 +596,7 @@ export class Matterbridge extends EventEmitter { this.nodeStorage = undefined; this.plugins.clear(); this.devices.clear(); - await this.cleanup('Exiting...'); + this.emit('shutdown'); return; } @@ -613,7 +613,7 @@ export class Matterbridge extends EventEmitter { await this.matterbridgeContext?.clearAll(); await this.stopMatterStorage(); this.log.info('Reset done! Remove the device from the controller.'); - await this.cleanup('Exiting...'); + this.emit('shutdown'); return; } @@ -630,7 +630,7 @@ export class Matterbridge extends EventEmitter { this.log.warn(`Plugin ${plg}${getParameter('reset')}${wr} not registerd in matterbridge`); } await this.stopMatterStorage(); - await this.cleanup('Exiting...'); + this.emit('shutdown'); return; } From 97eff86f6216af1e4bf87033848762ee95bc9ad2 Mon Sep 17 00:00:00 2001 From: Luligu Date: Wed, 27 Nov 2024 20:14:30 +0100 Subject: [PATCH 15/15] Release 1.6.3 --- package-lock.json | 4 ++-- package.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index c9bb102d..8644e7b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "matterbridge", - "version": "1.6.3-dev.1", + "version": "1.6.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "matterbridge", - "version": "1.6.3-dev.1", + "version": "1.6.3", "license": "Apache-2.0", "dependencies": { "@matter/main": "^0.11.6", diff --git a/package.json b/package.json index 74bb05dd..29e8e171 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "matterbridge", - "version": "1.6.3-dev.1", + "version": "1.6.3", "description": "Matterbridge plugin manager for Matter", "author": "https://github.com/Luligu", "license": "Apache-2.0", @@ -150,4 +150,4 @@ "typescript": "5.7.2", "typescript-eslint": "8.16.0" } -} +} \ No newline at end of file