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
21 changes: 20 additions & 1 deletion src/demetriek/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from aiohttp.helpers import BasicAuth
from yarl import URL

from .const import ScreensaverMode
from .exceptions import (
LaMetricAuthenticationError,
LaMetricConnectionError,
Expand All @@ -32,7 +33,7 @@
if TYPE_CHECKING:
from datetime import time

from .const import BrightnessMode, DeviceMode, ScreensaverMode
from .const import BrightnessMode, DeviceMode


@dataclass
Expand Down Expand Up @@ -203,7 +204,25 @@ async def display( # noqa: PLR0913 # pylint: disable=too-many-arguments
A Display object, with latest or updated information about
the display of the LaMetric device.

Raises:
------
ValueError: The time based mode was given without both of
its times.

"""
# The device wants both times on every time based write, even one
# that only toggles the mode. It rejects a lone end time and
# quietly ignores a lone start time, so catch that here rather
# than let it look like it worked.
if screensaver_mode is ScreensaverMode.TIME_BASED and (
screensaver_start_time is None or screensaver_end_time is None
):
msg = (
"The time based screensaver mode needs both"
" screensaver_start_time and screensaver_end_time"
)
raise ValueError(msg)

data: dict[str, Any] = {}

if brightness is not None:
Expand Down
50 changes: 50 additions & 0 deletions tests/test_display.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from datetime import time

import aiohttp
import pytest
from aresponses import Response, ResponsesMockServer

from demetriek import LaMetricDevice
Expand Down Expand Up @@ -161,3 +162,52 @@ async def response_handler(request: aiohttp.ClientResponse) -> Response:
async with aiohttp.ClientSession() as session:
demetriek = LaMetricDevice(host="127.0.0.2", api_key="abc", session=session)
await demetriek.display(screensaver_mode=ScreensaverMode.WHEN_DARK)


@pytest.mark.parametrize(
("start_time", "end_time"),
[
(time(23, 0, 0), None),
(None, time(7, 0, 0)),
(None, None),
],
)
async def test_set_display_screensaver_time_based_needs_both_times(
start_time: time | None,
end_time: time | None,
) -> None:
"""Test the time based mode is rejected without both of its times."""
demetriek = LaMetricDevice(host="127.0.0.2", api_key="abc")
with pytest.raises(ValueError, match="needs both"):
await demetriek.display(
screensaver_mode=ScreensaverMode.TIME_BASED,
screensaver_mode_enabled=True,
screensaver_start_time=start_time,
screensaver_end_time=end_time,
)


async def test_set_display_screensaver_when_dark_needs_no_times(
aresponses: ResponsesMockServer,
) -> None:
"""Test the other modes are unaffected by the time based requirement."""

async def response_handler(request: aiohttp.ClientResponse) -> Response:
"""Response handler for this test."""
assert await request.json() == {
"screensaver": {"mode": "when_dark", "mode_params": {"enabled": True}},
}
return aresponses.Response(
status=200,
headers={"Content-Type": "application/json"},
text=load_fixture("display_set_screensaver.json"),
)

aresponses.add("127.0.0.2:4343", "/api/v2/device/display", "PUT", response_handler)

async with aiohttp.ClientSession() as session:
demetriek = LaMetricDevice(host="127.0.0.2", api_key="abc", session=session)
await demetriek.display(
screensaver_mode=ScreensaverMode.WHEN_DARK,
screensaver_mode_enabled=True,
)