matterbridge
Version:
Matterbridge plugin manager for Matter
146 lines • 9.01 kB
JavaScript
/**
* This file contains the Evse class.
*
* @file energy-evse.ts
* @author Luca Liguori
* @contributor Ludovic BOUÉ
* @date 2025-05-27
* @version 1.1.0
*
* Copyright 2025, 2026, 2027 Luca Liguori.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License. *
*/
import { EnergyEvseServer } from '@matter/main/behaviors/energy-evse';
import { EnergyEvseModeServer } from '@matter/main/behaviors/energy-evse-mode';
import { EnergyEvse, EnergyEvseMode } from '@matter/main/clusters';
import { DeviceEnergyManagement } from '@matter/main/clusters/device-energy-management';
import { ModeBase } from '@matter/main/clusters/mode-base';
// Matterbridge
import { MatterbridgeEndpoint } from './matterbridgeEndpoint.js';
import { MatterbridgeServer } from './matterbridgeBehaviors.js';
import { deviceEnergyManagement, electricalSensor, evse, powerSource } from './matterbridgeDeviceTypes.js';
export class Evse extends MatterbridgeEndpoint {
/**
* Creates an instance of the EVSE class.
*
* @param {string} name - The name of the EVSE.
* @param {string} serial - The serial number of the EVSE.
* @param {number} [currentMode] - The current mode of the EnergyEvseMode cluster. Defaults to mode 1 (EnergyEvseMode.ModeTag.Manual).
* @param {EnergyEvseMode.ModeOption[]} [supportedModes] - The supported modes for the EnergyEvseMode cluster. This is a fixed attribute that defaults to a predefined set of EnergyEvseMode cluster modes.
* @param {EnergyEvse.State} [state] - The current state of the EVSE. Defaults to NotPluggedIn.
* @param {EnergyEvse.SupplyState} [supplyState] - The supply state of the EVSE. Defaults to Disabled.
* @param {EnergyEvse.FaultState} [faultState] - The fault state of the EVSE. Defaults to NoError.
* @param {number} [absMinPower=0] - Indicate the minimum electrical power that the ESA can consume when switched on. Defaults to `0` if not provided.
* @param {number} [absMaxPower=0] - Indicate the maximum electrical power that the ESA can consume when switched on. Defaults to `0` if not provided.
*/
constructor(name, serial, currentMode, supportedModes, state, supplyState, faultState, absMinPower, absMaxPower) {
super([evse, powerSource, electricalSensor, deviceEnergyManagement], { uniqueStorageKey: `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}` }, true);
this.createDefaultIdentifyClusterServer()
.createDefaultBasicInformationClusterServer(name, serial, 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge EVSE')
.createDefaultPowerSourceWiredClusterServer()
.createDefaultPowerTopologyClusterServer()
.createDefaultElectricalPowerMeasurementClusterServer()
.createDefaultElectricalEnergyMeasurementClusterServer()
.createDefaultDeviceEnergyManagementClusterServer(DeviceEnergyManagement.EsaType.Evse, false, DeviceEnergyManagement.EsaState.Online, absMinPower, absMaxPower)
.createDefaultEnergyEvseClusterServer(state, supplyState, faultState)
.createDefaultEnergyEvseModeClusterServer(currentMode, supportedModes)
.addRequiredClusterServers();
}
/**
* Creates a default EnergyEvseServer Cluster Server.
*
*/
createDefaultEnergyEvseClusterServer(state, supplyState, faultState) {
this.behaviors.require(MatterbridgeEnergyEvseServer, {
state: state ?? EnergyEvse.State.NotPluggedIn,
supplyState: supplyState ?? EnergyEvse.SupplyState.ChargingEnabled,
faultState: faultState ?? EnergyEvse.FaultState.NoError,
chargingEnabledUntil: 0, // Persistent attribute
circuitCapacity: 0, // Persistent attribute in mA
minimumChargeCurrent: 6000, // Persistent attribute in mA
maximumChargeCurrent: 0, // Persistent attribute in mA
sessionId: null, // Persistent attribute
sessionDuration: 0, // Persistent attribute
sessionEnergyCharged: 0, // Persistent attribute
});
return this;
}
/**
* Creates a default EnergyEvseMode Cluster Server.
*
* @param {number} [currentMode] - The current mode of the EnergyEvseMode cluster. Defaults to mode 1 (EnergyEvseMode.ModeTag.Manual).
* @param {EnergyEvseMode.ModeOption[]} [supportedModes] - The supported modes for the EnergyEvseMode cluster. Defaults all EnergyEvseMode cluster modes.
*
* @returns {this} The current MatterbridgeEndpoint instance for chaining.
*/
createDefaultEnergyEvseModeClusterServer(currentMode, supportedModes) {
this.behaviors.require(MatterbridgeEnergyEvseModeServer, {
supportedModes: supportedModes ?? [
{ label: 'On demand', mode: 1, modeTags: [{ value: EnergyEvseMode.ModeTag.Manual }] },
{ label: 'Scheduled', mode: 2, modeTags: [{ value: EnergyEvseMode.ModeTag.TimeOfUse }] },
{ label: 'Solar charging', mode: 3, modeTags: [{ value: EnergyEvseMode.ModeTag.SolarCharging }] },
// { label: 'Home to vehicle and Vehicle to home', mode: 4, modeTags: [{ value: EnergyEvseMode.ModeTag.V2X }] }, // This mode is not valid in charging only EVSEs
], // FixedAttribute
currentMode: currentMode ?? 1, // Persistent attribute
});
return this;
}
}
export class MatterbridgeEnergyEvseServer extends EnergyEvseServer {
disable() {
const device = this.endpoint.stateOf(MatterbridgeServer);
device.log.info(`Disable charging (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
device.commandHandler.executeHandler('disable', { request: {}, cluster: EnergyEvseServer.id, attributes: this.state, endpoint: this.endpoint });
device.log.debug(`MatterbridgeEnergyEvseServer disable called`);
this.state.supplyState = EnergyEvse.SupplyState.Disabled;
if (this.state.state === EnergyEvse.State.PluggedInCharging) {
this.state.state = EnergyEvse.State.PluggedInDemand;
}
this.state.chargingEnabledUntil = 0;
// super.disable();
// disable is not implemented in matter.js
}
enableCharging(request) {
const device = this.endpoint.stateOf(MatterbridgeServer);
device.log.info(`EnableCharging (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
device.commandHandler.executeHandler('enableCharging', { request, cluster: EnergyEvseServer.id, attributes: this.state, endpoint: this.endpoint });
device.log.debug(`MatterbridgeEnergyEvseServer enableCharging called`);
this.state.supplyState = EnergyEvse.SupplyState.ChargingEnabled;
if (this.state.state === EnergyEvse.State.PluggedInDemand) {
this.state.state = EnergyEvse.State.PluggedInCharging;
}
this.state.chargingEnabledUntil = request.chargingEnabledUntil;
this.state.minimumChargeCurrent = request.minimumChargeCurrent;
this.state.maximumChargeCurrent = request.maximumChargeCurrent;
// The implementation should also stop the charging session at the required time and update the sessionId, sessionDuration, and sessionEnergyCharged attributes if needed.
// super.enableCharging();
// enableCharging is not implemented in matter.js
}
}
export class MatterbridgeEnergyEvseModeServer extends EnergyEvseModeServer {
changeToMode(request) {
const device = this.endpoint.stateOf(MatterbridgeServer);
device.log.info(`Changing mode to ${request.newMode} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
device.commandHandler.executeHandler('changeToMode', { request, cluster: EnergyEvseModeServer.id, attributes: this.state, endpoint: this.endpoint });
const supported = this.state.supportedModes.find((mode) => mode.mode === request.newMode);
if (!supported) {
device.log.error(`MatterbridgeEnergyEvseModeServer changeToMode called with unsupported newMode: ${request.newMode}`);
return { status: ModeBase.ModeChangeStatus.UnsupportedMode, statusText: 'Unsupported mode' };
}
this.state.currentMode = request.newMode;
device.log.debug(`MatterbridgeEnergyEvseModeServer changeToMode called with newMode ${request.newMode} => ${supported.label}`);
return { status: ModeBase.ModeChangeStatus.Success, statusText: 'Success' };
}
}
//# sourceMappingURL=evse.js.map