From 1802a41734bdd0788962e99a476b84c30f37dd13 Mon Sep 17 00:00:00 2001 From: Ingo Fischer Date: Sat, 1 Feb 2025 16:40:31 +0100 Subject: [PATCH 1/4] DoorLock DoorState --- src/matter/to-iobroker/DoorLockToIoBroker.ts | 10 ++++-- src/matter/to-matter/LockToMatter.ts | 33 ++++++++++++++++++-- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/matter/to-iobroker/DoorLockToIoBroker.ts b/src/matter/to-iobroker/DoorLockToIoBroker.ts index 39b7b7f..847c94b 100644 --- a/src/matter/to-iobroker/DoorLockToIoBroker.ts +++ b/src/matter/to-iobroker/DoorLockToIoBroker.ts @@ -33,7 +33,6 @@ export class DoorLockToIoBroker extends GenericElectricityDataDeviceToIoBroker { this.#unboltingSupported = this.appEndpoint.getClusterClient(DoorLock.Complete)?.supportedFeatures.unbolting ?? false; - // TODO: support more featuresets? this.#ioBrokerDevice = new Lock( { ...ChannelDetector.getPatterns().lock, isIoBrokerDevice: false } as DetectedDevice, adapter, @@ -65,13 +64,20 @@ export class DoorLockToIoBroker extends GenericElectricityDataDeviceToIoBroker { endpointId: this.appEndpoint.getNumber(), clusterId: DoorLock.Cluster.id, attributeName: 'lockState', - convertValue: value => value === DoorLock.LockState.Unlocked, + convertValue: (state: DoorLock.LockState | null) => state === DoorLock.LockState.Unlocked, }); this.enableDeviceTypeStateForAttribute(PropertyType.Open, { changeHandler: async () => { await this.appEndpoint.getClusterClient(DoorLock.Complete)?.unlockDoor({}); }, }); + this.enableDeviceTypeStateForAttribute(PropertyType.DoorState, { + endpointId: this.appEndpoint.getNumber(), + clusterId: DoorLock.Cluster.id, + attributeName: 'doorState', + convertValue: (state: DoorLock.DoorState | null) => + state === DoorLock.DoorState.DoorOpen || state === DoorLock.DoorState.DoorForcedOpen, + }); return super.enableDeviceTypeStates(); } diff --git a/src/matter/to-matter/LockToMatter.ts b/src/matter/to-matter/LockToMatter.ts index 9693900..070b51e 100644 --- a/src/matter/to-matter/LockToMatter.ts +++ b/src/matter/to-matter/LockToMatter.ts @@ -17,7 +17,8 @@ const IoBrokerDoorLockDevice = DoorLockDevice.with( ); type IoBrokerDoorLockDevice = typeof IoBrokerDoorLockDevice; -// TODO Add Latching support when "Open" is there! +//const DoorPositionDoorLockServer = EventedDoorLockServer.with(DoorLock.Feature.DoorPositionSensor); +//const UnboltingDoorLockServer = EventedDoorLockServer.with(DoorLock.Feature.Unbolting); /** Mapping Logic to map a ioBroker Light device to a Matter OnOffLightDevice. */ export class LockToMatter extends GenericElectricityDataDeviceToMatter { @@ -27,7 +28,18 @@ export class LockToMatter extends GenericElectricityDataDeviceToMatter { constructor(ioBrokerDevice: Lock, name: string, uuid: string) { super(name, uuid); - this.#matterEndpoint = new Endpoint(IoBrokerDoorLockDevice, { + this.#ioBrokerDevice = ioBrokerDevice; + + const features = new Array(); + + if (this.#ioBrokerDevice.hasOpen()) { + features.push(DoorLock.Feature.Unbolting); + } + if (this.#ioBrokerDevice.hasDoorState()) { + features.push(DoorLock.Feature.DoorPositionSensor); + } + + this.#matterEndpoint = new Endpoint(IoBrokerDoorLockDevice.with(EventedDoorLockServer.with(...features)), { id: uuid, ioBrokerContext: { device: ioBrokerDevice, @@ -37,9 +49,10 @@ export class LockToMatter extends GenericElectricityDataDeviceToMatter { lockType: DoorLock.LockType.Other, actuatorEnabled: true, lockState: DoorLock.LockState.Locked, // Will be corrected later + // @ts-expect-error Simplify state setting because of dynamic features + doorState: this.#ioBrokerDevice.hasDoorState() ? DoorLock.DoorState.DoorClosed : undefined, }, }); - this.#ioBrokerDevice = ioBrokerDevice; } get matterEndpoints(): Endpoint[] { @@ -61,6 +74,14 @@ export class LockToMatter extends GenericElectricityDataDeviceToMatter { : DoorLock.LockState.Locked, }, }); + if (this.#ioBrokerDevice.hasDoorState()) { + await this.#matterEndpoint.setStateOf(EventedDoorLockServer, { + // @ts-expect-error Workaround a matter.js instancing/typing error + doorState: this.#ioBrokerDevice.getDoorState() + ? DoorLock.DoorState.DoorOpen + : DoorLock.DoorState.DoorClosed, + }); + } this.matterEvents.on(this.#matterEndpoint.events.ioBrokerEvents.doorLockStateControlled, async state => { switch (state) { @@ -92,6 +113,12 @@ export class LockToMatter extends GenericElectricityDataDeviceToMatter { }, }); break; + case PropertyType.DoorState: + await this.#matterEndpoint.setStateOf(EventedDoorLockServer, { + // @ts-expect-error Workaround a matter.js instancing/typing error + doorState: event.value ? DoorLock.DoorState.DoorOpen : DoorLock.DoorState.DoorClosed, + }); + break; } }); } From 2e00776a27428f934c941109965895bc79870bdf Mon Sep 17 00:00:00 2001 From: Ingo Fischer Date: Sat, 1 Feb 2025 16:40:48 +0100 Subject: [PATCH 2/4] Fix Boost on Thermostat --- src/matter/to-matter/ThermostatToMatter.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/matter/to-matter/ThermostatToMatter.ts b/src/matter/to-matter/ThermostatToMatter.ts index 6662509..a3bf9fe 100644 --- a/src/matter/to-matter/ThermostatToMatter.ts +++ b/src/matter/to-matter/ThermostatToMatter.ts @@ -151,6 +151,10 @@ export class ThermostatToMatter extends GenericDeviceToMatter { ), { id: `${uuid}-BoostOnOff`, + ioBrokerContext: { + device: ioBrokerDevice, + adapter: ioBrokerDevice.adapter, + }, }, ); } From 7ae6215ada1c4f3d5210bdafe633a6ade6c60ff7 Mon Sep 17 00:00:00 2001 From: Ingo Fischer Date: Sat, 1 Feb 2025 16:41:08 +0100 Subject: [PATCH 3/4] Other changes --- src-admin/package-lock.json | 4 ++-- src/lib/DeviceManagement.ts | 2 +- src/matter/to-iobroker/GenericDeviceToIoBroker.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src-admin/package-lock.json b/src-admin/package-lock.json index 7527438..0015665 100644 --- a/src-admin/package-lock.json +++ b/src-admin/package-lock.json @@ -1,12 +1,12 @@ { "name": "iobroker.matter", - "version": "0.4.11", + "version": "0.4.12", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "iobroker.matter", - "version": "0.4.11", + "version": "0.4.12", "dependencies": { "@foxriver76/iob-component-lib": "^0.2.0", "@iobroker/adapter-react-v5": "^7.4.19", diff --git a/src/lib/DeviceManagement.ts b/src/lib/DeviceManagement.ts index 5175e30..5c3b329 100644 --- a/src/lib/DeviceManagement.ts +++ b/src/lib/DeviceManagement.ts @@ -194,7 +194,7 @@ class MatterAdapterDeviceManagement extends DeviceManagement { hasDetails: true, actions: actions.length ? (actions as DeviceAction<'adapter'>[]) : undefined, backgroundColor, - color: backgroundColor === 'primary' ? '#164477' : '#57BFFF', + color: '#FFFFFF', group: { key: 'node', name: this.#adapter.getText('Node'), diff --git a/src/matter/to-iobroker/GenericDeviceToIoBroker.ts b/src/matter/to-iobroker/GenericDeviceToIoBroker.ts index 7201811..c0a37d2 100644 --- a/src/matter/to-iobroker/GenericDeviceToIoBroker.ts +++ b/src/matter/to-iobroker/GenericDeviceToIoBroker.ts @@ -27,7 +27,7 @@ export interface EnabledAttributeProperty extends EnabledProperty { attributeId?: AttributeId; attributeName?: string; convertValue?: (value: any) => MaybePromise; - changeHandler?: (value: any) => Promise | void; + changeHandler?: (value: any) => MaybePromise | void; pollAttribute?: boolean; } @@ -231,7 +231,7 @@ export abstract class GenericDeviceToIoBroker { endpointId?: EndpointNumber; clusterId?: ClusterId; convertValue?: (value: any) => MaybePromise; - changeHandler?: (value: any) => Promise | void; + changeHandler?: (value: any) => MaybePromise | void; pollAttribute?: boolean; } & ({ vendorSpecificAttributeId: AttributeId } | { attributeName?: string }), ): void { From 41b8b0eaa1ce9797f3ba9902e775245dbbba6e67 Mon Sep 17 00:00:00 2001 From: Ingo Fischer Date: Sat, 1 Feb 2025 16:41:17 +0100 Subject: [PATCH 4/4] Readme --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e6f32fb..8014acf 100644 --- a/README.md +++ b/README.md @@ -78,8 +78,12 @@ With the ioBroker Matter Adapter, it is possible to map the following use cases: --> ## Changelog -### 0.4.12 (2025-02-01) +### __WORK IN PROGRESS__ +* (@Apollon77) Added support for Door state feature for Devices and Controllers +* (@Apollon77) Fixed Thermostat creation with Boost state + +### 0.4.12 (2025-02-01) * (@GermanBluefox) Added the "copy to clipboard" button in the debug dialog * (@Apollon77) Updated matter.js with performance and Memory usage optimizations (and Tasmota pairing workaround) * (@Apollon77) Reworked Type detection in Backend and for Channel/Device detection type in UI, now multiple devicetypes are offered with most complex one pre-selected