Index: HemodialysisDevice.py =================================================================== diff -u -r3212865df6217fe18df05654a518d3821b340747 -r2a04f65829931c2e7dc62c6722a53da935cc32fb --- HemodialysisDevice.py (.../HemodialysisDevice.py) (revision 3212865df6217fe18df05654a518d3821b340747) +++ HemodialysisDevice.py (.../HemodialysisDevice.py) (revision 2a04f65829931c2e7dc62c6722a53da935cc32fb) @@ -8,28 +8,26 @@ # @file HemodialysisDevice.py # # @date 16-Oct-2019 -# @author L. Baloa +# @author S. Nash # -# @brief This class allows sending to and receiving from the HD device. +# @brief This class provides the basic interface to communicate with +# the HD board. # ############################################################################ from DialityCoreCanProtocol import DenaliCanMessenger from DialityCoreCanProtocol import DenaliMessage +from DialityCoreCanProtocol import DenaliChannels from time import sleep from binascii import unhexlify import struct class HD: - """ - \class HD + # for reset param in override commands + NO_RESET = 0 + RESET = 1 - \brief Hemodialysis Device (HD) Dialin API object. It provides the basic interface to communicate with - the HD board - - """ - def __init__(self, can__interface="can0"): """ HD constructor using can bus @@ -52,9 +50,6 @@ self.Buttons = HD.HD_Buttons(self) self.BloodFlow = HD.HD_BloodFlow(self, self.can_interface) self.Watchdog = HD.HD_Watchdog(self) - # Create constants - self.NO_RESET = 0 - self.RESET = 1 class HD__Basics: """ @@ -63,6 +58,13 @@ \brief Hemodialysis Device (HD) Dialin API sub-class for basic HD commands. """ + # Basic message IDs + MSG_ID_LOGIN_TO_HD = 0x8000 + MSG_ID_HD_MSG = 0x8001 + + # HD login password + HD_LOGIN_PASSWORD = '123' + def __init__(self, outer_instance): self.outer_instance = outer_instance @@ -82,9 +84,9 @@ \returns 1 if logged in, 0 if log in failed """ - message = DenaliMessage.buildMessage(channel_id=0x400, - message_id=0x8000, - payload=list(map(int, map(ord, '123')))) + message = DenaliMessage.buildMessage(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=self.MSG_ID_LOGIN_TO_HD, + payload=list(map(int, map(ord, self.HD_LOGIN_PASSWORD)))) print("login") @@ -93,8 +95,8 @@ if received_message is not None: print(received_message) - print("Logged In: " + str(received_message['message'][4])) - return received_message['message'][4] + print("Logged In: " + str(received_message['message'][DenaliMessage.PAYLOAD_START_INDEX])) + return received_message['message'][DenaliMessage.PAYLOAD_START_INDEX] else: print("Timeout!!!!") return False @@ -109,8 +111,8 @@ \returns 1 if successful, zero otherwise """ - message = DenaliMessage.buildMessage(channel_id=0x400, - message_id=0x8001, + message = DenaliMessage.buildMessage(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=self.MSG_ID_HD_MSG, payload=msg) print("insert HD message") @@ -121,9 +123,9 @@ # If there is content... if received_message is not None: print(received_message) - print("Inserted message: " + str(received_message['message'][4])) - # 5th element is OK or not OK - return received_message['message'][4] + print("Inserted message: " + 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 @@ -135,6 +137,10 @@ \brief Hemodialysis Device (HD) Dialin API sub-class for button related commands. """ + # Buttons message IDs + MSG_ID_HD_OFF_BUTTON_OVERRIDE = 0x8002 + MSG_ID_HD_STOP_BUTTON_OVERRIDE = 0x8003 + def __init__(self, outer_instance): self.outer_instance = outer_instance @@ -159,8 +165,8 @@ sta = self.outer_instance.integer2ByteArray(state) payload = rst + sta - message = DenaliMessage.buildMessage(channel_id=0x400, - message_id=0x8002, + message = DenaliMessage.buildMessage(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=self.MSG_ID_HD_OFF_BUTTON_OVERRIDE, payload=payload) print("override off button") @@ -171,14 +177,15 @@ # If there is content... if received_message is not None: print(received_message) - if reset == 1: + if reset == HD.RESET: str_res = "reset back to normal" else: str_res = ("pressed" if state != 0 else "released") - print("Off button overridden to " + str_res + ":" + str(received_message['message'][4])) - # 5th element is OK or not OK - return received_message['message'][4] + print("Off button 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 @@ -196,8 +203,8 @@ sta = self.outer_instance.integer2ByteArray(state) payload = rst + sta - message = DenaliMessage.buildMessage(channel_id=0x400, - message_id=0x8003, + message = DenaliMessage.buildMessage(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=self.MSG_ID_HD_STOP_BUTTON_OVERRIDE, payload=payload) print("override stop button") @@ -208,13 +215,14 @@ # If there is content... if received_message is not None: print(received_message) - if reset == 1: + if reset == HD.RESET: str_res = "reset back to normal" else: str_res = ("pressed" if state != 0 else "released") - print("Stop button overridden to " + str_res + ":" + str(received_message['message'][4])) - # 5th element is OK or not OK - return received_message["message"][4] + print("Stop button 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 @@ -226,6 +234,9 @@ \brief Hemodialysis Device (HD) Dialin API sub-class for watchdog related commands. """ + # Watchdog message IDs + MSG_ID_HD_WD_CHECKIN_OVERRIDE = 0x8005 + def __init__(self, outer_instance): self.outer_instance = outer_instance @@ -252,8 +263,8 @@ tsk = self.outer_instance.integer2ByteArray(task) payload = rst + sta + tsk - message = DenaliMessage.buildMessage(channel_id=0x400, - message_id=0x8005, + message = DenaliMessage.buildMessage(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=self.MSG_ID_HD_WD_CHECKIN_OVERRIDE, payload=payload) print("override watchdog task check-in state") @@ -264,13 +275,14 @@ # If there is content... if received_message is not None: print(received_message) - if reset == 1: + if reset == HD.RESET: str_res = "reset back to normal" else: str_res = ("checked in" if state != 0 else "not checked in") - print("Watchdog task check-in overridden to " + str_res + ":" + str(received_message['message'][4])) - # 5th element is OK or not OK - return received_message['message'][4] + print("Watchdog task check-in 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 @@ -282,17 +294,74 @@ \brief Hemodialysis Device (HD) Dialin API sub-class for alarm related commands. """ - def __init__(self, outer_instance): + # Alarms message IDs + MSG_ID_HD_ALARMS_PUBLISHED_STATUS = 0x0002 + MSG_ID_HD_ALARM_LAMP_OVERRIDE = 0x8004 + MSG_ID_HD_ALARM_STATE_OVERRIDE = 0x8006 + MSG_ID_HD_ALARM_TIME_OVERRIDE = 0x8007 + + # Alarm lamp patterns + HD_ALARM_LAMP_PATTERN_OFF = 0 + HD_ALARM_LAMP_PATTERN_OK = 1 + HD_ALARM_LAMP_PATTERN_FAULT = 2 + HD_ALARM_LAMP_PATTERN_HIGH = 3 + HD_ALARM_LAMP_PATTERN_MEDIUM = 4 + HD_ALARM_LAMP_PATTERN_LOW = 5 + HD_ALARM_LAMP_PATTERN_MANUAL = 6 + + # Alarm status message field positions + START_POS_ALARM_STATE = DenaliMessage.PAYLOAD_START_INDEX + END_POS_ALARM_STATE = START_POS_ALARM_STATE + 4 + START_POS_ALARM_TOP = END_POS_ALARM_STATE + END_POS_ALARM_TOP = START_POS_ALARM_TOP + 4 + START_POS_ALARM_SILENCE_EXPIRES_IN = END_POS_ALARM_TOP + END_POS_ALARM_SILENCE_EXPIRES_IN = START_POS_ALARM_SILENCE_EXPIRES_IN + 4 + START_POS_ALARMS_FLAGS = END_POS_ALARM_SILENCE_EXPIRES_IN + END_POS_ALARMS_FLAGS = START_POS_ALARMS_FLAGS + 2 + + def __init__(self, outer_instance, can_interface=None): + """ + HD_Alarms constructor + + \param outer_instance: reference to the HD (outer) class. + + \returns HD_Alarms object. + """ self.outer_instance = outer_instance - """ - HD_Alarms constructor + if can_interface is not None: + channel_id = DenaliChannels.hd_sync_broadcast_ch_id + msg_id = self.MSG_ID_HD_ALARMS_PUBLISHED_STATUS + can_interface.registerReceivingPublicationFunction(channel_id, msg_id, + self.handlerAlarmsStatusSyncFunction) - \param outer_instance: reference to the HD (outer) class. + self.alarmsState = 0 + self.alarmTop = 0 + self.alarmsSilenceExpiresIn = 0 + self.alarmsFlags = 0 - \returns HD_Alarms object. - """ + def handlerAlarmsStatusSyncFunction(self, message): + """ + Handles published alarms status messages. Alarms status data are captured + for reference. + \param message: published blood flow data message + \returns none + """ + + self.alarmsState = int.from_bytes(bytearray( + message['message'][self.START_POS_ALARM_STATE:self.END_POS_ALARM_STATE]), + byteorder=DenaliMessage.BYTE_ORDER) + self.alarmTop = int.from_bytes(bytearray( + message['message'][self.START_POS_ALARM_TOP:self.END_POS_ALARM_TOP]), + byteorder=DenaliMessage.BYTE_ORDER) + self.alarmsSilenceExpiresIn = int.from_bytes(bytearray( + message['message'][self.START_POS_ALARM_SILENCE_EXPIRES_IN:self.END_POS_ALARM_SILENCE_EXPIRES_IN]), + byteorder=DenaliMessage.BYTE_ORDER) + self.alarmsFlags = int.from_bytes(bytearray( + message['message'][self.START_POS_ALARMS_FLAGS:self.END_POS_ALARMS_FLAGS]), + byteorder=DenaliMessage.BYTE_ORDER) + def CmdAlarmStateOverride(self, reset, state, alarm): """ Constructs and sends the alarm state override command @@ -308,8 +377,8 @@ alm = self.outer_instance.integer2ByteArray(alarm) payload = rst + sta + alm - message = DenaliMessage.buildMessage(channel_id=0x400, - message_id=0x8006, + message = DenaliMessage.buildMessage(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=self.MSG_ID_HD_ALARM_STATE_OVERRIDE, payload=payload) print("override alarm state") @@ -320,13 +389,14 @@ # If there is content... if received_message is not None: print(received_message) - if reset == 1: + if reset == HD.RESET: str_res = "reset back to normal" else: str_res = ("active" if state != 0 else "inactive") - print("Alarm state overridden to " + str_res + ":" + str(received_message['message'][4])) - # 5th element is OK or not OK - return received_message['message'][4] + print("Alarm state 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 @@ -346,8 +416,8 @@ alm = self.outer_instance.integer2ByteArray(alarm) payload = rst + ms + alm - message = DenaliMessage.buildMessage(channel_id=0x400, - message_id=0x8007, + message = DenaliMessage.buildMessage(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=self.MSG_ID_HD_ALARM_TIME_OVERRIDE, payload=payload) print("override alarm time since activated") @@ -358,14 +428,14 @@ # If there is content... if received_message is not None: print(received_message) - if reset == 1: + if reset == HD.RESET: str_res = "reset back to normal" else: str_res = str(time_ms) print("Alarm time since activated overridden to " + str_res + " ms: " + str( - received_message['message'][4])) - # 5th element is OK or not OK - return received_message['message'][4] + 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 @@ -391,8 +461,8 @@ pat = self.outer_instance.integer2ByteArray(pattern) payload = rst + pat - message = DenaliMessage.buildMessage(channel_id=0x400, - message_id=0x8004, + message = DenaliMessage.buildMessage(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=self.CmdAlarmLampPatternOverride(), payload=payload) print("override alarm lamp pattern") @@ -403,25 +473,26 @@ # If there is content... if received_message is not None: print(received_message) - if reset == 1: + if reset == HD.RESET: str_pat = "reset back to normal" - elif pattern == 0: + elif pattern == self.HD_ALARM_LAMP_PATTERN_OFF: str_pat = "off" - elif pattern == 1: + elif pattern == self.HD_ALARM_LAMP_PATTERN_OK: str_pat = "ok" - elif pattern == 2: + elif pattern == self.HD_ALARM_LAMP_PATTERN_FAULT: str_pat = "fault" - elif pattern == 3: + elif pattern == self.HD_ALARM_LAMP_PATTERN_HIGH: str_pat = "high" - elif pattern == 4: + elif pattern == self.HD_ALARM_LAMP_PATTERN_MEDIUM: str_pat = "medium" - elif pattern == 5: + elif pattern == self.HD_ALARM_LAMP_PATTERN_LOW: str_pat = "low" else: str_pat = "manual" - print("Alarm lamp pattern overridden to " + str_pat + ":" + str(received_message['message'][4])) - # 5th element is OK or not OK - return received_message['message'][4] + print("Alarm lamp pattern overridden to " + str_pat + ":" + + 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 @@ -434,12 +505,45 @@ """ + # BloodFlow message IDs + MSG_ID_HD_BLOOD_FLOW_PUBLISHED_DATA = 0x0005 + MSG_ID_HD_BLOOD_FLOW_SET_RATE_OVERRIDE = 0x8008 + MSG_ID_HD_BLOOD_FLOW_MEAS_RATE_OVERRIDE = 0x8009 + MSG_ID_HD_BLOOD_PUMP_MC_MEAS_SPEED_OVERRIDE = 0x800A + MSG_ID_HD_BLOOD_PUMP_MC_MEAS_CURRENT_OVERRIDE = 0x800B + MSG_ID_HD_BLOOD_FLOW_PUBLISH_INTERVAL_OVERRIDE = 0x800C + MSG_ID_HD_BLOOD_PUMP_MEAS_SPEED_OVERRIDE = 0x800E + MSG_ID_HD_BLOOD_PUMP_ROTOR_MEAS_SPEED_OVERRIDE = 0x800F + + # 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_BloodFlow constructor + + \param outer_instance: reference to the HD (outer) class. + + \returns HD_BloodFlow object. + """ self.outer_instance = outer_instance if can_interface is not None: - channel_id = 0x40 - msg_id = 0x0005 + channel_id = DenaliChannels.hd_sync_broadcast_ch_id + msg_id = self.MSG_ID_HD_BLOOD_FLOW_PUBLISHED_DATA can_interface.registerReceivingPublicationFunction(channel_id, msg_id, self.handlerBloodFlowSyncFunction) @@ -449,22 +553,39 @@ self.MeasuredBloodPumpSpeed = 0.0 self.MeasuredBloodPumpMCSpeed = 0.0 self.MeasuredBloodPumpMCurrent = 0.0 + self.PWMDutyCyclePct = 0.0 - """ - HD_BloodFlow constructor + def handlerBloodFlowSyncFunction(self, message): + """ + Handles published blood flow data messages. Blood flow data are captured + for reference. - \param outer_instance: reference to the HD (outer) class. + \param message: published blood flow data message + \returns none + """ - \returns HD_BloodFlow object. - """ + self.TargetBloodFlowRate = 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])) - def handlerBloodFlowSyncFunction(self, message): - self.TargetBloodFlowRate = int.from_bytes(bytearray(message['message'][4:8]), byteorder='little') - self.MeasuredBloodFlowRate = struct.unpack('f', bytearray(message['message'][8:12])) - self.MeasuredBloodPumpRotorSpeed = struct.unpack('f', bytearray(message['message'][12:16])) - self.MeasuredBloodPumpSpeed = struct.unpack('f', bytearray(message['message'][16:20])) - self.MeasuredBloodPumpMCSpeed = struct.unpack('f', bytearray(message['message'][20:24])) - self.MeasuredBloodPumpMCCurrent = struct.unpack('f', bytearray(message['message'][24:28])) + self.MeasuredBloodFlowRate = flow[0] + self.MeasuredBloodPumpRotorSpeed = rotor[0] + self.MeasuredBloodPumpSpeed = speed[0] + self.MeasuredBloodPumpMCSpeed = mcspeed[0] + self.MeasuredBloodPumpMCCurrent = mccurr[0] + self.PWMDutyCyclePct = pwm[0] def CmdBloodFlowSetPointOverride(self, reset, flow): """ @@ -479,8 +600,8 @@ flo = self.outer_instance.integer2ByteArray(flow) payload = rst + flo - message = DenaliMessage.buildMessage(channel_id=0x400, - message_id=0x8008, + message = DenaliMessage.buildMessage(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=self.MSG_ID_HD_BLOOD_FLOW_SET_RATE_OVERRIDE, payload=payload) print("override blood flow set point") @@ -491,14 +612,15 @@ # If there is content... if received_message is not None: print(received_message) - if reset == 1: + if reset == HD.RESET: str_res = "reset back to normal" else: str_res = str(flow) print( - "Blood flow set point overridden to " + str_res + " mL/min: " + str(received_message['message'][4])) - # 5th element is OK or not OK - return received_message['message'][4] + "Blood 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 @@ -516,8 +638,8 @@ flo = self.outer_instance.integer2ByteArray(flow) payload = rst + flo - message = DenaliMessage.buildMessage(channel_id=0x400, - message_id=0x8009, + message = DenaliMessage.buildMessage(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=self.MSG_ID_HD_BLOOD_FLOW_MEAS_RATE_OVERRIDE, payload=payload) print("override measured blood flow") @@ -528,14 +650,14 @@ # If there is content... if received_message is not None: print(received_message) - if reset == 1: + if reset == HD.RESET: str_res = "reset back to normal" else: str_res = str(flow) - print("Blood flow (measured)) overridden to " + str_res + " mL/min: " + str( - received_message['message'][4])) - # 5th element is OK or not OK - return received_message['message'][4] + print("Blood 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 @@ -557,26 +679,26 @@ spd = self.outer_instance.integer2ByteArray(speed) payload = rst + spd - message = DenaliMessage.buildMessage(channel_id=0x400, - message_id=0x800A, + message = DenaliMessage.buildMessage(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=self.MSG_ID_HD_BLOOD_PUMP_MC_MEAS_SPEED_OVERRIDE, payload=payload) - print("override measured blood pump speed") + print("override measured blood 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 == 1: + if reset == HD.RESET: str_res = "reset back to normal" else: str_res = str(speed) - print("Blood pump speed (measured) overridden to " + str_res + " RPM: " + str( - received_message['message'][4])) - # 5th element is OK or not OK - return received_message['message'][4] + print("Blood 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 @@ -594,30 +716,106 @@ cur = self.outer_instance.integer2ByteArray(curr) payload = rst + cur - message = DenaliMessage.buildMessage(channel_id=0x400, - message_id=0x800B, + message = DenaliMessage.buildMessage(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=self.MSG_ID_HD_BLOOD_PUMP_MC_MEAS_CURRENT_OVERRIDE, payload=payload) - print("override measured blood pump motor current") + print("override measured blood 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 == 1: + if reset == HD.RESET: str_res = "reset back to normal" else: str_res = str(curr) - print("Blood pump current (measured) overridden to " + str_res + " mA: " + str( - received_message['message'][4])) - # 5th element is OK or not OK - return received_message['message'][4] + print("Blood 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 CmdBloodPumpMeasuredSpeedOverride(self, reset, speed): + """ + Constructs and sends the measured blood 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_BLOOD_PUMP_MEAS_SPEED_OVERRIDE, + payload=payload) + + print("override measured blood 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("Blood 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 CmdBloodPumpRotorMeasuredSpeedOverride(self, reset, speed): + """ + Constructs and sends the measured blood 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_BLOOD_PUMP_ROTOR_MEAS_SPEED_OVERRIDE, + payload=payload) + + print("override measured blood 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("Blood 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 CmdBloodFlowBroadcastIntervalOverride(self, reset, ms): """ Constructs and sends the measured flow broadcast interval override command @@ -631,8 +829,8 @@ mis = self.outer_instance.integer2ByteArray(ms) payload = rst + mis - message = DenaliMessage.buildMessage(channel_id=0x400, - message_id=0x800C, + message = DenaliMessage.buildMessage(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=self.MSG_ID_HD_BLOOD_FLOW_PUBLISH_INTERVAL_OVERRIDE, payload=payload) print("override blood flow broadcast interval") @@ -643,30 +841,37 @@ # If there is content... if received_message is not None: print(received_message) - if reset == 1: + if reset == HD.RESET: str_res = "reset back to normal: " else: str_res = str(ms) + " ms: " - print("Blood flow broadcast interval overridden to " + str_res + str(received_message['message'][4])) - # 5th element is OK or not OK - return received_message['message'][4] + print("Blood 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) + + \param val: integer to convert to byte array + \returns byte array + """ fmt = '%08x' # integer to hex string formatter - b = unhexlify(fmt % val) # convert reset int to byte array + b = unhexlify(fmt % val) # convert int to byte array b = b[::-1] # little endian byte order return b - def registerAsyncReceiver(self, message_id, method): - t1 = method - t2 = message_id +# def registerAsyncReceiver(self, message_id, method): +# t1 = method +# t2 = message_id - def registerSyncReceiver(self, message_id, method): - t1 = method - t2 = message_id +# def registerSyncReceiver(self, message_id, method): +# t1 = method +# t2 = message_id if __name__ == "__main__": @@ -690,4 +895,8 @@ hd.BloodFlow.CmdBloodFlowBroadcastIntervalOverride(hd.NO_RESET, 200) tgtRate = hd.BloodFlow.TargetBloodFlowRate + sleep(1) + + print(hd.BloodFlow.MeasuredBloodFlowRate) + # hd.BloodFlow.CmdBloodFlowBroadcastIntervalOverride(hd.RESET,0)