diff --git a/cri_lib/cri_controller.py b/cri_lib/cri_controller.py index 3f8f135..2dea64d 100644 --- a/cri_lib/cri_controller.py +++ b/cri_lib/cri_controller.py @@ -51,10 +51,9 @@ def __init__(self) -> None: self.can_mode: bool = False self.can_queue: Queue = Queue() - self.jog_thread = threading.Thread(target=self._bg_alivejog_thread, daemon=True) - self.receive_thread = threading.Thread( - target=self._bg_receive_thread, daemon=True - ) + # Threads are created upon connect() and should be accessed through read-only properties. + self._jog_thread: threading.Thread | None = None + self._receive_thread: threading.Thread | None = None self.sent_command_counter_lock = threading.Lock() self.sent_command_counter = 0 @@ -79,6 +78,22 @@ def __init__(self) -> None: } self.jog_speeds_lock = threading.Lock() + @property + def receive_thread(self) -> threading.Thread: + if self._receive_thread is None: + raise CRIConnectionError( + "Receive thread not started yet. Call connect() first." + ) + return self._receive_thread + + @property + def jog_thread(self) -> threading.Thread: + if self._jog_thread is None: + raise CRIConnectionError( + "Jog thread not started yet. Call connect() first." + ) + return self._jog_thread + def connect( self, host: str, @@ -113,18 +128,24 @@ def connect( ip = socket.gethostbyname(host) self.sock.connect((ip, port)) logger.debug("\t Robot connected: %s:%d", host, port) - self.connected = True # Start receiving commands + self._receive_thread = threading.Thread( + target=self._bg_receive_thread, daemon=True + ) self.receive_thread.start() # Start sending ALIVEJOG message + self._jog_thread = threading.Thread( + target=self._bg_alivejog_thread, daemon=True + ) self.jog_thread.start() hello_msg = f'INFO Hello "{application_name}" {application_version} {datetime.now(timezone.utc).strftime(format="%Y-%m-%dT%H:%M:%S")}' self._send_command(hello_msg) + self.connected = True return True except ConnectionRefusedError: @@ -152,9 +173,11 @@ def close(self) -> None: if self.jog_thread.is_alive(): self.jog_thread.join() + self._jog_thread = None if self.receive_thread.is_alive(): self.receive_thread.join() + self._receive_thread = None self.sock.close()