mirror of
https://github.com/python-kasa/python-kasa.git
synced 2025-08-09 20:24:02 +00:00
Initial implementation for modularized smartdevice (#757)
The initial steps to modularize the smartdevice. Modules are initialized based on the component negotiation, and each module can indicate which features it supports and which queries should be run during the update cycle.
This commit is contained in:
@@ -24,7 +24,8 @@ from ..emeterstatus import EmeterStatus
|
||||
from ..exceptions import SmartDeviceException
|
||||
from ..feature import Feature
|
||||
from ..protocol import BaseProtocol
|
||||
from .modules import Emeter, IotModule
|
||||
from .iotmodule import IotModule
|
||||
from .modules import Emeter
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@@ -1,20 +1,14 @@
|
||||
"""Base class for all module implementations."""
|
||||
"""Base class for IOT module implementations."""
|
||||
import collections
|
||||
import logging
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import TYPE_CHECKING, Dict
|
||||
|
||||
from ...exceptions import SmartDeviceException
|
||||
from ...feature import Feature
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from kasa.iot import IotDevice
|
||||
|
||||
from ..exceptions import SmartDeviceException
|
||||
from ..module import Module
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# TODO: This is used for query construcing
|
||||
# TODO: This is used for query constructing, check for a better place
|
||||
def merge(d, u):
|
||||
"""Update dict recursively."""
|
||||
for k, v in u.items():
|
||||
@@ -25,32 +19,16 @@ def merge(d, u):
|
||||
return d
|
||||
|
||||
|
||||
class IotModule(ABC):
|
||||
"""Base class implemention for all modules.
|
||||
class IotModule(Module):
|
||||
"""Base class implemention for all IOT modules."""
|
||||
|
||||
The base classes should implement `query` to return the query they want to be
|
||||
executed during the regular update cycle.
|
||||
"""
|
||||
def call(self, method, params=None):
|
||||
"""Call the given method with the given parameters."""
|
||||
return self._device._query_helper(self._module, method, params)
|
||||
|
||||
def __init__(self, device: "IotDevice", module: str):
|
||||
self._device = device
|
||||
self._module = module
|
||||
self._module_features: Dict[str, Feature] = {}
|
||||
|
||||
def _add_feature(self, feature: Feature):
|
||||
"""Add module feature."""
|
||||
feature_name = f"{self._module}_{feature.name}"
|
||||
if feature_name in self._module_features:
|
||||
raise SmartDeviceException("Duplicate name detected %s" % feature_name)
|
||||
self._module_features[feature_name] = feature
|
||||
|
||||
@abstractmethod
|
||||
def query(self):
|
||||
"""Query to execute during the update cycle.
|
||||
|
||||
The inheriting modules implement this to include their wanted
|
||||
queries to the query that gets executed when Device.update() gets called.
|
||||
"""
|
||||
def query_for_command(self, query, params=None):
|
||||
"""Create a request object for the given parameters."""
|
||||
return self._device._create_request(self._module, query, params)
|
||||
|
||||
@property
|
||||
def estimated_query_response_size(self):
|
||||
@@ -80,17 +58,3 @@ class IotModule(ABC):
|
||||
return True
|
||||
|
||||
return "err_code" not in self.data
|
||||
|
||||
def call(self, method, params=None):
|
||||
"""Call the given method with the given parameters."""
|
||||
return self._device._query_helper(self._module, method, params)
|
||||
|
||||
def query_for_command(self, query, params=None):
|
||||
"""Create a request object for the given parameters."""
|
||||
return self._device._create_request(self._module, query, params)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return (
|
||||
f"<Module {self.__class__.__name__} ({self._module})"
|
||||
f" for {self._device.host}>"
|
||||
)
|
@@ -4,7 +4,6 @@ from .antitheft import Antitheft
|
||||
from .cloud import Cloud
|
||||
from .countdown import Countdown
|
||||
from .emeter import Emeter
|
||||
from .module import IotModule
|
||||
from .motion import Motion
|
||||
from .rulemodule import Rule, RuleModule
|
||||
from .schedule import Schedule
|
||||
@@ -17,7 +16,6 @@ __all__ = [
|
||||
"Cloud",
|
||||
"Countdown",
|
||||
"Emeter",
|
||||
"IotModule",
|
||||
"Motion",
|
||||
"Rule",
|
||||
"RuleModule",
|
||||
|
@@ -1,5 +1,5 @@
|
||||
"""Implementation of the ambient light (LAS) module found in some dimmers."""
|
||||
from .module import IotModule
|
||||
from ..iotmodule import IotModule
|
||||
|
||||
# TODO create tests and use the config reply there
|
||||
# [{"hw_id":0,"enable":0,"dark_index":1,"min_adc":0,"max_adc":2450,
|
||||
|
@@ -5,7 +5,7 @@ except ImportError:
|
||||
from pydantic import BaseModel
|
||||
|
||||
from ...feature import Feature, FeatureType
|
||||
from .module import IotModule
|
||||
from ..iotmodule import IotModule
|
||||
|
||||
|
||||
class CloudInfo(BaseModel):
|
||||
|
@@ -3,7 +3,7 @@ from enum import Enum
|
||||
from typing import Optional
|
||||
|
||||
from ...exceptions import SmartDeviceException
|
||||
from .module import IotModule
|
||||
from ..iotmodule import IotModule
|
||||
|
||||
|
||||
class Range(Enum):
|
||||
|
@@ -9,7 +9,7 @@ except ImportError:
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
from .module import IotModule, merge
|
||||
from ..iotmodule import IotModule, merge
|
||||
|
||||
|
||||
class Action(Enum):
|
||||
|
@@ -2,7 +2,7 @@
|
||||
from datetime import datetime
|
||||
|
||||
from ...exceptions import SmartDeviceException
|
||||
from .module import IotModule, merge
|
||||
from ..iotmodule import IotModule, merge
|
||||
|
||||
|
||||
class Time(IotModule):
|
||||
|
@@ -2,7 +2,7 @@
|
||||
from datetime import datetime
|
||||
from typing import Dict
|
||||
|
||||
from .module import IotModule, merge
|
||||
from ..iotmodule import IotModule, merge
|
||||
|
||||
|
||||
class Usage(IotModule):
|
||||
|
Reference in New Issue
Block a user