From c4cfd889e42767ad600dd5ffde1efe3b23f043e2 Mon Sep 17 00:00:00 2001 From: Ingo Fischer Date: Sat, 25 Jan 2025 13:59:54 +0100 Subject: [PATCH] Updates 25.01.24 * Fixed Thermostat initialization logic and added more logging * Updated matter.js for further optimizations --- README.md | 5 + package-lock.json | 118 +++++++++---------- package.json | 8 +- src-admin/package-lock.json | 4 +- src/matter/to-matter/ThermostatToMatter.ts | 131 +++++++++------------ 5 files changed, 126 insertions(+), 140 deletions(-) diff --git a/README.md b/README.md index c7277a7..8b3cac0 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,11 @@ With the ioBroker Matter Adapter it is possible to map the following use cases: --> ## Changelog + +### __WORK IN PROGRESS__ +* (@Apollon77) Fixed Thermostat initialization logic and added more logging +* (@Apollon77) Updated matter.js for further optimizations + ### 0.4.4 (2025-01-24) * (@Apollon77) Added OPEN state for all Door Locks to open door again * (@Apollon77) Fixed Thermostat initialization when no AUTO mode is supported diff --git a/package-lock.json b/package-lock.json index 65ccaf8..b6a668d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,9 +13,9 @@ "@iobroker/dm-utils": "^1.0.7", "@iobroker/i18n": "^0.3.1", "@iobroker/type-detector": "^4.1.1", - "@matter/main": "0.12.0", - "@matter/nodejs": "0.12.0", - "@project-chip/matter.js": "0.12.0", + "@matter/main": "0.12.1", + "@matter/nodejs": "0.12.1", + "@project-chip/matter.js": "0.12.1", "axios": "^1.7.9", "jsonwebtoken": "^9.0.2" }, @@ -40,7 +40,7 @@ "node": ">=18" }, "optionalDependencies": { - "@matter/nodejs-ble": "0.12.0" + "@matter/nodejs-ble": "0.12.1" } }, "node_modules/@alcalzone/pak": { @@ -874,64 +874,64 @@ } }, "node_modules/@matter/general": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@matter/general/-/general-0.12.0.tgz", - "integrity": "sha512-D6XkH/17qbvbNclw8IG82QzBGXGkDTBCaHe3zIDsMBraVUcQzKbTFrSQIP4tzqU6R2NC7nkmMsqFBV7HRVwwyQ==", + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@matter/general/-/general-0.12.1.tgz", + "integrity": "sha512-26ZnXpcPeKUJ3xGJvJnkM7dMt32IlJ+5ZCoM8KN2FtXC2Z6EUBJMVxjSxXA4Wbg91wZvj/y/z0xkcEI3gcIOAA==", "license": "Apache-2.0", "dependencies": { "@noble/curves": "^1.8.1" } }, "node_modules/@matter/main": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@matter/main/-/main-0.12.0.tgz", - "integrity": "sha512-cqliR5nnFJCEXKUKcwI9rxPZQNcrJ8iFpd6bOOEQ2v85+dYFZGDOxOWHMo70EoQOqsu7lGozGWRq4m642iXIRw==", + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@matter/main/-/main-0.12.1.tgz", + "integrity": "sha512-TQscTaFzgtUy9R+tNDm1aIViW4qDiXVdnYZGTVWjWqPN/7wOtEO2IgwP3xk9c3bHNkEXPux6TfvPoAx7UkYUng==", "license": "Apache-2.0", "dependencies": { - "@matter/general": "0.12.0", - "@matter/model": "0.12.0", - "@matter/node": "0.12.0", - "@matter/protocol": "0.12.0", - "@matter/types": "0.12.0", + "@matter/general": "0.12.1", + "@matter/model": "0.12.1", + "@matter/node": "0.12.1", + "@matter/protocol": "0.12.1", + "@matter/types": "0.12.1", "@noble/curves": "^1.8.1" }, "optionalDependencies": { - "@matter/nodejs": "0.12.0" + "@matter/nodejs": "0.12.1" } }, "node_modules/@matter/model": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@matter/model/-/model-0.12.0.tgz", - "integrity": "sha512-uJhdwWpSFV0wl84Q9nIj1Je8y2Y223XEqomVRNlzDEK450MxaQ/MAK1nEvi3BBTvoiNvAtSij+pIrzu5fYxnlg==", + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@matter/model/-/model-0.12.1.tgz", + "integrity": "sha512-UlUR7iRuBRadfuf4Qwo3OYi7WUrXJk4nddqsD2tBq7y1cA5zsnV3E85zVX/8iiiUSqAbx3rcAuWJ+CCjn0ikUA==", "license": "Apache-2.0", "dependencies": { - "@matter/general": "0.12.0", + "@matter/general": "0.12.1", "@noble/curves": "^1.8.1" } }, "node_modules/@matter/node": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@matter/node/-/node-0.12.0.tgz", - "integrity": "sha512-J/wQaXSuN3/fZnyTpOE8brmv5mZE2co2yajTg9DmZDgi0EXWXCF97+2vemlPh6BXAszDas7FdN/1kXu2MEA9/Q==", + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@matter/node/-/node-0.12.1.tgz", + "integrity": "sha512-PtN1pRmMynPwwxaSZklCDwLt4uCz1o/moXi0PX2DU866JdkHaKPgLi+29PcalcDB2dMZbrcJTaimAhXcjPVkog==", "license": "Apache-2.0", "dependencies": { - "@matter/general": "0.12.0", - "@matter/model": "0.12.0", - "@matter/protocol": "0.12.0", - "@matter/types": "0.12.0", + "@matter/general": "0.12.1", + "@matter/model": "0.12.1", + "@matter/protocol": "0.12.1", + "@matter/types": "0.12.1", "@noble/curves": "^1.8.1" } }, "node_modules/@matter/nodejs": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@matter/nodejs/-/nodejs-0.12.0.tgz", - "integrity": "sha512-VZtZcW2UzXiAnYAwJ+9XPDqCfO3amlzgCPBDTXpUKti4HrO0v6U5LmydNRGoGkNUB9QABxLpiAmEId+URZ2r9Q==", + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@matter/nodejs/-/nodejs-0.12.1.tgz", + "integrity": "sha512-G4tPCzaCJMuly0yiIf+eOhz1ezSQQarETFtDuImE+9vicVyKKCL1eq5SviV5nx9DikIcalKMbKh6F6t21sslDA==", "license": "Apache-2.0", "dependencies": { - "@matter/general": "0.12.0", - "@matter/node": "0.12.0", - "@matter/protocol": "0.12.0", - "@matter/types": "0.12.0", + "@matter/general": "0.12.1", + "@matter/node": "0.12.1", + "@matter/protocol": "0.12.1", + "@matter/types": "0.12.1", "node-localstorage": "^3.0.5" }, "engines": { @@ -939,15 +939,15 @@ } }, "node_modules/@matter/nodejs-ble": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@matter/nodejs-ble/-/nodejs-ble-0.12.0.tgz", - "integrity": "sha512-Tz7ugttTnKAiSyj0ZtE3cr9n0fm1fcII3/8/YBllS4xEcMZQlsLEc/3qncIrN6ca16U71IcJ1r9gMLkHwf2wlA==", + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@matter/nodejs-ble/-/nodejs-ble-0.12.1.tgz", + "integrity": "sha512-AyDLb9cNAp0jiWPSR0vl3UAVRBgQfoO706y490QZ2UXddsotEAWzTkcYSYYi1M6Yp61nCxAQGIuHYbW8XtraAA==", "license": "Apache-2.0", "optional": true, "dependencies": { - "@matter/general": "0.12.0", - "@matter/protocol": "0.12.0", - "@matter/types": "0.12.0" + "@matter/general": "0.12.1", + "@matter/protocol": "0.12.1", + "@matter/types": "0.12.1" }, "engines": { "node": ">=18.0.0" @@ -958,25 +958,25 @@ } }, "node_modules/@matter/protocol": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@matter/protocol/-/protocol-0.12.0.tgz", - "integrity": "sha512-wtDZR/APxMWdf7hErRshWlgnjisnID66GQ9Xxlkq6U1BciXf8qIb8UyWxKN6LWWUhOLPJe6rcn8SnXt6t/q1mA==", + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@matter/protocol/-/protocol-0.12.1.tgz", + "integrity": "sha512-HOa5OdMsmmSjmtYA+wmBmS2poUeZqlcoA9fUk40kWla6yINJOyHZCgnPKARxXxm1qk95BEoLN3ovUIKoajkstQ==", "license": "Apache-2.0", "dependencies": { - "@matter/general": "0.12.0", - "@matter/model": "0.12.0", - "@matter/types": "0.12.0", + "@matter/general": "0.12.1", + "@matter/model": "0.12.1", + "@matter/types": "0.12.1", "@noble/curves": "^1.8.1" } }, "node_modules/@matter/types": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@matter/types/-/types-0.12.0.tgz", - "integrity": "sha512-tS5amwLRymfnqMuVwJ+xYkXGthoBpYb6Dg6GE1IKvZeccl3xGQIYEvIw0rB806h/WkK97T6mB39hHNHliMLAIg==", + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@matter/types/-/types-0.12.1.tgz", + "integrity": "sha512-O4zyMGLUnoWQZ7P5TJDWrtTpdaG8xSDq1a5xO3e8pmc3I9w6LSoKciEqrjFvq9lT6gvj3hcts/64c0Rxn7NEIw==", "license": "Apache-2.0", "dependencies": { - "@matter/general": "0.12.0", - "@matter/model": "0.12.0", + "@matter/general": "0.12.1", + "@matter/model": "0.12.1", "@noble/curves": "^1.8.1" } }, @@ -1139,16 +1139,16 @@ } }, "node_modules/@project-chip/matter.js": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@project-chip/matter.js/-/matter.js-0.12.0.tgz", - "integrity": "sha512-7WO7/h4eIOApXYd6ZGFkNp5GlDScQPpqDJALJCnUbB2Z6+d01PpJ9d6Q2Z7OC/vooCXod/nebyj2YCQtGK7VOQ==", + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@project-chip/matter.js/-/matter.js-0.12.1.tgz", + "integrity": "sha512-IPNbBxnduNUNoipn4ZHXWE8gEsYM9nryYvWXlLYWwTJ6tDTIR0oZmsUZzhJoDXjShqbXolYJ8bCkFQ7dfMba6w==", "license": "Apache-2.0", "dependencies": { - "@matter/general": "0.12.0", - "@matter/model": "0.12.0", - "@matter/node": "0.12.0", - "@matter/protocol": "0.12.0", - "@matter/types": "0.12.0", + "@matter/general": "0.12.1", + "@matter/model": "0.12.1", + "@matter/node": "0.12.1", + "@matter/protocol": "0.12.1", + "@matter/types": "0.12.1", "@noble/curves": "^1.8.1" } }, diff --git a/package.json b/package.json index c0dfeff..38fe06f 100644 --- a/package.json +++ b/package.json @@ -23,16 +23,16 @@ "url": "https://github.com/ioBroker/ioBroker.matter" }, "optionalDependencies": { - "@matter/nodejs-ble": "0.12.0" + "@matter/nodejs-ble": "0.12.1" }, "dependencies": { "@iobroker/adapter-core": "^3.2.3", "@iobroker/i18n": "^0.3.1", "@iobroker/dm-utils": "^1.0.7", "@iobroker/type-detector": "^4.1.1", - "@matter/main": "0.12.0", - "@matter/nodejs": "0.12.0", - "@project-chip/matter.js": "0.12.0", + "@matter/main": "0.12.1", + "@matter/nodejs": "0.12.1", + "@project-chip/matter.js": "0.12.1", "axios": "^1.7.9", "jsonwebtoken": "^9.0.2" }, diff --git a/src-admin/package-lock.json b/src-admin/package-lock.json index 02ca7c6..c43fcc6 100644 --- a/src-admin/package-lock.json +++ b/src-admin/package-lock.json @@ -1,12 +1,12 @@ { "name": "iobroker.matter", - "version": "0.4.3", + "version": "0.4.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "iobroker.matter", - "version": "0.4.3", + "version": "0.4.4", "dependencies": { "@foxriver76/iob-component-lib": "^0.2.0", "@iobroker/adapter-react-v5": "^7.4.17", diff --git a/src/matter/to-matter/ThermostatToMatter.ts b/src/matter/to-matter/ThermostatToMatter.ts index 286d5d4..7276c12 100644 --- a/src/matter/to-matter/ThermostatToMatter.ts +++ b/src/matter/to-matter/ThermostatToMatter.ts @@ -18,6 +18,7 @@ export class ThermostatToMatter extends GenericDeviceToMatter { readonly #matterEndpointThermostat: Endpoint; readonly #matterEndpointHumidity?: Endpoint; #supportedModes = new Array(); + #validModes = new Array(); constructor(ioBrokerDevice: Thermostat, name: string, uuid: string) { super(name, uuid); @@ -31,10 +32,12 @@ export class ThermostatToMatter extends GenericDeviceToMatter { switch (mode) { case ThermostatMode.Heat: this.#supportedModes.push(ThermostatMode.Heat); + this.#validModes.push(ThermostatMode.Heat); clusterModes.push(MatterThermostat.Feature.Heating); break; case ThermostatMode.Cool: this.#supportedModes.push(ThermostatMode.Cool); + this.#validModes.push(ThermostatMode.Cool); clusterModes.push(MatterThermostat.Feature.Cooling); break; case ThermostatMode.Auto: @@ -42,12 +45,15 @@ export class ThermostatToMatter extends GenericDeviceToMatter { break; case ThermostatMode.Off: this.#supportedModes.push(ThermostatMode.Off); + this.#validModes.push(ThermostatMode.Off); break; case ThermostatMode.FanOnly: this.#supportedModes.push(ThermostatMode.FanOnly); + this.#validModes.push(ThermostatMode.FanOnly); break; case ThermostatMode.Dry: this.#supportedModes.push(ThermostatMode.Dry); + this.#validModes.push(ThermostatMode.Dry); break; default: ignoredModes.push(mode); @@ -60,6 +66,7 @@ export class ThermostatToMatter extends GenericDeviceToMatter { ) { clusterModes.push(MatterThermostat.Feature.AutoMode); this.#supportedModes.push(ThermostatMode.Auto); + this.#validModes.push(ThermostatMode.Auto); } else { // Auto mode requires Heating and cooling to be supported too this.#ioBrokerDevice.adapter.log.info( @@ -68,7 +75,7 @@ export class ThermostatToMatter extends GenericDeviceToMatter { } if ( - !clusterModes.includes(MatterThermostat.Feature.Heating) || + !clusterModes.includes(MatterThermostat.Feature.Heating) && !clusterModes.includes(MatterThermostat.Feature.Cooling) ) { // When no mode is there tell that it is a Heating thermostat @@ -76,12 +83,19 @@ export class ThermostatToMatter extends GenericDeviceToMatter { `${uuid}: Matter Thermostats need to either support heating or cooling. Defaulting to Heating`, ); clusterModes.push(MatterThermostat.Feature.Heating); + this.#supportedModes.push(ThermostatMode.Heat); } if (ignoredModes.length > 0) { this.#ioBrokerDevice.adapter.log.info( `${uuid}: Ignoring unsupported modes for Thermostat: ${ignoredModes.join(', ')}`, ); } + this.#ioBrokerDevice.adapter.log.info( + `Mapped Thermostat Modes "${this.#supportedModes.join('","')}" to Matter Features "${clusterModes.map(feature => MatterThermostat.Feature[feature]).join('","')}"`, + ); + this.#ioBrokerDevice.adapter.log.info( + `Valid Modes the adapter will react on from ioBroker Device: ${this.#validModes.length ? `"${this.#validModes.join('","')}"` : 'None, Mode state is ignored'}`, + ); const hasHeating = clusterModes.includes(MatterThermostat.Feature.Heating); const hasCooling = clusterModes.includes(MatterThermostat.Feature.Cooling); @@ -105,10 +119,10 @@ export class ThermostatToMatter extends GenericDeviceToMatter { controlSequenceOfOperation: hasHeating && hasCooling ? MatterThermostat.ControlSequenceOfOperation.CoolingAndHeating - : hasHeating - ? MatterThermostat.ControlSequenceOfOperation.HeatingOnly - : MatterThermostat.ControlSequenceOfOperation.CoolingOnly, - minSetpointDeadBand: this.#supportedModes.includes(ThermostatMode.Auto) ? 0 : undefined, + : hasCooling + ? MatterThermostat.ControlSequenceOfOperation.CoolingOnly + : MatterThermostat.ControlSequenceOfOperation.HeatingOnly, + minSetpointDeadBand: clusterModes.includes(MatterThermostat.Feature.AutoMode) ? 0 : undefined, absMinHeatSetpointLimit: hasHeating ? this.convertTemperatureValue(7) : undefined, absMaxHeatSetpointLimit: hasHeating ? this.convertTemperatureValue(30) : undefined, absMinCoolSetpointLimit: hasCooling ? this.convertTemperatureValue(16) : undefined, @@ -145,6 +159,24 @@ export class ThermostatToMatter extends GenericDeviceToMatter { return parseFloat((value / 100).toFixed(2)); } + #mapModeToMatter(mode: ThermostatMode | undefined): MatterThermostat.SystemMode | undefined { + if (mode === undefined || !this.#validModes.includes(mode)) { + return; + } + switch (mode) { + case ThermostatMode.Heat: + return MatterThermostat.SystemMode.Heat; + case ThermostatMode.Cool: + return MatterThermostat.SystemMode.Cool; + case ThermostatMode.Auto: + return MatterThermostat.SystemMode.Auto; + case ThermostatMode.FanOnly: + return MatterThermostat.SystemMode.FanOnly; + case ThermostatMode.Dry: + return MatterThermostat.SystemMode.Dry; + } + } + async registerHandlersAndInitialize(): Promise { await super.registerHandlersAndInitialize(); @@ -154,31 +186,17 @@ export class ThermostatToMatter extends GenericDeviceToMatter { ? MatterThermostat.SystemMode.Off : undefined; if (systemMode === undefined && this.#ioBrokerDevice.hasMode()) { - const mode = this.#ioBrokerDevice.getMode(); - if (mode && this.#supportedModes.includes(mode)) { - switch (this.#ioBrokerDevice.getMode()) { - case ThermostatMode.Heat: - systemMode = MatterThermostat.SystemMode.Heat; - break; - case ThermostatMode.Cool: - systemMode = MatterThermostat.SystemMode.Cool; - break; - case ThermostatMode.Auto: - systemMode = MatterThermostat.SystemMode.Auto; - break; - case ThermostatMode.FanOnly: - systemMode = MatterThermostat.SystemMode.FanOnly; - break; - case ThermostatMode.Dry: - systemMode = MatterThermostat.SystemMode.Dry; - break; - } - } + systemMode = this.#mapModeToMatter(this.#ioBrokerDevice.getMode()); } if (systemMode === undefined) { systemMode = this.#supportedModes.includes(ThermostatMode.Heat) ? MatterThermostat.SystemMode.Heat - : MatterThermostat.SystemMode.Cool; + : this.#supportedModes.includes(ThermostatMode.Cool) + ? MatterThermostat.SystemMode.Cool + : undefined; + if (systemMode === undefined) { + this.#ioBrokerDevice.adapter.log.error(`${this.uuid}: Could not determine SystemMode`); + } } const controlSequenceOfOperation = this.#supportedModes.includes(ThermostatMode.Heat) && this.#supportedModes.includes(ThermostatMode.Cool) @@ -222,7 +240,7 @@ export class ThermostatToMatter extends GenericDeviceToMatter { await this.#ioBrokerDevice.setPower(false); break; case MatterThermostat.SystemMode.Heat: { - if (this.#ioBrokerDevice.hasMode()) { + if (this.#ioBrokerDevice.hasMode() && this.#validModes.includes(ThermostatMode.Heat)) { await this.#ioBrokerDevice.setMode(ThermostatMode.Heat); } const heatingTemp = @@ -234,7 +252,7 @@ export class ThermostatToMatter extends GenericDeviceToMatter { break; } case MatterThermostat.SystemMode.Cool: { - if (this.#ioBrokerDevice.hasMode()) { + if (this.#ioBrokerDevice.hasMode() && this.#validModes.includes(ThermostatMode.Cool)) { await this.#ioBrokerDevice.setMode(ThermostatMode.Cool); } const coolingTemp = @@ -246,20 +264,17 @@ export class ThermostatToMatter extends GenericDeviceToMatter { break; } case MatterThermostat.SystemMode.Auto: - if (this.#ioBrokerDevice.hasMode()) { + if (this.#ioBrokerDevice.hasMode() && this.#validModes.includes(ThermostatMode.Auto)) { await this.#ioBrokerDevice.setMode(ThermostatMode.Auto); } break; case MatterThermostat.SystemMode.FanOnly: - if ( - this.#ioBrokerDevice.hasMode() && - this.#ioBrokerDevice.getMode() !== ThermostatMode.FanOnly - ) { + if (this.#ioBrokerDevice.hasMode() && this.#validModes.includes(ThermostatMode.FanOnly)) { await this.#ioBrokerDevice.setMode(ThermostatMode.FanOnly); } break; case MatterThermostat.SystemMode.Dry: - if (this.#ioBrokerDevice.hasMode()) { + if (this.#ioBrokerDevice.hasMode() && this.#validModes.includes(ThermostatMode.Dry)) { await this.#ioBrokerDevice.setMode(ThermostatMode.Dry); } break; @@ -328,26 +343,11 @@ export class ThermostatToMatter extends GenericDeviceToMatter { let systemMode = event.value ? undefined : MatterThermostat.SystemMode.Off; if (event.value && this.#ioBrokerDevice.hasMode()) { const mode = this.#ioBrokerDevice.getMode(); - if (!mode || !this.#supportedModes.includes(mode)) { + const mappedMode = this.#mapModeToMatter(mode); + if (mappedMode == undefined) { return; } - switch (mode) { - case ThermostatMode.Heat: - systemMode = MatterThermostat.SystemMode.Heat; - break; - case ThermostatMode.Cool: - systemMode = MatterThermostat.SystemMode.Cool; - break; - case ThermostatMode.Auto: - systemMode = MatterThermostat.SystemMode.Auto; - break; - case ThermostatMode.FanOnly: - systemMode = MatterThermostat.SystemMode.FanOnly; - break; - case ThermostatMode.Dry: - systemMode = MatterThermostat.SystemMode.Dry; - break; - } + systemMode = mappedMode; } if (systemMode !== undefined) { await this.#matterEndpointThermostat.setStateOf(IoThermostatServer, { @@ -361,31 +361,12 @@ export class ThermostatToMatter extends GenericDeviceToMatter { // it is turned off, so do not report any mode changes return; } - if (!this.#supportedModes.includes(event.value as ThermostatMode)) { + if (!this.#validModes.length) { return; } - let systemMode: MatterThermostat.SystemMode; - switch (event.value) { - case ThermostatMode.Heat: - systemMode = MatterThermostat.SystemMode.Heat; - break; - case ThermostatMode.Cool: - systemMode = MatterThermostat.SystemMode.Cool; - break; - case ThermostatMode.Off: - systemMode = MatterThermostat.SystemMode.Off; - break; - case ThermostatMode.Auto: - systemMode = MatterThermostat.SystemMode.Auto; - break; - case ThermostatMode.FanOnly: - systemMode = MatterThermostat.SystemMode.FanOnly; - break; - case ThermostatMode.Dry: - systemMode = MatterThermostat.SystemMode.Dry; - break; - default: - return; + const systemMode = this.#mapModeToMatter(event.value as ThermostatMode); + if (systemMode === undefined) { + return; } await this.#matterEndpointThermostat.setStateOf(IoThermostatServer, { systemMode,