Add initial support for H100 and T315

Adds initial support for H100 and its alarmmodule.

Also implements the following modules for T315:
* reportmodule (reporting interval)
* battery
* humidity
* temperature
This commit is contained in:
Teemu Rytilahti 2024-02-20 00:32:29 +01:00
parent bced5e40c5
commit 66da963ff0
8 changed files with 281 additions and 1 deletions

View File

@ -14,7 +14,7 @@ from .protocol import (
BaseProtocol,
BaseTransport,
)
from .smart import SmartBulb, SmartPlug
from .smart import SmartBulb, SmartDevice, SmartPlug
from .smartprotocol import SmartProtocol
from .xortransport import XorTransport
@ -138,6 +138,7 @@ def get_device_class_from_family(device_type: str) -> Optional[Type[Device]]:
"SMART.TAPOPLUG": SmartPlug,
"SMART.TAPOBULB": SmartBulb,
"SMART.TAPOSWITCH": SmartBulb,
"SMART.TAPOHUB": SmartDevice,
"SMART.KASAPLUG": SmartPlug,
"SMART.KASASWITCH": SmartBulb,
"IOT.SMARTPLUGSWITCH": IotPlug,

View File

@ -31,6 +31,7 @@ class DeviceFamilyType(Enum):
SmartTapoPlug = "SMART.TAPOPLUG"
SmartTapoBulb = "SMART.TAPOBULB"
SmartTapoSwitch = "SMART.TAPOSWITCH"
SmartTapoHub = "SMART.TAPOHUB"
def _dataclass_from_dict(klass, in_val):

View File

