import time import json from cam_3.multispectral_service import MultiSpectralService from cam_3.stream_receiver import StreamReceiver from cam_3.pi.raw_processor_core import RawProcessorCore from cam_3.pi.raw_processor_preview import RawProcessorPreview class MultiSpectralClient: def __init__( self, pi_host="192.168.105.6", pc_host="192.168.105.5", server_port=5000, stream_port=6001, timeout=10, width=640, height=480, bayer="GBRG", fps=15, frame_type="RAW_BRUTO", output_dtype="uint8", capture_mode="AUTO", raw_policy="allow_single", module_calibration_json=None, ): self.pi_host = pi_host self.pc_host = pc_host self.server_port = server_port self.stream_port = stream_port self.width = width self.height = height self.bayer = bayer self.fps = fps self.frame_type = frame_type self.output_dtype = output_dtype self.capture_mode = capture_mode self.raw_policy = raw_policy self.module_calibration_json = module_calibration_json self.svc = MultiSpectralService( host=pi_host, port=server_port, timeout=timeout, ) self.receiver = StreamReceiver( host="0.0.0.0", port=stream_port, ) self.core = RawProcessorCore( sensor_width=width, sensor_height=height, bayer_pattern=bayer, calibration_json_path=module_calibration_json, ) self.preview = RawProcessorPreview( sensor_width=width, sensor_height=height, bayer_pattern=bayer, ) self.last_frame_id = None self.status = None self.begin_resp = None self.applied_params = None def __enter__(self): self.start() return self def __exit__(self, exc_type, exc, tb): self.stop() def start(self, print_debug=True): if print_debug: print(f"[INFO] Verificando módulo em {self.pi_host}:{self.server_port}...") if not self.svc.check_connection(2): raise RuntimeError("Módulo não encontrado ou não respondeu ao ping.") self.receiver.start() time.sleep(0.5) self.svc.connect() if print_debug: print("[OK] Módulo conectado.") self._configure_module(print_debug=print_debug) self._begin_module(print_debug=print_debug) self._apply_module_params(print_debug=print_debug) self._start_stream(print_debug=print_debug) return self def _configure_module(self, print_debug=True): r0 = self.svc.set_resolution(self.width, self.height) r1 = self.svc.set_bayer(self.bayer) r2 = self.svc.set_fps(self.fps) r3 = self.svc.set_capture_mode(self.capture_mode) r4 = self.svc.set_frame_type(self.frame_type) r5 = self.svc.set_output_dtype(self.output_dtype) if print_debug: print("SET RES:", r0) print("SET BAYER:", r1) print("SET FPS:", r2) print("SET CAPTURE MODE:", r3) print("SET FRAME TYPE:", r4) print("SET OUTPUT DTYPE:", r5) def _begin_module(self, print_debug=True): self.begin_resp = self.svc.begin( frame_type=self.frame_type, output_dtype=self.output_dtype, capture_mode=self.capture_mode, ) self.status = self.svc.get_status() self.svc.validate_module_ready( self.status, self.frame_type, self.raw_policy, self.capture_mode, ) if print_debug: print("BEGIN:", self.begin_resp) print("STATUS:", json.dumps({ "status": self.status.get("status"), "detected_mode": self.status.get("detected_mode"), "camera_count_active": self.status.get("camera_count_active"), "active_camera_ids": self.status.get("active_camera_ids"), }, ensure_ascii=False)) def _apply_module_params(self, print_debug=True): if not self.module_calibration_json: return None self.applied_params = self.svc.apply_camera_params_json( self.module_calibration_json ) if print_debug: print("[OK] Parâmetros do módulo aplicados:") print(json.dumps(self.applied_params.get("applied"), ensure_ascii=False, indent=2)) return self.applied_params def _start_stream(self, print_debug=True): resp = self.svc.start_stream( self.pc_host, self.stream_port, fps=self.fps, ) if print_debug: print("START STREAM:", resp) return resp def get_latest(self): return self.receiver.last_frame, self.receiver.last_meta def get_next_frame(self, timeout=2.0): t0 = time.perf_counter() while time.perf_counter() - t0 < timeout: frame = self.receiver.last_frame meta = self.receiver.last_meta if frame is None or meta is None: time.sleep(0.001) continue frame_id = meta.get("frame_id") if frame_id != self.last_frame_id: self.last_frame_id = frame_id return frame, meta time.sleep(0.001) raise TimeoutError("Timeout aguardando novo frame do stream.") def build_infer_tensor(self, frame, meta, channels_expected, target_size=None): return self.core.build_infer_tensor_from_stream( frame, meta, channels_expected=channels_expected, target_size=target_size, ) def stop(self): try: self.svc.stop_stream() except Exception: pass try: self.svc.stop() except Exception: pass try: self.svc.disconnect() except Exception: pass try: self.receiver.stop() except Exception: pass