Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
76 changes: 73 additions & 3 deletions blebox_uniapi/cover.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,21 @@ class ShutterBoxControlType(IntEnum):

SEGMENTED_SHUTTER = 1
NO_CALIBRATION = 2
TILT_SHUTTER = 3
TILT_SHUTTER_90 = 3
WINDOW_OPENER = 4
MATERIAL_SHUTTER = 5
AWNING = 6
SCREEN = 7
CURTAIN = 8
ROOF_SEGMENTED_SHUTTER = 9
SERVOMOTOR = 10
CURTAIN_ONE_SIDED = 11
CURTAIN_TWO_SIDED = 12
TILT_ONLY = 13
PERGOLA_ROOF = 14
PERGOLA_ROOF_TILT_ONLY = 15
TILT_SHUTTER_180 = 16
TILT_SHUTTER_WITHOUT_POSITIONING = 17


class GateBoxControlType(IntEnum):
Expand Down Expand Up @@ -155,7 +164,34 @@ def min_position(self) -> int:

@property
def has_tilt(self) -> bool:
return self._control_type == ShutterBoxControlType.TILT_SHUTTER
return self._control_type in (
ShutterBoxControlType.TILT_SHUTTER_90,
ShutterBoxControlType.TILT_SHUTTER_180,
ShutterBoxControlType.TILT_ONLY,
ShutterBoxControlType.PERGOLA_ROOF_TILT_ONLY,
ShutterBoxControlType.TILT_SHUTTER_WITHOUT_POSITIONING,
)

@property
def tilt_only(self) -> bool:
return self._control_type in (
ShutterBoxControlType.TILT_ONLY,
ShutterBoxControlType.PERGOLA_ROOF_TILT_ONLY,
)

@property
def is_tilt_180(self) -> bool:
return self._control_type == ShutterBoxControlType.TILT_SHUTTER_180

@property
def is_slider(self) -> bool:
return self._control_type not in (
ShutterBoxControlType.NO_CALIBRATION,
ShutterBoxControlType.CURTAIN,
ShutterBoxControlType.TILT_ONLY,
ShutterBoxControlType.PERGOLA_ROOF_TILT_ONLY,
ShutterBoxControlType.TILT_SHUTTER_WITHOUT_POSITIONING,
)

