Skip to content

Commit

Permalink
Merge branch 'matter' into matter_colortemperature
Browse files Browse the repository at this point in the history
  • Loading branch information
digitaldan authored Nov 15, 2024
2 parents 02e88c4 + ba4cda8 commit 3529f9d
Show file tree
Hide file tree
Showing 35 changed files with 959 additions and 194 deletions.
119 changes: 63 additions & 56 deletions bundles/org.openhab.binding.matter/README.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,28 @@ import { logEndpoint, EndpointInterface } from "@matter/protocol";
import { Endpoint, EndpointServer, MutableEndpoint, ServerNode } from "@matter/node";
import { AggregatorEndpoint } from "@matter/node/endpoints";
import { Environment, Logger } from "@matter/general";
import { GenericDevice } from "./devices/GenericDevice";
import { OnOffDevice } from "./devices/OnOffDevice";
import { OnOffPlugInDevice } from "./devices/OnOffPlugInDevice";
import { DimmableDevice } from "./devices/DimmableDevice";
import { ThermoDevice } from "./devices/ThermoDevice";
import { GenericDeviceType } from "./devices/GenericDeviceType";
import { OnOffDeviceType } from "./devices/OnOffDeviceType";
import { OnOffPlugInDeviceType } from "./devices/OnOffPlugInDeviceType";
import { DimmableDeviceType } from "./devices/DimmableDeviceType";
import { ThermostatDeviceType } from "./devices/ThermostatDeviceType";
import { WindowCoveringDeviceType } from "./devices/WindowCoveringDeviceType";
import { BridgeController } from "./BridgeController";
import { DoorLockDeviceType } from "./devices/DoorLockDeviceType";
import { TemperatureSensorType } from "./devices/TemperatureSensorType";
import { HumiditySensorType } from "./devices/HumiditySensorType";
import { OccupancySensorDeviceType } from "./devices/OccupancySensorDeviceType";



const logger = Logger.get("DeviceNode");

