Index: dialin/common/msg_defs.py =================================================================== diff -u -rd4cf7e98bfe73fde95043613fa894b64b57d11a8 -rd1895f75abcc170ffea2fbb50457e5c315d60995 --- dialin/common/msg_defs.py (.../msg_defs.py) (revision d4cf7e98bfe73fde95043613fa894b64b57d11a8) +++ dialin/common/msg_defs.py (.../msg_defs.py) (revision d1895f75abcc170ffea2fbb50457e5c315d60995) @@ -17,22 +17,27 @@ from ..utils.base import DialinEnum from .msg_ids import MsgIds + # Define msg ids that are not yet added to common but are needed in dialin @unique class MsgIdsDialin(DialinEnum): MSG_DIALIN_ID_HD_SERIAL_NUMBER_RESPONSE = 0X87 MSG_DIALIN_ID_DG_SERIAL_NUMBER_RESPONSE = 0X88 - MSG_DIALIN_ID_UI_SYSTEM_USAGE_REQUEST = 0x89 - MSG_DIALIN_ID_HD_SYSTEM_USAGE_RESPONSE = 0x8A - MSG_DIALIN_ID_DG_SYSTEM_USAGE_RESPONSE = 0x8C + MSG_DIALIN_ID_UI_SYSTEM_USAGE_REQUEST = 0x89 + MSG_DIALIN_ID_HD_SYSTEM_USAGE_RESPONSE = 0x8A + MSG_DIALIN_ID_DG_SYSTEM_USAGE_RESPONSE = 0x8C + MSG_DIALIN_ID_HD_FLUID_LEAK_STATE_DETECTOR_OVERRIDE = 0x8047 MSG_DIALIN_ID_HD_VALVES_POSITION_COUNT_OVERRIDE = 0x8058 - MSG_DIALIN_ID_HD_DISINFECT_STATE = 0x7E + MSG_DIALIN_ID_HD_DISINFECT_STATE = 0x7E + MSG_DIALIN_ID_HD_VERSION_REQUEST = 0x9E + MSG_DIALIN_ID_UI_POST_REPORT_VERSION = 0x9F ACK_NOT_REQUIRED = [ MsgIds.MSG_ID_ALARM_CONDITION_CLEARED.value ] + @unique class RequestRejectReasons(DialinEnum): REQUEST_REJECT_REASON_NONE = 0 @@ -42,7 +47,7 @@ REQUEST_REJECT_REASON_INVALID_TREATMENT_STATE = 4 REQUEST_REJECT_REASON_TREATMENT_TOO_CLOSE_TO_FINISHED = 5 REQUEST_REJECT_REASON_TREATMENT_TIME_OUT_OF_RANGE = 6 - REQUEST_REJECT_REASON_TREATMENT_TIME_LESS_THAN_CURRENT = 7 + EQUEST_REJECT_REASON_TREATMENT_TIME_LESS_THAN_CURRENT = 7 REQUEST_REJECT_REASON_BLOOD_FLOW_OUT_OF_RANGE = 8 REQUEST_REJECT_REASON_DIAL_FLOW_OUT_OF_RANGE = 9 REQUEST_REJECT_REASON_DIAL_VOLUME_OUT_OF_RANGE = 10 @@ -71,6 +76,7 @@ REQUEST_REJECT_REASON_DRAIN_NOT_COMPLETE = 33 NUM_OF_REQUEST_REJECT_REASONS = 34 + class MsgFieldPositions: # Generic response msg field byte positions (where 32-bit data fields are used) START_POS_FIELD_1 = 6 # Hardcoded for now to avoid cyclic import issue. See protocols.CAN.DenaliMessage class @@ -122,4 +128,4 @@ START_POS_FIELD_24 = END_POS_FIELD_23 END_POS_FIELD_24 = START_POS_FIELD_24 + 4 START_POS_FIELD_25 = END_POS_FIELD_24 - END_POS_FIELD_25 = START_POS_FIELD_25 + 4 \ No newline at end of file + END_POS_FIELD_25 = START_POS_FIELD_25 + 4 Index: dialin/common/msg_ids.py =================================================================== diff -u -r6356891100bf5058c4c77ac388eb23415d6435c6 -rd1895f75abcc170ffea2fbb50457e5c315d60995 --- dialin/common/msg_ids.py (.../msg_ids.py) (revision 6356891100bf5058c4c77ac388eb23415d6435c6) +++ dialin/common/msg_ids.py (.../msg_ids.py) (revision d1895f75abcc170ffea2fbb50457e5c315d60995) @@ -272,7 +272,9 @@ MSG_ID_HD_SYRINGE_PUMP_ADC_READ_COUNTER_OVERRIDE = 0X805C MSG_ID_HD_BUBBLES_DATA_SEND_INTERVAL_OVERRIDE = 0X805D MSG_ID_HD_BUBBLE_STATUS_OVERRIDE = 0X805E + MSG_ID_HD_BLOOD_PRIME_VOLUME_OVERRIDE = 0X805F MSG_ID_HD_BUBBLE_SELF_TEST_REQUEST = 0X8060 + MSG_ID_HD_BLOOD_PRIME_SAFETY_VOLUME_OVERRIDE = 0X8061 MSG_ID_DG_TESTER_LOGIN_REQUEST = 0XA000 MSG_ID_DG_ALARM_STATE_OVERRIDE = 0XA001 MSG_ID_DG_WATCHDOG_TASK_CHECKIN_OVERRIDE = 0XA002 Index: dialin/dg/hd_proxy.py =================================================================== diff -u -rd4cf7e98bfe73fde95043613fa894b64b57d11a8 -rd1895f75abcc170ffea2fbb50457e5c315d60995 --- dialin/dg/hd_proxy.py (.../hd_proxy.py) (revision d4cf7e98bfe73fde95043613fa894b64b57d11a8) +++ dialin/dg/hd_proxy.py (.../hd_proxy.py) (revision d1895f75abcc170ffea2fbb50457e5c315d60995) @@ -326,4 +326,4 @@ return received_message['message'][DenaliMessage.PAYLOAD_START_INDEX] else: self.logger.debug("Timeout!!!!") - return False \ No newline at end of file + return False Index: dialin/hd/treatment.py =================================================================== diff -u -r2b80b3c2a26012faf121aeb6be0b3f983061be1c -rd1895f75abcc170ffea2fbb50457e5c315d60995 --- dialin/hd/treatment.py (.../treatment.py) (revision 2b80b3c2a26012faf121aeb6be0b3f983061be1c) +++ dialin/hd/treatment.py (.../treatment.py) (revision d1895f75abcc170ffea2fbb50457e5c315d60995) @@ -20,6 +20,7 @@ from ..common.msg_defs import MsgIds, MsgFieldPositions from logging import Logger from ..utils.conversions import integer_to_bytearray, float_to_bytearray +from .constants import RESET, NO_RESET class HDTreatment(_AbstractSubSystem): @@ -125,6 +126,7 @@ # blood prime status self.blood_prime_tgt_vol = 0.0 self.blood_prime_cum_vol = 0.0 + self.blood_prime_ind_cum_vol = 0.0 # rinseback status self.rinseback_tgt_vol = 0.0 self.rinseback_cum_vol = 0.0 @@ -161,52 +163,76 @@ def get_treatment_state(self): """ - Gets the treatment state + Gets the current treatment state - @return: The treatment state + @return: The current treatment state ID """ return self.treatment_state - def get_treatment_uf_state(self): + def get_treatment_UF_state(self): """ - Gets the treatment uf state + Gets the current treatment ultrafiltration state - @return: The treatment uf state + @return: The current treatment ultrafiltration state ID """ return self.treatment_uf_state - def get_saline_bolus_state(self): + def get_treatment_saline_bolus_state(self): """ - Gets the current saline bolus state + Gets the current treatment saline bolus state - @return: The saline bolus state + @return: The current treatment saline bolus state ID """ return self.saline_bolus_state - def get_heparin_state(self): + def get_treatment_heparin_state(self): """ - Gets the current Heparin state + Gets the current treatment Heparin state - @return: The Heparin state + @return: The current treatment Heparin state ID """ return self.heparin_state - def get_rinseback_state(self): + def get_treatment_rinseback_state(self): """ - Gets the current rinseback state + Gets the current treatment rinseback state - @return: The rinseback state + @return: The current treatment rinseback state ID """ return self.rinseback_state - def get_treatment_recirc_state(self): + def get_treatment_recirculate_state(self): """ Gets the current treatment recirculate state - @return: The treatment recirculate state + @return: The current treatment recirculate state ID """ return self.treatment_recirculate_state + def get_treatment_blood_prime_state(self): + """ + Gets the current treatment blood prime state + + @return: The current treatment blood prime state ID + """ + return self.blood_prime_state + + def get_treatment_end_state(self): + """ + Gets the current treatment end state + + @return: The current treatment end state ID + """ + return self.treatment_end_state + + def get_treatment_stop_state(self): + """ + Gets the current treatment stop state + + @return: The current treatment stop state ID + """ + return self.treatment_stop_state + def get_saline_bolus_max_volume(self): """ Returns maximum volume (in mL) saline that can be delivered to a patient @@ -231,7 +257,30 @@ """ return self.saline_bolus_bol_vol + def get_blood_prime_target_volume(self): + """ + Returns blood prime target volume (in mL) + @return: The blood prime target volume + """ + return self.blood_prime_tgt_vol + + def get_blood_prime_volume_delivered(self): + """ + Returns blood prime volume (in mL) delivered + + @return: The blood prime volume delivered + """ + return self.blood_prime_cum_vol + + def get_blood_prime_safety_volume_delivered(self): + """ + Returns blood prime safety volume (in mL) delivered + + @return: The blood prime safety volume delivered + """ + return self.blood_prime_ind_cum_vol + @_publish([ "treatment_time_prescribed", "treatment_time_elapsed", @@ -381,9 +430,12 @@ message['message'][MsgFieldPositions.START_POS_FIELD_1:MsgFieldPositions.END_POS_FIELD_1])) cum = struct.unpack('f', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_2:MsgFieldPositions.END_POS_FIELD_2])) + ind = struct.unpack('f', bytearray( + message['message'][MsgFieldPositions.START_POS_FIELD_3:MsgFieldPositions.END_POS_FIELD_3])) self.blood_prime_tgt_vol = tgt[0] self.blood_prime_cum_vol = cum[0] + self.blood_prime_ind_cum_vol = ind[0] @_publish([ "recirc_timeout_secs", @@ -1095,3 +1147,72 @@ else: self.logger.debug("Timeout!!!!") return False + + def cmd_blood_prime_volume_delivered_override(self, volume: float, reset: int =NO_RESET) -> int: + """ + Constructs and sends the blood prime volume delivered override command + Constraints: + Must be logged into HD. + + @param volume: float - volume (in mL) of blood delivered during blood prime (must be positive) + @param reset: integer - 1 to reset a previous override, 0 to override + @return: 1 if successful, zero otherwise + """ + + rst = integer_to_bytearray(reset) + vol = float_to_bytearray(volume) + payload = rst + vol + + message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=MsgIds.MSG_ID_HD_BLOOD_PRIME_VOLUME_OVERRIDE.value, + payload=payload) + + self.logger.debug("override HD blood prime volume delivered (in mL).") + + # Send message + received_message = self.can_interface.send(message) + + # If there is content... + if received_message is not None: + self.logger.debug("Blood prime volume delivered overridden to " + str(volume) + " mL. " + + str(received_message['message'][DenaliMessage.PAYLOAD_START_INDEX])) + # response payload is OK or not OK + return received_message['message'][DenaliMessage.PAYLOAD_START_INDEX] + else: + self.logger.debug("Timeout!!!!") + return False + + def cmd_blood_prime_safety_volume_delivered_override(self, volume: float, reset: int =NO_RESET) -> int: + """ + Constructs and sends the blood prime safety volume delivered override command + Constraints: + Must be logged into HD. + + @param volume: float - safety volume (in mL) of blood delivered during blood prime (must be positive) + @param reset: integer - 1 to reset a previous override, 0 to override + @return: 1 if successful, zero otherwise + """ + + rst = integer_to_bytearray(reset) + vol = float_to_bytearray(volume) + payload = rst + vol + + message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=MsgIds.MSG_ID_HD_BLOOD_PRIME_SAFETY_VOLUME_OVERRIDE.value, + payload=payload) + + self.logger.debug("override HD blood prime safety volume delivered (in mL).") + + # Send message + received_message = self.can_interface.send(message) + + # If there is content... + if received_message is not None: + self.logger.debug("Blood prime safety volume delivered overridden to " + str(volume) + " mL. " + + str(received_message['message'][DenaliMessage.PAYLOAD_START_INDEX])) + # response payload is OK or not OK + return received_message['message'][DenaliMessage.PAYLOAD_START_INDEX] + else: + self.logger.debug("Timeout!!!!") + return False +