diff --git a/src/abbfreeathome/const.py b/src/abbfreeathome/const.py index 6e035cf..3d0d35d 100644 --- a/src/abbfreeathome/const.py +++ b/src/abbfreeathome/const.py @@ -21,7 +21,7 @@ from .devices.room_temperature_controller import RoomTemperatureController from .devices.smoke_detector import SmokeDetector from .devices.switch_actuator import SwitchActuator -from .devices.switch_sensor import SwitchSensor +from .devices.switch_sensor import DimmingSensor, SwitchSensor from .devices.temperature_sensor import TemperatureSensor from .devices.trigger import Trigger from .devices.wind_sensor import WindSensor @@ -44,6 +44,7 @@ Function.FID_DES_DOOR_OPENER_ACTUATOR: DesDoorOpenerActuator, Function.FID_DES_DOOR_RINGING_SENSOR: DesDoorRingingSensor, Function.FID_DIMMING_ACTUATOR: DimmingActuator, + Function.FID_DIMMING_SENSOR: DimmingSensor, Function.FID_FORCE_ON_OFF_SENSOR: ForceOnOffSensor, Function.FID_HEATING_ACTUATOR: HeatingActuator, Function.FID_MOVEMENT_DETECTOR: MovementDetector, diff --git a/src/abbfreeathome/devices/switch_sensor.py b/src/abbfreeathome/devices/switch_sensor.py index c32e2e4..df1ab76 100644 --- a/src/abbfreeathome/devices/switch_sensor.py +++ b/src/abbfreeathome/devices/switch_sensor.py @@ -1,5 +1,6 @@ """Free@Home SwitchSensor Class.""" +import enum from typing import Any from ..api import FreeAtHomeApi @@ -7,10 +8,21 @@ from .base import Base +class DimmingSensorLongpressState(enum.Enum): + """An Enum class for the longpress states.""" + + unknown = None + longpress_up_press = "9" + longpress_up_release = "8" + longpress_down_press = "1" + longpress_down_release = "0" + + class SwitchSensor(Base): """Free@Home SwitchSensor Class.""" _state_refresh_output_pairings: list[Pairing] = [ + Pairing.AL_RELATIVE_SET_VALUE_CONTROL, Pairing.AL_SWITCH_ON_OFF, ] @@ -29,6 +41,9 @@ def __init__( ) -> None: """Initialize the Free@Home SwitchSensor class.""" self._state: bool | None = None + self._longpress: DimmingSensorLongpressState = ( + DimmingSensorLongpressState.unknown + ) super().__init__( device_id, @@ -57,4 +72,19 @@ def _refresh_state_from_output(self, output: dict[str, Any]) -> bool: if output.get("pairingID") == Pairing.AL_SWITCH_ON_OFF.value: self._state = output.get("value") == "1" return True + if output.get("pairingID") == Pairing.AL_RELATIVE_SET_VALUE_CONTROL.value: + try: + self._longpress = DimmingSensorLongpressState(output.get("value")) + except ValueError: + self._longpress = DimmingSensorLongpressState.unknown + return True return False + + +class DimmingSensor(SwitchSensor): + """Free@Home DimmingSensor Class.""" + + @property + def longpress(self) -> str | None: + """Get the longpress value.""" + return self._longpress.name diff --git a/tests/test_freeathome.py b/tests/test_freeathome.py index aae1180..79f6d6e 100644 --- a/tests/test_freeathome.py +++ b/tests/test_freeathome.py @@ -336,7 +336,7 @@ async def test_load_devices(freeathome): devices = freeathome.get_devices() # Verify that the devices are loaded correctly - assert len(devices) == 4 + assert len(devices) == 5 # Check a single device device_key = "ABB7F500E17A/ch0003" @@ -350,7 +350,7 @@ async def test_load_devices(freeathome): # Unload a single device and test it's been removed freeathome.unload_device_by_device_serial(device_serial="ABB7F62F6C0B") devices = freeathome.get_devices() - assert len(devices) == 2 + assert len(devices) == 3 @pytest.mark.asyncio @@ -362,7 +362,7 @@ async def test_load_devices_with_orphans(freeathome_orphans): devices = freeathome_orphans.get_devices() # Verify that the devices are loaded correctly - assert len(devices) == 6 + assert len(devices) == 7 # Check a single orphan device device_key = "ABB28CBC3651/ch0006" diff --git a/tests/test_switch_sensor.py b/tests/test_switch_sensor.py index 8f1d957..fb91e41 100644 --- a/tests/test_switch_sensor.py +++ b/tests/test_switch_sensor.py @@ -5,7 +5,7 @@ import pytest from src.abbfreeathome.api import FreeAtHomeApi -from src.abbfreeathome.devices.switch_sensor import SwitchSensor +from src.abbfreeathome.devices.switch_sensor import DimmingSensor, SwitchSensor @pytest.fixture @@ -20,6 +20,8 @@ def switch_sensor(mock_api): inputs = {} outputs = { "odp0000": {"pairingID": 1, "value": "0"}, + "odp0001": {"pairingID": 16, "value": ""}, + "odp0006": {"pairingID": 4, "value": ""}, } parameters = {} @@ -35,6 +37,29 @@ def switch_sensor(mock_api): ) +@pytest.fixture +def dimming_sensor(mock_api): + """Set up the dimming-sensor instance for testing the DimmingSensor device.""" + inputs = {} + outputs = { + "odp0000": {"pairingID": 1, "value": "0"}, + "odp0001": {"pairingID": 16, "value": ""}, + "odp0006": {"pairingID": 4, "value": ""}, + } + parameters = {} + + return DimmingSensor( + device_id="ABB700D9C0A4", + device_name="Device Name", + channel_id="ch0000", + channel_name="Channel Name", + inputs=inputs, + outputs=outputs, + parameters=parameters, + api=mock_api, + ) + + @pytest.mark.asyncio async def test_initial_state(switch_sensor): """Test the intial state of the switch-sensor.""" @@ -54,10 +79,31 @@ async def test_refresh_state(switch_sensor): ) -def test_refresh_state_from_output(switch_sensor): +def test_refresh_state_from_output_switch(switch_sensor): """Test the _refresh_state_from_output function.""" # Check output that affects the state. switch_sensor._refresh_state_from_output( output={"pairingID": 1, "value": "1"}, ) assert switch_sensor.state is True + + +def test_refresh_state_from_output_dimming(dimming_sensor): + """Test the _refresh_state_from_output function.""" + # Check output that affects the state. + dimming_sensor._refresh_state_from_output( + output={"pairingID": 16, "value": "1"}, + ) + assert dimming_sensor.longpress == "longpress_down_press" + dimming_sensor._refresh_state_from_output( + output={"pairingID": 16, "value": "0"}, + ) + assert dimming_sensor.longpress == "longpress_down_release" + dimming_sensor._refresh_state_from_output( + output={"pairingID": 16, "value": "9"}, + ) + assert dimming_sensor.longpress == "longpress_up_press" + dimming_sensor._refresh_state_from_output( + output={"pairingID": 16, "value": "8"}, + ) + assert dimming_sensor.longpress == "longpress_up_release"