Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Matter EVSE (button entities version) #133662

Closed
wants to merge 64 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
23eea49
EnergyEvse.Attributes.MinimumChargeCurrent
lboue Dec 17, 2024
6988103
EnergyEvse.Attributes.MaximumChargeCurrent
lboue Dec 17, 2024
493d486
EnergyEvse.Attributes.UserMaximumChargeCurrent
lboue Dec 17, 2024
e367ff6
EnergyEvse.Enums.StateEnum
lboue Dec 17, 2024
0ecdeb0
Update sensor.py
lboue Dec 17, 2024
297e6e6
EnergyEvse.Attributes.CircuitCapacity
lboue Dec 17, 2024
8780ed9
ruff-format
lboue Dec 17, 2024
43ab4e3
ruff-format
lboue Dec 17, 2024
5c782a1
EnergyEvse.Attributes.SupplyState
lboue Dec 17, 2024
ad881d2
EnergyEvse.Enums.SupplyStateEnum
lboue Dec 17, 2024
d440e13
EnergyEvse.Commands.EnableCharging
lboue Dec 17, 2024
f5c5a82
EnergyEvse.Commands.Disable
lboue Dec 17, 2024
afee080
Create evse_charging.json
lboue Dec 18, 2024
80a20da
EnergyEvse.Enums.FaultStateEnum
lboue Dec 18, 2024
d03959a
EnergyEvse.Attributes.FaultState
lboue Dec 18, 2024
8c409fe
ruff-format
lboue Dec 18, 2024
f1eaa06
EnergyEvse.Enums.SupplyStateEnum.kEnabled Only with Matter 1.4
lboue Dec 18, 2024
b91fb0c
Custom class for requests with `timed_request_timeout_ms`
lboue Dec 18, 2024
8e78a21
Generic `MatterCommandButton` class
lboue Dec 18, 2024
8027a8e
Update icons.json
lboue Dec 18, 2024
5525f00
Update strings.json
lboue Dec 18, 2024
ba9a4f5
Update icons.json
lboue Dec 18, 2024
d39bc5e
Update strings.json
lboue Dec 18, 2024
bf7cdd8
Update strings.json
lboue Dec 18, 2024
cd1afcf
Test evse sensor
lboue Dec 18, 2024
90b0118
Update test_sensor.py
lboue Dec 19, 2024
cf0d433
Update test_sensor.py
lboue Dec 19, 2024
113bcc7
Update evse_charging.json
lboue Dec 19, 2024
bd87769
Update test_sensor.py
lboue Dec 20, 2024
7cc6765
Update evse_charging.json
lboue Dec 20, 2024
aebaa3e
Update sensor.py
lboue Dec 20, 2024
2fdbba9
Update test_sensor.py
lboue Dec 20, 2024
26e9363
Update strings.json
lboue Dec 20, 2024
5128238
EnergyEvse.Attributes.State
lboue Dec 20, 2024
03933cd
EnergyEvse.Attributes.SupplyState
lboue Dec 20, 2024
7b3905e
EnergyEvse.Attributes.FaultState
lboue Dec 20, 2024
1108486
Update sensor.py
lboue Dec 20, 2024
c379aea
EnergyEvse.Attributes.CircuitCapacity
lboue Dec 20, 2024
c118b1f
EnergyEvse.Attributes.MinimumChargeCurrent
lboue Dec 20, 2024
45f0f40
EnergyEvse.Attributes.MaximumChargeCurrent
lboue Dec 20, 2024
4f3dc0a
EnergyEvse.Attributes.UserMaximumChargeCurrent
lboue Dec 20, 2024
257c12e
Buttons
lboue Dec 20, 2024
c579194
Icons
lboue Dec 20, 2024
f6a7cf8
Strings
lboue Dec 20, 2024
21fcad3
Update test_sensor.py
lboue Dec 20, 2024
670803b
Merge branch 'EnergyEvse' into Matter_EVSE
lboue Dec 20, 2024
8b14c41
Merge branch 'dev' into Matter_EVSE
lboue Dec 20, 2024
a8179b2
Update sensor.py
lboue Dec 22, 2024
96f55c4
Translate maps into camelcase strings
lboue Dec 24, 2024
8b0e93b
Add states strings for EVSE maps
lboue Dec 24, 2024
6a9f74d
Update tests for state maps
lboue Dec 24, 2024
822994e
Merge branch 'Matter_EVSE' of https://github.com/lboue/ha_core into M…
lboue Dec 24, 2024
a6e7734
Fix tests
lboue Dec 24, 2024
71e4110
Add the evse_charging fixture to the list of fixtures
lboue Jan 16, 2025
9e7a6db
Merge branch 'dev' into Matter_EVSE
lboue Jan 16, 2025
8260389
Update icons.json
lboue Jan 16, 2025
f00a1cf
Update snapshots for EVSE
lboue Jan 16, 2025
f1ba30e
EnableCharging has arguments
lboue Jan 17, 2025
0555296
Merge branch 'dev' into Matter_EVSE
lboue Jan 17, 2025
b4a213b
Test EVSE buttons
lboue Jan 17, 2025
6fcbf0f
Test EnableCharging command
lboue Jan 17, 2025
e6147c6
Resolv conflicts
lboue Jan 24, 2025
8b3244e
Merge branch 'dev' into Matter_EVSE
lboue Jan 24, 2025
5e4e9a3
Update snapshots
lboue Jan 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions homeassistant/components/matter/button.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from typing import TYPE_CHECKING, Any

