diff --git a/README.md b/README.md index c7277a7..83d8fc7 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,12 @@ With the ioBroker Matter Adapter it is possible to map the following use cases: --> ## Changelog + +### __WORK IN PROGRESS__ +* (@Apollon77) Fixed Thermostat initialization logic and added more logging +* (@Apollon77) Fixed WindowCovering level to match ioBroker definition +* (@Apollon77) Updated matter.js for further optimizations + ### 0.4.4 (2025-01-24) * (@Apollon77) Added OPEN state for all Door Locks to open door again * (@Apollon77) Fixed Thermostat initialization when no AUTO mode is supported diff --git a/package-lock.json b/package-lock.json index 65ccaf8..30a1185 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,12 +10,12 @@ "license": "Apache-2.0", "dependencies": { "@iobroker/adapter-core": "^3.2.3", - "@iobroker/dm-utils": "^1.0.7", + "@iobroker/dm-utils": "1.0.7", "@iobroker/i18n": "^0.3.1", "@iobroker/type-detector": "^4.1.1", - "@matter/main": "0.12.0", - "@matter/nodejs": "0.12.0", - "@project-chip/matter.js": "0.12.0", + "@matter/main": "0.12.1", + "@matter/nodejs": "0.12.1", + "@project-chip/matter.js": "0.12.1", "axios": "^1.7.9", "jsonwebtoken": "^9.0.2" }, @@ -23,24 +23,24 @@ "@alcalzone/release-script": "^3.8.0", "@alcalzone/release-script-plugin-iobroker": "^3.7.2", "@alcalzone/release-script-plugin-license": "^3.7.0", - "@iobroker/build-tools": "^2.0.14", - "@iobroker/dev-server": "^0.7.3", + "@iobroker/build-tools": "^2.0.15", + "@iobroker/dev-server": "0.7.3", "@iobroker/eslint-config": "^1.0.0", "@iobroker/legacy-testing": "^2.0.2", "@iobroker/types": "^7.0.6", - "@types/jsonwebtoken": "^9.0.7", - "@types/node": "^22.10.7", + "@types/jsonwebtoken": "^9.0.8", + "@types/node": "^22.10.10", "chai": "^4.5.0", "colorette": "^2.0.20", - "mocha": "^11.0.1", - "puppeteer": "^24.1.0", + "mocha": "^11.1.0", + "puppeteer": "^24.1.1", "typescript": "~5.7.3" }, "engines": { "node": ">=18" }, "optionalDependencies": { - "@matter/nodejs-ble": "0.12.0" + "@matter/nodejs-ble": "0.12.1" } }, "node_modules/@alcalzone/pak": { @@ -497,9 +497,9 @@ } }, "node_modules/@iobroker/build-tools": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/@iobroker/build-tools/-/build-tools-2.0.14.tgz", - "integrity": "sha512-AdhOvxZ+wZC8EVSbHg/PvfSU/qsfAAny2AJMGMW03w9oPMrq/zTCBE9hAUnF59/I2RLrfFmUUIcg5xTkEDoy2A==", + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/@iobroker/build-tools/-/build-tools-2.0.15.tgz", + "integrity": "sha512-+nt+lstIdQROaB6u2kpQP4c4xwjCSD9aK0rYhpX4WJHhG6uxKaBYuWxKz79d5CThBY/MQ+wd5PuDz4acOQXKgA==", "dev": true, "dependencies": { "glob": "^10.4.5" @@ -874,64 +874,64 @@ } }, "node_modules/@matter/general": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@matter/general/-/general-0.12.0.tgz", - "integrity": "sha512-D6XkH/17qbvbNclw8IG82QzBGXGkDTBCaHe3zIDsMBraVUcQzKbTFrSQIP4tzqU6R2NC7nkmMsqFBV7HRVwwyQ==", + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@matter/general/-/general-0.12.1.tgz", + "integrity": "sha512-26ZnXpcPeKUJ3xGJvJnkM7dMt32IlJ+5ZCoM8KN2FtXC2Z6EUBJMVxjSxXA4Wbg91wZvj/y/z0xkcEI3gcIOAA==", "license": "Apache-2.0", "dependencies": { "@noble/curves": "^1.8.1" } }, "node_modules/@matter/main": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@matter/main/-/main-0.12.0.tgz", - "integrity": "sha512-cqliR5nnFJCEXKUKcwI9rxPZQNcrJ8iFpd6bOOEQ2v85+dYFZGDOxOWHMo70EoQOqsu7lGozGWRq4m642iXIRw==", + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@matter/main/-/main-0.12.1.tgz", + "integrity": "sha512-TQscTaFzgtUy9R+tNDm1aIViW4qDiXVdnYZGTVWjWqPN/7wOtEO2IgwP3xk9c3bHNkEXPux6TfvPoAx7UkYUng==", "license": "Apache-2.0", "dependencies": { - "@matter/general": "0.12.0", - "@matter/model": "0.12.0", - "@matter/node": "0.12.0", - "@matter/protocol": "0.12.0", - "@matter/types": "0.12.0", + "@matter/general": "0.12.1", + "@matter/model": "0.12.1", + "@matter/node": "0.12.1", + "@matter/protocol": "0.12.1", + "@matter/types": "0.12.1", "@noble/curves": "^1.8.1" }, "optionalDependencies": { - "@matter/nodejs": "0.12.0" + "@matter/nodejs": "0.12.1" } }, "node_modules/@matter/model": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@matter/model/-/model-0.12.0.tgz", - "integrity": "sha512-uJhdwWpSFV0wl84Q9nIj1Je8y2Y223XEqomVRNlzDEK450MxaQ/MAK1nEvi3BBTvoiNvAtSij+pIrzu5fYxnlg==", + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@matter/model/-/model-0.12.1.tgz", + "integrity": "sha512-UlUR7iRuBRadfuf4Qwo3OYi7WUrXJk4nddqsD2tBq7y1cA5zsnV3E85zVX/8iiiUSqAbx3rcAuWJ+CCjn0ikUA==", "license": "Apache-2.0", "dependencies": { - "@matter/general": "0.12.0", + "@matter/general": "0.12.1", "@noble/curves": "^1.8.1" } }, "node_modules/@matter/node": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@matter/node/-/node-0.12.0.tgz", - "integrity": "sha512-J/wQaXSuN3/fZnyTpOE8brmv5mZE2co2yajTg9DmZDgi0EXWXCF97+2vemlPh6BXAszDas7FdN/1kXu2MEA9/Q==", + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@matter/node/-/node-0.12.1.tgz", + "integrity": "sha512-PtN1pRmMynPwwxaSZklCDwLt4uCz1o/moXi0PX2DU866JdkHaKPgLi+29PcalcDB2dMZbrcJTaimAhXcjPVkog==", "license": "Apache-2.0", "dependencies": { - "@matter/general": "0.12.0", - "@matter/model": "0.12.0", - "@matter/protocol": "0.12.0", - "@matter/types": "0.12.0", + "@matter/general": "0.12.1", + "@matter/model": "0.12.1", + "@matter/protocol": "0.12.1", + "@matter/types": "0.12.1", "@noble/curves": "^1.8.1" } }, "node_modules/@matter/nodejs": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@matter/nodejs/-/nodejs-0.12.0.tgz", - "integrity": "sha512-VZtZcW2UzXiAnYAwJ+9XPDqCfO3amlzgCPBDTXpUKti4HrO0v6U5LmydNRGoGkNUB9QABxLpiAmEId+URZ2r9Q==", + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@matter/nodejs/-/nodejs-0.12.1.tgz", + "integrity": "sha512-G4tPCzaCJMuly0yiIf+eOhz1ezSQQarETFtDuImE+9vicVyKKCL1eq5SviV5nx9DikIcalKMbKh6F6t21sslDA==", "license": "Apache-2.0", "dependencies": { - "@matter/general": "0.12.0", - "@matter/node": "0.12.0", - "@matter/protocol": "0.12.0", - "@matter/types": "0.12.0", + "@matter/general": "0.12.1", + "@matter/node": "0.12.1", + "@matter/protocol": "0.12.1", + "@matter/types": "0.12.1", "node-localstorage": "^3.0.5" }, "engines": { @@ -939,15 +939,15 @@ } }, "node_modules/@matter/nodejs-ble": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@matter/nodejs-ble/-/nodejs-ble-0.12.0.tgz", - "integrity": "sha512-Tz7ugttTnKAiSyj0ZtE3cr9n0fm1fcII3/8/YBllS4xEcMZQlsLEc/3qncIrN6ca16U71IcJ1r9gMLkHwf2wlA==", + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@matter/nodejs-ble/-/nodejs-ble-0.12.1.tgz", + "integrity": "sha512-AyDLb9cNAp0jiWPSR0vl3UAVRBgQfoO706y490QZ2UXddsotEAWzTkcYSYYi1M6Yp61nCxAQGIuHYbW8XtraAA==", "license": "Apache-2.0", "optional": true, "dependencies": { - "@matter/general": "0.12.0", - "@matter/protocol": "0.12.0", - "@matter/types": "0.12.0" + "@matter/general": "0.12.1", + "@matter/protocol": "0.12.1", + "@matter/types": "0.12.1" }, "engines": { "node": ">=18.0.0" @@ -958,25 +958,25 @@ } }, "node_modules/@matter/protocol": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@matter/protocol/-/protocol-0.12.0.tgz", - "integrity": "sha512-wtDZR/APxMWdf7hErRshWlgnjisnID66GQ9Xxlkq6U1BciXf8qIb8UyWxKN6LWWUhOLPJe6rcn8SnXt6t/q1mA==", + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@matter/protocol/-/protocol-0.12.1.tgz", + "integrity": "sha512-HOa5OdMsmmSjmtYA+wmBmS2poUeZqlcoA9fUk40kWla6yINJOyHZCgnPKARxXxm1qk95BEoLN3ovUIKoajkstQ==", "license": "Apache-2.0", "dependencies": { - "@matter/general": "0.12.0", - "@matter/model": "0.12.0", - "@matter/types": "0.12.0", + "@matter/general": "0.12.1", + "@matter/model": "0.12.1", + "@matter/types": "0.12.1", "@noble/curves": "^1.8.1" } }, "node_modules/@matter/types": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@matter/types/-/types-0.12.0.tgz", - "integrity": "sha512-tS5amwLRymfnqMuVwJ+xYkXGthoBpYb6Dg6GE1IKvZeccl3xGQIYEvIw0rB806h/WkK97T6mB39hHNHliMLAIg==", + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@matter/types/-/types-0.12.1.tgz", + "integrity": "sha512-O4zyMGLUnoWQZ7P5TJDWrtTpdaG8xSDq1a5xO3e8pmc3I9w6LSoKciEqrjFvq9lT6gvj3hcts/64c0Rxn7NEIw==", "license": "Apache-2.0", "dependencies": { - "@matter/general": "0.12.0", - "@matter/model": "0.12.0", + "@matter/general": "0.12.1", + "@matter/model": "0.12.1", "@noble/curves": "^1.8.1" } }, @@ -1139,16 +1139,16 @@ } }, "node_modules/@project-chip/matter.js": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@project-chip/matter.js/-/matter.js-0.12.0.tgz", - "integrity": "sha512-7WO7/h4eIOApXYd6ZGFkNp5GlDScQPpqDJALJCnUbB2Z6+d01PpJ9d6Q2Z7OC/vooCXod/nebyj2YCQtGK7VOQ==", + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@project-chip/matter.js/-/matter.js-0.12.1.tgz", + "integrity": "sha512-IPNbBxnduNUNoipn4ZHXWE8gEsYM9nryYvWXlLYWwTJ6tDTIR0oZmsUZzhJoDXjShqbXolYJ8bCkFQ7dfMba6w==", "license": "Apache-2.0", "dependencies": { - "@matter/general": "0.12.0", - "@matter/model": "0.12.0", - "@matter/node": "0.12.0", - "@matter/protocol": "0.12.0", - "@matter/types": "0.12.0", + "@matter/general": "0.12.1", + "@matter/model": "0.12.1", + "@matter/node": "0.12.1", + "@matter/protocol": "0.12.1", + "@matter/types": "0.12.1", "@noble/curves": "^1.8.1" } }, @@ -1675,19 +1675,27 @@ "peer": true }, "node_modules/@types/jsonwebtoken": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.7.tgz", - "integrity": "sha512-ugo316mmTYBl2g81zDFnZ7cfxlut3o+/EQdaP7J8QN2kY6lJ22hmQYCK5EHcJHbrW+dkCGSCPgbG8JtYj6qSrg==", + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.8.tgz", + "integrity": "sha512-7fx54m60nLFUVYlxAB1xpe9CBWX2vSrk50Y6ogRJ1v5xxtba7qXTg5BgYDN5dq+yuQQ9HaVlHJyAAt1/mxryFg==", "dev": true, "license": "MIT", "dependencies": { + "@types/ms": "*", "@types/node": "*" } }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { - "version": "22.10.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.7.tgz", - "integrity": "sha512-V09KvXxFiutGp6B7XkpaDXlNadZxrzajcY50EuoLIpQ6WWYCSvf19lVIazzfIzQvhUN2HjX12spLojTnhuKlGg==", + "version": "22.10.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.10.tgz", + "integrity": "sha512-X47y/mPNzxviAGY5TcYPtYL8JsY3kAq2n8fMmKoRCxq/c4v4pyGNCzM2R6+M5/umG4ZfHuT+sgqDYqWc9rJ6ww==", "dev": true, "license": "MIT", "dependencies": { @@ -3364,9 +3372,9 @@ } }, "node_modules/chromium-bidi": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.12.0.tgz", - "integrity": "sha512-xzXveJmX826GGq1MeE5okD8XxaDT8172CXByhFJ687eY65rbjOIebdbUuQh+jXKaNyGKI14Veb3KjLLmSueaxA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-1.1.0.tgz", + "integrity": "sha512-HislCEczCuamWm3+55Lig9XKmMF13K+BGKum9rwtDAzgUAHT4h5jNwhDmD4U20VoVUG8ujnv9UZ89qiIf5uF8w==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -8053,9 +8061,9 @@ } }, "node_modules/mocha": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.0.1.tgz", - "integrity": "sha512-+3GkODfsDG71KSCQhc4IekSW+ItCK/kiez1Z28ksWvYhKXV/syxMlerR/sC7whDp7IyreZ4YxceMLdTs5hQE8A==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.1.0.tgz", + "integrity": "sha512-8uJR5RTC2NgpY3GrYcgpZrsEd9zKbPDpob1RezyR2upGHRQtHWofmzTMzTMSV6dru3tj5Ukt0+Vnq1qhFEEwAg==", "dev": true, "license": "MIT", "dependencies": { @@ -8076,8 +8084,8 @@ "strip-json-comments": "^3.1.1", "supports-color": "^8.1.1", "workerpool": "^6.5.1", - "yargs": "^16.2.0", - "yargs-parser": "^20.2.9", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1", "yargs-unparser": "^2.0.0" }, "bin": { @@ -8098,18 +8106,6 @@ "balanced-match": "^1.0.0" } }, - "node_modules/mocha/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, "node_modules/mocha/node_modules/minimatch": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", @@ -8139,23 +8135,14 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/mocha/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "node_modules/mocha/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, + "license": "ISC", "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/ms": { @@ -9358,18 +9345,18 @@ } }, "node_modules/puppeteer": { - "version": "24.1.0", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.1.0.tgz", - "integrity": "sha512-F+3yKILaosLToT7amR7LIkTKkKMR0EGQPjFBch+MtgS8vRPS+4cPnLJuXDVTfCj2NqfrCnShtOr7yD+9dEgHRQ==", + "version": "24.1.1", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.1.1.tgz", + "integrity": "sha512-fuhceZ5HZuDXVuaMIRxUuDHfCJLmK0pXh8FlzVQ0/+OApStevxZhU5kAVeYFOEqeCF5OoAyZjcWbdQK27xW/9A==", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { "@puppeteer/browsers": "2.7.0", - "chromium-bidi": "0.12.0", + "chromium-bidi": "1.1.0", "cosmiconfig": "^9.0.0", "devtools-protocol": "0.0.1380148", - "puppeteer-core": "24.1.0", + "puppeteer-core": "24.1.1", "typed-query-selector": "^2.12.0" }, "bin": { @@ -9380,14 +9367,14 @@ } }, "node_modules/puppeteer-core": { - "version": "24.1.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.1.0.tgz", - "integrity": "sha512-ReefWoQgqdyl67uWEBy/TMZ4mAB7hP0JB5HIxSE8B1ot/4ningX1gmzHCOSNfMbTiS/VJHCvaZAe3oJTXph7yw==", + "version": "24.1.1", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.1.1.tgz", + "integrity": "sha512-7FF3gq6bpIsbq3I8mfbodXh3DCzXagoz3l2eGv1cXooYU4g0P4mcHQVHuBD4iSZPXNg8WjzlP5kmRwK9UvwF0A==", "dev": true, "license": "Apache-2.0", "dependencies": { "@puppeteer/browsers": "2.7.0", - "chromium-bidi": "0.11.0", + "chromium-bidi": "1.1.0", "debug": "^4.4.0", "devtools-protocol": "0.0.1380148", "typed-query-selector": "^2.12.0", @@ -9397,20 +9384,6 @@ "node": ">=18" } }, - "node_modules/puppeteer-core/node_modules/chromium-bidi": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.11.0.tgz", - "integrity": "sha512-6CJWHkNRoyZyjV9Rwv2lYONZf1Xm0IuDyNq97nwSsxxP3wf5Bwy15K5rOvVKMtJ127jJBmxFUanSAOjgFRxgrA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "mitt": "3.0.1", - "zod": "3.23.8" - }, - "peerDependencies": { - "devtools-protocol": "*" - } - }, "node_modules/puppeteer-core/node_modules/debug": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", @@ -9429,23 +9402,6 @@ } } }, - "node_modules/puppeteer-core/node_modules/mitt": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", - "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", - "dev": true, - "license": "MIT" - }, - "node_modules/puppeteer-core/node_modules/zod": { - "version": "3.23.8", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", - "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, "node_modules/qs": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", diff --git a/package.json b/package.json index c0dfeff..931b67b 100644 --- a/package.json +++ b/package.json @@ -23,16 +23,16 @@ "url": "https://github.com/ioBroker/ioBroker.matter" }, "optionalDependencies": { - "@matter/nodejs-ble": "0.12.0" + "@matter/nodejs-ble": "0.12.1" }, "dependencies": { "@iobroker/adapter-core": "^3.2.3", "@iobroker/i18n": "^0.3.1", - "@iobroker/dm-utils": "^1.0.7", + "@iobroker/dm-utils": "1.0.7", "@iobroker/type-detector": "^4.1.1", - "@matter/main": "0.12.0", - "@matter/nodejs": "0.12.0", - "@project-chip/matter.js": "0.12.0", + "@matter/main": "0.12.1", + "@matter/nodejs": "0.12.1", + "@project-chip/matter.js": "0.12.1", "axios": "^1.7.9", "jsonwebtoken": "^9.0.2" }, @@ -40,17 +40,17 @@ "@alcalzone/release-script": "^3.8.0", "@alcalzone/release-script-plugin-iobroker": "^3.7.2", "@alcalzone/release-script-plugin-license": "^3.7.0", - "@iobroker/build-tools": "^2.0.14", - "@iobroker/dev-server": "^0.7.3", + "@iobroker/build-tools": "^2.0.15", + "@iobroker/dev-server": "0.7.3", "@iobroker/eslint-config": "^1.0.0", "@iobroker/legacy-testing": "^2.0.2", "@iobroker/types": "^7.0.6", - "@types/jsonwebtoken": "^9.0.7", - "@types/node": "^22.10.7", + "@types/jsonwebtoken": "^9.0.8", + "@types/node": "^22.10.10", "chai": "^4.5.0", "colorette": "^2.0.20", - "mocha": "^11.0.1", - "puppeteer": "^24.1.0", + "mocha": "^11.1.0", + "puppeteer": "^24.1.1", "typescript": "~5.7.3" }, "bugs": { diff --git a/src-admin/package-lock.json b/src-admin/package-lock.json index 02ca7c6..c43fcc6 100644 --- a/src-admin/package-lock.json +++ b/src-admin/package-lock.json @@ -1,12 +1,12 @@ { "name": "iobroker.matter", - "version": "0.4.3", + "version": "0.4.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "iobroker.matter", - "version": "0.4.3", + "version": "0.4.4", "dependencies": { "@foxriver76/iob-component-lib": "^0.2.0", "@iobroker/adapter-react-v5": "^7.4.17", diff --git a/src/matter/to-iobroker/WindowCoveringToIoBroker.ts b/src/matter/to-iobroker/WindowCoveringToIoBroker.ts index 8ca472b..8654f7a 100644 --- a/src/matter/to-iobroker/WindowCoveringToIoBroker.ts +++ b/src/matter/to-iobroker/WindowCoveringToIoBroker.ts @@ -129,7 +129,7 @@ export class WindowCoveringToIoBroker extends GenericElectricityDataDeviceToIoBr this.updateWorkingStateForLift(value).catch(e => this.ioBrokerDevice.adapter.log.error(`Failed to update working state: ${e}`), ); - return Math.round(value / 100); + return 100 - Math.round(value / 100); }, changeHandler: async value => { if ( @@ -138,7 +138,7 @@ export class WindowCoveringToIoBroker extends GenericElectricityDataDeviceToIoBr throw new Error('Position aware lift not supported. Can not set lift target percentage'); } await this.appEndpoint.getClusterClient(WindowCovering.Complete)?.goToLiftPercentage({ - liftPercent100thsValue: Math.round(value * 100), + liftPercent100thsValue: Math.round(100 - value) * 100, }); }, }); @@ -146,7 +146,7 @@ export class WindowCoveringToIoBroker extends GenericElectricityDataDeviceToIoBr endpointId: this.appEndpoint.getNumber(), clusterId: WindowCovering.Cluster.id, attributeName: 'currentPositionLiftPercent100ths', - convertValue: value => Math.round(value / 100), + convertValue: value => 100 - Math.round(value / 100), }); this.enableDeviceTypeStateForAttribute(PropertyType.Stop, { @@ -184,7 +184,7 @@ export class WindowCoveringToIoBroker extends GenericElectricityDataDeviceToIoBr this.updateWorkingStateForTilt(value).catch(e => this.ioBrokerDevice.adapter.log.error(`Failed to update working state: ${e}`), ); - return Math.round(value / 100); + return 100 - Math.round(value / 100); }, changeHandler: async value => { if ( @@ -193,7 +193,7 @@ export class WindowCoveringToIoBroker extends GenericElectricityDataDeviceToIoBr throw new Error('Position aware tilt not supported. Can not set tilt target percentage'); } await this.appEndpoint.getClusterClient(WindowCovering.Complete)?.goToTiltPercentage({ - tiltPercent100thsValue: Math.round(value * 100), + tiltPercent100thsValue: Math.round(100 - value) * 100, }); }, }); @@ -201,7 +201,7 @@ export class WindowCoveringToIoBroker extends GenericElectricityDataDeviceToIoBr endpointId: this.appEndpoint.getNumber(), clusterId: WindowCovering.Cluster.id, attributeName: 'currentPositionTiltPercent100ths', - convertValue: value => Math.round(value / 100), + convertValue: value => 100 - Math.round(value / 100), }); } diff --git a/src/matter/to-matter/BlindsToMatter.ts b/src/matter/to-matter/BlindsToMatter.ts index 9e9635a..db0c688 100644 --- a/src/matter/to-matter/BlindsToMatter.ts +++ b/src/matter/to-matter/BlindsToMatter.ts @@ -92,8 +92,8 @@ export class BlindsToMatter extends GenericDeviceToMatter { ) { await this.#matterEndpoint.setStateOf(EventedWindowCoveringServer, { // @ts-expect-error Workaround a matter.js instancing/typing error - currentPositionTiltPercent100ths: (this.#ioBrokerDevice.getTiltLevel() ?? 0) * 100, - targetPositionTiltPercent100ths: (this.#ioBrokerDevice.getTiltLevel() ?? 0) * 100, + currentPositionTiltPercent100ths: Math.round(100 - (this.#ioBrokerDevice.getTiltLevel() ?? 0)) * 100, + targetPositionTiltPercent100ths: Math.round(100 - (this.#ioBrokerDevice.getTiltLevel() ?? 0)) * 100, }); } if ( @@ -102,8 +102,10 @@ export class BlindsToMatter extends GenericDeviceToMatter { ) { await this.#matterEndpoint.setStateOf(EventedWindowCoveringServer, { // @ts-expect-error Workaround a matter.js instancing/typing error - currentPositionLiftPercent100ths: ((this.#ioBrokerDevice as Blind).getLevel() ?? 0) * 100, - targetPositionLiftPercent100ths: ((this.#ioBrokerDevice as Blind).getLevel() ?? 0) * 100, + currentPositionLiftPercent100ths: + Math.round(100 - ((this.#ioBrokerDevice as Blind).getLevel() ?? 0)) * 100, + targetPositionLiftPercent100ths: + Math.round(100 - ((this.#ioBrokerDevice as Blind).getLevel() ?? 0)) * 100, }); } @@ -121,19 +123,19 @@ export class BlindsToMatter extends GenericDeviceToMatter { targetPercent100ths !== undefined && this.#ioBrokerDevice.hasLiftLevel() ) { - await (this.#ioBrokerDevice as Blind).setLevel(Math.round(targetPercent100ths / 100)); + await (this.#ioBrokerDevice as Blind).setLevel(100 - Math.round(targetPercent100ths / 100)); } else { if (direction === MovementDirection.Open || reversed) { if (this.#ioBrokerDevice.hasLiftButtons()) { await (this.#ioBrokerDevice as BlindButtons).setOpen(); } else if (this.#ioBrokerDevice.hasLiftLevel()) { - await (this.#ioBrokerDevice as Blind).setLevel(reversed ? 100 : 0); + await (this.#ioBrokerDevice as Blind).setLevel(reversed ? 0 : 100); } } else { if (this.#ioBrokerDevice.hasLiftButtons()) { await (this.#ioBrokerDevice as BlindButtons).setClose(); } else if (this.#ioBrokerDevice.hasLiftLevel()) { - await (this.#ioBrokerDevice as Blind).setLevel(reversed ? 0 : 100); + await (this.#ioBrokerDevice as Blind).setLevel(reversed ? 100 : 0); } } } @@ -146,19 +148,19 @@ export class BlindsToMatter extends GenericDeviceToMatter { targetPercent100ths !== undefined && this.#ioBrokerDevice.hasTiltLevel() ) { - await this.#ioBrokerDevice.setTiltLevel(Math.round(targetPercent100ths / 100)); + await this.#ioBrokerDevice.setTiltLevel(100 - Math.round(targetPercent100ths / 100)); } else { if (direction === MovementDirection.Open || reversed) { if (this.#ioBrokerDevice.hasTiltButtons()) { await (this.#ioBrokerDevice as BlindButtons).setTiltOpen(); } else if (this.#ioBrokerDevice.hasTiltLevel()) { - await (this.#ioBrokerDevice as Blind).setLevel(reversed ? 100 : 0); + await (this.#ioBrokerDevice as Blind).setLevel(reversed ? 0 : 100); } } else { if (this.#ioBrokerDevice.hasTiltButtons()) { await (this.#ioBrokerDevice as BlindButtons).setTiltClose(); } else if (this.#ioBrokerDevice.hasTiltLevel()) { - await (this.#ioBrokerDevice as Blind).setLevel(reversed ? 0 : 100); + await (this.#ioBrokerDevice as Blind).setLevel(reversed ? 100 : 0); } } } @@ -199,12 +201,12 @@ export class BlindsToMatter extends GenericDeviceToMatter { ) { await this.#matterEndpoint.setStateOf(EventedWindowCoveringServer, { // @ts-expect-error Workaround a matter.js instancing/typing error - currentPositionTiltPercent100ths: (event.value as number) * 100, + currentPositionTiltPercent100ths: Math.round(100 - event.value) * 100, }); if (event.property === PropertyType.TiltLevel) { await this.#matterEndpoint.setStateOf(EventedWindowCoveringServer, { // @ts-expect-error Workaround a matter.js instancing/typing error - targetPositionTiltPercent100ths: (event.value as number) * 100, + targetPositionTiltPercent100ths: Math.round(100 - event.value) * 100, }); } } @@ -217,12 +219,12 @@ export class BlindsToMatter extends GenericDeviceToMatter { ) { await this.#matterEndpoint.setStateOf(EventedWindowCoveringServer, { // @ts-expect-error Workaround a matter.js instancing/typing error - currentPositionLiftPercent100ths: (event.value as number) * 100, + currentPositionLiftPercent100ths: Math.round(100 - event.value) * 100, }); if (event.property === PropertyType.Level) { await this.#matterEndpoint.setStateOf(EventedWindowCoveringServer, { // @ts-expect-error Workaround a matter.js instancing/typing error - targetPositionLiftPercent100ths: (event.value as number) * 100, + targetPositionLiftPercent100ths: Math.round(100 - event.value) * 100, }); } } diff --git a/src/matter/to-matter/ThermostatToMatter.ts b/src/matter/to-matter/ThermostatToMatter.ts index 286d5d4..7276c12 100644 --- a/src/matter/to-matter/ThermostatToMatter.ts +++ b/src/matter/to-matter/ThermostatToMatter.ts @@ -18,6 +18,7 @@ export class ThermostatToMatter extends GenericDeviceToMatter { readonly #matterEndpointThermostat: Endpoint; readonly #matterEndpointHumidity?: Endpoint; #supportedModes = new Array(); + #validModes = new Array(); constructor(ioBrokerDevice: Thermostat, name: string, uuid: string) { super(name, uuid); @@ -31,10 +32,12 @@ export class ThermostatToMatter extends GenericDeviceToMatter { switch (mode) { case ThermostatMode.Heat: this.#supportedModes.push(ThermostatMode.Heat); + this.#validModes.push(ThermostatMode.Heat); clusterModes.push(MatterThermostat.Feature.Heating); break; case ThermostatMode.Cool: this.#supportedModes.push(ThermostatMode.Cool); + this.#validModes.push(ThermostatMode.Cool); clusterModes.push(MatterThermostat.Feature.Cooling); break; case ThermostatMode.Auto: @@ -42,12 +45,15 @@ export class ThermostatToMatter extends GenericDeviceToMatter { break; case ThermostatMode.Off: this.#supportedModes.push(ThermostatMode.Off); + this.#validModes.push(ThermostatMode.Off); break; case ThermostatMode.FanOnly: this.#supportedModes.push(ThermostatMode.FanOnly); + this.#validModes.push(ThermostatMode.FanOnly); break; case ThermostatMode.Dry: this.#supportedModes.push(ThermostatMode.Dry); + this.#validModes.push(ThermostatMode.Dry); break; default: ignoredModes.push(mode); @@ -60,6 +66,7 @@ export class ThermostatToMatter extends GenericDeviceToMatter { ) { clusterModes.push(MatterThermostat.Feature.AutoMode); this.#supportedModes.push(ThermostatMode.Auto); + this.#validModes.push(ThermostatMode.Auto); } else { // Auto mode requires Heating and cooling to be supported too this.#ioBrokerDevice.adapter.log.info( @@ -68,7 +75,7 @@ export class ThermostatToMatter extends GenericDeviceToMatter { } if ( - !clusterModes.includes(MatterThermostat.Feature.Heating) || + !clusterModes.includes(MatterThermostat.Feature.Heating) && !clusterModes.includes(MatterThermostat.Feature.Cooling) ) { // When no mode is there tell that it is a Heating thermostat @@ -76,12 +83,19 @@ export class ThermostatToMatter extends GenericDeviceToMatter { `${uuid}: Matter Thermostats need to either support heating or cooling. Defaulting to Heating`, ); clusterModes.push(MatterThermostat.Feature.Heating); + this.#supportedModes.push(ThermostatMode.Heat); } if (ignoredModes.length > 0) { this.#ioBrokerDevice.adapter.log.info( `${uuid}: Ignoring unsupported modes for Thermostat: ${ignoredModes.join(', ')}`, ); } + this.#ioBrokerDevice.adapter.log.info( + `Mapped Thermostat Modes "${this.#supportedModes.join('","')}" to Matter Features "${clusterModes.map(feature => MatterThermostat.Feature[feature]).join('","')}"`, + ); + this.#ioBrokerDevice.adapter.log.info( + `Valid Modes the adapter will react on from ioBroker Device: ${this.#validModes.length ? `"${this.#validModes.join('","')}"` : 'None, Mode state is ignored'}`, + ); const hasHeating = clusterModes.includes(MatterThermostat.Feature.Heating); const hasCooling = clusterModes.includes(MatterThermostat.Feature.Cooling); @@ -105,10 +119,10 @@ export class ThermostatToMatter extends GenericDeviceToMatter { controlSequenceOfOperation: hasHeating && hasCooling ? MatterThermostat.ControlSequenceOfOperation.CoolingAndHeating - : hasHeating - ? MatterThermostat.ControlSequenceOfOperation.HeatingOnly - : MatterThermostat.ControlSequenceOfOperation.CoolingOnly, - minSetpointDeadBand: this.#supportedModes.includes(ThermostatMode.Auto) ? 0 : undefined, + : hasCooling + ? MatterThermostat.ControlSequenceOfOperation.CoolingOnly + : MatterThermostat.ControlSequenceOfOperation.HeatingOnly, + minSetpointDeadBand: clusterModes.includes(MatterThermostat.Feature.AutoMode) ? 0 : undefined, absMinHeatSetpointLimit: hasHeating ? this.convertTemperatureValue(7) : undefined, absMaxHeatSetpointLimit: hasHeating ? this.convertTemperatureValue(30) : undefined, absMinCoolSetpointLimit: hasCooling ? this.convertTemperatureValue(16) : undefined, @@ -145,6 +159,24 @@ export class ThermostatToMatter extends GenericDeviceToMatter { return parseFloat((value / 100).toFixed(2)); } + #mapModeToMatter(mode: ThermostatMode | undefined): MatterThermostat.SystemMode | undefined { + if (mode === undefined || !this.#validModes.includes(mode)) { + return; + } + switch (mode) { + case ThermostatMode.Heat: + return MatterThermostat.SystemMode.Heat; + case ThermostatMode.Cool: + return MatterThermostat.SystemMode.Cool; + case ThermostatMode.Auto: + return MatterThermostat.SystemMode.Auto; + case ThermostatMode.FanOnly: + return MatterThermostat.SystemMode.FanOnly; + case ThermostatMode.Dry: + return MatterThermostat.SystemMode.Dry; + } + } + async registerHandlersAndInitialize(): Promise { await super.registerHandlersAndInitialize(); @@ -154,31 +186,17 @@ export class ThermostatToMatter extends GenericDeviceToMatter { ? MatterThermostat.SystemMode.Off : undefined; if (systemMode === undefined && this.#ioBrokerDevice.hasMode()) { - const mode = this.#ioBrokerDevice.getMode(); - if (mode && this.#supportedModes.includes(mode)) { - switch (this.#ioBrokerDevice.getMode()) { - case ThermostatMode.Heat: - systemMode = MatterThermostat.SystemMode.Heat; - break; - case ThermostatMode.Cool: - systemMode = MatterThermostat.SystemMode.Cool; - break; - case ThermostatMode.Auto: - systemMode = MatterThermostat.SystemMode.Auto; - break; - case ThermostatMode.FanOnly: - systemMode = MatterThermostat.SystemMode.FanOnly; - break; - case ThermostatMode.Dry: - systemMode = MatterThermostat.SystemMode.Dry; - break; - } - } + systemMode = this.#mapModeToMatter(this.#ioBrokerDevice.getMode()); } if (systemMode === undefined) { systemMode = this.#supportedModes.includes(ThermostatMode.Heat) ? MatterThermostat.SystemMode.Heat - : MatterThermostat.SystemMode.Cool; + : this.#supportedModes.includes(ThermostatMode.Cool) + ? MatterThermostat.SystemMode.Cool + : undefined; + if (systemMode === undefined) { + this.#ioBrokerDevice.adapter.log.error(`${this.uuid}: Could not determine SystemMode`); + } } const controlSequenceOfOperation = this.#supportedModes.includes(ThermostatMode.Heat) && this.#supportedModes.includes(ThermostatMode.Cool) @@ -222,7 +240,7 @@ export class ThermostatToMatter extends GenericDeviceToMatter { await this.#ioBrokerDevice.setPower(false); break; case MatterThermostat.SystemMode.Heat: { - if (this.#ioBrokerDevice.hasMode()) { + if (this.#ioBrokerDevice.hasMode() && this.#validModes.includes(ThermostatMode.Heat)) { await this.#ioBrokerDevice.setMode(ThermostatMode.Heat); } const heatingTemp = @@ -234,7 +252,7 @@ export class ThermostatToMatter extends GenericDeviceToMatter { break; } case MatterThermostat.SystemMode.Cool: { - if (this.#ioBrokerDevice.hasMode()) { + if (this.#ioBrokerDevice.hasMode() && this.#validModes.includes(ThermostatMode.Cool)) { await this.#ioBrokerDevice.setMode(ThermostatMode.Cool); } const coolingTemp = @@ -246,20 +264,17 @@ export class ThermostatToMatter extends GenericDeviceToMatter { break; } case MatterThermostat.SystemMode.Auto: - if (this.#ioBrokerDevice.hasMode()) { + if (this.#ioBrokerDevice.hasMode() && this.#validModes.includes(ThermostatMode.Auto)) { await this.#ioBrokerDevice.setMode(ThermostatMode.Auto); } break; case MatterThermostat.SystemMode.FanOnly: - if ( - this.#ioBrokerDevice.hasMode() && - this.#ioBrokerDevice.getMode() !== ThermostatMode.FanOnly - ) { + if (this.#ioBrokerDevice.hasMode() && this.#validModes.includes(ThermostatMode.FanOnly)) { await this.#ioBrokerDevice.setMode(ThermostatMode.FanOnly); } break; case MatterThermostat.SystemMode.Dry: - if (this.#ioBrokerDevice.hasMode()) { + if (this.#ioBrokerDevice.hasMode() && this.#validModes.includes(ThermostatMode.Dry)) { await this.#ioBrokerDevice.setMode(ThermostatMode.Dry); } break; @@ -328,26 +343,11 @@ export class ThermostatToMatter extends GenericDeviceToMatter { let systemMode = event.value ? undefined : MatterThermostat.SystemMode.Off; if (event.value && this.#ioBrokerDevice.hasMode()) { const mode = this.#ioBrokerDevice.getMode(); - if (!mode || !this.#supportedModes.includes(mode)) { + const mappedMode = this.#mapModeToMatter(mode); + if (mappedMode == undefined) { return; } - switch (mode) { - case ThermostatMode.Heat: - systemMode = MatterThermostat.SystemMode.Heat; - break; - case ThermostatMode.Cool: - systemMode = MatterThermostat.SystemMode.Cool; - break; - case ThermostatMode.Auto: - systemMode = MatterThermostat.SystemMode.Auto; - break; - case ThermostatMode.FanOnly: - systemMode = MatterThermostat.SystemMode.FanOnly; - break; - case ThermostatMode.Dry: - systemMode = MatterThermostat.SystemMode.Dry; - break; - } + systemMode = mappedMode; } if (systemMode !== undefined) { await this.#matterEndpointThermostat.setStateOf(IoThermostatServer, { @@ -361,31 +361,12 @@ export class ThermostatToMatter extends GenericDeviceToMatter { // it is turned off, so do not report any mode changes return; } - if (!this.#supportedModes.includes(event.value as ThermostatMode)) { + if (!this.#validModes.length) { return; } - let systemMode: MatterThermostat.SystemMode; - switch (event.value) { - case ThermostatMode.Heat: - systemMode = MatterThermostat.SystemMode.Heat; - break; - case ThermostatMode.Cool: - systemMode = MatterThermostat.SystemMode.Cool; - break; - case ThermostatMode.Off: - systemMode = MatterThermostat.SystemMode.Off; - break; - case ThermostatMode.Auto: - systemMode = MatterThermostat.SystemMode.Auto; - break; - case ThermostatMode.FanOnly: - systemMode = MatterThermostat.SystemMode.FanOnly; - break; - case ThermostatMode.Dry: - systemMode = MatterThermostat.SystemMode.Dry; - break; - default: - return; + const systemMode = this.#mapModeToMatter(event.value as ThermostatMode); + if (systemMode === undefined) { + return; } await this.#matterEndpointThermostat.setStateOf(IoThermostatServer, { systemMode,