Index: HemodialysisDevice.py =================================================================== diff -u -r2a04f65829931c2e7dc62c6722a53da935cc32fb -r6f0c6e8ae8f99446a0b5f88595207fe373c1ea83 --- HemodialysisDevice.py (.../HemodialysisDevice.py) (revision 2a04f65829931c2e7dc62c6722a53da935cc32fb) +++ HemodialysisDevice.py (.../HemodialysisDevice.py) (revision 6f0c6e8ae8f99446a0b5f88595207fe373c1ea83) @@ -552,7 +552,7 @@ self.MeasuredBloodPumpRotorSpeed = 0.0 self.MeasuredBloodPumpSpeed = 0.0 self.MeasuredBloodPumpMCSpeed = 0.0 - self.MeasuredBloodPumpMCurrent = 0.0 + self.MeasuredBloodPumpMCCurrent = 0.0 self.PWMDutyCyclePct = 0.0 def handlerBloodFlowSyncFunction(self, message): @@ -662,9 +662,6 @@ print("Timeout!!!!") return False - # TODO - add override command for blood pump motor speed (motor hall sensor via FPGA) - # TODO - add override command for blood pump speed (pump hall sensor via NHET?) - def CmdBloodPumpMCMeasuredSpeedOverride(self, reset, speed): """ Constructs and sends the measured blood pump motor controller speed \n @@ -818,7 +815,7 @@ def CmdBloodFlowBroadcastIntervalOverride(self, reset, ms): """ - Constructs and sends the measured flow broadcast interval override command + Constructs and sends the measured blood flow broadcast interval override command \param reset: integer - 1 to reset a previous override, 0 to override \param ms: integer - interval (in ms) to override with @@ -853,6 +850,359 @@ print("Timeout!!!!") return False + class HD_DialysateInletFlow: + """ + \class HD_DialysateInletFlow + + \brief Hemodialysis Device (HD) Dialin API sub-class for dialysate inlet pump related commands. + + """ + + # DialysateFlow message IDs + MSG_ID_HD_DIAL_IN_FLOW_PUBLISHED_DATA = 0x0006 + MSG_ID_HD_DIAL_IN_FLOW_SET_RATE_OVERRIDE = 0x8010 + MSG_ID_HD_DIAL_IN_FLOW_MEAS_RATE_OVERRIDE = 0x8011 + MSG_ID_HD_DIAL_IN_PUMP_MC_MEAS_SPEED_OVERRIDE = 0x8012 + MSG_ID_HD_DIAL_IN_PUMP_MC_MEAS_CURRENT_OVERRIDE = 0x8013 + MSG_ID_HD_DIAL_IN_FLOW_PUBLISH_INTERVAL_OVERRIDE = 0x8014 + MSG_ID_HD_DIAL_IN_PUMP_MEAS_SPEED_OVERRIDE = 0x8015 + MSG_ID_HD_DIAL_IN_PUMP_ROTOR_MEAS_SPEED_OVERRIDE = 0x8016 + + # BloodFlow broadcast message field positions + START_POS_SET_PT = DenaliMessage.PAYLOAD_START_INDEX + END_POS_SET_PT = START_POS_SET_PT + 4 + START_POS_MEAS_FLOW = END_POS_SET_PT + END_POS_MEAS_FLOW = START_POS_MEAS_FLOW + 4 + START_POS_MEAS_ROT_SPEED = END_POS_MEAS_FLOW + END_POS_MEAS_ROT_SPEED = START_POS_MEAS_ROT_SPEED + 4 + START_POS_MEAS_SPEED = END_POS_MEAS_ROT_SPEED + END_POS_MEAS_SPEED = START_POS_MEAS_SPEED + 4 + START_POS_MEAS_MC_SPEED = END_POS_MEAS_SPEED + END_POS_MEAS_MC_SPEED = START_POS_MEAS_MC_SPEED + 4 + START_POS_MEAS_MC_CURR = END_POS_MEAS_MC_SPEED + END_POS_MEAS_MC_CURR = START_POS_MEAS_MC_CURR + 4 + START_POS_PWM_DC = END_POS_MEAS_MC_CURR + END_POS_PWM_DC = START_POS_PWM_DC + 4 + + def __init__(self, outer_instance, can_interface=None): + """ + HD_DialysateFlow constructor + + \param outer_instance: reference to the HD (outer) class. + + \returns HD_DialysateFlow object. + """ + self.outer_instance = outer_instance + + if can_interface is not None: + channel_id = DenaliChannels.hd_sync_broadcast_ch_id + msg_id = self.MSG_ID_HD_DIAL_IN_FLOW_PUBLISHED_DATA + can_interface.registerReceivingPublicationFunction(channel_id, msg_id, + self.handlerDialysateInletFlowSyncFunction) + + self.TargetDialysateInletFlowRate = 0 + self.MeasuredDialysateInletFlowRate = 0.0 + self.MeasuredDialysateInletPumpRotorSpeed = 0.0 + self.MeasuredDialysateInletPumpSpeed = 0.0 + self.MeasuredDialysateInletPumpMCSpeed = 0.0 + self.MeasuredDialysateInletPumpMCCurrent = 0.0 + self.PWMDutyCyclePct = 0.0 + + def handlerDialysateInletFlowSyncFunction(self, message): + """ + Handles published dialysate inlet flow data messages. Dialysate flow data are captured + for reference. + + \param message: published dialysate flow data message + \returns none + """ + + self.TargetDialysateInletFlowRate = int.from_bytes(bytearray( + message['message'][self.START_POS_SET_PT:self.END_POS_SET_PT]), + byteorder=DenaliMessage.BYTE_ORDER) + flow = struct.unpack('f', bytearray( + message['message'][self.START_POS_MEAS_FLOW:self.END_POS_MEAS_FLOW])) + rotor = struct.unpack('f', bytearray( + message['message'][self.START_POS_MEAS_ROT_SPEED:self.END_POS_MEAS_ROT_SPEED])) + speed = struct.unpack('f', bytearray( + message['message'][self.START_POS_MEAS_SPEED:self.END_POS_MEAS_SPEED])) + mcspeed = struct.unpack('f', bytearray( + message['message'][self.START_POS_MEAS_MC_SPEED:self.END_POS_MEAS_MC_SPEED])) + mccurr = struct.unpack('f', bytearray( + message['message'][self.START_POS_MEAS_MC_CURR:self.END_POS_MEAS_MC_CURR])) + pwm = struct.unpack('f', bytearray( + message['message'][self.START_POS_PWM_DC:self.END_POS_PWM_DC])) + + self.MeasuredDialysateInletFlowRate = flow[0] + self.MeasuredDialysateInletPumpRotorSpeed = rotor[0] + self.MeasuredDialysateInletPumpSpeed = speed[0] + self.MeasuredDialysateInletPumpMCSpeed = mcspeed[0] + self.MeasuredDialysateInletPumpMCCurrent = mccurr[0] + self.PWMDutyCyclePct = pwm[0] + + def CmdDialysateInletFlowSetPointOverride(self, reset, flow): + """ + Constructs and sends the dialysate flow set point override command + + \param reset: integer - 1 to reset a previous override, 0 to override + \param flow: integer - flow set point (in mL/min) to override with + \returns 1 if successful, zero otherwise + """ + + rst = self.outer_instance.integer2ByteArray(reset) + flo = self.outer_instance.integer2ByteArray(flow) + payload = rst + flo + + message = DenaliMessage.buildMessage(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=self.MSG_ID_HD_DIAL_IN_FLOW_SET_RATE_OVERRIDE, + payload=payload) + + print("override dialysate flow set point") + + # Send message + received_message = self.outer_instance.can_interface.send(message) + + # If there is content... + if received_message is not None: + print(received_message) + if reset == HD.RESET: + str_res = "reset back to normal" + else: + str_res = str(flow) + print( + "Dialysate flow set point overridden to " + str_res + " 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: + print("Timeout!!!!") + return False + + def CmdDialysateInletFlowMeasuredOverride(self, reset, flow): + """ + Constructs and sends the measured dialysate flow override command + + \param reset: integer - 1 to reset a previous override, 0 to override + \param flow: integer - measured flow (in mL/min) to override with + \returns 1 if successful, zero otherwise + """ + + rst = self.outer_instance.integer2ByteArray(reset) + flo = self.outer_instance.integer2ByteArray(flow) + payload = rst + flo + + message = DenaliMessage.buildMessage(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=self.MSG_ID_HD_DIAL_IN_FLOW_MEAS_RATE_OVERRIDE, + payload=payload) + + print("override measured dialysate flow") + + # Send message + received_message = self.outer_instance.can_interface.send(message) + + # If there is content... + if received_message is not None: + print(received_message) + if reset == HD.RESET: + str_res = "reset back to normal" + else: + str_res = str(flow) + print("Dialysate flow (measured)) overridden to " + str_res + " 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: + print("Timeout!!!!") + return False + + def CmdDialysateInletPumpMCMeasuredSpeedOverride(self, reset, speed): + """ + Constructs and sends the measured dialysate inlet pump motor controller speed \n + override command. + + \param reset: integer - 1 to reset a previous override, 0 to override + \param speed: integer - speed (in RPM) to override with + \returns 1 if successful, zero otherwise + """ + + rst = self.outer_instance.integer2ByteArray(reset) + spd = self.outer_instance.integer2ByteArray(speed) + payload = rst + spd + + message = DenaliMessage.buildMessage(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=self.MSG_ID_HD_DIAL_IN_PUMP_MC_MEAS_SPEED_OVERRIDE, + payload=payload) + + print("override measured dialysate inlet pump motor controller speed") + + # Send message + received_message = self.outer_instance.can_interface.send(message) + + # If there is content... + if received_message is not None: + print(received_message) + if reset == HD.RESET: + str_res = "reset back to normal" + else: + str_res = str(speed) + print("Dialysate pump MC speed (measured) overridden to " + str_res + " RPM: " + + str(received_message['message'][DenaliMessage.PAYLOAD_START_INDEX])) + # response payload is OK or not OK + return received_message['message'][DenaliMessage.PAYLOAD_START_INDEX] + else: + print("Timeout!!!!") + return False + + def CmdDialysateInletPumpMeasuredCurrentOverride(self, reset, curr): + """ + Constructs and sends the measured dialysate inlet pump motor current override command + + \param reset: integer - 1 to reset a previous override, 0 to override + \param curr: integer - current (in mA) to override with + \returns 1 if successful, zero otherwise + """ + + rst = self.outer_instance.integer2ByteArray(reset) + cur = self.outer_instance.integer2ByteArray(curr) + payload = rst + cur + + message = DenaliMessage.buildMessage(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=self.MSG_ID_HD_DIAL_IN_PUMP_MC_MEAS_CURRENT_OVERRIDE, + payload=payload) + + print("override measured dialysate inlet pump motor controller current") + + # Send message + received_message = self.outer_instance.can_interface.send(message) + + # If there is content... + if received_message is not None: + print(received_message) + if reset == HD.RESET: + str_res = "reset back to normal" + else: + str_res = str(curr) + print("Dialysate inlet pump MC current (measured) overridden to " + str_res + " mA: " + + str(received_message['message'][DenaliMessage.PAYLOAD_START_INDEX])) + # response payload is OK or not OK + return received_message['message'][DenaliMessage.PAYLOAD_START_INDEX] + else: + print("Timeout!!!!") + return False + + def CmdDialysateInletPumpMeasuredSpeedOverride(self, reset, speed): + """ + Constructs and sends the measured dialysate inlet pump motor speed override \n + command. + + \param reset: integer - 1 to reset a previous override, 0 to override + \param speed: integer - speed (in RPM) to override with + \returns 1 if successful, zero otherwise + """ + + rst = self.outer_instance.integer2ByteArray(reset) + spd = self.outer_instance.integer2ByteArray(speed) + payload = rst + spd + + message = DenaliMessage.buildMessage(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=self.MSG_ID_HD_DIAL_IN_PUMP_MEAS_SPEED_OVERRIDE, + payload=payload) + + print("override measured dialysate inlet pump speed") + + # Send message + received_message = self.outer_instance.can_interface.send(message) + + # If there is content... + if received_message is not None: + print(received_message) + if reset == HD.RESET: + str_res = "reset back to normal" + else: + str_res = str(speed) + print("Dialysate inlet pump speed (measured) overridden to " + str_res + " RPM: " + + str(received_message['message'][DenaliMessage.PAYLOAD_START_INDEX])) + # response payload is OK or not OK + return received_message['message'][DenaliMessage.PAYLOAD_START_INDEX] + else: + print("Timeout!!!!") + return False + + def CmdDialysateInletPumpRotorMeasuredSpeedOverride(self, reset, speed): + """ + Constructs and sends the measured dialysate inlet pump rotor speed override \n + command. + + \param reset: integer - 1 to reset a previous override, 0 to override + \param speed: integer - speed (in RPM) to override with + \returns 1 if successful, zero otherwise + """ + + rst = self.outer_instance.integer2ByteArray(reset) + spd = self.outer_instance.integer2ByteArray(speed) + payload = rst + spd + + message = DenaliMessage.buildMessage(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=self.MSG_ID_HD_DIAL_IN_PUMP_ROTOR_MEAS_SPEED_OVERRIDE, + payload=payload) + + print("override measured dialysate inlet pump rotor speed") + + # Send message + received_message = self.outer_instance.can_interface.send(message) + + # If there is content... + if received_message is not None: + print(received_message) + if reset == HD.RESET: + str_res = "reset back to normal" + else: + str_res = str(speed) + print("Dialysate inlet pump rotor speed (measured) overridden to " + str_res + " RPM: " + + str(received_message['message'][DenaliMessage.PAYLOAD_START_INDEX])) + # response payload is OK or not OK + return received_message['message'][DenaliMessage.PAYLOAD_START_INDEX] + else: + print("Timeout!!!!") + return False + + def CmdDialysateInletFlowBroadcastIntervalOverride(self, reset, ms): + """ + Constructs and sends the measured dialysate inlet flow broadcast interval override command + + \param reset: integer - 1 to reset a previous override, 0 to override + \param ms: integer - interval (in ms) to override with + \returns 1 if successful, zero otherwise + """ + + rst = self.outer_instance.integer2ByteArray(reset) + mis = self.outer_instance.integer2ByteArray(ms) + payload = rst + mis + + message = DenaliMessage.buildMessage(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=self.MSG_ID_HD_DIAL_IN_FLOW_PUBLISH_INTERVAL_OVERRIDE, + payload=payload) + + print("override dialysate inlet flow broadcast interval") + + # Send message + received_message = self.outer_instance.can_interface.send(message) + + # If there is content... + if received_message is not None: + print(received_message) + if reset == HD.RESET: + str_res = "reset back to normal: " + else: + str_res = str(ms) + " ms: " + print("Dialysate inlet flow 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: + print("Timeout!!!!") + return False + def integer2ByteArray(self, val): """ Converts an integer value into a byte array (little endian)