diff --git a/README.md b/README.md
index bcf59379..b3670f27 100644
--- a/README.md
+++ b/README.md
@@ -213,13 +213,19 @@ TBD
-->
## Changelog
+
+### __WORK IN PROGRESS__
+* (@Apollon77) Uses plain matter.js logs for better readability
+* (@Apollon77) Prevents ghost connection entries in the UI
+* (@Apollon77) Adds some missing implementations for Controller of Door, Window, FloodAlarm and Motion
+
### 0.2.1 (2024-11-27)
* (@Apollon77) Adds Color Temperature conversion if unit is "mireds"
* (@Apollon77) Fixes Color Temperature cluster initialization
* (@Apollon77) Fixes Min/Max calculation when unit conversion is used
### 0.2.0 (2024-11-26)
-* IMPORTANT: Breaking change!! Please decommission ALL devices and do a full factory reset of the adapter Matter storage before installing this version. Pair the devices new afterwards.
+* IMPORTANT: Breaking change!! Please decommission ALL devices and do a full factory reset of the adapter Matter storage before installing this version. Pair the devices new afterward.
* (@Apollon77) Finalizes Devices, Bridges and Controller functionality with a first set of 11 device types
* (@Apollon77) Upgrades to new Matter.js version and API (breaks storage structure)
* (@GermanBluefox) Moved build process of GUI to vite
diff --git a/src-admin/package-lock.json b/src-admin/package-lock.json
index 0445af94..b7688e65 100644
--- a/src-admin/package-lock.json
+++ b/src-admin/package-lock.json
@@ -12,7 +12,6 @@
"@iobroker/adapter-react-v5": "^7.4.2",
"@iobroker/dm-gui-components": "~7.4.2",
"@iobroker/type-detector": "^4.0.1",
- "@rollup/rollup-linux-x64-gnu": "*",
"@types/react-dom": "^18.3.1",
"@types/uuid": "^10.0.0",
"@vitejs/plugin-react": "^4.3.3",
diff --git a/src-admin/src/Tabs/BridgesAndDevices.tsx b/src-admin/src/Tabs/BridgesAndDevices.tsx
index b2a40cb2..9b933784 100644
--- a/src-admin/src/Tabs/BridgesAndDevices.tsx
+++ b/src-admin/src/Tabs/BridgesAndDevices.tsx
@@ -110,13 +110,19 @@ class BridgesAndDevices
);
}
- if (vendor === 'Apple Inc.') {
+ if (vendor === 'Apple Inc.' || vendor === 'Apple Keychain') {
return (
);
}
- if (vendor === 'Samsung') {
+ if (vendor === 'SmartThings, Inc.' || vendor === 'Samsung') {
return (
{BridgesAndDevices.getVendorIcon(info.vendorId, this.props.themeType) ||
- info.vendorId}
+ BridgesAndDevices.getVendorName(info.vendorId)}
{info.label ? (
{
+ if (!this.#getValueState) {
+ throw new Error('Value state not found');
+ }
+ return this.#getValueState.updateValue(value);
+ }
}
export default Door;
diff --git a/src/lib/devices/FloodAlarm.ts b/src/lib/devices/FloodAlarm.ts
index 5bcd9c06..534274e4 100644
--- a/src/lib/devices/FloodAlarm.ts
+++ b/src/lib/devices/FloodAlarm.ts
@@ -26,6 +26,13 @@ class FloodAlarm extends GenericDevice {
}
return this.#getValueState.value;
}
+
+ updateValue(value: boolean): Promise {
+ if (!this.#getValueState) {
+ throw new Error('Value state not found');
+ }
+ return this.#getValueState.updateValue(value);
+ }
}
export default FloodAlarm;
diff --git a/src/lib/devices/Motion.ts b/src/lib/devices/Motion.ts
index 0ae88929..f7e3680c 100644
--- a/src/lib/devices/Motion.ts
+++ b/src/lib/devices/Motion.ts
@@ -35,6 +35,13 @@ class Motion extends GenericDevice {
return this.#getMotionState.value;
}
+ updateMotion(value: boolean): Promise {
+ if (!this.#getMotionState) {
+ throw new Error('Value state not found');
+ }
+ return this.#getMotionState.updateValue(value);
+ }
+
hasBrightness(): boolean {
return this.propertyNames.includes(PropertyType.Brightness);
}
@@ -45,6 +52,13 @@ class Motion extends GenericDevice {
}
return this.#getBrightnessState.value;
}
+
+ updateBrightness(value: number): Promise {
+ if (!this.#getBrightnessState) {
+ throw new Error('Brightness state not found');
+ }
+ return this.#getBrightnessState.updateValue(value);
+ }
}
export default Motion;
diff --git a/src/lib/devices/Temperature.ts b/src/lib/devices/Temperature.ts
index e35d3afe..6692b0a9 100644
--- a/src/lib/devices/Temperature.ts
+++ b/src/lib/devices/Temperature.ts
@@ -55,6 +55,13 @@ class Temperature extends GenericDevice {
}
return this.#getHumidityState.value;
}
+
+ updateHumidity(value: number): Promise {
+ if (!this.#getHumidityState) {
+ throw new Error('Humidity state not found');
+ }
+ return this.#getHumidityState.updateValue(value);
+ }
}
export default Temperature;
diff --git a/src/lib/devices/Window.ts b/src/lib/devices/Window.ts
index 55f1a879..1be47f4d 100644
--- a/src/lib/devices/Window.ts
+++ b/src/lib/devices/Window.ts
@@ -26,6 +26,13 @@ class Window extends GenericDevice {
}
return this.#getValueState.value;
}
+
+ updateValue(value: boolean): Promise {
+ if (!this.#getValueState) {
+ throw new Error('Value state not found');
+ }
+ return this.#getValueState.updateValue(value);
+ }
}
export default Window;
diff --git a/src/main.ts b/src/main.ts
index 56ec516b..1c56f1f0 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,6 +1,6 @@
import * as utils from '@iobroker/adapter-core';
import ChannelDetector, { type DetectorState, Types } from '@iobroker/type-detector';
-import { Environment, LogLevel, Logger, StorageService } from '@matter/main';
+import { Environment, LogLevel, LogFormat, Logger, StorageService } from '@matter/main';
import axios from 'axios';
import jwt from 'jsonwebtoken';
import fs from 'node:fs/promises';
@@ -340,6 +340,7 @@ export class MatterAdapter extends utils.Adapter {
async prepareMatterEnvironment(): Promise {
const config: MatterAdapterConfig = this.config as MatterAdapterConfig;
Logger.defaultLogLevel = LogLevel.DEBUG;
+ Logger.format = LogFormat.PLAIN;
Logger.log = (level: LogLevel, formattedLog: string) => {
switch (level) {
case LogLevel.DEBUG:
diff --git a/src/matter/BaseServerNode.ts b/src/matter/BaseServerNode.ts
index 0681acec..ac52c7d2 100644
--- a/src/matter/BaseServerNode.ts
+++ b/src/matter/BaseServerNode.ts
@@ -1,4 +1,4 @@
-import { Logger, type ServerNode, type SessionsBehavior } from '@matter/main';
+import { Logger, type ServerNode, type SessionsBehavior, serialize } from '@matter/main';
import type { MatterAdapter } from '../main';
import type { GeneralNode, MessageResponse } from './GeneralNode';
@@ -82,24 +82,13 @@ export abstract class BaseServerNode implements GeneralNode {
const activeSessions = Object.values(this.serverNode.state.sessions.sessions);
const fabrics = Object.values(this.serverNode.state.commissioning.fabrics);
- const connectionInfo: ConnectionInfo[] = activeSessions.map(session => {
- const vendorId = session?.fabric?.rootVendorId;
- return {
- vendorId,
- connected: !!session.numberOfActiveSubscriptions,
- label: session?.fabric?.label,
- };
- });
-
- fabrics.forEach(fabric => {
- if (!activeSessions.find(session => session.fabric?.fabricId === fabric.fabricId)) {
- connectionInfo.push({
- vendorId: fabric?.rootVendorId,
- connected: false,
- label: fabric?.label,
- });
- }
- });
+ const connectionInfo: ConnectionInfo[] = fabrics.map(fabric => ({
+ vendorId: fabric?.rootVendorId,
+ connected: activeSessions
+ .filter(session => session.fabric?.fabricId === fabric.fabricId)
+ .some(({ numberOfActiveSubscriptions }) => !!numberOfActiveSubscriptions),
+ label: fabric?.label,
+ }));
if (connectionInfo.find(info => info.connected)) {
this.adapter.log.debug(`${this.type} ${this.uuid} is already commissioned and connected with controller`);
@@ -145,7 +134,7 @@ export abstract class BaseServerNode implements GeneralNode {
}
this.serverNode.events.commissioning.fabricsChanged.on(async fabricIndex => {
this.adapter.log.debug(
- `commissioningChangedCallback: Commissioning changed on Fabric ${fabricIndex}: ${JSON.stringify(this.serverNode?.state.operationalCredentials.fabrics.find(fabric => fabric.fabricIndex === fabricIndex))}`,
+ `commissioningChangedCallback: Commissioning changed on Fabric ${fabricIndex}: ${serialize(this.serverNode?.state.operationalCredentials.fabrics.find(fabric => fabric.fabricIndex === fabricIndex))}`,
);
await this.updateUiState();
});
diff --git a/src/matter/to-matter/CtToMatter.ts b/src/matter/to-matter/CtToMatter.ts
index 8b65dff9..88fc8159 100644
--- a/src/matter/to-matter/CtToMatter.ts
+++ b/src/matter/to-matter/CtToMatter.ts
@@ -105,7 +105,7 @@ export class CtToMatter extends GenericElectricityDataDeviceToMatter {
}
async registerIoBrokerHandlersAndInitialize(): Promise {
- const { min = 2_000, max = 6_500 } = this.#ioBrokerDevice.getTemperatureMinMax() ?? {};
+ const { min = 2_000, max = 6_536 } = this.#ioBrokerDevice.getTemperatureMinMax() ?? {}; // 153 till 500 mireds
this.#ioBrokerDevice.onChange(async event => {
switch (event.property) {