File: exceptions.py

package info (click to toggle)
python-broadlink 0.19.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 232 kB
  • sloc: python: 2,140; makefile: 6
file content (152 lines) | stat: -rw-r--r-- 4,472 bytes parent folder | download
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)