Add support for Matter EVSE devicetype (#137189)

* Binary sensors

* Add tests

* Update strings

* Enable testing

* Add command_timeout to MatterEntityDescription

* Add entities

* Update strings.json

* Add sensors

* Add tests

* Move command_timeout keyword to MatterGenericCommandSwitch

* Icons

* Update snapshots

* Add tests for switch entity

* Fix switch tests

* Rename states

* Update strings.json

* Update snapshot

* Rename charging switch

* Remove MatterEntity

* Update strings.json

* Update snapshots

* Update snaphots 2/2

* Update strings

* Update test binary
This commit is contained in:
Ludovic BOUÉ 2025-04-04 17:57:22 +02:00 committed by GitHub
parent 61d2c9335f
commit 3c60bff7dc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 1674 additions and 0 deletions

View File

@ -265,4 +265,61 @@ DISCOVERY_SCHEMAS = [
entity_class=MatterBinarySensor, entity_class=MatterBinarySensor,
required_attributes=(clusters.SmokeCoAlarm.Attributes.InterconnectCOAlarm,), required_attributes=(clusters.SmokeCoAlarm.Attributes.InterconnectCOAlarm,),
), ),
MatterDiscoverySchema(
platform=Platform.BINARY_SENSOR,
entity_description=MatterBinarySensorEntityDescription(
key="EnergyEvseChargingStatusSensor",
translation_key="evse_charging_status",
device_class=BinarySensorDeviceClass.BATTERY_CHARGING,
measurement_to_ha={
clusters.EnergyEvse.Enums.StateEnum.kNotPluggedIn: False,
clusters.EnergyEvse.Enums.StateEnum.kPluggedInNoDemand: False,
clusters.EnergyEvse.Enums.StateEnum.kPluggedInDemand: False,
clusters.EnergyEvse.Enums.StateEnum.kPluggedInCharging: True,
clusters.EnergyEvse.Enums.StateEnum.kPluggedInDischarging: False,
clusters.EnergyEvse.Enums.StateEnum.kSessionEnding: False,
clusters.EnergyEvse.Enums.StateEnum.kFault: False,
}.get,
),
entity_class=MatterBinarySensor,
required_attributes=(clusters.EnergyEvse.Attributes.State,),
allow_multi=True, # also used for sensor entity
),
MatterDiscoverySchema(
platform=Platform.BINARY_SENSOR,
entity_description=MatterBinarySensorEntityDescription(
key="EnergyEvsePlugStateSensor",
translation_key="evse_plug_state",
device_class=BinarySensorDeviceClass.PLUG,
measurement_to_ha={
clusters.EnergyEvse.Enums.StateEnum.kNotPluggedIn: False,
clusters.EnergyEvse.Enums.StateEnum.kPluggedInNoDemand: True,
clusters.EnergyEvse.Enums.StateEnum.kPluggedInDemand: True,
clusters.EnergyEvse.Enums.StateEnum.kPluggedInCharging: True,
clusters.EnergyEvse.Enums.StateEnum.kPluggedInDischarging: True,
clusters.EnergyEvse.Enums.StateEnum.kSessionEnding: False,
clusters.EnergyEvse.Enums.StateEnum.kFault: False,
}.get,
),
entity_class=MatterBinarySensor,
required_attributes=(clusters.EnergyEvse.Attributes.State,),
allow_multi=True, # also used for sensor entity
),
MatterDiscoverySchema(
platform=Platform.BINARY_SENSOR,
entity_description=MatterBinarySensorEntityDescription(
key="EnergyEvseSupplyStateSensor",
translation_key="evse_supply_charging_state",
device_class=BinarySensorDeviceClass.RUNNING,
measurement_to_ha={
clusters.EnergyEvse.Enums.SupplyStateEnum.kDisabled: False,
clusters.EnergyEvse.Enums.SupplyStateEnum.kChargingEnabled: True,
clusters.EnergyEvse.Enums.SupplyStateEnum.kDischargingEnabled: False,
clusters.EnergyEvse.Enums.SupplyStateEnum.kDisabledDiagnostics: False,
}.get,
),
entity_class=MatterBinarySensor,
required_attributes=(clusters.EnergyEvse.Attributes.SupplyState,),
allow_multi=True, # also used for sensor entity
),
] ]

View File

@ -61,6 +61,7 @@ class MatterEntityDescription(EntityDescription):
# convert the value from the primary attribute to the value used by HA # convert the value from the primary attribute to the value used by HA
measurement_to_ha: Callable[[Any], Any] | None = None measurement_to_ha: Callable[[Any], Any] | None = None
ha_to_native_value: Callable[[Any], Any] | None = None ha_to_native_value: Callable[[Any], Any] | None = None
command_timeout: int | None = None
class MatterEntity(Entity): class MatterEntity(Entity):

View File

@ -71,6 +71,15 @@
}, },
"battery_replacement_description": { "battery_replacement_description": {
"default": "mdi:battery-sync-outline" "default": "mdi:battery-sync-outline"
},
"evse_state": {
"default": "mdi:ev-station"
},
"evse_supply_state": {
"default": "mdi:ev-station"
},
"evse_fault_state": {
"default": "mdi:ev-station"
} }
}, },
"switch": { "switch": {
@ -80,6 +89,9 @@
"on": "mdi:lock", "on": "mdi:lock",
"off": "mdi:lock-off" "off": "mdi:lock-off"
} }
},
"evse_charging_switch": {
"default": "mdi:ev-station"
} }
} }
} }

View File

@ -77,6 +77,25 @@ OPERATIONAL_STATE_MAP = {
clusters.RvcOperationalState.Enums.OperationalStateEnum.kDocked: "docked", clusters.RvcOperationalState.Enums.OperationalStateEnum.kDocked: "docked",
} }
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( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant,
@ -904,4 +923,77 @@ DISCOVERY_SCHEMAS = [
# don't discover this entry if the supported state list is empty # don't discover this entry if the supported state list is empty
secondary_value_is_not=[], secondary_value_is_not=[],
), ),
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,),
),
] ]

