From cb810ab60fc1b1f51385cbc83b7408dbe0fd0ab0 Mon Sep 17 00:00:00 2001
From: Pierre-Gilles Leymarie <7365207+Pierre-Gilles@users.noreply.github.com>
Date: Mon, 23 Mar 2026 09:08:41 +0100
Subject: [PATCH 01/16] Update Matter.js to 0.16.10 and adapt code
---
server/package-lock.json | 204 +++++++++---------
server/package.json | 2 +-
server/services/matter/lib/matter.getNodes.js | 10 +-
server/services/matter/lib/matter.init.js | 5 +-
server/services/matter/lib/matter.setValue.js | 21 +-
server/services/matter/package-lock.json | 124 +++++------
server/services/matter/package.json | 4 +-
.../matter/utils/convertToGladysDevice.js | 6 +-
8 files changed, 191 insertions(+), 185 deletions(-)
diff --git a/server/package-lock.json b/server/package-lock.json
index 55ef046d84..047b10e7fe 100644
--- a/server/package-lock.json
+++ b/server/package-lock.json
@@ -53,7 +53,7 @@
"ws": "^6.2.2"
},
"devDependencies": {
- "@matter/main": "^0.13.0",
+ "@matter/main": "^0.16.10",
"apidoc": "^1.0.3",
"chai": "^4.3.7",
"chai-as-promised": "^7.1.1",
@@ -1062,93 +1062,93 @@
}
},
"node_modules/@matter/general": {
- "version": "0.13.0",
- "resolved": "https://registry.npmjs.org/@matter/general/-/general-0.13.0.tgz",
- "integrity": "sha512-PZ+FVJotKWgtoBvorqN+PLCuTBBbTCJTCss2P5C6n9r/ZAIcCgW7LDTFmRXNNNMJEri8JUVR0REvHaa92zVj2Q==",
+ "version": "0.16.10",
+ "resolved": "https://registry.npmjs.org/@matter/general/-/general-0.16.10.tgz",
+ "integrity": "sha512-/qytvaxvDDhEdHLaEoxlEFVBWg982jL+XXvOmAFgIv92yGDQvN4U+VcNW7S5dueJuv/L+gi0zDqhl8LUzHHAlg==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@noble/curves": "^1.8.2"
+ "@noble/curves": "^2.0.1"
}
},
"node_modules/@matter/main": {
- "version": "0.13.0",
- "resolved": "https://registry.npmjs.org/@matter/main/-/main-0.13.0.tgz",
- "integrity": "sha512-Qu60G05f821bEtp2yU+rJ7Xpe66GHDn9NdSPGrAn1EJH/iWplmVeLS1nSXzyGE28iPVPYNLcMX0edY/FejAhmQ==",
+ "version": "0.16.10",
+ "resolved": "https://registry.npmjs.org/@matter/main/-/main-0.16.10.tgz",
+ "integrity": "sha512-QKoQrmMnt6cB893+Oezk3DdIVgQJj5spt/ikEszF8pjyTuvB69zlzq1wnrn52N3mi57R6UWwk6+BPEbQE95FSw==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@matter/general": "0.13.0",
- "@matter/model": "0.13.0",
- "@matter/node": "0.13.0",
- "@matter/protocol": "0.13.0",
- "@matter/types": "0.13.0"
+ "@matter/general": "0.16.10",
+ "@matter/model": "0.16.10",
+ "@matter/node": "0.16.10",
+ "@matter/protocol": "0.16.10",
+ "@matter/types": "0.16.10"
},
"optionalDependencies": {
- "@matter/nodejs": "0.13.0"
+ "@matter/nodejs": "0.16.10"
}
},
"node_modules/@matter/model": {
- "version": "0.13.0",
- "resolved": "https://registry.npmjs.org/@matter/model/-/model-0.13.0.tgz",
- "integrity": "sha512-rcXu7OdMctlOGVOkClH6/+11ct6FMDSK2/Yu05+J7BJfohJY5mQbo0jnz8l0FPbwRrk5ADbqfAJ5jh/1OKHR2Q==",
+ "version": "0.16.10",
+ "resolved": "https://registry.npmjs.org/@matter/model/-/model-0.16.10.tgz",
+ "integrity": "sha512-6Ei8gETAkcKGEMRW+z8Mak55Y1Jl1TKGQIboC/4vvsrqcvB8zhIvGBS3GaAllxzvF0qjE7ihCPpgXXr6HuTLyg==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@matter/general": "0.13.0"
+ "@matter/general": "0.16.10"
}
},
"node_modules/@matter/node": {
- "version": "0.13.0",
- "resolved": "https://registry.npmjs.org/@matter/node/-/node-0.13.0.tgz",
- "integrity": "sha512-HQkzpRnhAUfj9u2ijkT4qgyFzEfaNqyAxh+dgMpLKnbbGQoHTskJ/wEgkRRI7B0Q57mr6VJ5KgXYdbXUYA7xFA==",
+ "version": "0.16.10",
+ "resolved": "https://registry.npmjs.org/@matter/node/-/node-0.16.10.tgz",
+ "integrity": "sha512-Hb2AxuEf0DlfN8yHxeahZGYurUUu/UDWJkmdvpDKuwSR0eIHhMweOG2RBO55/anyRFObANaUr1gr3DnyocB/0w==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@matter/general": "0.13.0",
- "@matter/model": "0.13.0",
- "@matter/protocol": "0.13.0",
- "@matter/types": "0.13.0"
+ "@matter/general": "0.16.10",
+ "@matter/model": "0.16.10",
+ "@matter/protocol": "0.16.10",
+ "@matter/types": "0.16.10"
}
},
"node_modules/@matter/nodejs": {
- "version": "0.13.0",
- "resolved": "https://registry.npmjs.org/@matter/nodejs/-/nodejs-0.13.0.tgz",
- "integrity": "sha512-ThWrLZJo7UH4Ebanf3gxkhe2p8vq4X3PxyRG+ICDRGPfzSAJZ3znh2hD/zdvcdyzQlSoXeLpFbLpTkJu7aRMHg==",
+ "version": "0.16.10",
+ "resolved": "https://registry.npmjs.org/@matter/nodejs/-/nodejs-0.16.10.tgz",
+ "integrity": "sha512-o8e9tGZVsiqmEtD1osSL9+gRMIuNjtwXt29I3YDRzSqb3N5Dvd4Khj3HN68YhaFFeBlM4YEV2TS0/9VF3C06/w==",
"dev": true,
"license": "Apache-2.0",
"optional": true,
"dependencies": {
- "@matter/general": "0.13.0",
- "@matter/node": "0.13.0",
- "@matter/protocol": "0.13.0",
- "@matter/types": "0.13.0"
+ "@matter/general": "0.16.10",
+ "@matter/node": "0.16.10",
+ "@matter/protocol": "0.16.10",
+ "@matter/types": "0.16.10"
},
"engines": {
- "node": ">=18.0.0"
+ "node": ">=20.19.0 <22.0.0 || >=22.13.0"
}
},
"node_modules/@matter/protocol": {
- "version": "0.13.0",
- "resolved": "https://registry.npmjs.org/@matter/protocol/-/protocol-0.13.0.tgz",
- "integrity": "sha512-wFxU6+LG5ygzruOV5JF30hmLkk88hz8PqAMkQ6ow81ZvoDFBevsW0OyqxXMCNwYd/zmGXmvr3mpC0mi9/troHg==",
+ "version": "0.16.10",
+ "resolved": "https://registry.npmjs.org/@matter/protocol/-/protocol-0.16.10.tgz",
+ "integrity": "sha512-vPQEMl8Wf4vc3tauwsGlLZRrDx+VrCPfccw3n50Lvyucws4UBt+SuBszSyIO2+QPnJcr4MB4L+EgCRI14U4zRA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@matter/general": "0.13.0",
- "@matter/model": "0.13.0",
- "@matter/types": "0.13.0"
+ "@matter/general": "0.16.10",
+ "@matter/model": "0.16.10",
+ "@matter/types": "0.16.10"
}
},
"node_modules/@matter/types": {
- "version": "0.13.0",
- "resolved": "https://registry.npmjs.org/@matter/types/-/types-0.13.0.tgz",
- "integrity": "sha512-8mH7hRC4MBSy4KUs8zb6uDTr0MfRYGtGBFq9t2uedlsiHA5lMUP3L1fitszoeCbpJh4EeqKHWSvF6RxWzKNueA==",
+ "version": "0.16.10",
+ "resolved": "https://registry.npmjs.org/@matter/types/-/types-0.16.10.tgz",
+ "integrity": "sha512-AW86tGgL3sN1Vb76+03VPdQMsW9vWsaVGHe9agcED1sjtWRJBV17tcLDymAQ8k7fEeVqiy3qf9CUwFK1bhfXKQ==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@matter/general": "0.13.0",
- "@matter/model": "0.13.0"
+ "@matter/general": "0.16.10",
+ "@matter/model": "0.16.10"
}
},
"node_modules/@microsoft/recognizers-text": {
@@ -1776,29 +1776,29 @@
}
},
"node_modules/@noble/curves": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.0.tgz",
- "integrity": "sha512-7YDlXiNMdO1YZeH6t/kvopHHbIZzlxrCV9WLqCY6QhcXOoXiNCMDqJIglZ9Yjx5+w7Dz30TITFrlTjnRg7sKEg==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-2.0.1.tgz",
+ "integrity": "sha512-vs1Az2OOTBiP4q0pwjW5aF0xp9n4MxVrmkFBxc6EKZc6ddYx5gaZiAsZoq0uRRXWbi3AT/sBqn05eRPtn1JCPw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@noble/hashes": "1.8.0"
+ "@noble/hashes": "2.0.1"
},
"engines": {
- "node": "^14.21.3 || >=16"
+ "node": ">= 20.19.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@noble/hashes": {
- "version": "1.8.0",
- "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
- "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.0.1.tgz",
+ "integrity": "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==",
"dev": true,
"license": "MIT",
"engines": {
- "node": "^14.21.3 || >=16"
+ "node": ">= 20.19.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
@@ -13146,81 +13146,81 @@
}
},
"@matter/general": {
- "version": "0.13.0",
- "resolved": "https://registry.npmjs.org/@matter/general/-/general-0.13.0.tgz",
- "integrity": "sha512-PZ+FVJotKWgtoBvorqN+PLCuTBBbTCJTCss2P5C6n9r/ZAIcCgW7LDTFmRXNNNMJEri8JUVR0REvHaa92zVj2Q==",
+ "version": "0.16.10",
+ "resolved": "https://registry.npmjs.org/@matter/general/-/general-0.16.10.tgz",
+ "integrity": "sha512-/qytvaxvDDhEdHLaEoxlEFVBWg982jL+XXvOmAFgIv92yGDQvN4U+VcNW7S5dueJuv/L+gi0zDqhl8LUzHHAlg==",
"dev": true,
"requires": {
- "@noble/curves": "^1.8.2"
+ "@noble/curves": "^2.0.1"
}
},
"@matter/main": {
- "version": "0.13.0",
- "resolved": "https://registry.npmjs.org/@matter/main/-/main-0.13.0.tgz",
- "integrity": "sha512-Qu60G05f821bEtp2yU+rJ7Xpe66GHDn9NdSPGrAn1EJH/iWplmVeLS1nSXzyGE28iPVPYNLcMX0edY/FejAhmQ==",
+ "version": "0.16.10",
+ "resolved": "https://registry.npmjs.org/@matter/main/-/main-0.16.10.tgz",
+ "integrity": "sha512-QKoQrmMnt6cB893+Oezk3DdIVgQJj5spt/ikEszF8pjyTuvB69zlzq1wnrn52N3mi57R6UWwk6+BPEbQE95FSw==",
"dev": true,
"requires": {
- "@matter/general": "0.13.0",
- "@matter/model": "0.13.0",
- "@matter/node": "0.13.0",
- "@matter/nodejs": "0.13.0",
- "@matter/protocol": "0.13.0",
- "@matter/types": "0.13.0"
+ "@matter/general": "0.16.10",
+ "@matter/model": "0.16.10",
+ "@matter/node": "0.16.10",
+ "@matter/nodejs": "0.16.10",
+ "@matter/protocol": "0.16.10",
+ "@matter/types": "0.16.10"
}
},
"@matter/model": {
- "version": "0.13.0",
- "resolved": "https://registry.npmjs.org/@matter/model/-/model-0.13.0.tgz",
- "integrity": "sha512-rcXu7OdMctlOGVOkClH6/+11ct6FMDSK2/Yu05+J7BJfohJY5mQbo0jnz8l0FPbwRrk5ADbqfAJ5jh/1OKHR2Q==",
+ "version": "0.16.10",
+ "resolved": "https://registry.npmjs.org/@matter/model/-/model-0.16.10.tgz",
+ "integrity": "sha512-6Ei8gETAkcKGEMRW+z8Mak55Y1Jl1TKGQIboC/4vvsrqcvB8zhIvGBS3GaAllxzvF0qjE7ihCPpgXXr6HuTLyg==",
"dev": true,
"requires": {
- "@matter/general": "0.13.0"
+ "@matter/general": "0.16.10"
}
},
"@matter/node": {
- "version": "0.13.0",
- "resolved": "https://registry.npmjs.org/@matter/node/-/node-0.13.0.tgz",
- "integrity": "sha512-HQkzpRnhAUfj9u2ijkT4qgyFzEfaNqyAxh+dgMpLKnbbGQoHTskJ/wEgkRRI7B0Q57mr6VJ5KgXYdbXUYA7xFA==",
+ "version": "0.16.10",
+ "resolved": "https://registry.npmjs.org/@matter/node/-/node-0.16.10.tgz",
+ "integrity": "sha512-Hb2AxuEf0DlfN8yHxeahZGYurUUu/UDWJkmdvpDKuwSR0eIHhMweOG2RBO55/anyRFObANaUr1gr3DnyocB/0w==",
"dev": true,
"requires": {
- "@matter/general": "0.13.0",
- "@matter/model": "0.13.0",
- "@matter/protocol": "0.13.0",
- "@matter/types": "0.13.0"
+ "@matter/general": "0.16.10",
+ "@matter/model": "0.16.10",
+ "@matter/protocol": "0.16.10",
+ "@matter/types": "0.16.10"
}
},
"@matter/nodejs": {
- "version": "0.13.0",
- "resolved": "https://registry.npmjs.org/@matter/nodejs/-/nodejs-0.13.0.tgz",
- "integrity": "sha512-ThWrLZJo7UH4Ebanf3gxkhe2p8vq4X3PxyRG+ICDRGPfzSAJZ3znh2hD/zdvcdyzQlSoXeLpFbLpTkJu7aRMHg==",
+ "version": "0.16.10",
+ "resolved": "https://registry.npmjs.org/@matter/nodejs/-/nodejs-0.16.10.tgz",
+ "integrity": "sha512-o8e9tGZVsiqmEtD1osSL9+gRMIuNjtwXt29I3YDRzSqb3N5Dvd4Khj3HN68YhaFFeBlM4YEV2TS0/9VF3C06/w==",
"dev": true,
"optional": true,
"requires": {
- "@matter/general": "0.13.0",
- "@matter/node": "0.13.0",
- "@matter/protocol": "0.13.0",
- "@matter/types": "0.13.0"
+ "@matter/general": "0.16.10",
+ "@matter/node": "0.16.10",
+ "@matter/protocol": "0.16.10",
+ "@matter/types": "0.16.10"
}
},
"@matter/protocol": {
- "version": "0.13.0",
- "resolved": "https://registry.npmjs.org/@matter/protocol/-/protocol-0.13.0.tgz",
- "integrity": "sha512-wFxU6+LG5ygzruOV5JF30hmLkk88hz8PqAMkQ6ow81ZvoDFBevsW0OyqxXMCNwYd/zmGXmvr3mpC0mi9/troHg==",
+ "version": "0.16.10",
+ "resolved": "https://registry.npmjs.org/@matter/protocol/-/protocol-0.16.10.tgz",
+ "integrity": "sha512-vPQEMl8Wf4vc3tauwsGlLZRrDx+VrCPfccw3n50Lvyucws4UBt+SuBszSyIO2+QPnJcr4MB4L+EgCRI14U4zRA==",
"dev": true,
"requires": {
- "@matter/general": "0.13.0",
- "@matter/model": "0.13.0",
- "@matter/types": "0.13.0"
+ "@matter/general": "0.16.10",
+ "@matter/model": "0.16.10",
+ "@matter/types": "0.16.10"
}
},
"@matter/types": {
- "version": "0.13.0",
- "resolved": "https://registry.npmjs.org/@matter/types/-/types-0.13.0.tgz",
- "integrity": "sha512-8mH7hRC4MBSy4KUs8zb6uDTr0MfRYGtGBFq9t2uedlsiHA5lMUP3L1fitszoeCbpJh4EeqKHWSvF6RxWzKNueA==",
+ "version": "0.16.10",
+ "resolved": "https://registry.npmjs.org/@matter/types/-/types-0.16.10.tgz",
+ "integrity": "sha512-AW86tGgL3sN1Vb76+03VPdQMsW9vWsaVGHe9agcED1sjtWRJBV17tcLDymAQ8k7fEeVqiy3qf9CUwFK1bhfXKQ==",
"dev": true,
"requires": {
- "@matter/general": "0.13.0",
- "@matter/model": "0.13.0"
+ "@matter/general": "0.16.10",
+ "@matter/model": "0.16.10"
}
},
"@microsoft/recognizers-text": {
@@ -13824,18 +13824,18 @@
}
},
"@noble/curves": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.0.tgz",
- "integrity": "sha512-7YDlXiNMdO1YZeH6t/kvopHHbIZzlxrCV9WLqCY6QhcXOoXiNCMDqJIglZ9Yjx5+w7Dz30TITFrlTjnRg7sKEg==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-2.0.1.tgz",
+ "integrity": "sha512-vs1Az2OOTBiP4q0pwjW5aF0xp9n4MxVrmkFBxc6EKZc6ddYx5gaZiAsZoq0uRRXWbi3AT/sBqn05eRPtn1JCPw==",
"dev": true,
"requires": {
- "@noble/hashes": "1.8.0"
+ "@noble/hashes": "2.0.1"
}
},
"@noble/hashes": {
- "version": "1.8.0",
- "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
- "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.0.1.tgz",
+ "integrity": "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==",
"dev": true
},
"@nodelib/fs.scandir": {
diff --git a/server/package.json b/server/package.json
index 594741446b..b5ad5cc1e0 100644
--- a/server/package.json
+++ b/server/package.json
@@ -46,7 +46,7 @@
]
},
"devDependencies": {
- "@matter/main": "^0.13.0",
+ "@matter/main": "^0.16.10",
"apidoc": "^1.0.3",
"chai": "^4.3.7",
"chai-as-promised": "^7.1.1",
diff --git a/server/services/matter/lib/matter.getNodes.js b/server/services/matter/lib/matter.getNodes.js
index 5ec7a37a83..bdbe3c9591 100644
--- a/server/services/matter/lib/matter.getNodes.js
+++ b/server/services/matter/lib/matter.getNodes.js
@@ -5,7 +5,8 @@ const convertDevice = (device) => {
const clusterClients = [];
// Each cluster client is a feature of the device
- device.clusterClients.forEach((clusterClient, clusterIndex) => {
+ const allClusterClients = device.getAllClusterClients();
+ allClusterClients.forEach((clusterClient) => {
clusterClients.push({
id: clusterClient.id.toString(),
name: clusterClient.name,
@@ -16,7 +17,8 @@ const convertDevice = (device) => {
});
// Convert child endpoints (child devices)
- const childEndpoints = device.childEndpoints.map((childDeviceEndpoint) => {
+ const childEndpointsList = device.getChildEndpoints();
+ const childEndpoints = childEndpointsList.map((childDeviceEndpoint) => {
return convertDevice(childDeviceEndpoint);
});
@@ -37,8 +39,8 @@ const convertDevice = (device) => {
async function getNodes() {
const nodeDetails = this.commissioningController.getCommissionedNodesDetails();
const filteredNodeDetails = nodeDetails.filter((nodeDetail) => {
- if (!nodeDetail.deviceData) {
- logger.warn(`Matter: Node ${nodeDetail.nodeId} has no device data`);
+ if (!nodeDetail.deviceData || !nodeDetail.deviceData.basicInformation) {
+ logger.warn(`Matter: Node ${nodeDetail.nodeId} has no device data or basic information`);
return false;
}
return true;
diff --git a/server/services/matter/lib/matter.init.js b/server/services/matter/lib/matter.init.js
index 0b566e76a0..9e52e9d03f 100644
--- a/server/services/matter/lib/matter.init.js
+++ b/server/services/matter/lib/matter.init.js
@@ -45,9 +45,10 @@ async function init() {
environment,
id: 'matter-controller-data',
},
- autoConnect: true,
+ // Set autoConnect to undefined to fix matter-js bug (https://github.com/matter-js/matter.js/pull/3436)
+ // Once the fix is live in matter-js, we can switch back to true
+ autoConnect: undefined,
adminFabricLabel: 'Gladys Assistant',
- storage: storageService,
});
await this.commissioningController.start();
diff --git a/server/services/matter/lib/matter.setValue.js b/server/services/matter/lib/matter.setValue.js
index 7e74b8de79..87d84c3156 100644
--- a/server/services/matter/lib/matter.setValue.js
+++ b/server/services/matter/lib/matter.setValue.js
@@ -27,8 +27,9 @@ function findDeviceRecursively(parentDevice, path) {
const deviceNumber = Number(currentNumber);
// Look in child endpoints
- if (parentDevice.childEndpoints) {
- const childDevice = parentDevice.childEndpoints.find((child) => child.number === deviceNumber);
+ const childEndpoints = parentDevice.getChildEndpoints();
+ if (childEndpoints && childEndpoints.length > 0) {
+ const childDevice = childEndpoints.find((child) => child.number === deviceNumber);
if (childDevice) {
return findDeviceRecursively(childDevice, remainingPath);
}
@@ -85,7 +86,7 @@ async function setValue(gladysDevice, gladysFeature, value) {
// Handle binary device
if (gladysFeature.type === DEVICE_FEATURE_TYPES.SWITCH.BINARY) {
- const onOff = targetDevice.clusterClients.get(OnOff.Complete.id);
+ const onOff = targetDevice.getClusterClientById(OnOff.Complete.id);
if (!onOff) {
throw new Error('Device does not support OnOff cluster');
@@ -101,7 +102,7 @@ async function setValue(gladysDevice, gladysFeature, value) {
// Handle shutters
if (gladysFeature.category === DEVICE_FEATURE_CATEGORIES.SHUTTER) {
- const windowCovering = targetDevice.clusterClients.get(WindowCovering.Complete.id);
+ const windowCovering = targetDevice.getClusterClientById(WindowCovering.Complete.id);
// Handle device feature shutter position
if (gladysFeature.type === DEVICE_FEATURE_TYPES.SHUTTER.POSITION) {
await windowCovering.goToLiftPercentage({
@@ -125,8 +126,8 @@ async function setValue(gladysDevice, gladysFeature, value) {
gladysFeature.category === DEVICE_FEATURE_CATEGORIES.LIGHT &&
gladysFeature.type === DEVICE_FEATURE_TYPES.LIGHT.BRIGHTNESS
) {
- const levelControl = targetDevice.clusterClients.get(LevelControl.Complete.id);
- const onOff = targetDevice.clusterClients.get(OnOff.Complete.id);
+ const levelControl = targetDevice.getClusterClientById(LevelControl.Complete.id);
+ const onOff = targetDevice.getClusterClientById(OnOff.Complete.id);
await levelControl.moveToLevel({
level: value,
transitionTime: null,
@@ -147,8 +148,8 @@ async function setValue(gladysDevice, gladysFeature, value) {
gladysFeature.category === DEVICE_FEATURE_CATEGORIES.LIGHT &&
gladysFeature.type === DEVICE_FEATURE_TYPES.LIGHT.COLOR
) {
- const colorControl = targetDevice.clusterClients.get(ColorControl.Complete.id);
- const onOff = targetDevice.clusterClients.get(OnOff.Complete.id);
+ const colorControl = targetDevice.getClusterClientById(ColorControl.Complete.id);
+ const onOff = targetDevice.getClusterClientById(OnOff.Complete.id);
const [hue, saturation] = intToHsb(value);
// Convert from standard HSB ranges to Matter ranges
@@ -175,7 +176,7 @@ async function setValue(gladysDevice, gladysFeature, value) {
gladysFeature.category === DEVICE_FEATURE_CATEGORIES.THERMOSTAT &&
gladysFeature.type === DEVICE_FEATURE_TYPES.THERMOSTAT.TARGET_TEMPERATURE
) {
- const thermostat = targetDevice.clusterClients.get(Thermostat.Complete.id);
+ const thermostat = targetDevice.getClusterClientById(Thermostat.Complete.id);
await thermostat.setOccupiedHeatingSetpointAttribute(value * 100);
}
@@ -184,7 +185,7 @@ async function setValue(gladysDevice, gladysFeature, value) {
gladysFeature.category === DEVICE_FEATURE_CATEGORIES.AIR_CONDITIONING &&
gladysFeature.type === DEVICE_FEATURE_TYPES.AIR_CONDITIONING.TARGET_TEMPERATURE
) {
- const thermostat = targetDevice.clusterClients.get(Thermostat.Complete.id);
+ const thermostat = targetDevice.getClusterClientById(Thermostat.Complete.id);
await thermostat.setOccupiedCoolingSetpointAttribute(value * 100);
}
}
diff --git a/server/services/matter/package-lock.json b/server/services/matter/package-lock.json
index 328c3bd4e0..210445bb14 100644
--- a/server/services/matter/package-lock.json
+++ b/server/services/matter/package-lock.json
@@ -16,133 +16,133 @@
"win32"
],
"dependencies": {
- "@matter/main": "^0.13.0",
- "@project-chip/matter.js": "^0.13.0",
+ "@matter/main": "^0.16.10",
+ "@project-chip/matter.js": "^0.16.10",
"bluebird": "^3.7.2",
"fs-extra": "^11.3.0"
}
},
"node_modules/@matter/general": {
- "version": "0.13.0",
- "resolved": "https://registry.npmjs.org/@matter/general/-/general-0.13.0.tgz",
- "integrity": "sha512-PZ+FVJotKWgtoBvorqN+PLCuTBBbTCJTCss2P5C6n9r/ZAIcCgW7LDTFmRXNNNMJEri8JUVR0REvHaa92zVj2Q==",
+ "version": "0.16.10",
+ "resolved": "https://registry.npmjs.org/@matter/general/-/general-0.16.10.tgz",
+ "integrity": "sha512-/qytvaxvDDhEdHLaEoxlEFVBWg982jL+XXvOmAFgIv92yGDQvN4U+VcNW7S5dueJuv/L+gi0zDqhl8LUzHHAlg==",
"license": "Apache-2.0",
"dependencies": {
- "@noble/curves": "^1.8.2"
+ "@noble/curves": "^2.0.1"
}
},
"node_modules/@matter/main": {
- "version": "0.13.0",
- "resolved": "https://registry.npmjs.org/@matter/main/-/main-0.13.0.tgz",
- "integrity": "sha512-Qu60G05f821bEtp2yU+rJ7Xpe66GHDn9NdSPGrAn1EJH/iWplmVeLS1nSXzyGE28iPVPYNLcMX0edY/FejAhmQ==",
+ "version": "0.16.10",
+ "resolved": "https://registry.npmjs.org/@matter/main/-/main-0.16.10.tgz",
+ "integrity": "sha512-QKoQrmMnt6cB893+Oezk3DdIVgQJj5spt/ikEszF8pjyTuvB69zlzq1wnrn52N3mi57R6UWwk6+BPEbQE95FSw==",
"license": "Apache-2.0",
"dependencies": {
- "@matter/general": "0.13.0",
- "@matter/model": "0.13.0",
- "@matter/node": "0.13.0",
- "@matter/protocol": "0.13.0",
- "@matter/types": "0.13.0"
+ "@matter/general": "0.16.10",
+ "@matter/model": "0.16.10",
+ "@matter/node": "0.16.10",
+ "@matter/protocol": "0.16.10",
+ "@matter/types": "0.16.10"
},
"optionalDependencies": {
- "@matter/nodejs": "0.13.0"
+ "@matter/nodejs": "0.16.10"
}
},
"node_modules/@matter/model": {
- "version": "0.13.0",
- "resolved": "https://registry.npmjs.org/@matter/model/-/model-0.13.0.tgz",
- "integrity": "sha512-rcXu7OdMctlOGVOkClH6/+11ct6FMDSK2/Yu05+J7BJfohJY5mQbo0jnz8l0FPbwRrk5ADbqfAJ5jh/1OKHR2Q==",
+ "version": "0.16.10",
+ "resolved": "https://registry.npmjs.org/@matter/model/-/model-0.16.10.tgz",
+ "integrity": "sha512-6Ei8gETAkcKGEMRW+z8Mak55Y1Jl1TKGQIboC/4vvsrqcvB8zhIvGBS3GaAllxzvF0qjE7ihCPpgXXr6HuTLyg==",
"license": "Apache-2.0",
"dependencies": {
- "@matter/general": "0.13.0"
+ "@matter/general": "0.16.10"
}
},
"node_modules/@matter/node": {
- "version": "0.13.0",
- "resolved": "https://registry.npmjs.org/@matter/node/-/node-0.13.0.tgz",
- "integrity": "sha512-HQkzpRnhAUfj9u2ijkT4qgyFzEfaNqyAxh+dgMpLKnbbGQoHTskJ/wEgkRRI7B0Q57mr6VJ5KgXYdbXUYA7xFA==",
+ "version": "0.16.10",
+ "resolved": "https://registry.npmjs.org/@matter/node/-/node-0.16.10.tgz",
+ "integrity": "sha512-Hb2AxuEf0DlfN8yHxeahZGYurUUu/UDWJkmdvpDKuwSR0eIHhMweOG2RBO55/anyRFObANaUr1gr3DnyocB/0w==",
"license": "Apache-2.0",
"dependencies": {
- "@matter/general": "0.13.0",
- "@matter/model": "0.13.0",
- "@matter/protocol": "0.13.0",
- "@matter/types": "0.13.0"
+ "@matter/general": "0.16.10",
+ "@matter/model": "0.16.10",
+ "@matter/protocol": "0.16.10",
+ "@matter/types": "0.16.10"
}
},
"node_modules/@matter/nodejs": {
- "version": "0.13.0",
- "resolved": "https://registry.npmjs.org/@matter/nodejs/-/nodejs-0.13.0.tgz",
- "integrity": "sha512-ThWrLZJo7UH4Ebanf3gxkhe2p8vq4X3PxyRG+ICDRGPfzSAJZ3znh2hD/zdvcdyzQlSoXeLpFbLpTkJu7aRMHg==",
+ "version": "0.16.10",
+ "resolved": "https://registry.npmjs.org/@matter/nodejs/-/nodejs-0.16.10.tgz",
+ "integrity": "sha512-o8e9tGZVsiqmEtD1osSL9+gRMIuNjtwXt29I3YDRzSqb3N5Dvd4Khj3HN68YhaFFeBlM4YEV2TS0/9VF3C06/w==",
"license": "Apache-2.0",
"optional": true,
"dependencies": {
- "@matter/general": "0.13.0",
- "@matter/node": "0.13.0",
- "@matter/protocol": "0.13.0",
- "@matter/types": "0.13.0"
+ "@matter/general": "0.16.10",
+ "@matter/node": "0.16.10",
+ "@matter/protocol": "0.16.10",
+ "@matter/types": "0.16.10"
},
"engines": {
- "node": ">=18.0.0"
+ "node": ">=20.19.0 <22.0.0 || >=22.13.0"
}
},
"node_modules/@matter/protocol": {
- "version": "0.13.0",
- "resolved": "https://registry.npmjs.org/@matter/protocol/-/protocol-0.13.0.tgz",
- "integrity": "sha512-wFxU6+LG5ygzruOV5JF30hmLkk88hz8PqAMkQ6ow81ZvoDFBevsW0OyqxXMCNwYd/zmGXmvr3mpC0mi9/troHg==",
+ "version": "0.16.10",
+ "resolved": "https://registry.npmjs.org/@matter/protocol/-/protocol-0.16.10.tgz",
+ "integrity": "sha512-vPQEMl8Wf4vc3tauwsGlLZRrDx+VrCPfccw3n50Lvyucws4UBt+SuBszSyIO2+QPnJcr4MB4L+EgCRI14U4zRA==",
"license": "Apache-2.0",
"dependencies": {
- "@matter/general": "0.13.0",
- "@matter/model": "0.13.0",
- "@matter/types": "0.13.0"
+ "@matter/general": "0.16.10",
+ "@matter/model": "0.16.10",
+ "@matter/types": "0.16.10"
}
},
"node_modules/@matter/types": {
- "version": "0.13.0",
- "resolved": "https://registry.npmjs.org/@matter/types/-/types-0.13.0.tgz",
- "integrity": "sha512-8mH7hRC4MBSy4KUs8zb6uDTr0MfRYGtGBFq9t2uedlsiHA5lMUP3L1fitszoeCbpJh4EeqKHWSvF6RxWzKNueA==",
+ "version": "0.16.10",
+ "resolved": "https://registry.npmjs.org/@matter/types/-/types-0.16.10.tgz",
+ "integrity": "sha512-AW86tGgL3sN1Vb76+03VPdQMsW9vWsaVGHe9agcED1sjtWRJBV17tcLDymAQ8k7fEeVqiy3qf9CUwFK1bhfXKQ==",
"license": "Apache-2.0",
"dependencies": {
- "@matter/general": "0.13.0",
- "@matter/model": "0.13.0"
+ "@matter/general": "0.16.10",
+ "@matter/model": "0.16.10"
}
},
"node_modules/@noble/curves": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.0.tgz",
- "integrity": "sha512-7YDlXiNMdO1YZeH6t/kvopHHbIZzlxrCV9WLqCY6QhcXOoXiNCMDqJIglZ9Yjx5+w7Dz30TITFrlTjnRg7sKEg==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-2.0.1.tgz",
+ "integrity": "sha512-vs1Az2OOTBiP4q0pwjW5aF0xp9n4MxVrmkFBxc6EKZc6ddYx5gaZiAsZoq0uRRXWbi3AT/sBqn05eRPtn1JCPw==",
"license": "MIT",
"dependencies": {
- "@noble/hashes": "1.8.0"
+ "@noble/hashes": "2.0.1"
},
"engines": {
- "node": "^14.21.3 || >=16"
+ "node": ">= 20.19.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@noble/hashes": {
- "version": "1.8.0",
- "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
- "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.0.1.tgz",
+ "integrity": "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==",
"license": "MIT",
"engines": {
- "node": "^14.21.3 || >=16"
+ "node": ">= 20.19.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@project-chip/matter.js": {
- "version": "0.13.0",
- "resolved": "https://registry.npmjs.org/@project-chip/matter.js/-/matter.js-0.13.0.tgz",
- "integrity": "sha512-QWmfuDorGBW8dpgYk+3L9V4SdW80PQ4pW90s+ORxtWnpBcJoiP6a5skS7NJuW3kNRSMLtXQmpG+yI8oDXcULSg==",
+ "version": "0.16.10",
+ "resolved": "https://registry.npmjs.org/@project-chip/matter.js/-/matter.js-0.16.10.tgz",
+ "integrity": "sha512-5SpMsaNftqrqHSppP8J1RTdWdtJgehs3k9CVf0cM0IrZLQMK67W2cWVlTbsJElV7zOfKatjU56FdRA2UgkbvMQ==",
"license": "Apache-2.0",
"dependencies": {
- "@matter/general": "0.13.0",
- "@matter/model": "0.13.0",
- "@matter/node": "0.13.0",
- "@matter/protocol": "0.13.0",
- "@matter/types": "0.13.0"
+ "@matter/general": "0.16.10",
+ "@matter/model": "0.16.10",
+ "@matter/node": "0.16.10",
+ "@matter/protocol": "0.16.10",
+ "@matter/types": "0.16.10"
}
},
"node_modules/bluebird": {
diff --git a/server/services/matter/package.json b/server/services/matter/package.json
index c4965473c9..b696541e9d 100644
--- a/server/services/matter/package.json
+++ b/server/services/matter/package.json
@@ -12,8 +12,8 @@
"arm64"
],
"dependencies": {
- "@matter/main": "^0.13.0",
- "@project-chip/matter.js": "^0.13.0",
+ "@matter/main": "^0.16.10",
+ "@project-chip/matter.js": "^0.16.10",
"bluebird": "^3.7.2",
"fs-extra": "^11.3.0"
}
diff --git a/server/services/matter/utils/convertToGladysDevice.js b/server/services/matter/utils/convertToGladysDevice.js
index 7975f66333..2059e1c813 100644
--- a/server/services/matter/utils/convertToGladysDevice.js
+++ b/server/services/matter/utils/convertToGladysDevice.js
@@ -101,8 +101,10 @@ async function convertToGladysDevice(serviceId, nodeId, device, nodeDetailDevice
// Add endpoint number to the name so the user can identify the device
gladysDevice.name += ` ${device.number}`;
- if (device.clusterClients) {
- await Promise.each(Array.from(device.clusterClients.entries()), async ([clusterIndex, clusterClient]) => {
+ const allClusterClients = device.getAllClusterClients();
+ if (allClusterClients && allClusterClients.length > 0) {
+ await Promise.each(allClusterClients, async (clusterClient) => {
+ const clusterIndex = clusterClient.id;
const commonNewFeature = {
name: `${clusterClient.name} - ${clusterClient.endpointId}`,
selector: slugify(`matter-${device.name}-${clusterClient.name}`, true),
From 77373e25588cb240ac96b1b28fa4a34a297bb958 Mon Sep 17 00:00:00 2001
From: Pierre-Gilles Leymarie <7365207+Pierre-Gilles@users.noreply.github.com>
Date: Mon, 23 Mar 2026 09:19:29 +0100
Subject: [PATCH 02/16] adapt tests and listenToStateChange
---
.../services/matter/lib/matter.handleNode.js | 7 +-
.../matter/lib/matter.listenToStateChange.js | 38 ++--
.../matter/lib/convertToGladysDevice.test.js | 16 +-
.../matter/lib/listenToStateChange.test.js | 193 +++++++++---------
.../matter/lib/matter.getNodes.test.js | 13 +-
.../services/matter/lib/matter.init.test.js | 9 +-
.../matter/lib/matter.pairDevice.test.js | 45 ++--
.../matter/lib/matter.refreshDevices.test.js | 9 +-
.../matter/lib/matter.setValue.test.js | 45 ++--
9 files changed, 203 insertions(+), 172 deletions(-)
diff --git a/server/services/matter/lib/matter.handleNode.js b/server/services/matter/lib/matter.handleNode.js
index 85cc866658..806fc3834d 100644
--- a/server/services/matter/lib/matter.handleNode.js
+++ b/server/services/matter/lib/matter.handleNode.js
@@ -26,7 +26,7 @@ const handleDevice = async (
};
// If we have this cluster, it means we are in a bridge device
- const bridgedDeviceBasicInformationClusterClient = device.clusterClients.get(
+ const bridgedDeviceBasicInformationClusterClient = device.getClusterClientById(
BridgedDeviceBasicInformation.Complete.id,
);
@@ -82,8 +82,9 @@ const handleDevice = async (
devices.push(gladysDevice);
}
- if (device.childEndpoints) {
- await Promise.each(device.childEndpoints, async (childDevice, index) => {
+ const childEndpoints = device.getChildEndpoints();
+ if (childEndpoints && childEndpoints.length > 0) {
+ await Promise.each(childEndpoints, async (childDevice, index) => {
await handleDevice(
nodeId,
childInformations,
diff --git a/server/services/matter/lib/matter.listenToStateChange.js b/server/services/matter/lib/matter.listenToStateChange.js
index 99b34f395c..3681c2e4cf 100644
--- a/server/services/matter/lib/matter.listenToStateChange.js
+++ b/server/services/matter/lib/matter.listenToStateChange.js
@@ -32,8 +32,8 @@ const { EVENTS, STATE, BUTTON_STATUS } = require('../../../utils/constants');
* @example matter.listenToStateChange(nodeId, device);
*/
async function listenToStateChange(nodeId, devicePath, device) {
- // Get the OnOff cluster from clusterClients map
- const onOff = device.clusterClients.get(OnOff.Complete.id);
+ // Get the OnOff cluster
+ const onOff = device.getClusterClientById(OnOff.Complete.id);
// We only add the listener if it's not already added
if (onOff && !this.stateChangeListeners.has(onOff)) {
@@ -49,7 +49,7 @@ async function listenToStateChange(nodeId, devicePath, device) {
});
}
- const booleanState = device.clusterClients.get(BooleanState.Complete.id);
+ const booleanState = device.getClusterClientById(BooleanState.Complete.id);
if (booleanState && !this.stateChangeListeners.has(booleanState)) {
logger.debug(`Matter: Adding state change listener for BooleanState cluster ${booleanState.name}`);
this.stateChangeListeners.add(booleanState);
@@ -62,7 +62,7 @@ async function listenToStateChange(nodeId, devicePath, device) {
});
}
- const switchCluster = device.clusterClients.get(Switch.Complete.id);
+ const switchCluster = device.getClusterClientById(Switch.Complete.id);
if (switchCluster && !this.stateChangeListeners.has(switchCluster)) {
logger.debug(`Matter: Adding state change listener for Switch cluster ${switchCluster.name}`);
this.stateChangeListeners.add(switchCluster);
@@ -104,7 +104,7 @@ async function listenToStateChange(nodeId, devicePath, device) {
}
}
- const occupancy = device.clusterClients.get(OccupancySensing.Complete.id);
+ const occupancy = device.getClusterClientById(OccupancySensing.Complete.id);
if (occupancy && !this.stateChangeListeners.has(occupancy)) {
logger.debug(`Matter: Adding state change listener for OccupancySensing cluster ${occupancy.name}`);
this.stateChangeListeners.add(occupancy);
@@ -118,7 +118,7 @@ async function listenToStateChange(nodeId, devicePath, device) {
});
}
- const illuminance = device.clusterClients.get(IlluminanceMeasurement.Complete.id);
+ const illuminance = device.getClusterClientById(IlluminanceMeasurement.Complete.id);
if (illuminance && !this.stateChangeListeners.has(illuminance)) {
logger.debug(`Matter: Adding state change listener for IlluminanceMeasurement cluster ${illuminance.name}`);
this.stateChangeListeners.add(illuminance);
@@ -133,7 +133,7 @@ async function listenToStateChange(nodeId, devicePath, device) {
});
}
- const temperatureSensor = device.clusterClients.get(TemperatureMeasurement.Complete.id);
+ const temperatureSensor = device.getClusterClientById(TemperatureMeasurement.Complete.id);
if (temperatureSensor && !this.stateChangeListeners.has(temperatureSensor)) {
logger.debug(`Matter: Adding state change listener for TemperatureMeasurement cluster ${temperatureSensor.name}`);
this.stateChangeListeners.add(temperatureSensor);
@@ -147,7 +147,7 @@ async function listenToStateChange(nodeId, devicePath, device) {
});
}
- const windowCover = device.clusterClients.get(WindowCovering.Complete.id);
+ const windowCover = device.getClusterClientById(WindowCovering.Complete.id);
if (windowCover && !this.stateChangeListeners.has(windowCover)) {
logger.debug(`Matter: Adding state change listener for WindowCovering cluster ${windowCover.name}`);
@@ -162,7 +162,7 @@ async function listenToStateChange(nodeId, devicePath, device) {
});
}
- const levelControl = device.clusterClients.get(LevelControl.Complete.id);
+ const levelControl = device.getClusterClientById(LevelControl.Complete.id);
if (levelControl && !this.stateChangeListeners.has(levelControl)) {
logger.debug(`Matter: Adding state change listener for LevelControl cluster ${levelControl.name}`);
this.stateChangeListeners.add(levelControl);
@@ -176,7 +176,7 @@ async function listenToStateChange(nodeId, devicePath, device) {
});
}
- const colorControl = device.clusterClients.get(ColorControl.Complete.id);
+ const colorControl = device.getClusterClientById(ColorControl.Complete.id);
if (colorControl && !this.stateChangeListeners.has(colorControl)) {
logger.debug(`Matter: Adding state change listener for ColorControl cluster ${colorControl.name}`);
this.stateChangeListeners.add(colorControl);
@@ -220,7 +220,7 @@ async function listenToStateChange(nodeId, devicePath, device) {
}
}
- const relativeHumidityMeasurement = device.clusterClients.get(RelativeHumidityMeasurement.Complete.id);
+ const relativeHumidityMeasurement = device.getClusterClientById(RelativeHumidityMeasurement.Complete.id);
if (relativeHumidityMeasurement && !this.stateChangeListeners.has(relativeHumidityMeasurement)) {
logger.debug(
`Matter: Adding state change listener for RelativeHumidityMeasurement cluster ${relativeHumidityMeasurement.name}`,
@@ -236,7 +236,7 @@ async function listenToStateChange(nodeId, devicePath, device) {
});
}
- const pm25ConcentrationMeasurement = device.clusterClients.get(Pm25ConcentrationMeasurement.Complete.id);
+ const pm25ConcentrationMeasurement = device.getClusterClientById(Pm25ConcentrationMeasurement.Complete.id);
if (pm25ConcentrationMeasurement && !this.stateChangeListeners.has(pm25ConcentrationMeasurement)) {
logger.debug(
`Matter: Adding state change listener for Pm25ConcentrationMeasurement cluster ${pm25ConcentrationMeasurement.name}`,
@@ -252,7 +252,7 @@ async function listenToStateChange(nodeId, devicePath, device) {
});
}
- const pm10ConcentrationMeasurement = device.clusterClients.get(Pm10ConcentrationMeasurement.Complete.id);
+ const pm10ConcentrationMeasurement = device.getClusterClientById(Pm10ConcentrationMeasurement.Complete.id);
if (pm10ConcentrationMeasurement && !this.stateChangeListeners.has(pm10ConcentrationMeasurement)) {
logger.debug(
`Matter: Adding state change listener for Pm10ConcentrationMeasurement cluster ${pm10ConcentrationMeasurement.name}`,
@@ -268,7 +268,7 @@ async function listenToStateChange(nodeId, devicePath, device) {
});
}
- const totalVolatileOrganicCompoundsConcentrationMeasurement = device.clusterClients.get(
+ const totalVolatileOrganicCompoundsConcentrationMeasurement = device.getClusterClientById(
TotalVolatileOrganicCompoundsConcentrationMeasurement.Complete.id,
);
if (
@@ -289,7 +289,7 @@ async function listenToStateChange(nodeId, devicePath, device) {
});
}
- const formaldehydeConcentrationMeasurement = device.clusterClients.get(
+ const formaldehydeConcentrationMeasurement = device.getClusterClientById(
FormaldehydeConcentrationMeasurement.Complete.id,
);
if (formaldehydeConcentrationMeasurement && !this.stateChangeListeners.has(formaldehydeConcentrationMeasurement)) {
@@ -307,7 +307,7 @@ async function listenToStateChange(nodeId, devicePath, device) {
});
}
- const thermostat = device.clusterClients.get(Thermostat.Complete.id);
+ const thermostat = device.getClusterClientById(Thermostat.Complete.id);
if (thermostat && !this.stateChangeListeners.has(thermostat)) {
logger.debug(`Matter: Adding state change listener for Thermostat cluster ${thermostat.name}`);
this.stateChangeListeners.add(thermostat);
@@ -332,7 +332,7 @@ async function listenToStateChange(nodeId, devicePath, device) {
}
}
- const electricalPowerMeasurement = device.clusterClients.get(ElectricalPowerMeasurement.Complete.id);
+ const electricalPowerMeasurement = device.getClusterClientById(ElectricalPowerMeasurement.Complete.id);
if (electricalPowerMeasurement && !this.stateChangeListeners.has(electricalPowerMeasurement)) {
logger.debug(
`Matter: Adding state change listener for ElectricalPowerMeasurement cluster ${electricalPowerMeasurement.name}`,
@@ -374,7 +374,7 @@ async function listenToStateChange(nodeId, devicePath, device) {
}
}
- const electricalEnergyMeasurement = device.clusterClients.get(ElectricalEnergyMeasurement.Complete.id);
+ const electricalEnergyMeasurement = device.getClusterClientById(ElectricalEnergyMeasurement.Complete.id);
if (electricalEnergyMeasurement && !this.stateChangeListeners.has(electricalEnergyMeasurement)) {
logger.debug(
`Matter: Adding state change listener for ElectricalEnergyMeasurement cluster ${electricalEnergyMeasurement.name}`,
@@ -395,7 +395,7 @@ async function listenToStateChange(nodeId, devicePath, device) {
}
}
- const hepaFilterMonitoring = device.clusterClients.get(HepaFilterMonitoring.Complete.id);
+ const hepaFilterMonitoring = device.getClusterClientById(HepaFilterMonitoring.Complete.id);
if (hepaFilterMonitoring && !this.stateChangeListeners.has(hepaFilterMonitoring)) {
logger.debug(`Matter: Adding state change listener for HepaFilterMonitoring cluster ${hepaFilterMonitoring.name}`);
this.stateChangeListeners.add(hepaFilterMonitoring);
diff --git a/server/test/services/matter/lib/convertToGladysDevice.test.js b/server/test/services/matter/lib/convertToGladysDevice.test.js
index a241489ecf..d7983fdb62 100644
--- a/server/test/services/matter/lib/convertToGladysDevice.test.js
+++ b/server/test/services/matter/lib/convertToGladysDevice.test.js
@@ -13,17 +13,17 @@ describe('Matter.convertToGladysDevice', () => {
};
it('should create a read-only binary feature for BooleanState cluster', async () => {
- const clusterClients = new Map();
- clusterClients.set(BooleanState.Complete.id, {
+ const clusterClient = {
id: BooleanState.Complete.id,
name: 'BooleanState',
endpointId: 1,
- });
+ };
const device = {
name: 'Test Device',
number: 1,
- clusterClients,
+ getAllClusterClients: () => [clusterClient],
+ getChildEndpoints: () => [],
};
const gladysDevice = await convertToGladysDevice(serviceId, nodeId, device, basicInformation, '1');
@@ -43,17 +43,17 @@ describe('Matter.convertToGladysDevice', () => {
});
it('should create a button click feature for Switch cluster', async () => {
- const clusterClients = new Map();
- clusterClients.set(Switch.Complete.id, {
+ const clusterClient = {
id: Switch.Complete.id,
name: 'Switch',
endpointId: 2,
- });
+ };
const device = {
name: 'Test Device',
number: 2,
- clusterClients,
+ getAllClusterClients: () => [clusterClient],
+ getChildEndpoints: () => [],
};
const gladysDevice = await convertToGladysDevice(serviceId, nodeId, device, basicInformation, '1:child_endpoint:2');
diff --git a/server/test/services/matter/lib/listenToStateChange.test.js b/server/test/services/matter/lib/listenToStateChange.test.js
index 2e95802e47..f7c093d5f3 100644
--- a/server/test/services/matter/lib/listenToStateChange.test.js
+++ b/server/test/services/matter/lib/listenToStateChange.test.js
@@ -48,15 +48,15 @@ describe('Matter.listenToStateChange', () => {
});
it('should listen to state change (ON)', async () => {
- const clusterClients = new Map();
- clusterClients.set(OnOff.Complete.id, {
+ const clusterClient = {
+ id: OnOff.Complete.id,
addOnOffAttributeListener: (callback) => {
callback(true);
},
- });
+ };
const device = {
number: 1,
- clusterClients,
+ getClusterClientById: (id) => (id === clusterClient.id ? clusterClient : null),
};
await matterHandler.listenToStateChange(1234n, '1', device);
assert.calledWith(gladys.event.emit, EVENTS.DEVICE.NEW_STATE, {
@@ -65,15 +65,15 @@ describe('Matter.listenToStateChange', () => {
});
});
it('should listen to state change (OFF)', async () => {
- const clusterClients = new Map();
- clusterClients.set(OnOff.Complete.id, {
+ const clusterClient = {
+ id: OnOff.Complete.id,
addOnOffAttributeListener: (callback) => {
callback(false);
},
- });
+ };
const device = {
number: 1,
- clusterClients,
+ getClusterClientById: (id) => (id === clusterClient.id ? clusterClient : null),
};
await matterHandler.listenToStateChange(1234n, '1', device);
assert.calledWith(gladys.event.emit, EVENTS.DEVICE.NEW_STATE, {
@@ -82,15 +82,15 @@ describe('Matter.listenToStateChange', () => {
});
});
it('should listen to state change in nested child endpoint (OFF)', async () => {
- const clusterClients = new Map();
- clusterClients.set(OnOff.Complete.id, {
+ const clusterClient = {
+ id: OnOff.Complete.id,
addOnOffAttributeListener: (callback) => {
callback(false);
},
- });
+ };
const device = {
number: 1,
- clusterClients,
+ getClusterClientById: (id) => (id === clusterClient.id ? clusterClient : null),
};
await matterHandler.listenToStateChange(1234n, '1:child_endpoint:2', device);
assert.calledWith(gladys.event.emit, EVENTS.DEVICE.NEW_STATE, {
@@ -99,15 +99,15 @@ describe('Matter.listenToStateChange', () => {
});
});
it('should listen to state change (BooleanState = true)', async () => {
- const clusterClients = new Map();
- clusterClients.set(BooleanState.Complete.id, {
+ const clusterClient = {
+ id: BooleanState.Complete.id,
addStateValueAttributeListener: (callback) => {
callback(true);
},
- });
+ };
const device = {
number: 1,
- clusterClients,
+ getClusterClientById: (id) => (id === clusterClient.id ? clusterClient : null),
};
await matterHandler.listenToStateChange(1234n, '1', device);
assert.calledWith(gladys.event.emit, EVENTS.DEVICE.NEW_STATE, {
@@ -116,8 +116,8 @@ describe('Matter.listenToStateChange', () => {
});
});
it('should listen to switch events', async () => {
- const clusterClients = new Map();
- clusterClients.set(Switch.Complete.id, {
+ const clusterClient = {
+ id: Switch.Complete.id,
addInitialPressEventListener: (callback) => {
callback();
},
@@ -130,10 +130,10 @@ describe('Matter.listenToStateChange', () => {
addLongReleaseEventListener: (callback) => {
callback();
},
- });
+ };
const device = {
number: 1,
- clusterClients,
+ getClusterClientById: (id) => (id === clusterClient.id ? clusterClient : null),
};
await matterHandler.listenToStateChange(1234n, '1', device);
assert.calledWith(gladys.event.emit, EVENTS.DEVICE.NEW_STATE, {
@@ -154,15 +154,15 @@ describe('Matter.listenToStateChange', () => {
});
});
it('should listen to state change (Occupancy = true)', async () => {
- const clusterClients = new Map();
- clusterClients.set(OccupancySensing.Complete.id, {
+ const clusterClient = {
+ id: OccupancySensing.Complete.id,
addOccupancyAttributeListener: (callback) => {
callback({ occupied: true });
},
- });
+ };
const device = {
number: 1,
- clusterClients,
+ getClusterClientById: (id) => (id === clusterClient.id ? clusterClient : null),
};
await matterHandler.listenToStateChange(1234n, '1', device);
assert.calledWith(gladys.event.emit, EVENTS.DEVICE.NEW_STATE, {
@@ -171,15 +171,15 @@ describe('Matter.listenToStateChange', () => {
});
});
it('should listen to state change (Occupancy = false)', async () => {
- const clusterClients = new Map();
- clusterClients.set(OccupancySensing.Complete.id, {
+ const clusterClient = {
+ id: OccupancySensing.Complete.id,
addOccupancyAttributeListener: (callback) => {
callback({ occupied: false });
},
- });
+ };
const device = {
number: 1,
- clusterClients,
+ getClusterClientById: (id) => (id === clusterClient.id ? clusterClient : null),
};
await matterHandler.listenToStateChange(1234n, '1', device);
assert.calledWith(gladys.event.emit, EVENTS.DEVICE.NEW_STATE, {
@@ -188,16 +188,16 @@ describe('Matter.listenToStateChange', () => {
});
});
it('should listen to state change (IlluminanceMeasurement)', async () => {
- const clusterClients = new Map();
// Matter: Illuminance attribute changed to 21327 (Converted to 136 lux)
- clusterClients.set(IlluminanceMeasurement.Complete.id, {
+ const clusterClient = {
+ id: IlluminanceMeasurement.Complete.id,
addMeasuredValueAttributeListener: (callback) => {
callback(21327);
},
- });
+ };
const device = {
number: 1,
- clusterClients,
+ getClusterClientById: (id) => (id === clusterClient.id ? clusterClient : null),
};
await matterHandler.listenToStateChange(1234n, '1', device);
assert.calledWith(gladys.event.emit, EVENTS.DEVICE.NEW_STATE, {
@@ -206,15 +206,15 @@ describe('Matter.listenToStateChange', () => {
});
});
it('should listen to state change (TemperatureMeasurement)', async () => {
- const clusterClients = new Map();
- clusterClients.set(TemperatureMeasurement.Complete.id, {
+ const clusterClient = {
+ id: TemperatureMeasurement.Complete.id,
addMeasuredValueAttributeListener: (callback) => {
callback(2150);
},
- });
+ };
const device = {
number: 1,
- clusterClients,
+ getClusterClientById: (id) => (id === clusterClient.id ? clusterClient : null),
};
await matterHandler.listenToStateChange(1234n, '1', device);
assert.calledWith(gladys.event.emit, EVENTS.DEVICE.NEW_STATE, {
@@ -223,15 +223,15 @@ describe('Matter.listenToStateChange', () => {
});
});
it('should listen to state change (RelativeHumidityMeasurement)', async () => {
- const clusterClients = new Map();
- clusterClients.set(RelativeHumidityMeasurement.Complete.id, {
+ const clusterClient = {
+ id: RelativeHumidityMeasurement.Complete.id,
addMeasuredValueAttributeListener: (callback) => {
callback(5000);
},
- });
+ };
const device = {
number: 1,
- clusterClients,
+ getClusterClientById: (id) => (id === clusterClient.id ? clusterClient : null),
};
await matterHandler.listenToStateChange(1234n, '1', device);
assert.calledWith(gladys.event.emit, EVENTS.DEVICE.NEW_STATE, {
@@ -240,15 +240,15 @@ describe('Matter.listenToStateChange', () => {
});
});
it('should listen to state change (Pm25ConcentrationMeasurement)', async () => {
- const clusterClients = new Map();
- clusterClients.set(Pm25ConcentrationMeasurement.Complete.id, {
+ const clusterClient = {
+ id: Pm25ConcentrationMeasurement.Complete.id,
addMeasuredValueAttributeListener: (callback) => {
callback(100);
},
- });
+ };
const device = {
number: 1,
- clusterClients,
+ getClusterClientById: (id) => (id === clusterClient.id ? clusterClient : null),
};
await matterHandler.listenToStateChange(1234n, '1', device);
assert.calledWith(gladys.event.emit, EVENTS.DEVICE.NEW_STATE, {
@@ -257,15 +257,15 @@ describe('Matter.listenToStateChange', () => {
});
});
it('should listen to state change (Pm10ConcentrationMeasurement)', async () => {
- const clusterClients = new Map();
- clusterClients.set(Pm10ConcentrationMeasurement.Complete.id, {
+ const clusterClient = {
+ id: Pm10ConcentrationMeasurement.Complete.id,
addMeasuredValueAttributeListener: (callback) => {
callback(100);
},
- });
+ };
const device = {
number: 1,
- clusterClients,
+ getClusterClientById: (id) => (id === clusterClient.id ? clusterClient : null),
};
await matterHandler.listenToStateChange(1234n, '1', device);
assert.calledWith(gladys.event.emit, EVENTS.DEVICE.NEW_STATE, {
@@ -274,15 +274,15 @@ describe('Matter.listenToStateChange', () => {
});
});
it('should listen to state change (TotalVolatileOrganicCompoundsConcentrationMeasurement)', async () => {
- const clusterClients = new Map();
- clusterClients.set(TotalVolatileOrganicCompoundsConcentrationMeasurement.Complete.id, {
+ const clusterClient = {
+ id: TotalVolatileOrganicCompoundsConcentrationMeasurement.Complete.id,
addLevelValueAttributeListener: (callback) => {
callback(3);
},
- });
+ };
const device = {
number: 1,
- clusterClients,
+ getClusterClientById: (id) => (id === clusterClient.id ? clusterClient : null),
};
await matterHandler.listenToStateChange(1234n, '1', device);
assert.calledWith(gladys.event.emit, EVENTS.DEVICE.NEW_STATE, {
@@ -291,15 +291,15 @@ describe('Matter.listenToStateChange', () => {
});
});
it('should listen to state change (FormaldehydeConcentrationMeasurement)', async () => {
- const clusterClients = new Map();
- clusterClients.set(FormaldehydeConcentrationMeasurement.Complete.id, {
+ const clusterClient = {
+ id: FormaldehydeConcentrationMeasurement.Complete.id,
addMeasuredValueAttributeListener: (callback) => {
callback(100);
},
- });
+ };
const device = {
number: 1,
- clusterClients,
+ getClusterClientById: (id) => (id === clusterClient.id ? clusterClient : null),
};
await matterHandler.listenToStateChange(1234n, '1', device);
assert.calledWith(gladys.event.emit, EVENTS.DEVICE.NEW_STATE, {
@@ -308,18 +308,18 @@ describe('Matter.listenToStateChange', () => {
});
});
it('should listen to state change (Thermostat heating)', async () => {
- const clusterClients = new Map();
- clusterClients.set(Thermostat.Complete.id, {
+ const clusterClient = {
+ id: Thermostat.Complete.id,
supportedFeatures: {
heating: true,
},
addOccupiedHeatingSetpointAttributeListener: (callback) => {
callback(2000);
},
- });
+ };
const device = {
number: 1,
- clusterClients,
+ getClusterClientById: (id) => (id === clusterClient.id ? clusterClient : null),
};
await matterHandler.listenToStateChange(1234n, '1', device);
assert.calledWith(gladys.event.emit, EVENTS.DEVICE.NEW_STATE, {
@@ -328,18 +328,18 @@ describe('Matter.listenToStateChange', () => {
});
});
it('should listen to state change (Thermostat cooling)', async () => {
- const clusterClients = new Map();
- clusterClients.set(Thermostat.Complete.id, {
+ const clusterClient = {
+ id: Thermostat.Complete.id,
supportedFeatures: {
cooling: true,
},
addOccupiedCoolingSetpointAttributeListener: (callback) => {
callback(2000);
},
- });
+ };
const device = {
number: 1,
- clusterClients,
+ getClusterClientById: (id) => (id === clusterClient.id ? clusterClient : null),
};
await matterHandler.listenToStateChange(1234n, '1', device);
assert.calledWith(gladys.event.emit, EVENTS.DEVICE.NEW_STATE, {
@@ -348,15 +348,15 @@ describe('Matter.listenToStateChange', () => {
});
});
it('should listen to state change (WindowCovering)', async () => {
- const clusterClients = new Map();
- clusterClients.set(WindowCovering.Complete.id, {
+ const clusterClient = {
+ id: WindowCovering.Complete.id,
addCurrentPositionLiftPercent100thsAttributeListener: (callback) => {
callback(8400);
},
- });
+ };
const device = {
number: 1,
- clusterClients,
+ getClusterClientById: (id) => (id === clusterClient.id ? clusterClient : null),
};
await matterHandler.listenToStateChange(1234n, '1', device);
assert.calledWith(gladys.event.emit, EVENTS.DEVICE.NEW_STATE, {
@@ -365,15 +365,15 @@ describe('Matter.listenToStateChange', () => {
});
});
it('should listen to state change (LevelControl)', async () => {
- const clusterClients = new Map();
- clusterClients.set(LevelControl.Complete.id, {
+ const clusterClient = {
+ id: LevelControl.Complete.id,
addCurrentLevelAttributeListener: (callback) => {
callback(99);
},
- });
+ };
const device = {
number: 1,
- clusterClients,
+ getClusterClientById: (id) => (id === clusterClient.id ? clusterClient : null),
};
await matterHandler.listenToStateChange(1234n, '1', device);
assert.calledWith(gladys.event.emit, EVENTS.DEVICE.NEW_STATE, {
@@ -382,7 +382,7 @@ describe('Matter.listenToStateChange', () => {
});
});
it('should listen to state change (ColorControl)', async () => {
- const clusterClients = new Map();
+ let clusterClient;
const promise = new Promise((resolve) => {
let callCount = 0;
const checkThatEveryThingWasCalled = () => {
@@ -391,7 +391,8 @@ describe('Matter.listenToStateChange', () => {
resolve();
}
};
- clusterClients.set(ColorControl.Complete.id, {
+ clusterClient = {
+ id: ColorControl.Complete.id,
supportedFeatures: {
hueSaturation: true,
},
@@ -411,11 +412,11 @@ describe('Matter.listenToStateChange', () => {
checkThatEveryThingWasCalled();
return 40;
},
- });
+ };
});
const device = {
number: 1,
- clusterClients,
+ getClusterClientById: (id) => (id === clusterClient.id ? clusterClient : null),
};
await matterHandler.listenToStateChange(1234n, '1', device);
// We need to make sure that we called all 4 functions before checking the events
@@ -431,17 +432,17 @@ describe('Matter.listenToStateChange', () => {
});
});
it('should listen to state change (ElectricalPowerMeasurement - ActivePower)', async () => {
- const clusterClients = new Map();
- clusterClients.set(ElectricalPowerMeasurement.Complete.id, {
+ const clusterClient = {
+ id: ElectricalPowerMeasurement.Complete.id,
addActivePowerAttributeListener: (callback) => {
callback(1500000); // 1500000 mW = 1500 W
},
addVoltageAttributeListener: () => {},
addActiveCurrentAttributeListener: () => {},
- });
+ };
const device = {
number: 1,
- clusterClients,
+ getClusterClientById: (id) => (id === clusterClient.id ? clusterClient : null),
};
await matterHandler.listenToStateChange(1234n, '1', device);
assert.calledWith(gladys.event.emit, EVENTS.DEVICE.NEW_STATE, {
@@ -450,8 +451,8 @@ describe('Matter.listenToStateChange', () => {
});
});
it('should listen to state change (ElectricalPowerMeasurement - Voltage)', async () => {
- const clusterClients = new Map();
- clusterClients.set(ElectricalPowerMeasurement.Complete.id, {
+ const clusterClient = {
+ id: ElectricalPowerMeasurement.Complete.id,
supportedFeatures: {
voltage: true,
},
@@ -460,10 +461,10 @@ describe('Matter.listenToStateChange', () => {
callback(230000); // 230000 mV = 230 V
},
addActiveCurrentAttributeListener: () => {},
- });
+ };
const device = {
number: 1,
- clusterClients,
+ getClusterClientById: (id) => (id === clusterClient.id ? clusterClient : null),
};
await matterHandler.listenToStateChange(1234n, '1', device);
assert.calledWith(gladys.event.emit, EVENTS.DEVICE.NEW_STATE, {
@@ -472,8 +473,8 @@ describe('Matter.listenToStateChange', () => {
});
});
it('should listen to state change (ElectricalPowerMeasurement - ActiveCurrent)', async () => {
- const clusterClients = new Map();
- clusterClients.set(ElectricalPowerMeasurement.Complete.id, {
+ const clusterClient = {
+ id: ElectricalPowerMeasurement.Complete.id,
supportedFeatures: {
current: true,
},
@@ -482,10 +483,10 @@ describe('Matter.listenToStateChange', () => {
addActiveCurrentAttributeListener: (callback) => {
callback(6500); // 6500 mA = 6.5 A
},
- });
+ };
const device = {
number: 1,
- clusterClients,
+ getClusterClientById: (id) => (id === clusterClient.id ? clusterClient : null),
};
await matterHandler.listenToStateChange(1234n, '1', device);
assert.calledWith(gladys.event.emit, EVENTS.DEVICE.NEW_STATE, {
@@ -494,18 +495,18 @@ describe('Matter.listenToStateChange', () => {
});
});
it('should listen to state change (ElectricalEnergyMeasurement - CumulativeEnergy)', async () => {
- const clusterClients = new Map();
- clusterClients.set(ElectricalEnergyMeasurement.Complete.id, {
+ const clusterClient = {
+ id: ElectricalEnergyMeasurement.Complete.id,
supportedFeatures: {
cumulativeEnergy: true,
},
addCumulativeEnergyImportedAttributeListener: (callback) => {
callback({ energy: 1500000000 }); // 1500000000 mWh = 1500 kWh
},
- });
+ };
const device = {
number: 1,
- clusterClients,
+ getClusterClientById: (id) => (id === clusterClient.id ? clusterClient : null),
};
await matterHandler.listenToStateChange(1234n, '1', device);
assert.calledWith(gladys.event.emit, EVENTS.DEVICE.NEW_STATE, {
@@ -514,15 +515,15 @@ describe('Matter.listenToStateChange', () => {
});
});
it('should listen to state change (HepaFilterMonitoring)', async () => {
- const clusterClients = new Map();
- clusterClients.set(HepaFilterMonitoring.Complete.id, {
+ const clusterClient = {
+ id: HepaFilterMonitoring.Complete.id,
addConditionAttributeListener: (callback) => {
callback(75); // 75% filter life remaining
},
- });
+ };
const device = {
number: 1,
- clusterClients,
+ getClusterClientById: (id) => (id === clusterClient.id ? clusterClient : null),
};
await matterHandler.listenToStateChange(1234n, '1', device);
assert.calledWith(gladys.event.emit, EVENTS.DEVICE.NEW_STATE, {
diff --git a/server/test/services/matter/lib/matter.getNodes.test.js b/server/test/services/matter/lib/matter.getNodes.test.js
index 2515b02a2d..2c8f186fe8 100644
--- a/server/test/services/matter/lib/matter.getNodes.test.js
+++ b/server/test/services/matter/lib/matter.getNodes.test.js
@@ -21,15 +21,14 @@ describe('Matter.getNodes', () => {
});
it('should return all nodes', async () => {
- const clusterClients = new Map();
- clusterClients.set(6, {
+ const clusterClient = {
id: 2,
name: 'OnOff',
attributes: {
onOff: {},
},
commands: {},
- });
+ };
matterHandler.commissioningController = {
getNode: fake.returns({
isConnected: true,
@@ -37,13 +36,13 @@ describe('Matter.getNodes', () => {
{
number: 1,
name: 'Test Device',
- clusterClients: new Map(),
- childEndpoints: [
+ getAllClusterClients: () => [],
+ getChildEndpoints: () => [
{
name: 'Test Device child',
number: 2,
- clusterClients,
- childEndpoints: [],
+ getAllClusterClients: () => [clusterClient],
+ getChildEndpoints: () => [],
},
],
},
diff --git a/server/test/services/matter/lib/matter.init.test.js b/server/test/services/matter/lib/matter.init.test.js
index a9ae89572d..b1d3846b08 100644
--- a/server/test/services/matter/lib/matter.init.test.js
+++ b/server/test/services/matter/lib/matter.init.test.js
@@ -294,13 +294,16 @@ describe('Matter.init', () => {
id: 'device-1',
name: 'Test Device',
number: 1,
- clusterClients,
- childEndpoints: [
+ getAllClusterClients: () => Array.from(clusterClients.values()),
+ getClusterClientById: (id) => clusterClients.get(id),
+ getChildEndpoints: () => [
{
id: 'child-endpoint-1',
name: 'Child Endpoint',
number: 2,
- clusterClients,
+ getAllClusterClients: () => Array.from(clusterClients.values()),
+ getClusterClientById: (id) => clusterClients.get(id),
+ getChildEndpoints: () => [],
},
],
},
diff --git a/server/test/services/matter/lib/matter.pairDevice.test.js b/server/test/services/matter/lib/matter.pairDevice.test.js
index 82ef8a9ce4..ab63197d7b 100644
--- a/server/test/services/matter/lib/matter.pairDevice.test.js
+++ b/server/test/services/matter/lib/matter.pairDevice.test.js
@@ -24,10 +24,10 @@ describe('Matter.pairDevice', () => {
it('should pair a device', async () => {
const pairingCode = '1450-134-1614';
- const clusterClients = new Map();
- clusterClients.set(6, {
+ const clusterClient = {
+ id: 6,
addOnOffAttributeListener: fake.returns(null),
- });
+ };
matterHandler.commissioningController = {
commissionNode: fake.resolves(12345n),
getCommissionedNodesDetails: fake.returns([
@@ -47,13 +47,16 @@ describe('Matter.pairDevice', () => {
id: 'device-1',
name: 'Test Device',
number: 1,
- clusterClients: new Map(),
- childEndpoints: [
+ getAllClusterClients: () => [],
+ getClusterClientById: () => null,
+ getChildEndpoints: () => [
{
id: 'child-endpoint-1',
name: 'Child Endpoint',
number: 2,
- clusterClients,
+ getAllClusterClients: () => [clusterClient],
+ getClusterClientById: () => null,
+ getChildEndpoints: () => [],
},
],
},
@@ -66,12 +69,12 @@ describe('Matter.pairDevice', () => {
});
it('should pair a bridge device', async () => {
const pairingCode = '1450-134-1614';
- const clusterClients = new Map();
- clusterClients.set(6, {
+ const clusterClient = {
+ id: 6,
addOnOffAttributeListener: fake.returns(null),
- });
- const bridgeClusterClients = new Map();
- bridgeClusterClients.set(BridgedDeviceBasicInformation.Complete.id, {
+ };
+ const bridgeClusterClient = {
+ id: BridgedDeviceBasicInformation.Complete.id,
attributes: {
vendorName: {
get: fake.resolves('Test Vendor'),
@@ -92,7 +95,7 @@ describe('Matter.pairDevice', () => {
get: fake.resolves('serialNumber'),
},
},
- });
+ };
matterHandler.commissioningController = {
commissionNode: fake.resolves(12345n),
getCommissionedNodesDetails: fake.returns([
@@ -114,13 +117,16 @@ describe('Matter.pairDevice', () => {
id: 'device-1',
name: 'Test Device',
number: 1,
- clusterClients: bridgeClusterClients,
- childEndpoints: [
+ getAllClusterClients: () => [bridgeClusterClient],
+ getClusterClientById: (id) => (id === bridgeClusterClient.id ? bridgeClusterClient : null),
+ getChildEndpoints: () => [
{
id: 'child-endpoint-1',
name: 'Child Endpoint',
number: 2,
- clusterClients,
+ getAllClusterClients: () => [clusterClient],
+ getClusterClientById: () => null,
+ getChildEndpoints: () => [],
},
],
},
@@ -128,13 +134,16 @@ describe('Matter.pairDevice', () => {
id: 'device-2',
name: 'Test Device 2',
number: 2,
- clusterClients: bridgeClusterClients,
- childEndpoints: [
+ getAllClusterClients: () => [bridgeClusterClient],
+ getClusterClientById: (id) => (id === bridgeClusterClient.id ? bridgeClusterClient : null),
+ getChildEndpoints: () => [
{
id: 'child-endpoint-2',
name: 'Child Endpoint 2',
number: 2,
- clusterClients,
+ getAllClusterClients: () => [clusterClient],
+ getClusterClientById: () => null,
+ getChildEndpoints: () => [],
},
],
},
diff --git a/server/test/services/matter/lib/matter.refreshDevices.test.js b/server/test/services/matter/lib/matter.refreshDevices.test.js
index 1e867e5fb6..2a16141b7d 100644
--- a/server/test/services/matter/lib/matter.refreshDevices.test.js
+++ b/server/test/services/matter/lib/matter.refreshDevices.test.js
@@ -53,13 +53,16 @@ describe('Matter.refreshDevices', () => {
id: 'device-1',
name: 'Test Device',
number: 1,
- clusterClients,
- childEndpoints: [
+ getAllClusterClients: () => Array.from(clusterClients.values()),
+ getClusterClientById: (id) => clusterClients.get(id),
+ getChildEndpoints: () => [
{
id: 'child-endpoint-1',
name: 'Child Endpoint',
number: 2,
- clusterClients,
+ getAllClusterClients: () => Array.from(clusterClients.values()),
+ getClusterClientById: (id) => clusterClients.get(id),
+ getChildEndpoints: () => [],
},
],
},
diff --git a/server/test/services/matter/lib/matter.setValue.test.js b/server/test/services/matter/lib/matter.setValue.test.js
index d05e24e9d0..5137dfcb3a 100644
--- a/server/test/services/matter/lib/matter.setValue.test.js
+++ b/server/test/services/matter/lib/matter.setValue.test.js
@@ -51,7 +51,8 @@ describe('Matter.setValue', () => {
getDevices: fake.returns([
{
number: 1,
- clusterClients,
+ getClusterClientById: (id) => clusterClients.get(id),
+ getChildEndpoints: () => [],
},
]),
});
@@ -90,7 +91,8 @@ describe('Matter.setValue', () => {
getDevices: fake.returns([
{
number: 1,
- clusterClients,
+ getClusterClientById: (id) => clusterClients.get(id),
+ getChildEndpoints: () => [],
},
]),
});
@@ -130,13 +132,16 @@ describe('Matter.setValue', () => {
getDevices: fake.returns([
{
number: 1,
- childEndpoints: [
+ getClusterClientById: () => null,
+ getChildEndpoints: () => [
{
number: 2,
- childEndpoints: [
+ getClusterClientById: () => null,
+ getChildEndpoints: () => [
{
number: 2,
- clusterClients,
+ getClusterClientById: (id) => clusterClients.get(id),
+ getChildEndpoints: () => [],
},
],
},
@@ -179,7 +184,8 @@ describe('Matter.setValue', () => {
getDevices: fake.returns([
{
number: 1,
- clusterClients,
+ getClusterClientById: (id) => clusterClients.get(id),
+ getChildEndpoints: () => [],
},
]),
});
@@ -218,7 +224,8 @@ describe('Matter.setValue', () => {
getDevices: fake.returns([
{
number: 1,
- clusterClients,
+ getClusterClientById: (id) => clusterClients.get(id),
+ getChildEndpoints: () => [],
},
]),
});
@@ -265,7 +272,8 @@ describe('Matter.setValue', () => {
getDevices: fake.returns([
{
number: 1,
- clusterClients,
+ getClusterClientById: (id) => clusterClients.get(id),
+ getChildEndpoints: () => [],
},
]),
});
@@ -319,7 +327,8 @@ describe('Matter.setValue', () => {
getDevices: fake.returns([
{
number: 1,
- clusterClients,
+ getClusterClientById: (id) => clusterClients.get(id),
+ getChildEndpoints: () => [],
},
]),
});
@@ -366,7 +375,8 @@ describe('Matter.setValue', () => {
getDevices: fake.returns([
{
number: 1,
- clusterClients,
+ getClusterClientById: (id) => clusterClients.get(id),
+ getChildEndpoints: () => [],
},
]),
});
@@ -404,7 +414,8 @@ describe('Matter.setValue', () => {
getDevices: fake.returns([
{
number: 1,
- clusterClients,
+ getClusterClientById: (id) => clusterClients.get(id),
+ getChildEndpoints: () => [],
},
]),
});
@@ -475,7 +486,8 @@ describe('Matter.setValue', () => {
getDevices: fake.returns([
{
number: 1,
- clusterClients,
+ getClusterClientById: (id) => clusterClients.get(id),
+ getChildEndpoints: () => [],
},
]),
});
@@ -507,7 +519,8 @@ describe('Matter.setValue', () => {
getDevices: fake.returns([
{
number: 1,
- clusterClients,
+ getClusterClientById: (id) => clusterClients.get(id),
+ getChildEndpoints: () => [],
},
]),
});
@@ -539,10 +552,12 @@ describe('Matter.setValue', () => {
getDevices: fake.returns([
{
number: 1,
- childEndpoints: [
+ getClusterClientById: (id) => clusterClients.get(id),
+ getChildEndpoints: () => [
{
number: 1,
- clusterClients,
+ getClusterClientById: (id) => clusterClients.get(id),
+ getChildEndpoints: () => [],
},
],
},
From 417aa1dd8ab63fde1151a45df3a7e8e683893325 Mon Sep 17 00:00:00 2001
From: Pierre-Gilles Leymarie <7365207+Pierre-Gilles@users.noreply.github.com>
Date: Mon, 23 Mar 2026 09:37:48 +0100
Subject: [PATCH 03/16] Add cleaner log to device.newStateEvent in case device
was not added to Gladys
---
server/lib/device/device.newStateEvent.js | 6 ++--
.../lib/device/device.newStateEvent.test.js | 32 +++++++------------
2 files changed, 16 insertions(+), 22 deletions(-)
diff --git a/server/lib/device/device.newStateEvent.js b/server/lib/device/device.newStateEvent.js
index 341403385a..111eb6d33a 100644
--- a/server/lib/device/device.newStateEvent.js
+++ b/server/lib/device/device.newStateEvent.js
@@ -15,11 +15,13 @@ const logger = require('../../utils/logger');
async function newStateEvent(event) {
const deviceFeature = this.stateManager.get('deviceFeatureByExternalId', event.device_feature_external_id);
if (deviceFeature === null) {
- throw new NotFoundError(`DeviceFeature ${event.device_feature_external_id} not found`);
+ logger.info(`DeviceFeature "${event.device_feature_external_id}" not found (or not added to Gladys), skipping state update.`);
+ return;
}
const device = this.stateManager.get('deviceById', deviceFeature.device_id);
if (device === null) {
- throw new NotFoundError(`Device ${deviceFeature.device_id} not found`);
+ logger.info(`Device "${deviceFeature.device_id}" not found, skipping state update.`);
+ return;
}
try {
// If there is a "text" property in the even, we save as string
diff --git a/server/test/lib/device/device.newStateEvent.test.js b/server/test/lib/device/device.newStateEvent.test.js
index 4fe49897fe..dabc1c96a8 100644
--- a/server/test/lib/device/device.newStateEvent.test.js
+++ b/server/test/lib/device/device.newStateEvent.test.js
@@ -184,16 +184,12 @@ describe('Device.newStateEvent', () => {
it('should not save state missing device feature', async () => {
const stateManager = new StateManager(event);
const device = new Device(event, {}, stateManager, {}, {}, {}, job);
- try {
- await device.newStateEvent({
- device_feature_external_id: 'hue:binary:1',
- state: 12,
- created_at: '2019-02-12 07:49:07.556 +00:00',
- });
- assert.fail();
- } catch (e) {
- expect(e).to.be.instanceOf(NotFoundError);
- }
+ // Should not throw, just log and return early
+ await device.newStateEvent({
+ device_feature_external_id: 'hue:binary:1',
+ state: 12,
+ created_at: '2019-02-12 07:49:07.556 +00:00',
+ });
const newDeviceFeature = stateManager.get('deviceFeatureByExternalId', 'hue:binary:1');
// eslint-disable-next-line no-unused-expressions
expect(newDeviceFeature).to.be.null;
@@ -209,16 +205,12 @@ describe('Device.newStateEvent', () => {
};
stateManager.setState('deviceFeatureByExternalId', 'hue:binary:1', currentDeviceFeature);
const device = new Device(event, {}, stateManager, {}, {}, {}, job);
- try {
- await device.newStateEvent({
- device_feature_external_id: 'hue:binary:1',
- state: 12,
- created_at: '2019-02-12 07:49:07.556 +00:00',
- });
- assert.fail();
- } catch (e) {
- expect(e).to.be.instanceOf(NotFoundError);
- }
+ // Should not throw, just log and return early
+ await device.newStateEvent({
+ device_feature_external_id: 'hue:binary:1',
+ state: 12,
+ created_at: '2019-02-12 07:49:07.556 +00:00',
+ });
const newDeviceFeature = stateManager.get('deviceFeatureByExternalId', 'hue:binary:1');
expect(newDeviceFeature).not.to.have.property('last_value');
expect(newDeviceFeature).not.to.have.property('last_value_changed');
From 2bdfd3d134c461bbe529ab34c6bd8714a47597e7 Mon Sep 17 00:00:00 2001
From: Pierre-Gilles Leymarie <7365207+Pierre-Gilles@users.noreply.github.com>
Date: Mon, 23 Mar 2026 09:40:46 +0100
Subject: [PATCH 04/16] refreshDevices should be non-blocking during startup to
avoid blocking Gladys
---
server/services/matter/lib/matter.init.js | 6 +++++-
server/test/services/matter/lib/matter.init.test.js | 2 ++
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/server/services/matter/lib/matter.init.js b/server/services/matter/lib/matter.init.js
index 9e52e9d03f..7da45e27a4 100644
--- a/server/services/matter/lib/matter.init.js
+++ b/server/services/matter/lib/matter.init.js
@@ -53,7 +53,11 @@ async function init() {
await this.commissioningController.start();
logger.info('Matter controller started');
- await this.refreshDevices();
+ // Refresh devices in the background to avoid blocking Gladys startup
+ // Store the promise so it can be awaited in tests
+ this.refreshDevicesPromise = this.refreshDevices().catch((err) => {
+ logger.error('Matter: Error refreshing devices in background:', err);
+ });
// Schedule reccurent job if not already scheduled
if (!this.backupScheduledJob) {
this.backupScheduledJob = this.gladys.scheduler.scheduleJob('0 0 4 * * *', () => this.backupController());
diff --git a/server/test/services/matter/lib/matter.init.test.js b/server/test/services/matter/lib/matter.init.test.js
index b1d3846b08..c8cd06ea29 100644
--- a/server/test/services/matter/lib/matter.init.test.js
+++ b/server/test/services/matter/lib/matter.init.test.js
@@ -349,6 +349,8 @@ describe('Matter.init', () => {
it('should initialize matter service successfully', async () => {
await matterHandler.init();
+ // Wait for background refreshDevices() to complete
+ await matterHandler.refreshDevicesPromise;
expect(matterHandler.devices).to.have.lengthOf(2);
// Device selector should be a slug of the name with 4 random characters at the end
expect(matterHandler.devices[0].selector).to.satisfy(
From 6aba08305d35617809ded7a9d102b085201376e4 Mon Sep 17 00:00:00 2001
From: Pierre-Gilles Leymarie <7365207+Pierre-Gilles@users.noreply.github.com>
Date: Mon, 23 Mar 2026 09:44:26 +0100
Subject: [PATCH 05/16] Fix linting & prettier
---
server/lib/device/device.newStateEvent.js | 5 +++--
server/test/lib/device/device.newStateEvent.test.js | 1 -
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/server/lib/device/device.newStateEvent.js b/server/lib/device/device.newStateEvent.js
index 111eb6d33a..0738ef1548 100644
--- a/server/lib/device/device.newStateEvent.js
+++ b/server/lib/device/device.newStateEvent.js
@@ -1,4 +1,3 @@
-const { NotFoundError } = require('../../utils/coreErrors');
const { DEVICE_FEATURE_CATEGORIES, DEVICE_FEATURE_TYPES } = require('../../utils/constants');
const logger = require('../../utils/logger');
@@ -15,7 +14,9 @@ const logger = require('../../utils/logger');
async function newStateEvent(event) {
const deviceFeature = this.stateManager.get('deviceFeatureByExternalId', event.device_feature_external_id);
if (deviceFeature === null) {
- logger.info(`DeviceFeature "${event.device_feature_external_id}" not found (or not added to Gladys), skipping state update.`);
+ logger.info(
+ `DeviceFeature "${event.device_feature_external_id}" not found (or not added to Gladys), skipping state update.`,
+ );
return;
}
const device = this.stateManager.get('deviceById', deviceFeature.device_id);
diff --git a/server/test/lib/device/device.newStateEvent.test.js b/server/test/lib/device/device.newStateEvent.test.js
index dabc1c96a8..bd9e43a429 100644
--- a/server/test/lib/device/device.newStateEvent.test.js
+++ b/server/test/lib/device/device.newStateEvent.test.js
@@ -8,7 +8,6 @@ const { expect } = require('chai');
const Device = require('../../../lib/device');
const StateManager = require('../../../lib/state');
const Job = require('../../../lib/job');
-const { NotFoundError } = require('../../../utils/coreErrors');
const event = new EventEmitter();
const job = new Job(event);
From 33f34ff41cc475d688cfb92c23f599b06b2c52ce Mon Sep 17 00:00:00 2001
From: Pierre-Gilles Leymarie <7365207+Pierre-Gilles@users.noreply.github.com>
Date: Mon, 23 Mar 2026 09:55:00 +0100
Subject: [PATCH 06/16] Add missing test for coverage
---
server/test/services/matter/lib/matter.init.test.js | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/server/test/services/matter/lib/matter.init.test.js b/server/test/services/matter/lib/matter.init.test.js
index c8cd06ea29..73731e0489 100644
--- a/server/test/services/matter/lib/matter.init.test.js
+++ b/server/test/services/matter/lib/matter.init.test.js
@@ -897,6 +897,16 @@ describe('Matter.init', () => {
expect(matterHandler.nodesMap.size).to.equal(0);
});
+ it('should log error when refreshDevices fails in background', async () => {
+ const error = new Error('Test error');
+ matterHandler.refreshDevices = fake.rejects(error);
+ await matterHandler.init();
+ // Wait for background promise to complete
+ await matterHandler.refreshDevicesPromise;
+ // The error should be caught and logged, not thrown
+ expect(matterHandler.refreshDevicesPromise).to.be.fulfilled;
+ });
+
it('should return PPM for 0', () => {
expect(convertMeasurementUnitToDeviceFeatureUnits(0)).to.equal('ppm');
});
From 08fad078977bc3a979dd680e0238bb639d2eede2 Mon Sep 17 00:00:00 2001
From: Pierre-Gilles Leymarie <7365207+Pierre-Gilles@users.noreply.github.com>
Date: Mon, 23 Mar 2026 10:02:36 +0100
Subject: [PATCH 07/16] Fix linting
---
server/test/services/matter/lib/matter.init.test.js | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/server/test/services/matter/lib/matter.init.test.js b/server/test/services/matter/lib/matter.init.test.js
index 73731e0489..c33973f986 100644
--- a/server/test/services/matter/lib/matter.init.test.js
+++ b/server/test/services/matter/lib/matter.init.test.js
@@ -901,10 +901,8 @@ describe('Matter.init', () => {
const error = new Error('Test error');
matterHandler.refreshDevices = fake.rejects(error);
await matterHandler.init();
- // Wait for background promise to complete
+ // Wait for background promise to complete - error should be caught and logged, not thrown
await matterHandler.refreshDevicesPromise;
- // The error should be caught and logged, not thrown
- expect(matterHandler.refreshDevicesPromise).to.be.fulfilled;
});
it('should return PPM for 0', () => {
From 19faba388e1b022bdf3190bb0a3264efd0134380 Mon Sep 17 00:00:00 2001
From: Pierre-Gilles Leymarie <7365207+Pierre-Gilles@users.noreply.github.com>
Date: Mon, 23 Mar 2026 11:06:17 +0100
Subject: [PATCH 08/16] refreshDevices should not fail completely if one device
fail
---
.../matter/lib/matter.refreshDevices.js | 9 +++-
.../matter/lib/matter.refreshDevices.test.js | 50 +++++++++++++++++++
2 files changed, 58 insertions(+), 1 deletion(-)
diff --git a/server/services/matter/lib/matter.refreshDevices.js b/server/services/matter/lib/matter.refreshDevices.js
index 005e37b584..e875e410bc 100644
--- a/server/services/matter/lib/matter.refreshDevices.js
+++ b/server/services/matter/lib/matter.refreshDevices.js
@@ -1,5 +1,7 @@
const Promise = require('bluebird');
+const logger = require('../../../utils/logger');
+
/**
* @description Refresh the devices.
* @example matter.refreshDevices();
@@ -10,7 +12,12 @@ async function refreshDevices() {
const nodeDetails = this.commissioningController.getCommissionedNodesDetails();
await Promise.each(nodeDetails, async (nodeDetail) => {
- await this.handleNode(nodeDetail);
+ try {
+ await this.handleNode(nodeDetail);
+ } catch (err) {
+ // Log error but continue with other devices - one unreachable device shouldn't break the others
+ logger.warn(`Matter: Error handling node ${nodeDetail.nodeId}: ${err.message}`);
+ }
});
}
diff --git a/server/test/services/matter/lib/matter.refreshDevices.test.js b/server/test/services/matter/lib/matter.refreshDevices.test.js
index 2a16141b7d..46a98c0ed9 100644
--- a/server/test/services/matter/lib/matter.refreshDevices.test.js
+++ b/server/test/services/matter/lib/matter.refreshDevices.test.js
@@ -79,4 +79,54 @@ describe('Matter.refreshDevices', () => {
expect(matterHandler.devices).to.have.lengthOf(2);
expect(matterHandler.nodesMap.size).to.equal(1);
});
+
+ it('should continue with other devices when one node fails', async () => {
+ let callCount = 0;
+ // First node throws an error, second node succeeds
+ matterHandler.commissioningController = {
+ getCommissionedNodesDetails: fake.returns([
+ {
+ nodeId: 11111n,
+ deviceData: {
+ basicInformation: {
+ vendorName: 'Unreachable Vendor',
+ productName: 'Unreachable Product',
+ },
+ },
+ },
+ {
+ nodeId: 22222n,
+ deviceData: {
+ basicInformation: {
+ vendorName: 'Reachable Vendor',
+ productName: 'Reachable Product',
+ },
+ },
+ },
+ ]),
+ getNode: sinon.stub().callsFake(async () => {
+ callCount += 1;
+ if (callCount === 1) {
+ throw new Error('Node is not reachable right now');
+ }
+ return {
+ getDevices: fake.returns([
+ {
+ id: 'device-2',
+ name: 'Reachable Device',
+ number: 1,
+ getAllClusterClients: () => Array.from(clusterClients.values()),
+ getClusterClientById: (id) => clusterClients.get(id),
+ getChildEndpoints: () => [],
+ },
+ ]),
+ };
+ }),
+ };
+
+ await matterHandler.refreshDevices();
+ // Should have 1 device from the second node (first node failed)
+ expect(matterHandler.devices).to.have.lengthOf(1);
+ expect(matterHandler.devices[0].name).to.include('Reachable');
+ });
});
From 987f2d6efc4a5b25f74e54fcc6c93fbc4fef3cc8 Mon Sep 17 00:00:00 2001
From: Pierre-Gilles Leymarie <7365207+Pierre-Gilles@users.noreply.github.com>
Date: Fri, 10 Apr 2026 11:18:08 +0200
Subject: [PATCH 09/16] Upgrade Matter.js to v0.16.11
---
server/package-lock.json | 166 +++++++++++------------
server/package.json | 2 +-
server/services/matter/package-lock.json | 102 +++++++-------
server/services/matter/package.json | 4 +-
4 files changed, 137 insertions(+), 137 deletions(-)
diff --git a/server/package-lock.json b/server/package-lock.json
index 047b10e7fe..82491feb4a 100644
--- a/server/package-lock.json
+++ b/server/package-lock.json
@@ -53,7 +53,7 @@
"ws": "^6.2.2"
},
"devDependencies": {
- "@matter/main": "^0.16.10",
+ "@matter/main": "^0.16.11",
"apidoc": "^1.0.3",
"chai": "^4.3.7",
"chai-as-promised": "^7.1.1",
@@ -1062,9 +1062,9 @@
}
},
"node_modules/@matter/general": {
- "version": "0.16.10",
- "resolved": "https://registry.npmjs.org/@matter/general/-/general-0.16.10.tgz",
- "integrity": "sha512-/qytvaxvDDhEdHLaEoxlEFVBWg982jL+XXvOmAFgIv92yGDQvN4U+VcNW7S5dueJuv/L+gi0zDqhl8LUzHHAlg==",
+ "version": "0.16.11",
+ "resolved": "https://registry.npmjs.org/@matter/general/-/general-0.16.11.tgz",
+ "integrity": "sha512-iOnCR7azYgRzr4p/WQRRmbediZFYsqfaqSIp7yyGhnfn2gx386F/Wh96HGXYWdprTWet/7IsFV6uiA9jcDNHvA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
@@ -1072,83 +1072,83 @@
}
},
"node_modules/@matter/main": {
- "version": "0.16.10",
- "resolved": "https://registry.npmjs.org/@matter/main/-/main-0.16.10.tgz",
- "integrity": "sha512-QKoQrmMnt6cB893+Oezk3DdIVgQJj5spt/ikEszF8pjyTuvB69zlzq1wnrn52N3mi57R6UWwk6+BPEbQE95FSw==",
+ "version": "0.16.11",
+ "resolved": "https://registry.npmjs.org/@matter/main/-/main-0.16.11.tgz",
+ "integrity": "sha512-FDFhTix4AcH7t7TP7PnU2smFayza2RrI3uppSRzEmJ+Vxy8btelJMpDjBcxBbNb2Iao7jX7W8DLPMMuH6AzMQg==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@matter/general": "0.16.10",
- "@matter/model": "0.16.10",
- "@matter/node": "0.16.10",
- "@matter/protocol": "0.16.10",
- "@matter/types": "0.16.10"
+ "@matter/general": "0.16.11",
+ "@matter/model": "0.16.11",
+ "@matter/node": "0.16.11",
+ "@matter/protocol": "0.16.11",
+ "@matter/types": "0.16.11"
},
"optionalDependencies": {
- "@matter/nodejs": "0.16.10"
+ "@matter/nodejs": "0.16.11"
}
},
"node_modules/@matter/model": {
- "version": "0.16.10",
- "resolved": "https://registry.npmjs.org/@matter/model/-/model-0.16.10.tgz",
- "integrity": "sha512-6Ei8gETAkcKGEMRW+z8Mak55Y1Jl1TKGQIboC/4vvsrqcvB8zhIvGBS3GaAllxzvF0qjE7ihCPpgXXr6HuTLyg==",
+ "version": "0.16.11",
+ "resolved": "https://registry.npmjs.org/@matter/model/-/model-0.16.11.tgz",
+ "integrity": "sha512-7a64fUnf3EFwfqt5C/p4aR9RrQBWgNYnP/FKPAI4wC6cp3OyOm9Yt7fqE//Q6ikPpU867kMLxhMHwmgvntMgtA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@matter/general": "0.16.10"
+ "@matter/general": "0.16.11"
}
},
"node_modules/@matter/node": {
- "version": "0.16.10",
- "resolved": "https://registry.npmjs.org/@matter/node/-/node-0.16.10.tgz",
- "integrity": "sha512-Hb2AxuEf0DlfN8yHxeahZGYurUUu/UDWJkmdvpDKuwSR0eIHhMweOG2RBO55/anyRFObANaUr1gr3DnyocB/0w==",
+ "version": "0.16.11",
+ "resolved": "https://registry.npmjs.org/@matter/node/-/node-0.16.11.tgz",
+ "integrity": "sha512-Y+ji+A8iWRCaG2HI7yXlvgOizwePIt3lSZV+wVo+Pyf86vwtDLxxY225nfRcV/Iwawmm/l2WM8aoPaNh37C0iw==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@matter/general": "0.16.10",
- "@matter/model": "0.16.10",
- "@matter/protocol": "0.16.10",
- "@matter/types": "0.16.10"
+ "@matter/general": "0.16.11",
+ "@matter/model": "0.16.11",
+ "@matter/protocol": "0.16.11",
+ "@matter/types": "0.16.11"
}
},
"node_modules/@matter/nodejs": {
- "version": "0.16.10",
- "resolved": "https://registry.npmjs.org/@matter/nodejs/-/nodejs-0.16.10.tgz",
- "integrity": "sha512-o8e9tGZVsiqmEtD1osSL9+gRMIuNjtwXt29I3YDRzSqb3N5Dvd4Khj3HN68YhaFFeBlM4YEV2TS0/9VF3C06/w==",
+ "version": "0.16.11",
+ "resolved": "https://registry.npmjs.org/@matter/nodejs/-/nodejs-0.16.11.tgz",
+ "integrity": "sha512-Q/kOWerSnHHUI5A/FnD6Tz61asO0C4Rz/hemF3L7DAWu4nEEq6O2msH+RTaj3NrHK9ef28PGpTMS35PbMpFOyg==",
"dev": true,
"license": "Apache-2.0",
"optional": true,
"dependencies": {
- "@matter/general": "0.16.10",
- "@matter/node": "0.16.10",
- "@matter/protocol": "0.16.10",
- "@matter/types": "0.16.10"
+ "@matter/general": "0.16.11",
+ "@matter/node": "0.16.11",
+ "@matter/protocol": "0.16.11",
+ "@matter/types": "0.16.11"
},
"engines": {
"node": ">=20.19.0 <22.0.0 || >=22.13.0"
}
},
"node_modules/@matter/protocol": {
- "version": "0.16.10",
- "resolved": "https://registry.npmjs.org/@matter/protocol/-/protocol-0.16.10.tgz",
- "integrity": "sha512-vPQEMl8Wf4vc3tauwsGlLZRrDx+VrCPfccw3n50Lvyucws4UBt+SuBszSyIO2+QPnJcr4MB4L+EgCRI14U4zRA==",
+ "version": "0.16.11",
+ "resolved": "https://registry.npmjs.org/@matter/protocol/-/protocol-0.16.11.tgz",
+ "integrity": "sha512-+Q6s+Cmvcm5BJEFBtS6m0vUVrHdxTBteDcJ+VfpNna1ST910371lVqtDwYFclqECQMlDYxoNjkfcYNv4pZfNPg==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@matter/general": "0.16.10",
- "@matter/model": "0.16.10",
- "@matter/types": "0.16.10"
+ "@matter/general": "0.16.11",
+ "@matter/model": "0.16.11",
+ "@matter/types": "0.16.11"
}
},
"node_modules/@matter/types": {
- "version": "0.16.10",
- "resolved": "https://registry.npmjs.org/@matter/types/-/types-0.16.10.tgz",
- "integrity": "sha512-AW86tGgL3sN1Vb76+03VPdQMsW9vWsaVGHe9agcED1sjtWRJBV17tcLDymAQ8k7fEeVqiy3qf9CUwFK1bhfXKQ==",
+ "version": "0.16.11",
+ "resolved": "https://registry.npmjs.org/@matter/types/-/types-0.16.11.tgz",
+ "integrity": "sha512-RcZk5N4AeoqKaLzlC6M6+J8YGJgxnLYpF/3WL7CeIM1DpA9ebkPQB9B8of+RJnqy8kgr6eqL/3ATmPGDA46fwg==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@matter/general": "0.16.10",
- "@matter/model": "0.16.10"
+ "@matter/general": "0.16.11",
+ "@matter/model": "0.16.11"
}
},
"node_modules/@microsoft/recognizers-text": {
@@ -13146,81 +13146,81 @@
}
},
"@matter/general": {
- "version": "0.16.10",
- "resolved": "https://registry.npmjs.org/@matter/general/-/general-0.16.10.tgz",
- "integrity": "sha512-/qytvaxvDDhEdHLaEoxlEFVBWg982jL+XXvOmAFgIv92yGDQvN4U+VcNW7S5dueJuv/L+gi0zDqhl8LUzHHAlg==",
+ "version": "0.16.11",
+ "resolved": "https://registry.npmjs.org/@matter/general/-/general-0.16.11.tgz",
+ "integrity": "sha512-iOnCR7azYgRzr4p/WQRRmbediZFYsqfaqSIp7yyGhnfn2gx386F/Wh96HGXYWdprTWet/7IsFV6uiA9jcDNHvA==",
"dev": true,
"requires": {
"@noble/curves": "^2.0.1"
}
},
"@matter/main": {
- "version": "0.16.10",
- "resolved": "https://registry.npmjs.org/@matter/main/-/main-0.16.10.tgz",
- "integrity": "sha512-QKoQrmMnt6cB893+Oezk3DdIVgQJj5spt/ikEszF8pjyTuvB69zlzq1wnrn52N3mi57R6UWwk6+BPEbQE95FSw==",
+ "version": "0.16.11",
+ "resolved": "https://registry.npmjs.org/@matter/main/-/main-0.16.11.tgz",
+ "integrity": "sha512-FDFhTix4AcH7t7TP7PnU2smFayza2RrI3uppSRzEmJ+Vxy8btelJMpDjBcxBbNb2Iao7jX7W8DLPMMuH6AzMQg==",
"dev": true,
"requires": {
- "@matter/general": "0.16.10",
- "@matter/model": "0.16.10",
- "@matter/node": "0.16.10",
- "@matter/nodejs": "0.16.10",
- "@matter/protocol": "0.16.10",
- "@matter/types": "0.16.10"
+ "@matter/general": "0.16.11",
+ "@matter/model": "0.16.11",
+ "@matter/node": "0.16.11",
+ "@matter/nodejs": "0.16.11",
+ "@matter/protocol": "0.16.11",
+ "@matter/types": "0.16.11"
}
},
"@matter/model": {
- "version": "0.16.10",
- "resolved": "https://registry.npmjs.org/@matter/model/-/model-0.16.10.tgz",
- "integrity": "sha512-6Ei8gETAkcKGEMRW+z8Mak55Y1Jl1TKGQIboC/4vvsrqcvB8zhIvGBS3GaAllxzvF0qjE7ihCPpgXXr6HuTLyg==",
+ "version": "0.16.11",
+ "resolved": "https://registry.npmjs.org/@matter/model/-/model-0.16.11.tgz",
+ "integrity": "sha512-7a64fUnf3EFwfqt5C/p4aR9RrQBWgNYnP/FKPAI4wC6cp3OyOm9Yt7fqE//Q6ikPpU867kMLxhMHwmgvntMgtA==",
"dev": true,
"requires": {
- "@matter/general": "0.16.10"
+ "@matter/general": "0.16.11"
}
},
"@matter/node": {
- "version": "0.16.10",
- "resolved": "https://registry.npmjs.org/@matter/node/-/node-0.16.10.tgz",
- "integrity": "sha512-Hb2AxuEf0DlfN8yHxeahZGYurUUu/UDWJkmdvpDKuwSR0eIHhMweOG2RBO55/anyRFObANaUr1gr3DnyocB/0w==",
+ "version": "0.16.11",
+ "resolved": "https://registry.npmjs.org/@matter/node/-/node-0.16.11.tgz",
+ "integrity": "sha512-Y+ji+A8iWRCaG2HI7yXlvgOizwePIt3lSZV+wVo+Pyf86vwtDLxxY225nfRcV/Iwawmm/l2WM8aoPaNh37C0iw==",
"dev": true,
"requires": {
- "@matter/general": "0.16.10",
- "@matter/model": "0.16.10",
- "@matter/protocol": "0.16.10",
- "@matter/types": "0.16.10"
+ "@matter/general": "0.16.11",
+ "@matter/model": "0.16.11",
+ "@matter/protocol": "0.16.11",
+ "@matter/types": "0.16.11"
}
},
"@matter/nodejs": {
- "version": "0.16.10",
- "resolved": "https://registry.npmjs.org/@matter/nodejs/-/nodejs-0.16.10.tgz",
- "integrity": "sha512-o8e9tGZVsiqmEtD1osSL9+gRMIuNjtwXt29I3YDRzSqb3N5Dvd4Khj3HN68YhaFFeBlM4YEV2TS0/9VF3C06/w==",
+ "version": "0.16.11",
+ "resolved": "https://registry.npmjs.org/@matter/nodejs/-/nodejs-0.16.11.tgz",
+ "integrity": "sha512-Q/kOWerSnHHUI5A/FnD6Tz61asO0C4Rz/hemF3L7DAWu4nEEq6O2msH+RTaj3NrHK9ef28PGpTMS35PbMpFOyg==",
"dev": true,
"optional": true,
"requires": {
- "@matter/general": "0.16.10",
- "@matter/node": "0.16.10",
- "@matter/protocol": "0.16.10",
- "@matter/types": "0.16.10"
+ "@matter/general": "0.16.11",
+ "@matter/node": "0.16.11",
+ "@matter/protocol": "0.16.11",
+ "@matter/types": "0.16.11"
}
},
"@matter/protocol": {
- "version": "0.16.10",
- "resolved": "https://registry.npmjs.org/@matter/protocol/-/protocol-0.16.10.tgz",
- "integrity": "sha512-vPQEMl8Wf4vc3tauwsGlLZRrDx+VrCPfccw3n50Lvyucws4UBt+SuBszSyIO2+QPnJcr4MB4L+EgCRI14U4zRA==",
+ "version": "0.16.11",
+ "resolved": "https://registry.npmjs.org/@matter/protocol/-/protocol-0.16.11.tgz",
+ "integrity": "sha512-+Q6s+Cmvcm5BJEFBtS6m0vUVrHdxTBteDcJ+VfpNna1ST910371lVqtDwYFclqECQMlDYxoNjkfcYNv4pZfNPg==",
"dev": true,
"requires": {
- "@matter/general": "0.16.10",
- "@matter/model": "0.16.10",
- "@matter/types": "0.16.10"
+ "@matter/general": "0.16.11",
+ "@matter/model": "0.16.11",
+ "@matter/types": "0.16.11"
}
},
"@matter/types": {
- "version": "0.16.10",
- "resolved": "https://registry.npmjs.org/@matter/types/-/types-0.16.10.tgz",
- "integrity": "sha512-AW86tGgL3sN1Vb76+03VPdQMsW9vWsaVGHe9agcED1sjtWRJBV17tcLDymAQ8k7fEeVqiy3qf9CUwFK1bhfXKQ==",
+ "version": "0.16.11",
+ "resolved": "https://registry.npmjs.org/@matter/types/-/types-0.16.11.tgz",
+ "integrity": "sha512-RcZk5N4AeoqKaLzlC6M6+J8YGJgxnLYpF/3WL7CeIM1DpA9ebkPQB9B8of+RJnqy8kgr6eqL/3ATmPGDA46fwg==",
"dev": true,
"requires": {
- "@matter/general": "0.16.10",
- "@matter/model": "0.16.10"
+ "@matter/general": "0.16.11",
+ "@matter/model": "0.16.11"
}
},
"@microsoft/recognizers-text": {
diff --git a/server/package.json b/server/package.json
index b5ad5cc1e0..65ff7411a6 100644
--- a/server/package.json
+++ b/server/package.json
@@ -46,7 +46,7 @@
]
},
"devDependencies": {
- "@matter/main": "^0.16.10",
+ "@matter/main": "^0.16.11",
"apidoc": "^1.0.3",
"chai": "^4.3.7",
"chai-as-promised": "^7.1.1",
diff --git a/server/services/matter/package-lock.json b/server/services/matter/package-lock.json
index 210445bb14..6402b1532b 100644
--- a/server/services/matter/package-lock.json
+++ b/server/services/matter/package-lock.json
@@ -16,93 +16,93 @@
"win32"
],
"dependencies": {
- "@matter/main": "^0.16.10",
- "@project-chip/matter.js": "^0.16.10",
+ "@matter/main": "^0.16.11",
+ "@project-chip/matter.js": "^0.16.11",
"bluebird": "^3.7.2",
"fs-extra": "^11.3.0"
}
},
"node_modules/@matter/general": {
- "version": "0.16.10",
- "resolved": "https://registry.npmjs.org/@matter/general/-/general-0.16.10.tgz",
- "integrity": "sha512-/qytvaxvDDhEdHLaEoxlEFVBWg982jL+XXvOmAFgIv92yGDQvN4U+VcNW7S5dueJuv/L+gi0zDqhl8LUzHHAlg==",
+ "version": "0.16.11",
+ "resolved": "https://registry.npmjs.org/@matter/general/-/general-0.16.11.tgz",
+ "integrity": "sha512-iOnCR7azYgRzr4p/WQRRmbediZFYsqfaqSIp7yyGhnfn2gx386F/Wh96HGXYWdprTWet/7IsFV6uiA9jcDNHvA==",
"license": "Apache-2.0",
"dependencies": {
"@noble/curves": "^2.0.1"
}
},
"node_modules/@matter/main": {
- "version": "0.16.10",
- "resolved": "https://registry.npmjs.org/@matter/main/-/main-0.16.10.tgz",
- "integrity": "sha512-QKoQrmMnt6cB893+Oezk3DdIVgQJj5spt/ikEszF8pjyTuvB69zlzq1wnrn52N3mi57R6UWwk6+BPEbQE95FSw==",
+ "version": "0.16.11",
+ "resolved": "https://registry.npmjs.org/@matter/main/-/main-0.16.11.tgz",
+ "integrity": "sha512-FDFhTix4AcH7t7TP7PnU2smFayza2RrI3uppSRzEmJ+Vxy8btelJMpDjBcxBbNb2Iao7jX7W8DLPMMuH6AzMQg==",
"license": "Apache-2.0",
"dependencies": {
- "@matter/general": "0.16.10",
- "@matter/model": "0.16.10",
- "@matter/node": "0.16.10",
- "@matter/protocol": "0.16.10",
- "@matter/types": "0.16.10"
+ "@matter/general": "0.16.11",
+ "@matter/model": "0.16.11",
+ "@matter/node": "0.16.11",
+ "@matter/protocol": "0.16.11",
+ "@matter/types": "0.16.11"
},
"optionalDependencies": {
- "@matter/nodejs": "0.16.10"
+ "@matter/nodejs": "0.16.11"
}
},
"node_modules/@matter/model": {
- "version": "0.16.10",
- "resolved": "https://registry.npmjs.org/@matter/model/-/model-0.16.10.tgz",
- "integrity": "sha512-6Ei8gETAkcKGEMRW+z8Mak55Y1Jl1TKGQIboC/4vvsrqcvB8zhIvGBS3GaAllxzvF0qjE7ihCPpgXXr6HuTLyg==",
+ "version": "0.16.11",
+ "resolved": "https://registry.npmjs.org/@matter/model/-/model-0.16.11.tgz",
+ "integrity": "sha512-7a64fUnf3EFwfqt5C/p4aR9RrQBWgNYnP/FKPAI4wC6cp3OyOm9Yt7fqE//Q6ikPpU867kMLxhMHwmgvntMgtA==",
"license": "Apache-2.0",
"dependencies": {
- "@matter/general": "0.16.10"
+ "@matter/general": "0.16.11"
}
},
"node_modules/@matter/node": {
- "version": "0.16.10",
- "resolved": "https://registry.npmjs.org/@matter/node/-/node-0.16.10.tgz",
- "integrity": "sha512-Hb2AxuEf0DlfN8yHxeahZGYurUUu/UDWJkmdvpDKuwSR0eIHhMweOG2RBO55/anyRFObANaUr1gr3DnyocB/0w==",
+ "version": "0.16.11",
+ "resolved": "https://registry.npmjs.org/@matter/node/-/node-0.16.11.tgz",
+ "integrity": "sha512-Y+ji+A8iWRCaG2HI7yXlvgOizwePIt3lSZV+wVo+Pyf86vwtDLxxY225nfRcV/Iwawmm/l2WM8aoPaNh37C0iw==",
"license": "Apache-2.0",
"dependencies": {
- "@matter/general": "0.16.10",
- "@matter/model": "0.16.10",
- "@matter/protocol": "0.16.10",
- "@matter/types": "0.16.10"
+ "@matter/general": "0.16.11",
+ "@matter/model": "0.16.11",
+ "@matter/protocol": "0.16.11",
+ "@matter/types": "0.16.11"
}
},
"node_modules/@matter/nodejs": {
- "version": "0.16.10",
- "resolved": "https://registry.npmjs.org/@matter/nodejs/-/nodejs-0.16.10.tgz",
- "integrity": "sha512-o8e9tGZVsiqmEtD1osSL9+gRMIuNjtwXt29I3YDRzSqb3N5Dvd4Khj3HN68YhaFFeBlM4YEV2TS0/9VF3C06/w==",
+ "version": "0.16.11",
+ "resolved": "https://registry.npmjs.org/@matter/nodejs/-/nodejs-0.16.11.tgz",
+ "integrity": "sha512-Q/kOWerSnHHUI5A/FnD6Tz61asO0C4Rz/hemF3L7DAWu4nEEq6O2msH+RTaj3NrHK9ef28PGpTMS35PbMpFOyg==",
"license": "Apache-2.0",
"optional": true,
"dependencies": {
- "@matter/general": "0.16.10",
- "@matter/node": "0.16.10",
- "@matter/protocol": "0.16.10",
- "@matter/types": "0.16.10"
+ "@matter/general": "0.16.11",
+ "@matter/node": "0.16.11",
+ "@matter/protocol": "0.16.11",
+ "@matter/types": "0.16.11"
},
"engines": {
"node": ">=20.19.0 <22.0.0 || >=22.13.0"
}
},
"node_modules/@matter/protocol": {
- "version": "0.16.10",
- "resolved": "https://registry.npmjs.org/@matter/protocol/-/protocol-0.16.10.tgz",
- "integrity": "sha512-vPQEMl8Wf4vc3tauwsGlLZRrDx+VrCPfccw3n50Lvyucws4UBt+SuBszSyIO2+QPnJcr4MB4L+EgCRI14U4zRA==",
+ "version": "0.16.11",
+ "resolved": "https://registry.npmjs.org/@matter/protocol/-/protocol-0.16.11.tgz",
+ "integrity": "sha512-+Q6s+Cmvcm5BJEFBtS6m0vUVrHdxTBteDcJ+VfpNna1ST910371lVqtDwYFclqECQMlDYxoNjkfcYNv4pZfNPg==",
"license": "Apache-2.0",
"dependencies": {
- "@matter/general": "0.16.10",
- "@matter/model": "0.16.10",
- "@matter/types": "0.16.10"
+ "@matter/general": "0.16.11",
+ "@matter/model": "0.16.11",
+ "@matter/types": "0.16.11"
}
},
"node_modules/@matter/types": {
- "version": "0.16.10",
- "resolved": "https://registry.npmjs.org/@matter/types/-/types-0.16.10.tgz",
- "integrity": "sha512-AW86tGgL3sN1Vb76+03VPdQMsW9vWsaVGHe9agcED1sjtWRJBV17tcLDymAQ8k7fEeVqiy3qf9CUwFK1bhfXKQ==",
+ "version": "0.16.11",
+ "resolved": "https://registry.npmjs.org/@matter/types/-/types-0.16.11.tgz",
+ "integrity": "sha512-RcZk5N4AeoqKaLzlC6M6+J8YGJgxnLYpF/3WL7CeIM1DpA9ebkPQB9B8of+RJnqy8kgr6eqL/3ATmPGDA46fwg==",
"license": "Apache-2.0",
"dependencies": {
- "@matter/general": "0.16.10",
- "@matter/model": "0.16.10"
+ "@matter/general": "0.16.11",
+ "@matter/model": "0.16.11"
}
},
"node_modules/@noble/curves": {
@@ -133,16 +133,16 @@
}
},
"node_modules/@project-chip/matter.js": {
- "version": "0.16.10",
- "resolved": "https://registry.npmjs.org/@project-chip/matter.js/-/matter.js-0.16.10.tgz",
- "integrity": "sha512-5SpMsaNftqrqHSppP8J1RTdWdtJgehs3k9CVf0cM0IrZLQMK67W2cWVlTbsJElV7zOfKatjU56FdRA2UgkbvMQ==",
+ "version": "0.16.11",
+ "resolved": "https://registry.npmjs.org/@project-chip/matter.js/-/matter.js-0.16.11.tgz",
+ "integrity": "sha512-FAgJuh1uSWY7o+Hn0rVKS7i6+5crv3lGekwp002JoU5joty8jdNqMKUiSfwNtPGdYAkm5aMa7KTOaewHkx5taQ==",
"license": "Apache-2.0",
"dependencies": {
- "@matter/general": "0.16.10",
- "@matter/model": "0.16.10",
- "@matter/node": "0.16.10",
- "@matter/protocol": "0.16.10",
- "@matter/types": "0.16.10"
+ "@matter/general": "0.16.11",
+ "@matter/model": "0.16.11",
+ "@matter/node": "0.16.11",
+ "@matter/protocol": "0.16.11",
+ "@matter/types": "0.16.11"
}
},
"node_modules/bluebird": {
diff --git a/server/services/matter/package.json b/server/services/matter/package.json
index b696541e9d..97647f4661 100644
--- a/server/services/matter/package.json
+++ b/server/services/matter/package.json
@@ -12,8 +12,8 @@
"arm64"
],
"dependencies": {
- "@matter/main": "^0.16.10",
- "@project-chip/matter.js": "^0.16.10",
+ "@matter/main": "^0.16.11",
+ "@project-chip/matter.js": "^0.16.11",
"bluebird": "^3.7.2",
"fs-extra": "^11.3.0"
}
From 03cd3b1f73d754b3dba6a3b7d8b1d6f178bd29e7 Mon Sep 17 00:00:00 2001
From: Pierre-Gilles Leymarie <7365207+Pierre-Gilles@users.noreply.github.com>
Date: Fri, 10 Apr 2026 15:42:04 +0200
Subject: [PATCH 10/16] Set log level to debug in matter.js
---
server/services/matter/lib/matter.init.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/server/services/matter/lib/matter.init.js b/server/services/matter/lib/matter.init.js
index 7da45e27a4..6f150c2b27 100644
--- a/server/services/matter/lib/matter.init.js
+++ b/server/services/matter/lib/matter.init.js
@@ -35,7 +35,7 @@ async function init() {
// Set the log level to "notice"
// Log levels are defined here:
// https://github.com/project-chip/matter.js/blob/b0ffc2ff3c8acd7fef19918337d4fd95dfa466e6/packages/general/src/log/LogLevel.ts
- Logger.level = LogLevel('notice');
+ Logger.level = LogLevel('debug');
const storageService = environment.get(StorageService);
storageService.location = storagePath;
From c7256195f0034dacbfb8ee1bfb4caf681e8919e7 Mon Sep 17 00:00:00 2001
From: Pierre-Gilles Leymarie <7365207+Pierre-Gilles@users.noreply.github.com>
Date: Mon, 13 Apr 2026 14:18:18 +0200
Subject: [PATCH 11/16] Add new button to reset Matter integration
---
front/src/config/i18n/en.json | 11 ++-
front/src/config/i18n/fr.json | 11 ++-
.../all/matter/MatterSettingsPage.jsx | 82 ++++++++++++++++-
.../services/matter/api/matter.controller.js | 15 ++++
server/services/matter/lib/index.js | 2 +
server/services/matter/lib/matter.reset.js | 43 +++++++++
.../matter/api/matter.controller.test.js | 11 +++
.../services/matter/lib/matter.reset.test.js | 90 +++++++++++++++++++
8 files changed, 261 insertions(+), 4 deletions(-)
create mode 100644 server/services/matter/lib/matter.reset.js
create mode 100644 server/test/services/matter/lib/matter.reset.test.js
diff --git a/front/src/config/i18n/en.json b/front/src/config/i18n/en.json
index 9de1d41897..3469c9974e 100644
--- a/front/src/config/i18n/en.json
+++ b/front/src/config/i18n/en.json
@@ -2133,7 +2133,16 @@
"disabledWarningSettings": "Matter is not activated, please click on the button below to activate it.",
"enableButton": "Enable Matter",
"disableButton": "Disable Matter",
- "downloadNodesJson": "Download Nodes JSON"
+ "downloadNodesJson": "Download Nodes JSON",
+ "reset": {
+ "title": "Reset Integration",
+ "description": "Use this option if you want to start from scratch with Matter. This will delete all controller data, backup, and Matter folder.",
+ "button": "Reset",
+ "confirmMessage": "Warning, resetting the integration will delete all Matter controller data, backup, and Matter folder. All Matter devices currently paired will need to be re-paired.",
+ "confirmButton": "Yes, reset everything",
+ "cancelButton": "Cancel",
+ "error": "An error occurred while resetting the integration."
+ }
},
"device": {
"title": "Matter Devices",
diff --git a/front/src/config/i18n/fr.json b/front/src/config/i18n/fr.json
index aae0b1fcaf..1cf37f933d 100644
--- a/front/src/config/i18n/fr.json
+++ b/front/src/config/i18n/fr.json
@@ -2164,7 +2164,16 @@
"disabledWarningSettings": "Matter n'est pas activé, veuillez cliquer sur le bouton ci-dessous pour l'activer.",
"enableButton": "Activer Matter",
"disableButton": "Désactiver Matter",
- "downloadNodesJson": "Télécharger Noeuds Matter en JSON"
+ "downloadNodesJson": "Télécharger Noeuds Matter en JSON",
+ "reset": {
+ "title": "Réinitialiser l'intégration",
+ "description": "Utilisez cette option si vous souhaitez repartir de zéro avec Matter. Cela supprimera toutes les données du contrôleur, la sauvegarde et le dossier Matter.",
+ "button": "Réinitialiser",
+ "confirmMessage": "Attention, la réinitialisation de l'intégration supprimera toutes les données du contrôleur Matter, la sauvegarde et le dossier Matter. Tous les appareils Matter actuellement appairés devront être ré-appairés.",
+ "confirmButton": "Oui, tout réinitialiser",
+ "cancelButton": "Annuler",
+ "error": "Une erreur est survenue lors de la réinitialisation de l'intégration."
+ }
}
},
"mcp": {
diff --git a/front/src/routes/integration/all/matter/MatterSettingsPage.jsx b/front/src/routes/integration/all/matter/MatterSettingsPage.jsx
index 2dfe725d05..0d6f3e7b69 100644
--- a/front/src/routes/integration/all/matter/MatterSettingsPage.jsx
+++ b/front/src/routes/integration/all/matter/MatterSettingsPage.jsx
@@ -136,7 +136,10 @@ class MatterSettingsPage extends Component {
loadingNodes: true,
decommissioningNodes: {},
collapsedDevices: {},
- visibleKeys: {}
+ visibleKeys: {},
+ showConfirmReset: false,
+ resetting: false,
+ resetError: null
};
}
@@ -319,6 +322,29 @@ class MatterSettingsPage extends Component {
window.URL.revokeObjectURL(url);
};
+ showConfirmReset = () => {
+ this.setState({ showConfirmReset: true });
+ };
+
+ cancelReset = () => {
+ this.setState({ showConfirmReset: false });
+ };
+
+ confirmReset = async () => {
+ this.setState({ showConfirmReset: false, resetting: true, resetError: null });
+ try {
+ await this.props.httpClient.post('/api/v1/service/matter/reset');
+ this.setState({
+ resetting: false,
+ matterEnabled: false,
+ nodes: []
+ });
+ } catch (e) {
+ console.error(e);
+ this.setState({ resetting: false, resetError: true });
+ }
+ };
+
render() {
const {
matterEnabled,
@@ -330,7 +356,10 @@ class MatterSettingsPage extends Component {
decommissioningNodes,
collapsedDevices,
visibleKeys,
- hasIpv6
+ hasIpv6,
+ showConfirmReset,
+ resetting,
+ resetError
} = this.state;
return (
@@ -464,6 +493,55 @@ class MatterSettingsPage extends Component {
+