Skip to content

Commit

Permalink
ImplementDesDoorOpenerActuator (#98)
Browse files Browse the repository at this point in the history
Co-authored-by: Adam Kingsley <[email protected]>
  • Loading branch information
derjoerg and kingsleyadam authored Nov 6, 2024
1 parent 4ab66eb commit a332aa9
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/abbfreeathome/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
BlindActuator,
ShutterActuator,
)
from .devices.des_door_opener_actuator import DesDoorOpenerActuator
from .devices.des_door_ringing_sensor import DesDoorRingingSensor
from .devices.dimming_actuator import DimmingActuator
from .devices.force_on_off_sensor import ForceOnOffSensor
Expand Down Expand Up @@ -40,6 +41,7 @@
Function.FID_BLIND_SENSOR_PUSHBUTTON_TYPE3: BlindSensor,
Function.FID_BRIGHTNESS_SENSOR: BrightnessSensor,
Function.FID_CARBON_MONOXIDE_SENSOR: CarbonMonoxideSensor,
Function.FID_DES_DOOR_OPENER_ACTUATOR: DesDoorOpenerActuator,
Function.FID_DES_DOOR_RINGING_SENSOR: DesDoorRingingSensor,
Function.FID_DIMMING_ACTUATOR: DimmingActuator,
Function.FID_FORCE_ON_OFF_SENSOR: ForceOnOffSensor,
Expand Down
82 changes: 82 additions & 0 deletions src/abbfreeathome/devices/des_door_opener_actuator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
"""Free@Home DesDoorOpenerActuator Class."""

from typing import Any

from ..api import FreeAtHomeApi
from ..bin.pairing import Pairing
from .base import Base


class DesDoorOpenerActuator(Base):
"""Free@Home DesDoorOpenerActuator Class."""

_state_refresh_output_pairings: list[Pairing] = [
Pairing.AL_INFO_ON_OFF,
]

def __init__(
self,
device_id: str,
device_name: str,
channel_id: str,
channel_name: str,
inputs: dict[str, dict[str, Any]],
outputs: dict[str, dict[str, Any]],
parameters: dict[str, dict[str, Any]],
api: FreeAtHomeApi,
floor_name: str | None = None,
room_name: str | None = None,
) -> None:
"""Initialize the Free@Home DesDoorOpenerActuator class."""
self._state: bool | None = None

super().__init__(
device_id,
device_name,
channel_id,
channel_name,
inputs,
outputs,
parameters,
api,
floor_name,
room_name,
)

@property
def state(self) -> bool | None:
"""Get the state of the DesDoorOpenerActuator."""
return self._state

async def lock(self):
"""Lock the door."""
await self._set_switching_datapoint("0")
self._state = False

async def unlock(self):
"""Unlock the door."""
await self._set_switching_datapoint("1")
self._state = True

def _refresh_state_from_output(self, output: dict[str, Any]) -> bool:
"""
Refresh the state of the device from a given output.
This will return whether the state was refreshed as a boolean value.
"""
if output.get("pairingID") == Pairing.AL_INFO_ON_OFF.value:
self._state = output.get("value") == "1"
return True
return False

async def _set_switching_datapoint(self, value: str):
"""Set the switching datapoint on the api."""
_switch_input_id, _switch_input_value = self.get_input_by_pairing(
pairing=Pairing.AL_TIMED_START_STOP
)
return await self._api.set_datapoint(
device_id=self.device_id,
channel_id=self.channel_id,
datapoint=_switch_input_id,
value=value,
)
83 changes: 83 additions & 0 deletions tests/test_des_door_opener_actuator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
"""Test class to test the DesDoorOpenerActuator device."""

from unittest.mock import AsyncMock

import pytest

from src.abbfreeathome.api import FreeAtHomeApi
from src.abbfreeathome.devices.des_door_opener_actuator import DesDoorOpenerActuator


@pytest.fixture
def mock_api():
"""Create a mock api function."""
return AsyncMock(spec=FreeAtHomeApi)


@pytest.fixture
def des_door_opener_actuator(mock_api):
"""Set up the instance for testing the DesDoorOpenerActuator device."""
inputs = {
"idp0000": {"pairingID": 2, "value": "0"},
}
outputs = {
"odp0000": {"pairingID": 256, "value": "0"},
"odp0001": {"pairingID": 0, "value": "0"},
}
parameters = {}

return DesDoorOpenerActuator(
device_id="0007EE9503A4",
device_name="Device Name",
channel_id="ch0040",
channel_name="Channel Name",
inputs=inputs,
outputs=outputs,
parameters=parameters,
api=mock_api,
)


@pytest.mark.asyncio
async def test_initial_state(des_door_opener_actuator):
"""Test the intial state of the DesDoorOpenerActuator."""
assert des_door_opener_actuator.state is False


@pytest.mark.asyncio
async def test_lock(des_door_opener_actuator):
"""Test to lock."""
await des_door_opener_actuator.lock()
assert des_door_opener_actuator.state is False
des_door_opener_actuator._api.set_datapoint.assert_called_with(
device_id="0007EE9503A4",
channel_id="ch0040",
datapoint="idp0000",
value="0",
)


@pytest.mark.asyncio
async def test_unlock(des_door_opener_actuator):
"""Test to unlock."""
await des_door_opener_actuator.unlock()
assert des_door_opener_actuator.state is True
des_door_opener_actuator._api.set_datapoint.assert_called_with(
device_id="0007EE9503A4",
channel_id="ch0040",
datapoint="idp0000",
value="1",
)


@pytest.mark.asyncio
async def test_refresh_state(des_door_opener_actuator):
"""Test refreshing the state of the DesDoorOpenerActuator."""
des_door_opener_actuator._api.get_datapoint.return_value = ["1"]
await des_door_opener_actuator.refresh_state()
assert des_door_opener_actuator.state is True
des_door_opener_actuator._api.get_datapoint.assert_called_with(
device_id="0007EE9503A4",
channel_id="ch0040",
datapoint="odp0000",
)

0 comments on commit a332aa9

Please sign in to comment.