Index: dialin/hd/hemodialysis_device.py =================================================================== diff -u -ra03128f183206dc430bc0e27f43d7f3aee62672d -r466c5e664fc45118fabad5bbaf930dcfe0c4f154 --- dialin/hd/hemodialysis_device.py (.../hemodialysis_device.py) (revision a03128f183206dc430bc0e27f43d7f3aee62672d) +++ dialin/hd/hemodialysis_device.py (.../hemodialysis_device.py) (revision 466c5e664fc45118fabad5bbaf930dcfe0c4f154) @@ -26,6 +26,7 @@ from .dialysate_outlet_flow import HDDialysateOutletFlow from .treatment import HDTreatment from .pressure_occlusion import HDPressureOcclusion +from .valves import HDValves from ..protocols.CAN import (DenaliMessage, DenaliCanMessenger, DenaliChannels) @@ -98,6 +99,7 @@ self.dialysate_outlet_flow = HDDialysateOutletFlow(self.can_interface) self.treatment = HDTreatment(self.can_interface) self.pressure_occlusion = HDPressureOcclusion(self.can_interface) + self.valves = HDValves(self.can_interface) def handler_hd_op_mode_sync(self, message): """ Index: dialin/hd/valves.py =================================================================== diff -u --- dialin/hd/valves.py (revision 0) +++ dialin/hd/valves.py (revision 466c5e664fc45118fabad5bbaf930dcfe0c4f154) @@ -0,0 +1,121 @@ + + +import struct +from ..utils.conversions import integer_to_bytearray +from .constants import NO_RESET +from ..protocols.CAN import (DenaliMessage, DenaliChannels) + +class HDValves: + """ + \class HDValves + + \brief Hemodialysis Device (HD) Dialin API sub-class for valves related commands. + """ + + # Valve state message IDs + MSG_ID_HD_VALVES_DATA = 0x3A + MSG_ID_HD_VALVES_SEND_INTERVAL_OVERRIDE = 0xA022 + MSG_ID_HD_VALVES_HOME = 0xA023 + + # Valves states publish message field positions + START_POS_VALVES_ID = DenaliMessage.PAYLOAD_START_INDEX + END_POS_VALVES_ID = START_POS_VALVES_ID + 4 + START_VALVES_STATE = END_POS_VALVES_ID + END_VALVES_STATE = START_VALVES_STATE + 4 + START_POS_VALVES_CURR_POS = END_VALVES_STATE + END_POS_VALVES_CURR_POS = START_POS_VALVES_CURR_POS + 4 + START_POS_VALVES_CURR_POS_CNT = END_POS_VALVES_CURR_POS + END_POS_VALVES_CURR_POS_CNT = START_POS_VALVES_CURR_POS_CNT + 2 + START_POS_VALVES_NEXT_POS_CNT = END_POS_VALVES_CURR_POS_CNT + END_POS_VALVES_NEXT_POS_CNT = START_POS_VALVES_NEXT_POS_CNT + 2 + START_POS_VALVES_CURRENT = END_POS_VALVES_NEXT_POS_CNT + END_POS_VALVES_CURRENT = START_POS_VALVES_CURRENT + 4 + START_VALVES_PREV_POS_CNT = END_POS_VALVES_CURRENT + END_VALVES_PREV_POS_CNT = START_VALVES_PREV_POS_CNT + 2 + + def __init__(self, can_interface=None): + """ + DGDrainPump constructor + + \param outer_instance: reference to the DG (outer) class. + """ + self.can_interface = can_interface + + if self.can_interface is not None: + channel_id = DenaliChannels.hd_sync_broadcast_ch_id + msg_id = self.MSG_ID_HD_VALVES_DATA + self.can_interface.register_receiving_publication_function(channel_id, msg_id, + self.handler_hd_valves_sync) + + self.states = ["VALVE_STATE_WAIT_FOR_POST", "VALVE_STATE_IDLE", "VALVE_STATE_IN_TRANSITION", + "VALVE_STATE_HOMING_NOT_STARTED", "VALVE_STATE_HOMING_FIND_ENERGIZED_EDGE", + "VALVE_STATE_HOMING_FIND_DEENERGIZED_EDGE"] + + self.positions = ["VALVE_POSITION_NOT_IN_POSITION", "VALVE_POSITION_A_INSERT_EJECT", + "VALVE_POSITION_B_OPEN", "VALVE_POSITION_C_CLOSE"] + + self.valves = ["VDI", "VDO", "VBA", "VBV"] + + self.hd_valve_ID = 0 + self.hd_valve_state = 0 + self.hd_valve_curr_pos_ID = 0 + self.hd_valve_curr_pos_cnt = 0 + self.hd_valve_prev_pos_cnt = 0 + self.hd_valve_next_pos_cnt = 0 + self.hd_valve_current = 0 + + def cmd_home_hd_valve(self, valve): + """ + Constructs and sends the HD valves home command + + \param vavle: integer - Valve number to be homed (from 0 to 3) + \returns 1 if successful, zero otherwise + """ + #index = self.valves.index(valve) + + payload = integer_to_bytearray(valve) + + message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_hd_ch_id, + message_id=self.MSG_ID_HD_VALVES_HOME, + payload=payload) + # Send message + received_message = self.can_interface.send(message) + + # If there is content... + if received_message is not None: + # response payload is OK or not OK + return received_message['message'][DenaliMessage.PAYLOAD_START_INDEX] + else: + print("HD cmd_valve_override Timeout!!!") + return False + + def handler_hd_valves_sync(self, message): + """ + Handles published HD valves data messages. HD valves data are captured + for reference. + + \param message: published HD valves data message + \returns none + """ + vlv_ID = struct.unpack('i', bytearray( + message['message'][self.START_POS_VALVES_ID:self.END_POS_VALVES_ID])) + state_ID = struct.unpack('i', bytearray( + message['message'][self.START_VALVES_STATE:self.END_VALVES_STATE])) + pos_ID = struct.unpack('i', bytearray( + message['message'][self.START_POS_VALVES_CURR_POS:self.END_POS_VALVES_CURR_POS])) + pos_cnt = struct.unpack('h', bytearray( + message['message'][self.START_POS_VALVES_CURR_POS_CNT:self.END_POS_VALVES_CURR_POS_CNT])) + next_pos = struct.unpack('h', bytearray( + message['message'][self.START_POS_VALVES_NEXT_POS_CNT:self.END_POS_VALVES_NEXT_POS_CNT])) + current = struct.unpack('f', bytearray( + message['message'][self.START_POS_VALVES_CURRENT:self.END_POS_VALVES_CURRENT])) + prev_pos = struct.unpack('h', bytearray( + message['message'][self.START_VALVES_PREV_POS_CNT:self.END_VALVES_PREV_POS_CNT])) + + self.hd_valve_ID = self.valves[vlv_ID[0]] + self.hd_valve_state = self.states[state_ID[0]] + self.hd_valve_curr_pos_ID = self.positions[pos_ID[0]] + self.hd_valve_curr_pos_cnt = pos_cnt[0] + self.hd_valve_prev_pos_cnt = prev_pos[0] + self.hd_valve_next_pos_cnt = next_pos[0] + self.hd_valve_current = current[0] \ No newline at end of file Index: tests/hd_valves_test.py =================================================================== diff -u --- tests/hd_valves_test.py (revision 0) +++ tests/hd_valves_test.py (revision 466c5e664fc45118fabad5bbaf930dcfe0c4f154) @@ -0,0 +1,24 @@ +import sys +sys.path.append("..") +from dialin.hd.constants import RESET, NO_RESET +from dialin.hd.hemodialysis_device import HD +from time import sleep + +if __name__ == "__main__": + # Create an instance of the DG Class + hd = HD() + + if hd.cmd_log_in_to_hd() == 0: + exit(1) + + valves = hd.valves + + valves.cmd_home_hd_valve(1) + + while True: + print("Valve, {}, State, {}, Curr_Pos_ID, {}, Prev_Pos_Cnt, {}, Curr_Pos_Cnt {}, Next_Pos_Cnt {}, Current, {}" + .format(valves.hd_valve_ID, valves.hd_valve_state, valves.hd_valve_curr_pos_ID, + valves.hd_valve_prev_pos_cnt, valves.hd_valve_curr_pos_cnt, valves.hd_valve_next_pos_cnt, + valves.hd_valve_current)) + + sleep(0.1)