Index: dialin/hd/ui_proxy.py =================================================================== diff -u -rcd9d98248537d10d9cf188307ae2237c8cf8e6e4 -r3b2f75c25b2f794d171c49487afcf72c9552431e --- dialin/hd/ui_proxy.py (.../ui_proxy.py) (revision cd9d98248537d10d9cf188307ae2237c8cf8e6e4) +++ dialin/hd/ui_proxy.py (.../ui_proxy.py) (revision 3b2f75c25b2f794d171c49487afcf72c9552431e) @@ -17,6 +17,7 @@ DenaliChannels) from ..utils.conversions import integer_to_bytearray, float_to_bytearray import struct +import enum from ..utils.base import _AbstractSubSystem, _publish from ..common.msg_defs import MsgIds, RequestRejectReasons, MsgFldPositions from collections import OrderedDict @@ -67,6 +68,32 @@ START_POS_FPGA_LAB = END_POS_FPGA_MINOR END_POS_FPGA_LAB = START_POS_FPGA_LAB + 1 + class TreatmentParameters(enum.Enum): + + TREATMENT_PARAM_BLOOD_FLOW_RATE_ML_MIN = 0 + TREATMENT_PARAM_DIALYSATE_FLOW_RATE_ML_MIN = 1 + TREATMENT_PARAM_TREATMENT_DURATION_MIN = 2 + TREATMENT_PARAM_HEPARIN_PRESTOP_MIN = 3 + TREATMENT_PARAM_SALINE_BOLUS_VOLUME_ML = 4 + TREATMENT_PARAM_ACID_CONCENTRATE = 5 + TREATMENT_PARAM_BICARB_CONCENTRATE = 6 + TREATMENT_PARAM_DIALYZER_TYPE = 7 + TREATMENT_PARAM_BLOOD_PRESSURE_MEAS_INTERVAL_MIN = 8 + TREATMENT_PARAM_RINSEBACK_FLOW_RATE_ML_MIN = 9 + TREATMENT_PARAM_ARTERIAL_PRESSURE_LOW_LIMIT_MMHG = 10 + TREATMENT_PARAM_ARTERIAL_PRESSURE_HIGH_LIMIT_MMHG = 11 + TREATMENT_PARAM_VENOUS_PRESSURE_LOW_LIMIT_MMHG = 12 + TREATMENT_PARAM_VENOUS_PRESSURE_HIGH_LIMIT_MMHG = 13 + TREATMENT_PARAM_HEPARIN_DISPENSE_RATE_ML_HR = 14 + TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME_ML = 15 + TREATMENT_PARAM_DIALYSATE_TEMPERATURE_C = 16 + TREATMENT_PARAM_UF_VOLUME_L = 17 + NUM_OF_TREATMENT_PARAMS = 18 + + @classmethod + def has_value(cls, value): + return value in cls._value2member_map_ + def __init__(self, can_interface, logger: Logger): """ @@ -96,51 +123,21 @@ self._handler_treatment_param_ranges) self.can_interface.register_receiving_publication_function(DenaliChannels.hd_to_ui_ch_id, MsgIds.MSG_ID_HD_VERSION.value, self._handler_hd_version) - self.can_interface.register_receiving_publication_function(DenaliChannels.hd_to_ui_ch_id, MsgIds.MSG_ID_HD_NEW_TREATMENT_PARAMS_RESPONSE.value, + self.can_interface.register_receiving_publication_function(DenaliChannels.hd_to_ui_ch_id, MsgIds.MSG_ID_UI_NEW_TREATMENT_PARAMS.value, self._handler_treatment_param_settings) + self.can_interface.register_receiving_publication_function(DenaliChannels.hd_to_ui_ch_id, MsgIds.MSG_ID_HD_NEW_TREATMENT_PARAMS_RESPONSE.value, + self._handler_treatment_param_settings_response) self.can_interface.register_receiving_publication_function(DenaliChannels.hd_to_ui_ch_id, MsgIds.MSG_ID_USER_SALINE_BOLUS_RESPONSE.value, self._handler_saline_bolus_response) # initialize variables that will be populated by HD version response self.hd_version = None self.fpga_version = None - # initialize treatment parameters that Dialin user sets - self.blood_flow_rate = 0 - self.dialysate_flow_rate = 0 - self.treatment_duration = 0 - self.heparin_dispense_rate = 0.0 - self.heparin_bolus_volume = 0.0 - self.heparin_pre_stop_time = 0 - self.saline_bolus_volume = 0 - self.acid_concentrate = 0 - self.bicarb_concentrate = 0 - self.dialyzer_type = 0 - self.dialysate_temperature = 0.0 - self.arterial_pressure_low_alarm_limit = 0 - self.arterial_pressure_high_alarm_limit = 0 - self.venous_pressure_low_alarm_limit = 0 - self.venous_pressure_high_alarm_limit = 0 - self.blood_pressure_meas_interval = 0 - self.rinseback_flow_rate = 0 + # initialize treatment parameters that are seen from UI or that Dialin user sets + self.treatment_parameters = [0.0] * self.TreatmentParameters.NUM_OF_TREATMENT_PARAMS.value # initialize variables that will be populated by treatment parameters response message self.treatment_parameters_valid = False - self.blood_flow_rate_reject_reason = 0 - self.dialysate_flow_rate_reject_reason = 0 - self.treatment_duration_reject_reason = 0 - self.heparin_dispense_rate_reject_reason = 0 - self.heparin_bolus_volume_reject_reason = 0 - self.heparin_pre_stop_time_reject_reason = 0 - self.saline_bolus_volume_reject_reason = 0 - self.acid_concentrate_reject_reason = 0 - self.bicarb_concentrate_reject_reason = 0 - self.dialyzer_type_reject_reason = 0 - self.dialysate_temperature_reject_reason = 0 - self.arterial_pressure_low_alarm_limit_reject_reason = 0 - self.arterial_pressure_high_alarm_limit_reject_reason = 0 - self.venous_pressure_low_alarm_limit_reject_reason = 0 - self.venous_pressure_high_alarm_limit_reject_reason = 0 - self.blood_pressure_meas_interval_reject_reason = 0 - self.rinseback_flow_rate_reject_reason = 0 + self.treatment_parameters_reject_reasons = [0] * self.TreatmentParameters.NUM_OF_TREATMENT_PARAMS.value # initialize variables that will be populated by treatment parameter ranges message self.min_treatment_duration_min = 0 self.max_treatment_duration_min = 0 @@ -194,6 +191,14 @@ """ return self.fpga_version + def get_treatment_parameters(self): + """ + Gets the array of treatment parameters set by user or Dialin + + @return: the array of treatment parameters + """ + return self.treatment_parameters + def get_min_treatment_duration_min(self): """ Gets the min treatment duration @@ -377,6 +382,15 @@ """ return self.treatment_parameters_valid + def get_treatment_parameters_reject_reasons(self): + """ + Gets the reject reason codes for the treatment parameters + sent to the HD for validation. + + @return: The array of reject reason codes for all treatment parameters + """ + return self.treatment_parameters_reject_reasons + def get_blood_flow_rate_reject_reason(self): """ Gets the reject reason code for the blood flow rate @@ -589,6 +603,87 @@ self.logger.debug(f"HD FPGA VERSION: {self.fpga_version}") @_publish([ + "treatment_parameters" + ]) + def _handler_treatment_param_settings(self, message): + """ + Handler for UI msg containing user set treatment parameters. + + @param message: message from UI to HD containing user selected treatment parameters.\n + U32 blood flow rate. \n + U32 dialysate flow rate. \n + U32 treatment duration. \n + U32 Heparin pre-stop time. \n + U32 saline bolus volume. \n + U32 acid concentrate. \n + U32 bicarb concentrate. \n + U32 dialyzer type. \n + U32 BP measurement interval. \n + U32 rinseback flow rate. \n + S32 arterial pressure low alarm limit. \n + S32 arterial pressure high alarm limit. \n + S32 venous pressure low alarm limit. \n + S32 venous pressure high alarm limit. \n + F32 Heparin dispense rate. \n + F32 Heparin bolus volume. \n + F32 dialysate temperature. \n + + @return: none + """ + bld = struct.unpack('i', bytearray( + message['message'][MsgFldPositions.START_POS_FIELD_1:MsgFldPositions.END_POS_FIELD_1])) + dia = struct.unpack('i', bytearray( + message['message'][MsgFldPositions.START_POS_FIELD_2:MsgFldPositions.END_POS_FIELD_2])) + dur = struct.unpack('i', bytearray( + message['message'][MsgFldPositions.START_POS_FIELD_3:MsgFldPositions.END_POS_FIELD_3])) + sto = struct.unpack('i', bytearray( + message['message'][MsgFldPositions.START_POS_FIELD_4:MsgFldPositions.END_POS_FIELD_4])) + sal = struct.unpack('i', bytearray( + message['message'][MsgFldPositions.START_POS_FIELD_5:MsgFldPositions.END_POS_FIELD_5])) + acd = struct.unpack('i', bytearray( + message['message'][MsgFldPositions.START_POS_FIELD_6:MsgFldPositions.END_POS_FIELD_6])) + bic = struct.unpack('i', bytearray( + message['message'][MsgFldPositions.START_POS_FIELD_7:MsgFldPositions.END_POS_FIELD_7])) + dlz = struct.unpack('i', bytearray( + message['message'][MsgFldPositions.START_POS_FIELD_8:MsgFldPositions.END_POS_FIELD_8])) + bpi = struct.unpack('i', bytearray( + message['message'][MsgFldPositions.START_POS_FIELD_9:MsgFldPositions.END_POS_FIELD_9])) + rbf = struct.unpack('i', bytearray( + message['message'][MsgFldPositions.START_POS_FIELD_10:MsgFldPositions.END_POS_FIELD_10])) + apl = struct.unpack('i', bytearray( + message['message'][MsgFldPositions.START_POS_FIELD_11:MsgFldPositions.END_POS_FIELD_11])) + aph = struct.unpack('i', bytearray( + message['message'][MsgFldPositions.START_POS_FIELD_12:MsgFldPositions.END_POS_FIELD_12])) + vpl = struct.unpack('i', bytearray( + message['message'][MsgFldPositions.START_POS_FIELD_13:MsgFldPositions.END_POS_FIELD_13])) + vph = struct.unpack('i', bytearray( + message['message'][MsgFldPositions.START_POS_FIELD_14:MsgFldPositions.END_POS_FIELD_14])) + hdr = struct.unpack('f', bytearray( + message['message'][MsgFldPositions.START_POS_FIELD_15:MsgFldPositions.END_POS_FIELD_15])) + hbv = struct.unpack('f', bytearray( + message['message'][MsgFldPositions.START_POS_FIELD_16:MsgFldPositions.END_POS_FIELD_16])) + tmp = struct.unpack('f', bytearray( + message['message'][MsgFldPositions.START_POS_FIELD_17:MsgFldPositions.END_POS_FIELD_17])) + + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_BLOOD_FLOW_RATE_ML_MIN.value] = bld[0] + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_DIALYSATE_FLOW_RATE_ML_MIN.value] = dia[0] + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_TREATMENT_DURATION_MIN.value] = dur[0] + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_HEPARIN_PRESTOP_MIN.value] = sto[0] + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_SALINE_BOLUS_VOLUME_ML.value] = sal[0] + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_ACID_CONCENTRATE.value] = acd[0] + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_BICARB_CONCENTRATE.value] = bic[0] + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_DIALYZER_TYPE.value] = dlz[0] + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_BLOOD_PRESSURE_MEAS_INTERVAL_MIN.value] = bpi[0] + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_RINSEBACK_FLOW_RATE_ML_MIN.value] = rbf[0] + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_ARTERIAL_PRESSURE_LOW_LIMIT_MMHG.value] = apl[0] + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_ARTERIAL_PRESSURE_HIGH_LIMIT_MMHG.value] = aph[0] + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_VENOUS_PRESSURE_LOW_LIMIT_MMHG.value] = vpl[0] + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_VENOUS_PRESSURE_HIGH_LIMIT_MMHG.value] = vph[0] + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_HEPARIN_DISPENSE_RATE_ML_HR.value] = hdr[0] + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME_ML.value] = hbv[0] + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_DIALYSATE_TEMPERATURE_C.value] = tmp[0] + + @_publish([ "treatment_parameters_valid", "blood_flow_rate_reject_reason", "dialysate_flow_rate_reject_reason", @@ -608,7 +703,7 @@ "heparin_bolus_volume_reject_reason", "dialysate_temperature_reject_reason" ]) - def _handler_treatment_param_settings(self, message): + def _handler_treatment_param_settings_response(self, message): """ Handler for response from HD regarding validation of treatment parameters. @@ -1107,6 +1202,43 @@ return 0 + def set_a_treatment_parameter(self, param_idx, value): + """ + Constructs and sends a set treatment parameter message + Constraints: + Must be logged into HD. + + @param param_idx: (int) index/enum of parameter to set (see TreatmentParameters enum) + @param value: (int or float - depends on param_idx) value to set for given treatment parameter + + @return: none + """ + if self.TreatmentParameters.has_value(param_idx): + self.treatment_parameters[self.TreatmentParameters(param_idx)] = value + idx = integer_to_bytearray(param_idx) + if param_idx == self.TreatmentParameters.TREATMENT_PARAM_HEPARIN_DISPENSE_RATE_ML_HR.value: + val = float_to_bytearray(value) + elif param_idx == self.TreatmentParameters.TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME_ML.value: + val = float_to_bytearray(value) + elif param_idx == self.TreatmentParameters.TREATMENT_PARAM_DIALYSATE_TEMPERATURE_C.value: + val = float_to_bytearray(value) + elif param_idx == self.TreatmentParameters.TREATMENT_PARAM_UF_VOLUME_L.value: + val = float_to_bytearray(value) + else: + val = integer_to_bytearray(value) + payload = idx+val + 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 parameter " + param_idx + " to " + value + ".") + self.can_interface.send(message, 0) + else: + self.logger.debug("Invalid param_idx given.") + + + + return 0 + def set_treatment_parameters(self, bld_flow, dia_flow, duration, hep_rate, hep_bol, hep_stop, sal_bol, acid, bicarb, dialyzer, dia_temp, art_low, art_high, ven_low, ven_high, bp_intvl, rb_flow): @@ -1135,23 +1267,23 @@ @return: none """ - self.blood_flow_rate = bld_flow - self.dialysate_flow_rate = dia_flow - self.treatment_duration = duration - self.heparin_pre_stop_time = hep_stop - self.saline_bolus_volume = sal_bol - self.acid_concentrate = acid - self.bicarb_concentrate = bicarb - self.dialyzer_type = dialyzer - self.blood_pressure_meas_interval = bp_intvl - self.rinseback_flow_rate = rb_flow - self.arterial_pressure_low_alarm_limit = art_low - self.arterial_pressure_high_alarm_limit = art_high - self.venous_pressure_low_alarm_limit = ven_low - self.venous_pressure_high_alarm_limit = ven_high - self.heparin_dispense_rate = hep_rate - self.heparin_bolus_volume = hep_bol - self.dialysate_temperature = dia_temp + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_BLOOD_FLOW_RATE_ML_MIN.value] = bld_flow + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_DIALYSATE_FLOW_RATE_ML_MIN.value] = dia_flow + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_TREATMENT_DURATION_MIN.value] = duration + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_HEPARIN_PRESTOP_MIN.value] = hep_stop + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_SALINE_BOLUS_VOLUME_ML.value] = sal_bol + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_ACID_CONCENTRATE.value] = acid + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_BICARB_CONCENTRATE.value] = bicarb + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_DIALYZER_TYPE.value] = dialyzer + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_BLOOD_PRESSURE_MEAS_INTERVAL_MIN.value] = bp_intvl + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_RINSEBACK_FLOW_RATE_ML_MIN.value] = rb_flow + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_ARTERIAL_PRESSURE_LOW_LIMIT_MMHG.value] = art_low + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_ARTERIAL_PRESSURE_HIGH_LIMIT_MMHG.value] = art_high + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_VENOUS_PRESSURE_LOW_LIMIT_MMHG.value] = ven_low + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_VENOUS_PRESSURE_HIGH_LIMIT_MMHG.value] = ven_high + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_HEPARIN_DISPENSE_RATE_ML_HR.value] = hep_rate + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME_ML.value] = hep_bol + self.treatment_parameters[self.TreatmentParameters.TREATMENT_PARAM_DIALYSATE_TEMPERATURE_C.value] = dia_temp bld = integer_to_bytearray(bld_flow) dia = integer_to_bytearray(dia_flow)