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 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
|
"""Module for XKXN Exceptions."""
from __future__ import annotations
import logging
from typing import Any
class XKNXException(Exception):
"""Default XKNX Exception."""
def __eq__(self, other: object | None) -> bool:
"""Equal operator."""
return repr(self) == repr(other)
def __hash__(self) -> int:
"""Hash function."""
return hash(str(self))
def __repr__(self) -> str:
"""Representation of object."""
return str(self)
class CommunicationError(XKNXException):
"""Unable to communicate with KNX bus."""
def __init__(self, message: str, should_log: bool = True) -> None:
"""Instantiate exception."""
super().__init__(message)
self.should_log = should_log
class ConfirmationError(CommunicationError):
"""No confirmation received from KNX server for sent Telegram."""
class TunnellingAckError(CommunicationError):
"""No ACK or error status received from UDP KNX server for sent Telegram."""
class IPSecureError(CommunicationError):
"""Error in IP Secure communication."""
class CouldNotParseTelegram(XKNXException):
"""Could not parse telegram error."""
def __init__(self, description: str, **kwargs: Any) -> None:
"""Initialize CouldNotParseTelegram class."""
super().__init__()
self.description = description
self.parameter = kwargs
def _format_parameter(self) -> str:
return " ".join(
[f'{key}="{value}"' for (key, value) in sorted(self.parameter.items())]
)
def __str__(self) -> str:
"""Return object as readable string."""
return (
"<CouldNotParseTelegram "
f'description="{self.description}" {self._format_parameter()}/>'
)
class CouldNotParseKNXIP(XKNXException):
"""Exception class for wrong KNXIP data."""
def __init__(self, description: str = "") -> None:
"""Initialize CouldNotParseKNXIP class."""
super().__init__()
self.description = description
def __str__(self) -> str:
"""Return object as readable string."""
return f'<CouldNotParseKNXIP description="{self.description}" />'
class KNXSecureValidationError(CouldNotParseKNXIP):
"""Exception class for invalid KNX Secure data."""
def __str__(self) -> str:
"""Return object as readable string."""
return f'<KNXSecureValidationError description="{self.description}" />'
class IncompleteKNXIPFrame(CouldNotParseKNXIP):
"""
Exception class for incomplete KNXIP data.
Used for TCP connections to indicate to buffer the data until the complete frame is received.
UDP connections should just handle CouldNotParseKNXIP.
"""
def __str__(self) -> str:
"""Return object as readable string."""
return f'<IncompleteKNXIPFrame description="{self.description}" />'
class CouldNotParseCEMI(XKNXException):
"""Exception class for wrong CEMI data."""
def __init__(self, description: str = "") -> None:
"""Initialize CouldNotParseCEMI class."""
super().__init__()
self.description = description
def __str__(self) -> str:
"""Return object as readable string."""
return f'<CouldNotParseCEMI description="{self.description}" />'
class UnsupportedCEMIMessage(XKNXException):
"""Exception class for unsupported CEMI Messages."""
def __init__(self, description: str = "") -> None:
"""Initialize UnsupportedCEMIMessage class."""
super().__init__()
self.description = description
def __str__(self) -> str:
"""Return object as readable string."""
return f'<UnsupportedCEMIMessage description="{self.description}" />'
class ConversionError(XKNXException):
"""Exception class for error while converting one type to another."""
def __init__(self, description: str, **kwargs: Any) -> None:
"""Initialize ConversionError class."""
super().__init__()
self.description = description
self.parameter = kwargs
def _format_parameter(self) -> str:
return " ".join(
[f'{key}="{value}"' for (key, value) in sorted(self.parameter.items())]
)
def __str__(self) -> str:
"""Return object as readable string."""
return f'<ConversionError description="{self.description}" {self._format_parameter()}/>'
class CouldNotParseAddress(XKNXException):
"""Exception class for wrong address format."""
def __init__(self, address: Any = None, message: str = "") -> None:
"""Initialize CouldNotParseAddress class."""
super().__init__()
self.address = address
self.message = message
def __str__(self) -> str:
"""Return object as readable string."""
_msg = f'message="{self.message}" ' if self.message else ""
return f'<CouldNotParseAddress address="{self.address}" {_msg}/>'
class DeviceIllegalValue(XKNXException):
"""Exception class for setting a value of a device with an illegal value."""
def __init__(self, value: Any, description: str) -> None:
"""Initialize DeviceIllegalValue class."""
super().__init__()
self.value = value
self.description = description
def __str__(self) -> str:
"""Return object as readable string."""
return f'<DeviceIllegalValue description="{self.value}" value="{self.description}" />'
class DataSecureError(XKNXException):
"""Exception class for KNX Data Secure handling."""
def __init__(self, message: str, log_level: int = logging.WARNING) -> None:
"""Instantiate exception."""
super().__init__(message)
self.log_level = log_level
class InvalidSecureConfiguration(XKNXException):
"""Exception class used when the secure configuration is invalid."""
class ManagementConnectionError(XKNXException):
"""Exception class used when a management connection fails."""
class ManagementConnectionRefused(ManagementConnectionError):
"""Exception class used when a management connection request is refused."""
class ManagementConnectionTimeout(ManagementConnectionError):
"""Exception class used when a management connection timed out."""
|