mirror of
https://github.com/python-kasa/python-kasa.git
synced 2024-12-22 19:23:34 +00:00
Add T315 fixture, tests for humidity&temperature modules (#802)
This commit is contained in:
parent
adce92a761
commit
3495bd83df
@ -37,7 +37,11 @@ class Module(ABC):
|
||||
|
||||
def _add_feature(self, feature: Feature):
|
||||
"""Add module feature."""
|
||||
feat_name = f"{self._module}_{feature.name}"
|
||||
|
||||
def _slugified_name(name):
|
||||
return name.lower().replace(" ", "_").replace("'", "_")
|
||||
|
||||
feat_name = _slugified_name(feature.name)
|
||||
if feat_name in self._module_features:
|
||||
raise KasaException("Duplicate name detected %s" % feat_name)
|
||||
self._module_features[feat_name] = feature
|
||||
|
@ -11,7 +11,7 @@ if TYPE_CHECKING:
|
||||
class TemperatureSensor(SmartModule):
|
||||
"""Implementation of temperature module."""
|
||||
|
||||
REQUIRED_COMPONENT = "humidity"
|
||||
REQUIRED_COMPONENT = "temperature"
|
||||
QUERY_GETTER_NAME = "get_comfort_temp_config"
|
||||
|
||||
def __init__(self, device: "SmartDevice", module: str):
|
||||
@ -53,7 +53,7 @@ class TemperatureSensor(SmartModule):
|
||||
|
||||
@property
|
||||
def temperature_warning(self) -> bool:
|
||||
"""Return True if humidity is outside of the wanted range."""
|
||||
"""Return True if temperature is outside of the wanted range."""
|
||||
return self._device.sys_info["current_temp_exception"] != 0
|
||||
|
||||
@property
|
||||
|
@ -2,7 +2,7 @@ import warnings
|
||||
from typing import Dict
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest # type: ignore # see https://github.com/pytest-dev/pytest/issues/3342
|
||||
import pytest
|
||||
|
||||
from kasa import (
|
||||
DeviceConfig,
|
||||
|
@ -1,3 +1,4 @@
|
||||
from itertools import chain
|
||||
from typing import Dict, List, Set
|
||||
|
||||
import pytest
|
||||
@ -106,6 +107,7 @@ DIMMERS = {
|
||||
}
|
||||
|
||||
HUBS_SMART = {"H100"}
|
||||
SENSORS_SMART = {"T315"}
|
||||
|
||||
WITH_EMETER_IOT = {"HS110", "HS300", "KP115", "KP125", *BULBS_IOT}
|
||||
WITH_EMETER_SMART = {"P110", "KP125M", "EP25"}
|
||||
@ -121,6 +123,7 @@ ALL_DEVICES_SMART = (
|
||||
.union(STRIPS_SMART)
|
||||
.union(DIMMERS_SMART)
|
||||
.union(HUBS_SMART)
|
||||
.union(SENSORS_SMART)
|
||||
.union(SWITCHES_SMART)
|
||||
)
|
||||
ALL_DEVICES = ALL_DEVICES_IOT.union(ALL_DEVICES_SMART)
|
||||
@ -263,6 +266,9 @@ dimmers_smart = parametrize(
|
||||
hubs_smart = parametrize(
|
||||
"hubs smart", model_filter=HUBS_SMART, protocol_filter={"SMART"}
|
||||
)
|
||||
sensors_smart = parametrize(
|
||||
"sensors smart", model_filter=SENSORS_SMART, protocol_filter={"SMART.CHILD"}
|
||||
)
|
||||
device_smart = parametrize(
|
||||
"devices smart", model_filter=ALL_DEVICES_SMART, protocol_filter={"SMART"}
|
||||
)
|
||||
@ -283,6 +289,7 @@ def check_categories():
|
||||
+ bulb_smart.args[1]
|
||||
+ dimmers_smart.args[1]
|
||||
+ hubs_smart.args[1]
|
||||
+ sensors_smart.args[1]
|
||||
)
|
||||
diffs: Set[FixtureInfo] = set(FIXTURE_DATA) - set(categorized_fixtures)
|
||||
if diffs:
|
||||
@ -299,24 +306,14 @@ check_categories()
|
||||
|
||||
def device_for_fixture_name(model, protocol):
|
||||
if "SMART" in protocol:
|
||||
for d in PLUGS_SMART:
|
||||
for d in chain(
|
||||
PLUGS_SMART, SWITCHES_SMART, STRIPS_SMART, HUBS_SMART, SENSORS_SMART
|
||||
):
|
||||
if d in model:
|
||||
return SmartDevice
|
||||
for d in SWITCHES_SMART:
|
||||
if d in model:
|
||||
return SmartDevice
|
||||
for d in BULBS_SMART:
|
||||
for d in chain(BULBS_SMART, DIMMERS_SMART):
|
||||
if d in model:
|
||||
return SmartBulb
|
||||
for d in DIMMERS_SMART:
|
||||
if d in model:
|
||||
return SmartBulb
|
||||
for d in STRIPS_SMART:
|
||||
if d in model:
|
||||
return SmartDevice
|
||||
for d in HUBS_SMART:
|
||||
if d in model:
|
||||
return SmartDevice
|
||||
else:
|
||||
for d in STRIPS_IOT:
|
||||
if d in model:
|
||||
@ -378,6 +375,7 @@ async def get_device_for_fixture(fixture_data: FixtureInfo):
|
||||
discovery_data = {
|
||||
"system": {"get_sysinfo": fixture_data.data["system"]["get_sysinfo"]}
|
||||
}
|
||||
|
||||
if discovery_data: # Child devices do not have discovery info
|
||||
d.update_from_discover_info(discovery_data)
|
||||
|
||||
@ -392,7 +390,7 @@ async def get_device_for_fixture_protocol(fixture, protocol):
|
||||
return await get_device_for_fixture(fixture_info)
|
||||
|
||||
|
||||
@pytest.fixture(params=FIXTURE_DATA, ids=idgenerator)
|
||||
@pytest.fixture(params=filter_fixtures("main devices"), ids=idgenerator)
|
||||
async def dev(request):
|
||||
"""Device fixture.
|
||||
|
||||
|
@ -93,7 +93,7 @@ def filter_fixtures(
|
||||
|
||||
data_root_filter: return fixtures containing the supplied top
|
||||
level key, i.e. discovery_result
|
||||
protocol_filter: set of protocols to match, IOT or SMART
|
||||
protocol_filter: set of protocols to match, IOT, SMART, SMART.CHILD
|
||||
model_filter: set of device models to match
|
||||
component_filter: filter SMART fixtures that have the provided
|
||||
component in component_nego details.
|
||||
|
1
kasa/tests/fixtures/smart/child/.gitkeep
vendored
1
kasa/tests/fixtures/smart/child/.gitkeep
vendored
@ -1 +0,0 @@
|
||||
Can be deleted when first fixture is added
|
537
kasa/tests/fixtures/smart/child/T315(EU)_1.0_1.7.0.json
vendored
Normal file
537
kasa/tests/fixtures/smart/child/T315(EU)_1.0_1.7.0.json
vendored
Normal file
@ -0,0 +1,537 @@
|
||||
{
|
||||
"component_nego" : {
|
||||
"component_list" : [
|
||||
{
|
||||
"id" : "device",
|
||||
"ver_code" : 2
|
||||
},
|
||||
{
|
||||
"id" : "quick_setup",
|
||||
"ver_code" : 3
|
||||
},
|
||||
{
|
||||
"id" : "trigger_log",
|
||||
"ver_code" : 1
|
||||
},
|
||||
{
|
||||
"id" : "time",
|
||||
"ver_code" : 1
|
||||
},
|
||||
{
|
||||
"id" : "device_local_time",
|
||||
"ver_code" : 1
|
||||
},
|
||||
{
|
||||
"id" : "account",
|
||||
"ver_code" : 1
|
||||
},
|
||||
{
|
||||
"id" : "synchronize",
|
||||
"ver_code" : 1
|
||||
},
|
||||
{
|
||||
"id" : "cloud_connect",
|
||||
"ver_code" : 1
|
||||
},
|
||||
{
|
||||
"id" : "iot_cloud",
|
||||
"ver_code" : 1
|
||||
},
|
||||
{
|
||||
"id" : "firmware",
|
||||
"ver_code" : 1
|
||||
},
|
||||
{
|
||||
"id" : "localSmart",
|
||||
"ver_code" : 1
|
||||
},
|
||||
{
|
||||
"id" : "battery_detect",
|
||||
"ver_code" : 1
|
||||
},
|
||||
{
|
||||
"id" : "temperature",
|
||||
"ver_code" : 1
|
||||
},
|
||||
{
|
||||
"id" : "humidity",
|
||||
"ver_code" : 1
|
||||
},
|
||||
{
|
||||
"id" : "temp_humidity_record",
|
||||
"ver_code" : 1
|
||||
},
|
||||
{
|
||||
"id" : "comfort_temperature",
|
||||
"ver_code" : 1
|
||||
},
|
||||
{
|
||||
"id" : "comfort_humidity",
|
||||
"ver_code" : 1
|
||||
},
|
||||
{
|
||||
"id" : "report_mode",
|
||||
"ver_code" : 1
|
||||
}
|
||||
]
|
||||
},
|
||||
"get_connect_cloud_state" : {
|
||||
"status" : 0
|
||||
},
|
||||
"get_device_info" : {
|
||||
"at_low_battery" : false,
|
||||
"avatar" : "",
|
||||
"battery_percentage" : 100,
|
||||
"bind_count" : 1,
|
||||
"category" : "subg.trigger.temp-hmdt-sensor",
|
||||
"current_humidity" : 61,
|
||||
"current_humidity_exception" : 1,
|
||||
"current_temp" : 21.4,
|
||||
"current_temp_exception" : 0,
|
||||
"device_id" : "SCRUBBED_CHILD_DEVICE_ID_1",
|
||||
"fw_ver" : "1.7.0 Build 230424 Rel.170332",
|
||||
"hw_id" : "00000000000000000000000000000000",
|
||||
"hw_ver" : "1.0",
|
||||
"jamming_rssi" : -122,
|
||||
"jamming_signal_level" : 1,
|
||||
"lastOnboardingTimestamp" : 1706990901,
|
||||
"mac" : "F0A731000000",
|
||||
"model" : "T315",
|
||||
"nickname" : "I01BU0tFRF9OQU1FIw==",
|
||||
"oem_id" : "00000000000000000000000000000000",
|
||||
"parent_device_id" : "0000000000000000000000000000000000000000",
|
||||
"region" : "Europe/Berlin",
|
||||
"report_interval" : 16,
|
||||
"rssi" : -56,
|
||||
"signal_level" : 3,
|
||||
"specs" : "EU",
|
||||
"status" : "online",
|
||||
"status_follow_edge" : false,
|
||||
"temp_unit" : "celsius",
|
||||
"type" : "SMART.TAPOSENSOR"
|
||||
},
|
||||
"get_fw_download_state" : {
|
||||
"cloud_cache_seconds" : 1,
|
||||
"download_progress" : 0,
|
||||
"reboot_time" : 5,
|
||||
"status" : 0,
|
||||
"upgrade_time" : 5
|
||||
},
|
||||
"get_latest_fw" : {
|
||||
"fw_ver" : "1.8.0 Build 230921 Rel.091446",
|
||||
"hw_id" : "00000000000000000000000000000000",
|
||||
"need_to_upgrade" : true,
|
||||
"oem_id" : "00000000000000000000000000000000",
|
||||
"release_date" : "2023-12-01",
|
||||
"release_note" : "Modifications and Bug Fixes:\nEnhance the stability of the sensor.",
|
||||
"type" : 2
|
||||
},
|
||||
"get_temp_humidity_records" : {
|
||||
"local_time" : 1709061516,
|
||||
"past24h_humidity" : [
|
||||
60,
|
||||
60,
|
||||
59,
|
||||
59,
|
||||
59,
|
||||
59,
|
||||
59,
|
||||
59,
|
||||
59,
|
||||
59,
|
||||
58,
|
||||
59,
|
||||
59,
|
||||
58,
|
||||
59,
|
||||
59,
|
||||
59,
|
||||
60,
|
||||
60,
|
||||
60,
|
||||
60,
|
||||
60,
|
||||
60,
|
||||
60,
|
||||
60,
|
||||
60,
|
||||
60,
|
||||
60,
|
||||
60,
|
||||
60,
|
||||
60,
|
||||
60,
|
||||
60,
|
||||
60,
|
||||
60,
|
||||
60,
|
||||
60,
|
||||
60,
|
||||
59,
|
||||
59,
|
||||
59,
|
||||
59,
|
||||
59,
|
||||
59,
|
||||
60,
|
||||
60,
|
||||
59,
|
||||
59,
|
||||
59,
|
||||
59,
|
||||
59,
|
||||
59,
|
||||
59,
|
||||
59,
|
||||
59,
|
||||
59,
|
||||
59,
|
||||
59,
|
||||
59,
|
||||
59,
|
||||
59,
|
||||
59,
|
||||
59,
|
||||
59,
|
||||
59,
|
||||
59,
|
||||
59,
|
||||
60,
|
||||
60,
|
||||
60,
|
||||
60,
|
||||
60,
|
||||
60,
|
||||
60,
|
||||
60,
|
||||
60,
|
||||
64,
|
||||
56,
|
||||
53,
|
||||
55,
|
||||
56,
|
||||
57,
|
||||
57,
|
||||
58,
|
||||
59,
|
||||
63,
|
||||
63,
|
||||
62,
|
||||
62,
|
||||
62,
|
||||
62,
|
||||
61,
|
||||
62,
|
||||
62,
|
||||
61,
|
||||
61
|
||||
],
|
||||
"past24h_humidity_exception" : [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
4,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
3,
|
||||
3,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
1,
|
||||
2,
|
||||
2,
|
||||
1,
|
||||
1
|
||||
],
|
||||
"past24h_temp" : [
|
||||
217,
|
||||
216,
|
||||
215,
|
||||
214,
|
||||
214,
|
||||
214,
|
||||
214,
|
||||
214,
|
||||
214,
|
||||
213,
|
||||
213,
|
||||
213,
|
||||
213,
|
||||
213,
|
||||
212,
|
||||
212,
|
||||
211,
|
||||
211,
|
||||
211,
|
||||
211,
|
||||
211,
|
||||
211,
|
||||
212,
|
||||
212,
|
||||
212,
|
||||
211,
|
||||
211,
|
||||
211,
|
||||
211,
|
||||
212,
|
||||
212,
|
||||
212,
|
||||
212,
|
||||
212,
|
||||
211,
|
||||
211,
|
||||
211,
|
||||
212,
|
||||
213,
|
||||
214,
|
||||
214,
|
||||
214,
|
||||
213,
|
||||
212,
|
||||
212,
|
||||
212,
|
||||
212,
|
||||
212,
|
||||
212,
|
||||
212,
|
||||
212,
|
||||
212,
|
||||
212,
|
||||
213,
|
||||
213,
|
||||
213,
|
||||
213,
|
||||
213,
|
||||
213,
|
||||
213,
|
||||
213,
|
||||
213,
|
||||
213,
|
||||
214,
|
||||
214,
|
||||
215,
|
||||
215,
|
||||
215,
|
||||
214,
|
||||
215,
|
||||
216,
|
||||
216,
|
||||
216,
|
||||
216,
|
||||
216,
|
||||
216,
|
||||
216,
|
||||
205,
|
||||
196,
|
||||
210,
|
||||
213,
|
||||
213,
|
||||
213,
|
||||
213,
|
||||
213,
|
||||
214,
|
||||
215,
|
||||
214,
|
||||
214,
|
||||
213,
|
||||
213,
|
||||
214,
|
||||
214,
|
||||
214,
|
||||
213,
|
||||
213
|
||||
],
|
||||
"past24h_temp_exception" : [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
-4,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"temp_unit" : "celsius"
|
||||
},
|
||||
"get_trigger_logs" : {
|
||||
"logs" : [
|
||||
{
|
||||
"event" : "tooDry",
|
||||
"eventId" : "118040a8-5422-1100-0804-0a8542211000",
|
||||
"id" : 1,
|
||||
"timestamp" : 1706996915
|
||||
}
|
||||
],
|
||||
"start_id" : 1,
|
||||
"sum" : 1
|
||||
}
|
||||
}
|
0
kasa/tests/smart/__init__.py
Normal file
0
kasa/tests/smart/__init__.py
Normal file
0
kasa/tests/smart/modules/__init__.py
Normal file
0
kasa/tests/smart/modules/__init__.py
Normal file
26
kasa/tests/smart/modules/test_humidity.py
Normal file
26
kasa/tests/smart/modules/test_humidity.py
Normal file
@ -0,0 +1,26 @@
|
||||
import pytest
|
||||
|
||||
from kasa.smart.modules import HumiditySensor
|
||||
from kasa.tests.device_fixtures import parametrize
|
||||
|
||||
humidity = parametrize("has humidity", component_filter="humidity", protocol_filter={"SMART.CHILD"})
|
||||
|
||||
|
||||
@humidity
|
||||
@pytest.mark.parametrize(
|
||||
"feature, type",
|
||||
[
|
||||
("humidity", int),
|
||||
("humidity_warning", bool),
|
||||
],
|
||||
)
|
||||
async def test_humidity_features(dev, feature, type):
|
||||
"""Test that features are registered and work as expected."""
|
||||
humidity: HumiditySensor = dev.modules["HumiditySensor"]
|
||||
|
||||
prop = getattr(humidity, feature)
|
||||
assert isinstance(prop, type)
|
||||
|
||||
feat = humidity._module_features[feature]
|
||||
assert feat.value == prop
|
||||
assert isinstance(feat.value, type)
|
27
kasa/tests/smart/modules/test_temperature.py
Normal file
27
kasa/tests/smart/modules/test_temperature.py
Normal file
@ -0,0 +1,27 @@
|
||||
import pytest
|
||||
|
||||
from kasa.smart.modules import TemperatureSensor
|
||||
from kasa.tests.device_fixtures import parametrize
|
||||
|
||||
temperature = parametrize("has temperature", component_filter="temperature", protocol_filter={"SMART.CHILD"})
|
||||
|
||||
|
||||
@temperature
|
||||
@pytest.mark.parametrize(
|
||||
"feature, type",
|
||||
[
|
||||
("temperature", float),
|
||||
("temperature_warning", bool),
|
||||
("temperature_unit", str),
|
||||
],
|
||||
)
|
||||
async def test_temperature_features(dev, feature, type):
|
||||
"""Test that features are registered and work as expected."""
|
||||
temp_module: TemperatureSensor = dev.modules["TemperatureSensor"]
|
||||
|
||||
prop = getattr(temp_module, feature)
|
||||
assert isinstance(prop, type)
|
||||
|
||||
feat = temp_module._module_features[feature]
|
||||
assert feat.value == prop
|
||||
assert isinstance(feat.value, type)
|
Loading…
Reference in New Issue
Block a user