""" Custom exceptions for laser control module. Provides a hierarchy of exceptions for different error conditions that may occur during laser control operations. """ class LaserControlError(Exception): """Base exception for all laser control errors.""" pass class ValidationError(LaserControlError): """Base exception for validation errors.""" pass class TemperatureOutOfRangeError(ValidationError): """Exception raised when temperature is outside valid range.""" def __init__(self, param_name: str, value: float, min_val: float, max_val: float): self.param_name = param_name self.value = value self.min_val = min_val self.max_val = max_val super().__init__( f"{param_name}: Temperature {value}°C is out of range " f"[{min_val}°C - {max_val}°C]" ) class CurrentOutOfRangeError(ValidationError): """Exception raised when current is outside valid range.""" def __init__(self, param_name: str, value: float, min_val: float, max_val: float): self.param_name = param_name self.value = value self.min_val = min_val self.max_val = max_val super().__init__( f"{param_name}: Current {value}mA is out of range " f"[{min_val}mA - {max_val}mA]" ) class InvalidParameterError(ValidationError): """Exception raised for invalid parameter types or values.""" def __init__(self, param_name: str, message: str): self.param_name = param_name super().__init__(f"{param_name}: {message}") class CommunicationError(LaserControlError): """Base exception for communication errors.""" pass class PortNotFoundError(CommunicationError): """Exception raised when serial port cannot be found.""" def __init__(self, port: str = None): if port: message = f"Serial port '{port}' not found" else: message = "No suitable serial port found for device connection" super().__init__(message) class DeviceNotRespondingError(CommunicationError): """Exception raised when device doesn't respond to commands.""" def __init__(self, timeout: float = None): if timeout: message = f"Device did not respond within {timeout} seconds" else: message = "Device is not responding to commands" super().__init__(message) class CRCError(CommunicationError): """Exception raised when CRC check fails.""" def __init__(self, expected: int = None, received: int = None): if expected is not None and received is not None: message = f"CRC check failed. Expected: 0x{expected:04X}, Received: 0x{received:04X}" else: message = "CRC check failed on received data" super().__init__(message) class ProtocolError(CommunicationError): """Exception raised for protocol-level errors.""" def __init__(self, message: str): super().__init__(f"Protocol error: {message}") class DeviceError(LaserControlError): """Base exception for device-level errors.""" pass class DeviceOverheatingError(DeviceError): """Exception raised when device reports overheating.""" def __init__(self, laser_id: int = None, temperature: float = None): if laser_id and temperature: message = f"Laser {laser_id} overheating: {temperature}°C" else: message = "Device overheating detected" super().__init__(message) class PowerSupplyError(DeviceError): """Exception raised when power supply issues are detected.""" def __init__(self, rail: str = None, voltage: float = None, expected: float = None): if rail and voltage is not None: if expected: message = f"Power supply {rail}: {voltage}V (expected ~{expected}V)" else: message = f"Power supply {rail}: abnormal voltage {voltage}V" else: message = "Power supply error detected" super().__init__(message) class DeviceStateError(DeviceError): """Exception raised when device is in an error state.""" def __init__(self, state_code: int, state_name: str = None): self.state_code = state_code if state_name: message = f"Device error state: {state_name} (0x{state_code:04X})" else: message = f"Device error state: 0x{state_code:04X}" super().__init__(message)