from chip.clusters import Objects as clusters
from chip.clusters.Objects import NullValue

from homeassistant.components.button import (
ButtonDeviceClass,
Expand Down Expand Up @@ -38,6 +39,7 @@ class MatterButtonEntityDescription(ButtonEntityDescription, MatterEntityDescrip
"""Describe Matter Button entities."""

command: Callable[[], Any] | None = None
command_timeout: int | None = None


class MatterCommandButton(MatterEntity, ButtonEntity):
Expand All @@ -53,6 +55,7 @@ async def async_press(self) -> None:
node_id=self._endpoint.node.node_id,
endpoint_id=self._endpoint.endpoint_id,
command=self.entity_description.command(),
timed_request_timeout_ms=self.entity_description.command_timeout,
)


Expand Down Expand Up @@ -147,4 +150,34 @@ async def async_press(self) -> None:
value_contains=clusters.ActivatedCarbonFilterMonitoring.Commands.ResetCondition.command_id,
allow_multi=True,
),
MatterDiscoverySchema(
platform=Platform.BUTTON,
entity_description=MatterButtonEntityDescription(
key="EnergyEvseEnableChargingButton",
translation_key="enable_charging",
command=lambda: clusters.EnergyEvse.Commands.EnableCharging(
chargingEnabledUntil=NullValue,
minimumChargeCurrent=0,
maximumChargeCurrent=0,
),
command_timeout=3000,
),
entity_class=MatterCommandButton,
required_attributes=(clusters.EnergyEvse.Attributes.AcceptedCommandList,),
value_contains=clusters.EnergyEvse.Commands.EnableCharging.command_id,
allow_multi=True,
),
MatterDiscoverySchema(
platform=Platform.BUTTON,
entity_description=MatterButtonEntityDescription(
key="EnergyEvseDisableChargingButton",
translation_key="disable_charging",
command=clusters.EnergyEvse.Commands.Disable,
command_timeout=3000,
),
entity_class=MatterCommandButton,
required_attributes=(clusters.EnergyEvse.Attributes.AcceptedCommandList,),
value_contains=clusters.EnergyEvse.Commands.Disable.command_id,
allow_multi=True,
),
]
15 changes: 15 additions & 0 deletions homeassistant/components/matter/icons.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
},
"stop": {
"default": "mdi:stop"
},
"enable_charging": {
"default": "mdi:play"
},
"disable_charging": {
"default": "mdi:stop"
}
},
"fan": {
Expand Down Expand Up @@ -58,6 +64,15 @@
"valve_position": {
"default": "mdi:valve"
},
"evse_state": {
"default": "mdi:ev-station"
},
"evse_supply_state": {
"default": "mdi:ev-station"
},
"evse_fault_state": {
"default": "mdi:ev-station"
},
"battery_replacement_description": {
"default": "mdi:battery-sync-outline"
}
Expand Down
133 changes: 133 additions & 0 deletions homeassistant/components/matter/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,42 @@
clusters.OperationalState.Enums.OperationalStateEnum.kError: "error",
}

EVSE_STATE_MAP = {
clusters.EnergyEvse.Enums.StateEnum.kNotPluggedIn: "not_plugged_in",
clusters.EnergyEvse.Enums.StateEnum.kPluggedInNoDemand: "plugged_in_no_demand",
clusters.EnergyEvse.Enums.StateEnum.kPluggedInDemand: "plugged_in_demand",
clusters.EnergyEvse.Enums.StateEnum.kPluggedInCharging: "plugged_in_charging",
clusters.EnergyEvse.Enums.StateEnum.kPluggedInDischarging: "plugged_in_discharging",
clusters.EnergyEvse.Enums.StateEnum.kSessionEnding: "session_ending",
clusters.EnergyEvse.Enums.StateEnum.kFault: "fault",
}

