From 84a3e254d89841dc71805afb8fbb9f021a411570 Mon Sep 17 00:00:00 2001 From: Vincent MEURISSE Date: Fri, 27 Dec 2024 15:08:31 +0100 Subject: [PATCH] fix: correctly match manufacturerCode in findClusterNameByID Previous logic stopped on the first cluster with no manufacturerCode. Fixes Koenkk/zigbee2mqtt#25333 --- src/zspec/zcl/utils.ts | 30 ++++++++++++++++-------------- test/zspec/zcl/utils.test.ts | 8 ++++++-- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/zspec/zcl/utils.ts b/src/zspec/zcl/utils.ts index d4dade6017..1a78cdea0e 100644 --- a/src/zspec/zcl/utils.ts +++ b/src/zspec/zcl/utils.ts @@ -89,31 +89,33 @@ function findClusterNameByID( manufacturerCode: number | undefined, clusters: CustomClusters, ): [name: string | undefined, partialMatch: boolean] { - let name: string | undefined; - // if manufacturer code is given, consider partial match if didn't match against manufacturer code - let partialMatch = Boolean(manufacturerCode); + let matchingManufacturer: string | undefined; + let noManufacturer: string | undefined; + let anyManufacturer: string | undefined; for (const clusterName in clusters) { const cluster = clusters[clusterName as ClusterName]; if (cluster.ID === id) { - // priority on first match when matching only ID - if (name == undefined) { - name = clusterName; - } - + // When a manufacturerCode is requested, match the first cluster with matching manufacturerCode, if (manufacturerCode && cluster.manufacturerCode === manufacturerCode) { - name = clusterName; - partialMatch = false; - break; - } else if (!cluster.manufacturerCode) { - name = clusterName; + matchingManufacturer = clusterName; break; + + // Otherwise, match the first cluster with no manufacturerCode, + } else if (!noManufacturer && !cluster.manufacturerCode) { + noManufacturer = clusterName; + + // Finally, match the first cluster with a matching ID. + } else if (!anyManufacturer) { + anyManufacturer = clusterName; } } } - return [name, partialMatch]; + const exactMatch = (manufacturerCode && matchingManufacturer) || (!manufacturerCode && noManufacturer); + const clusterName = matchingManufacturer || noManufacturer || anyManufacturer; + return [clusterName, !exactMatch]; } function getClusterDefinition( diff --git a/test/zspec/zcl/utils.test.ts b/test/zspec/zcl/utils.test.ts index 096797450e..029e1c7228 100644 --- a/test/zspec/zcl/utils.test.ts +++ b/test/zspec/zcl/utils.test.ts @@ -55,8 +55,12 @@ describe('ZCL Utils', () => { ], [ 'by ID with matching manufacturer code', - {key: Zcl.Clusters.sprutDevice.ID, manufacturerCode: Zcl.Clusters.sprutDevice.manufacturerCode!, customClusters: {}}, - {cluster: Zcl.Clusters.sprutDevice, name: 'sprutDevice'}, + { + key: Zcl.Clusters.manuSpecificNodOnPilotWire.ID, + manufacturerCode: Zcl.Clusters.manuSpecificNodOnPilotWire.manufacturerCode!, + customClusters: {}, + }, + {cluster: Zcl.Clusters.manuSpecificNodOnPilotWire, name: 'manuSpecificNodOnPilotWire'}, ], [ 'custom by ID',