########################################################################### # # Copyright (c) 2019-2021 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 treatment.py # # @author (last) Sean Nash # @date (last) 12-Nov-2021 # @author (original) Peter Lucia # @date (original) 02-Apr-2020 # ############################################################################ import struct from logging import Logger from ..common.msg_defs import MsgIds, MsgFieldPositions from ..protocols.CAN import DenaliMessage, DenaliChannels from ..utils.base import AbstractSubSystem, publish from ..utils.conversions import integer_to_bytearray, float_to_bytearray from ..utils.checks import check_broadcast_interval_override_ms from .constants import RESET, NO_RESET class HDTreatment(AbstractSubSystem): """ Hemodialysis Delivery (HD) Dialin API sub-class for treatment related commands. """ # Treatment Parameter IDs HD_TREATMENT_PARAMETER_BLOOD_FLOW = 0 HD_TREATMENT_PARAMETER_DIALYSATE_FLOW = 1 HD_TREATMENT_PARAMETER_TREATMENT_DURATION = 2 HD_TREATMENT_PARAMETER_HEPARIN_PRE_STOP_TIME = 3 HD_TREATMENT_PARAMETER_SALINE_BOLUS_VOLUME = 4 HD_TREATMENT_PARAMETER_ACID_CONCENTRATE = 5 HD_TREATMENT_PARAMETER_BICARB_CONCENTRATE = 6 HD_TREATMENT_PARAMETER_DIALYZER_TYPE = 7 HD_TREATMENT_PARAMETER_BP_MEAS_INTERVAL = 8 HD_TREATMENT_PARAMETER_RINSEBACK_FLOW_RATE = 9 HD_TREATMENT_PARAMETER_ART_PRESSURE_LOW_LIMIT = 10 HD_TREATMENT_PARAMETER_ART_PRESSURE_HIGH_LIMIT = 11 HD_TREATMENT_PARAMETER_VEN_PRESSURE_LOW_LIMIT = 12 HD_TREATMENT_PARAMETER_VEN_PRESSURE_HIGH_LIMIT = 13 HD_TREATMENT_PARAMETER_HEPARIN_DISPENSE_RATE = 14 HD_TREATMENT_PARAMETER_HEPARIN_BOLUS_VOLUME = 15 HD_TREATMENT_PARAMETER_DIALYSATE_TEMPERATURE = 16 HD_TREATMENT_PARAMETER_UF_VOLUME = 17 # Dialyzer Type IDs DIALYZER_TYPE_NIPRO_ELISIO_H_17 = 0 DIALYZER_TYPE_NIPRO_ELISIO_H_19 = 1 DIALYZER_TYPE_FRESENIUS_OPTIFLUX_F160NRE = 2 DIALYZER_TYPE_FRESENIUS_OPTIFLUX_F180NRE = 3 # Acid Concentrate IDs ACID_CONC_TYPE_FRESENIUS_08_1251_1 = 0 ACID_CONC_TYPE_FRESENIUS_08_2251_0 = 1 ACID_CONC_TYPE_FRESENIUS_08_3251_9 = 2 # Bicarbonate Concentrate IDs BICARB_CONC_TYPE_FRESENIUS_CENTRISOL = 0 # UF states UF_START_STATE = 0 # Start state of the ultrafiltration state machine UF_PAUSED_STATE = 1 # Paused state of the ultrafiltration state machine UF_RUNNING_STATE = 2 # Running state of the ultrafiltration state machine # Saline bolus states SALINE_BOLUS_STATE_IDLE = 0 # No saline bolus delivery is in progress SALINE_BOLUS_STATE_WAIT_FOR_PUMPS_STOP = 1 # Wait for pumps to stop before starting bolus SALINE_BOLUS_STATE_IN_PROGRESS = 2 # A saline bolus delivery is in progress SALINE_BOLUS_STATE_MAX_DELIVERED = 3 # Maximum saline bolus volume reached def __init__(self, can_interface, logger: Logger): """ HDTreatment constructor """ super().__init__() self.can_interface = can_interface self.logger = logger if self.can_interface is not None: channel_id = DenaliChannels.hd_sync_broadcast_ch_id msg_id = MsgIds.MSG_ID_TREATMENT_TIME.value self.can_interface.register_receiving_publication_function(channel_id, msg_id, self._handler_treatment_time_sync) msg_id = MsgIds.MSG_ID_TREATMENT_STATE.value self.can_interface.register_receiving_publication_function(channel_id, msg_id, self._handler_treatment_state_sync) msg_id = MsgIds.MSG_ID_SALINE_BOLUS_DATA.value self.can_interface.register_receiving_publication_function(channel_id, msg_id, self._handler_saline_bolus_data_sync) msg_id = MsgIds.MSG_ID_HD_RINSEBACK_PROGRESS.value self.can_interface.register_receiving_publication_function(channel_id, msg_id, self._handler_rinseback_data_sync) msg_id = MsgIds.MSG_ID_HD_BLOOD_PRIME_PROGRESS.value self.can_interface.register_receiving_publication_function(channel_id, msg_id, self._handler_blood_prime_data_sync) msg_id = MsgIds.MSG_ID_HD_RECIRC_PROGRESS.value self.can_interface.register_receiving_publication_function(channel_id, msg_id, self._handler_recirculate_data_sync) msg_id = MsgIds.MSG_ID_HD_TREATMENT_STOP_TIMER_DATA.value self.can_interface.register_receiving_publication_function(channel_id, msg_id, self._handler_treatment_stop_timer_data_sync) # treatment duration data self.treatment_time_prescribed = 0 self.treatment_time_elapsed = 0 self.treatment_time_remaining = 0 # treatment state data self.treatment_state = 0 self.treatment_uf_state = 0 self.saline_bolus_state = 0 self.heparin_state = 0 self.rinseback_state = 0 self.treatment_recirculate_state = 0 self.blood_prime_state = 0 self.treatment_end_state = 0 self.treatment_stop_state = 0 # saline bolus status self.saline_bolus_max_vol = 0 self.saline_bolus_cum_vol = 0.0 self.saline_bolus_bol_vol = 0.0 # blood prime status self.blood_prime_tgt_vol = 0.0 self.blood_prime_cum_vol = 0.0 # rinseback status self.rinseback_tgt_vol = 0.0 self.rinseback_cum_vol = 0.0 self.rinseback_cur_rate = 0 self.rinseback_timeout_secs = 0 self.rinseback_countdown_secs = 0 # re-circulation status self.recirc_timeout_secs = 0 self.recirc_countdown_secs = 0 # treatment stop status self.treatment_stop_timeout_secs = 0 self.treatment_stop_timeout_coundown_secs = 0 def reset(self) -> None: """ Reset all treatment variables @return: None """ # treatment duration data self.treatment_time_prescribed = 0 self.treatment_time_elapsed = 0 self.treatment_time_remaining = 0 # treatment state data self.treatment_state = 0 self.treatment_uf_state = 0 self.saline_bolus_state = 0 self.heparin_state = 0 self.rinseback_state = 0 self.treatment_recirculate_state = 0 self.blood_prime_state = 0 self.treatment_end_state = 0 self.treatment_stop_state = 0 self.dialysis_state = 0 # saline bolus status self.saline_bolus_max_vol = 0 self.saline_bolus_cum_vol = 0.0 self.saline_bolus_bol_vol = 0.0 # 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 self.rinseback_cur_rate = 0 self.rinseback_timeout_secs = 0 self.rinseback_countdown_secs = 0 # re-circulation status self.recirc_timeout_secs = 0 self.recirc_countdown_secs = 0 def get_treatment_time_prescribed(self) -> int: """ Gets the prescribed treatment time @return: The prescribed treatment time """ return self.treatment_time_prescribed def get_treatment_time_elapsed(self) -> int: """ Gets the elapsed treatment time @return: The elapsed treatment time """ return self.treatment_time_elapsed def get_treatment_time_remaining(self) -> int: """ Gets the remaining treatment time @return: The remaining treatment time """ return self.treatment_time_remaining def get_treatment_state(self) -> int: """ Gets the current treatment state @return: The current treatment state ID """ return self.treatment_state def get_treatment_UF_state(self) -> int: """ Gets the current treatment ultrafiltration state @return: The current treatment ultrafiltration state ID """ return self.treatment_uf_state def get_treatment_saline_bolus_state(self) -> int: """ Gets the current treatment saline bolus state @return: The current treatment saline bolus state ID """ return self.saline_bolus_state def get_treatment_heparin_state(self) -> int: """ Gets the current treatment Heparin state @return: The current treatment Heparin state ID """ return self.heparin_state def get_treatment_rinseback_state(self) -> int: """ Gets the current treatment rinseback state @return: The current treatment rinseback state ID """ return self.rinseback_state def get_treatment_recirculate_state(self) -> int: """ Gets the current treatment recirculate state @return: The current treatment recirculate state ID """ return self.treatment_recirculate_state def get_treatment_blood_prime_state(self) -> int: """ 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) -> int: """ Gets the current treatment end state @return: The current treatment end state ID """ return self.treatment_end_state def get_treatment_stop_state(self) -> int: """ Gets the current treatment stop state @return: The current treatment stop state ID """ return self.treatment_stop_state def get_dialysis_state(self) -> int: """ Gets the current treatment dialysis state @return: The current treatment dialysis state ID """ return self.dialysis_state def get_saline_bolus_max_volume(self) -> int: """ Returns maximum volume (in mL) saline that can be delivered to a patient @return: The maximum saline bolus volume """ return self.saline_bolus_max_vol def get_saline_bolus_cumulative_volume_delivered(self) -> float: """ Returns cumulative volume (in mL) of saline delivered @return: The cumulative saline volume delivered """ return self.saline_bolus_cum_vol def get_saline_bolus_volume_delivered(self) -> float: """ Returns bolus volume (in mL) of saline delivered @return: The bolus saline volume delivered """ return self.saline_bolus_bol_vol def get_blood_prime_target_volume(self) -> float: """ 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) -> float: """ Returns blood prime volume (in mL) delivered @return: The blood prime volume delivered """ return self.blood_prime_cum_vol def get_rinseback_target_volume(self) -> float: """ Returns rinseback target volume (in mL) @return: The rinseback target volume """ return self.rinseback_tgt_vol def get_rinseback_volume_delivered(self) -> float: """ Returns rinseback volume (in mL) delivered @return: The rinseback volume delivered """ return self.rinseback_cum_vol def get_rinseback_current_rate(self) -> int: """ Returns rinseback current rate (in mL/min) @return: The rinseback current rate """ return self.rinseback_cur_rate def get_rinseback_timeout(self) -> int: """ Returns rinseback timeout period (in seconds) @return: The rinseback timeout period """ return self.rinseback_timeout_secs def get_rinseback_timeout_countdown(self) -> int: """ Returns rinseback timeout countdown (in seconds) @return: The rinseback timeout countdown """ return self.rinseback_countdown_secs def get_recirc_timeout(self) -> int: """ Returns recirc timeout (in seconds) @return: The recirc timeout """ return self.recirc_timeout_secs def get_recirc_timeout_countdown(self) -> int: """ Returns recirc timeout countdown (in seconds) @return: The recirc timeout countdown """ return self.recirc_countdown_secs @publish([ "treatment_time_prescribed", "treatment_time_elapsed", "treatment_time_remaining" ]) def _handler_treatment_time_sync(self, message): """ Handles published treatment time data messages. treatment time data are captured for reference. @param message: published treatment time data message @return: None """ tot = struct.unpack('i', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_1:MsgFieldPositions.END_POS_FIELD_1])) ela = struct.unpack('i', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_2:MsgFieldPositions.END_POS_FIELD_2])) rem = struct.unpack('i', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_3:MsgFieldPositions.END_POS_FIELD_3])) self.treatment_time_prescribed = tot[0] self.treatment_time_elapsed = ela[0] self.treatment_time_remaining = rem[0] @publish([ "treatment_state", "treatment_uf_state", "saline_bolus_state", "heparin_state", "rinseback_state", "treatment_recirculate_state", "blood_prime_state", "treatment_end_state", "treatment_stop_state", "dialysis_state" ]) def _handler_treatment_state_sync(self, message): """ Handles published treatment state data messages. treatment state data are captured for reference. @param message: published treatment state data message @return: none """ tst = struct.unpack('i', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_1:MsgFieldPositions.END_POS_FIELD_1])) ufs = struct.unpack('i', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_2:MsgFieldPositions.END_POS_FIELD_2])) bol = struct.unpack('i', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_3:MsgFieldPositions.END_POS_FIELD_3])) hep = struct.unpack('i', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_4:MsgFieldPositions.END_POS_FIELD_4])) rin = struct.unpack('i', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_5:MsgFieldPositions.END_POS_FIELD_5])) rec = struct.unpack('i', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_6:MsgFieldPositions.END_POS_FIELD_6])) bpr = struct.unpack('i', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_7:MsgFieldPositions.END_POS_FIELD_7])) txe = struct.unpack('i', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_8:MsgFieldPositions.END_POS_FIELD_8])) txs = struct.unpack('i', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_9:MsgFieldPositions.END_POS_FIELD_9])) dia = struct.unpack('i', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_10:MsgFieldPositions.END_POS_FIELD_10])) self.treatment_state = tst[0] self.treatment_uf_state = ufs[0] self.saline_bolus_state = bol[0] self.heparin_state = hep[0] self.rinseback_state = rin[0] self.treatment_recirculate_state = rec[0] self.blood_prime_state = bpr[0] self.treatment_end_state = txe[0] self.treatment_stop_state = txs[0] self.dialysis_state = dia[0] @publish([ "saline_bolus_max_vol", "saline_bolus_cum_vol", "saline_bolus_bol_vol" ]) def _handler_saline_bolus_data_sync(self, message): """ Handles published saline bolus data messages. Saline bolus data are captured for reference. @param message: published saline bolus data message @return: none """ mxm = struct.unpack('i', bytearray( 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])) bol = struct.unpack('f', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_3:MsgFieldPositions.END_POS_FIELD_3])) self.saline_bolus_max_vol = mxm[0] self.saline_bolus_cum_vol = cum[0] self.saline_bolus_bol_vol = bol[0] @publish([ "rinseback_tgt_vol", "rinseback_cum_vol", "rinseback_cur_rate", "rinseback_timeout_secs", "rinseback_countdown_secs" ]) def _handler_rinseback_data_sync(self, message): """ Handles published rinseback data (progress) messages. Rinseback data are captured for reference. @param message: published rinseback data message @return: none """ tgt = struct.unpack('f', bytearray( 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])) rat = struct.unpack('i', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_3:MsgFieldPositions.END_POS_FIELD_3])) tmo = struct.unpack('i', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_4:MsgFieldPositions.END_POS_FIELD_4])) cdn = struct.unpack('i', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_5:MsgFieldPositions.END_POS_FIELD_5])) self.rinseback_tgt_vol = tgt[0] self.rinseback_cum_vol = cum[0] self.rinseback_cur_rate = rat[0] self.rinseback_timeout_secs = tmo[0] self.rinseback_countdown_secs = cdn[0] @publish([ "blood_prime_tgt_vol", "blood_prime_cum_vol", "blood_prime_ind_cum_vol" ]) def _handler_blood_prime_data_sync(self, message): """ Handles published blood prime data (progress) messages. Blood prime data are captured for reference. @param message: published blood prime data message @return: none """ tgt = struct.unpack('f', bytearray( 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", "recirc_countdown_secs" ]) def _handler_recirculate_data_sync(self, message): """ Handles published recirculate data (progress) messages. Recirculate data are captured for reference. @param message: published recirculate data message @return: none """ tmo = struct.unpack('i', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_1:MsgFieldPositions.END_POS_FIELD_1])) cdn = struct.unpack('i', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_2:MsgFieldPositions.END_POS_FIELD_2])) self.recirc_timeout_secs = tmo[0] self.recirc_countdown_secs = cdn[0] @publish(["treatment_stop_timeout_secs", "treatment_stop_timeout_coundown_secs"]) def _handler_treatment_stop_timer_data_sync(self, message) -> None: """ Handles published treatment stop progress data messages. @param message: published treatment stop progress data message @return: None """ tmo = struct.unpack('i', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_1:MsgFieldPositions.END_POS_FIELD_1])) cnd = struct.unpack('i', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_2:MsgFieldPositions.END_POS_FIELD_2])) self.treatment_stop_timeout_secs = tmo[0] self.treatment_stop_timeout_coundown_secs = cnd[0] def cmd_set_treatment_param_blood_flow_rate(self, flow: int) -> int: """ Constructs and sends the set blood flow rate treatment parameter command. This will only set the treatment parameter setting. It will not immediately set the blood pump on with this set point. Constraints: Must be logged into HD. Flow must be positive integer and should be between 100 and 500 mL/min @param flow: integer - set blood flow rate (in mL/min) @return: 1 if successful, zero otherwise """ par = integer_to_bytearray(self.HD_TREATMENT_PARAMETER_BLOOD_FLOW) flo = integer_to_bytearray(flow) payload = par + flo message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=MsgIds.MSG_ID_HD_SET_PARAMETER_TREATMENT_PARAMETER.value, payload=payload) self.logger.debug("setting blood flow rate") # Send message received_message = self.can_interface.send(message) # If there is content... if received_message is not None: str_flo = str(flow) self.logger.debug("Blood flow rate parameter set to " + str_flo + " mL/min: " + 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_set_treatment_param_dialysate_flow_rate(self, flow: int) -> int: """ Constructs and sends the set dialysate flow rate treatment parameter command. This will only set the treatment parameter setting. It will not immediately set the dialysate inlet pump on with this set point. Constraints: Must be logged into HD. Flow must be positive integer and should be between 100 and 600 mL/min @param flow: integer - set blood flow rate (in mL/min) @return: 1 if successful, zero otherwise """ par = integer_to_bytearray(self.HD_TREATMENT_PARAMETER_DIALYSATE_FLOW) flo = integer_to_bytearray(flow) payload = par + flo message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=MsgIds.MSG_ID_HD_SET_PARAMETER_TREATMENT_PARAMETER.value, payload=payload) self.logger.debug("setting dialysate flow rate") # Send message received_message = self.can_interface.send(message) # If there is content... if received_message is not None: # self.logger.debug(received_message) str_flo = str(flow) self.logger.debug("Dialysate flow rate parameter set to " + str_flo + " mL/min: " + 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_set_treatment_param_duration(self, duration: int) -> int: """ Constructs and sends the set treatment duration parameter command. Constraints: Must be logged into HD. Duration must be positive integer and should be between 60 and 480 min @param duration: integer - set treatment duration (in min) @return: 1 if successful, zero otherwise """ par = integer_to_bytearray(self.HD_TREATMENT_PARAMETER_TREATMENT_DURATION) dur = integer_to_bytearray(duration) payload = par + dur message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=MsgIds.MSG_ID_HD_SET_PARAMETER_TREATMENT_PARAMETER.value, payload=payload) self.logger.debug("setting treatment duration") # Send message received_message = self.can_interface.send(message) # If there is content... if received_message is not None: # self.logger.debug(received_message) str_dur = str(duration) self.logger.debug("Treatment duration parameter set to " + str_dur + " min: " + 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_set_heparin_pre_stop_time(self, pre_stop: int) -> int: """ Constructs and sends the set Heparin pre-stop time parameter command. Constraints: Must be logged into HD. Pre-stop time for Heparin must be positive integer and should be between 0 and 120 min @param pre_stop: integer - set Heparin pre-stop time (in min) @return: 1 if successful, zero otherwise """ par = integer_to_bytearray(self.HD_TREATMENT_PARAMETER_HEPARIN_PRE_STOP_TIME) sto = integer_to_bytearray(pre_stop) payload = par + sto message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=MsgIds.MSG_ID_HD_SET_PARAMETER_TREATMENT_PARAMETER.value, payload=payload) self.logger.debug("setting Heparin pre-stop time") # Send message received_message = self.can_interface.send(message) # If there is content... if received_message is not None: # self.logger.debug(received_message) str_sto = str(pre_stop) self.logger.debug("Heparin pre-stop time parameter set to " + str_sto + " min: " + 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_set_saline_bolus_volume(self, volume: int) -> int: """ Constructs and sends the set saline bolus volume parameter command. Constraints: Must be logged into HD. Volume must be positive integer and should be between 0 and 300 mL @param volume: integer - set saline bolus volume (in mL) @return: 1 if successful, zero otherwise """ par = integer_to_bytearray(self.HD_TREATMENT_PARAMETER_SALINE_BOLUS_VOLUME) vol = integer_to_bytearray(volume) payload = par + vol message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=MsgIds.MSG_ID_HD_SET_PARAMETER_TREATMENT_PARAMETER.value, payload=payload) self.logger.debug("setting saline bolus volume") # Send message received_message = self.can_interface.send(message) # If there is content... if received_message is not None: # self.logger.debug(received_message) str_vol = str(volume) self.logger.debug("Saline bolus volume parameter set to " + str_vol + " 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_set_acid_concentrate(self, acid: int) -> int: """ Constructs and sends the set acid concentrate parameter command. Constraints: Must be logged into HD. Acid ID must be positive integer and should be between 0 and 2 (see below) ACID_CONC_TYPE_FRESENIUS_08_1251_1 = 0 ACID_CONC_TYPE_FRESENIUS_08_2251_0 = 1 ACID_CONC_TYPE_FRESENIUS_08_3251_9 = 2 @param acid: integer - set acid concentrate type @return: 1 if successful, zero otherwise """ par = integer_to_bytearray(self.HD_TREATMENT_PARAMETER_ACID_CONCENTRATE) acd = integer_to_bytearray(acid) payload = par + acd message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=MsgIds.MSG_ID_HD_SET_PARAMETER_TREATMENT_PARAMETER.value, payload=payload) self.logger.debug("setting acid concentrate parameter") # Send message received_message = self.can_interface.send(message) # If there is content... if received_message is not None: # self.logger.debug(received_message) str_acd = str(acid) self.logger.debug("Acid concentrate parameter set to " + str_acd + ": " + 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_set_bicarb_concentrate(self, bicarb: int) -> int: """ Constructs and sends the set bicarbonate concentrate parameter command. Constraints: Must be logged into HD. Bicarb ID must be positive integer and should be between 0 and 0 (see below) BICARB_CONC_TYPE_FRESENIUS_CENTRISOL = 0 @param bicarb: integer - set bicarbonate concentrate type @return: 1 if successful, zero otherwise """ par = integer_to_bytearray(self.HD_TREATMENT_PARAMETER_BICARB_CONCENTRATE) bic = integer_to_bytearray(bicarb) payload = par + bic message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=MsgIds.MSG_ID_HD_SET_PARAMETER_TREATMENT_PARAMETER.value, payload=payload) self.logger.debug("setting bicarbonate concentrate parameter") # Send message received_message = self.can_interface.send(message) # If there is content... if received_message is not None: # self.logger.debug(received_message) str_bic = str(bicarb) self.logger.debug("Bicarbonate concentrate parameter set to " + str_bic + ": " + 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_set_dialyzer_type(self, dialyzer: int) -> int: """ Constructs and sends the set dialyzer type parameter command. Constraints: Must be logged into HD. Dialyzer ID must be positive integer and should be between 0 and 3 (see below) DIALYZER_TYPE_NIPRO_ELISIO_H_17 = 0 DIALYZER_TYPE_NIPRO_ELISIO_H_19 = 1 DIALYZER_TYPE_FRESENIUS_OPTIFLUX_F160NRE = 2 DIALYZER_TYPE_FRESENIUS_OPTIFLUX_F180NRE = 3 @param dialyzer: integer - set dialyzer type @return: 1 if successful, zero otherwise """ par = integer_to_bytearray(self.HD_TREATMENT_PARAMETER_DIALYZER_TYPE) dia = integer_to_bytearray(dialyzer) payload = par + dia message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=MsgIds.MSG_ID_HD_SET_PARAMETER_TREATMENT_PARAMETER.value, payload=payload) self.logger.debug("setting dialyzer type parameter") # Send message received_message = self.can_interface.send(message) # If there is content... if received_message is not None: # self.logger.debug(received_message) str_dia = str(dialyzer) self.logger.debug("Dialyzer type parameter set to " + str_dia + ": " + 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_set_bp_measurement_interval(self, intvl: int) -> int: """ Constructs and sends the set blood pressure measurement interval parameter command. Constraints: Must be logged into HD. Interval must be positive integer and should be between 0 and 60 min @param intvl: integer - set blood pressure measurement interval (in min) @return: 1 if successful, zero otherwise """ par = integer_to_bytearray(self.HD_TREATMENT_PARAMETER_BP_MEAS_INTERVAL) bpi = integer_to_bytearray(intvl) payload = par + bpi message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=MsgIds.MSG_ID_HD_SET_PARAMETER_TREATMENT_PARAMETER.value, payload=payload) self.logger.debug("setting BP measurement interval parameter") # Send message received_message = self.can_interface.send(message) # If there is content... if received_message is not None: # self.logger.debug(received_message) str_bpi = str(intvl) self.logger.debug("BP measurement interval parameter set to " + str_bpi + ": " + 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_set_rinseback_flow_rate(self, flow: int) -> int: """ Constructs and sends the set rinseback flow rate parameter command. Constraints: Must be logged into HD. Flow must be positive integer and should be between 50 and 175 mL/min @param flow: integer - set rinseback flow rate (in mL/min) @return: 1 if successful, zero otherwise """ par = integer_to_bytearray(self.HD_TREATMENT_PARAMETER_RINSEBACK_FLOW_RATE) flo = integer_to_bytearray(flow) payload = par + flo message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=MsgIds.MSG_ID_HD_SET_PARAMETER_TREATMENT_PARAMETER.value, payload=payload) self.logger.debug("setting rinseback flow rate parameter") # Send message received_message = self.can_interface.send(message) # If there is content... if received_message is not None: # self.logger.debug(received_message) str_flo = str(flow) self.logger.debug("Rinseback flow rate parameter set to " + str_flo + ": " + 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_set_arterial_pressure_low_alarm_limit(self, pres: int) -> int: """ Constructs and sends the set arterial pressure lower alarm limit parameter command. Constraints: Must be logged into HD. Pressure must be integer and should be between -300 and +0 mmHg @param pres: integer - set arterial pressure lower alarm limit (in mmHg) @return: 1 if successful, zero otherwise """ par = integer_to_bytearray(self.HD_TREATMENT_PARAMETER_ART_PRESSURE_LOW_LIMIT) pre = integer_to_bytearray(pres) payload = par + pre message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=MsgIds.MSG_ID_HD_SET_PARAMETER_TREATMENT_PARAMETER.value, payload=payload) self.logger.debug("setting arterial pressure lower alarm limit parameter") # Send message received_message = self.can_interface.send(message) # If there is content... if received_message is not None: # self.logger.debug(received_message) str_pre = str(pres) self.logger.debug("Arterial pressure lower alarm limit parameter set to " + str_pre + ": " + 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_set_arterial_pressure_high_alarm_limit(self, pres: int) -> int: """ Constructs and sends the set arterial pressure upper alarm limit parameter command. Constraints: Must be logged into HD. Pressure must be integer and should be between -300 and +0 mmHg @param pres: integer - set arterial pressure upper alarm limit (in mmHg) @return: 1 if successful, zero otherwise """ par = integer_to_bytearray(self.HD_TREATMENT_PARAMETER_ART_PRESSURE_HIGH_LIMIT) pre = integer_to_bytearray(pres) payload = par + pre message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=MsgIds.MSG_ID_HD_SET_PARAMETER_TREATMENT_PARAMETER.value, payload=payload) self.logger.debug("setting arterial pressure upper alarm limit parameter") # Send message received_message = self.can_interface.send(message) # If there is content... if received_message is not None: # self.logger.debug(received_message) str_pre = str(pres) self.logger.debug("Arterial pressure upper alarm limit parameter set to " + str_pre + ": " + 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_set_venous_pressure_low_alarm_limit(self, pres: int) -> int: """ Constructs and sends the set venous pressure lower alarm limit parameter command. Constraints: Must be logged into HD. Pressure must be integer and should be between +20 and +600 mmHg @param pres: integer - set venous pressure lower alarm limit (in mmHg) @return: 1 if successful, zero otherwise """ par = integer_to_bytearray(self.HD_TREATMENT_PARAMETER_VEN_PRESSURE_LOW_LIMIT) pre = integer_to_bytearray(pres) payload = par + pre message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=MsgIds.MSG_ID_HD_SET_PARAMETER_TREATMENT_PARAMETER.value, payload=payload) self.logger.debug("setting venous pressure lower alarm limit parameter") # Send message received_message = self.can_interface.send(message) # If there is content... if received_message is not None: # self.logger.debug(received_message) str_pre = str(pres) self.logger.debug("Venous pressure lower alarm limit parameter set to " + str_pre + ": " + 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_set_venous_pressure_high_alarm_limit(self, pres: int) -> int: """ Constructs and sends the set venous pressure upper alarm limit parameter command. Constraints: Must be logged into HD. Pressure must be integer and should be between +20 and +600 mmHg @param pres: integer - set venous pressure upper alarm limit (in mmHg) @return: 1 if successful, zero otherwise """ par = integer_to_bytearray(self.HD_TREATMENT_PARAMETER_VEN_PRESSURE_HIGH_LIMIT) pre = integer_to_bytearray(pres) payload = par + pre message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=MsgIds.MSG_ID_HD_SET_PARAMETER_TREATMENT_PARAMETER.value, payload=payload) self.logger.debug("setting venous pressure upper alarm limit parameter") # Send message received_message = self.can_interface.send(message) # If there is content... if received_message is not None: # self.logger.debug(received_message) str_pre = str(pres) self.logger.debug("Venous pressure upper alarm limit parameter set to " + str_pre + ": " + 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_set_heparin_dispense_rate(self, rate: float) -> int: """ Constructs and sends the set Heparin dispense rate parameter command. Constraints: Must be logged into HD. Rate must be floating point value and should be between 0 and 1.0 mL/hr @param rate: float - set Heparin dispense rate (in mL/hr) @return: 1 if successful, zero otherwise """ par = integer_to_bytearray(self.HD_TREATMENT_PARAMETER_HEPARIN_DISPENSE_RATE) rat = float_to_bytearray(rate) payload = par + rat message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=MsgIds.MSG_ID_HD_SET_PARAMETER_TREATMENT_PARAMETER.value, payload=payload) self.logger.debug("setting Heparin dispense rate parameter") # Send message received_message = self.can_interface.send(message) # If there is content... if received_message is not None: # self.logger.debug(received_message) str_rat = str(rate) self.logger.debug("Heparin dispense rate parameter set to " + str_rat + ": " + 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_set_heparin_bolus_volume(self, volume: float) -> int: """ Constructs and sends the set Heparin bolus volume parameter command. Constraints: Must be logged into HD. Volume must be floating point value and should be between 0 and 2.0 mL @param volume: float - set Heparin bolus volume (in mL) @return: 1 if successful, zero otherwise """ par = integer_to_bytearray(self.HD_TREATMENT_PARAMETER_HEPARIN_BOLUS_VOLUME) vol = float_to_bytearray(volume) payload = par + vol message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=MsgIds.MSG_ID_HD_SET_PARAMETER_TREATMENT_PARAMETER.value, payload=payload) self.logger.debug("setting Heparin bolus volume parameter") # Send message received_message = self.can_interface.send(message) # If there is content... if received_message is not None: # self.logger.debug(received_message) str_vol = str(volume) self.logger.debug("Heparin bolus volume parameter set to " + str_vol + ": " + 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_set_dialysate_temperature(self, temp: float) -> int: """ Constructs and sends the set dialysate temperature parameter command. Constraints: Must be logged into HD. Temperature must be floating point value and should be between 35.0 and 38.0 deg C @param temp: float - set dialysate temperature (in deg C) @return: 1 if successful, zero otherwise """ par = integer_to_bytearray(self.HD_TREATMENT_PARAMETER_DIALYSATE_TEMPERATURE) tmp = float_to_bytearray(temp) payload = par + tmp message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=MsgIds.MSG_ID_HD_SET_PARAMETER_TREATMENT_PARAMETER.value, payload=payload) self.logger.debug("setting dialysate temperature parameter") # Send message received_message = self.can_interface.send(message) # If there is content... if received_message is not None: # self.logger.debug(received_message) str_tmp = str(temp) self.logger.debug("Dialysate temperature parameter set to " + str_tmp + ": " + 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_set_ultrafiltration_volume(self, volume: float) -> int: """ Constructs and sends the set ultrafiltration volume parameter command. Constraints: Must be logged into HD. Volume must be floating point value and should be between 0.0 and 8.0L @param volume: float - set ultrafiltration volume (in L) @return: 1 if successful, zero otherwise """ par = integer_to_bytearray(self.HD_TREATMENT_PARAMETER_UF_VOLUME) vol = float_to_bytearray(volume) payload = par + vol message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=MsgIds.MSG_ID_HD_SET_PARAMETER_TREATMENT_PARAMETER.value, payload=payload) self.logger.debug("setting ultrafiltration volume parameter") # Send message received_message = self.can_interface.send(message) # If there is content... if received_message is not None: # self.logger.debug(received_message) str_vol = str(volume) self.logger.debug("Ultrafiltration volume parameter set to " + str_vol + ": " + 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_treatment_time_remaining_override(self, secs_remaining: int) -> int: """ Constructs and sends the treatment time remaining override command Constraints: Must be logged into HD. @param secs_remaining: integer - number of seconds remaining (must be positive) @return: 1 if successful, zero otherwise """ payload = integer_to_bytearray(secs_remaining) message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=MsgIds.MSG_ID_TREATMENT_TIME_REMAINING_OVERRIDE.value, payload=payload) self.logger.debug("override HD treatment time remaining (in seconds).") # Send message received_message = self.can_interface.send(message) # If there is content... if received_message is not None: self.logger.debug("Treatment time remaining overridden to " + str(secs_remaining) + " seconds. " + 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_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_rinseback_volume_delivered_override(self, volume: float, reset: int = NO_RESET) -> int: """ Constructs and sends the rinseback volume delivered override command Constraints: Must be logged into HD. @param volume: float - volume (in mL) of blood returned during rinseback (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_RINSEBACK_VOLUME_OVERRIDE.value, payload=payload) self.logger.debug("override HD rinseback 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("Rinseback 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_submode_broadcast_interval_override(self, ms: int = 250, reset: int = NO_RESET): """ Constructs and sends the treatment blood prime sub-mode broadcast interval override command Constraints: Must be logged into HD. Given interval must be non-zero and a multiple of the HD general task interval (50 ms). @param ms: integer - interval (in ms) to override with @param reset: integer - 1 to reset a previous override, 0 to override @return: 1 if successful, zero otherwise """ if not check_broadcast_interval_override_ms(ms): return False rst = integer_to_bytearray(reset) mis = integer_to_bytearray(ms) payload = rst + mis message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=MsgIds.MSG_ID_HD_BLOOD_PRIME_DATA_PUBLISH_INTERVAL_OVERRIDE.value, payload=payload) self.logger.debug("override treatment blood prime sub-mode data broadcast interval") # Send message received_message = self.can_interface.send(message) # If there is content... if received_message is not None: if reset == RESET: str_res = "reset back to normal: " else: str_res = str(ms) + " ms: " self.logger.debug("Treatment blood prime sub-mode data broadcast interval overridden to " + str_res + 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_treatment_stop_submode_broadcast_interval_override(self, ms: int = 250, reset: int = NO_RESET): """ Constructs and sends the treatment stop sub-mode broadcast interval override command Constraints: Must be logged into HD. Given interval must be non-zero and a multiple of the HD general task interval (50 ms). @param ms: integer - interval (in ms) to override with @param reset: integer - 1 to reset a previous override, 0 to override @return: 1 if successful, zero otherwise """ if not check_broadcast_interval_override_ms(ms): return False rst = integer_to_bytearray(reset) mis = integer_to_bytearray(ms) payload = rst + mis message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=MsgIds.MSG_ID_HD_TREATMENT_STOP_DATA_PUBLISH_INTERVAL_OVERRIDE.value, payload=payload) self.logger.debug("override treatment stop sub-mode data broadcast interval") # Send message received_message = self.can_interface.send(message) # If there is content... if received_message is not None: if reset == RESET: str_res = "reset back to normal: " else: str_res = str(ms) + " ms: " self.logger.debug("Treatment stop sub-mode data broadcast interval overridden to " + str_res + 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_rinseback_broadcast_interval_override(self, ms: int = 250, reset: int = NO_RESET): """ Constructs and sends the treatment rinseback sub-mode broadcast interval override command Constraints: Must be logged into HD. Given interval must be non-zero and a multiple of the HD general task interval (50 ms). @param ms: integer - interval (in ms) to override with @param reset: integer - 1 to reset a previous override, 0 to override @return: 1 if successful, zero otherwise """ if not check_broadcast_interval_override_ms(ms): return False rst = integer_to_bytearray(reset) mis = integer_to_bytearray(ms) payload = rst + mis message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=MsgIds.MSG_ID_HD_RINSEBACK_DATA_PUBLISH_INTERVAL_OVERRIDE.value, payload=payload) self.logger.debug("override treatment rinseback sub-mode data broadcast interval") # Send message received_message = self.can_interface.send(message) # If there is content... if received_message is not None: if reset == RESET: str_res = "reset back to normal: " else: str_res = str(ms) + " ms: " self.logger.debug("Treatment rinseback sub-mode data broadcast interval overridden to " + str_res + 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_treatment_param_ranges_broadcast_interval_override(self, ms: int = 60000, reset: int = NO_RESET): """ Constructs and sends the treatment parameter ranges broadcast interval override command Constraints: Must be logged into HD. Given interval must be non-zero and a multiple of the HD general task interval (50 ms). @param ms: integer - interval (in ms) to override with @param reset: integer - 1 to reset a previous override, 0 to override @return: 1 if successful, zero otherwise """ if not check_broadcast_interval_override_ms(ms): return False rst = integer_to_bytearray(reset) mis = integer_to_bytearray(ms) payload = rst + mis message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=MsgIds.MSG_ID_HD_TREATMENT_RANGES_PUBLISH_INTERVAL_OVERRIDE.value, payload=payload) self.logger.debug("override treatment parameter ranges data broadcast interval") # Send message received_message = self.can_interface.send(message) # If there is content... if received_message is not None: if reset == RESET: str_res = "reset back to normal: " else: str_res = str(ms) + " ms: " self.logger.debug("Treatment parameter ranges data broadcast interval overridden to " + str_res + 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_treatment_time_broadcast_interval_override(self, ms: int = 250, reset: int = NO_RESET): """ Constructs and sends the treatment time data broadcast interval override command Constraints: Must be logged into HD. Given interval must be non-zero and a multiple of the HD general task interval (50 ms). @param ms: integer - interval (in ms) to override with @param reset: integer - 1 to reset a previous override, 0 to override @return: 1 if successful, zero otherwise """ if not check_broadcast_interval_override_ms(ms): return False rst = integer_to_bytearray(reset) mis = integer_to_bytearray(ms) payload = rst + mis message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=MsgIds.MSG_ID_HD_TREATMENT_TIME_DATA_PUBLISH_INTERVAL_OVERRIDE.value, payload=payload) self.logger.debug("override treatment time data broadcast interval") # Send message received_message = self.can_interface.send(message) # If there is content... if received_message is not None: if reset == RESET: str_res = "reset back to normal: " else: str_res = str(ms) + " ms: " self.logger.debug("Treatment time data broadcast interval overridden to " + str_res + 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