########################################################################### # # Copyright (c) 2019-2020 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 ui.py # # @date 31-Mar-2020 # @author P. Lucia # # @brief # # ############################################################################ from ..protocols.CAN import (DenaliMessage, DenaliChannels) from ..utils.conversions import integer_to_bytearray, float_to_bytearray import struct from ..utils.base import _AbstractSubSystem, _publish class HDUIProxy(_AbstractSubSystem): """ Hemodialysis Device (HD) Dialin API sub-class for ui commands. """ # ui message IDs MSG_ID_UI_CHECKIN_WITH_HD = 0x0007 MSG_ID_HD_UF_PAUSE_RESUME_REQUEST = 0x0010 MSG_ID_HD_TREATMENT_PARAMS_RANGES = 0x001A MSG_ID_UF_SETTINGS_CHANGE_REQUEST_BY_USER = 0x0011 MSG_ID_UF_SETTINGS_CHANGE_RESPONSE_FROM_HD = 0x0013 MSG_ID_UF_SETTINGS_CHANGE_CONFIRMED_BY_USER = 0x0015 MSG_ID_TREATMENT_DURATION_SETTING_CHANGE_REQUEST = 0x0016 MSG_ID_TREATMENT_DURATION_SETTING_CHANGE_RESPONSE_FROM_HD = 0x001B MSG_ID_BLOOD_DIALYSATE_FLOW_SETTING_CHANGE_REQUEST_BY_USER = 0x0017 MSG_ID_BLOOD_DIALYSATE_FLOW_SETTING_CHANGE_RESPONSE_FROM_HD = 0x0018 MSG_ID_UI_REQUEST_HD_VERSION = 0x001C MSG_ID_UI_HD_VERSION_RESPONSE = 0x001D LITER_TO_ML_CONVERSION_FACTOR = 1000.0 UF_CMD_PAUSE = 0 UF_CMD_RESUME = 1 UF_CMD_CHANGE_TIME_TO_ADJUST = 0 UF_CMD_CHANGE_RATE_TO_ADJUST = 1 RESPONSE_REJECTED = 0 RESPONSE_ACCEPTED = 1 # HD version message field positions START_POS_MAJOR = DenaliMessage.PAYLOAD_START_INDEX END_POS_MAJOR = START_POS_MAJOR + 1 START_POS_MINOR = END_POS_MAJOR END_POS_MINOR = START_POS_MINOR + 1 START_POS_MICRO = END_POS_MINOR END_POS_MICRO = START_POS_MICRO + 1 START_POS_BUILD = END_POS_MICRO END_POS_BUILD = START_POS_BUILD + 2 # HD update on valid treatment parameter ranges message field positions START_POS_MIN_TREAT_TIME = DenaliMessage.PAYLOAD_START_INDEX END_POS_MIN_TREAT_TIME = START_POS_MIN_TREAT_TIME + 4 START_POS_MAX_TREAT_TIME = END_POS_MIN_TREAT_TIME END_POS_MAX_TREAT_TIME = START_POS_MAX_TREAT_TIME + 4 START_POS_MIN_UF_VOL = END_POS_MAX_TREAT_TIME END_POS_MIN_UF_VOL = START_POS_MIN_UF_VOL + 4 START_POS_MAX_UF_VOL = END_POS_MIN_UF_VOL END_POS_MAX_UF_VOL = START_POS_MAX_UF_VOL + 4 START_POS_MIN_DIAL_RATE = END_POS_MAX_UF_VOL END_POS_MIN_DIAL_RATE = START_POS_MIN_DIAL_RATE + 4 START_POS_MAX_DIAL_RATE = END_POS_MIN_DIAL_RATE END_POS_MAX_DIAL_RATE = START_POS_MAX_DIAL_RATE + 4 # HD response to treatment duration change request message field positions START_POS_TIME_CHG_RSP_ACCEPTED = DenaliMessage.PAYLOAD_START_INDEX END_POS_TIME_CHG_RSP_ACCEPTED = START_POS_TIME_CHG_RSP_ACCEPTED + 4 START_POS_TIME_CHG_RSP_REASON = END_POS_TIME_CHG_RSP_ACCEPTED END_POS_TIME_CHG_RSP_REASON = START_POS_TIME_CHG_RSP_REASON + 4 START_POS_TIME_CHG_RSP_TIME = END_POS_TIME_CHG_RSP_REASON END_POS_TIME_CHG_RSP_TIME = START_POS_TIME_CHG_RSP_TIME + 4 START_POS_TIME_CHG_RSP_UF_VOL = END_POS_TIME_CHG_RSP_TIME END_POS_TIME_CHG_RSP_UF_VOL = START_POS_TIME_CHG_RSP_UF_VOL + 4 # HD response to UF volume change request message field positions START_POS_UF_CHG_RSP_RESP = DenaliMessage.PAYLOAD_START_INDEX END_POS_UF_CHG_RSP_RESP = START_POS_UF_CHG_RSP_RESP + 4 START_POS_UF_CHG_RSP_REJECT_REASON = END_POS_UF_CHG_RSP_RESP END_POS_UF_CHG_RSP_REJECT_REASON = START_POS_UF_CHG_RSP_REJECT_REASON + 4 START_POS_UF_CHG_RSP_VOL = END_POS_UF_CHG_RSP_RESP END_POS_UF_CHG_RSP_VOL = START_POS_UF_CHG_RSP_VOL + 4 START_POS_UF_CHG_RSP_TIME = END_POS_UF_CHG_RSP_VOL END_POS_UF_CHG_RSP_TIME = START_POS_UF_CHG_RSP_TIME + 4 START_POS_UF_CHG_RSP_TIME_DIFF = END_POS_UF_CHG_RSP_TIME END_POS_UF_CHG_RSP_TIME_DIFF = START_POS_UF_CHG_RSP_TIME_DIFF + 4 START_POS_UF_CHG_RSP_RATE = END_POS_UF_CHG_RSP_TIME_DIFF END_POS_UF_CHG_RSP_RATE = START_POS_UF_CHG_RSP_RATE + 4 START_POS_UF_CHG_RSP_RATE_DIFF = END_POS_UF_CHG_RSP_RATE END_POS_UF_CHG_RSP_RATE_DIFF = START_POS_UF_CHG_RSP_RATE_DIFF + 4 # HD response to blood/dialysate flow change request message field positions START_POS_BLD_DIAL_CHG_RSP_ACCEPTED = DenaliMessage.PAYLOAD_START_INDEX END_POS_BLD_DIAL_CHG_RSP_ACCEPTED = START_POS_BLD_DIAL_CHG_RSP_ACCEPTED + 4 START_POS_BLD_DIAL_CHG_RSP_REASON = END_POS_BLD_DIAL_CHG_RSP_ACCEPTED END_POS_BLD_DIAL_CHG_RSP_REASON = START_POS_BLD_DIAL_CHG_RSP_REASON + 4 START_POS_BLD_DIAL_CHG_RSP_BLD_RATE = END_POS_BLD_DIAL_CHG_RSP_REASON END_POS_BLD_DIAL_CHG_RSP_BLD_RATE = START_POS_BLD_DIAL_CHG_RSP_BLD_RATE + 4 START_POS_BLD_DIAL_CHG_RSP_DIAL_RATE = END_POS_BLD_DIAL_CHG_RSP_BLD_RATE END_POS_BLD_DIAL_CHG_RSP_DIAL_RATE = START_POS_BLD_DIAL_CHG_RSP_DIAL_RATE + 4 def __init__(self, can_interface): """ @param can_interface: the denali can interface object """ super().__init__() self.can_interface = can_interface # register function to handle HD response to UF change requests if self.can_interface is not None: channel_id = DenaliChannels.hd_to_ui_ch_id self.can_interface.register_receiving_publication_function(channel_id, self.MSG_ID_UF_SETTINGS_CHANGE_RESPONSE_FROM_HD, self._handler_uf_change_response) self.can_interface.register_receiving_publication_function(channel_id, self.MSG_ID_TREATMENT_DURATION_SETTING_CHANGE_RESPONSE_FROM_HD, self._handler_treatment_duration_change_response) self.can_interface.register_receiving_publication_function(channel_id, self.MSG_ID_BLOOD_DIALYSATE_FLOW_SETTING_CHANGE_RESPONSE_FROM_HD, self._handler_blood_and_dialysate_change_response) self.can_interface.register_receiving_publication_function(channel_id, self.MSG_ID_HD_TREATMENT_PARAMS_RANGES, self._handler_treatment_param_ranges) self.can_interface.register_receiving_publication_function(DenaliChannels.hd_to_ui_ch_id, self.MSG_ID_UI_HD_VERSION_RESPONSE, self._handler_hd_version) # initialize variables that will be populated by HD version response self.hd_version = None # initialize variables that will be populated by treatment parameter ranges message self.min_treatment_duration_min = 0 self.max_treatment_duration_min = 0 self.min_uf_volume_ml = 0 self.max_uf_volume_ml = 0 self.min_dialysate_flow_rate_ml_min = 0 self.max_dialysate_flow_rate_ml_min = 0 # initialize variables that will be populated by response from HD to treatment duration change request self.duration_change_succeeded = False self.duration_change_reject_reason = 0 self.duration_change_time_min = 0 self.duration_change_uf_vol_ml = 0 # initialize variables that will be populated by response from HD to UF change request self.uf_change_succeeded = False self.uf_change_reject_reason = 0 self.uf_change_volume_ml = 0 self.uf_change_time_min = 0 self.uf_change_rate_ml_min = 0.0 self.uf_change_time_diff = 0 self.uf_change_rate_diff = 0.0 # initialize variables that will be populated by response from HD to blood & dialysate flow rate change request self.blood_and_dialysate_flow_rate_change_succeeded = False self.blood_and_dialysate_flow_rate_change_reject_reason = 0 self.target_blood_flow_rate = 0 self.target_dialysate_flow_rate = 0 def get_hd_version(self): """ Gets the hd version @return: The hd version """ return self.hd_version def get_min_treatment_duration_min(self): """ Gets the min treatment duration @return: the min treatment duration (minutes) """ return self.min_treatment_duration_min def get_max_treatment_duration_min(self): """ Gets the max treatment duration @return: The max treatment duration (minutes) """ return self.max_treatment_duration_min def get_min_uf_volume_ml(self): """ Gets the min uf volume @return: the min uf volume (mL) """ return self.min_uf_volume_ml def get_max_uf_volume_ml(self): """ Gets the max uf volume @return: The max uf volume (mL) """ return self.max_uf_volume_ml def get_min_dialysate_flow_rate_ml_min(self): """ Gets the min dialysate flow rate @return: The min dialysate flow rate (mL/min) """ return self.min_dialysate_flow_rate_ml_min def get_max_dialysate_flow_rate_ml_min(self): """ Gets the max dialysate flow rate @return: The max dialysate flow rate (mL/min) """ return self.max_dialysate_flow_rate_ml_min def get_duration_change_succeeded(self): """ Gets the duration change succeeded status @return: (bool) The duration change succeeded status """ return self.duration_change_succeeded def get_duration_change_reject_reason(self): """ Gets the duration change reject reason @return: (int) The duration change reject reason """ return self.duration_change_reject_reason def get_duration_change_time_min(self): """ Gets the duration change time @return: the duration change time (min) """ return self.duration_change_time_min def get_duration_change_uf_vol_ml(self): """ Gets the duration change uf vol @return: the duration change uf vol (mL) """ return self.duration_change_uf_vol_ml def get_uf_change_succeeded(self): """ Gets the uf change succeeded status @return: The uf change succeeded status """ return self.uf_change_succeeded def get_uf_change_reject_reason(self): """ Gets the uf change reject reason @return: (int) The uf change reject reason """ return self.uf_change_reject_reason def get_uf_change_volume_ml(self): """ Gets the uf change volume @return: The uf change volume (mL) """ return self.uf_change_volume_ml def get_uf_change_time_min(self): """ Gets the uf change time @return: The uf change time (min) """ return self.uf_change_time_min def get_uf_change_rate_ml_min(self): """ Gets the uf change rate @return: The uf change rate (mL/min) """ return self.uf_change_rate_ml_min def get_uf_change_time_diff(self): """ Gets the uf change time diff @return: The uf change time diff """ return self.uf_change_time_diff def get_uf_change_rate_diff(self): """ Gets the uf change rate diff @return: The uf change rate diff """ return self.uf_change_rate_diff def get_blood_and_dialysate_flow_rate_change_succeeded(self): """ Gets the blood and dialysate flow rate change succeeded status @return: True if successful, False otherwise """ return self.blood_and_dialysate_flow_rate_change_succeeded def get_blood_and_dialysate_flow_rate_change_reject_reason(self): """ Gets the blood and dialysate flow rate change reject reason @return: (int) The reason for the rejection """ return self.blood_and_dialysate_flow_rate_change_reject_reason def get_target_blood_flow_rate(self): """ Gets the target blood flow rate @return: The target blood flow rate """ return self.target_blood_flow_rate def get_target_dialysate_flow_rate(self): """ Gets the target dialysate flow rate @return: The target dialysate flow rate """ return self.target_dialysate_flow_rate @_publish([ "hd_version" ]) def _handler_hd_version(self, message): """ Handler for response from HD regarding its version. @param message: response message from HD regarding valid treatment parameter ranges.\n U08 Major \n U08 Minor \n U08 Micro \n U16 Build \n @return: None if not successful, the version string if unpacked successfully """ major = struct.unpack('B', bytearray( message['message'][self.START_POS_MAJOR:self.END_POS_MAJOR])) minor = struct.unpack('B', bytearray( message['message'][self.START_POS_MINOR:self.END_POS_MINOR])) micro = struct.unpack('B', bytearray( message['message'][self.START_POS_MICRO:self.END_POS_MICRO])) build = struct.unpack('H', bytearray( message['message'][self.START_POS_BUILD:self.END_POS_BUILD])) if len(major) > 0 and len(minor) > 0 and len(micro) > 0 and len(build) > 0: self.hd_version = f"v{major[0]}.{minor[0]}.{micro[0]}-{build[0]}" print(self.hd_version) return self.hd_version @_publish([ "min_treatment_duration_min", "max_treatment_duration_min", "min_uf_volume_ml", "max_uf_volume_ml", "min_dialysate_flow_rate_ml_min", "max_dialysate_flow_rate_ml_min" ]) def _handler_treatment_param_ranges(self, message): """ Handler for response from HD regarding valid treatment parameter ranges. @param message: response message from HD regarding valid treatment parameter ranges.\n U32 Minimum treatment duration setting (in min.). \n U32 Maximum treatment duration setting (in min.). \n U32 Minimum ultrafiltration volume (in mL). \n U32 Maximum ultrafiltration volume (in mL). \n U32 Minimum dialysate flow rate (in mL/min). \n U32 Maximum dialysate flow rate (in mL/min). @return: none """ mintime = struct.unpack('i', bytearray( message['message'][self.START_POS_MIN_TREAT_TIME:self.END_POS_MIN_TREAT_TIME])) maxtime = struct.unpack('i', bytearray( message['message'][self.START_POS_MAX_TREAT_TIME:self.END_POS_MAX_TREAT_TIME])) minufvol = struct.unpack('i', bytearray( message['message'][self.START_POS_MIN_UF_VOL:self.END_POS_MIN_UF_VOL])) maxufvol = struct.unpack('i', bytearray( message['message'][self.START_POS_MAX_UF_VOL:self.END_POS_MAX_UF_VOL])) mindialrt = struct.unpack('i', bytearray( message['message'][self.START_POS_MIN_DIAL_RATE:self.END_POS_MIN_DIAL_RATE])) maxdialrt = struct.unpack('i', bytearray( message['message'][self.START_POS_MAX_DIAL_RATE:self.END_POS_MAX_DIAL_RATE])) self.min_treatment_duration_min = mintime[0] self.max_treatment_duration_min = maxtime[0] self.min_uf_volume_ml = minufvol[0] self.max_uf_volume_ml = maxufvol[0] self.min_dialysate_flow_rate_ml_min = mindialrt[0] self.max_dialysate_flow_rate_ml_min = maxdialrt[0] @_publish([ "duration_change_succeeded", "duration_change_reject_reason", "duration_change_time_min", "duration_change_uf_vol_ml" ]) def _handler_treatment_duration_change_response(self, message): """ Handler for response from HD regarding treatment duration change request. @param message: response message from HD regarding treatment duration change.\n BOOL Accepted \n U32 Reject reason (if not accepted) \n U32 treatment duration (min) \n U32 UF volue (mL) \n @return: none """ rsp = struct.unpack('i', bytearray( message['message'][self.START_POS_TIME_CHG_RSP_ACCEPTED:self.END_POS_TIME_CHG_RSP_ACCEPTED])) rea = struct.unpack('i', bytearray( message['message'][self.START_POS_TIME_CHG_RSP_REASON:self.END_POS_TIME_CHG_RSP_REASON])) tim = struct.unpack('i', bytearray( message['message'][self.START_POS_TIME_CHG_RSP_TIME:self.END_POS_TIME_CHG_RSP_TIME])) vol = struct.unpack('i', bytearray( message['message'][self.START_POS_TIME_CHG_RSP_UF_VOL:self.END_POS_TIME_CHG_RSP_UF_VOL])) self.duration_change_succeeded = rsp[0] self.duration_change_reject_reason = rea[0] self.duration_change_time_min = tim[0] self.duration_change_uf_vol_ml = vol[0] @_publish([ "blood_and_dialysate_flow_rate_change_succeeded", "blood_and_dialysate_flow_rate_change_reject_reason", "target_blood_flow_rate", "target_dialysate_flow_rate" ]) def _handler_blood_and_dialysate_change_response(self, message): """ Handler for response from HD regarding blood & dialysate flow rate change request. @param message: response message from HD regarding requested blood & dialysate flow rate settings change.\n BOOL Accepted \n U32 Reject reason (if not accepted) \n U32 Blood flow rate (mL/min) \n U32 Dialysate flow rate (mL/min) \n @return: none """ rsp = struct.unpack('i', bytearray( message['message'][self.START_POS_BLD_DIAL_CHG_RSP_ACCEPTED:self.END_POS_BLD_DIAL_CHG_RSP_ACCEPTED])) rea = struct.unpack('i', bytearray( message['message'][self.START_POS_BLD_DIAL_CHG_RSP_REASON:self.END_POS_BLD_DIAL_CHG_RSP_REASON])) bld = struct.unpack('i', bytearray( message['message'][self.START_POS_BLD_DIAL_CHG_RSP_BLD_RATE:self.END_POS_BLD_DIAL_CHG_RSP_BLD_RATE])) dil = struct.unpack('i', bytearray( message['message'][self.START_POS_BLD_DIAL_CHG_RSP_DIAL_RATE:self.END_POS_BLD_DIAL_CHG_RSP_DIAL_RATE])) if rsp[0] == self.RESPONSE_REJECTED: resp = False else: resp = True self.blood_and_dialysate_flow_rate_change_succeeded = resp self.blood_and_dialysate_flow_rate_change_reject_reason = rea[0] self.target_blood_flow_rate = bld[0] self.target_dialysate_flow_rate = dil[0] @_publish([ "uf_change_succeeded", "uf_change_reject_reason", "uf_change_volume_ml", "uf_change_time_min", "uf_change_time_diff", "uf_change_rate_ml_min", "uf_change_rate_diff" ]) def _handler_uf_change_response(self, message): """ Handler for response from HD regarding UF change request. @param message: response message from HD regarding requested ultrafiltration settings change.\n BOOL Accepted \n U32 RejectReason (if not accepted) F32 UF Volume (mL) - converted to Liters \n U32 treatment Time (min) \n S32 treatment Time Change (min) \n F32 UF Rate (mL/min) \n F32 UF Rate Change (mL/min) @return: none """ rsp = struct.unpack('i', bytearray( message['message'][self.START_POS_UF_CHG_RSP_RESP:self.END_POS_UF_CHG_RSP_RESP])) rea = struct.unpack('i', bytearray( message['message'][self.START_POS_UF_CHG_RSP_REJECT_REASON:self.END_POS_UF_CHG_RSP_REJECT_REASON])) vol = struct.unpack('f', bytearray( message['message'][self.START_POS_UF_CHG_RSP_VOL:self.END_POS_UF_CHG_RSP_VOL])) tim = struct.unpack('i', bytearray( message['message'][self.START_POS_UF_CHG_RSP_TIME:self.END_POS_UF_CHG_RSP_TIME])) tmd = struct.unpack('i', bytearray( message['message'][self.START_POS_UF_CHG_RSP_TIME_DIFF:self.END_POS_UF_CHG_RSP_TIME_DIFF])) rat = struct.unpack('f', bytearray( message['message'][self.START_POS_UF_CHG_RSP_RATE:self.END_POS_UF_CHG_RSP_RATE])) rtd = struct.unpack('f', bytearray( message['message'][self.START_POS_UF_CHG_RSP_RATE_DIFF:self.END_POS_UF_CHG_RSP_RATE_DIFF])) if rsp[0] == self.RESPONSE_REJECTED: resp = False else: resp = True self.uf_change_succeeded = resp self.uf_change_reject_reason = rea[0] self.uf_change_volume_ml = vol[0] self.uf_change_time_min = tim[0] self.uf_change_time_diff = tmd[0] self.uf_change_rate_ml_min = rat[0] self.uf_change_rate_diff = rtd[0] def cmd_ui_checkin_with_hd(self): """ Constructs and sends the ui check-in message @return: 0 """ message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=self.MSG_ID_UI_CHECKIN_WITH_HD) print("Sending ui checkin w/ HD") self.can_interface.send(message, 0) return 0 def cmd_ui_request_hd_version(self): """ Constructs and sends the ui request for version message """ message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=self.MSG_ID_UI_REQUEST_HD_VERSION) print("Sending ui request for version to HD") self.can_interface.send(message, 0) def cmd_ui_uf_pause_resume(self, cmd=UF_CMD_PAUSE): """ Constructs and sends a ui UF command message @param cmd: 0 for pause, 1 for resume @return: none """ payload = integer_to_bytearray(cmd) message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=self.MSG_ID_HD_UF_PAUSE_RESUME_REQUEST, payload=payload) if cmd == self.UF_CMD_PAUSE: str_cmd = "pause" else: str_cmd = "resume" print("Sending UF " + str_cmd + " command.") self.can_interface.send(message, 0) return 0 def cmd_ui_uf_settings_change_request(self, vol=0.0): """ Constructs and sends a ui UF change settings command message @param vol (float): new ultrafiltration volume setting (in L) @return: none """ # reset response to this command so we can tell when response is received self.UFChangeResponse = None # build command message volume = float_to_bytearray(vol * self.LITER_TO_ML_CONVERSION_FACTOR) message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=self.MSG_ID_UF_SETTINGS_CHANGE_REQUEST_BY_USER, payload=volume) print("Sending UF settings change request.") self.can_interface.send(message, 0) return 0 def cmd_ui_uf_settings_change_confirm(self, vol=0.0, adj=UF_CMD_CHANGE_TIME_TO_ADJUST): """ Constructs and sends a ui UF change settings command message @param vol (float): new ultrafiltration volume setting (in L) @param adj (int): 0 for adjust time, 1 for adjust rate @return: none """ # reset response to this command so we can tell when response is received self.UFChangeResponse = None # build command message volume = float_to_bytearray(vol * self.LITER_TO_ML_CONVERSION_FACTOR) adjust = integer_to_bytearray(adj) payload = volume + adjust message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=self.MSG_ID_UF_SETTINGS_CHANGE_REQUEST_BY_USER, payload=payload) print("Sending UF settings change request.") self.can_interface.send(message, 0) return 0 def cmd_ui_uf_change_settings_confirmed_by_user(self, response=RESPONSE_REJECTED, vol=0.0, tm=0, rate=0.0): """ Constructs and sends a ui UF change settings confirmed by user message @param response (int): 0 for rejected, 1 for confirmed @param vol (float): volume (in L) that was confirmed @param tm (int): treatment time (in min) that was confirmed @param rate (float): ultrafiltration rate (in mL/min) that was confirmed @return: none """ resp = integer_to_bytearray(response) volume = float_to_bytearray(vol * self.LITER_TO_ML_CONVERSION_FACTOR) mins = integer_to_bytearray(tm) ufrate = float_to_bytearray(rate) payload = resp + volume + mins + ufrate message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=self.MSG_ID_UF_SETTINGS_CHANGE_CONFIRMED_BY_USER, payload=payload) print("Sending UF settings change confirmation.") self.can_interface.send(message, 0) return 0 def cmd_ui_treatment_duration_setting_change_request(self, timeMin=0): """ Constructs and sends a ui UF change settings confirmed by user message @param timeMin (int): treatment time (in min). @return: none """ payload = integer_to_bytearray(timeMin) message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=self.MSG_ID_TREATMENT_DURATION_SETTING_CHANGE_REQUEST, payload=payload) print("Sending treatment duration setting change request.") # Send message self.can_interface.send(message, 0) return 0 def cmd_ui_blood_and_dialysate_flow_settings_change_request(self, bloodFlow, dialFlow): """ Constructs and sends a ui blood & dialysate flow settings change request by user message @param bloodFlow (int): blood flow rate set point (in mL/min). @param dialFlow (int): dialysate flow rate set point (in mL/min). @return: none """ bld = integer_to_bytearray(bloodFlow) dial = integer_to_bytearray(dialFlow) payload = bld + dial message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, message_id=self.MSG_ID_BLOOD_DIALYSATE_FLOW_SETTING_CHANGE_REQUEST_BY_USER, payload=payload) print("Sending blood & dialysate flow rate settings change request.") self.can_interface.send(message, 0) return 0