Index: dialin/common/msg_ids.py =================================================================== diff -u -r4eebf06e7b22d8bed803d79925fb5e5b32b4cac4 -r171cfe518f3441e140b2995fbaa790d322697b38 --- dialin/common/msg_ids.py (.../msg_ids.py) (revision 4eebf06e7b22d8bed803d79925fb5e5b32b4cac4) +++ dialin/common/msg_ids.py (.../msg_ids.py) (revision 171cfe518f3441e140b2995fbaa790d322697b38) @@ -387,7 +387,7 @@ MSG_ID_DG_ACCEL_SEND_INTERVAL_OVERRIDE = 0xA019 MSG_ID_DG_MONITORED_VOLTAGES_SEND_INTERVAL_OVERRIDE = 0xA01A MSG_ID_DG_MONITORED_VOLTAGES_OVERRIDE = 0xA01B - MSG_ID_DRAIN_PUMP_TARGET_OUTLET_PRESSURE = 0xA01C + MSG_ID_DRAIN_PUMP_TARGET_OUTLET_FLOW = 0xA01C MSG_ID_DG_SWITCHES_STATUS_OVERRIDE = 0xA01D MSG_ID_DG_SWITCHES_PUBLISH_INTERVAL_OVERRIDE = 0xA01E MSG_ID_DG_OP_MODE_PUBLISH_INTERVAL_OVERRIDE = 0xA01F @@ -455,6 +455,7 @@ MSG_ID_DG_CONC_PUMP_PARK_STATUS_OVERRIDE = 0xA05E MSG_ID_DG_CONC_PUMP_PARK_FAULT_STATUS_OVERRIDE = 0xA05F MSG_ID_DG_CONC_PUMP_PARK_COMMAND = 0xA060 + MSG_ID_DG_HEATERS_DUTY_CYCLE_OVERRIDE = 0xA061 MSG_ID_HD_DEBUG_EVENT = 0xFFF1 MSG_ID_DG_DEBUG_EVENT = 0xFFF2 Index: dialin/dg/drain_pump.py =================================================================== diff -u -rf0cb1f298e3960769e0133172769deb9afe5a393 -r171cfe518f3441e140b2995fbaa790d322697b38 --- dialin/dg/drain_pump.py (.../drain_pump.py) (revision f0cb1f298e3960769e0133172769deb9afe5a393) +++ dialin/dg/drain_pump.py (.../drain_pump.py) (revision 171cfe518f3441e140b2995fbaa790d322697b38) @@ -118,32 +118,32 @@ self.drain_pump_direction = struct.unpack('i', bytearray( message['message'][MsgFieldPositions.START_POS_FIELD_7:MsgFieldPositions.END_POS_FIELD_7]))[0] - def cmd_drain_pump_set_outlet_target_pressure(self, pressure: float) -> int: + def cmd_drain_pump_set_outlet_target_flow_lpm(self, flow: float) -> int: """ - Constructs and sends the drain pump target outlet pressure command + Constructs and sends the drain pump target outlet flow in L/min Constraints: Must be logged into DG. - @param pressure: (float) target outlet pressure + @param flow: (float) target outlet flow in L/min @return: 1 if successful, zero otherwise """ - prssr = float_to_bytearray(pressure) - payload = prssr + flw = float_to_bytearray(flow) + payload = flw message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_dg_ch_id, - message_id=MsgIds.MSG_ID_DRAIN_PUMP_TARGET_OUTLET_PRESSURE.value, + message_id=MsgIds.MSG_ID_DRAIN_PUMP_TARGET_OUTLET_FLOW.value, payload=payload) - self.logger.debug("Setting drain pump target pressure") + self.logger.debug("Setting drain pump target flow") # Send message received_message = self.can_interface.send(message) # If there is no content... if received_message is not None: - self.logger.debug("Drain pump outlet pressure set to " + str(pressure) + " psi" + + self.logger.debug("Drain pump outlet flow set to " + str(flow) + " L/min" + str(received_message['message'][DenaliMessage.PAYLOAD_START_INDEX])) # response payload is OK or not OK return received_message['message'][DenaliMessage.PAYLOAD_START_INDEX] Index: dialin/dg/heaters.py =================================================================== diff -u -rf0cb1f298e3960769e0133172769deb9afe5a393 -r171cfe518f3441e140b2995fbaa790d322697b38 --- dialin/dg/heaters.py (.../heaters.py) (revision f0cb1f298e3960769e0133172769deb9afe5a393) +++ dialin/dg/heaters.py (.../heaters.py) (revision 171cfe518f3441e140b2995fbaa790d322697b38) @@ -34,12 +34,22 @@ @unique class HeatersState(DialinEnum): - HEATER_EXEC_STATE_OFF = 0 - HEATER_EXEC_STATE_RAMP_UP_TO_TARGET = 1 - HEATER_EXEC_STATE_CONTROL_TO_TARGET = 2 + HEATER_EXEC_STATE_PRIMARY_RAMP_TO_TARGET = 1 + HEATER_EXEC_STATE_PRIMARY_CONTROL_TO_TARGET = 2 + HEATER_EXEC_STATE_CONTROL_TO_DISINFECT_TARGE = 3 + HEATER_EXEC_STATE_TRIMMER_RAMP_TO_TARGET = 4 + HEATER_EXEC_STATE_TRIMMER_CONTROL_TO_TARGET = 5 + NUM_OF_HEATERS_STATE = 6 +@unique +class HeatersNames(DialinEnum): + DG_PRIMARY_HEATER = 0 + DG_TRIMMER_HEATER = 1 + NUM_OF_DG_HEATERS = 2 + + class Heaters(AbstractSubSystem): """ @@ -237,6 +247,37 @@ trimmer_target_temp)) self.can_interface.send(message, 0) + def cmd_heater_duty_cycle_override(self, heater: int, duty_cycle: float, reset: int = NO_RESET) -> int: + """ + Constructs and sends heater duty cycle override command + Must be logged into DG + There must be a minimum flow available for the heaters (FMP for primary and FMD for trimmer) + + @param heater the heater to override its value (primary, trimmer) + @param duty_cycle the duty cycle value to override + @param reset: (int) 1 to reset a previous override, 0 to override + @returns 1 if successful, zero otherwise + """ + reset_value = integer_to_bytearray(reset) + heater_name = integer_to_bytearray(heater) + duty = float_to_bytearray(duty_cycle) + payload = reset_value + heater_name + duty + message = DenaliMessage.build_message(channel_id=DenaliChannels.dialin_to_dg_ch_id, + message_id=MsgIds.MSG_ID_DG_HEATERS_DUTY_CYCLE_OVERRIDE.value, + payload=payload) + + self.logger.debug("Overriding {} heater's duty cycle to {:5.3f}".format(HeatersNames(heater).name, duty_cycle)) + # Send message + received_message = self.can_interface.send(message) + + # If there is content in message + if received_message is not None: + # Response payload is OK or not + return received_message['message'][DenaliMessage.PAYLOAD_START_INDEX] + else: + self.logger.debug("Timeout!!!!") + return False + def cmd_heaters_broadcast_interval_override(self, ms: int, reset: int = NO_RESET) -> int: """ Constructs and sends broadcast time interval. @@ -270,3 +311,5 @@ else: self.logger.debug("Timeout!!!!") return False + + Index: dialin/hd/blood_leak.py =================================================================== diff -u -rf0cb1f298e3960769e0133172769deb9afe5a393 -r171cfe518f3441e140b2995fbaa790d322697b38 --- dialin/hd/blood_leak.py (.../blood_leak.py) (revision f0cb1f298e3960769e0133172769deb9afe5a393) +++ dialin/hd/blood_leak.py (.../blood_leak.py) (revision 171cfe518f3441e140b2995fbaa790d322697b38) @@ -41,7 +41,16 @@ C = 10 -class BloodLeakObserver(AbstractObserver): +@unique +class BloodLeakStates(DialinEnum): + BLOOD_LEAK_WAIT_FOR_POST_STATE = 0 + BLOOD_LEAK_CHECK_SET_POINT_STATE = 1 + BLOOD_LEAK_INIT_STATE = 2 + BLOOD_LEAK_CHECK_ZERO_AND_SELF_TEST_STATE = 3 + BLOOD_LEAK_NORMAL_STATE = 4 + + +class BloodLeakObserver(AbstractObserver): # TODO remove """ Observation class @@ -73,12 +82,6 @@ BLOOD_LEAK_DETECTED = 0 # Blood detected NO_BLOOD_LEAK_DETECTED = 1 # No blood detected - # Blood leak detector state machine states - BLOOD_LEAK_INIT_STATE = 0 # Initial state - BLOOD_LEAK_ZERO_STATE = 1 # Zero state - BLOOD_LEAK_SELF_TEST_STATE = 2 # Self-test state - BLOOD_LEAK_NORMAL_STATE = 3 # Normal state - def __init__(self, can_interface, logger: Logger): """ @@ -100,13 +103,17 @@ self._handler_blood_leak_emb_mode_cmd_resp) self.blood_leak_status = self.NO_BLOOD_LEAK_DETECTED - self.blood_leak_state = self.BLOOD_LEAK_INIT_STATE + self.blood_leak_state = BloodLeakStates.BLOOD_LEAK_INIT_STATE.value self.blood_leak_detect_set_point = 0 self.blood_leak_detect_level = 0 self.blood_leak_led_intensity = 0 - self.blood_leak_emb_mode_cmd_response = '' - self._is_emb_mode_command_in_progress = False + self._is_emb_mode_command_in_progress = False # TODO remove + self.blood_leak_emb_mode_cmds = dict() + for cmd in EmbModeCommands.__members__: + # Initialize all the embedded mode commands + self.blood_leak_emb_mode_cmds[cmd] = '' + def get_blood_leak_status(self): """ Gets the current blood leak status @@ -147,12 +154,15 @@ """ return self.blood_leak_led_intensity - def get_blood_leak_emb_mode_command_response(self): + def get_blood_leak_emb_mode_command_response(self, emb_mod_cmd: int) -> str: """ Gets the embedded mode command response + @param emb_mod_cmd the command to get its response + @return: string - embedded mode command response """ + """ # Check if there has been a recent command sent to the firmware and then start an observer # If there is no command sent and therefore, there is no pending response, the observer will hang if self._is_emb_mode_command_in_progress is True: @@ -173,9 +183,9 @@ observer_timer_counter += 1 # Done with receiving the response from the firmware self._is_emb_mode_command_in_progress = False + """ + return self.blood_leak_emb_mode_cmds[ EmbModeCommands(emb_mod_cmd).name ] - return self.blood_leak_emb_mode_cmd_response - @publish(['blood_leak_status', 'blood_leak_state']) def _handler_blood_leak_sync(self, message): """ @@ -318,6 +328,7 @@ @return: non-zero integer if successful, False otherwise """ command_bytes = byte_to_bytearray(command) + self.blood_leak_emb_mode_cmds[EmbModeCommands(command).name] = '' data = 0 if msg_payload is not None: @@ -352,12 +363,15 @@ @return: None """ # Clear the variable for the next read - self.blood_leak_emb_mode_cmd_response = '' + blood_leak_emb_mode_cmd_response = '' payload = message['message'] index = MsgFieldPositions.START_POS_FIELD_1 + cmd, index = bytearray_to_integer(payload, index, False) length, index = bytearray_to_integer(payload, index, False) for i in range(0, length): # Loop through the length and get the char, char_index = bytearray_to_byte(payload, index + i, False) - self.blood_leak_emb_mode_cmd_response += chr(char) + blood_leak_emb_mode_cmd_response += chr(char) + + self.blood_leak_emb_mode_cmds[EmbModeCommands(cmd).name] = blood_leak_emb_mode_cmd_response Index: tests/dg_nvm_scripts.py =================================================================== diff -u -rf8e8a2028269c7d914f30d28b6be993e74388534 -r171cfe518f3441e140b2995fbaa790d322697b38 --- tests/dg_nvm_scripts.py (.../dg_nvm_scripts.py) (revision f8e8a2028269c7d914f30d28b6be993e74388534) +++ tests/dg_nvm_scripts.py (.../dg_nvm_scripts.py) (revision 171cfe518f3441e140b2995fbaa790d322697b38) @@ -27,12 +27,12 @@ # It creates a folder called DG_NV_Records in the destination that is called # If no address is provided, the default location is one folder above the dialin folder wherever it is installed # in your computer. - dg.sw_configs.cmd_get_dg_sw_config_record() + #dg.sw_configs.cmd_get_dg_sw_config_record() # Use cmd_set_dg_sw_config_record() set the changes back to firmware # This function requires an address for the excel report. Use the absolute address of your excel report like the # example below - #dg.sw_configs.cmd_update_dg_sw_config_record('/home/fw/projects/DG_NV_Records/2022-11-29-DG-SW-CONFIGS-Record.xlsx') + dg.sw_configs.cmd_update_dg_sw_config_record('/home/fw/projects/DG_NV_Records/2022-12-28-DG-SW-CONFIGS-Record.xlsx') # Use this function to reset the configuration records to all be 0 #dg.sw_configs.cmd_reset_dg_sw_config_record() @@ -112,13 +112,13 @@ if dg.cmd_log_in_to_dg(): - #run_sw_configs_commands() + run_sw_configs_commands() #run_calibration_commands() #run_system_commands() - run_usage_info_commands() + #run_usage_info_commands() #run_service_commands() Index: tests/dg_tests.py =================================================================== diff -u -rf8e8a2028269c7d914f30d28b6be993e74388534 -r171cfe518f3441e140b2995fbaa790d322697b38 --- tests/dg_tests.py (.../dg_tests.py) (revision f8e8a2028269c7d914f30d28b6be993e74388534) +++ tests/dg_tests.py (.../dg_tests.py) (revision 171cfe518f3441e140b2995fbaa790d322697b38) @@ -702,19 +702,19 @@ hd.cmd_log_in_to_hd() sleep(1) - #run_heat_disinfect() + run_heat_disinfect() #run_flush_mode() #run_chemical_disinfect() - run_chem_disinfect_flush_mode() + #run_chem_disinfect_flush_mode() #run_dg() # cmd_set_disinfect_ui_screen() - collect_treatment_data() + #collect_treatment_data() #collect_hd_treatment()