Index: leahi_dialin/common/td_defs.py =================================================================== diff -u -r95205b22fbcf8ce097fd7dba0a34156e5f9008a5 -rb24b5cd51889ebf8087f52adaf864b4bec02b2e2 --- leahi_dialin/common/td_defs.py (.../td_defs.py) (revision 95205b22fbcf8ce097fd7dba0a34156e5f9008a5) +++ leahi_dialin/common/td_defs.py (.../td_defs.py) (revision b24b5cd51889ebf8087f52adaf864b4bec02b2e2) @@ -371,37 +371,45 @@ # TDPreTreatmentModesStates.PRIME_STATE sub states unique class TDPreTreaPrimeStates(DialinEnum): - WAIT_FOR_USER_START_STATE = 0 # Wait for user to start prime state - SALINE_SETUP_STATE = 1 # Saline setup state - SALINE_PURGE_AIR_STATE = 2 # Saline purge air state - SALINE_CIRC_BLOOD_CIRCUIT_STATE = 3 # Circulate blood circuit state - RESERVOIR_ONE_FILL_COMPLETE_STATE = 4 # Wait for reservoir 1 fill complete - DIALYSATE_DIALYZER_STATE = 5 # Dialysate dialyzer fluid path state - SALINE_DIALYZER_SETUP_STATE = 6 # Saline dialyzer setup state - SALINE_DIALYZER_STATE = 7 # Saline dialyzer fluid path state - RESERVOIR_TWO_FILL_COMPLETE_STATE = 8 # Wait for reservoir 2 fill complete - DIALYSATE_BYPASS_STATE = 9 # Dialysate bypass fluid path state - WET_SELF_TESTS_STATE = 10 # Perform wet self-tests after priming complete - PAUSE = 11 # Prime pause state, waits to be resumed - COMPLETE = 12 # Prime complete state - NUM_OF_TD_PRIME_STATES = 13 # Number of prime sub-mode states + START = 0 # Init (start) state. + BC_INITIAL_REVERSE = 1 # Blood circuit initial reverse prime state. + BC_AIR_TRAP_LOWER = 2 # Air Trap lower state + BC_INITIAL_DIALYZER = 3 # Blood circuit initial dialyzer prime state + BC_FILL = 4 # Blood circuit fill state + BC_CLEAR_1 = 5 # Blood circuit air clear stage 1 prime state + BC_CLEAR_2 = 6 # Blood circuit air clear stage 2 prime state + BC_CLEAR_3 = 7 # Blood circuit air clear stage 3 prime state + WAIT_FOR_DIALYSATE_READY = 8 # Wait for dialysate ready state + DC_INITIAL_DIALYSATE = 9 # Dialysate circuit Initial dialysate prime state + WAIT_FOR_AIR_TRAP_FILL = 10 # Wait for air trap fill state + BC2_FORWARD_RECIRC = 11 # Blood circuit 2 forward recirc state + BC2_PAUSE_TO_ROTATE_OPP_DIR = 12 # Pause to rotate opp dir state + BC2_REVERSE_RECIRC = 13 # Blood circuit 2 reverse recirc state + DC_DISCARD_AND_REVERSE_PRIME = 14 # Priming Fluid Discard and Reverse Prime state + PAUSE = 15 # Prime pause state + COMPLETE = 16 # Prime complete state. + NUM_OF_PRIME_STATES = 17 # Number of Prime states. TDPreTreaPrimeStates._str_list = { # Official Name : Accepted strings - 'WAIT_FOR_USER_START_STATE': ['wait for user', 'wait for user to start'], - 'SALINE_SETUP_STATE': ['saline setup', 'saline bolus setup'], - 'SALINE_PURGE_AIR_STATE': ['saline purge air', 'saline bolus air purge'], - 'SALINE_CIRC_BLOOD_CIRCUIT_STATE': ['saline circulate blood', 'saline bolus circulate blood'], - 'RESERVOIR_ONE_FILL_COMPLETE_STATE': ['reservoir 1 fill complete'], - 'DIALYSATE_DIALYZER_STATE': ['dialysate dialyzer', 'dialyzer setup'], - 'SALINE_DIALYZER_SETUP_STATE': ['fill dialyzer with saline bolus', 'saline dialyzer setup'], - 'SALINE_DIALYZER_STATE': ['saline dialyzer'], - 'RESERVOIR_TWO_FILL_COMPLETE_STATE': ['reservoir 2 fill complete'], - 'DIALYSATE_BYPASS_STATE': ['dialysate bypass'], - 'WET_SELF_TESTS_STATE': ['wet self tests'], - 'PAUSE': ['prime paused', 'priming paused'], - 'COMPLETE': ['prime completed', 'priming completed'], - 'NUM_OF_TD_PRIME_STATES': [], + 'START': [], + 'BC_INITIAL_REVERSE': [], + 'BC_AIR_TRAP_LOWER': [], + 'BC_INITIAL_DIALYZER': [], + 'BC_FILL': [], + 'BC_CLEAR_1': [], + 'BC_CLEAR_2': [], + 'BC_CLEAR_3': [], + 'WAIT_FOR_DIALYSATE_READY': [], + 'DC_INITIAL_DIALYSATE': [], + 'WAIT_FOR_AIR_TRAP_FILL': [], + 'BC2_FORWARD_RECIRC': [], + 'BC2_PAUSE_TO_ROTATE_OPP_DIR': [], + 'BC2_REVERSE_RECIRC': [], + 'DC_DISCARD_AND_REVERSE_PRIME': [], + 'PAUSE': [], + 'COMPLETE': [], + 'NUM_OF_PRIME_STATES': [] } Index: leahi_dialin/td/modules/post_treatment.py =================================================================== diff -u --- leahi_dialin/td/modules/post_treatment.py (revision 0) +++ leahi_dialin/td/modules/post_treatment.py (revision b24b5cd51889ebf8087f52adaf864b4bec02b2e2) @@ -0,0 +1,86 @@ +########################################################################### +# +# 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 post_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.protocols.CAN import CanMessenger, CanChannels +from leahi_dialin.utils.abstract_classes import AbstractSubSystem +from leahi_dialin.utils.base import publish + + +class TDPostTreatment(AbstractSubSystem): + """ + Post-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_UNUSED.value, + function = self._handler_post_treatment_state_sync) + + # Treatment State Data + self.post_tx_state_timestamp = 0 #: The timestamp of the latest Post-Treatment State message + self.post_treatment_states = { + 'sub_mode': 0, # The Pre-Treatment Operation Sub-Mode + } + + + +# ============================================================ Properties ============================================================ + @property + def post_treatment_states(self) -> dict: + """ + The Post-Treatment states + """ + return self._post_treatment_states + + @post_treatment_states.setter + def post_treatment_states(self, value): + self._post_treatment_states = value + + + +# ============================================================ Handlers ============================================================ + @publish([MsgIds.MSG_ID_UNUSED.name.lower(), "post_treatment_states", "post_tx_state_timestamp"]) + def _handler_post_treatment_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((self.post_treatment_states, 'sub_mode', DataTypes.U32)) + + + self.process_into_vars(decoder_list = msg_list, message = message) + self.post_tx_state_timestamp = timestamp + + + +# ============================================================ Overrides and Requests ============================================================ Index: leahi_dialin/td/modules/pre_treatment.py =================================================================== diff -u -r02dbda406f0e7c06773e3ac24765d3ee93b4ec35 -rb24b5cd51889ebf8087f52adaf864b4bec02b2e2 --- leahi_dialin/td/modules/pre_treatment.py (.../pre_treatment.py) (revision 02dbda406f0e7c06773e3ac24765d3ee93b4ec35) +++ leahi_dialin/td/modules/pre_treatment.py (.../pre_treatment.py) (revision b24b5cd51889ebf8087f52adaf864b4bec02b2e2) @@ -18,15 +18,12 @@ from logging import Logger # Project imports -from leahi_dialin.common.constants import NO_RESET from leahi_dialin.common.generic_defs import DataTypes from leahi_dialin.common.msg_ids import MsgIds -from leahi_dialin.common.override_templates import cmd_generic_override -from leahi_dialin.common import td_enum_repository +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 -from leahi_dialin.utils.conversions import integer_to_bytearray, float_to_bytearray class TDPreTreatment(AbstractSubSystem): @@ -47,8 +44,12 @@ 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 Treatment State message + 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 @@ -60,11 +61,18 @@ '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) -> int: + def pre_treatment_states(self) -> dict: """ The Pre-Treatment states """ @@ -75,28 +83,102 @@ 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 treatment state data message + @param message: published pre treatment state data message @return: none """ msg_list = [] - msg_list.append((self.treatment_states, 'sub_mode', DataTypes.U32)) - msg_list.append((self.treatment_states, 'install_state', DataTypes.U32)) - msg_list.append((self.treatment_states, 'dry_self_test_state', DataTypes.U32)) - msg_list.append((self.treatment_states, 'prime_state', DataTypes.U32)) - msg_list.append((self.treatment_states, 'recirculate_state', DataTypes.U32)) - msg_list.append((self.treatment_states, 'confirm_rx_state', DataTypes.U32)) - msg_list.append((self.treatment_states, 'heparin_state', DataTypes.U32)) - msg_list.append((self.treatment_states, 'patient_connect_state', DataTypes.U32)) + 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.tx_state_timestamp = timestamp + 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 ============================================================ Index: leahi_dialin/td/modules/treatment.py =================================================================== diff -u -r02dbda406f0e7c06773e3ac24765d3ee93b4ec35 -rb24b5cd51889ebf8087f52adaf864b4bec02b2e2 --- leahi_dialin/td/modules/treatment.py (.../treatment.py) (revision 02dbda406f0e7c06773e3ac24765d3ee93b4ec35) +++ leahi_dialin/td/modules/treatment.py (.../treatment.py) (revision b24b5cd51889ebf8087f52adaf864b4bec02b2e2) @@ -170,7 +170,7 @@ @property - def ultrafiltration(self) -> int: + def ultrafiltration(self) -> dict: """ The Ultrafiltration data """ @@ -182,7 +182,7 @@ @property - def treatment_times(self) -> int: + def treatment_times(self) -> dict: """ The Treatment times """ @@ -194,7 +194,7 @@ @property - def treatment_states(self) -> int: + def treatment_states(self) -> dict: """ The Treatment states """ @@ -206,7 +206,7 @@ @property - def treatment_paramters(self) -> int: + def treatment_paramters(self) -> dict: """ The Treatment Parameters """