View File

@ -76,6 +76,15 @@
}, },
"muted": { "muted": {
"name": "Muted" "name": "Muted"
},
"evse_charging_status": {
"name": "Charging status"
},
"evse_plug": {
"name": "Plug state"
},
"evse_supply_charging_state": {
"name": "Supply charging state"
} }
}, },
"button": { "button": {
@ -278,6 +287,42 @@
}, },
"current_phase": { "current_phase": {
"name": "Current phase" "name": "Current phase"
},
"evse_fault_state": {
"name": "Fault state",
"state": {
"no_error": "OK",
"meter_failure": "Meter failure",
"over_voltage": "Overvoltage",
"under_voltage": "Undervoltage",
"over_current": "Overcurrent",
"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": "Overtemperature",
"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": { "switch": {
@ -289,6 +334,9 @@
}, },
"child_lock": { "child_lock": {
"name": "Child lock" "name": "Child lock"
},
"evse_charging_switch": {
"name": "Enable charging"
} }
}, },
"vacuum": { "vacuum": {

View File

@ -2,10 +2,12 @@
from __future__ import annotations from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass from dataclasses import dataclass
from typing import Any from typing import Any
from chip.clusters import Objects as clusters from chip.clusters import Objects as clusters
from chip.clusters.Objects import ClusterCommand, NullValue
from matter_server.client.models import device_types from matter_server.client.models import device_types
from homeassistant.components.switch import ( from homeassistant.components.switch import (
@ -22,6 +24,13 @@ from .entity import MatterEntity, MatterEntityDescription
from .helpers import get_matter from .helpers import get_matter
from .models import MatterDiscoverySchema from .models import MatterDiscoverySchema
EVSE_SUPPLY_STATE_MAP = {
clusters.EnergyEvse.Enums.SupplyStateEnum.kDisabled: False,
clusters.EnergyEvse.Enums.SupplyStateEnum.kChargingEnabled: True,
clusters.EnergyEvse.Enums.SupplyStateEnum.kDischargingEnabled: False,
clusters.EnergyEvse.Enums.SupplyStateEnum.kDisabledDiagnostics: False,
}
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant,
@ -58,6 +67,66 @@ class MatterSwitch(MatterEntity, SwitchEntity):
) )
class MatterGenericCommandSwitch(MatterSwitch):
"""Representation of a Matter switch."""
entity_description: MatterGenericCommandSwitchEntityDescription
_platform_translation_key = "switch"
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn switch on."""
if self.entity_description.on_command:
# custom command defined to set the new value
await self.send_device_command(
self.entity_description.on_command(),
self.entity_description.command_timeout,
)
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn switch off."""
if self.entity_description.off_command:
await self.send_device_command(
self.entity_description.off_command(),
self.entity_description.command_timeout,
)
@callback
def _update_from_device(self) -> None:
"""Update from device."""
value = self.get_matter_attribute_value(self._entity_info.primary_attribute)
if value_convert := self.entity_description.measurement_to_ha:
value = value_convert(value)
self._attr_is_on = value
async def send_device_command(
self,
command: ClusterCommand,
command_timeout: int | None = None,
**kwargs: Any,
) -> None:
"""Send device command with timeout."""
await self.matter_client.send_device_command(
node_id=self._endpoint.node.node_id,
endpoint_id=self._endpoint.endpoint_id,
command=command,
timed_request_timeout_ms=command_timeout,
**kwargs,
)
@dataclass(frozen=True)
class MatterGenericCommandSwitchEntityDescription(
SwitchEntityDescription, MatterEntityDescription
):
"""Describe Matter Generic command Switch entities."""
# command: a custom callback to create the command to send to the device
on_command: Callable[[], Any] | None = None
off_command: Callable[[], Any] | None = None
command_timeout: int | None = None
@dataclass(frozen=True) @dataclass(frozen=True)
class MatterNumericSwitchEntityDescription( class MatterNumericSwitchEntityDescription(
SwitchEntityDescription, MatterEntityDescription SwitchEntityDescription, MatterEntityDescription
@ -194,4 +263,26 @@ DISCOVERY_SCHEMAS = [
), ),
vendor_id=(4874,), vendor_id=(4874,),
), ),
MatterDiscoverySchema(
platform=Platform.SWITCH,
entity_description=MatterGenericCommandSwitchEntityDescription(
key="EnergyEvseChargingSwitch",
translation_key="evse_charging_switch",
on_command=lambda: clusters.EnergyEvse.Commands.EnableCharging(
chargingEnabledUntil=NullValue,
minimumChargeCurrent=0,
maximumChargeCurrent=0,
),
off_command=clusters.EnergyEvse.Commands.Disable,
command_timeout=3000,
measurement_to_ha=EVSE_SUPPLY_STATE_MAP.get,
),
entity_class=MatterGenericCommandSwitch,
required_attributes=(
clusters.EnergyEvse.Attributes.SupplyState,
clusters.EnergyEvse.Attributes.AcceptedCommandList,
),
value_contains=clusters.EnergyEvse.Commands.EnableCharging.command_id,
allow_multi=True,
),
] ]

View File