EVSE_SUPPLY_STATE_MAP = {
clusters.EnergyEvse.Enums.SupplyStateEnum.kDisabled: "disabled",
clusters.EnergyEvse.Enums.SupplyStateEnum.kChargingEnabled: "charging_enabled",
clusters.EnergyEvse.Enums.SupplyStateEnum.kDischargingEnabled: "discharging_enabled",
clusters.EnergyEvse.Enums.SupplyStateEnum.kDisabledDiagnostics: "disabled_diagnostics",
}

EVSE_FAULT_STATE_MAP = {
clusters.EnergyEvse.Enums.FaultStateEnum.kNoError: "no_error",
clusters.EnergyEvse.Enums.FaultStateEnum.kMeterFailure: "meter_failure",
clusters.EnergyEvse.Enums.FaultStateEnum.kOverVoltage: "over_voltage",
clusters.EnergyEvse.Enums.FaultStateEnum.kUnderVoltage: "under_voltage",
clusters.EnergyEvse.Enums.FaultStateEnum.kOverCurrent: "over_current",
clusters.EnergyEvse.Enums.FaultStateEnum.kContactWetFailure: "contact_wet_failure",
clusters.EnergyEvse.Enums.FaultStateEnum.kContactDryFailure: "contact_dry_failure",
clusters.EnergyEvse.Enums.FaultStateEnum.kPowerLoss: "power_loss",
clusters.EnergyEvse.Enums.FaultStateEnum.kPowerQuality: "power_quality",
clusters.EnergyEvse.Enums.FaultStateEnum.kPilotShortCircuit: "pilot_short_circuit",
clusters.EnergyEvse.Enums.FaultStateEnum.kEmergencyStop: "emergency_stop",
clusters.EnergyEvse.Enums.FaultStateEnum.kEVDisconnected: "ev_disconnected",
clusters.EnergyEvse.Enums.FaultStateEnum.kWrongPowerSupply: "wrong_power_supply",
clusters.EnergyEvse.Enums.FaultStateEnum.kLiveNeutralSwap: "live_neutral_swap",
clusters.EnergyEvse.Enums.FaultStateEnum.kOverTemperature: "over_temperature",
clusters.EnergyEvse.Enums.FaultStateEnum.kOther: "other",
}


