Add bare-bones matter modules to smart and smartcam devices (#1371)

This commit is contained in:
Steven B.
2024-12-13 19:45:38 +00:00
committed by GitHub
parent 223f3318ea
commit 2ca6d3ebe9
12 changed files with 183 additions and 12 deletions

View File

@@ -151,6 +151,13 @@ class FakeSmartTransport(BaseTransport):
"energy_monitoring",
{"igain": 10861, "vgain": 118657},
),
"get_matter_setup_info": (
"matter",
{
"setup_code": "00000000000",
"setup_payload": "00:0000000-0000.00.000",
},
),
}
async def send(self, request: str):

View File

@@ -44,6 +44,7 @@ class FakeSmartCamTransport(BaseTransport):
),
),
)
self.fixture_name = fixture_name
# When True verbatim will bypass any extra processing of missing
# methods and is used to test the fixture creation itself.
@@ -58,6 +59,13 @@ class FakeSmartCamTransport(BaseTransport):
# self.child_protocols = self._get_child_protocols()
self.list_return_size = list_return_size
self.components = {
comp["name"]: comp["version"]
for comp in self.info["getAppComponentList"]["app_component"][
"app_component_list"
]
}
@property
def default_port(self):
"""Default port for the transport."""
@@ -112,6 +120,15 @@ class FakeSmartCamTransport(BaseTransport):
info = info[key]
info[set_keys[-1]] = value
FIXTURE_MISSING_MAP = {
"getMatterSetupInfo": (
"matter",
{
"setup_code": "00000000000",
"setup_payload": "00:0000000-0000.00.000",
},
)
}
# Setters for when there's not a simple mapping of setters to getters
SETTERS = {
("system", "sys", "dev_alias"): [
@@ -217,8 +234,17 @@ class FakeSmartCamTransport(BaseTransport):
start_index : start_index + self.list_return_size
]
return {"result": result, "error_code": 0}
else:
return {"error_code": -1}
if (
# FIXTURE_MISSING is for service calls not in place when
# SMART fixtures started to be generated
missing_result := self.FIXTURE_MISSING_MAP.get(method)
) and missing_result[0] in self.components:
# Copy to info so it will work with update methods
info[method] = copy.deepcopy(missing_result[1])
result = copy.deepcopy(info[method])
return {"result": result, "error_code": 0}
return {"error_code": -1}
return {"error_code": -1}
async def close(self) -> None:

View File

@@ -145,12 +145,21 @@ def filter_fixtures(
def _component_match(
fixture_data: FixtureInfo, component_filter: str | ComponentFilter
):
if (component_nego := fixture_data.data.get("component_nego")) is None:
components = {}
if component_nego := fixture_data.data.get("component_nego"):
components = {
component["id"]: component["ver_code"]
for component in component_nego["component_list"]
}
if get_app_component_list := fixture_data.data.get("getAppComponentList"):
components = {
component["name"]: component["version"]
for component in get_app_component_list["app_component"][
"app_component_list"
]
}
if not components:
return False
components = {
component["id"]: component["ver_code"]
for component in component_nego["component_list"]
}
if isinstance(component_filter, str):
return component_filter in components
else:

View File

@@ -0,0 +1,20 @@
from kasa import Module
from kasa.smart import SmartDevice
from ...device_fixtures import parametrize
matter = parametrize(
"has matter", component_filter="matter", protocol_filter={"SMART", "SMARTCAM"}
)
@matter
async def test_info(dev: SmartDevice):
"""Test matter info."""
matter = dev.modules.get(Module.Matter)
assert matter
assert matter.info
setup_code = dev.features.get("matter_setup_code")
assert setup_code
setup_payload = dev.features.get("matter_setup_payload")
assert setup_payload

View File

@@ -533,3 +533,16 @@ async def test_initialize_modules_required_component(
assert "AvailableComponent" in dev.modules
assert "NonExistingComponent" not in dev.modules
async def test_smartmodule_query():
"""Test that a module that doesn't set QUERY_GETTER_NAME has empty query."""
class DummyModule(SmartModule):
pass
dummy_device = await get_device_for_fixture_protocol(
"KS240(US)_1.0_1.0.5.json", "SMART"
)
mod = DummyModule(dummy_device, "dummy")
assert mod.query() == {}