Index: dialin/common/dg_defs.py =================================================================== diff -u -r107697bd31dc87e450f18cca334025c631a6825d -rb85f0e224e74d44979c955528b0c81935710a189 --- dialin/common/dg_defs.py (.../dg_defs.py) (revision 107697bd31dc87e450f18cca334025c631a6825d) +++ dialin/common/dg_defs.py (.../dg_defs.py) (revision b85f0e224e74d44979c955528b0c81935710a189) @@ -74,7 +74,25 @@ @unique -class HeatDisinfectStates(DialinEnum): +class DGFlushStates(DialinEnum): + DG_FLUSH_STATE_START = 0 + DG_FLUSH_STATE_DRAIN_R1 = 1 + DG_FLUSH_STATE_DRAIN_R2 = 2 + DG_FLUSH_STATE_FLUSH_DRAIN = 3 + DG_FLUSH_STATE_FLUSH_DIALYSATE = 4 + DG_FLUSH_STATE_FLUSH_CONCENTRATE_STRAWS = 5 + DG_FLUSH_STATE_FLUSH_R1_TO_R2 = 6 + DG_FLUSH_STATE_FLUSH_R2_AND_DRAIN_R1 = 7 + DG_FLUSH_STATE_FLUSH_CIRCULATION_DRAIN_LINE = 8 + DG_FLUSH_STATE_FLUSH_CIRCULATION = 9 + DG_FLUSH_STATE_FLUSH_WITH_FRESH_WATER = 10 + DG_FLUSH_STATE_CANCEL_BASIC_PATH = 11 + DG_FLUSH_STATE_CANCEL_WATER_PATH = 12 + DG_FLUSH_STATE_COMPLETE = 13 + + +@unique +class DGHeatDisinfectStates(DialinEnum): DG_HEAT_DISINFECT_STATE_START = 0 # Heat disinfect, start mode state DG_HEAT_DISINFECT_STATE_DRAIN_R1 = 1 # Heat disinfect, drain R1 state DG_HEAT_DISINFECT_STATE_DRAIN_R2 = 2 # Heat disinfect, drain R2 state @@ -102,8 +120,7 @@ @unique -class HeatDisinfectUIStates(DialinEnum): - +class DGHeatDisinfectUIStates(DialinEnum): HEAT_DISINFECT_UI_STATE_NOT_RUNNING = 0 HEAT_DISINFECT_UI_STATE_FLUSH_BEFORE_DISINFECT = 1 HEAT_DISINFECT_UI_STATE_HEAT_UP_WATER = 2 @@ -117,7 +134,7 @@ @unique -class ChemicalDisinfectStates(DialinEnum): +class DGChemicalDisinfectStates(DialinEnum): DG_CHEM_DISINFECT_STATE_START = 0 DG_CHEM_DISINFECT_STATE_DRAIN_R1 = 1 DG_CHEM_DISINFECT_STATE_DRAIN_R2 = 2 @@ -146,7 +163,7 @@ @unique -class ChemDisinfectUIStates(DialinEnum): +class DGChemDisinfectUIStates(DialinEnum): CHEM_DISINFECT_UI_STATE_NOT_RUNNING = 0 CHEM_DISINFECT_UI_STATE_FLUSH_BEFORE_DISINFECT = 1 CHEM_DISINFECT_UI_STATE_MIX_WATER_AND_ACID = 2 Index: dialin/dg/events.py =================================================================== diff -u -r1936d2c112d7629ddef976e2bd4cba60664c621f -rb85f0e224e74d44979c955528b0c81935710a189 --- dialin/dg/events.py (.../events.py) (revision 1936d2c112d7629ddef976e2bd4cba60664c621f) +++ dialin/dg/events.py (.../events.py) (revision b85f0e224e74d44979c955528b0c81935710a189) @@ -1,8 +1,7 @@ import struct from logging import Logger - -from ..common import DGEventList, DGEventDataType +from ..common import * from ..common.msg_defs import MsgIds, MsgFieldPositions from ..protocols.CAN import DenaliChannels from ..utils.base import AbstractSubSystem, publish @@ -33,6 +32,15 @@ self._dg_event_dictionary = dict() self._dg_event_data_type = dict() + # Dictionary of the the mode as key and the sub mode states enum class as the value + self._dg_op_mode_2_sub_mode = {DGOpModes.DG_MODE_STAN.name: DGStandByModeStates, + DGOpModes.DG_MODE_CIRC.name: DGRecircModeStates, + DGOpModes.DG_MODE_FILL.name: DGFillModeStates, + DGOpModes.DG_MODE_DRAI.name: DGDrainModeStates, + DGOpModes.DG_MODE_FLUS.name: DGFlushStates, + DGOpModes.DG_MODE_HEAT.name: DGHeatDisinfectStates, + DGOpModes.DG_MODE_CHEM.name: DGChemicalDisinfectStates} + # Loop through the list of the DG events enums and initial the event dictionary. Each event is a key in the # dictionary and the value is a list. for event in DGEventList: @@ -121,16 +129,60 @@ event_data_type_2 = struct.unpack('i', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_4:MsgFieldPositions.END_POS_FIELD_4]))[0] - struct_data_type = self._dg_event_data_type[DGEventDataType(event_data_type_2).name] event_data_2 = struct.unpack(struct_data_type, bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_5:MsgFieldPositions.END_POS_FIELD_5]))[0] # Convert the event ID to enum event_state_name = DGEventList(event_id).name + # Check if the event state name is operation mode change. If it is, get the name of the operation modes + # from the op modes enum class + if event_state_name == DGEventList.DG_EVENT_OP_MODE_CHANGE.name: + event_data_1 = DGOpModes(event_data_1).name + event_data_2 = DGOpModes(event_data_2).name + # Check if the event state name is sub mode change. + elif event_state_name == DGEventList.DG_EVENT_SUB_MODE_CHANGE.name: + # Get the length of the list of the sub mode list + event_list_len = len(self._dg_event_dictionary[DGEventList.DG_EVENT_OP_MODE_CHANGE.name]) + # Get the last tuple of the sub mode + # It is a list of tuples that each tuple is (timestamp, event type, prev op mode, current op mode) + last_op_mode = self._dg_event_dictionary[DGEventList.DG_EVENT_OP_MODE_CHANGE.name][event_list_len - 1] + # Get the current and previous operation modes of the last tuple in the list of the sub modes + # i.e. (timestamp, event type, prev, current) + last_current = last_op_mode[len(last_op_mode) - 1] + last_previous = last_op_mode[len(last_op_mode) - 2] + + # Get the tuple prior to the last tuple and get its previous and current operation modes + prev_to_last_op = self._dg_event_dictionary[DGEventList.DG_EVENT_OP_MODE_CHANGE.name][event_list_len - 2] + prev_current = prev_to_last_op[len(prev_to_last_op) - 1] + prev_previous = prev_to_last_op[len(prev_to_last_op) - 2] + + # Get the class of the states enums of the current operation mode that is running + current_sub_mode_enum_class = self._dg_op_mode_2_sub_mode[last_current] + + # Check if the operation modes of the two tuples match + # i.e. last = (timestamp, event type, prev, current) and one before = (timestamp, event type, prev, current) + # If the prev and current match respectively, it means the current operation mode has not changed so the + # operation mode states can be converted from the current sub mode enum class + if last_current == prev_current and last_previous == prev_previous: + + event_data_1 = current_sub_mode_enum_class(event_data_1).name + event_data_2 = current_sub_mode_enum_class(event_data_2).name + + else: + # If the previous and current of the last two tuples do not match, then an operation modes transition + # has occurred and and the previous state is converted from the previous class and the current op mode + # is converted from current operation states enum class. + # i.e last = (timestamp, event type, 3, 8) and one before = (timestamp, event type, 8, 3) + # previous and current do not match so in the last type (timestamp, event type, 8, 3) the prev state + # should be from op mode 8 and the current state should be from op mode 3 + previous_sub_mode_enum_class = self._dg_op_mode_2_sub_mode[last_previous] + event_data_1 = previous_sub_mode_enum_class(event_data_1).name + event_data_2 = current_sub_mode_enum_class(event_data_2).name + # Get the current timestamp and create a tuple of the current events event_tuple = (str(datetime.now()), event_state_name, event_data_1, event_data_2) # Update event dictionary - self._dg_event_dictionary[event_state_name].append(event_tuple) \ No newline at end of file + self._dg_event_dictionary[event_state_name].append(event_tuple) Index: dialin/dg/flush.py =================================================================== diff -u -r8474f8e345f165187d4dde17840575ee4e98a9b4 -rb85f0e224e74d44979c955528b0c81935710a189 --- dialin/dg/flush.py (.../flush.py) (revision 8474f8e345f165187d4dde17840575ee4e98a9b4) +++ dialin/dg/flush.py (.../flush.py) (revision b85f0e224e74d44979c955528b0c81935710a189) @@ -19,27 +19,10 @@ from ..common.msg_defs import MsgIds, MsgFieldPositions from ..protocols.CAN import DenaliChannels -from ..utils.base import AbstractSubSystem, publish, DialinEnum +from ..utils.base import AbstractSubSystem, publish +from ..common.dg_defs import DGFlushStates -@unique -class FlushStates(DialinEnum): - DG_FLUSH_STATE_START = 0 - DG_FLUSH_STATE_DRAIN_R1 = 1 - DG_FLUSH_STATE_DRAIN_R2 = 2 - DG_FLUSH_STATE_FLUSH_DRAIN = 3 - DG_FLUSH_STATE_FLUSH_DIALYSATE = 4 - DG_FLUSH_STATE_FLUSH_CONCENTRATE_STRAWS = 5 - DG_FLUSH_STATE_FLUSH_R1_TO_R2 = 6 - DG_FLUSH_STATE_FLUSH_R2_AND_DRAIN_R1 = 7 - DG_FLUSH_STATE_FLUSH_CIRCULATION_DRAIN_LINE = 8 - DG_FLUSH_STATE_FLUSH_CIRCULATION = 9 - DG_FLUSH_STATE_FLUSH_WITH_FRESH_WATER = 10 - DG_FLUSH_STATE_CANCEL_BASIC_PATH = 11 - DG_FLUSH_STATE_CANCEL_WATER_PATH = 12 - DG_FLUSH_STATE_COMPLETE = 13 - - class FlushMode(AbstractSubSystem): """ Flush Mode class with APIs to set the timing of each of the stages. @@ -78,7 +61,7 @@ drain_line_volume = struct.unpack('f', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_4:MsgFieldPositions.END_POS_FIELD_4]))[0] - self.flush_state = FlushStates(state).name + self.flush_state = DGFlushStates(state).name self.overall_elapsed_time = int(elapsed_time / 1000) self.state_elapsed_time = int(state_elapsed_time / 1000) self.flush_drain_line_volume_l = drain_line_volume Index: tests/dg_heat_and_chemical_disinfect_test.py =================================================================== diff -u -r1936d2c112d7629ddef976e2bd4cba60664c621f -rb85f0e224e74d44979c955528b0c81935710a189 --- tests/dg_heat_and_chemical_disinfect_test.py (.../dg_heat_and_chemical_disinfect_test.py) (revision 1936d2c112d7629ddef976e2bd4cba60664c621f) +++ tests/dg_heat_and_chemical_disinfect_test.py (.../dg_heat_and_chemical_disinfect_test.py) (revision b85f0e224e74d44979c955528b0c81935710a189) @@ -17,9 +17,9 @@ from dialin.dg.dialysate_generator import DG from dialin.hd.hemodialysis_device import HD -from dialin.common.dg_defs import HeatDisinfectStates, HeatDisinfectUIStates +from dialin.common.dg_defs import DGHeatDisinfectStates, DGHeatDisinfectUIStates from dialin.dg.heat_disinfect import HeatCancellationModes -from dialin.common.dg_defs import ChemicalDisinfectStates, ChemDisinfectUIStates +from dialin.common.dg_defs import DGChemicalDisinfectStates, DGChemDisinfectUIStates from dialin.dg.chemical_disinfect import ChemCancellationModes from dialin.dg.drain_pump import DrainPumpStates from dialin.dg.thermistors import ThermistorsNames @@ -38,13 +38,13 @@ info = ('State, {}, Overall_elapsed_time, {}, State_elapsed_time, {}, Disinfect_elapsed_time, {}, ' 'Cancellation_mode, {}, R1_level, {:5.3f}, R2_level, {:5.3f}, Current_rinse_count, {}, ' 'Total_rinse_count, {}, UI_state, {}, ' - .format(ChemicalDisinfectStates(dg.chemical_disinfect.chemical_disinfect_state).name, + .format(DGChemicalDisinfectStates(dg.chemical_disinfect.chemical_disinfect_state).name, dg.chemical_disinfect.overall_elapsed_time, dg.chemical_disinfect.state_elapsed_time, dg.chemical_disinfect.chemical_disinfect_elapsed_time, ChemCancellationModes(dg.chemical_disinfect.cancellation_mode).name, dg.chemical_disinfect.r1_level, dg.chemical_disinfect.r2_level, dg.chemical_disinfect.current_post_rinse_count, dg.chemical_disinfect.target_post_rinse_count, - ChemDisinfectUIStates(dg.chemical_disinfect.chemical_disinfect_ui_state).name)) + DGChemDisinfectUIStates(dg.chemical_disinfect.chemical_disinfect_ui_state).name)) return info @@ -62,11 +62,11 @@ info = ('State, {}, Overall_elapsed_time, {}, State_elapsed_time, {}, Disinfect_elapsed_time, {}, ' 'R1_level, {:5.3f}, R2_level, {:5.3f}, Top_alarm, {}, UI_state, {} ' - .format(HeatDisinfectStates(dg.heat_disinfect.heat_disinfect_state).name, + .format(DGHeatDisinfectStates(dg.heat_disinfect.heat_disinfect_state).name, dg.heat_disinfect.overall_elapsed_time, dg.heat_disinfect.state_elapsed_time, dg.heat_disinfect.heat_disinfect_count_down_time, dg.heat_disinfect.r1_level, dg.heat_disinfect.r2_level, hd.alarms.alarm_top, - HeatDisinfectUIStates(dg.chemical_disinfect.chemical_disinfect_ui_state).name)) + DGHeatDisinfectUIStates(dg.chemical_disinfect.chemical_disinfect_ui_state).name)) return info @@ -542,11 +542,11 @@ hd.cmd_log_in_to_hd() sleep(1) - #run_heat_disinfect() + run_heat_disinfect() #run_chemical_disinfect() - run_dg() + #run_dg() #run_ro_pump_duty_cycles()