Extend smartcam detection support (#1552)

New detection added with tests:

- bark detection
- glass detection
- line crossing detection
- meow detection
- vehicle detection
This commit is contained in:
Gabriele Pongelli
2025-08-25 15:20:33 +02:00
committed by GitHub
parent e21ab90e96
commit 0cd0434160
23 changed files with 1549 additions and 379 deletions

View File

@@ -293,6 +293,7 @@ All Tapo devices require authentication.<br>Hub-Connected Devices may work acros
- Hardware: 2.0 (EU) / Firmware: 1.4.3
- **C220**
- Hardware: 1.0 (EU) / Firmware: 1.2.2
- Hardware: 1.0 (EU) / Firmware: 1.2.5
- **C225**
- Hardware: 2.0 (US) / Firmware: 1.0.11
- **C325WB**

View File

@@ -44,6 +44,11 @@ SMARTCAM_REQUESTS: list[dict] = [
{"getWhitelampConfig": {"image": {"name": "switch"}}},
{"getMsgPushConfig": {"msg_push": {"name": ["chn1_msg_push_info"]}}},
{"getSdCardStatus": {"harddisk_manage": {"table": ["hd_info"]}}},
{
"getLinecrossingDetectionConfig": {
"linecrossing_detection": {"name": ["detection", "arming_schedule"]}
}
},
{"getCircularRecordingConfig": {"harddisk_manage": {"name": "harddisk"}}},
{"getRecordPlan": {"record_plan": {"name": ["chn1_channel"]}}},
{"getAudioConfig": {"audio_config": {"name": ["speaker", "microphone"]}}},

View File

@@ -1,6 +1,7 @@
"""Package for supporting tapo-branded cameras."""
from .detectionmodule import DetectionModule
from .smartcamchild import SmartCamChild
from .smartcamdevice import SmartCamDevice
__all__ = ["SmartCamDevice", "SmartCamChild"]
__all__ = ["SmartCamDevice", "SmartCamChild", "DetectionModule"]

View File

@@ -0,0 +1,58 @@
"""SmartCamModule base class for all detections."""
from __future__ import annotations
import logging
from kasa.feature import Feature
from kasa.smart.smartmodule import allow_update_after
from kasa.smartcam.smartcammodule import SmartCamModule
_LOGGER = logging.getLogger(__name__)
class DetectionModule(SmartCamModule):
"""SmartCamModule base class for all detections."""
#: Feature ID, filled by inheriting class
DETECTION_FEATURE_ID: str = ""
#: User-friendly short description, filled by inheriting class
DETECTION_FEATURE_NAME: str = ""
#: Feature setter method name, filled by inheriting class
QUERY_SETTER_NAME: str = ""
#: Feature section name, filled by inheriting class
QUERY_SET_SECTION_NAME: str = ""
def _initialize_features(self) -> None:
"""Initialize features after the initial update."""
self._add_feature(
Feature(
self._device,
id=self.DETECTION_FEATURE_ID,
name=self.DETECTION_FEATURE_NAME,
container=self,
attribute_getter="enabled",
attribute_setter="set_enabled",
type=Feature.Type.Switch,
category=Feature.Category.Config,
)
)
@property
def enabled(self) -> bool:
"""Return the detection enabled state."""
return self.data[self.QUERY_SECTION_NAMES]["enabled"] == "on"
@allow_update_after
async def set_enabled(self, enable: bool) -> dict:
"""Set the detection enabled state."""
params = {"enabled": "on" if enable else "off"}
return await self._device._query_setter_helper(
self.QUERY_SETTER_NAME,
self.QUERY_MODULE_NAME,
self.QUERY_SET_SECTION_NAME,
params,
)

View File

@@ -2,31 +2,40 @@
from .alarm import Alarm
from .babycrydetection import BabyCryDetection
from .barkdetection import BarkDetection
from .battery import Battery
from .camera import Camera
from .childdevice import ChildDevice
from .childsetup import ChildSetup
from .device import DeviceModule
from .glassdetection import GlassDetection
from .homekit import HomeKit
from .led import Led
from .lensmask import LensMask
from .linecrossingdetection import LineCrossingDetection
from .matter import Matter
from .meowdetection import MeowDetection
from .motiondetection import MotionDetection
from .pantilt import PanTilt
from .persondetection import PersonDetection
from .petdetection import PetDetection
from .tamperdetection import TamperDetection
from .time import Time
from .vehicledetection import VehicleDetection
__all__ = [
"Alarm",
"BabyCryDetection",
"BarkDetection",
"Battery",
"Camera",
"ChildDevice",
"ChildSetup",
"DeviceModule",
"GlassDetection",
"Led",
"LineCrossingDetection",
"MeowDetection",
"PanTilt",
"PersonDetection",
"PetDetection",
@@ -36,4 +45,5 @@ __all__ = [
"MotionDetection",
"LensMask",
"TamperDetection",
"VehicleDetection",
]

View File

@@ -4,14 +4,12 @@ from __future__ import annotations
import logging
from ...feature import Feature
from ...smart.smartmodule import allow_update_after
from ..smartcammodule import SmartCamModule
from kasa.smartcam.detectionmodule import DetectionModule
_LOGGER = logging.getLogger(__name__)
class BabyCryDetection(SmartCamModule):
class BabyCryDetection(DetectionModule):
"""Implementation of baby cry detection module."""
REQUIRED_COMPONENT = "babyCryDetection"
@@ -20,30 +18,7 @@ class BabyCryDetection(SmartCamModule):
QUERY_MODULE_NAME = "sound_detection"
QUERY_SECTION_NAMES = "bcd"
def _initialize_features(self) -> None:
"""Initialize features after the initial update."""
self._add_feature(
Feature(
self._device,
id="baby_cry_detection",
name="Baby cry detection",
container=self,
attribute_getter="enabled",
attribute_setter="set_enabled",
type=Feature.Type.Switch,
category=Feature.Category.Config,
)
)
@property
def enabled(self) -> bool:
"""Return the baby cry detection enabled state."""
return self.data["bcd"]["enabled"] == "on"
@allow_update_after
async def set_enabled(self, enable: bool) -> dict:
"""Set the baby cry detection enabled state."""
params = {"enabled": "on" if enable else "off"}
return await self._device._query_setter_helper(
"setBCDConfig", self.QUERY_MODULE_NAME, "bcd", params
)
DETECTION_FEATURE_ID = "baby_cry_detection"
DETECTION_FEATURE_NAME = "Baby cry detection"
QUERY_SETTER_NAME = "setBCDConfig"
QUERY_SET_SECTION_NAME = "bcd"

View File

@@ -0,0 +1,24 @@
"""Implementation of bark detection module."""
from __future__ import annotations
import logging
from kasa.smartcam.detectionmodule import DetectionModule
_LOGGER = logging.getLogger(__name__)
class BarkDetection(DetectionModule):
"""Implementation of bark detection module."""
REQUIRED_COMPONENT = "barkDetection"
QUERY_GETTER_NAME = "getBarkDetectionConfig"
QUERY_MODULE_NAME = "bark_detection"
QUERY_SECTION_NAMES = "detection"
DETECTION_FEATURE_ID = "bark_detection"
DETECTION_FEATURE_NAME = "Bark detection"
QUERY_SETTER_NAME = "setBarkDetectionConfig"
QUERY_SET_SECTION_NAME = "detection"

View File

@@ -0,0 +1,24 @@
"""Implementation of glass detection module."""
from __future__ import annotations
import logging
from kasa.smartcam.detectionmodule import DetectionModule
_LOGGER = logging.getLogger(__name__)
class GlassDetection(DetectionModule):
"""Implementation of glass detection module."""
REQUIRED_COMPONENT = "glassDetection"
QUERY_GETTER_NAME = "getGlassDetectionConfig"
QUERY_MODULE_NAME = "glass_detection"
QUERY_SECTION_NAMES = "detection"
DETECTION_FEATURE_ID = "glass_detection"
DETECTION_FEATURE_NAME = "Glass detection"
QUERY_SETTER_NAME = "setGlassDetectionConfig"
QUERY_SET_SECTION_NAME = "detection"

View File

@@ -0,0 +1,24 @@
"""Implementation of line crossing detection module."""
from __future__ import annotations
import logging
from kasa.smartcam.detectionmodule import DetectionModule
_LOGGER = logging.getLogger(__name__)
class LineCrossingDetection(DetectionModule):
"""Implementation of line crossing detection module."""
REQUIRED_COMPONENT = "linecrossingDetection"
QUERY_GETTER_NAME = "getLinecrossingDetectionConfig"
QUERY_MODULE_NAME = "linecrossing_detection"
QUERY_SECTION_NAMES = "detection"
DETECTION_FEATURE_ID = "line_crossing_detection"
DETECTION_FEATURE_NAME = "Line crossing detection"
QUERY_SETTER_NAME = "setLinecrossingDetectionConfig"
QUERY_SET_SECTION_NAME = "detection"

View File

@@ -0,0 +1,24 @@
"""Implementation of meow detection module."""
from __future__ import annotations
import logging
from kasa.smartcam.detectionmodule import DetectionModule
_LOGGER = logging.getLogger(__name__)
class MeowDetection(DetectionModule):
"""Implementation of meow detection module."""
REQUIRED_COMPONENT = "meowDetection"
QUERY_GETTER_NAME = "getMeowDetectionConfig"
QUERY_MODULE_NAME = "meow_detection"
QUERY_SECTION_NAMES = "detection"
DETECTION_FEATURE_ID = "meow_detection"
DETECTION_FEATURE_NAME = "Meow detection"
QUERY_SETTER_NAME = "setMeowDetectionConfig"
QUERY_SET_SECTION_NAME = "detection"

View File

@@ -4,14 +4,12 @@ from __future__ import annotations
import logging
from ...feature import Feature
from ...smart.smartmodule import allow_update_after
from ..smartcammodule import SmartCamModule
from kasa.smartcam.detectionmodule import DetectionModule
_LOGGER = logging.getLogger(__name__)
class MotionDetection(SmartCamModule):
class MotionDetection(DetectionModule):
"""Implementation of motion detection module."""
REQUIRED_COMPONENT = "detection"
@@ -20,30 +18,7 @@ class MotionDetection(SmartCamModule):
QUERY_MODULE_NAME = "motion_detection"
QUERY_SECTION_NAMES = "motion_det"
def _initialize_features(self) -> None:
"""Initialize features after the initial update."""
self._add_feature(
Feature(
self._device,
id="motion_detection",
name="Motion detection",
container=self,
attribute_getter="enabled",
attribute_setter="set_enabled",
type=Feature.Type.Switch,
category=Feature.Category.Config,
)
)
@property
def enabled(self) -> bool:
"""Return the motion detection enabled state."""
return self.data["motion_det"]["enabled"] == "on"
@allow_update_after
async def set_enabled(self, enable: bool) -> dict:
"""Set the motion detection enabled state."""
params = {"enabled": "on" if enable else "off"}
return await self._device._query_setter_helper(
"setDetectionConfig", self.QUERY_MODULE_NAME, "motion_det", params
)
DETECTION_FEATURE_ID = "motion_detection"
DETECTION_FEATURE_NAME = "Motion detection"
QUERY_SETTER_NAME = "setDetectionConfig"
QUERY_SET_SECTION_NAME = "motion_det"

View File

@@ -4,14 +4,12 @@ from __future__ import annotations
import logging
from ...feature import Feature
from ...smart.smartmodule import allow_update_after
from ..smartcammodule import SmartCamModule
from kasa.smartcam.detectionmodule import DetectionModule
_LOGGER = logging.getLogger(__name__)
class PersonDetection(SmartCamModule):
class PersonDetection(DetectionModule):
"""Implementation of person detection module."""
REQUIRED_COMPONENT = "personDetection"
@@ -20,30 +18,7 @@ class PersonDetection(SmartCamModule):
QUERY_MODULE_NAME = "people_detection"
QUERY_SECTION_NAMES = "detection"
def _initialize_features(self) -> None:
"""Initialize features after the initial update."""
self._add_feature(
Feature(
self._device,
id="person_detection",
name="Person detection",
container=self,
attribute_getter="enabled",
attribute_setter="set_enabled",
type=Feature.Type.Switch,
category=Feature.Category.Config,
)
)
@property
def enabled(self) -> bool:
"""Return the person detection enabled state."""
return self.data["detection"]["enabled"] == "on"
@allow_update_after
async def set_enabled(self, enable: bool) -> dict:
"""Set the person detection enabled state."""
params = {"enabled": "on" if enable else "off"}
return await self._device._query_setter_helper(
"setPersonDetectionConfig", self.QUERY_MODULE_NAME, "detection", params
)
DETECTION_FEATURE_ID = "person_detection"
DETECTION_FEATURE_NAME = "Person detection"
QUERY_SETTER_NAME = "setPersonDetectionConfig"
QUERY_SET_SECTION_NAME = "detection"

View File

@@ -4,14 +4,12 @@ from __future__ import annotations
import logging
from ...feature import Feature
from ...smart.smartmodule import allow_update_after
from ..smartcammodule import SmartCamModule
from kasa.smartcam.detectionmodule import DetectionModule
_LOGGER = logging.getLogger(__name__)
class PetDetection(SmartCamModule):
class PetDetection(DetectionModule):
"""Implementation of pet detection module."""
REQUIRED_COMPONENT = "petDetection"
@@ -20,30 +18,7 @@ class PetDetection(SmartCamModule):
QUERY_MODULE_NAME = "pet_detection"
QUERY_SECTION_NAMES = "detection"
def _initialize_features(self) -> None:
"""Initialize features after the initial update."""
self._add_feature(
Feature(
self._device,
id="pet_detection",
name="Pet detection",
container=self,
attribute_getter="enabled",
attribute_setter="set_enabled",
type=Feature.Type.Switch,
category=Feature.Category.Config,
)
)
@property
def enabled(self) -> bool:
"""Return the pet detection enabled state."""
return self.data["detection"]["enabled"] == "on"
@allow_update_after
async def set_enabled(self, enable: bool) -> dict:
"""Set the pet detection enabled state."""
params = {"enabled": "on" if enable else "off"}
return await self._device._query_setter_helper(
"setPetDetectionConfig", self.QUERY_MODULE_NAME, "detection", params
)
DETECTION_FEATURE_ID = "pet_detection"
DETECTION_FEATURE_NAME = "Pet detection"
QUERY_SETTER_NAME = "setPetDetectionConfig"
QUERY_SET_SECTION_NAME = "detection"

View File

@@ -4,14 +4,12 @@ from __future__ import annotations
import logging
from ...feature import Feature
from ...smart.smartmodule import allow_update_after
from ..smartcammodule import SmartCamModule
from kasa.smartcam.detectionmodule import DetectionModule
_LOGGER = logging.getLogger(__name__)
class TamperDetection(SmartCamModule):
class TamperDetection(DetectionModule):
"""Implementation of tamper detection module."""
REQUIRED_COMPONENT = "tamperDetection"
@@ -20,30 +18,7 @@ class TamperDetection(SmartCamModule):
QUERY_MODULE_NAME = "tamper_detection"
QUERY_SECTION_NAMES = "tamper_det"
def _initialize_features(self) -> None:
"""Initialize features after the initial update."""
self._add_feature(
Feature(
self._device,
id="tamper_detection",
name="Tamper detection",
container=self,
attribute_getter="enabled",
attribute_setter="set_enabled",
type=Feature.Type.Switch,
category=Feature.Category.Config,
)
)
@property
def enabled(self) -> bool:
"""Return the tamper detection enabled state."""
return self.data["tamper_det"]["enabled"] == "on"
@allow_update_after
async def set_enabled(self, enable: bool) -> dict:
"""Set the tamper detection enabled state."""
params = {"enabled": "on" if enable else "off"}
return await self._device._query_setter_helper(
"setTamperDetectionConfig", self.QUERY_MODULE_NAME, "tamper_det", params
)
DETECTION_FEATURE_ID = "tamper_detection"
DETECTION_FEATURE_NAME = "Tamper detection"
QUERY_SETTER_NAME = "setTamperDetectionConfig"
QUERY_SET_SECTION_NAME = "tamper_det"

View File

@@ -0,0 +1,24 @@
"""Implementation of vehicle detection module."""
from __future__ import annotations
import logging
from kasa.smartcam.detectionmodule import DetectionModule
_LOGGER = logging.getLogger(__name__)
class VehicleDetection(DetectionModule):
"""Implementation of vehicle detection module."""
REQUIRED_COMPONENT = "vehicleDetection"
QUERY_GETTER_NAME = "getVehicleDetectionConfig"
QUERY_MODULE_NAME = "vehicle_detection"
QUERY_SECTION_NAMES = "detection"
DETECTION_FEATURE_ID = "vehicle_detection"
DETECTION_FEATURE_NAME = "Vehicle detection"
QUERY_SETTER_NAME = "setVehicleDetectionConfig"
QUERY_SET_SECTION_NAME = "detection"

View File

@@ -36,6 +36,22 @@ class SmartCamModule(SmartModule):
"BabyCryDetection"
)
SmartCamLineCrossingDetection: Final[ModuleName[modules.LineCrossingDetection]] = (
ModuleName("LineCrossingDetection")
)
SmartCamBarkDetection: Final[ModuleName[modules.BarkDetection]] = ModuleName(
"BarkDetection"
)
SmartCamGlassDetection: Final[ModuleName[modules.GlassDetection]] = ModuleName(
"GlassDetection"
)
SmartCamMeowDetection: Final[ModuleName[modules.MeowDetection]] = ModuleName(
"MeowDetection"
)
SmartCamVehicleDetection: Final[ModuleName[modules.VehicleDetection]] = ModuleName(
"VehicleDetection"
)
SmartCamBattery: Final[ModuleName[modules.Battery]] = ModuleName("Battery")
SmartCamDeviceModule: Final[ModuleName[modules.DeviceModule]] = ModuleName(

File diff suppressed because it is too large Load Diff

View File

@@ -1,45 +0,0 @@
"""Tests for smartcam baby cry detection module."""
from __future__ import annotations
from kasa import Device
from kasa.smartcam.smartcammodule import SmartCamModule
from ...device_fixtures import parametrize
babycrydetection = parametrize(
"has babycry detection",
component_filter="babyCryDetection",
protocol_filter={"SMARTCAM"},
)
@babycrydetection
async def test_babycrydetection(dev: Device):
"""Test device babycry detection."""
babycry = dev.modules.get(SmartCamModule.SmartCamBabyCryDetection)
assert babycry
bcde_feat = dev.features.get("baby_cry_detection")
assert bcde_feat
original_enabled = babycry.enabled
try:
await babycry.set_enabled(not original_enabled)
await dev.update()
assert babycry.enabled is not original_enabled
assert bcde_feat.value is not original_enabled
await babycry.set_enabled(original_enabled)
await dev.update()
assert babycry.enabled is original_enabled
assert bcde_feat.value is original_enabled
await bcde_feat.set_value(not original_enabled)
await dev.update()
assert babycry.enabled is not original_enabled
assert bcde_feat.value is not original_enabled
finally:
await babycry.set_enabled(original_enabled)

View File

@@ -0,0 +1,168 @@
"""Tests for smartcam detections."""
from __future__ import annotations
from typing import NamedTuple
import pytest
from kasa import Device
from kasa.modulemapping import ModuleName
from kasa.smartcam import DetectionModule
from kasa.smartcam.smartcammodule import SmartCamModule
from ...fixtureinfo import filter_fixtures, idgenerator
class Detection(NamedTuple):
desc: str
module: ModuleName[DetectionModule]
feature_name: str
component_filter: str
model_filter: str | None = None
def parametrize_detection(
*,
model_filter=None,
protocol_filter=None,
fixture_name="dev",
extra_params_names: list[str],
extra_params_values: list[Detection],
):
_pytest_parameters = []
_arg_names = fixture_name
if extra_params_names:
_arg_names = f"{fixture_name},{','.join(extra_params_names)}"
_model_filter = model_filter
for _detection in extra_params_values:
if _detection.model_filter:
_model_filter = _detection.model_filter
extra_values = list(map(lambda x: _detection._asdict()[x], extra_params_names))
_pytest_parameters.extend(
[
(i, *extra_values)
for i in filter_fixtures(
_detection.desc,
model_filter=_model_filter,
protocol_filter=protocol_filter,
component_filter=_detection.component_filter,
data_root_filter=None,
device_type_filter=None,
)
]
)
return pytest.mark.parametrize(
_arg_names,
_pytest_parameters,
indirect=[fixture_name],
ids=idgenerator,
)
detections = [
Detection(
desc="has baby cry detection",
module=SmartCamModule.SmartCamBabyCryDetection,
feature_name="baby_cry_detection",
component_filter="babyCryDetection",
),
Detection(
desc="has bark detection",
module=SmartCamModule.SmartCamBarkDetection,
feature_name="bark_detection",
component_filter="barkDetection",
),
Detection(
desc="has glass detection",
module=SmartCamModule.SmartCamGlassDetection,
feature_name="glass_detection",
component_filter="glassDetection",
),
Detection(
desc="has line crossing detection",
module=SmartCamModule.SmartCamLineCrossingDetection,
feature_name="line_crossing_detection",
component_filter="linecrossingDetection",
model_filter="C220(EU)_1.0_1.2.5",
),
Detection(
desc="has meow detection",
module=SmartCamModule.SmartCamMeowDetection,
feature_name="meow_detection",
component_filter="meowDetection",
),
Detection(
desc="has motion detection",
module=SmartCamModule.SmartCamMotionDetection,
feature_name="motion_detection",
component_filter="detection",
),
Detection(
desc="has person detection",
module=SmartCamModule.SmartCamPersonDetection,
feature_name="person_detection",
component_filter="personDetection",
),
Detection(
desc="has pet detection",
module=SmartCamModule.SmartCamPetDetection,
feature_name="pet_detection",
component_filter="petDetection",
),
Detection(
desc="has tamper detection",
module=SmartCamModule.SmartCamTamperDetection,
feature_name="tamper_detection",
component_filter="tamperDetection",
),
Detection(
desc="has vehicle detection",
module=SmartCamModule.SmartCamVehicleDetection,
feature_name="vehicle_detection",
component_filter="vehicleDetection",
),
]
params_detections = parametrize_detection(
protocol_filter={"SMARTCAM"},
extra_params_names=["module", "feature_name"],
extra_params_values=detections,
)
@params_detections
async def test_detections(
dev: Device, module: ModuleName[DetectionModule], feature_name: str
):
detection = dev.modules.get(module)
assert detection
detection_feat = dev.features.get(feature_name)
assert detection_feat
original_enabled = detection.enabled
try:
await detection.set_enabled(not original_enabled)
await dev.update()
assert detection.enabled is not original_enabled
assert detection_feat.value is not original_enabled
await detection.set_enabled(original_enabled)
await dev.update()
assert detection.enabled is original_enabled
assert detection_feat.value is original_enabled
await detection_feat.set_value(not original_enabled)
await dev.update()
assert detection.enabled is not original_enabled
assert detection_feat.value is not original_enabled
finally:
await detection.set_enabled(original_enabled)

View File

@@ -1,43 +0,0 @@
"""Tests for smartcam motion detection module."""
from __future__ import annotations
from kasa import Device
from kasa.smartcam.smartcammodule import SmartCamModule
from ...device_fixtures import parametrize
motiondetection = parametrize(
"has motion detection", component_filter="detection", protocol_filter={"SMARTCAM"}
)
@motiondetection
async def test_motiondetection(dev: Device):
"""Test device motion detection."""
motion = dev.modules.get(SmartCamModule.SmartCamMotionDetection)
assert motion
mde_feat = dev.features.get("motion_detection")
assert mde_feat
original_enabled = motion.enabled
try:
await motion.set_enabled(not original_enabled)
await dev.update()
assert motion.enabled is not original_enabled
assert mde_feat.value is not original_enabled
await motion.set_enabled(original_enabled)
await dev.update()
assert motion.enabled is original_enabled
assert mde_feat.value is original_enabled
await mde_feat.set_value(not original_enabled)
await dev.update()
assert motion.enabled is not original_enabled
assert mde_feat.value is not original_enabled
finally:
await motion.set_enabled(original_enabled)

View File

@@ -1,45 +0,0 @@
"""Tests for smartcam person detection module."""
from __future__ import annotations
from kasa import Device
from kasa.smartcam.smartcammodule import SmartCamModule
from ...device_fixtures import parametrize
persondetection = parametrize(
"has person detection",
component_filter="personDetection",
protocol_filter={"SMARTCAM"},
)
@persondetection
async def test_persondetection(dev: Device):
"""Test device person detection."""
person = dev.modules.get(SmartCamModule.SmartCamPersonDetection)
assert person
pde_feat = dev.features.get("person_detection")
assert pde_feat
original_enabled = person.enabled
try:
await person.set_enabled(not original_enabled)
await dev.update()
assert person.enabled is not original_enabled
assert pde_feat.value is not original_enabled
await person.set_enabled(original_enabled)
await dev.update()
assert person.enabled is original_enabled
assert pde_feat.value is original_enabled
await pde_feat.set_value(not original_enabled)
await dev.update()
assert person.enabled is not original_enabled
assert pde_feat.value is not original_enabled
finally:
await person.set_enabled(original_enabled)

View File

@@ -1,45 +0,0 @@
"""Tests for smartcam pet detection module."""
from __future__ import annotations
from kasa import Device
from kasa.smartcam.smartcammodule import SmartCamModule
from ...device_fixtures import parametrize
petdetection = parametrize(
"has pet detection",
component_filter="petDetection",
protocol_filter={"SMARTCAM"},
)
@petdetection
async def test_petdetection(dev: Device):
"""Test device pet detection."""
pet = dev.modules.get(SmartCamModule.SmartCamPetDetection)
assert pet
pde_feat = dev.features.get("pet_detection")
assert pde_feat
original_enabled = pet.enabled
try:
await pet.set_enabled(not original_enabled)
await dev.update()
assert pet.enabled is not original_enabled
assert pde_feat.value is not original_enabled
await pet.set_enabled(original_enabled)
await dev.update()
assert pet.enabled is original_enabled
assert pde_feat.value is original_enabled
await pde_feat.set_value(not original_enabled)
await dev.update()
assert pet.enabled is not original_enabled
assert pde_feat.value is not original_enabled
finally:
await pet.set_enabled(original_enabled)

View File

@@ -1,45 +0,0 @@
"""Tests for smartcam tamper detection module."""
from __future__ import annotations
from kasa import Device
from kasa.smartcam.smartcammodule import SmartCamModule
from ...device_fixtures import parametrize
tamperdetection = parametrize(
"has tamper detection",
component_filter="tamperDetection",
protocol_filter={"SMARTCAM"},
)
@tamperdetection
async def test_tamperdetection(dev: Device):
"""Test device tamper detection."""
tamper = dev.modules.get(SmartCamModule.SmartCamTamperDetection)
assert tamper
tde_feat = dev.features.get("tamper_detection")
assert tde_feat
original_enabled = tamper.enabled
try:
await tamper.set_enabled(not original_enabled)
await dev.update()
assert tamper.enabled is not original_enabled
assert tde_feat.value is not original_enabled
await tamper.set_enabled(original_enabled)
await dev.update()
assert tamper.enabled is original_enabled
assert tde_feat.value is original_enabled
await tde_feat.set_value(not original_enabled)
await dev.update()
assert tamper.enabled is not original_enabled
assert tde_feat.value is not original_enabled
finally:
await tamper.set_enabled(original_enabled)