########################################################################### # # Copyright (c) 2020-2025 Diality Inc. - All Rights Reserved. # # THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN # WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. # # @file pre_treatment.py # # @author (last) Zoltan Miskolci # @date (last) 21-Aug-2026 # @author (original) Zoltan Miskolci # @date (original) 21-Aug-2026 # ############################################################################ # Module imports from logging import Logger # Project imports from leahi_dialin.common.generic_defs import DataTypes from leahi_dialin.common.msg_ids import MsgIds from leahi_dialin.common.td_defs import TDPreTreaPrimeStates from leahi_dialin.protocols.CAN import CanMessenger, CanChannels from leahi_dialin.utils.abstract_classes import AbstractSubSystem from leahi_dialin.utils.base import publish class TDPreTreatment(AbstractSubSystem): """ Pre-Treatment Delivery (TD) Dialin API sub-class for treatment related commands. """ def __init__(self, can_interface: CanMessenger, logger: Logger): """ Constructor """ super().__init__() self.can_interface = can_interface self.logger = logger if self.can_interface is not None: self.can_interface.register_receiving_publication_function(channel_id = CanChannels.td_sync_broadcast_ch_id, message_id = MsgIds.MSG_ID_TD_PRE_TREATMENT_STATES_DATA.value, function = self._handler_pre_treatment_state_sync) self.can_interface.register_receiving_publication_function(channel_id = CanChannels.td_sync_broadcast_ch_id, message_id = MsgIds.MSG_ID_TD_PRIME_PROGRESS_DATA.value, function = self._handler_prime_state_sync) # Treatment State Data self.pre_tx_state_timestamp = 0 #: The timestamp of the latest Pre-Treatment State message self.pre_treatment_states = { 'sub_mode': 0, # The Pre-Treatment Operation Sub-Mode 'install_state': 0, # The Auto Load Operation State 'dry_self_test_state': 0, # The Dry Self Test Operation State 'prime_state': 0, # The Prime Operation State 'recirculate_state': 0, # The Recirculate Operation State 'confirm_rx_state': 0, # The Confirm Treatment Parameters Operation State 'heparin_state': 0, # The Heparin Operation State 'patient_connect_state': 0 # The Patient Connect Operation State } # Priming State Data self.prime_state_timestamp = 0 #: The timestamp of the latest Prime State message self.prime_state = TDPreTreaPrimeStates.START self.total_duration_sec = 0 self.count_down_to_total_sec = 0 self.count_down_to_pause_sec = 0 # ============================================================ Properties ============================================================ @property def pre_treatment_states(self) -> dict: """ The Pre-Treatment states """ return self._pre_treatment_states @pre_treatment_states.setter def pre_treatment_states(self, value): self._pre_treatment_states = value @property def prime_state(self) -> TDPreTreaPrimeStates: """ The Prime state """ return self._prime_state @prime_state.setter def prime_state(self, value): if isinstance(value, int): self._prime_state = TDPreTreaPrimeStates(value) elif isinstance(value, str): self._prime_state = TDPreTreaPrimeStates.from_str(value) else: self._prime_state = value @property def total_duration_sec(self) -> int: """ Total allowed prime duration """ return self._total_duration_sec @total_duration_sec.setter def total_duration_sec(self, value): self._total_duration_sec = value @property def count_down_to_total_sec(self) -> int: """ Remaining time before total duration """ return self._count_down_total_sec @count_down_to_total_sec.setter def count_down_to_total_sec(self, value): self._count_down_total_sec = value @property def count_down_to_pause_sec(self) -> int: """ Remaining time before pause timeout """ return self._count_down_to_pause_sec @count_down_to_pause_sec.setter def count_down_to_pause_sec(self, value): self._count_down_to_pause_sec = value # ============================================================ Handlers ============================================================ @publish([MsgIds.MSG_ID_TD_PRE_TREATMENT_STATES_DATA.name.lower(), "pre_treatment_states", "pre_tx_state_timestamp"]) def _handler_pre_treatment_state_sync(self, message, timestamp=0.0): """ Handles published treatment state data messages. @param message: published pre treatment state data message @return: none """ msg_list = [] msg_list.append((self.pre_treatment_states, 'sub_mode', DataTypes.U32)) msg_list.append((self.pre_treatment_states, 'install_state', DataTypes.U32)) msg_list.append((self.pre_treatment_states, 'dry_self_test_state', DataTypes.U32)) msg_list.append((self.pre_treatment_states, 'prime_state', DataTypes.U32)) msg_list.append((self.pre_treatment_states, 'recirculate_state', DataTypes.U32)) msg_list.append((self.pre_treatment_states, 'confirm_rx_state', DataTypes.U32)) msg_list.append((self.pre_treatment_states, 'heparin_state', DataTypes.U32)) msg_list.append((self.pre_treatment_states, 'patient_connect_state', DataTypes.U32)) self.process_into_vars(decoder_list = msg_list, message = message) self.pre_tx_state_timestamp = timestamp @publish([MsgIds.MSG_ID_TD_PRIME_PROGRESS_DATA.name.lower(), "prime_state", "total_duration_sec", "count_down_to_total_sec", "count_down_to_pause_sec", "prime_state_timestamp"]) def _handler_prime_state_sync(self, message, timestamp=0.0): """ Handles published treatment state data messages. @param message: published psot treatment state data message @return: none """ msg_list = [] msg_list.append((type(self).prime_state, DataTypes.U32)) msg_list.append((type(self).total_duration_sec, DataTypes.U32)) msg_list.append((type(self).count_down_to_total_sec, DataTypes.U32)) msg_list.append((type(self).count_down_to_pause_sec, DataTypes.U32)) self.process_into_vars(decoder_list = msg_list, message = message) self.prime_state_timestamp = timestamp # ============================================================ Overrides and Requests ============================================================