class ModuleState: def __init__(self): self.module_name = "multispectral" self.version = "0.1.0" self.payload_format_version = 1 self.status = "idle" self.status_detail = None self.last_error = None self.last_command = None self.camera_connected = False self.camera_id = "cam0" self.initialized = False self.streaming = False # Configuração da captura no sensor self.fps = 10 self.jpeg_quality = 90 self.width = 640 self.height = 480 self.source_bayer_pattern = "GBRG" self.source_bit_depth = 10 # Configuração do tipo de payload de saída self.frame_type = "RAW_BRUTO" # RAW_BRUTO | RGB | RGBNIR self.output_dtype = "uint8" # uint8 | float32 self.output_layout = "CHW" # sempre CHW self.output_channels = 1 self.output_channel_names = ["RAW10_PACKED"] self.output_width = 640 self.output_height = 480 self.trigger_enabled = True self.trigger_pin = 18 self.trigger_active_high = True self.trigger_pulse_ms = 5.0 self.trigger_settle_delay_ms = 0.0 self.stream_host = None self.stream_port = None self.stream_fps = None self.stream_frame_id = 0 self.codec_family = "none" self.codec_name = "blosc" self.codec_params = { "cname": "zstd", "clevel": 3, "shuffle": "BITSHUFFLE", } self.ae_enable = True self.awb_enable = True self.exposure_time_us = 15000 self.analogue_gain = 1.0 self.colour_gains = [1.0, 1.0] self.frame_duration_limits = None self.update_output_spec() def update_output_spec(self): if self.frame_type == "RAW_BRUTO": self.output_layout = "HW" self.output_channels = 1 self.output_channel_names = ["BAYER"] self.output_width = self.width self.output_height = self.height elif self.frame_type == "RGB": self.output_layout = "CHW" self.output_channels = 3 self.output_channel_names = ["R", "G", "B"] self.output_width = self.width // 2 self.output_height = self.height // 2 elif self.frame_type == "RGBNIR": self.output_layout = "CHW" self.output_channels = 5 self.output_channel_names = ["R", "G", "B", "NIR", "RE"] self.output_width = self.width // 2 self.output_height = self.height // 2 else: raise ValueError(f"frame_type inválido: {self.frame_type}") def clear_error(self): self.last_error = None if self.status == "error": self.status = "idle" self.status_detail = None def set_error(self, error: str): self.last_error = str(error) self.status = "error" self.status_detail = str(error) def to_dict(self): return { "module": self.module_name, "version": self.version, "status": self.status, "status_detail": self.status_detail, "last_error": self.last_error, "last_command": self.last_command, "camera_connected": self.camera_connected, "camera_id": self.camera_id, "initialized": self.initialized, "streaming": self.streaming, "fps": self.fps, "jpeg_quality": self.jpeg_quality, "width": self.width, "height": self.height, "trigger_enabled": self.trigger_enabled, "trigger_pin": self.trigger_pin, "trigger_active_high": self.trigger_active_high, "trigger_pulse_ms": self.trigger_pulse_ms, "trigger_settle_delay_ms": self.trigger_settle_delay_ms, "stream_host": self.stream_host, "stream_port": self.stream_port, "stream_fps": self.stream_fps, "stream_frame_id": self.stream_frame_id, "codec_family": self.codec_family, "codec_name": self.codec_name, "codec_params": self.codec_params, "ae_enable": self.ae_enable, "awb_enable": self.awb_enable, "exposure_time_us": self.exposure_time_us, "analogue_gain": self.analogue_gain, "colour_gains": self.colour_gains, "frame_duration_limits": self.frame_duration_limits, "payload_format_version": self.payload_format_version, "source_bayer_pattern": self.source_bayer_pattern, "source_bit_depth": self.source_bit_depth, "frame_type": self.frame_type, "output_dtype": self.output_dtype, "output_layout": self.output_layout, "output_channels": self.output_channels, "output_channel_names": self.output_channel_names, "output_width": self.output_width, "output_height": self.output_height, }