mirror of
https://github.com/python-kasa/python-kasa.git
synced 2025-08-09 20:24:02 +00:00
Add battery module to smartcam devices (#1452)
Some checks are pending
CI / Perform linting checks (3.13) (push) Waiting to run
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.13) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.13) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.13) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.13) (push) Blocked by required conditions
CodeQL checks / Analyze (python) (push) Waiting to run
Some checks are pending
CI / Perform linting checks (3.13) (push) Waiting to run
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.13) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.13) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.13) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.13) (push) Blocked by required conditions
CodeQL checks / Analyze (python) (push) Waiting to run
This commit is contained in:
@@ -435,6 +435,15 @@ async def get_device_for_fixture(
|
||||
d = device_for_fixture_name(fixture_data.name, fixture_data.protocol)(
|
||||
host="127.0.0.123"
|
||||
)
|
||||
|
||||
# smart child devices sometimes check _is_hub_child which needs a parent
|
||||
# of DeviceType.Hub
|
||||
class DummyParent:
|
||||
device_type = DeviceType.Hub
|
||||
|
||||
if fixture_data.protocol in {"SMARTCAM.CHILD"}:
|
||||
d._parent = DummyParent()
|
||||
|
||||
if fixture_data.protocol in {"SMART", "SMART.CHILD"}:
|
||||
d.protocol = FakeSmartProtocol(
|
||||
fixture_data.data, fixture_data.name, verbatim=verbatim
|
||||
|
@@ -262,7 +262,10 @@ class FakeSmartTransport(BaseTransport):
|
||||
child_fixture["get_device_info"]["device_id"] = device_id
|
||||
found_child_fixture_infos.append(child_fixture["get_device_info"])
|
||||
child_protocols[device_id] = FakeSmartProtocol(
|
||||
child_fixture, fixture_info_tuple.name, is_child=True
|
||||
child_fixture,
|
||||
fixture_info_tuple.name,
|
||||
is_child=True,
|
||||
verbatim=verbatim,
|
||||
)
|
||||
# Look for fixture inline
|
||||
elif (child_fixtures := parent_fixture_info.get("child_devices")) and (
|
||||
@@ -273,6 +276,7 @@ class FakeSmartTransport(BaseTransport):
|
||||
child_fixture,
|
||||
f"{parent_fixture_name}-{device_id}",
|
||||
is_child=True,
|
||||
verbatim=verbatim,
|
||||
)
|
||||
else:
|
||||
pytest.fixtures_missing_methods.setdefault( # type: ignore[attr-defined]
|
||||
@@ -299,7 +303,10 @@ class FakeSmartTransport(BaseTransport):
|
||||
# list for smartcam children in order for updates to work.
|
||||
found_child_fixture_infos.append(child_fixture[CHILD_INFO_FROM_PARENT])
|
||||
child_protocols[device_id] = FakeSmartCamProtocol(
|
||||
child_fixture, fixture_info_tuple.name, is_child=True
|
||||
child_fixture,
|
||||
fixture_info_tuple.name,
|
||||
is_child=True,
|
||||
verbatim=verbatim,
|
||||
)
|
||||
else:
|
||||
warn(
|
||||
|
@@ -6,7 +6,7 @@ from typing import Any
|
||||
|
||||
from kasa import Credentials, DeviceConfig, SmartProtocol
|
||||
from kasa.protocols.smartcamprotocol import SmartCamProtocol
|
||||
from kasa.smartcam.smartcamchild import CHILD_INFO_FROM_PARENT
|
||||
from kasa.smartcam.smartcamchild import CHILD_INFO_FROM_PARENT, SmartCamChild
|
||||
from kasa.transports.basetransport import BaseTransport
|
||||
|
||||
from .fakeprotocol_smart import FakeSmartTransport
|
||||
@@ -243,6 +243,20 @@ class FakeSmartCamTransport(BaseTransport):
|
||||
else:
|
||||
return {"error_code": -1}
|
||||
|
||||
# smartcam child devices do not make requests for getDeviceInfo as they
|
||||
# get updated from the parent's query. If this is being called from a
|
||||
# child it must be because the fixture has been created directly on the
|
||||
# child device with a dummy parent. In this case return the child info
|
||||
# from parent that's inside the fixture.
|
||||
if (
|
||||
not self.verbatim
|
||||
and method == "getDeviceInfo"
|
||||
and (cifp := info.get(CHILD_INFO_FROM_PARENT))
|
||||
):
|
||||
mapped = SmartCamChild._map_child_info_from_parent(cifp)
|
||||
result = {"device_info": {"basic_info": mapped}}
|
||||
return {"result": result, "error_code": 0}
|
||||
|
||||
if method in info:
|
||||
params = request_dict.get("params")
|
||||
result = copy.deepcopy(info[method])
|
||||
|
@@ -269,7 +269,7 @@ async def test_hub_children_update_delays(
|
||||
for modname, module in child._modules.items():
|
||||
if (
|
||||
not (q := module.query())
|
||||
and modname not in {"DeviceModule", "Light"}
|
||||
and modname not in {"DeviceModule", "Light", "Battery", "Camera"}
|
||||
and not module.SYSINFO_LOOKUP_KEYS
|
||||
):
|
||||
q = {f"get_dummy_{modname}": {}}
|
||||
|
33
tests/smartcam/modules/test_battery.py
Normal file
33
tests/smartcam/modules/test_battery.py
Normal file
@@ -0,0 +1,33 @@
|
||||
"""Tests for smartcam battery module."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from kasa import Device
|
||||
from kasa.smartcam.smartcammodule import SmartCamModule
|
||||
|
||||
from ...device_fixtures import parametrize
|
||||
|
||||
battery_smartcam = parametrize(
|
||||
"has battery",
|
||||
component_filter="battery",
|
||||
protocol_filter={"SMARTCAM", "SMARTCAM.CHILD"},
|
||||
)
|
||||
|
||||
|
||||
@battery_smartcam
|
||||
async def test_battery(dev: Device):
|
||||
"""Test device battery."""
|
||||
battery = dev.modules.get(SmartCamModule.SmartCamBattery)
|
||||
assert battery
|
||||
|
||||
feat_ids = {
|
||||
"battery_level",
|
||||
"battery_low",
|
||||
"battery_temperature",
|
||||
"battery_voltage",
|
||||
"battery_charging",
|
||||
}
|
||||
for feat_id in feat_ids:
|
||||
feat = dev.features.get(feat_id)
|
||||
assert feat
|
||||
assert feat.value is not None
|
Reference in New Issue
Block a user