mirror of
https://github.com/python-kasa/python-kasa.git
synced 2025-04-26 00:26:25 +00:00

Some checks failed
CI / Perform linting checks (3.13) (push) Has been cancelled
CodeQL checks / Analyze (python) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.11) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.12) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.13) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.11) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.12) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.13) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.11) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.12) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.13) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.11) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.12) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.13) (push) Has been cancelled
Co-authored-by: Teemu R. <tpr@iki.fi>
217 lines
6.8 KiB
Python
217 lines
6.8 KiB
Python
"""Implementation of alarm module."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Annotated
|
|
|
|
from ...feature import Feature
|
|
from ...interfaces import Alarm as AlarmInterface
|
|
from ...module import FeatureAttribute
|
|
from ...smart.smartmodule import allow_update_after
|
|
from ..smartcammodule import SmartCamModule
|
|
|
|
DURATION_MIN = 0
|
|
DURATION_MAX = 6000
|
|
|
|
VOLUME_MIN = 0
|
|
VOLUME_MAX = 10
|
|
|
|
|
|
class Alarm(SmartCamModule, AlarmInterface):
|
|
"""Implementation of alarm module."""
|
|
|
|
REQUIRED_COMPONENT = "siren"
|
|
QUERY_GETTER_NAME = "getSirenStatus"
|
|
QUERY_MODULE_NAME = "siren"
|
|
|
|
def query(self) -> dict:
|
|
"""Query to execute during the update cycle."""
|
|
q = super().query()
|
|
q["getSirenConfig"] = {self.QUERY_MODULE_NAME: {}}
|
|
q["getSirenTypeList"] = {self.QUERY_MODULE_NAME: {}}
|
|
|
|
return q
|
|
|
|
def _initialize_features(self) -> None:
|
|
"""Initialize features."""
|
|
device = self._device
|
|
self._add_feature(
|
|
Feature(
|
|
device,
|
|
id="alarm",
|
|
name="Alarm",
|
|
container=self,
|
|
attribute_getter="active",
|
|
icon="mdi:bell",
|
|
category=Feature.Category.Debug,
|
|
type=Feature.Type.BinarySensor,
|
|
)
|
|
)
|
|
self._add_feature(
|
|
Feature(
|
|
device,
|
|
id="alarm_sound",
|
|
name="Alarm sound",
|
|
container=self,
|
|
attribute_getter="alarm_sound",
|
|
attribute_setter="set_alarm_sound",
|
|
category=Feature.Category.Config,
|
|
type=Feature.Type.Choice,
|
|
choices_getter="alarm_sounds",
|
|
)
|
|
)
|
|
self._add_feature(
|
|
Feature(
|
|
device,
|
|
id="alarm_volume",
|
|
name="Alarm volume",
|
|
container=self,
|
|
attribute_getter="alarm_volume",
|
|
attribute_setter="set_alarm_volume",
|
|
category=Feature.Category.Config,
|
|
type=Feature.Type.Number,
|
|
range_getter=lambda: (VOLUME_MIN, VOLUME_MAX),
|
|
)
|
|
)
|
|
self._add_feature(
|
|
Feature(
|
|
device,
|
|
id="alarm_duration",
|
|
name="Alarm duration",
|
|
container=self,
|
|
attribute_getter="alarm_duration",
|
|
attribute_setter="set_alarm_duration",
|
|
category=Feature.Category.Config,
|
|
type=Feature.Type.Number,
|
|
range_getter=lambda: (DURATION_MIN, DURATION_MAX),
|
|
)
|
|
)
|
|
self._add_feature(
|
|
Feature(
|
|
device,
|
|
id="test_alarm",
|
|
name="Test alarm",
|
|
container=self,
|
|
attribute_setter="play",
|
|
type=Feature.Type.Action,
|
|
)
|
|
)
|
|
self._add_feature(
|
|
Feature(
|
|
device,
|
|
id="stop_alarm",
|
|
name="Stop alarm",
|
|
container=self,
|
|
attribute_setter="stop",
|
|
type=Feature.Type.Action,
|
|
)
|
|
)
|
|
|
|
@property
|
|
def alarm_sound(self) -> Annotated[str, FeatureAttribute()]:
|
|
"""Return current alarm sound."""
|
|
return self.data["getSirenConfig"]["siren_type"]
|
|
|
|
@allow_update_after
|
|
async def set_alarm_sound(self, sound: str) -> Annotated[dict, FeatureAttribute()]:
|
|
"""Set alarm sound.
|
|
|
|
See *alarm_sounds* for list of available sounds.
|
|
"""
|
|
config = self._validate_and_get_config(sound=sound)
|
|
return await self.call("setSirenConfig", {"siren": config})
|
|
|
|
@property
|
|
def alarm_sounds(self) -> list[str]:
|
|
"""Return list of available alarm sounds."""
|
|
return self.data["getSirenTypeList"]["siren_type_list"]
|
|
|
|
@property
|
|
def alarm_volume(self) -> Annotated[int, FeatureAttribute()]:
|
|
"""Return alarm volume.
|
|
|
|
Unlike duration the device expects/returns a string for volume.
|
|
"""
|
|
return int(self.data["getSirenConfig"]["volume"])
|
|
|
|
@allow_update_after
|
|
async def set_alarm_volume(
|
|
self, volume: int
|
|
) -> Annotated[dict, FeatureAttribute()]:
|
|
"""Set alarm volume."""
|
|
config = self._validate_and_get_config(volume=volume)
|
|
return await self.call("setSirenConfig", {"siren": config})
|
|
|
|
@property
|
|
def alarm_duration(self) -> Annotated[int, FeatureAttribute()]:
|
|
"""Return alarm duration."""
|
|
return self.data["getSirenConfig"]["duration"]
|
|
|
|
@allow_update_after
|
|
async def set_alarm_duration(
|
|
self, duration: int
|
|
) -> Annotated[dict, FeatureAttribute()]:
|
|
"""Set alarm volume."""
|
|
config = self._validate_and_get_config(duration=duration)
|
|
return await self.call("setSirenConfig", {"siren": config})
|
|
|
|
@property
|
|
def active(self) -> bool:
|
|
"""Return true if alarm is active."""
|
|
return self.data["getSirenStatus"]["status"] != "off"
|
|
|
|
async def play(
|
|
self,
|
|
*,
|
|
duration: int | None = None,
|
|
volume: int | None = None,
|
|
sound: str | None = None,
|
|
) -> dict:
|
|
"""Play alarm.
|
|
|
|
The optional *duration*, *volume*, and *sound* to override the device settings.
|
|
*duration* is in seconds.
|
|
See *alarm_sounds* for the list of sounds available for the device.
|
|
"""
|
|
if config := self._validate_and_get_config(
|
|
duration=duration, volume=volume, sound=sound
|
|
):
|
|
await self.call("setSirenConfig", {"siren": config})
|
|
|
|
return await self.call("setSirenStatus", {"siren": {"status": "on"}})
|
|
|
|
async def stop(self) -> dict:
|
|
"""Stop alarm."""
|
|
return await self.call("setSirenStatus", {"siren": {"status": "off"}})
|
|
|
|
def _validate_and_get_config(
|
|
self,
|
|
*,
|
|
duration: int | None = None,
|
|
volume: int | None = None,
|
|
sound: str | None = None,
|
|
) -> dict:
|
|
if sound and sound not in self.alarm_sounds:
|
|
raise ValueError(
|
|
f"sound must be one of {', '.join(self.alarm_sounds)}: {sound}"
|
|
)
|
|
|
|
if duration is not None and (
|
|
duration < DURATION_MIN or duration > DURATION_MAX
|
|
):
|
|
msg = f"duration must be between {DURATION_MIN} and {DURATION_MAX}"
|
|
raise ValueError(msg)
|
|
|
|
if volume is not None and (volume < VOLUME_MIN or volume > VOLUME_MAX):
|
|
raise ValueError(f"volume must be between {VOLUME_MIN} and {VOLUME_MAX}")
|
|
|
|
config: dict[str, str | int] = {}
|
|
if sound:
|
|
config["siren_type"] = sound
|
|
if duration is not None:
|
|
config["duration"] = duration
|
|
if volume is not None:
|
|
config["volume"] = str(volume)
|
|
|
|
return config
|