mirror of
https://github.com/python-kasa/python-kasa.git
synced 2025-10-10 01:18:03 +00:00
Add support for doorbells and chimes (#1435)
Add support for `smart` chimes and `smartcam` doorbells that are not hub child devices. Co-authored-by: Steven B <51370195+sdb9696@users.noreply.github.com>
This commit is contained in:
@@ -159,6 +159,7 @@ def get_device_class_from_family(
|
||||
"SMART.KASAHUB": SmartDevice,
|
||||
"SMART.KASASWITCH": SmartDevice,
|
||||
"SMART.IPCAMERA.HTTPS": SmartCamDevice,
|
||||
"SMART.TAPODOORBELL.HTTPS": SmartCamDevice,
|
||||
"SMART.TAPOROBOVAC.HTTPS": SmartDevice,
|
||||
"IOT.SMARTPLUGSWITCH": IotPlug,
|
||||
"IOT.SMARTBULB": IotBulb,
|
||||
@@ -194,7 +195,10 @@ def get_protocol(config: DeviceConfig, *, strict: bool = False) -> BaseProtocol
|
||||
protocol_name = ctype.device_family.value.split(".")[0]
|
||||
_LOGGER.debug("Finding protocol for %s", ctype.device_family)
|
||||
|
||||
if ctype.device_family is DeviceFamily.SmartIpCamera:
|
||||
if ctype.device_family in {
|
||||
DeviceFamily.SmartIpCamera,
|
||||
DeviceFamily.SmartTapoDoorbell,
|
||||
}:
|
||||
if strict and ctype.encryption_type is not DeviceEncryptionType.Aes:
|
||||
return None
|
||||
return SmartCamProtocol(transport=SslAesTransport(config=config))
|
||||
|
@@ -22,6 +22,8 @@ class DeviceType(Enum):
|
||||
Fan = "fan"
|
||||
Thermostat = "thermostat"
|
||||
Vacuum = "vacuum"
|
||||
Chime = "chime"
|
||||
Doorbell = "doorbell"
|
||||
Unknown = "unknown"
|
||||
|
||||
@staticmethod
|
||||
|
@@ -79,6 +79,8 @@ class DeviceFamily(Enum):
|
||||
SmartKasaHub = "SMART.KASAHUB"
|
||||
SmartIpCamera = "SMART.IPCAMERA"
|
||||
SmartTapoRobovac = "SMART.TAPOROBOVAC"
|
||||
SmartTapoChime = "SMART.TAPOCHIME"
|
||||
SmartTapoDoorbell = "SMART.TAPODOORBELL"
|
||||
|
||||
|
||||
class _DeviceConfigBaseMixin(DataClassJSONMixin):
|
||||
|
@@ -885,6 +885,8 @@ class SmartDevice(Device):
|
||||
return DeviceType.Thermostat
|
||||
if "ROBOVAC" in device_type:
|
||||
return DeviceType.Vacuum
|
||||
if "TAPOCHIME" in device_type:
|
||||
return DeviceType.Chime
|
||||
_LOGGER.warning("Unknown device type, falling back to plug")
|
||||
return DeviceType.Plug
|
||||
|
||||
|
@@ -9,7 +9,6 @@ from typing import Annotated
|
||||
from urllib.parse import quote_plus
|
||||
|
||||
from ...credentials import Credentials
|
||||
from ...device_type import DeviceType
|
||||
from ...feature import Feature
|
||||
from ...json import loads as json_loads
|
||||
from ...module import FeatureAttribute, Module
|
||||
@@ -31,6 +30,8 @@ class StreamResolution(StrEnum):
|
||||
class Camera(SmartCamModule):
|
||||
"""Implementation of device module."""
|
||||
|
||||
REQUIRED_COMPONENT = "video"
|
||||
|
||||
def _initialize_features(self) -> None:
|
||||
"""Initialize features after the initial update."""
|
||||
if Module.LensMask in self._device.modules:
|
||||
@@ -126,7 +127,3 @@ class Camera(SmartCamModule):
|
||||
return None
|
||||
|
||||
return f"http://{self._device.host}:{ONVIF_PORT}/onvif/device_service"
|
||||
|
||||
async def _check_supported(self) -> bool:
|
||||
"""Additional check to see if the module is supported by the device."""
|
||||
return self._device.device_type is DeviceType.Camera
|
||||
|
@@ -85,6 +85,13 @@ class SmartCamChild(SmartChildDevice, SmartCamDevice):
|
||||
# devices
|
||||
self._info = self._map_child_info_from_parent(info)
|
||||
|
||||
@property
|
||||
def device_type(self) -> DeviceType:
|
||||
"""Return the device type."""
|
||||
if self._device_type == DeviceType.Unknown and self._info:
|
||||
self._device_type = self._get_device_type_from_sysinfo(self._info)
|
||||
return self._device_type
|
||||
|
||||
@staticmethod
|
||||
def _get_device_info(
|
||||
info: dict[str, Any], discovery_info: dict[str, Any] | None
|
||||
|
@@ -26,12 +26,15 @@ class SmartCamDevice(SmartDevice):
|
||||
@staticmethod
|
||||
def _get_device_type_from_sysinfo(sysinfo: dict[str, Any]) -> DeviceType:
|
||||
"""Find type to be displayed as a supported device category."""
|
||||
if (
|
||||
sysinfo
|
||||
and (device_type := sysinfo.get("device_type"))
|
||||
and device_type.endswith("HUB")
|
||||
):
|
||||
if not (device_type := sysinfo.get("device_type")):
|
||||
return DeviceType.Unknown
|
||||
|
||||
if device_type.endswith("HUB"):
|
||||
return DeviceType.Hub
|
||||
|
||||
if "DOORBELL" in device_type:
|
||||
return DeviceType.Doorbell
|
||||
|
||||
return DeviceType.Camera
|
||||
|
||||
@staticmethod
|
||||
@@ -165,11 +168,6 @@ class SmartCamDevice(SmartDevice):
|
||||
if (
|
||||
mod.REQUIRED_COMPONENT
|
||||
and mod.REQUIRED_COMPONENT not in self._components
|
||||
# Always add Camera module to cameras
|
||||
and (
|
||||
mod._module_name() != Module.Camera
|
||||
or self._device_type is not DeviceType.Camera
|
||||
)
|
||||
):
|
||||
continue
|
||||
module = mod(self, mod._module_name())
|
||||
@@ -258,7 +256,7 @@ class SmartCamDevice(SmartDevice):
|
||||
@property
|
||||
def device_type(self) -> DeviceType:
|
||||
"""Return the device type."""
|
||||
if self._device_type == DeviceType.Unknown:
|
||||
if self._device_type == DeviceType.Unknown and self._info:
|
||||
self._device_type = self._get_device_type_from_sysinfo(self._info)
|
||||
return self._device_type
|
||||
|
||||
|
Reference in New Issue
Block a user