mirror of
https://github.com/python-kasa/python-kasa.git
synced 2025-10-10 09:28:02 +00:00
Add alarm module for smartcamera hubs (#1258)
This commit is contained in:
@@ -105,6 +105,7 @@ class FakeSmartCameraTransport(BaseTransport):
|
||||
info = info[key]
|
||||
info[set_keys[-1]] = value
|
||||
|
||||
# Setters for when there's not a simple mapping of setters to getters
|
||||
SETTERS = {
|
||||
("system", "sys", "dev_alias"): [
|
||||
"getDeviceInfo",
|
||||
@@ -112,36 +113,20 @@ class FakeSmartCameraTransport(BaseTransport):
|
||||
"basic_info",
|
||||
"device_alias",
|
||||
],
|
||||
("lens_mask", "lens_mask_info", "enabled"): [
|
||||
"getLensMaskConfig",
|
||||
"lens_mask",
|
||||
"lens_mask_info",
|
||||
"enabled",
|
||||
],
|
||||
# setTimezone maps to getClockStatus
|
||||
("system", "clock_status", "seconds_from_1970"): [
|
||||
"getClockStatus",
|
||||
"system",
|
||||
"clock_status",
|
||||
"seconds_from_1970",
|
||||
],
|
||||
# setTimezone maps to getClockStatus
|
||||
("system", "clock_status", "local_time"): [
|
||||
"getClockStatus",
|
||||
"system",
|
||||
"clock_status",
|
||||
"local_time",
|
||||
],
|
||||
("system", "basic", "zone_id"): [
|
||||
"getTimezone",
|
||||
"system",
|
||||
"basic",
|
||||
"zone_id",
|
||||
],
|
||||
("led", "config", "enabled"): [
|
||||
"getLedStatus",
|
||||
"led",
|
||||
"config",
|
||||
"enabled",
|
||||
],
|
||||
}
|
||||
|
||||
async def _send_request(self, request_dict: dict):
|
||||
@@ -154,27 +139,41 @@ class FakeSmartCameraTransport(BaseTransport):
|
||||
)
|
||||
|
||||
if method[:3] == "set":
|
||||
get_method = "g" + method[1:]
|
||||
for key, val in request_dict.items():
|
||||
if key != "method":
|
||||
# key is params for multi request and the actual params
|
||||
# for single requests
|
||||
if key == "params":
|
||||
module = next(iter(val))
|
||||
val = val[module]
|
||||
if key == "method":
|
||||
continue
|
||||
# key is params for multi request and the actual params
|
||||
# for single requests
|
||||
if key == "params":
|
||||
module = next(iter(val))
|
||||
val = val[module]
|
||||
else:
|
||||
module = key
|
||||
section = next(iter(val))
|
||||
skey_val = val[section]
|
||||
if not isinstance(skey_val, dict): # single level query
|
||||
section_key = section
|
||||
section_val = skey_val
|
||||
if (get_info := info.get(get_method)) and section_key in get_info:
|
||||
get_info[section_key] = section_val
|
||||
else:
|
||||
module = key
|
||||
section = next(iter(val))
|
||||
skey_val = val[section]
|
||||
for skey, sval in skey_val.items():
|
||||
section_key = skey
|
||||
section_value = sval
|
||||
if setter_keys := self.SETTERS.get(
|
||||
(module, section, section_key)
|
||||
):
|
||||
self._get_param_set_value(info, setter_keys, section_value)
|
||||
else:
|
||||
return {"error_code": -1}
|
||||
return {"error_code": -1}
|
||||
break
|
||||
for skey, sval in skey_val.items():
|
||||
section_key = skey
|
||||
section_value = sval
|
||||
if setter_keys := self.SETTERS.get((module, section, section_key)):
|
||||
self._get_param_set_value(info, setter_keys, section_value)
|
||||
elif (
|
||||
section := info.get(get_method, {})
|
||||
.get(module, {})
|
||||
.get(section, {})
|
||||
) and section_key in section:
|
||||
section[section_key] = section_value
|
||||
else:
|
||||
return {"error_code": -1}
|
||||
break
|
||||
return {"error_code": 0}
|
||||
elif method[:3] == "get":
|
||||
params = request_dict.get("params")
|
||||
|
0
tests/smartcamera/modules/__init__.py
Normal file
0
tests/smartcamera/modules/__init__.py
Normal file
159
tests/smartcamera/modules/test_alarm.py
Normal file
159
tests/smartcamera/modules/test_alarm.py
Normal file
@@ -0,0 +1,159 @@
|
||||
"""Tests for smart camera devices."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from kasa import Device
|
||||
from kasa.smartcamera.modules.alarm import (
|
||||
DURATION_MAX,
|
||||
DURATION_MIN,
|
||||
VOLUME_MAX,
|
||||
VOLUME_MIN,
|
||||
)
|
||||
from kasa.smartcamera.smartcameramodule import SmartCameraModule
|
||||
|
||||
from ...conftest import hub_smartcamera
|
||||
|
||||
|
||||
@hub_smartcamera
|
||||
async def test_alarm(dev: Device):
|
||||
"""Test device alarm."""
|
||||
alarm = dev.modules.get(SmartCameraModule.SmartCameraAlarm)
|
||||
assert alarm
|
||||
|
||||
original_duration = alarm.alarm_duration
|
||||
assert original_duration is not None
|
||||
original_volume = alarm.alarm_volume
|
||||
assert original_volume is not None
|
||||
original_sound = alarm.alarm_sound
|
||||
|
||||
try:
|
||||
# test volume
|
||||
new_volume = original_volume - 1 if original_volume > 1 else original_volume + 1
|
||||
await alarm.set_alarm_volume(new_volume) # type: ignore[arg-type]
|
||||
await dev.update()
|
||||
assert alarm.alarm_volume == new_volume
|
||||
|
||||
# test duration
|
||||
new_duration = (
|
||||
original_duration - 1 if original_duration > 1 else original_duration + 1
|
||||
)
|
||||
await alarm.set_alarm_duration(new_duration)
|
||||
await dev.update()
|
||||
assert alarm.alarm_duration == new_duration
|
||||
|
||||
# test start
|
||||
await alarm.play()
|
||||
await dev.update()
|
||||
assert alarm.active
|
||||
|
||||
# test stop
|
||||
await alarm.stop()
|
||||
await dev.update()
|
||||
assert not alarm.active
|
||||
|
||||
# test set sound
|
||||
new_sound = (
|
||||
alarm.alarm_sounds[0]
|
||||
if alarm.alarm_sound != alarm.alarm_sounds[0]
|
||||
else alarm.alarm_sounds[1]
|
||||
)
|
||||
await alarm.set_alarm_sound(new_sound)
|
||||
await dev.update()
|
||||
assert alarm.alarm_sound == new_sound
|
||||
|
||||
finally:
|
||||
await alarm.set_alarm_volume(original_volume)
|
||||
await alarm.set_alarm_duration(original_duration)
|
||||
await alarm.set_alarm_sound(original_sound)
|
||||
await dev.update()
|
||||
|
||||
|
||||
@hub_smartcamera
|
||||
async def test_alarm_invalid_setters(dev: Device):
|
||||
"""Test device alarm invalid setter values."""
|
||||
alarm = dev.modules.get(SmartCameraModule.SmartCameraAlarm)
|
||||
assert alarm
|
||||
|
||||
# test set sound invalid
|
||||
msg = f"sound must be one of {', '.join(alarm.alarm_sounds)}: foobar"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
await alarm.set_alarm_sound("foobar")
|
||||
|
||||
# test volume invalid
|
||||
msg = f"volume must be between {VOLUME_MIN} and {VOLUME_MAX}"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
await alarm.set_alarm_volume(-3)
|
||||
|
||||
# test duration invalid
|
||||
msg = f"duration must be between {DURATION_MIN} and {DURATION_MAX}"
|
||||
with pytest.raises(ValueError, match=msg):
|
||||
await alarm.set_alarm_duration(-3)
|
||||
|
||||
|
||||
@hub_smartcamera
|
||||
async def test_alarm_features(dev: Device):
|
||||
"""Test device alarm features."""
|
||||
alarm = dev.modules.get(SmartCameraModule.SmartCameraAlarm)
|
||||
assert alarm
|
||||
|
||||
original_duration = alarm.alarm_duration
|
||||
assert original_duration is not None
|
||||
original_volume = alarm.alarm_volume
|
||||
assert original_volume is not None
|
||||
original_sound = alarm.alarm_sound
|
||||
|
||||
try:
|
||||
# test volume
|
||||
new_volume = original_volume - 1 if original_volume > 1 else original_volume + 1
|
||||
feature = dev.features.get("alarm_volume")
|
||||
assert feature
|
||||
await feature.set_value(new_volume) # type: ignore[arg-type]
|
||||
await dev.update()
|
||||
assert feature.value == new_volume
|
||||
|
||||
# test duration
|
||||
feature = dev.features.get("alarm_duration")
|
||||
assert feature
|
||||
new_duration = (
|
||||
original_duration - 1 if original_duration > 1 else original_duration + 1
|
||||
)
|
||||
await feature.set_value(new_duration)
|
||||
await dev.update()
|
||||
assert feature.value == new_duration
|
||||
|
||||
# test start
|
||||
feature = dev.features.get("test_alarm")
|
||||
assert feature
|
||||
await feature.set_value(None)
|
||||
await dev.update()
|
||||
feature = dev.features.get("alarm")
|
||||
assert feature
|
||||
assert feature.value is True
|
||||
|
||||
# test stop
|
||||
feature = dev.features.get("stop_alarm")
|
||||
assert feature
|
||||
await feature.set_value(None)
|
||||
await dev.update()
|
||||
assert dev.features["alarm"].value is False
|
||||
|
||||
# test set sound
|
||||
feature = dev.features.get("alarm_sound")
|
||||
assert feature
|
||||
new_sound = (
|
||||
alarm.alarm_sounds[0]
|
||||
if alarm.alarm_sound != alarm.alarm_sounds[0]
|
||||
else alarm.alarm_sounds[1]
|
||||
)
|
||||
await feature.set_value(new_sound)
|
||||
await alarm.set_alarm_sound(new_sound)
|
||||
await dev.update()
|
||||
assert feature.value == new_sound
|
||||
|
||||
finally:
|
||||
await alarm.set_alarm_volume(original_volume)
|
||||
await alarm.set_alarm_duration(original_duration)
|
||||
await alarm.set_alarm_sound(original_sound)
|
||||
await dev.update()
|
Reference in New Issue
Block a user