def read_cover_type(
self, alias: str, raw_value: Any, product: "Box"
Expand All @@ -164,7 +200,7 @@ def read_cover_type(
return UnifiedCoverType.SHUTTER
if self._control_type == ShutterBoxControlType.NO_CALIBRATION:
return UnifiedCoverType.SHUTTER
if self._control_type == ShutterBoxControlType.TILT_SHUTTER:
if self._control_type == ShutterBoxControlType.TILT_SHUTTER_90:
return UnifiedCoverType.SHUTTER
if self._control_type == ShutterBoxControlType.WINDOW_OPENER:
return UnifiedCoverType.WINDOW
Expand All @@ -176,6 +212,24 @@ def read_cover_type(
return UnifiedCoverType.SHADE
if self._control_type == ShutterBoxControlType.CURTAIN:
return UnifiedCoverType.CURTAIN
if self._control_type == ShutterBoxControlType.ROOF_SEGMENTED_SHUTTER:
return UnifiedCoverType.SHUTTER
if self._control_type == ShutterBoxControlType.SERVOMOTOR:
return UnifiedCoverType.SHUTTER
if self._control_type == ShutterBoxControlType.CURTAIN_ONE_SIDED:
return UnifiedCoverType.CURTAIN
if self._control_type == ShutterBoxControlType.CURTAIN_TWO_SIDED:
return UnifiedCoverType.CURTAIN
if self._control_type == ShutterBoxControlType.TILT_ONLY:
return UnifiedCoverType.SHUTTER
if self._control_type == ShutterBoxControlType.PERGOLA_ROOF:
return UnifiedCoverType.AWNING
if self._control_type == ShutterBoxControlType.PERGOLA_ROOF_TILT_ONLY:
return UnifiedCoverType.AWNING
if self._control_type == ShutterBoxControlType.TILT_SHUTTER_180:
return UnifiedCoverType.SHUTTER
if self._control_type == ShutterBoxControlType.TILT_SHUTTER_WITHOUT_POSITIONING:
return UnifiedCoverType.SHUTTER


class GateBox(Gate):
Expand Down Expand Up @@ -345,6 +399,22 @@ def is_position_inverted(self) -> bool:
def has_stop(self) -> bool:
return self._has_stop

@property
def tilt_only(self) -> bool:
return (
self._attributes.tilt_only
if hasattr(self._attributes, "tilt_only")
else False
)

@property
def is_tilt_180(self) -> bool:
return (
self._attributes.is_tilt_180
if hasattr(self._attributes, "is_tilt_180")
else False
)

@property
def cover_type(self) -> Optional[UnifiedCoverType]:
return self._cover_type
Expand Down
109 changes: 109 additions & 0 deletions tests/test_cover.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from blebox_uniapi.box_types import get_latest_api_level
from blebox_uniapi import error
from blebox_uniapi.cover import Shutter, ShutterBoxControlType, UnifiedCoverType

from .conftest import CommonEntity, DefaultBoxTest, future_date, jmerge

Expand Down Expand Up @@ -142,6 +143,114 @@ def assert_state(self, entity, state):
assert entity.is_closed is closed


class TestShutterAttributes:
"""Unit tests for Shutter attribute properties based on control type."""

@pytest.mark.parametrize(
"control_type",
[
ShutterBoxControlType.TILT_SHUTTER_90,
ShutterBoxControlType.TILT_SHUTTER_180,
ShutterBoxControlType.TILT_ONLY,
ShutterBoxControlType.PERGOLA_ROOF_TILT_ONLY,
ShutterBoxControlType.TILT_SHUTTER_WITHOUT_POSITIONING,
],
)
def test_has_tilt_true(self, control_type):
assert Shutter(control_type).has_tilt is True

@pytest.mark.parametrize(
"control_type",
[
ShutterBoxControlType.SEGMENTED_SHUTTER,
ShutterBoxControlType.NO_CALIBRATION,
ShutterBoxControlType.WINDOW_OPENER,
ShutterBoxControlType.PERGOLA_ROOF,
ShutterBoxControlType.CURTAIN,
],
)
def test_has_tilt_false(self, control_type):
assert Shutter(control_type).has_tilt is False

@pytest.mark.parametrize(
"control_type",
[
ShutterBoxControlType.TILT_ONLY,
ShutterBoxControlType.PERGOLA_ROOF_TILT_ONLY,
],
)
def test_tilt_only_true(self, control_type):
assert Shutter(control_type).tilt_only is True

@pytest.mark.parametrize(
"control_type",
[
ShutterBoxControlType.TILT_SHUTTER_90,
ShutterBoxControlType.TILT_SHUTTER_180,
ShutterBoxControlType.TILT_SHUTTER_WITHOUT_POSITIONING,
ShutterBoxControlType.SEGMENTED_SHUTTER,
],
)
def test_tilt_only_false(self, control_type):
assert Shutter(control_type).tilt_only is False

def test_is_tilt_180_true(self):
assert Shutter(ShutterBoxControlType.TILT_SHUTTER_180).is_tilt_180 is True

@pytest.mark.parametrize(
"control_type",
[
ShutterBoxControlType.TILT_SHUTTER_90,
ShutterBoxControlType.TILT_ONLY,
ShutterBoxControlType.TILT_SHUTTER_WITHOUT_POSITIONING,
],
)
def test_is_tilt_180_false(self, control_type):
assert Shutter(control_type).is_tilt_180 is False

@pytest.mark.parametrize(
"control_type",
[
ShutterBoxControlType.NO_CALIBRATION,
ShutterBoxControlType.CURTAIN,
ShutterBoxControlType.TILT_ONLY,
ShutterBoxControlType.PERGOLA_ROOF_TILT_ONLY,
ShutterBoxControlType.TILT_SHUTTER_WITHOUT_POSITIONING,
],
)
def test_is_slider_false(self, control_type):
assert Shutter(control_type).is_slider is False

@pytest.mark.parametrize(
"control_type",
[
ShutterBoxControlType.TILT_SHUTTER_90,
ShutterBoxControlType.TILT_SHUTTER_180,
ShutterBoxControlType.PERGOLA_ROOF,
ShutterBoxControlType.SEGMENTED_SHUTTER,
],
)
def test_is_slider_true(self, control_type):
assert Shutter(control_type).is_slider is True

@pytest.mark.parametrize(
"control_type, expected",
[
(ShutterBoxControlType.ROOF_SEGMENTED_SHUTTER, UnifiedCoverType.SHUTTER),
(ShutterBoxControlType.SERVOMOTOR, UnifiedCoverType.SHUTTER),
(ShutterBoxControlType.CURTAIN_ONE_SIDED, UnifiedCoverType.CURTAIN),
(ShutterBoxControlType.CURTAIN_TWO_SIDED, UnifiedCoverType.CURTAIN),
(ShutterBoxControlType.TILT_ONLY, UnifiedCoverType.SHUTTER),
(ShutterBoxControlType.PERGOLA_ROOF, UnifiedCoverType.AWNING),
(ShutterBoxControlType.PERGOLA_ROOF_TILT_ONLY, UnifiedCoverType.AWNING),
(ShutterBoxControlType.TILT_SHUTTER_180, UnifiedCoverType.SHUTTER),
(ShutterBoxControlType.TILT_SHUTTER_WITHOUT_POSITIONING, UnifiedCoverType.SHUTTER),
],
)
def test_read_cover_type_new_types(self, control_type, expected):
assert Shutter(control_type).read_cover_type(None, None, None) == expected


class TestShutter(CoverTest):
"""Tests for cover devices representing a BleBox ShutterBox."""

Expand Down
Loading