1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
|
"""Exceptions for Broadlink devices."""
import collections
import struct
class BroadlinkException(Exception):
"""Base class common to all Broadlink exceptions."""
def __init__(self, *args, **kwargs):
"""Initialize the exception."""
super().__init__(*args, **kwargs)
if len(args) >= 2:
self.errno = args[0]
self.strerror = ": ".join(str(arg) for arg in args[1:])
elif len(args) == 1:
self.errno = None
self.strerror = str(args[0])
else:
self.errno = None
self.strerror = ""
def __str__(self):
"""Return str(self)."""
if self.errno is not None:
return "[Errno %s] %s" % (self.errno, self.strerror)
return self.strerror
def __eq__(self, other):
"""Return self==value."""
# pylint: disable=unidiomatic-typecheck
return type(self) == type(other) and self.args == other.args
def __hash__(self):
"""Return hash(self)."""
return hash((type(self), self.args))
class MultipleErrors(BroadlinkException):
"""Multiple errors."""
def __init__(self, *args, **kwargs):
"""Initialize the exception."""
errors = args[0][:] if args else []
counter = collections.Counter(errors)
strerror = "Multiple errors occurred: %s" % counter
super().__init__(strerror, **kwargs)
self.errors = errors
def __repr__(self):
"""Return repr(self)."""
return "MultipleErrors(%r)" % self.errors
def __str__(self):
"""Return str(self)."""
return self.strerror
class AuthenticationError(BroadlinkException):
"""Authentication error."""
class AuthorizationError(BroadlinkException):
"""Authorization error."""
class CommandNotSupportedError(BroadlinkException):
"""Command not supported error."""
class ConnectionClosedError(BroadlinkException):
"""Connection closed error."""
class StructureAbnormalError(BroadlinkException):
"""Structure abnormal error."""
class DeviceOfflineError(BroadlinkException):
"""Device offline error."""
class ReadError(BroadlinkException):
"""Read error."""
class SendError(BroadlinkException):
"""Send error."""
class SSIDNotFoundError(BroadlinkException):
"""SSID not found error."""
class StorageError(BroadlinkException):
"""Storage error."""
class WriteError(BroadlinkException):
"""Write error."""
class NetworkTimeoutError(BroadlinkException):
"""Network timeout error."""
class DataValidationError(BroadlinkException):
"""Data validation error."""
class UnknownError(BroadlinkException):
"""Unknown error."""
BROADLINK_EXCEPTIONS = {
# Firmware-related errors are generated by the device.
-1: (AuthenticationError, "Authentication failed"),
-2: (ConnectionClosedError, "You have been logged out"),
-3: (DeviceOfflineError, "The device is offline"),
-4: (CommandNotSupportedError, "Command not supported"),
-5: (StorageError, "The device storage is full"),
-6: (StructureAbnormalError, "Structure is abnormal"),
-7: (AuthorizationError, "Control key is expired"),
-8: (SendError, "Send error"),
-9: (WriteError, "Write error"),
-10: (ReadError, "Read error"),
-11: (SSIDNotFoundError, "SSID could not be found in AP configuration"),
# SDK related errors are generated by this module.
-2040: (DataValidationError, "Device information is not intact"),
-4000: (NetworkTimeoutError, "Network timeout"),
-4007: (DataValidationError, "Received data packet length error"),
-4008: (DataValidationError, "Received data packet check error"),
-4009: (DataValidationError, "Received data packet information type error"),
-4010: (DataValidationError, "Received encrypted data packet length error"),
-4011: (DataValidationError, "Received encrypted data packet check error"),
-4012: (AuthorizationError, "Device control ID error"),
}
def exception(err_code: int) -> BroadlinkException:
"""Return exception corresponding to an error code."""
try:
exc, msg = BROADLINK_EXCEPTIONS[err_code]
return exc(err_code, msg)
except KeyError:
return UnknownError(err_code, "Unknown error")
def check_error(error: bytes) -> None:
"""Raise exception if an error occurred."""
error_code = struct.unpack("h", error)[0]
if error_code:
raise exception(error_code)
|