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

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)