@ -104,6 +104,7 @@ async def integration_fixture(
"pressure_sensor", "pressure_sensor",
"room_airconditioner", "room_airconditioner",
"silabs_dishwasher", "silabs_dishwasher",
"silabs_evse_charging",
"silabs_laundrywasher", "silabs_laundrywasher",
"smoke_detector", "smoke_detector",
"switch_unit", "switch_unit",

View File

@ -0,0 +1,580 @@
{
"node_id": 23,
"date_commissioned": "2024-12-17T18:14:53.210190",
"last_interview": "2024-12-17T18:14:53.211611",
"interview_version": 6,
"available": true,
"is_bridge": false,
"attributes": {
"0/29/0": [
{
"0": 22,
"1": 1
}
],
"0/29/1": [29, 31, 40, 43, 44, 45, 48, 49, 51, 60, 62, 63],
"0/29/2": [],
"0/29/3": [1],
"0/29/65532": 0,
"0/29/65533": 2,
"0/29/65528": [],
"0/29/65529": [],
"0/29/65531": [0, 1, 2, 3, 65528, 65529, 65531, 65532, 65533],
"0/31/0": [
{
"1": 5,
"2": 2,
"3": [112233],
"4": null,
"254": 1
}
],
"0/31/2": 4,
"0/31/3": 3,
"0/31/4": 4,
"0/31/65532": 0,
"0/31/65533": 2,
"0/31/65528": [],
"0/31/65529": [],
"0/31/65531": [0, 2, 3, 4, 65528, 65529, 65531, 65532, 65533],
"0/40/0": 18,
"0/40/1": "Silabs",
"0/40/2": 65521,
"0/40/3": "evse",
"0/40/4": 32769,
"0/40/5": "evse",
"0/40/6": "**REDACTED**",
"0/40/7": 0,
"0/40/8": "TEST_VERSION",
"0/40/9": 1,
"0/40/10": "1.0",
"0/40/15": "TEST_SN",
"0/40/18": "evse",
"0/40/19": {
"0": 3,
"1": 65535
},
"0/40/21": 17039360,
"0/40/22": 1,
"0/40/65532": 0,
"0/40/65533": 4,
"0/40/65528": [],
"0/40/65529": [],
"0/40/65531": [
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 18, 19, 21, 22, 65528, 65529, 65531,
65532, 65533
],
"0/43/0": "en-US",
"0/43/1": [
"en-US",
"de-DE",
"fr-FR",
"en-GB",
"es-ES",
"zh-CN",
"it-IT",
"ja-JP"
],
"0/43/65532": 0,
"0/43/65533": 1,
"0/43/65528": [],
"0/43/65529": [],
"0/43/65531": [0, 1, 65528, 65529, 65531, 65532, 65533],
"0/44/0": 0,
"0/44/65532": 0,
"0/44/65533": 1,
"0/44/65528": [],
"0/44/65529": [],
"0/44/65531": [0, 65528, 65529, 65531, 65532, 65533],
"0/45/65532": 0,
"0/45/65533": 1,
"0/45/65528": [],
"0/45/65529": [],
"0/45/65531": [65528, 65529, 65531, 65532, 65533],
"0/48/0": 0,
"0/48/1": {
"0": 60,
"1": 900
},
"0/48/2": 0,
"0/48/3": 2,
"0/48/4": true,
"0/48/65532": 0,
"0/48/65533": 2,
"0/48/65528": [1, 3, 5],
"0/48/65529": [0, 2, 4],
"0/48/65531": [0, 1, 2, 3, 4, 65528, 65529, 65531, 65532, 65533],
"0/49/0": 1,
"0/49/1": [
{
"0": "ZW5zMzM=",
"1": true
}
],
"0/49/4": true,
"0/49/5": null,
"0/49/6": null,
"0/49/7": null,
"0/49/8": [0],
"0/49/65532": 4,
"0/49/65533": 2,
"0/49/65528": [],
"0/49/65529": [],
"0/49/65531": [0, 1, 4, 5, 6, 7, 8, 65528, 65529, 65531, 65532, 65533],
"0/51/0": [
{
"0": "docker0",
"1": false,
"2": null,
"3": null,
"4": "AkI9NTnB",
"5": ["rBEAAQ=="],
"6": [""],
"7": 0
},
{
"0": "ens33",
"1": true,
"2": null,
"3": null,
"4": "AAwp/F0T",
"5": ["wKgBpw=="],
"6": [
"KgEOCgKzOZCNB+q+Uz0I9w==",
"KgEOCgKzOZC/O1Ew1WvS4A==",
"/oAAAAAAAADml3Ozl7GZug=="
],
"7": 2
},
{
"0": "lo",
"1": true,
"2": null,
"3": null,
"4": "AAAAAAAA",
"5": ["fwAAAQ=="],
"6": ["AAAAAAAAAAAAAAAAAAAAAQ=="],
"7": 0
}
],
"0/51/1": 1,
"0/51/2": 10129,
"0/51/8": true,
"0/51/65532": 0,
"0/51/65533": 2,
"0/51/65528": [2],
"0/51/65529": [0, 1],
"0/51/65531": [0, 1, 2, 8, 65528, 65529, 65531, 65532, 65533],
"0/60/0": 0,
"0/60/1": null,
"0/60/2": null,
"0/60/65532": 0,
"0/60/65533": 1,
"0/60/65528": [],
"0/60/65529": [0, 2],
"0/60/65531": [0, 1, 2, 65528, 65529, 65531, 65532, 65533],
"0/62/0": [
{
"1": "FTABAQEkAgE3AyQTAhgmBIAigScmBYAlTTo3BiQVASQRFxgkBwEkCAEwCUEECp4PASYUFk/DwQqGNBikYdiBRDJZbrfF4AYK8Y9jOeIpx7Xy+giJhmTpAVZ662hwszsFDGULGY/owXtMrqTxEDcKNQEoARgkAgE2AwQCBAEYMAQUqBmxO16fPQhbf33Gb2XwQ+NkXpswBRTx8+4bdkuqlxInfB5LXkhRBBvS2hgwC0A8aefsLm663Vuy+TkSvn/oLhRqt2phrG+i5aM5o15xiWDjnNVdUYpT09+K0mgVoMdFuFsmoWQxQh6jahaFJzUgGA==",
"2": "FTABAQEkAgE3AyQUARgmBIAigScmBYAlTTo3BiQTAhgkBwEkCAEwCUEEGp55xGRB0FBQ3Yw7ayQSzVtYA0BtCJFm9vRRcdr+nk0cuGX6zrUowSYOO/qiRBEACcCNNSqKh+DpRm2uVLOtaDcKNQEpARgkAmAwBBTx8+4bdkuqlxInfB5LXkhRBBvS2jAFFIxTG68U5WQVsk8AtvSQyeK3KLqPGDALQIw/6q5ILMNdOMcSif8HNbEgpjBeaBMfUpzOJFCRPM16sv1xiq3mALZj0u+iG8lUJEvDJOFKPoBvsOubwIwRgAQY",
"254": 1
}
],
"0/62/1": [
{
"1": "BMeyHMXjJpVWF9saehBu7pZLTwdopKZTl5JdhU0/ozZ/sk1paVFE1U8OtuZqM/S/4W/fnkCnUrQ/Xcs7Ddy0hPE=",
"2": 65521,
"3": 1,
"4": 23,
"5": "HA_test",
"254": 1
},
{
"1": "BBF47gm4BEBA6LXQluAHjn6P3+MZKrhuMcJligg1xcBM7X++F7GsZFh4hYAhdmD9HHwhtZxH2c85aAzbpikViwI=",
"2": 65521,
"3": 1,
"4": 100,
"5": "",
"254": 2
}
],
"0/62/2": 16,
"0/62/3": 2,
"0/62/4": [
"FTABAQEkAgE3AyQUARgmBIAigScmBYAlTTo3BiQUARgkBwEkCAEwCUEEx7IcxeMmlVYX2xp6EG7ulktPB2ikplOXkl2FTT+jNn+yTWlpUUTVTw625moz9L/hb9+eQKdStD9dyzsN3LSE8TcKNQEpARgkAmAwBBSMUxuvFOVkFbJPALb0kMnityi6jzAFFIxTG68U5WQVsk8AtvSQyeK3KLqPGDALQPBVUg+OBUWl1pe/k55ZigAZl3lfBP1Qd5zQP4AUB45mNTzdli8DRCj+h7cIs3JHQQPlUaRvG5xUoBZ+C7Gg2sQY",
"FTABAQEkAgE3AyQUARgmBIAigScmBYAlTTo3BiQUARgkBwEkCAEwCUEEEXjuCbgEQEDotdCW4AeOfo/f4xkquG4xwmWKCDXFwEztf74XsaxkWHiFgCF2YP0cfCG1nEfZzzloDNumKRWLAjcKNQEpARgkAmAwBBQD3rx0jOdkiCPt06hxW7Z2jJBPXTAFFAPevHSM52SII+3TqHFbtnaMkE9dGDALQL+L3Zc6En6Ionk6WIz+lM50iwOEzTi9VwyYQRUdtO99T8jRX52+Olh6zcUtWQuYO2XYiH2OZ8lM4guqqnS8U4UY"
],
"0/62/5": 1,
"0/62/65532": 0,
"0/62/65533": 1,
"0/62/65528": [1, 3, 5, 8],
"0/62/65529": [0, 2, 4, 6, 7, 9, 10, 11],
"0/62/65531": [0, 1, 2, 3, 4, 5, 65528, 65529, 65531, 65532, 65533],
"0/63/0": [],
"0/63/1": [],
"0/63/2": 4,
"0/63/3": 3,
"0/63/65532": 0,
"0/63/65533": 2,
"0/63/65528": [2, 5],
"0/63/65529": [0, 1, 3, 4],
"0/63/65531": [0, 1, 2, 3, 65528, 65529, 65531, 65532, 65533],
"1/3/0": 0,
"1/3/1": 0,
"1/3/65532": 0,
"1/3/65533": 5,
"1/3/65528": [],
"1/3/65529": [0, 64],
"1/3/65531": [0, 1, 65528, 65529, 65531, 65532, 65533],
"1/29/0": [
{
"0": 1293,
"1": 1
},
{
"0": 1292,
"1": 1
},
{
"0": 1296,
"1": 1
},
{
"0": 17,
"1": 1
}
],
"1/29/1": [3, 29, 47, 144, 145, 152, 153, 156, 157, 159],
"1/29/2": [],
"1/29/3": [],
"1/29/65532": 0,
"1/29/65533": 2,
"1/29/65528": [],
"1/29/65529": [],
"1/29/65531": [0, 1, 2, 3, 65528, 65529, 65531, 65532, 65533],
"1/47/0": 1,
"1/47/1": 0,
"1/47/2": "Primary Mains Power",
"1/47/5": 0,
"1/47/7": 230000,
"1/47/8": 32000,
"1/47/31": [1],
"1/47/65532": 1,
"1/47/65533": 3,
"1/47/65528": [],
"1/47/65529": [],
"1/47/65531": [0, 1, 2, 5, 7, 8, 31, 65528, 65529, 65531, 65532, 65533],
"1/144/0": 2,
"1/144/1": 3,
"1/144/2": [
{
"0": 5,
"1": true,
"2": -50000000,
"3": 50000000,
"4": [
{
"0": -50000000,
"1": -10000000,
"2": 5000,
"3": 2000,
"4": 3000
},
{
"0": -9999999,
"1": 9999999,
"2": 1000,
"3": 100,
"4": 500
},
{
"0": 10000000,
"1": 50000000,
"2": 5000,
"3": 2000,
"4": 3000
}
]
},
{
"0": 2,
"1": true,
"2": -100000,
"3": 100000,
"4": [
{
"0": -100000,
"1": -5000,
"2": 5000,
"3": 2000,
"4": 3000
},
{
"0": -4999,
"1": 4999,
"2": 1000,
"3": 100,
"4": 500
},
{
"0": 5000,
"1": 100000,
"2": 5000,
"3": 2000,
"4": 3000
}
]
},
{
"0": 1,
"1": true,
"2": -500000,
"3": 500000,
"4": [
{
"0": -500000,
"1": -100000,
"2": 5000,
"3": 2000,
"4": 3000
},
{
"0": -99999,
"1": 99999,
"2": 1000,
"3": 100,
"4": 500
},
{
"0": 100000,
"1": 500000,
"2": 5000,
"3": 2000,
"4": 3000
}
]
}
],
"1/144/3": [],
"1/144/4": null,
"1/144/5": null,
"1/144/6": null,
"1/144/7": null,
"1/144/8": null,
"1/144/9": null,
"1/144/10": null,
"1/144/11": null,
"1/144/12": null,
"1/144/13": null,
"1/144/14": null,
"1/144/15": [
{
"0": 1,
"1": 100000
}
],
"1/144/16": [
{
"0": 1,
"1": 100000
}
],
"1/144/17": null,
"1/144/18": null,
"1/144/65532": 31,
"1/144/65533": 1,
"1/144/65528": [],
"1/144/65529": [],
"1/144/65531": [
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 65528,
65529, 65531, 65532, 65533
],
"1/145/0": {
"0": 14,
"1": true,
"2": 0,
"3": 1000000000000000,
"4": [
{
"0": 98440650424323,
"1": 98442759724168,
"2": 0,
"3": 0,
"5": 140728898420739,
"6": 98440650424355
}
]
},
"1/145/1": null,
"1/145/2": null,
"1/145/3": null,
"1/145/4": null,
"1/145/5": {
"0": 0,
"1": 0,
"2": 0,
"3": 0
},
"1/145/65532": 15,
"1/145/65533": 1,
"1/145/65528": [],
"1/145/65529": [],
"1/145/65531": [0, 1, 2, 3, 4, 5, 65528, 65529, 65531, 65532, 65533],
"1/152/0": 0,
"1/152/1": false,
"1/152/2": 1,
"1/152/3": 1200000,
"1/152/4": 7600000,
"1/152/5": null,
"1/152/6": null,
"1/152/7": 0,
"1/152/65532": 123,
"1/152/65533": 4,
"1/152/65528": [],
"1/152/65529": [0, 1, 2, 3, 4, 5, 6, 7],
"1/152/65531": [0, 1, 2, 3, 4, 5, 6, 7, 65528, 65529, 65531, 65532, 65533],
"1/153/0": 3,
"1/153/1": 1,
"1/153/2": 0,
"1/153/3": null,
"1/153/5": 32000,
"1/153/6": 2000,
"1/153/7": 30000,
"1/153/9": 32000,
"1/153/10": 600,
"1/153/35": null,
"1/153/36": null,
"1/153/37": null,
"1/153/38": null,
"1/153/39": null,
"1/153/64": 2,
"1/153/65": 0,
"1/153/66": 0,
"1/153/65532": 9,
"1/153/65533": 3,
"1/153/65528": [0],
"1/153/65529": [1, 2, 5, 6, 7, 4],
"1/153/65531": [
0, 1, 2, 3, 5, 6, 7, 9, 10, 35, 36, 37, 38, 39, 64, 65, 66, 65528, 65529,
65531, 65532, 65533
],
"1/156/65532": 1,
"1/156/65533": 1,
"1/156/65528": [],
"1/156/65529": [],
"1/156/65531": [65528, 65529, 65531, 65532, 65533],
"1/157/0": [
{
"0": "Manual",
"1": 0,
"2": [
{
"1": 16384
}
]
},
{
"0": "Auto-scheduled",
"1": 1,
"2": [
{
"1": 16385
}
]
},
{
"0": "Solar",
"1": 2,
"2": [
{
"1": 16386
}
]
},
{
"0": "Auto-scheduled with Solar charging",
"1": 3,
"2": [
{
"1": 16385
},
{
"1": 16386
}
]
}
],
"1/157/1": 1,
"1/157/65532": 0,
"1/157/65533": 2,
"1/157/65528": [1],
"1/157/65529": [0],
"1/157/65531": [0, 1, 65528, 65529, 65531, 65532, 65533],
"1/159/0": [
{
"0": "No energy management (forecast only)",
"1": 0,
"2": [
{
"1": 16384
}
]
},
{
"0": "Device optimizes (no local or grid control)",
"1": 1,
"2": [
{
"1": 16385
}
]
},
{
"0": "Optimized within building",
"1": 2,
"2": [
{
"1": 16386
},
{
"1": 16385
}
]
},
{
"0": "Optimized for grid",
"1": 3,
"2": [
{
"1": 16385
},
{
"1": 16387
}
]
},
{
"0": "Optimized for grid and building",
"1": 4,
"2": [
{
"1": 16386
},
{
"1": 16385
},
{
"1": 16387
}
]
}
],
"1/159/1": 3,
"1/159/65532": 0,
"1/159/65533": 2,
"1/159/65528": [1],
"1/159/65529": [0],
"1/159/65531": [0, 1, 65528, 65529, 65531, 65532, 65533]
},
"attribute_subscriptions": []
}

View File

@ -383,6 +383,150 @@
'state': 'off', 'state': 'off',
}) })
# --- # ---
# name: test_binary_sensors[silabs_evse_charging][binary_sensor.evse_charging_status-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': None,
'entity_id': 'binary_sensor.evse_charging_status',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.BATTERY_CHARGING: 'battery_charging'>,
'original_icon': None,
'original_name': 'Charging status',
'platform': 'matter',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'evse_charging_status',
'unique_id': '00000000000004D2-0000000000000017-MatterNodeDevice-1-EnergyEvseChargingStatusSensor-153-0',
'unit_of_measurement': None,
})
# ---
# name: test_binary_sensors[silabs_evse_charging][binary_sensor.evse_charging_status-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'battery_charging',
'friendly_name': 'evse Charging status',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.evse_charging_status',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_binary_sensors[silabs_evse_charging][binary_sensor.evse_plug-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': None,
'entity_id': 'binary_sensor.evse_plug',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.PLUG: 'plug'>,
'original_icon': None,
'original_name': 'Plug',
'platform': 'matter',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'evse_plug_state',
'unique_id': '00000000000004D2-0000000000000017-MatterNodeDevice-1-EnergyEvsePlugStateSensor-153-0',
'unit_of_measurement': None,
})
# ---
# name: test_binary_sensors[silabs_evse_charging][binary_sensor.evse_plug-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'plug',
'friendly_name': 'evse Plug',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.evse_plug',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_binary_sensors[silabs_evse_charging][binary_sensor.evse_supply_charging_state-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': None,
'entity_id': 'binary_sensor.evse_supply_charging_state',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.RUNNING: 'running'>,
'original_icon': None,
'original_name': 'Supply charging state',
'platform': 'matter',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'evse_supply_charging_state',
'unique_id': '00000000000004D2-0000000000000017-MatterNodeDevice-1-EnergyEvseSupplyStateSensor-153-1',
'unit_of_measurement': None,
})
# ---
# name: test_binary_sensors[silabs_evse_charging][binary_sensor.evse_supply_charging_state-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'running',
'friendly_name': 'evse Supply charging state',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.evse_supply_charging_state',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_binary_sensors[smoke_detector][binary_sensor.smoke_sensor_battery_alert-entry] # name: test_binary_sensors[smoke_detector][binary_sensor.smoke_sensor_battery_alert-entry]
EntityRegistryEntrySnapshot({ EntityRegistryEntrySnapshot({
'aliases': set({ 'aliases': set({

View File

@ -1543,6 +1543,128 @@
'state': 'previous', 'state': 'previous',
}) })
# --- # ---
# name: test_selects[silabs_evse_charging][select.evse_energy_management_mode-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'options': list([
'No energy management (forecast only)',
'Device optimizes (no local or grid control)',
'Optimized within building',
'Optimized for grid',
'Optimized for grid and building',
]),
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'select',
'entity_category': None,
'entity_id': 'select.evse_energy_management_mode',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Energy management mode',
'platform': 'matter',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'device_energy_management_mode',
'unique_id': '00000000000004D2-0000000000000017-MatterNodeDevice-1-MatterDeviceEnergyManagementMode-159-1',
'unit_of_measurement': None,
})
# ---
# name: test_selects[silabs_evse_charging][select.evse_energy_management_mode-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'evse Energy management mode',
'options': list([
'No energy management (forecast only)',
'Device optimizes (no local or grid control)',
'Optimized within building',
'Optimized for grid',
'Optimized for grid and building',
]),
}),
'context': <ANY>,
'entity_id': 'select.evse_energy_management_mode',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'Optimized for grid',
})
# ---
# name: test_selects[silabs_evse_charging][select.evse_mode-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'options': list([
'Manual',
'Auto-scheduled',
'Solar',
'Auto-scheduled with Solar charging',
]),
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'select',
'entity_category': None,
'entity_id': 'select.evse_mode',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Mode',
'platform': 'matter',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'mode',
'unique_id': '00000000000004D2-0000000000000017-MatterNodeDevice-1-MatterEnergyEvseMode-157-1',
'unit_of_measurement': None,
})
# ---
# name: test_selects[silabs_evse_charging][select.evse_mode-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'evse Mode',
'options': list([
'Manual',
'Auto-scheduled',
'Solar',
'Auto-scheduled with Solar charging',
]),
}),
'context': <ANY>,
'entity_id': 'select.evse_mode',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'Auto-scheduled',
})
# ---
# name: test_selects[silabs_laundrywasher][select.laundrywasher_number_of_rinses-entry] # name: test_selects[silabs_laundrywasher][select.laundrywasher_number_of_rinses-entry]
EntityRegistryEntrySnapshot({ EntityRegistryEntrySnapshot({
'aliases': set({ 'aliases': set({

View File

@ -2866,6 +2866,323 @@
'state': '120.0', 'state': '120.0',
}) })
# --- # ---
# name: test_sensors[silabs_evse_charging][sensor.evse_circuit_capacity-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.evse_circuit_capacity',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
'sensor': dict({
'suggested_display_precision': 2,
}),
'sensor.private': dict({
'suggested_unit_of_measurement': <UnitOfElectricCurrent.AMPERE: 'A'>,
}),
}),
'original_device_class': <SensorDeviceClass.CURRENT: 'current'>,
'original_icon': None,
'original_name': 'Circuit capacity',
'platform': 'matter',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'evse_circuit_capacity',
'unique_id': '00000000000004D2-0000000000000017-MatterNodeDevice-1-EnergyEvseCircuitCapacity-153-5',
'unit_of_measurement': <UnitOfElectricCurrent.AMPERE: 'A'>,
})
# ---
# name: test_sensors[silabs_evse_charging][sensor.evse_circuit_capacity-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'current',
'friendly_name': 'evse Circuit capacity',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': <UnitOfElectricCurrent.AMPERE: 'A'>,
}),
'context': <ANY>,
'entity_id': 'sensor.evse_circuit_capacity',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '32.0',
})
# ---
# name: test_sensors[silabs_evse_charging][sensor.evse_fault_state-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'options': list([
'no_error',
'meter_failure',
'over_voltage',
'under_voltage',
'over_current',
'contact_wet_failure',
'contact_dry_failure',
'power_loss',
'power_quality',
'pilot_short_circuit',
'emergency_stop',
'ev_disconnected',
'wrong_power_supply',
'live_neutral_swap',
'over_temperature',
'other',
]),
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.evse_fault_state',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <SensorDeviceClass.ENUM: 'enum'>,
'original_icon': None,
'original_name': 'Fault state',
'platform': 'matter',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'evse_fault_state',
'unique_id': '00000000000004D2-0000000000000017-MatterNodeDevice-1-EnergyEvseFaultState-153-2',
'unit_of_measurement': None,
})
# ---
# name: test_sensors[silabs_evse_charging][sensor.evse_fault_state-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'enum',
'friendly_name': 'evse Fault state',
'options': list([
'no_error',
'meter_failure',
'over_voltage',
'under_voltage',
'over_current',
'contact_wet_failure',
'contact_dry_failure',
'power_loss',
'power_quality',
'pilot_short_circuit',
'emergency_stop',
'ev_disconnected',
'wrong_power_supply',
'live_neutral_swap',
'over_temperature',
'other',
]),
}),
'context': <ANY>,
'entity_id': 'sensor.evse_fault_state',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'no_error',
})
# ---
# name: test_sensors[silabs_evse_charging][sensor.evse_max_charge_current-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.evse_max_charge_current',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
'sensor': dict({
'suggested_display_precision': 2,
}),
'sensor.private': dict({
'suggested_unit_of_measurement': <UnitOfElectricCurrent.AMPERE: 'A'>,
}),
}),
'original_device_class': <SensorDeviceClass.CURRENT: 'current'>,
'original_icon': None,
'original_name': 'Max charge current',
'platform': 'matter',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'evse_max_charge_current',
'unique_id': '00000000000004D2-0000000000000017-MatterNodeDevice-1-EnergyEvseMaximumChargeCurrent-153-7',
'unit_of_measurement': <UnitOfElectricCurrent.AMPERE: 'A'>,
})
# ---
# name: test_sensors[silabs_evse_charging][sensor.evse_max_charge_current-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'current',
'friendly_name': 'evse Max charge current',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': <UnitOfElectricCurrent.AMPERE: 'A'>,
}),
'context': <ANY>,
'entity_id': 'sensor.evse_max_charge_current',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '30.0',
})
# ---
# name: test_sensors[silabs_evse_charging][sensor.evse_min_charge_current-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.evse_min_charge_current',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
'sensor': dict({
'suggested_display_precision': 2,
}),
'sensor.private': dict({
'suggested_unit_of_measurement': <UnitOfElectricCurrent.AMPERE: 'A'>,
}),
}),
'original_device_class': <SensorDeviceClass.CURRENT: 'current'>,
'original_icon': None,
'original_name': 'Min charge current',
'platform': 'matter',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'evse_min_charge_current',
'unique_id': '00000000000004D2-0000000000000017-MatterNodeDevice-1-EnergyEvseMinimumChargeCurrent-153-6',
'unit_of_measurement': <UnitOfElectricCurrent.AMPERE: 'A'>,
})
# ---
# name: test_sensors[silabs_evse_charging][sensor.evse_min_charge_current-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'current',
'friendly_name': 'evse Min charge current',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': <UnitOfElectricCurrent.AMPERE: 'A'>,
}),
'context': <ANY>,
'entity_id': 'sensor.evse_min_charge_current',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '2.0',
})
# ---
# name: test_sensors[silabs_evse_charging][sensor.evse_user_max_charge_current-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'sensor.evse_user_max_charge_current',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
'sensor': dict({
'suggested_display_precision': 2,
}),
'sensor.private': dict({
'suggested_unit_of_measurement': <UnitOfElectricCurrent.AMPERE: 'A'>,
}),
}),
'original_device_class': <SensorDeviceClass.CURRENT: 'current'>,
'original_icon': None,
'original_name': 'User max charge current',
'platform': 'matter',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'evse_user_max_charge_current',
'unique_id': '00000000000004D2-0000000000000017-MatterNodeDevice-1-EnergyEvseUserMaximumChargeCurrent-153-9',
'unit_of_measurement': <UnitOfElectricCurrent.AMPERE: 'A'>,
})
# ---
# name: test_sensors[silabs_evse_charging][sensor.evse_user_max_charge_current-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'current',
'friendly_name': 'evse User max charge current',
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
'unit_of_measurement': <UnitOfElectricCurrent.AMPERE: 'A'>,
}),
'context': <ANY>,
'entity_id': 'sensor.evse_user_max_charge_current',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '32.0',
})
# ---
# name: test_sensors[silabs_laundrywasher][sensor.laundrywasher_current-entry] # name: test_sensors[silabs_laundrywasher][sensor.laundrywasher_current-entry]
EntityRegistryEntrySnapshot({ EntityRegistryEntrySnapshot({
'aliases': set({ 'aliases': set({

View File

@ -334,6 +334,53 @@
'state': 'off', 'state': 'off',
}) })
# --- # ---
# name: test_switches[silabs_evse_charging][switch.evse_enable_charging-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'switch',
'entity_category': None,
'entity_id': 'switch.evse_enable_charging',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Enable charging',
'platform': 'matter',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'evse_charging_switch',
'unique_id': '00000000000004D2-0000000000000017-MatterNodeDevice-1-EnergyEvseChargingSwitch-153-1',
'unit_of_measurement': None,
})
# ---
# name: test_switches[silabs_evse_charging][switch.evse_enable_charging-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'evse Enable charging',
}),
'context': <ANY>,
'entity_id': 'switch.evse_enable_charging',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_switches[switch_unit][switch.mock_switchunit-entry] # name: test_switches[switch_unit][switch.mock_switchunit-entry]
EntityRegistryEntrySnapshot({ EntityRegistryEntrySnapshot({
'aliases': set({ 'aliases': set({

View File

@ -147,3 +147,53 @@ async def test_optional_sensor_from_featuremap(
) )
state = hass.states.get(entity_id) state = hass.states.get(entity_id)
assert state is None assert state is None
@pytest.mark.parametrize("node_fixture", ["silabs_evse_charging"])
async def test_evse_sensor(
hass: HomeAssistant,
matter_client: MagicMock,
matter_node: MatterNode,
) -> None:
"""Test evse sensors."""
# Test StateEnum value with binary_sensor.evse_charging_status
entity_id = "binary_sensor.evse_charging_status"
state = hass.states.get(entity_id)
assert state
assert state.state == "on"
# switch to PluggedInDemand state
set_node_attribute(matter_node, 1, 153, 0, 2)
await trigger_subscription_callback(
hass, matter_client, data=(matter_node.node_id, "1/153/0", 2)
)
state = hass.states.get(entity_id)
assert state
assert state.state == "off"
# Test StateEnum value with binary_sensor.evse_plug
entity_id = "binary_sensor.evse_plug"
state = hass.states.get(entity_id)
assert state
assert state.state == "on"
# switch to NotPluggedIn state
set_node_attribute(matter_node, 1, 153, 0, 0)
await trigger_subscription_callback(
hass, matter_client, data=(matter_node.node_id, "1/153/0", 0)
)
state = hass.states.get(entity_id)
assert state
assert state.state == "off"
# Test SupplyStateEnum value with binary_sensor.evse_supply_charging
entity_id = "binary_sensor.evse_supply_charging_state"
state = hass.states.get(entity_id)
assert state
assert state.state == "on"
# switch to Disabled state
set_node_attribute(matter_node, 1, 153, 1, 0)
await trigger_subscription_callback(
hass, matter_client, data=(matter_node.node_id, "1/153/1", 0)
)
state = hass.states.get(entity_id)
assert state
assert state.state == "off"

View File

@ -399,3 +399,71 @@ async def test_list_sensor(
state = hass.states.get("sensor.laundrywasher_current_phase") state = hass.states.get("sensor.laundrywasher_current_phase")
assert state assert state
assert state.state == "rinse" assert state.state == "rinse"
@pytest.mark.parametrize("node_fixture", ["silabs_evse_charging"])
async def test_evse_sensor(
hass: HomeAssistant,
matter_client: MagicMock,
matter_node: MatterNode,
) -> None:
"""Test evse sensors."""
# EnergyEvseFaultState
state = hass.states.get("sensor.evse_fault_state")
assert state
assert state.state == "no_error"
set_node_attribute(matter_node, 1, 153, 2, 4)
await trigger_subscription_callback(hass, matter_client)
state = hass.states.get("sensor.evse_fault_state")
assert state
assert state.state == "over_current"
# EnergyEvseCircuitCapacity
state = hass.states.get("sensor.evse_circuit_capacity")
assert state
assert state.state == "32.0"
set_node_attribute(matter_node, 1, 153, 5, 63000)
await trigger_subscription_callback(hass, matter_client)
state = hass.states.get("sensor.evse_circuit_capacity")
assert state
assert state.state == "63.0"
# EnergyEvseMinimumChargeCurrent
state = hass.states.get("sensor.evse_min_charge_current")
assert state
assert state.state == "2.0"
set_node_attribute(matter_node, 1, 153, 6, 5000)
await trigger_subscription_callback(hass, matter_client)
state = hass.states.get("sensor.evse_min_charge_current")
assert state
assert state.state == "5.0"
# EnergyEvseMaximumChargeCurrent
state = hass.states.get("sensor.evse_max_charge_current")
assert state
assert state.state == "30.0"
set_node_attribute(matter_node, 1, 153, 7, 20000)
await trigger_subscription_callback(hass, matter_client)
state = hass.states.get("sensor.evse_max_charge_current")
assert state
assert state.state == "20.0"
# EnergyEvseUserMaximumChargeCurrent
state = hass.states.get("sensor.evse_user_max_charge_current")
assert state
assert state.state == "32.0"
set_node_attribute(matter_node, 1, 153, 9, 63000)
await trigger_subscription_callback(hass, matter_client)
state = hass.states.get("sensor.evse_user_max_charge_current")
assert state
assert state.state == "63.0"

View File

@ -3,6 +3,7 @@
from unittest.mock import MagicMock, call from unittest.mock import MagicMock, call
from chip.clusters import Objects as clusters from chip.clusters import Objects as clusters
from chip.clusters.Objects import NullValue
from matter_server.client.models.node import MatterNode from matter_server.client.models.node import MatterNode
from matter_server.common.errors import MatterError from matter_server.common.errors import MatterError
from matter_server.common.helpers.util import create_attribute_path_from_attribute from matter_server.common.helpers.util import create_attribute_path_from_attribute
@ -188,3 +189,46 @@ async def test_matter_exception_on_command(
}, },
blocking=True, blocking=True,
) )
@pytest.mark.parametrize("node_fixture", ["silabs_evse_charging"])
async def test_evse_sensor(
hass: HomeAssistant,
matter_client: MagicMock,
matter_node: MatterNode,
) -> None:
"""Test evse sensors."""
state = hass.states.get("switch.evse_enable_charging")
assert state
assert state.state == "on"
# test switch service
await hass.services.async_call(
"switch",
"turn_off",
{"entity_id": "switch.evse_enable_charging"},
blocking=True,
)
assert matter_client.send_device_command.call_count == 1
assert matter_client.send_device_command.call_args == call(
node_id=matter_node.node_id,
endpoint_id=1,
command=clusters.EnergyEvse.Commands.Disable(),
timed_request_timeout_ms=3000,
)
await hass.services.async_call(
"switch",
"turn_on",
{"entity_id": "switch.evse_enable_charging"},
blocking=True,
)
assert matter_client.send_device_command.call_count == 2
assert matter_client.send_device_command.call_args == call(
node_id=matter_node.node_id,
endpoint_id=1,
command=clusters.EnergyEvse.Commands.EnableCharging(
chargingEnabledUntil=NullValue,
minimumChargeCurrent=0,
maximumChargeCurrent=0,
),
timed_request_timeout_ms=3000,
)