Index: dialin/dg/hd_proxy.py =================================================================== diff -u -rb62b040b80e3b42e9749ee8689f5d65c5dcc71e0 -ra08848ed6275cf2afa3bfb7f3c87709b69c224bc --- dialin/dg/hd_proxy.py (.../hd_proxy.py) (revision b62b040b80e3b42e9749ee8689f5d65c5dcc71e0) +++ dialin/dg/hd_proxy.py (.../hd_proxy.py) (revision a08848ed6275cf2afa3bfb7f3c87709b69c224bc) @@ -5,7 +5,7 @@ # 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 hd_proxy.py +# @file hd_simulator.py # # @date 14-Apr-2020 # @author S. Nash Index: dialin/hd/buttons.py =================================================================== diff -u -rb62b040b80e3b42e9749ee8689f5d65c5dcc71e0 -ra08848ed6275cf2afa3bfb7f3c87709b69c224bc --- dialin/hd/buttons.py (.../buttons.py) (revision b62b040b80e3b42e9749ee8689f5d65c5dcc71e0) +++ dialin/hd/buttons.py (.../buttons.py) (revision a08848ed6275cf2afa3bfb7f3c87709b69c224bc) @@ -14,6 +14,7 @@ # ############################################################################ from ..protocols.CAN import (DenaliMessage, + DenaliCanMessenger, DenaliChannels) from ..utils.conversions import integer_to_bytearray from .constants import RESET, NO_RESET @@ -30,7 +31,12 @@ MSG_ID_HD_OFF_BUTTON_OVERRIDE = 0x8002 MSG_ID_HD_STOP_BUTTON_OVERRIDE = 0x8003 - def __init__(self, can_interface, logger: Logger): + MSG_ID_HD_POWEROFF_TIMEOUT = 0x000E + + PRESSED = 1 + RELEASED = 0 + + def __init__(self, can_interface: DenaliCanMessenger, logger: Logger): """ HD_Buttons constructor @@ -40,7 +46,28 @@ super().__init__() self.can_interface = can_interface self.logger = logger + self.poweroff_timeout_expired = False + self.can_interface.register_receiving_publication_function(DenaliChannels.hd_to_ui_ch_id, + self.MSG_ID_HD_POWEROFF_TIMEOUT, + self._handler_poweroff_timeout_occurred) + + def get_power_timeout_expired(self): + """ + Gets the poweroff timeout expired status + + @return: True if expired, False otherwise + """ + + return self.poweroff_timeout_expired + + @_publish(["poweroff_timeout_expired"]) + def _handler_poweroff_timeout_occurred(self): + pass + + + + def cmd_off_button_override(self, state, reset=NO_RESET): """ Constructs and sends the Off button override command Index: dialin/hd/hemodialysis_device.py =================================================================== diff -u -radd8b1e7cce0187c9fb5b09a5881d0121f9a0ddb -ra08848ed6275cf2afa3bfb7f3c87709b69c224bc --- dialin/hd/hemodialysis_device.py (.../hemodialysis_device.py) (revision add8b1e7cce0187c9fb5b09a5881d0121f9a0ddb) +++ dialin/hd/hemodialysis_device.py (.../hemodialysis_device.py) (revision a08848ed6275cf2afa3bfb7f3c87709b69c224bc) @@ -41,6 +41,7 @@ MSG_ID_HD_OPERATION_MODE_BROADCAST = 0x0025 MSG_ID_LOGIN_TO_HD = 0x8000 MSG_ID_HD_SAFETY_SHUTDOWN_OVERRIDE = 0x8026 + MSG_ID_POWEROFF_NOTIFY = 0x0020 # broadcast message field positions START_POS_HD_OP_MODE = DenaliMessage.PAYLOAD_START_INDEX Index: dialin/hd/ui_proxy.py =================================================================== diff -u -rb62b040b80e3b42e9749ee8689f5d65c5dcc71e0 -ra08848ed6275cf2afa3bfb7f3c87709b69c224bc --- dialin/hd/ui_proxy.py (.../ui_proxy.py) (revision b62b040b80e3b42e9749ee8689f5d65c5dcc71e0) +++ dialin/hd/ui_proxy.py (.../ui_proxy.py) (revision a08848ed6275cf2afa3bfb7f3c87709b69c224bc) @@ -308,7 +308,7 @@ """ Gets the uf change succeeded status - @return: The uf change succeeded status + @return: True if succeeded, False otherwise """ return self.uf_change_succeeded Index: dialin/ui/__init__.py =================================================================== diff -u --- dialin/ui/__init__.py (revision 0) +++ dialin/ui/__init__.py (revision a08848ed6275cf2afa3bfb7f3c87709b69c224bc) @@ -0,0 +1 @@ \ No newline at end of file Index: dialin/ui/dg_simulator.py =================================================================== diff -u --- dialin/ui/dg_simulator.py (revision 0) +++ dialin/ui/dg_simulator.py (revision a08848ed6275cf2afa3bfb7f3c87709b69c224bc) @@ -0,0 +1 @@ \ No newline at end of file Index: dialin/ui/hd_simulator.py =================================================================== diff -u --- dialin/ui/hd_simulator.py (revision 0) +++ dialin/ui/hd_simulator.py (revision a08848ed6275cf2afa3bfb7f3c87709b69c224bc) @@ -0,0 +1,244 @@ +########################################################################### +# +# 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 hd_simulator.py +# +# @date 29-July-2020 +# @author P. Lucia +# +# @brief This class simulates the hd when interfacing with the UI +# +############################################################################ +from dialin.protocols.CAN import (DenaliMessage, + DenaliCanMessenger, + DenaliChannels) +from dialin.utils.base import _AbstractSubSystem, _publish, _LogManager +from dialin.utils.conversions import integer_to_bytearray +from dialin.hd.alarms import HDAlarms +import enum +from typing import List + +HIGH = 3 +MED = 2 +LOW = 1 +NONE = 0 + + +class Alarms: + + # ALARM_ID = (priority, alarmID, escalates in, silent_espires_in, flags) + ALARM_ID_NO_ALARM = (NONE, 0, 0, 0, 0) + ALARM_ID_SOFTWARE_FAULT = (HIGH, 1, 0, 0, 0) + ALARM_ID_STUCK_BUTTON_TEST_FAILED = (HIGH, 2, 0, 0, 0) + ALARM_ID_FPGA_POST_TEST_FAILED = (HIGH, 3, 0, 0, 0) + ALARM_ID_WATCHDOG_POST_TEST_FAILED = (HIGH, 4, 0, 0, 0) + ALARM_ID_UI_COMM_POST_FAILED = (HIGH, 5, 0, 0, 0) + ALARM_ID_BLOOD_PUMP_MC_CURRENT_CHECK = (MED, 6, 0, 0, 0) + ALARM_ID_BLOOD_PUMP_OFF_CHECK = (MED, 7, 0, 0, 0) + ALARM_ID_BLOOD_PUMP_MC_DIRECTION_CHECK = (MED, 8, 0, 0, 0) + ALARM_ID_BLOOD_PUMP_ROTOR_SPEED_CHECK = (HIGH, 9, 0, 0, 0) + ALARM_ID_DIAL_IN_PUMP_MC_CURRENT_CHECK = (MED, 10, 0, 0, 0) + ALARM_ID_DIAL_IN_PUMP_OFF_CHECK = (MED, 11, 0, 0, 0) + ALARM_ID_DIAL_IN_PUMP_MC_DIRECTION_CHECK = (MED, 12, 0, 0, 0) + ALARM_ID_DIAL_IN_PUMP_ROTOR_SPEED_CHECK = (HIGH, 13, 0, 0, 0) + ALARM_ID_DIAL_OUT_PUMP_MC_CURRENT_CHECK = (MED, 14, 0, 0, 0) + ALARM_ID_DIAL_OUT_PUMP_OFF_CHECK = (MED, 15, 0, 0, 0) + ALARM_ID_DIAL_OUT_PUMP_MC_DIRECTION_CHECK = (MED, 16, 0, 0, 0) + ALARM_ID_DIAL_OUT_PUMP_ROTOR_SPEED_CHECK = (HIGH, 17, 0, 0, 0) + ALARM_ID_WATCHDOG_EXPIRED = (HIGH, 18, 0, 0, 0) + ALARM_ID_RTC_COMM_ERROR = (HIGH, 19, 0, 0, 0) + ALARM_ID_RTC_CONFIG_ERROR = (HIGH, 20, 0, 0, 0) + ALARM_ID_DG_COMM_TIMEOUT = (HIGH, 21, 0, 0, 0) + ALARM_ID_UI_COMM_TIMEOUT = (HIGH, 22, 0, 0, 0) + ALARM_ID_COMM_TOO_MANY_BAD_CRCS = (HIGH, 23, 0, 0, 0) + ALARM_ID_TREATMENT_STOPPED_BY_USER = (LOW, 24, 0, 0, 0) + ALARM_ID_BLOOD_SITTING_WARNING = (MED, 25, 0, 0, 0) + ALARM_ID_BLOOD_SITTING_TOO_LONG_NO_RESUME = (MED, 26, 0, 0, 0) + ALARM_ID_BLOOD_SITTING_TOO_LONG_NO_RINSEBACK = (HIGH, 27, 0, 0, 0) + ALARM_ID_CAN_MESSAGE_NOT_ACKED = (HIGH, 28, 0, 0, 0) + ALARM_ID_OCCLUSION_BLOOD_PUMP = (HIGH, 29, 0, 0, 0) + ALARM_ID_OCCLUSION_DIAL_IN_PUMP = (HIGH, 30, 0, 0, 0) + ALARM_ID_OCCLUSION_DIAL_OUT_PUMP = (HIGH, 31, 0, 0, 0) + ALARM_ID_ARTERIAL_PRESSURE_LOW = (HIGH, 32, 0, 0, 0) + ALARM_ID_ARTERIAL_PRESSURE_HIGH = (HIGH, 33, 0, 0, 0) + ALARM_ID_VENOUS_PRESSURE_LOW = (HIGH, 34, 0, 0, 0) + ALARM_ID_VENOUS_PRESSURE_HIGH = (HIGH, 35, 0, 0, 0) + ALARM_ID_UF_RATE_TOO_HIGH_ERROR = (HIGH, 36, 0, 0, 0) + ALARM_ID_UF_VOLUME_ACCURACY_ERROR = (HIGH, 37, 0, 0, 0) + ALARM_ID_RTC_BATTERY_LOW = (HIGH, 38, 0, 0, 0) + ALARM_ID_RTC_OR_TIMER_ACCURACY_FAILURE = (HIGH, 39, 0, 0, 0) + ALARM_ID_RTC_RAM_OPS_ERROR = (HIGH, 40, 0, 0, 0) + ALARM_ID_NVDATA_EEPROM_OPS_FAILURE = (HIGH, 41, 0, 0, 0) + ALARM_ID_NVDATA_MFG_RECORD_CRC_ERROR = (HIGH, 42, 0, 0, 0) + ALARM_ID_NVDATA_SRVC_RECORD_CRC_ERROR = (HIGH, 43, 0, 0, 0) + ALARM_ID_NVDATA_CAL_RECORD_CRC_ERROR = (HIGH, 44, 0, 0, 0) + ALARM_ID_NVDATA_HW_USAGE_DATA_CRC_ERROR = (HIGH, 45, 0, 0, 0) + ALARM_ID_NVDATA_DISINFECTION_DATE_CRC_ERROR = (HIGH, 46, 0, 0, 0) + ALARM_ID_RO_PUMP_OUT_PRESSURE_OUT_OF_RANGE = (HIGH, 47, 0, 0, 0) + ALARM_ID_TEMPERATURE_SENSORS_OUT_OF_RANGE = (HIGH, 48, 0, 0, 0) + ALARM_ID_TEMPERATURE_SENSORS_INCONSISTENT = (HIGH, 49, 0, 0, 0) + ALARM_ID_HD_COMM_TIMEOUT = (HIGH, 50, 0, 0, 0) + ALARM_ID_VALVE_CONTROL_FAILURE = (HIGH, 51, 0, 0, 0) + ALARM_ID_BLOOD_PUMP_FLOW_VS_MOTOR_SPEED_CHECK = (HIGH, 52, 0, 0, 0) + ALARM_ID_DIAL_IN_PUMP_FLOW_VS_MOTOR_SPEED_CHECK = (HIGH, 53, 0, 0, 0) + ALARM_ID_DIAL_OUT_PUMP_FLOW_VS_MOTOR_SPEED_CHECK = (HIGH, 54, 0, 0, 0) + ALARM_ID_BLOOD_PUMP_MOTOR_SPEED_CHECK = (HIGH, 55, 0, 0, 0) + ALARM_ID_DIAL_IN_PUMP_MOTOR_SPEED_CHECK = (HIGH, 56, 0, 0, 0) + ALARM_ID_DIAL_OUT_PUMP_MOTOR_SPEED_CHECK = (HIGH, 57, 0, 0, 0) + ALARM_ID_BLOOD_PUMP_ROTOR_SPEED_TOO_HIGH = (HIGH, 58, 0, 0, 0) + ALARM_ID_INLET_WATER_TEMPERATURE_OUT_OF_RANGE = (HIGH, 59, 0, 0, 0) + ALARM_ID_DOES_NOT_EXIST = (HIGH, 99, 0, 0, 0) + + + +class MsgDefs(enum.Enum): + + REQUEST_REJECT_REASON_NONE = 0 + REQUEST_REJECT_REASON_NOT_ALLOWED_IN_CURRENT_MODE = 1 + REQUEST_REJECT_REASON_TIMEOUT_WAITING_FOR_USER_CONFIRM = 2 + REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE = 3 + REQUEST_REJECT_REASON_INVALID_TREATMENT_STATE = 4 + REQUEST_REJECT_REASON_TREATMENT_TOO_CLOSE_TO_FINISHED = 5 + REQUEST_REJECT_REASON_TREATMENT_TIME_OUT_OF_RANGE = 6 + REQUEST_REJECT_REASON_TREATMENT_TIME_LESS_THAN_CURRENT = 7 + REQUEST_REJECT_REASON_BLOOD_FLOW_OUT_OF_RANGE = 8 + REQUEST_REJECT_REASON_DIAL_FLOW_OUT_OF_RANGE = 9 + REQUEST_REJECT_REASON_DIAL_VOLUME_OUT_OF_RANGE = 10 + REQUEST_REJECT_REASON_UF_VOLUME_OUT_OF_RANGE = 11 + REQUEST_REJECT_REASON_UF_RATE_OUT_OF_RANGE = 12 + REQUEST_REJECT_REASON_TREATMENT_TIME_LESS_THAN_MINIMUM = 13 + REQUEST_REJECT_REASON_UF_NOT_IN_PROGESS = 14 + REQUEST_REJECT_REASON_UF_NOT_PAUSED = 15 + REQUEST_REJECT_REASON_SALINE_BOLUS_IN_PROGRESS = 16 + + +class HDSimulator(_AbstractSubSystem): + + MSG_ID_HD_CREATE_TREATMENT_RESPONSE = 0x0036 + + MSG_ID_HD_POWEROFF = 0x01 + MSG_ID_HD_POWEROFF_BROADCAST = 0x000E + MSG_ID_CLEAR_ALARMS = 0x04 + + NUM_TREATMENT_PARAMETERS = 18 + + def __init__(self, can_interface="can0", log_level=None): + + super().__init__() + + self._log_manager = _LogManager(log_level=log_level, log_filepath=self.__class__.__name__+".log") + self.logger = self._log_manager.logger + self.can_interface = DenaliCanMessenger(can_interface=can_interface, + logger=self.logger, + log_can=self._log_manager.log_level == "CAN_ONLY") + + def cmd_send_treatment_parameter_validation_response(self, rejections: List[MsgDefs]): + """ + Sends a treatment parameter validation response + + @param rejections: A list of rejection code enums + @return: True if successful, False otherwise + """ + if len(rejections) != self.NUM_TREATMENT_PARAMETERS: + self.logger.error("Invalid number of treatment parameter enums provided.") + return False + + if not all([isinstance(each, enum.Enum) for each in rejections]): + self.logger.error("Not all rejections are enums.") + return False + + payload = bytearray() + + for rejection in rejections: + payload += integer_to_bytearray(rejection.value) + + message = DenaliMessage.build_message(channel_id=DenaliChannels.hd_to_ui_ch_id, + message_id=self.MSG_ID_HD_CREATE_TREATMENT_RESPONSE, + payload=payload) + + # Send message + self.can_interface.send(message, 0) + + return True + + def cmd_send_poweroff_button_pressed(self): + """ + Broadcast that the poweroff button was pressed + + @return: None + """ + + payload = bytearray(0x01) + + message = DenaliMessage.build_message(channel_id=DenaliChannels.hd_to_ui_ch_id, + message_id=self.MSG_ID_HD_POWEROFF, + payload=payload) + + self.can_interface.send(message, 0) + + def cmd_send_broadcast_poweroff(self): + """ + Broadcast a power-off message event + + @return: None + """ + + payload = integer_to_bytearray(1) + + message = DenaliMessage.build_message(channel_id=DenaliChannels.hd_sync_broadcast_ch_id, + message_id=self.MSG_ID_HD_POWEROFF_BROADCAST, + payload=payload) + + self.can_interface.send(message, 0) + + def cmd_activate_alarm(self, alarm: Alarms): + """ + Send alarm + + @return: None + """ + + state = integer_to_bytearray(alarm[0]) + top = integer_to_bytearray(alarm[1]) + escalates_in = integer_to_bytearray(alarm[2]) + silence_expires = integer_to_bytearray(alarm[3]) + flags = integer_to_bytearray(alarm[4]) + + payload = state + top + escalates_in + silence_expires + flags + + message = DenaliMessage.build_message(channel_id=DenaliChannels.hd_alarm_broadcast_ch_id, + message_id=HDAlarms.MSG_ID_HD_ALARMS_PUBLISHED_STATUS, + payload=payload) + + self.can_interface.send(message, 0) + + def cmd_send_clear_alarms(self): + """ + Broadcasts a clear alarms message + + @return: None + """ + + state = integer_to_bytearray(0) + top = integer_to_bytearray(0) + escalates_in = integer_to_bytearray(0) + silence_expires = integer_to_bytearray(0) + flags = integer_to_bytearray(0) + + payload = state + top + escalates_in + silence_expires + flags + + # payload = bytearray([0,0,0,0,0]) + + message = DenaliMessage.build_message(channel_id=DenaliChannels.hd_alarm_broadcast_ch_id, + message_id=HDAlarms.MSG_ID_HD_ALARMS_PUBLISHED_STATUS, + payload=payload) + + self.can_interface.send(message, 0) + + + + Index: docs/source/dialin.ui.rst =================================================================== diff -u --- docs/source/dialin.ui.rst (revision 0) +++ docs/source/dialin.ui.rst (revision a08848ed6275cf2afa3bfb7f3c87709b69c224bc) @@ -0,0 +1,22 @@ +dialin\.ui package +================== + +Submodules +---------- + +dialin\.ui\.hd\_simulator module +-------------------------------- + +.. automodule:: dialin.ui.hd_simulator + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: dialin.ui + :members: + :undoc-members: + :show-inheritance: Index: tests/test_buttons.py =================================================================== diff -u --- tests/test_buttons.py (revision 0) +++ tests/test_buttons.py (revision a08848ed6275cf2afa3bfb7f3c87709b69c224bc) @@ -0,0 +1,32 @@ +########################################################################### +# +# Copyright (c) 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 test_buttons.py +# +# @date 06-Aug-2020 +# @author P. Lucia +# +# @brief +# +# +############################################################################ +import sys +sys.path.append("..") + +from dialin.hd.hemodialysis_device import HD +from dialin.hd.constants import RESET, NO_RESET + +def test_buttons(): + hd = HD(log_level="DEBUG") + hd.buttons.PRESSED + hd.buttons.cmd_stop_button_override(hd.buttons.PRESSED, RESET) + hd.buttons.cmd_stop_button_override(hd.buttons.PRESSED, NO_RESET) + + +if __name__ == '__main__': + test_buttons() + Index: tests/test_gen_requirements.py =================================================================== diff -u -r878d608b5b6e1974f14e3da2956ac8063e30bf14 -ra08848ed6275cf2afa3bfb7f3c87709b69c224bc --- tests/test_gen_requirements.py (.../test_gen_requirements.py) (revision 878d608b5b6e1974f14e3da2956ac8063e30bf14) +++ tests/test_gen_requirements.py (.../test_gen_requirements.py) (revision a08848ed6275cf2afa3bfb7f3c87709b69c224bc) @@ -83,13 +83,12 @@ return result +def generate_requirements(): + """ + Generates requires for both HD and DG -def gen_dg_requirements(): - pass - - - -if __name__ == '__main__': + @return: None + """ hd = HD() result = {} @@ -128,3 +127,7 @@ gen_publish_requirements(modules) gen_cmd_requirements(modules) + + +if __name__ == '__main__': + generate_requirements() Index: tests/test_hd_simulator.py =================================================================== diff -u --- tests/test_hd_simulator.py (revision 0) +++ tests/test_hd_simulator.py (revision a08848ed6275cf2afa3bfb7f3c87709b69c224bc) @@ -0,0 +1,69 @@ +########################################################################### +# +# Copyright (c) 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 test_hd_simulator.py +# +# @date 06-Aug-2020 +# @author P. Lucia +# +# @brief +# +# +############################################################################ +import sys +sys.path.append("..") + +from dialin.ui.hd_simulator import HDSimulator, MsgDefs, Alarms +from time import sleep + + +def test_invalid_parameters(): + hd_simulator = HDSimulator(log_level="DEBUG") + + rejections = [ + MsgDefs.REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE, # overall response + MsgDefs.REQUEST_REJECT_REASON_BLOOD_FLOW_OUT_OF_RANGE, # blood flow + MsgDefs.REQUEST_REJECT_REASON_DIAL_FLOW_OUT_OF_RANGE, # dialysate flow + MsgDefs.REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE, # duration + MsgDefs.REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE, # heparin dispensing rate + MsgDefs.REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE, # heparin bolus volume + MsgDefs.REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE, # heparin stop time + MsgDefs.REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE, # saline bolus + MsgDefs.REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE, # acid concentrate + MsgDefs.REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE, # bicarbonate concentrate + MsgDefs.REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE, # dialyzer type + MsgDefs.REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE, # dialysate temperature + MsgDefs.REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE, # arterial pressure limit low + MsgDefs.REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE, # arterial pressure limit high + MsgDefs.REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE, # venous pressure limit low + MsgDefs.REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE, # venous pressure limit high + MsgDefs.REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE, # blood pressure measurement interval + MsgDefs.REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE # rinseback flow rate + ] + hd_simulator.cmd_send_treatment_parameter_validation_response(rejections) + + +def test_poweroff(): + hd_simulator = HDSimulator(log_level="DEBUG") + hd_simulator.cmd_send_poweroff_button_pressed() + hd_simulator.cmd_send_broadcast_poweroff() + + +def test_clear_alarms(): + hd_simulator = HDSimulator() + + hd_simulator.cmd_activate_alarm(Alarms.ALARM_ID_ARTERIAL_PRESSURE_HIGH) + sleep(1) + hd_simulator.cmd_send_clear_alarms() + + +if __name__ == '__main__': + # test_invalid_parameters() + test_clear_alarms() + + + Index: tools/document.sh =================================================================== diff -u -rc6596d42d995bed3789849bd85c83da5a3837fac -ra08848ed6275cf2afa3bfb7f3c87709b69c224bc --- tools/document.sh (.../document.sh) (revision c6596d42d995bed3789849bd85c83da5a3837fac) +++ tools/document.sh (.../document.sh) (revision a08848ed6275cf2afa3bfb7f3c87709b69c224bc) @@ -14,11 +14,16 @@ # @brief Generates doxygen documentation # ############################################################################ -# Assumes you have already run the following setup: + CURR_DIR=$(pwd) if [[ "$@" == "*--setup*" ]]; then - sudo apt-get install python3-sphinx + if [[ $(dpkg-query -W -f='${Status}' python3-sphinx | grep -c "ok installed") -eq 0 ]]; then + echo "Please run the following required packages: " + echo "sudo apt-get install python3-sphinx" + echo "Exiting..." + exit 1 + fi mkdir -p ../docs/ cd ../docs/