From 12b148fae8a276a58a2f4edd774bccdc096bccb8 Mon Sep 17 00:00:00 2001 From: AlCalzone Date: Sat, 30 Jan 2021 16:03:45 +0100 Subject: [PATCH] feat: add compat flag to remove support of CCs (#1531) --- docs/development/config-files.md | 21 +++++++ maintenance/schemas/device-config.json | 25 ++++++++ .../devices/0x000c/hs-wd200_0.0-5.9.json | 11 ++++ .../config/devices/0x000c/hs-wd200_5.11.json | 11 ++++ packages/config/src/CompatConfig.ts | 57 +++++++++++++++++++ packages/zwave-js/src/lib/node/Node.ts | 15 +++++ 6 files changed, 140 insertions(+) diff --git a/docs/development/config-files.md b/docs/development/config-files.md index 28fca9cea0a..e41f624d0a7 100644 --- a/docs/development/config-files.md +++ b/docs/development/config-files.md @@ -187,6 +187,27 @@ If a device does not report some CCs in its NIF, this can be used to add them. T } ``` +### `commandClasses.remove` + +If a device reports support for a CCs but does not correctly support it, this can be used to remove them. This property has the following shape: + +```json +"compat": { + "commandClasses": { + "remove": { + // Removes the CC Anti-Theft from the node and all endpoints + "0x5d": { + "endpoints": "*" + }, + // Removes the CC Battery from the node (endpoint 0) and endpoint 2 + "0x80": { + "endpoints": [0, 2] + } + } + } +} +``` + ### `disableBasicMapping` By default, received `Basic` commands are mapped to a more appropriate CC. Setting `disableBasicMapping` to `true` disables this feature. diff --git a/maintenance/schemas/device-config.json b/maintenance/schemas/device-config.json index 4dc29d7544c..1273a991bda 100644 --- a/maintenance/schemas/device-config.json +++ b/maintenance/schemas/device-config.json @@ -228,6 +228,31 @@ } }, "additionalProperties": false + }, + "remove": { + "type": "object", + "patternProperties": { + "^(0x)?[0-9a-f]+$": { + "type": "object", + "properties": { + "endpoints": { + "anyOf": [ + { "const": "*" }, + { + "type": "array", + "items": { + "type": "integer", + "minimum": 0 + }, + "minItems": 1 + } + ] + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false } }, "additionalProperties": false diff --git a/packages/config/config/devices/0x000c/hs-wd200_0.0-5.9.json b/packages/config/config/devices/0x000c/hs-wd200_0.0-5.9.json index 85d13cb3700..856e0ae10c4 100644 --- a/packages/config/config/devices/0x000c/hs-wd200_0.0-5.9.json +++ b/packages/config/config/devices/0x000c/hs-wd200_0.0-5.9.json @@ -643,5 +643,16 @@ } ] } + }, + "compat": { + "commandClasses": { + "remove": { + "0x6c": { + // The device reports that it supports Supervision, but it does not support all + // commands supervision-encapsulated + "endpoints": "*" + } + } + } } } diff --git a/packages/config/config/devices/0x000c/hs-wd200_5.11.json b/packages/config/config/devices/0x000c/hs-wd200_5.11.json index 7d628156b04..f4f4d414d5b 100644 --- a/packages/config/config/devices/0x000c/hs-wd200_5.11.json +++ b/packages/config/config/devices/0x000c/hs-wd200_5.11.json @@ -643,5 +643,16 @@ } ] } + }, + "compat": { + "commandClasses": { + "remove": { + "0x6c": { + // The device reports that it supports Supervision, but it does not support all + // commands supervision-encapsulated + "endpoints": "*" + } + } + } } } diff --git a/packages/config/src/CompatConfig.ts b/packages/config/src/CompatConfig.ts index a60b6bfd420..8b326928926 100644 --- a/packages/config/src/CompatConfig.ts +++ b/packages/config/src/CompatConfig.ts @@ -222,10 +222,67 @@ All values in compat option commandClasses.add must be objects`, } this.addCCs = addCCs; } + + if (definition.commandClasses.remove != undefined) { + if (!isObject(definition.commandClasses.remove)) { + throwInvalidConfig( + "devices", + `config/devices/${filename}: +error in compat option commandClasses.remove`, + ); + } else if ( + !Object.keys(definition.commandClasses.remove).every((k) => + hexKeyRegex2Digits.test(k), + ) + ) { + throwInvalidConfig( + "devices", + `config/devices/${filename}: +All keys in compat option commandClasses.remove must be 2-digit hex numbers!`, + ); + } + + const removeCCs = new Map< + CommandClasses, + "*" | readonly number[] + >(); + for (const [cc, info] of Object.entries( + definition.commandClasses.remove, + )) { + if (isObject(info) && "endpoints" in info) { + if ( + info.endpoints === "*" || + (isArray(info.endpoints) && + info.endpoints.every( + (i) => typeof i === "number", + )) + ) { + removeCCs.set(parseInt(cc), info.endpoints as any); + } else { + throwInvalidConfig( + "devices", + `config/devices/${filename}: +Compat option commandClasses.remove has an invalid "endpoints" property. Only "*" and numeric arrays are allowed!`, + ); + } + } else { + throwInvalidConfig( + "devices", + `config/devices/${filename}: +All values in compat option commandClasses.remove must be objects with an "endpoints" property!`, + ); + } + } + this.removeCCs = removeCCs; + } } } public readonly addCCs?: ReadonlyMap; + public readonly removeCCs?: ReadonlyMap< + CommandClasses, + "*" | readonly number[] + >; public readonly disableBasicMapping?: boolean; public readonly overrideFloatEncoding?: { size?: number; diff --git a/packages/zwave-js/src/lib/node/Node.ts b/packages/zwave-js/src/lib/node/Node.ts index 833d5a08891..31d3ec0c993 100644 --- a/packages/zwave-js/src/lib/node/Node.ts +++ b/packages/zwave-js/src/lib/node/Node.ts @@ -1673,6 +1673,21 @@ version: ${this.version}`; } } } + // And remove those that it marks as unsupported + const removeCCs = this.deviceConfig.compat?.removeCCs; + if (removeCCs) { + for (const [cc, endpoints] of removeCCs) { + if (endpoints === "*") { + for (const ep of this.getAllEndpoints()) { + ep.removeCC(cc); + } + } else { + for (const ep of endpoints) { + this.getEndpoint(ep)?.removeCC(cc); + } + } + } + } } await this.setInterviewStage(InterviewStage.OverwriteConfig);