@ -1,18 +1,27 @@
"""Modules for SMART devices."""
from .autooffmodule import AutoOffModule
from .battery import BatterySensor
from .childdevicemodule import ChildDeviceModule
from .cloudmodule import CloudModule
from .devicemodule import DeviceModule
from .energymodule import EnergyModule
from .ledmodule import LedModule
from .lighttransitionmodule import LightTransitionModule
from .humidity import HumiditySensor
from .reportmodule import ReportModule
from .temperature import TemperatureSensor
from .timemodule import TimeModule
__all__ = [
"AlarmModule",
"TimeModule",
"EnergyModule",
"DeviceModule",
"ChildDeviceModule",
"BatterySensor",
"HumiditySensor",
"TemperatureSensor",
"ReportModule",
"AutoOffModule",
"LedModule",
"CloudModule",

View File

@ -0,0 +1,87 @@
"""Implementation of alarm module."""
from typing import TYPE_CHECKING, Dict, List, Optional
from ...feature import Feature, FeatureType
from ..smartmodule import SmartModule
if TYPE_CHECKING:
from ..smartdevice import SmartDevice
class AlarmModule(SmartModule):
"""Implementation of alarm module."""
REQUIRED_COMPONENT = "alarm"
def query(self) -> Dict:
"""Query to execute during the update cycle."""
return {
"get_alarm_configure": None,
"get_support_alarm_type_list": None, # This should be needed only once
}
def __init__(self, device: "SmartDevice", module: str):
super().__init__(device, module)
self._add_feature(
Feature(
device,
"Alarm",
container=self,
attribute_getter="active",
icon="mdi:bell",
type=FeatureType.BinarySensor,
)
)
self._add_feature(
Feature(
device,
"Alarm source",
container=self,
attribute_getter="source",
icon="mdi:bell",
)
)
self._add_feature(
Feature(
device, "Alarm sound", container=self, attribute_getter="alarm_sound"
)
)
self._add_feature(
Feature(
device, "Alarm volume", container=self, attribute_getter="alarm_volume"
)
)
@property
def alarm_sound(self):
"""Return current alarm sound."""
return self.data["get_alarm_configure"]["type"]
@property
def alarm_sounds(self) -> List[str]:
"""Return list of available alarm sounds."""
return self.data["get_support_alarm_type_list"]["alarm_type_list"]
@property
def alarm_volume(self):
"""Return alarm volume."""
return self.data["get_alarm_configure"]["volume"]
@property
def active(self) -> bool:
"""Return true if alarm is active."""
return self._device.sys_info["in_alarm"]
@property
def source(self) -> Optional[str]:
"""Return the alarm cause."""
src = self._device.sys_info["in_alarm_source"]
return src if src else None
async def play(self):
"""Play alarm."""
return self.call("play_alarm")
async def stop(self):
"""Stop alarm."""
return self.call("stop_alarm")

View File

@ -0,0 +1,47 @@
"""Implementation of battery module."""
from typing import TYPE_CHECKING
from ...feature import Feature, FeatureType
from ..smartmodule import SmartModule
if TYPE_CHECKING:
from ..smartdevice import SmartDevice
class BatterySensor(SmartModule):
"""Implementation of battery module."""
REQUIRED_COMPONENT = "battery_detect"
QUERY_GETTER_NAME = "get_battery_detect_info"
def __init__(self, device: "SmartDevice", module: str):
super().__init__(device, module)
self._add_feature(
Feature(
device,
"Battery level",
container=self,
attribute_getter="battery",
icon="mdi:battery",
)
)
self._add_feature(
Feature(
device,
"Battery low",
container=self,
attribute_getter="battery_low",
icon="mdi:alert",
type=FeatureType.BinarySensor,
)
)
@property
def battery(self):
"""Return battery level."""
return self._device.sys_info["battery_percentage"]
@property
def battery_low(self):
"""Return True if battery is low."""
return self._device.sys_info["at_low_battery"]

View File

@ -0,0 +1,47 @@
"""Implementation of humidity module."""
from typing import TYPE_CHECKING
from ...feature import Feature, FeatureType
from ..smartmodule import SmartModule
if TYPE_CHECKING:
from ..smartdevice import SmartDevice
class HumiditySensor(SmartModule):
"""Implementation of humidity module."""
REQUIRED_COMPONENT = "humidity"
QUERY_GETTER_NAME = "get_comfort_humidity_config"
def __init__(self, device: "SmartDevice", module: str):
super().__init__(device, module)
self._add_feature(
Feature(
device,
"Humidity",
container=self,
attribute_getter="humidity",
icon="mdi:water-percent",
)
)
self._add_feature(
Feature(
device,
"Humidity warning",
container=self,
attribute_getter="humidity_warning",
type=FeatureType.BinarySensor,
icon="mdi:alert",
)
)
@property
def humidity(self):
"""Return current humidity in percentage."""
return self._device.sys_info["current_humidity"]
@property
def humidity_warning(self) -> bool:
"""Return true if humidity is outside of the wanted range."""
return self._device.sys_info["current_humidity_exception"] != 0

View File

@ -0,0 +1,31 @@
"""Implementation of report module."""
from typing import TYPE_CHECKING
from ...feature import Feature
from ..smartmodule import SmartModule
if TYPE_CHECKING:
from ..smartdevice import SmartDevice
class ReportModule(SmartModule):
"""Implementation of report module."""
REQUIRED_COMPONENT = "report_mode"
QUERY_GETTER_NAME = "get_report_mode"
def __init__(self, device: "SmartDevice", module: str):
super().__init__(device, module)
self._add_feature(
Feature(
device,
"Report interval",
container=self,
attribute_getter="report_interval",
)
)
@property
def report_interval(self):
"""Reporting interval of a sensor device."""
return self._device.sys_info["report_interval"]

View File

@ -0,0 +1,57 @@
"""Implementation of temperature module."""
from typing import TYPE_CHECKING, Literal
from ...feature import Feature, FeatureType
from ..smartmodule import SmartModule
if TYPE_CHECKING:
from ..smartdevice import SmartDevice
class TemperatureSensor(SmartModule):
"""Implementation of temperature module."""
REQUIRED_COMPONENT = "humidity"
QUERY_GETTER_NAME = "get_comfort_temp_config"
def __init__(self, device: "SmartDevice", module: str):
super().__init__(device, module)
self._add_feature(
Feature(
device,
"Temperature",
container=self,
attribute_getter="temperature",
icon="mdi:thermometer",
)
)
self._add_feature(
Feature(
device,
"Temperature warning",
container=self,
attribute_getter="temperature_warning",
type=FeatureType.BinarySensor,
icon="mdi:alert",
)
)
# TODO: use temperature_unit for feature creation
@property
def temperature(self):
"""Return current humidity in percentage."""
return self._device.sys_info["current_temp"]
@property
def temperature_warning(self) -> bool:
"""Return True if humidity is outside of the wanted range."""
return self._device.sys_info["current_temp_exception"] != 0
@property
def temperature_unit(self):
"""Return current temperature unit."""
return self._device.sys_info["temp_unit"]
async def set_temperature_unit(self, unit: Literal["celsius", "fahrenheit"]):
"""Set the device temperature unit."""
return await self.call("set_temperature_unit", {"temp_unit": unit})