Index: dialin/dg/pressures.py =================================================================== diff -u -r7b2d65304d1cc925e5000d9621fa195ce6a08cf1 -rc260906118f578a6d20e5579ed660466ee874fee --- dialin/dg/pressures.py (.../pressures.py) (revision 7b2d65304d1cc925e5000d9621fa195ce6a08cf1) +++ dialin/dg/pressures.py (.../pressures.py) (revision c260906118f578a6d20e5579ed660466ee874fee) @@ -160,4 +160,3 @@ else: print("Timeout!!!!") return False - Index: dialin/dg/valves.py =================================================================== diff -u --- dialin/dg/valves.py (revision 0) +++ dialin/dg/valves.py (revision c260906118f578a6d20e5579ed660466ee874fee) @@ -0,0 +1,219 @@ +########################################################################### +# +# 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 valves.py +# +# @date 6-May-2020 +# @author P. Montazemi +# +# @brief +# +# +############################################################################ + +import struct +from ..utils.conversions import integer_to_bytearray, float_to_bytearray +from .constants import NO_RESET +from ..protocols.CAN import (DenaliMessage, DenaliChannels) + +class DGValves: + """ + \class DGValves + + \brief Dialysate Generation (DG) Device Dialin API sub-class for valve related commands. + """ + + # Valve state message IDs + MSG_ID_DG_VALVES_STATES = 0x2A + MSG_ID_DG_VALVE_STATE_OVERRIDE = 0xA00E + MSG_ID_DG_VALVES_STATES_PUBLISH_INTERVAL_OVERRIDE = 0xA00F + + # Valve state publish message field positions + START_POS_VALVE_VRF = DenaliMessage.PAYLOAD_START_INDEX + END_POS_VALVE_VRF = START_POS_VALVE_VRF + 4 + START_POS_VALVE_VRI = END_POS_VALVE_VRF + 4 + END_POS_VALVE_VRI = START_POS_VALVE_VRI + 4 + START_POS_VALVE_VRD = END_POS_VALVE_VRI + 4 + END_POS_VALVE_VRD = START_POS_VALVE_VRD + 4 + START_POS_VALVE_VRO = END_POS_VALVE_VRD + 4 + END_POS_VALVE_VRO = START_POS_VALVE_VRO + 4 + START_POS_VALVE_VPO = END_POS_VALVE_VRO + 4 + END_POS_VALVE_VPO = START_POS_VALVE_VPO + 4 + START_POS_VALVE_VBF = END_POS_VALVE_VPO + 4 + END_POS_VALVE_VBF = START_POS_VALVE_VBF + 4 + START_POS_VALVE_VRC = END_POS_VALVE_VBF + 4 + END_POS_VALVE_VRC = START_POS_VALVE_VRC + 4 + START_POS_VALVE_VDR = END_POS_VALVE_VRC + 4 + END_POS_VALVE_VDR = START_POS_VALVE_VDR + 4 + START_POS_VALVE_VPI = END_POS_VALVE_VDR + 4 + END_POS_VALVE_VPI = START_POS_VALVE_VPI + 4 + START_POS_VALVE_VSP = END_POS_VALVE_VPI + 4 + END_POS_VALVE_VSP = START_POS_VALVE_VSP + 4 + START_POS_VALVE_VR1 = END_POS_VALVE_VSP + 4 + END_POS_VALVE_VR1 = START_POS_VALVE_VR1 + 4 + START_POS_VALVE_VR2 = END_POS_VALVE_VR1 + 4 + END_POS_VALVE_VR2 = START_POS_VALVE_VR2 + 4 + START_POS_VALVE_VPD = END_POS_VALVE_VR2 + 4 + END_POS_VALVE_VPD = START_POS_VALVE_VPD + 4 + + # Valve IDs + VALVE_RESERVOIR_FILL = 0 # VRF + VALVE_RESERVOIR_INLET = 1 # VRI + VALVE_RESERVOIR_DRAIN = 2 # VRD + VALVE_RESERVOIR_OUTLET = 3 # VRO + VALVE_PRESSURE_OUTLET = 4 # VPO + VALVE_BYPASS_FILTER = 5 # VBF + VALVE_RECIRCULATE = 6 # VRC + VALVE_DRAIN = 7 # VDR + VALVE_PRESSURE_INLET = 8 # VPI + VALVE_SAMPLING_PORT = 9 # VSP + VALVE_RESERVOIR_1 = 10 # VR1 + VALVE_RESERVOIR_2 = 11 # VR2 + VALVE_PRODUCTION_DRAIN = 12 # VPD + + def __init__(self, can_interface=None): + """ + DGValves constructor + + \param outer_instance: reference to the DG (outer) class. + + \returns DGValvesStates object. + """ + self.can_interface = can_interface + + if self.can_interface is not None: + channel_id = DenaliChannels.dg_sync_broadcast_ch_id + msg_id = self.MSG_ID_DG_VALVES_STATES + self.can_interface.register_receiving_publication_function(channel_id, msg_id, self.handler_valves_sync) + + self.valve_state_VRF = 0 + self.valve_state_VRI = 0 + self.valve_state_VRD = 0 + self.valve_state_VRO = 0 + self.valve_state_VPO = 0 + self.valve_state_VBF = 0 + self.valve_state_VRC = 0 + self.valve_state_VDR = 0 + self.valve_state_VPI = 0 + self.valve_state_VSP = 0 + self.valve_state_VR1 = 0 + self.valve_state_VR2 = 0 + self.valve_state_VPD = 0 + + def handler_valves_sync(self, message): + """ + Handles published valves states messages. Valves states are captured for reference. + + \param message: published valves states message + \returns none + """ + + vrf = struct.unpack('f', bytearray(message['message'][self.START_POS_VALVE_VRF:self.END_POS_VALVE_VRF])) + vri = struct.unpack('f', bytearray(message['message'][self.START_POS_VALVE_VRI:self.END_POS_VALVE_VRI])) + vrd = struct.unpack('f', bytearray(message['message'][self.START_POS_VALVE_VRD:self.END_POS_VALVE_VRD])) + vro = struct.unpack('f', bytearray(message['message'][self.START_POS_VALVE_VRO:self.END_POS_VALVE_VRO])) + vpo = struct.unpack('f', bytearray(message['message'][self.START_POS_VALVE_VPO:self.END_POS_VALVE_VPO])) + vbf = struct.unpack('f', bytearray(message['message'][self.START_POS_VALVE_VBF:self.END_POS_VALVE_VBF])) + vrc = struct.unpack('f', bytearray(message['message'][self.START_POS_VALVE_VRC:self.END_POS_VALVE_VRC])) + vdr = struct.unpack('f', bytearray(message['message'][self.START_POS_VALVE_VDR:self.END_POS_VALVE_VDR])) + vpi = struct.unpack('f', bytearray(message['message'][self.START_POS_VALVE_VPI:self.END_POS_VALVE_VPI])) + vsp = struct.unpack('f', bytearray(message['message'][self.START_POS_VALVE_VSP:self.END_POS_VALVE_VSP])) + vr1 = struct.unpack('f', bytearray(message['message'][self.START_POS_VALVE_VR1:self.END_POS_VALVE_VR1])) + vr2 = struct.unpack('f', bytearray(message['message'][self.START_POS_VALVE_VR2:self.END_POS_VALVE_VR2])) + vpd = struct.unpack('f', bytearray(message['message'][self.START_POS_VALVE_VPD:self.END_POS_VALVE_VPD])) + + self.valve_state_VRF = vrf[0] + self.valve_state_VRI = vri[0] + self.valve_state_VRD = vrd[0] + self.valve_state_VRO = vro[0] + self.valve_state_VPO = vpo[0] + self.valve_state_VBF = vbf[0] + self.valve_state_VRC = vrc[0] + self.valve_state_VDR = vdr[0] + self.valve_state_VPI = vpi[0] + self.valve_state_VSP = vsp[0] + self.valve_state_VR1 = vr1[0] + self.valve_state_VR2 = vr2[0] + self.valve_state_VPD = vpd[0] + + def cmd_valve_override(self, state, valve, reset=NO_RESET): + """ + Constructs and sends the valve state override command + + \param state: unsigned int - valve state + \param valve: unsigned int - valve ID + \param reset: integer - 1 to reset a previous override, 0 to override + \returns 1 if successful, zero otherwise + + \details valve IDs: \n + 0 = Valve Reservoir Fill + 1 = Valve Reservoir Inlet + 2 = Valve Reservoir Drain + 3 = Valve Reservoir Outlet + 4 = Valve Pressure Outlet + 5 = Valve Bypass Filter + 6 = Valve Recirculate + 7 = Valve Drain + 8 = Valve Pressure Inlet + 9 = Valve Sampling Port + 10 = Valve Reservoir 1 (spare for now including DG FPGA, as valve is of passive air relief type) + 11 = Valve Reservoir 2 (spare for now including DG FPGA, as valve is of passive air relief type) + 12 = Valve Production Drain + """ + + rst = integer_to_bytearray(reset) + ste = float_to_bytearray(state) + vlv = integer_to_bytearray(valve) + payload = rst + ste + vlv + + message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_dg_ch_id, + message_id=self.MSG_ID_DG_VALVE_STATE_OVERRIDE, + payload=payload) + + print("override valve state") + + # 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("Timeout!!!!") + return False + + def cmd_valve_broadcast_interval_override(self, ms, reset=NO_RESET): + """ + Constructs and sends the valve state override command + + \param ms: unsigned int - broadcast interval (in ms) + \param reset: integer - 1 to reset a previous override, 0 to override + \returns 1 if successful, zero otherwise + + """ + + rst = integer_to_bytearray(reset) + ivl = integer_to_bytearray(ms) + payload = rst + ivl + + message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_dg_ch_id, + message_id=self.MSG_ID_DG_VALVES_STATES_PUBLISH_INTERVAL_OVERRIDE, + payload=payload) + + print("override valves states publish interval") + + # 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("Timeout!!!!") + return False