mirror of
https://github.com/python-kasa/python-kasa.git
synced 2024-12-22 11:13:34 +00:00
Add smartcamera devices to supported docs (#1257)
The library now officially supports H200, C200 and TC65
This commit is contained in:
parent
b8f6651d9b
commit
5fe75cada9
@ -197,7 +197,8 @@ The following devices have been tested and confirmed as working. If your device
|
|||||||
- **Wall Switches**: S500D, S505, S505D
|
- **Wall Switches**: S500D, S505, S505D
|
||||||
- **Bulbs**: L510B, L510E, L530E, L630
|
- **Bulbs**: L510B, L510E, L530E, L630
|
||||||
- **Light Strips**: L900-10, L900-5, L920-5, L930-5
|
- **Light Strips**: L900-10, L900-5, L920-5, L930-5
|
||||||
- **Hubs**: H100
|
- **Cameras**: C210, TC65
|
||||||
|
- **Hubs**: H100, H200
|
||||||
- **Hub-Connected Devices<sup>\*\*\*</sup>**: S200B, S200D, T100, T110, T300, T310, T315
|
- **Hub-Connected Devices<sup>\*\*\*</sup>**: S200B, S200D, T100, T110, T300, T310, T315
|
||||||
|
|
||||||
<!--SUPPORTED_END-->
|
<!--SUPPORTED_END-->
|
||||||
|
11
SUPPORTED.md
11
SUPPORTED.md
@ -246,12 +246,23 @@ All Tapo devices require authentication.<br>Hub-Connected Devices may work acros
|
|||||||
- **L930-5**
|
- **L930-5**
|
||||||
- Hardware: 1.0 (US) / Firmware: 1.1.2
|
- Hardware: 1.0 (US) / Firmware: 1.1.2
|
||||||
|
|
||||||
|
### Cameras
|
||||||
|
|
||||||
|
- **C210**
|
||||||
|
- Hardware: 2.0 (EU) / Firmware: 1.4.2
|
||||||
|
- Hardware: 2.0 (EU) / Firmware: 1.4.3
|
||||||
|
- **TC65**
|
||||||
|
- Hardware: 1.0 / Firmware: 1.3.9
|
||||||
|
|
||||||
### Hubs
|
### Hubs
|
||||||
|
|
||||||
- **H100**
|
- **H100**
|
||||||
- Hardware: 1.0 (EU) / Firmware: 1.2.3
|
- Hardware: 1.0 (EU) / Firmware: 1.2.3
|
||||||
- Hardware: 1.0 (EU) / Firmware: 1.5.10
|
- Hardware: 1.0 (EU) / Firmware: 1.5.10
|
||||||
- Hardware: 1.0 (EU) / Firmware: 1.5.5
|
- Hardware: 1.0 (EU) / Firmware: 1.5.5
|
||||||
|
- **H200**
|
||||||
|
- Hardware: 1.0 (EU) / Firmware: 1.3.2
|
||||||
|
- Hardware: 1.0 (US) / Firmware: 1.3.6
|
||||||
|
|
||||||
### Hub-Connected Devices
|
### Hub-Connected Devices
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ from kasa.protocols.smartcameraprotocol import (
|
|||||||
)
|
)
|
||||||
from kasa.protocols.smartprotocol import SmartProtocol, _ChildProtocolWrapper
|
from kasa.protocols.smartprotocol import SmartProtocol, _ChildProtocolWrapper
|
||||||
from kasa.smart import SmartChildDevice
|
from kasa.smart import SmartChildDevice
|
||||||
|
from kasa.smartcamera import SmartCamera
|
||||||
|
|
||||||
Call = namedtuple("Call", "module method")
|
Call = namedtuple("Call", "module method")
|
||||||
FixtureResult = namedtuple("FixtureResult", "filename, folder, data")
|
FixtureResult = namedtuple("FixtureResult", "filename, folder, data")
|
||||||
@ -973,14 +974,12 @@ async def get_smart_fixtures(
|
|||||||
copy_folder = SMART_FOLDER
|
copy_folder = SMART_FOLDER
|
||||||
else:
|
else:
|
||||||
# smart camera protocol
|
# smart camera protocol
|
||||||
basic_info = final["getDeviceInfo"]["device_info"]["basic_info"]
|
model_info = SmartCamera._get_device_info(final, discovery_info)
|
||||||
hw_version = basic_info["hw_version"]
|
model = model_info.long_name
|
||||||
sw_version = basic_info["sw_version"]
|
hw_version = model_info.hardware_version
|
||||||
model = basic_info["device_model"]
|
sw_version = model_info.firmare_version
|
||||||
region = basic_info.get("region")
|
if model_info.region is not None:
|
||||||
sw_version = sw_version.split(" ", maxsplit=1)[0]
|
model = f"{model}({model_info.region})"
|
||||||
if region is not None:
|
|
||||||
model = f"{model}({region})"
|
|
||||||
copy_folder = SMARTCAMERA_FOLDER
|
copy_folder = SMARTCAMERA_FOLDER
|
||||||
|
|
||||||
save_filename = f"{model}_{hw_version}_{sw_version}.json"
|
save_filename = f"{model}_{hw_version}_{sw_version}.json"
|
||||||
|
@ -10,7 +10,8 @@ from typing import NamedTuple
|
|||||||
|
|
||||||
from kasa.device_factory import _get_device_type_from_sys_info
|
from kasa.device_factory import _get_device_type_from_sys_info
|
||||||
from kasa.device_type import DeviceType
|
from kasa.device_type import DeviceType
|
||||||
from kasa.smart.smartdevice import SmartDevice
|
from kasa.smart import SmartDevice
|
||||||
|
from kasa.smartcamera import SmartCamera
|
||||||
|
|
||||||
|
|
||||||
class SupportedVersion(NamedTuple):
|
class SupportedVersion(NamedTuple):
|
||||||
@ -32,6 +33,7 @@ DEVICE_TYPE_TO_PRODUCT_GROUP = {
|
|||||||
DeviceType.Fan: "Wall Switches",
|
DeviceType.Fan: "Wall Switches",
|
||||||
DeviceType.Bulb: "Bulbs",
|
DeviceType.Bulb: "Bulbs",
|
||||||
DeviceType.LightStrip: "Light Strips",
|
DeviceType.LightStrip: "Light Strips",
|
||||||
|
DeviceType.Camera: "Cameras",
|
||||||
DeviceType.Hub: "Hubs",
|
DeviceType.Hub: "Hubs",
|
||||||
DeviceType.Sensor: "Hub-Connected Devices",
|
DeviceType.Sensor: "Hub-Connected Devices",
|
||||||
DeviceType.Thermostat: "Hub-Connected Devices",
|
DeviceType.Thermostat: "Hub-Connected Devices",
|
||||||
@ -43,6 +45,7 @@ README_FILENAME = "README.md"
|
|||||||
|
|
||||||
IOT_FOLDER = "tests/fixtures/"
|
IOT_FOLDER = "tests/fixtures/"
|
||||||
SMART_FOLDER = "tests/fixtures/smart/"
|
SMART_FOLDER = "tests/fixtures/smart/"
|
||||||
|
SMARTCAMERA_FOLDER = "tests/fixtures/smartcamera/"
|
||||||
|
|
||||||
|
|
||||||
def generate_supported(args):
|
def generate_supported(args):
|
||||||
@ -58,6 +61,7 @@ def generate_supported(args):
|
|||||||
|
|
||||||
_get_iot_supported(supported)
|
_get_iot_supported(supported)
|
||||||
_get_smart_supported(supported)
|
_get_smart_supported(supported)
|
||||||
|
_get_smartcamera_supported(supported)
|
||||||
|
|
||||||
readme_updated = _update_supported_file(
|
readme_updated = _update_supported_file(
|
||||||
README_FILENAME, _supported_summary(supported), print_diffs
|
README_FILENAME, _supported_summary(supported), print_diffs
|
||||||
@ -234,6 +238,29 @@ def _get_smart_supported(supported):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_smartcamera_supported(supported):
|
||||||
|
for file in Path(SMARTCAMERA_FOLDER).glob("**/*.json"):
|
||||||
|
with file.open() as f:
|
||||||
|
fixture_data = json.load(f)
|
||||||
|
|
||||||
|
model_info = SmartCamera._get_device_info(
|
||||||
|
fixture_data, fixture_data.get("discovery_result")
|
||||||
|
)
|
||||||
|
|
||||||
|
supported_type = DEVICE_TYPE_TO_PRODUCT_GROUP[model_info.device_type]
|
||||||
|
|
||||||
|
stype = supported[model_info.brand].setdefault(supported_type, {})
|
||||||
|
smodel = stype.setdefault(model_info.long_name, [])
|
||||||
|
smodel.append(
|
||||||
|
SupportedVersion(
|
||||||
|
region=model_info.region,
|
||||||
|
hw=model_info.hardware_version,
|
||||||
|
fw=model_info.firmare_version,
|
||||||
|
auth=model_info.requires_auth,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _get_iot_supported(supported):
|
def _get_iot_supported(supported):
|
||||||
for file in Path(IOT_FOLDER).glob("*.json"):
|
for file in Path(IOT_FOLDER).glob("*.json"):
|
||||||
with file.open() as f:
|
with file.open() as f:
|
||||||
|
@ -152,6 +152,22 @@ class WifiNetwork:
|
|||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class _DeviceInfo:
|
||||||
|
"""Device Model Information."""
|
||||||
|
|
||||||
|
short_name: str
|
||||||
|
long_name: str
|
||||||
|
brand: str
|
||||||
|
device_family: str
|
||||||
|
device_type: DeviceType
|
||||||
|
hardware_version: str
|
||||||
|
firmare_version: str
|
||||||
|
firmware_build: str
|
||||||
|
requires_auth: bool
|
||||||
|
region: str | None
|
||||||
|
|
||||||
|
|
||||||
class Device(ABC):
|
class Device(ABC):
|
||||||
"""Common device interface.
|
"""Common device interface.
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ from __future__ import annotations
|
|||||||
import logging
|
import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
from ..device import _DeviceInfo
|
||||||
from ..device_type import DeviceType
|
from ..device_type import DeviceType
|
||||||
from ..module import Module
|
from ..module import Module
|
||||||
from ..protocols.smartcameraprotocol import _ChildCameraProtocolWrapper
|
from ..protocols.smartcameraprotocol import _ChildCameraProtocolWrapper
|
||||||
@ -29,6 +30,30 @@ class SmartCamera(SmartDevice):
|
|||||||
return DeviceType.Hub
|
return DeviceType.Hub
|
||||||
return DeviceType.Camera
|
return DeviceType.Camera
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _get_device_info(
|
||||||
|
info: dict[str, Any], discovery_info: dict[str, Any] | None
|
||||||
|
) -> _DeviceInfo:
|
||||||
|
"""Get model information for a device."""
|
||||||
|
basic_info = info["getDeviceInfo"]["device_info"]["basic_info"]
|
||||||
|
short_name = basic_info["device_model"]
|
||||||
|
long_name = discovery_info["device_model"] if discovery_info else short_name
|
||||||
|
device_type = SmartCamera._get_device_type_from_sysinfo(basic_info)
|
||||||
|
fw_version_full = basic_info["sw_version"]
|
||||||
|
firmare_version, firmware_build = fw_version_full.split(" ", maxsplit=1)
|
||||||
|
return _DeviceInfo(
|
||||||
|
short_name=basic_info["device_model"],
|
||||||
|
long_name=long_name,
|
||||||
|
brand="tapo",
|
||||||
|
device_family=basic_info["device_type"],
|
||||||
|
device_type=device_type,
|
||||||
|
hardware_version=basic_info["hw_version"],
|
||||||
|
firmare_version=firmare_version,
|
||||||
|
firmware_build=firmware_build,
|
||||||
|
requires_auth=True,
|
||||||
|
region=basic_info.get("region"),
|
||||||
|
)
|
||||||
|
|
||||||
def _update_internal_info(self, info_resp: dict) -> None:
|
def _update_internal_info(self, info_resp: dict) -> None:
|
||||||
"""Update the internal device info."""
|
"""Update the internal device info."""
|
||||||
info = self._try_get_response(info_resp, "getDeviceInfo")
|
info = self._try_get_response(info_resp, "getDeviceInfo")
|
||||||
|
Loading…
Reference in New Issue
Block a user