async def async_setup_entry(
hass: HomeAssistant,
Expand Down Expand Up @@ -677,4 +713,101 @@ def _update_from_device(self) -> None:
clusters.OperationalState.Attributes.OperationalStateList,
),
),
MatterDiscoverySchema(
platform=Platform.SENSOR,
entity_description=MatterSensorEntityDescription(
key="EnergyEvseState",
translation_key="evse_state",
device_class=SensorDeviceClass.ENUM,
options=list(EVSE_STATE_MAP.values()),
measurement_to_ha=EVSE_STATE_MAP.get,
),
entity_class=MatterSensor,
required_attributes=(clusters.EnergyEvse.Attributes.State,),
),
MatterDiscoverySchema(
platform=Platform.SENSOR,
entity_description=MatterSensorEntityDescription(
key="EnergyEvseSupplyState",
translation_key="evse_supply_state",
device_class=SensorDeviceClass.ENUM,
options=list(EVSE_SUPPLY_STATE_MAP.values()),
measurement_to_ha=EVSE_SUPPLY_STATE_MAP.get,
),
entity_class=MatterSensor,
required_attributes=(clusters.EnergyEvse.Attributes.SupplyState,),
),
MatterDiscoverySchema(
platform=Platform.SENSOR,
entity_description=MatterSensorEntityDescription(
key="EnergyEvseFaultState",
translation_key="evse_fault_state",
device_class=SensorDeviceClass.ENUM,
entity_category=EntityCategory.DIAGNOSTIC,
options=list(EVSE_FAULT_STATE_MAP.values()),
measurement_to_ha=EVSE_FAULT_STATE_MAP.get,
),
entity_class=MatterSensor,
required_attributes=(clusters.EnergyEvse.Attributes.FaultState,),
),
MatterDiscoverySchema(
platform=Platform.SENSOR,
entity_description=MatterSensorEntityDescription(
key="EnergyEvseCircuitCapacity",
translation_key="evse_circuit_capacity",
device_class=SensorDeviceClass.CURRENT,
entity_category=EntityCategory.DIAGNOSTIC,
native_unit_of_measurement=UnitOfElectricCurrent.MILLIAMPERE,
suggested_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
suggested_display_precision=2,
state_class=SensorStateClass.MEASUREMENT,
),
entity_class=MatterSensor,
required_attributes=(clusters.EnergyEvse.Attributes.CircuitCapacity,),
),
MatterDiscoverySchema(
platform=Platform.SENSOR,
entity_description=MatterSensorEntityDescription(
key="EnergyEvseMinimumChargeCurrent",
translation_key="evse_min_charge_current",
device_class=SensorDeviceClass.CURRENT,
entity_category=EntityCategory.DIAGNOSTIC,
native_unit_of_measurement=UnitOfElectricCurrent.MILLIAMPERE,
suggested_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
suggested_display_precision=2,
state_class=SensorStateClass.MEASUREMENT,
),
entity_class=MatterSensor,
required_attributes=(clusters.EnergyEvse.Attributes.MinimumChargeCurrent,),
),
MatterDiscoverySchema(
platform=Platform.SENSOR,
entity_description=MatterSensorEntityDescription(
key="EnergyEvseMaximumChargeCurrent",
translation_key="evse_max_charge_current",
device_class=SensorDeviceClass.CURRENT,
entity_category=EntityCategory.DIAGNOSTIC,
native_unit_of_measurement=UnitOfElectricCurrent.MILLIAMPERE,
suggested_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
suggested_display_precision=2,
state_class=SensorStateClass.MEASUREMENT,
),
entity_class=MatterSensor,
required_attributes=(clusters.EnergyEvse.Attributes.MaximumChargeCurrent,),
),
MatterDiscoverySchema(
platform=Platform.SENSOR,
entity_description=MatterSensorEntityDescription(
key="EnergyEvseUserMaximumChargeCurrent",
translation_key="evse_user_max_charge_current",
device_class=SensorDeviceClass.CURRENT,
entity_category=EntityCategory.DIAGNOSTIC,
native_unit_of_measurement=UnitOfElectricCurrent.MILLIAMPERE,
suggested_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
suggested_display_precision=2,
state_class=SensorStateClass.MEASUREMENT,
),
entity_class=MatterSensor,
required_attributes=(clusters.EnergyEvse.Attributes.UserMaximumChargeCurrent,),
),
]
63 changes: 63 additions & 0 deletions homeassistant/components/matter/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@
},
"reset_filter_condition": {
"name": "Reset filter condition"
},
"enable_charging": {
"name": "Enable charging"
},
"disable_charging": {
"name": "Disable charging"
}
},
"climate": {
Expand Down Expand Up @@ -254,6 +260,63 @@
},
"battery_replacement_description": {
"name": "Battery type"
},
"evse_state": {
"name": "State",
"state": {
"not_plugged_in": "Not plugged in",
"plugged_in_no_demand": "Plugged in, no demand",
"plugged_in_demand": "Plugged in, demand",
"plugged_in_charging": "Plugged in, charging",
"plugged_in_discharging": "Plugged in, discharging",
"session_ending": "Session ending",
"fault": "Fault"
}
},
"evse_supply_state": {
"name": "Supply state",
"state": {
"disabled": "Disabled",
"charging_enabled": "Charging enabled",
"discharging_enabled": "Discharging enabled",
"disabled_diagnostics": "Disabled diagnostics"
}
},
"evse_fault_state": {
"name": "Fault state",
"state": {
"no_error": "OK",
"meter_failure": "Meter failure",
"over_voltage": "Over Voltage",
"under_voltage": "Under Voltage",
"over_current": "Over current",
"contact_wet_failure": "Contact wet failure",
"contact_dry_failure": "Contact dry failure",
"power_loss": "Power loss",
"power_quality": "Power quality",
"pilot_short_circuit": "Pilot short circuit",
"emergency_stop": "Emergency stop",
"ev_disconnected": "EV disconnected",
"wrong_power_supply": "Wrong power supply",
"live_neutral_swap": "Live neutral swap",
"over_temperature": "Over temperature",
"other": "Other fault"
}
},
"evse_circuit_capacity": {
"name": "Circuit capacity"
},
"evse_charge_current": {
"name": "Charge current"
},
"evse_min_charge_current": {
"name": "Min charge current"
},
"evse_max_charge_current": {
"name": "Max charge current"
},
"evse_user_max_charge_current": {
"name": "User max charge current"
}
},
"switch": {
Expand Down
1 change: 1 addition & 0 deletions tests/components/matter/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ async def integration_fixture(
"eve_energy_plug_patched",
"eve_thermo",
"eve_weather_sensor",
"evse_charging",
"extended_color_light",
"fan",
"flow_sensor",
Expand Down
Loading
Loading