export class DeviceNode {
private server!: ServerNode;
#environment: Environment = Environment.default;

private aggregator!: Endpoint<AggregatorEndpoint>;
private devices: Map<string, GenericDevice> = new Map();
private devices: Map<string, GenericDeviceType> = new Map();

constructor(private bridgeController: BridgeController, private storagePath: string, private resetStorage: boolean, private deviceName: string, private vendorName: string, private passcode: number, private discriminator: number, private vendorId: number, private productName: string, private productId: number, private port: number, private uniqueId: string) {
}
Expand Down Expand Up @@ -77,7 +84,7 @@ export class DeviceNode {
logger.info(`ServerNode created with ID: ${this.server.id}`);
this.aggregator = new Endpoint(AggregatorEndpoint, { id: "aggregator" });
await this.server.add(this.aggregator);
await this.server.start();


//reset this for future restarts
this.#environment.vars.set("storage.clear", false);
Expand Down Expand Up @@ -107,7 +114,7 @@ export class DeviceNode {

async addEndpoint(deviceType: string, id: string, nodeLabel: string, productName: string, productLabel: string, serialNumber: string, attributeMap: { [key: string]: any }) {
//const deviceType = this.deviceTypes[endpointType];
let device: GenericDevice | null = null;
let device: GenericDeviceType | null = null;

if (this.devices.has(id)) {
logger.error(`Device ${id} already exists! Call 'resetEndpoints' first and try again.`);
Expand All @@ -116,30 +123,38 @@ export class DeviceNode {

switch (deviceType) {
case "OnOffLightDevice":
device = new OnOffDevice(this.bridgeController, attributeMap, id, nodeLabel, productName, productLabel, serialNumber);
device = new OnOffDeviceType(this.bridgeController, attributeMap, id, nodeLabel, productName, productLabel, serialNumber);
break;
case "OnOffPlugInUnitDevice":
device = new OnOffPlugInDevice(this.bridgeController, attributeMap, id, nodeLabel, productName, productLabel, serialNumber);
device = new OnOffPlugInDeviceType(this.bridgeController, attributeMap, id, nodeLabel, productName, productLabel, serialNumber);
break;
case "DimmableLightDevice":
device = new DimmableDevice(this.bridgeController, attributeMap, id, nodeLabel, productName, productLabel, serialNumber);
device = new DimmableDeviceType(this.bridgeController, attributeMap, id, nodeLabel, productName, productLabel, serialNumber);
break;
case "ThermostatDevice":
device = new ThermoDevice(this.bridgeController, attributeMap, id, nodeLabel, productName, productLabel, serialNumber);
device = new ThermostatDeviceType(this.bridgeController, attributeMap, id, nodeLabel, productName, productLabel, serialNumber);
break;
case "WindowCoveringDevice":
device = new WindowCoveringDeviceType(this.bridgeController, attributeMap, id, nodeLabel, productName, productLabel, serialNumber);
break;
case "DoorLockDevice":
device = new DoorLockDeviceType(this.bridgeController, attributeMap, id, nodeLabel, productName, productLabel, serialNumber);
break;
case "TemperatureSensor":
device = new TemperatureSensorType(this.bridgeController, attributeMap, id, nodeLabel, productName, productLabel, serialNumber);
break;
case "HumiditySensor":
device = new HumiditySensorType(this.bridgeController, attributeMap, id, nodeLabel, productName, productLabel, serialNumber);
break;
case "OccupancySensor":
device = new OccupancySensorDeviceType(this.bridgeController, attributeMap, id, nodeLabel, productName, productLabel, serialNumber);
break;
default:
logger.error(`Unsupported device type ${deviceType}`);
throw new Error(`Unsupported device type ${deviceType}`);
}
if (device != null) {
this.devices.set(id, device);
await this.aggregator.add(device.endpoint);
/**
* Log the endpoint structure for debugging reasons and to allow to verify anything is correct
*/
//logEndpoint(EndpointServer.forEndpoint(this.server));
}

}
Expand All @@ -149,6 +164,11 @@ export class DeviceNode {
return this.init();
}

async startBridge() {
await this.server.start();
logEndpoint(EndpointServer.forEndpoint(this.server));
}

async setEndpointState(endpointId: string, clusterName: string, stateName: string, stateValue: any) {
const device = this.devices.get(endpointId);
if (device) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import { Endpoint } from "@matter/node";
import { DimmableLightDevice } from "@matter/node/devices/dimmable-light";
import { BridgedDeviceBasicInformationServer } from "@matter/node/behaviors/bridged-device-basic-information";
import { GenericDevice } from './GenericDevice'; // Adjust the path as needed
import { GenericDeviceType } from './GenericDeviceType'; // Adjust the path as needed
import { BridgeController } from "../BridgeController";
import { Logger } from "@matter/general";

const logger = Logger.get("DimmableDevice");
const logger = Logger.get("DimmableDeviceType");

export class DimmableDevice extends GenericDevice {
export class DimmableDeviceType extends GenericDeviceType {


override createEndpoint() {
const endpoint = new Endpoint(DimmableLightDevice.with(BridgedDeviceBasicInformationServer), {
id: this.endpointId,
Expand All @@ -20,6 +19,12 @@ export class DimmableDevice extends GenericDevice {
serialNumber: this.serialNumber,
reachable: true,
},
levelControl: {
currentLevel: this.attributeMap.currentLevel || 0,
},
onOff: {
onOff: this.attributeMap.onOff || false,
},
});
endpoint.events.onOff.onOff$Changed.on(value => {
this.sendBridgeEvent("onOff","onOff", value);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Endpoint } from "@matter/node";
import { DoorLockDevice } from "@matter/node/devices/door-lock";
import { BridgedDeviceBasicInformationServer } from "@matter/node/behaviors/bridged-device-basic-information";
import { GenericDeviceType } from './GenericDeviceType'; // Adjust the path as needed
import { BridgeController } from "../BridgeController";
import { Logger } from "@matter/general";

const logger = Logger.get("DoorLockDeviceType");

export class DoorLockDeviceType extends GenericDeviceType {

override createEndpoint() {

const defaultParams = {
lockState: 0,
lockType: 0,
actuatorEnabled: true,
doorState: 1
}
const finalMap = { ...defaultParams, ...this.attributeMap }

const endpoint = new Endpoint(DoorLockDevice.with(BridgedDeviceBasicInformationServer), {
id: this.endpointId,
bridgedDeviceBasicInformation: {
nodeLabel: this.nodeLabel,
productName: this.productName,
productLabel: this.productLabel,
serialNumber: this.serialNumber,
reachable: true,
},
doorLock: {
...finalMap
},
});
endpoint.events.doorLock.lockState$Changed.on(value => {
this.sendBridgeEvent("doorLock", "lockState", value);
});

return endpoint
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ import { Logger } from "@matter/main";

const logger = Logger.get("GenericDevice");

export abstract class GenericDevice {
export abstract class GenericDeviceType {

protected updateLocks = new Set<string>();
endpoint: Endpoint;

constructor(protected bridgeController: BridgeController, protected attributeMap: { [key: string]: any }, protected endpointId: string, protected nodeLabel: string, protected productName: string, protected productLabel: string, protected serialNumber: string) {
this.nodeLabel = this.truncateString(nodeLabel);
this.productLabel = this.truncateString(productLabel);
this.productName = this.truncateString(productName);
this.serialNumber = this.truncateString(serialNumber);
this.endpoint = this.createEndpoint();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Endpoint } from "@matter/node";
import { HumiditySensorDevice } from "@matter/node/devices/humidity-sensor";
import { BridgedDeviceBasicInformationServer } from "@matter/node/behaviors/bridged-device-basic-information";
import { GenericDeviceType } from './GenericDeviceType'; // Adjust the path as needed
import { BridgeController } from "../BridgeController";
import { Logger } from"@matter/general";

const logger = Logger.get("HumiditySensorType");

export class HumiditySensorType extends GenericDeviceType {

override createEndpoint() {
const endpoint = new Endpoint(HumiditySensorDevice.with(BridgedDeviceBasicInformationServer), {
id: this.endpointId,
bridgedDeviceBasicInformation: {
nodeLabel: this.nodeLabel,
productName: this.productName,
productLabel: this.productLabel,
serialNumber: this.serialNumber,
reachable: true,
},
relativeHumidityMeasurement: {
measuredValue: this.attributeMap.measuredValue || 0,
},
});
return endpoint
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Endpoint } from "@matter/node";
import { OccupancySensorDevice } from "@matter/node/devices/occupancy-sensor";
import { BridgedDeviceBasicInformationServer } from "@matter/node/behaviors/bridged-device-basic-information";
import { GenericDeviceType } from './GenericDeviceType'; // Adjust the path as needed
import { BridgeController } from "../BridgeController";
import { Logger } from"@matter/general";

const logger = Logger.get("OccupancySensorDeviceType");

export class OccupancySensorDeviceType extends GenericDeviceType {

override createEndpoint() {
logger.info(`Creating Occupancy Sensor Device Endpoint ${JSON.stringify(this.attributeMap)}`);
const endpoint = new Endpoint(OccupancySensorDevice.with(BridgedDeviceBasicInformationServer), {
id: this.endpointId,
bridgedDeviceBasicInformation: {
nodeLabel: this.nodeLabel,
productName: this.productName,
productLabel: this.productLabel,
serialNumber: this.serialNumber,
reachable: true,
},
occupancySensing: {
occupancy: this.attributeMap.occupancy,
occupancySensorType : this.attributeMap.occupancySensorType || 3,
},
});
return endpoint
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { Endpoint } from "@matter/node";
import { OnOffLightDevice } from "@matter/node/devices/on-off-light";
import { BridgedDeviceBasicInformationServer } from "@matter/node/behaviors/bridged-device-basic-information";
import { GenericDevice } from './GenericDevice'; // Adjust the path as needed
import { GenericDeviceType } from './GenericDeviceType'; // Adjust the path as needed
import { BridgeController } from "../BridgeController";
import { Logger } from"@matter/general";

const logger = Logger.get("OnOff");
const logger = Logger.get("OnOffDeviceType");

export class OnOffDevice extends GenericDevice {
export class OnOffDeviceType extends GenericDeviceType {

override createEndpoint() {
const endpoint = new Endpoint(OnOffLightDevice.with(BridgedDeviceBasicInformationServer), {
Expand All @@ -19,6 +19,9 @@ export class OnOffDevice extends GenericDevice {
serialNumber: this.serialNumber,
reachable: true,
},
onOff: {
onOff: this.attributeMap.onOff || false,
},
});
endpoint.events.onOff.onOff$Changed.on(value => {
this.sendBridgeEvent("onOff","onOff", value);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { Endpoint } from "@matter/node";
import { OnOffPlugInUnitDevice } from "@matter/node/devices/on-off-plug-in-unit";
import { BridgedDeviceBasicInformationServer } from "@matter/node/behaviors/bridged-device-basic-information";
import { GenericDevice } from './GenericDevice'; // Adjust the path as needed
import { GenericDeviceType } from './GenericDeviceType'; // Adjust the path as needed
import { BridgeController } from "../BridgeController";
import { Logger } from"@matter/general";

const logger = Logger.get("OnOffPlugInDevice");

export class OnOffPlugInDevice extends GenericDevice {
export class OnOffPlugInDeviceType extends GenericDeviceType {

override createEndpoint() {
const endpoint = new Endpoint(OnOffPlugInUnitDevice.with(BridgedDeviceBasicInformationServer), {
Expand All @@ -19,6 +19,9 @@ export class OnOffPlugInDevice extends GenericDevice {
serialNumber: this.serialNumber,
reachable: true,
},
onOff: {
onOff: this.attributeMap.onOff || false,
}
});
endpoint.events.onOff.onOff$Changed.on(value => {
this.sendBridgeEvent("onOff","onOff", value);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Endpoint } from "@matter/node";
import { TemperatureSensorDevice } from "@matter/node/devices/temperature-sensor";
import { BridgedDeviceBasicInformationServer } from "@matter/node/behaviors/bridged-device-basic-information";
import { GenericDeviceType } from './GenericDeviceType'; // Adjust the path as needed
import { BridgeController } from "../BridgeController";
import { Logger } from"@matter/general";

const logger = Logger.get("TemperatureSensorType");

export class TemperatureSensorType extends GenericDeviceType {

override createEndpoint() {
const endpoint = new Endpoint(TemperatureSensorDevice.with(BridgedDeviceBasicInformationServer), {
id: this.endpointId,
bridgedDeviceBasicInformation: {
nodeLabel: this.nodeLabel,
productName: this.productName,
productLabel: this.productLabel,
serialNumber: this.serialNumber,
reachable: true,
},
temperatureMeasurement: {
measuredValue: this.attributeMap.measuredValue || 0,
},
});
return endpoint
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import { ThermostatDevice } from "@matter/node/devices/thermostat";
import { BridgedDeviceBasicInformationServer } from "@matter/node/behaviors/bridged-device-basic-information";
import { ThermostatServer } from '@matter/node/behaviors/thermostat';
import { Thermostat } from '@matter/main/clusters';
import { GenericDevice } from './GenericDevice'; // Adjust the path as needed
import { GenericDeviceType } from './GenericDeviceType'; // Adjust the path as needed
import { BridgeController } from "../BridgeController";
import { Logger } from"@matter/general";

const logger = Logger.get("ThermoDevice");
const logger = Logger.get("ThermostatDeviceType");

export class ThermoDevice extends GenericDevice {
export class ThermostatDeviceType extends GenericDeviceType {

override createEndpoint() {
let controlSequenceOfOperation = -1;
Expand Down
Loading

0 comments on commit 3529f9d

Please sign in to comment.