mirror of
https://github.com/python-kasa/python-kasa.git
synced 2026-11-06 11:57:26 +00:00
Some checks failed
CI / Perform Lint Checks (3.15) (push) Has been cancelled
CodeQL Checks / Analyze (python) (push) Has been cancelled
CI / Python 3.11 on macos-latest (push) Has been cancelled
CI / Python 3.12 on macos-latest (push) Has been cancelled
CI / Python 3.13 on macos-latest (push) Has been cancelled
CI / Python 3.14 on macos-latest (push) Has been cancelled
CI / Python 3.15 on macos-latest (push) Has been cancelled
CI / Python 3.11 on ubuntu-latest (push) Has been cancelled
CI / Python 3.12 on ubuntu-latest (push) Has been cancelled
CI / Python 3.13 on ubuntu-latest (push) Has been cancelled
CI / Python 3.14 on ubuntu-latest (push) Has been cancelled
CI / Python 3.15 on ubuntu-latest (push) Has been cancelled
CI / Python 3.11 on windows-latest (push) Has been cancelled
CI / Python 3.12 on windows-latest (push) Has been cancelled
CI / Python 3.13 on windows-latest (push) Has been cancelled
CI / Python 3.14 on windows-latest (push) Has been cancelled
CI / Python 3.15 on windows-latest (push) Has been cancelled
Stale / stale (push) Has been cancelled
Hubs keep reporting for children they have lost contact with, so callers see stale values as if they were live. Trying to write to such devices fail after timeouts with a generic error. This PR exposes the offline/online information as reported by the hub, and refuses writes to unreachable child devices without waiting for device errors. In details: - Add new API: `Device.is_available`; hub children report unavailable when the hub marks them offline or no longer lists them. - New feature `available` for child devices to make it visible to the CLI. - Refuse writes to unavailable children with the new `DeviceUnavailableError` instead of waiting for the hub to time out.
160 lines
4.8 KiB
Python
Executable File
160 lines
4.8 KiB
Python
Executable File
"""Python interface for TP-Link's smart home devices.
|
|
|
|
All common, shared functionalities are available through `Device` class::
|
|
|
|
>>> from kasa import Discover
|
|
>>> x = await Discover.discover_single("192.168.1.1")
|
|
>>> print(x.model)
|
|
|
|
For device type specific actions `modules` and `features` should be used instead.
|
|
|
|
Module-specific errors are raised as `KasaException` and are expected
|
|
to be handled by the user of the library.
|
|
"""
|
|
|
|
from importlib.metadata import version
|
|
from typing import TYPE_CHECKING, Any
|
|
from warnings import warn
|
|
|
|
from kasa.credentials import Credentials
|
|
from kasa.device import Device
|
|
from kasa.device_type import DeviceType
|
|
from kasa.deviceconfig import (
|
|
DeviceConfig,
|
|
DeviceConnectionParameters,
|
|
DeviceEncryptionType,
|
|
DeviceFamily,
|
|
)
|
|
from kasa.discover import Discover
|
|
from kasa.emeterstatus import EmeterStatus
|
|
from kasa.exceptions import (
|
|
AuthenticationError,
|
|
DeviceError,
|
|
DeviceUnavailableError,
|
|
KasaException,
|
|
TimeoutError,
|
|
UnsupportedDeviceError,
|
|
)
|
|
from kasa.feature import Feature
|
|
from kasa.interfaces.light import HSV, ColorTempRange, Light, LightState
|
|
from kasa.interfaces.thermostat import Thermostat, ThermostatState
|
|
from kasa.module import Module
|
|
from kasa.protocols import BaseProtocol, IotProtocol, SmartCamProtocol, SmartProtocol
|
|
from kasa.protocols.iotprotocol import _deprecated_TPLinkSmartHomeProtocol # noqa: F401
|
|
from kasa.smartcam.modules.camera import StreamResolution
|
|
from kasa.transports import BaseTransport
|
|
|
|
__version__ = version("python-kasa")
|
|
|
|
|
|
__all__ = [
|
|
"Discover",
|
|
"BaseProtocol",
|
|
"BaseTransport",
|
|
"IotProtocol",
|
|
"SmartProtocol",
|
|
"SmartCamProtocol",
|
|
"LightState",
|
|
"TurnOnBehaviors",
|
|
"TurnOnBehavior",
|
|
"DeviceType",
|
|
"Feature",
|
|
"EmeterStatus",
|
|
"Device",
|
|
"Light",
|
|
"ColorTempRange",
|
|
"HSV",
|
|
"Plug",
|
|
"Module",
|
|
"KasaException",
|
|
"AuthenticationError",
|
|
"DeviceError",
|
|
"DeviceUnavailableError",
|
|
"UnsupportedDeviceError",
|
|
"TimeoutError",
|
|
"Credentials",
|
|
"DeviceConfig",
|
|
"DeviceConnectionParameters",
|
|
"DeviceEncryptionType",
|
|
"DeviceFamily",
|
|
"ThermostatState",
|
|
"Thermostat",
|
|
"StreamResolution",
|
|
]
|
|
|
|
from . import iot
|
|
from .iot.modules.lightpreset import IotLightPreset
|
|
|
|
deprecated_names = ["TPLinkSmartHomeProtocol"]
|
|
deprecated_smart_devices = {
|
|
"SmartDevice": iot.IotDevice,
|
|
"SmartPlug": iot.IotPlug,
|
|
"SmartBulb": iot.IotBulb,
|
|
"SmartLightStrip": iot.IotLightStrip,
|
|
"SmartStrip": iot.IotStrip,
|
|
"SmartDimmer": iot.IotDimmer,
|
|
"SmartBulbPreset": IotLightPreset,
|
|
}
|
|
deprecated_classes = {
|
|
"SmartDeviceException": KasaException,
|
|
"UnsupportedDeviceException": UnsupportedDeviceError,
|
|
"AuthenticationException": AuthenticationError,
|
|
"TimeoutException": TimeoutError,
|
|
"ConnectionType": DeviceConnectionParameters,
|
|
"EncryptType": DeviceEncryptionType,
|
|
"DeviceFamilyType": DeviceFamily,
|
|
}
|
|
|
|
if not TYPE_CHECKING:
|
|
|
|
def __getattr__(name: str) -> Any:
|
|
if name in deprecated_names:
|
|
warn(f"{name} is deprecated", DeprecationWarning, stacklevel=2)
|
|
return globals()[f"_deprecated_{name}"]
|
|
if name in deprecated_smart_devices:
|
|
new_class = deprecated_smart_devices[name]
|
|
package_name = ".".join(new_class.__module__.split(".")[:-1])
|
|
warn(
|
|
f"{name} is deprecated, use {new_class.__name__} from "
|
|
+ f"package {package_name} instead or use Discover.discover_single()"
|
|
+ " and Device.connect() to support new protocols",
|
|
DeprecationWarning,
|
|
stacklevel=2,
|
|
)
|
|
return new_class
|
|
if name in deprecated_classes:
|
|
new_class = deprecated_classes[name] # type: ignore[assignment]
|
|
msg = f"{name} is deprecated, use {new_class.__name__} instead"
|
|
warn(msg, DeprecationWarning, stacklevel=2)
|
|
return new_class
|
|
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
|
|
|
|
if TYPE_CHECKING:
|
|
SmartDevice = Device
|
|
SmartBulb = iot.IotBulb
|
|
SmartPlug = iot.IotPlug
|
|
SmartLightStrip = iot.IotLightStrip
|
|
SmartStrip = iot.IotStrip
|
|
SmartDimmer = iot.IotDimmer
|
|
SmartBulbPreset = IotLightPreset
|
|
|
|
SmartDeviceException = KasaException
|
|
UnsupportedDeviceException = UnsupportedDeviceError
|
|
AuthenticationException = AuthenticationError
|
|
TimeoutException = TimeoutError
|
|
ConnectionType = DeviceConnectionParameters
|
|
EncryptType = DeviceEncryptionType
|
|
DeviceFamilyType = DeviceFamily
|
|
|
|
# Instanstiate all classes so the type checkers catch abstract issues
|
|
from . import smart
|
|
|
|
smart.SmartDevice("127.0.0.1")
|
|
iot.IotDevice("127.0.0.1")
|
|
iot.IotPlug("127.0.0.1")
|
|
iot.IotBulb("127.0.0.1")
|
|
iot.IotLightStrip("127.0.0.1")
|
|
iot.IotStrip("127.0.0.1")
|
|
iot.IotDimmer("127.0.0.1")
|