mirror of
https://github.com/python-kasa/python-kasa.git
synced 2024-12-23 03:33:35 +00:00
7fd5c213e6
Addresses stability issues on older hw device versions - Handles module timeout errors better by querying modules individually on errors and disabling problematic modules like Firmware that go out to the internet to get updates. - Addresses an issue with the Led module on P100 hardware version 1.0 which appears to have a memory leak and will cause the device to crash after approximately 500 calls. - Delays updates of modules that do not have regular changes like LightPreset and LightEffect and enables them to be updated on the next update cycle only if required values have changed.
149 lines
4.1 KiB
Python
149 lines
4.1 KiB
Python
"""python-kasa exceptions."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from asyncio import TimeoutError as _asyncioTimeoutError
|
|
from enum import IntEnum
|
|
from functools import cache
|
|
from typing import Any
|
|
|
|
|
|
class KasaException(Exception):
|
|
"""Base exception for library errors."""
|
|
|
|
|
|
class TimeoutError(KasaException, _asyncioTimeoutError):
|
|
"""Timeout exception for device errors."""
|
|
|
|
def __repr__(self):
|
|
return KasaException.__repr__(self)
|
|
|
|
def __str__(self):
|
|
return KasaException.__str__(self)
|
|
|
|
|
|
class _ConnectionError(KasaException):
|
|
"""Connection exception for device errors."""
|
|
|
|
|
|
class UnsupportedDeviceError(KasaException):
|
|
"""Exception for trying to connect to unsupported devices."""
|
|
|
|
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
|
self.discovery_result = kwargs.get("discovery_result")
|
|
super().__init__(*args)
|
|
|
|
|
|
class DeviceError(KasaException):
|
|
"""Base exception for device errors."""
|
|
|
|
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
|
self.error_code: SmartErrorCode | None = kwargs.get("error_code", None)
|
|
super().__init__(*args)
|
|
|
|
def __repr__(self):
|
|
err_code = self.error_code.__repr__() if self.error_code else ""
|
|
return f"{self.__class__.__name__}({err_code})"
|
|
|
|
def __str__(self):
|
|
err_code = f" (error_code={self.error_code.name})" if self.error_code else ""
|
|
return super().__str__() + err_code
|
|
|
|
|
|
class AuthenticationError(DeviceError):
|
|
"""Base exception for device authentication errors."""
|
|
|
|
|
|
class _RetryableError(DeviceError):
|
|
"""Retryable exception for device errors."""
|
|
|
|
|
|
class SmartErrorCode(IntEnum):
|
|
"""Enum for SMART Error Codes."""
|
|
|
|
def __str__(self):
|
|
return f"{self.name}({self.value})"
|
|
|
|
@staticmethod
|
|
@cache
|
|
def from_int(value: int) -> SmartErrorCode:
|
|
"""Convert an integer to a SmartErrorCode."""
|
|
return SmartErrorCode(value)
|
|
|
|
SUCCESS = 0
|
|
|
|
# Transport Errors
|
|
SESSION_TIMEOUT_ERROR = 9999
|
|
MULTI_REQUEST_FAILED_ERROR = 1200
|
|
HTTP_TRANSPORT_FAILED_ERROR = 1112
|
|
LOGIN_FAILED_ERROR = 1111
|
|
HAND_SHAKE_FAILED_ERROR = 1100
|
|
#: Real description unknown, seen after an encryption-changing fw upgrade
|
|
TRANSPORT_UNKNOWN_CREDENTIALS_ERROR = 1003
|
|
TRANSPORT_NOT_AVAILABLE_ERROR = 1002
|
|
CMD_COMMAND_CANCEL_ERROR = 1001
|
|
NULL_TRANSPORT_ERROR = 1000
|
|
|
|
# Common Method Errors
|
|
COMMON_FAILED_ERROR = -1
|
|
UNSPECIFIC_ERROR = -1001
|
|
UNKNOWN_METHOD_ERROR = -1002
|
|
JSON_DECODE_FAIL_ERROR = -1003
|
|
JSON_ENCODE_FAIL_ERROR = -1004
|
|
AES_DECODE_FAIL_ERROR = -1005
|
|
REQUEST_LEN_ERROR_ERROR = -1006
|
|
CLOUD_FAILED_ERROR = -1007
|
|
PARAMS_ERROR = -1008
|
|
INVALID_PUBLIC_KEY_ERROR = -1010 # Unverified
|
|
SESSION_PARAM_ERROR = -1101
|
|
|
|
# Method Specific Errors
|
|
QUICK_SETUP_ERROR = -1201
|
|
DEVICE_ERROR = -1301
|
|
DEVICE_NEXT_EVENT_ERROR = -1302
|
|
FIRMWARE_ERROR = -1401
|
|
FIRMWARE_VER_ERROR_ERROR = -1402
|
|
LOGIN_ERROR = -1501
|
|
TIME_ERROR = -1601
|
|
TIME_SYS_ERROR = -1602
|
|
TIME_SAVE_ERROR = -1603
|
|
WIRELESS_ERROR = -1701
|
|
WIRELESS_UNSUPPORTED_ERROR = -1702
|
|
SCHEDULE_ERROR = -1801
|
|
SCHEDULE_FULL_ERROR = -1802
|
|
SCHEDULE_CONFLICT_ERROR = -1803
|
|
SCHEDULE_SAVE_ERROR = -1804
|
|
SCHEDULE_INDEX_ERROR = -1805
|
|
COUNTDOWN_ERROR = -1901
|
|
COUNTDOWN_CONFLICT_ERROR = -1902
|
|
COUNTDOWN_SAVE_ERROR = -1903
|
|
ANTITHEFT_ERROR = -2001
|
|
ANTITHEFT_CONFLICT_ERROR = -2002
|
|
ANTITHEFT_SAVE_ERROR = -2003
|
|
ACCOUNT_ERROR = -2101
|
|
STAT_ERROR = -2201
|
|
STAT_SAVE_ERROR = -2202
|
|
DST_ERROR = -2301
|
|
DST_SAVE_ERROR = -2302
|
|
|
|
# Library internal for unknown error codes
|
|
INTERNAL_UNKNOWN_ERROR = -100_000
|
|
# Library internal for query errors
|
|
INTERNAL_QUERY_ERROR = -100_001
|
|
|
|
|
|
SMART_RETRYABLE_ERRORS = [
|
|
SmartErrorCode.TRANSPORT_NOT_AVAILABLE_ERROR,
|
|
SmartErrorCode.HTTP_TRANSPORT_FAILED_ERROR,
|
|
SmartErrorCode.UNSPECIFIC_ERROR,
|
|
SmartErrorCode.SESSION_TIMEOUT_ERROR,
|
|
]
|
|
|
|
SMART_AUTHENTICATION_ERRORS = [
|
|
SmartErrorCode.LOGIN_ERROR,
|
|
SmartErrorCode.LOGIN_FAILED_ERROR,
|
|
SmartErrorCode.AES_DECODE_FAIL_ERROR,
|
|
SmartErrorCode.HAND_SHAKE_FAILED_ERROR,
|
|
SmartErrorCode.TRANSPORT_UNKNOWN_CREDENTIALS_ERROR,
|
|
]
|