Index: dialin/dg/dialysate_generator.py =================================================================== diff -u -r0035249fd22540886ba093c4e7dc72f9ba8c8353 -r400e03c12e615a00c4e0a770471209fd82e184b8 --- dialin/dg/dialysate_generator.py (.../dialysate_generator.py) (revision 0035249fd22540886ba093c4e7dc72f9ba8c8353) +++ dialin/dg/dialysate_generator.py (.../dialysate_generator.py) (revision 400e03c12e615a00c4e0a770471209fd82e184b8) @@ -26,7 +26,7 @@ from .heaters import Heaters from .temperature_sensors import TemperatureSensors from .conductivity_sensors import ConductivitySensors -from .heat_disinfection import HeatDisinfect +from .heat_disinfect import HeatDisinfect from .thermistors import Thermistors from .fans import Fans from .uv_reactors import UVReactors Index: dialin/dg/heat_disinfect.py =================================================================== diff -u --- dialin/dg/heat_disinfect.py (revision 0) +++ dialin/dg/heat_disinfect.py (revision 400e03c12e615a00c4e0a770471209fd82e184b8) @@ -0,0 +1,113 @@ + +import struct +from ..utils.conversions import integer_to_bytearray +from ..utils.conversions import float_to_bytearray #TODO remove +from ..common.msg_defs import MsgIds, MsgFieldPositions +from ..protocols.CAN import (DenaliMessage, DenaliChannels) +from ..utils.base import _AbstractSubSystem, _publish, DialinEnum +from logging import Logger +from enum import unique + +@unique +class HeatDisinfectStates(DialinEnum): + + DG_HEAT_DISINFECT_STATE_START = 0 + DG_HEAT_DISINFECT_STATE_DRAIN_R1 = 1 + DG_HEAT_DISINFECT_STATE_DRAIN_R2 = 2 + DG_HEAT_DISINFECT_STATE_FLUSH_DRAIN = 3 + DG_HEAT_DISINFECT_STATE_FLUSH_CIRCULATION = 4 + DG_HEAT_DISINFECT_STATE_FLUSH_R1_AND_R2 = 5 + DG_HEAT_DISINFECT_STATE_FLUSH_R2_AND_DRAIN_R1 = 6 + DG_HEAT_DISINFECT_STATE_FLUSH_DRAIN_R2 = 7 + DG_HEAT_DISINFECT_STATE_FLUSH_DRAIN_R1 = 8 + DG_HEAT_DISINFECT_STATE_FILL_WITH_WATER = 9 + DG_HEAT_DISINFECT_STATE_DISINFECT_R1_TO_R2 = 10 + DG_HEAT_DISINFECT_STATE_FILL_R2_WITH_HOT_WATER = 11 + DG_HEAT_DISINFECT_STATE_DISINFECT_R2_TO_R1 = 12 + DG_HEAT_DISINFECT_STATE_MIX_DRAIN_R1 = 13 + DG_HEAT_DISINFECT_STATE_MIX_DRAIN_R2 = 14 + DG_HEAT_DISINFECT_STATE_RINSE_R1_TO_R2 = 15 + DG_HEAT_DISINFECT_STATE_RINSE_R2_TO_R1_AND_DRAIN_R1 = 16 + DG_HEAT_DISINFECT_STATE_RINSE_CIRCULATION = 17 + DG_HEAT_DISINFECT_STATE_CANCEL_MODE_BASIC_PATH = 18 + DG_HEAT_DISINFECT_STATE_CANCEL_MODE_COLD_WATER_PATH = 19 + DG_HEAT_DISINFECT_STATE_CANCEL_MODE_HOT_WATER_PATH = 20 + DG_HEAT_DISINFECT_STATE_COMPLETE = 21 + + +class HeatDisinfect(_AbstractSubSystem): + """ + \class HeatDisinfect + + \brief Heat disinfection class with APIs to set the timing of each of the stages. + """ + + def __init__(self, can_interface, logger: Logger): + + super().__init__() + + self.can_interface = can_interface + self.logger = logger + + self.current_state = 0 + self.overall_elapsed_time = 0 + self.state_elapsed_time = 0 + self.current_cycle_count = 0 #TODO remove + + if self.can_interface is not None: + channel_id = DenaliChannels.dg_sync_broadcast_ch_id + msg_id = MsgIds.MSG_ID_DG_HEAT_DISINFECT_DATA.value + self.can_interface.register_receiving_publication_function(channel_id, msg_id, + self._handler_heat_disinfect_sync) + + @_publish(["current_state", "overall_elapsed_time", "state_elapsed_time"]) + def _handler_heat_disinfect_sync(self, message): + """ + Handles published heat disinfection message + + @param message: published heat disinfection data message + @returns none + """ + state = struct.unpack('i', bytearray( + message['message'][MsgFieldPositions.START_POS_FIELD_1:MsgFieldPositions.END_POS_FIELD_1]))[0] + elapsed_time = struct.unpack('i', bytearray( + message['message'][MsgFieldPositions.START_POS_FIELD_2:MsgFieldPositions.END_POS_FIELD_2]))[0] + state_elapsed_time = struct.unpack('i', bytearray( + message['message'][MsgFieldPositions.START_POS_FIELD_3:MsgFieldPositions.END_POS_FIELD_3]))[0] + + #TODO remove + self.current_state = state#HeatDisinfectStates(state).name if HeatDisinfectStates.has_value(state) else 'Unknown' + self.overall_elapsed_time = int(elapsed_time / 1000) + self.state_elapsed_time = int(state_elapsed_time/1000) + + def cmd_start_stop_heat_disinfect(self, start=True): + """ + Constructs and sends the start/stop DG heat disinfection command + + @param start: (bool) True = start heat disinfection, False = stop heat disinfection. + @return: non-zero integer if successful, False otherwise + """ + # 1 is to start + if start: + cmd = 1 + str = "Starting" + else: + cmd = 0 + str = "Stopping" + payload = integer_to_bytearray(cmd) + message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_dg_ch_id, + message_id=MsgIds.MSG_ID_DG_START_STOP_HEAT_DISINFECT.value, + payload=payload) + + self.logger.debug(str + " DG heat disinfection") + + 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: + self.logger.debug("Timeout!!!!") + return False + Fisheye: Tag 400e03c12e615a00c4e0a770471209fd82e184b8 refers to a dead (removed) revision in file `dialin/dg/heat_disinfection.py'. Fisheye: No comparison available. Pass `N' to diff? Index: dialin/dg/ro_pump.py =================================================================== diff -u -r2cbba85a1d29583fef38e818844c9dbe64933598 -r400e03c12e615a00c4e0a770471209fd82e184b8 --- dialin/dg/ro_pump.py (.../ro_pump.py) (revision 2cbba85a1d29583fef38e818844c9dbe64933598) +++ dialin/dg/ro_pump.py (.../ro_pump.py) (revision 400e03c12e615a00c4e0a770471209fd82e184b8) @@ -26,11 +26,10 @@ @unique class ROPumpStates(DialinEnum): RO_PUMP_OFF_STATE = 0 - RO_PUMP_CONTROL_SETUP_STATE = 1 - RO_PUMP_RAMP_UP_STATE = 2 - RO_PUMP_VERIFY_FLOW_STATE = 3 - RO_PUMP_CONTROL_TO_TARGET_STATE = 4 - RO_PUMP_OPEN_LOOP_STATE = 5 + RO_PUMP_RAMP_UP_TO_TARGET_FLOW_STATE = 1 + RO_PUMP_CONTROL_TO_TARGET_FLOW_STATE = 2 + RO_PUMP_CONTROL_TO_MAX_PRESSURE_STATE = 3 + RO_PUMP_OPEN_LOOP_STATE = 4 class DGROPump(_AbstractSubSystem): Index: tests/dg_heat_disinfect_test.py =================================================================== diff -u -r2cbba85a1d29583fef38e818844c9dbe64933598 -r400e03c12e615a00c4e0a770471209fd82e184b8 --- tests/dg_heat_disinfect_test.py (.../dg_heat_disinfect_test.py) (revision 2cbba85a1d29583fef38e818844c9dbe64933598) +++ tests/dg_heat_disinfect_test.py (.../dg_heat_disinfect_test.py) (revision 400e03c12e615a00c4e0a770471209fd82e184b8) @@ -5,33 +5,31 @@ from dialin.dg.dialysate_generator import DG from dialin.hd.hemodialysis_device import HD from dialin.dg.hd_proxy import DGHDProxy -from dialin.dg.heat_disinfection import HeatDisinfectStates +from dialin.dg.heat_disinfect import HeatDisinfectStates from dialin.dg.drain_pump import DrainPumpStates +from dialin.dg.ro_pump import ROPumpStates from dialin.dg.thermistors import Thermistors from dialin.dg.uv_reactors import ReactorsStates from dialin.dg.thermistors import ThermistorsNames from dialin.dg.temperature_sensors import TemperatureSensorsNames from time import sleep -if __name__ == "__main__": +def run_ro_pump_test(): - dg = DG(log_level='DEBUG') - dg.cmd_log_in_to_dg() - sleep(1) f = open("RO_Pump_Low.log", "w") - try: dg.hd_proxy.cmd_start_stop_dg() - sleep(1) while True: - sleep(0.1) - var = "Mode, {}, Duty, {:5.3f}, Pres, {:5.3f}, Tgt_Pres, {:5.3f}, Flow, {:5.3f}, State, {}\r".format( - dg.dg_operation_mode, - dg.ro_pump.pwm_duty_cycle_pct, - dg.pressures.ro_pump_outlet_pressure, - dg.ro_pump.target_pressure_psi, - dg.ro_pump.measured_flow_rate_lpm, - dg.ro_pump.ro_pump_state) + sleep(0.5) + var = "Mode, {}, Sub-Mode, {}, Duty, {:5.3f}, Pres, {:5.3f}, Tgt_Pres, {:5.3f}, Flow, {:5.3f}, " \ + "State, {}\r".format( + dg.dg_operation_mode, + dg.dg_operation_sub_mode, + dg.ro_pump.pwm_duty_cycle_pct, + dg.pressures.ro_pump_outlet_pressure, + dg.ro_pump.target_pressure_psi, + dg.ro_pump.measured_flow_rate_lpm, + dg.ro_pump.ro_pump_state) print(var) f.write(var) @@ -40,97 +38,85 @@ f.close() - """" - while True: - sleep(0.5) +def get_heat_disinfect_mode_info(): - print('BoardT, {}, Inlet, {}, Outlet, {}, CP1, {}, CP2, {}, OutletR, {}, InletD, {}, ' - 'PHThe, {}, THThe, {}, PHCJ, {}, THCJ, {}, PHInt, {}, THInt, {}, FPGA, {}, ' - 'LCA1B1, {}, LCA2B2, {}, InTHDo, {}, IntTDi, {}, IntCond, {} Fan1, {}, Fan2, {}' - .format(dg.thermistors.thermistors[ThermistorsNames.THERMISTOR_ONBOARD_NTC.name], - dg.temperature_sensors.temperature_sensors[TemperatureSensorsNames.INLET_PRIMARY_HEATER.name], - dg.temperature_sensors.temperature_sensors[TemperatureSensorsNames.OUTLET_PRIMARY_HEATER.name], - dg.temperature_sensors.temperature_sensors[TemperatureSensorsNames.CONDUCTIVITY_SENSOR_1.name], - dg.temperature_sensors.temperature_sensors[TemperatureSensorsNames.CONDUCTIVITY_SENSOR_2.name], - dg.temperature_sensors.temperature_sensors[TemperatureSensorsNames.OUTLET_DIALYSATE_REDUNDANT.name], - dg.temperature_sensors.temperature_sensors[TemperatureSensorsNames.INLET_DIALYSATE.name], - dg.temperature_sensors.temperature_sensors[TemperatureSensorsNames.PRIMARY_HEATER_THERMOCOUPLE.name], - dg.temperature_sensors.temperature_sensors[TemperatureSensorsNames.TRIMMER_HEATER_THERMOCOUPLE.name], - dg.temperature_sensors.temperature_sensors[TemperatureSensorsNames.PRIMARY_HEATER_COLD_JUNCTION.name], - dg.temperature_sensors.temperature_sensors[TemperatureSensorsNames.TRIMMER_HEATER_COLD_JUNCTION.name], - dg.temperature_sensors.temperature_sensors[TemperatureSensorsNames.PRIMARY_HEATER_INTERNAL.name], - dg.temperature_sensors.temperature_sensors[TemperatureSensorsNames.TRIMMER_HEATER_INTERNAL.name], - dg.temperature_sensors.temperature_sensors[TemperatureSensorsNames.FPGA_BOARD_SENSOR.name], - dg.temperature_sensors.temperature_sensors[TemperatureSensorsNames.LOAD_CELL_A1_B1.name], - dg.temperature_sensors.temperature_sensors[TemperatureSensorsNames.LOAD_CELL_A2_B2.name], - dg.temperature_sensors.temperature_sensors[TemperatureSensorsNames.INTERNAL_THDO_RTD.name], - dg.temperature_sensors.temperature_sensors[TemperatureSensorsNames.INTERNAL_TDI_RTD.name], - dg.temperature_sensors.temperature_sensors[TemperatureSensorsNames.INTERNAL_COND_TEMP_SENSOR.name], - dg.fans.inlet_1_rpm, dg.fans.inlet_2_rpm)) - + info = ('State, {}, Overall_time, {}, State_elapsed_time, {},' + .format(HeatDisinfectStates(dg.heat_disinfect.current_state).name, dg.heat_disinfect.overall_elapsed_time, + dg.heat_disinfect.state_elapsed_time)) + return info - f = open("Heat_disinfection.txt", "w") - #dg.drain_pump.cmd_drain_pump_speed_set_point_override(2800) +def get_dg_valves_states(): - #dg.valves.cmd_valve_override(0, dg.valves.VALVE_PRESSURE_OUTLET ) - #sleep(1) - #dg.valves.cmd_valve_override(0, dg.valves.VALVE_RESERVOIR_OUTLET) - #dg.valves.cmd_valve_override(1, dg.valves.VALVE_RESERVOIR_INLET) - #dg.heat_disinfect.cmd_start_stop_heat_disinfection(start=False) - #sleep(1) - #time = 1 + info = ('VPi, {}, VSP, {}, VPd, {}, VBf, {}, VPo, {}, VDr, {}, VRc, {}, VRo, {}, VRd, {}, VRi, {}, VRf, {},' + .format(dg.valves.valve_states_enum[dg.valves.VALVE_PRESSURE_INLET], + dg.valves.valve_states_enum[dg.valves.VALVE_SAMPLING_PORT], + dg.valves.valve_states_enum[dg.valves.VALVE_PRODUCTION_DRAIN], + dg.valves.valve_states_enum[dg.valves.VALVE_BYPASS_FILTER], + dg.valves.valve_states_enum[dg.valves.VALVE_PRESSURE_OUTLET], + dg.valves.valve_states_enum[dg.valves.VALVE_DRAIN], + dg.valves.valve_states_enum[dg.valves.VALVE_RECIRCULATE], + dg.valves.valve_states_enum[dg.valves.VALVE_RESERVOIR_OUTLET], + dg.valves.valve_states_enum[dg.valves.VALVE_RESERVOIR_DRAIN], + dg.valves.valve_states_enum[dg.valves.VALVE_RESERVOIR_INLET], + dg.valves.valve_states_enum[dg.valves.VALVE_RESERVOIR_FILL])) + return info - dg.heat_disinfect.cmd_start_stop_heat_disinfection() +def get_drain_states_info(): + + info = ('Drain, {}, DAC, {}, PRd, {:5.3f}, PDr, {:5.3f}'.format(DrainPumpStates(dg.drain_pump.drain_pump_state).name, + dg.drain_pump.dac_value, dg.pressures.drain_pump_inlet_pressure, dg.pressures.drain_pump_outlet_pressure)) + return info + + +def get_load_cells_info(): + + info = ('Primary_A1, {:5.3f}, Primary_B1, {:5.3f},'.format(dg.load_cells.load_cell_A1, dg.load_cells.load_cell_B1)) + return info + + +def get_ro_info(): + + info = ('RO, {}, PPi, {:5.3f}, PPo, {:5.3f}, PWM, {:5.3f}, Flow, {:5.3f},' + .format(dg.ro_pump.ro_pump_state, dg.pressures.ro_pump_outlet_pressure, + dg.pressures.ro_pump_outlet_pressure, dg.ro_pump.pwm_duty_cycle_pct, + dg.ro_pump.measured_flow_rate_lpm)) + return info + + +def run_heat_disinfect(): + + f = open("Heat_disinfection.log", "w") + dg.heat_disinfect.cmd_start_stop_heat_disinfect() try: while True: - - var = ('Mode, {}, State, {}, Sub, {}, RO, {}, Drain, {}, VPi, {}, VBf, {}, VSP, {}, VPd, {}, VPo, {}, VDr, {}, ' - 'VRc, {}, VRo, {}, VRd, {}, VRi, {}, VRf, {}\r' - .format(dg.dg_operation_mode, - HeatDisinfectStates(dg.dg_operation_sub_mode).name, - HeatDisinfectionInternalStates(dg.heat_disinfect.current_state).name, - dg.ro_pump.ro_pump_state, - DrainPumpStates(dg.drain_pump.drain_pump_state).name, - dg.valves.valve_states_enum[dg.valves.VALVE_PRESSURE_INLET], - dg.valves.valve_states_enum[dg.valves.VALVE_BYPASS_FILTER], - dg.valves.valve_states_enum[dg.valves.VALVE_SAMPLING_PORT], - dg.valves.valve_states_enum[dg.valves.VALVE_PRODUCTION_DRAIN], - dg.valves.valve_states_enum[dg.valves.VALVE_PRESSURE_OUTLET], - dg.valves.valve_states_enum[dg.valves.VALVE_DRAIN], - dg.valves.valve_states_enum[dg.valves.VALVE_RECIRCULATE], - dg.valves.valve_states_enum[dg.valves.VALVE_RESERVOIR_OUTLET], - dg.valves.valve_states_enum[dg.valves.VALVE_RESERVOIR_DRAIN], - dg.valves.valve_states_enum[dg.valves.VALVE_RESERVOIR_INLET], - dg.valves.valve_states_enum[dg.valves.VALVE_RESERVOIR_FILL])) - - var = ('Mode, {}, State, {}, RO, {}, Flow, {:5.3f}, TgtPres, {:5.3f}, InletPres, {:5.3f}, ' - 'OutletPres, {:5.3f}, PWM, {:5.3f}, Drain, {}, DInletPres, {:5.3f}, DOutletPres, {:5.3f}, ' - 'DrainDAC, {:5.3f}, R1, {:5.3f}, R2, {:5.3f}, TPi, {:5.3f}, TPo, {:5.3f}, TDi, {:5.3f} \r' - .format(dg.dg_operation_mode, - HeatDisinfectionStates(dg.dg_operation_sub_mode).name, - dg.ro_pump.ro_pump_state, - dg.ro_pump.measured_flow_rate_lpm, - dg.ro_pump.target_pressure_psi, - dg.pressures.ro_pump_inlet_pressure, - dg.pressures.ro_pump_outlet_pressure, - dg.ro_pump.pwm_duty_cycle_pct, - DrainPumpStates(dg.drain_pump.drain_pump_state).name, - dg.pressures.drain_pump_inlet_pressure, - dg.pressures.drain_pump_outlet_pressure, dg.drain_pump.dac_value, - dg.load_cells.load_cell_A1, - dg.load_cells.load_cell_B1, - dg.temperature_sensors.inlet_primary, dg.temperature_sensors.outlet_primary, - dg.temperature_sensors.outlet_redundancy)) + disinfect = get_heat_disinfect_mode_info() + drain = get_drain_states_info() + load_cell = get_load_cells_info() + valves = get_dg_valves_states() + ro = get_ro_info() + + var = disinfect + ' ' + drain + ' ' + load_cell + ' ' + ro + ' ' + valves + '\r' + print(var) f.write(var) - sleep(0.25) - - + sleep(1) + except KeyboardInterrupt: - dg.hd_proxy.cmd_start_stop_dg(start=False) - dg.heat_disinfect.cmd_start_stop_heat_disinfection(start=False) + dg.heat_disinfect.cmd_start_stop_heat_disinfect(start=False) f.close() - """"" \ No newline at end of file + + +if __name__ == "__main__": + + dg = DG(log_level='DEBUG') + dg.cmd_log_in_to_dg() + sleep(1) + + #run_ro_pump_test() + + run_heat_disinfect() + +