python-kasa/tests/smart/modules/test_powerprotection.py
Teemu R. 62c1dd87dc
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
Add powerprotection module (#1337)
Implements power protection on supported devices.
If the power usage is above the given threshold and the feature is
enabled, the device will be turned off.

Adds the following features:
* `overloaded` binary sensor
* `power_protection_threshold` number, setting this to `0` turns the
feature off.

---------

Co-authored-by: Steven B <51370195+sdb9696@users.noreply.github.com>
2025-01-26 01:43:02 +01:00

99 lines
3.0 KiB
Python

import pytest
from pytest_mock import MockerFixture
from kasa import Module, SmartDevice
from ...device_fixtures import get_parent_and_child_modules, parametrize
powerprotection = parametrize(
"has powerprotection",
component_filter="power_protection",
protocol_filter={"SMART"},
)
@powerprotection
@pytest.mark.parametrize(
("feature", "prop_name", "type"),
[
("overloaded", "overloaded", bool),
("power_protection_threshold", "protection_threshold", int),
],
)
async def test_features(dev, feature, prop_name, type):
"""Test that features are registered and work as expected."""
powerprot = next(get_parent_and_child_modules(dev, Module.PowerProtection))
assert powerprot
device = powerprot._device
prop = getattr(powerprot, prop_name)
assert isinstance(prop, type)
feat = device.features[feature]
assert feat.value == prop
assert isinstance(feat.value, type)
@powerprotection
async def test_set_enable(dev: SmartDevice, mocker: MockerFixture):
"""Test enable."""
powerprot = next(get_parent_and_child_modules(dev, Module.PowerProtection))
assert powerprot
device = powerprot._device
original_enabled = powerprot.enabled
original_threshold = powerprot.protection_threshold
try:
# Simple enable with an existing threshold
call_spy = mocker.spy(powerprot, "call")
await powerprot.set_enabled(True)
params = {
"enabled": True,
"protection_power": mocker.ANY,
}
call_spy.assert_called_with("set_protection_power", params)
# Enable with no threshold param when 0
call_spy.reset_mock()
await powerprot.set_protection_threshold(0)
await device.update()
await powerprot.set_enabled(True)
params = {
"enabled": True,
"protection_power": int(powerprot._max_power / 2),
}
call_spy.assert_called_with("set_protection_power", params)
# Enable false should not update the threshold
call_spy.reset_mock()
await powerprot.set_protection_threshold(0)
await device.update()
await powerprot.set_enabled(False)
params = {
"enabled": False,
"protection_power": 0,
}
call_spy.assert_called_with("set_protection_power", params)
finally:
await powerprot.set_enabled(original_enabled, threshold=original_threshold)
@powerprotection
async def test_set_threshold(dev: SmartDevice, mocker: MockerFixture):
"""Test enable."""
powerprot = next(get_parent_and_child_modules(dev, Module.PowerProtection))
assert powerprot
call_spy = mocker.spy(powerprot, "call")
await powerprot.set_protection_threshold(123)
params = {
"enabled": mocker.ANY,
"protection_power": 123,
}
call_spy.assert_called_with("set_protection_power", params)
with pytest.raises(ValueError, match="Threshold out of range"):
await powerprot.set_protection_threshold(-10)