Index: dialin/ui/dd_selection_handler.py =================================================================== diff -u --- dialin/ui/dd_selection_handler.py (revision 0) +++ dialin/ui/dd_selection_handler.py (revision 1e9de03223eeeec426716c6157ce88ddd60e4d5a) @@ -0,0 +1,598 @@ +########################################################################### +# +# Copyright (c) 2020-2023 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 dd_selection_handler.py +# @author (last) Mohammad Suleiman +# @date (original) 11--2023 +# +############################################################################ + +from ..common import * +from ..protocols.CAN import DenaliMessage, DenaliChannels +from ..utils import * +from time import time +from random import random + + +def reset(parent): + rsp_id = MsgIds.MSG_ID_HD_OP_MODE_DATA + rsp_payload = integer_to_bytearray(HDOpModes.MODE_INIT.value) + rsp_payload += integer_to_bytearray(HDInitStates.POST_STATE_START.value) + parent.demoSelection = 2 # setup event to change state on demoTimer + parent.demoCount = 3 + parent.demoGroupCount = None + return rsp_id, rsp_payload + + +def auto_transit_to_standby(parent): + rsp_id = MsgIds.MSG_ID_HD_OP_MODE_DATA + rsp_payload = integer_to_bytearray(HDOpModes.MODE_STAN.value) + rsp_payload += integer_to_bytearray(HDStandbyStates.STANDBY_START_STATE.value) + parent.demoSelection = 0 # wait for user + return rsp_id, rsp_payload + + +def filter_flush(parent): + rsp_id = MsgIds.MSG_ID_HD_OP_MODE_DATA + rsp_payload = integer_to_bytearray(HDOpModes.MODE_PRET.value) + rsp_payload += integer_to_bytearray(PreTreatmentSubModes.HD_PRE_TREATMENT_WATER_SAMPLE_STATE.value) + parent.demoSelection = 5 # = PreTreatmentDrySelfTestsStates.NUM_OF_DRY_SELF_TESTS_STATES.value - 1: + parent.demoTimedIncValue = PreTreatmentPrimeStates.HD_PRIME_WAIT_FOR_USER_START_STATE.value - 1 # 1st pass is v+1 + parent.demoSelection = 10 # TBD! setup event to change to ... Wait for User + parent.demoCount = 0 # TBD! don't advance until user 'Start Prime' + else: + parent.demoCountdownId = MsgIds.MSG_ID_HD_DRY_SELF_TEST_PROGRESS_DATA + # TBD setup above: parent.demoGroupCount = 14 * 4 # aggregate counter + + return rsp_id, rsp_payload + + +def prime_circuits_with_dialysate(parent): + rsp_id = MsgIds.MSG_ID_PRE_TREATMENT_STATE_DATA + rsp_payload = struct.pack( + "<" + str(PreTreatmentSubModes.NUM_OF_HD_PRE_TREATMENT_STATES.value + 1) + "i", + PreTreatmentSubModes.HD_PRE_TREATMENT_PRIME_STATE.value, + 0, # 2 No cartridge self-tests state + 0, # 3 Consumable and cartridge installation state + 0, # 0 Water sample state + 0, # 1 Consumable self-tests state + 0, # 4 Self-tests when the cartridge is dry state + parent.demoTimedIncValue, # 5 Prime blood and dialysate circuits and run wet self-tests state + 0, # 6 Re-circulate blood and dialysate circuits state + 0, # 7 Patient connection state + 0, + 0 + ) + parent.demoCountdownId = MsgIds.MSG_ID_HD_PRIMING_STATUS_DATA + parent.demoGroupCount = PreTreatmentPrimeStates.NUM_OF_HD_PRIME_STATES.value * 5 # aggregate count up to TBD! cleanup numbers + if parent.demoTimedIncValue == PreTreatmentPrimeStates.HD_PRIME_WAIT_FOR_USER_START_STATE.value: + parent.demoSelection = 0 # Wait for User + # parent.demoGroupCounter = 0 # aggregate counter + # TBD! could skip HD_PRIME_PAUSE? + elif parent.demoTimedIncValue >= PreTreatmentPrimeStates.NUM_OF_HD_PRIME_STATES.value - 1: + parent.demoTimedIncValue = None ## TBD!! + parent.demoSelection = 11 # on next countdown transition + parent.demoCount = 0 # immediate timeout # TBD!! Hack to make counter neat + parent.demoGroupCounter = parent.demoGroupCount # aggregate counter + # TBD else: + # TBD parent.demoCountdownId = MsgIds.MSG_ID_HD_PRIMING_STATUS_DATA # TBD! need an aggregate time/timer + return rsp_id, rsp_payload + + +def recirculate_primed_circuits_1(parent): + rsp_id = MsgIds.MSG_ID_PRE_TREATMENT_STATE_DATA + rsp_payload = struct.pack( + "<" + str(PreTreatmentSubModes.NUM_OF_HD_PRE_TREATMENT_STATES.value + 1) + "i", + PreTreatmentSubModes.HD_PRE_TREATMENT_RECIRCULATE_STATE.value, + 0, # 0 Water sample state + 0, # 1 Consumable self-tests state + 0, # 2 No cartridge self-tests state + 0, # 3 Consumable and cartridge installation state + 0, # 4 Self-tests when the cartridge is dry state + 0, # 5 Prime blood and dialysate circuits and run wet self-tests state + PreTreatmentRecircStates.PRE_TREATMENT_RECIRC_STATE.value, + # 6 Re-circulate blood and dialysate circuits state + 0, # 7 Patient connection state + 0, + 0 + ) + parent.demoSelection = 0 # Then wait for User + parent.demoGroupCount = None # clear aggregate count + return rsp_id, rsp_payload + + +def recirculate_primed_circuits_2(parent): + rsp_id = MsgIds.MSG_ID_PRE_TREATMENT_STATE_DATA + rsp_payload = struct.pack( + "<" + str(PreTreatmentSubModes.NUM_OF_HD_PRE_TREATMENT_STATES.value + 1) + "i", + PreTreatmentSubModes.HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE.value, + 0, # 0 Water sample state + 0, # 1 Consumable self-tests state + 0, # 2 No cartridge self-tests state + 0, # 3 Consumable and cartridge installation state + 0, # 4 Self-tests when the cartridge is dry state + 0, # 5 Prime blood and dialysate circuits and run wet self-tests state + 0, # 6 Re-circulate blood and dialysate circuits state + PreTreatmentPatientConnectionStates.PRE_TREATMENT_PAT_CONN_WAIT_FOR_UF_VOL_STATE.value, + # 7 Patient connection state + 0, + 0 + ) + parent.demoSelection = 0 # Then wait for User + parent.demoGroupCount = None # clear aggregate count + return rsp_id, rsp_payload + + +def start_treatment(parent): + rsp_id = MsgIds.MSG_ID_HD_OP_MODE_DATA + rsp_payload = integer_to_bytearray(HDOpModes.MODE_TREA.value) + rsp_payload += integer_to_bytearray(0) + parent.demoCountdownId = MsgIds.MSG_ID_HD_BLOOD_PRIME_PROGRESS_DATA + parent.demoCount = 0 + parent.demoCounter = 1 + # parent.demoGroupCount = int(120 / 8) # TBD! fix const numbers + # parent.demoGroupCount = -1 + parent.demoSelection = 21 # Initiate Blood Prime + parent.blood_prime_set_point_blood_flow = 20 + return rsp_id, rsp_payload + + +def blood_prime(parent): + rsp_id = MsgIds.MSG_ID_TREATMENT_STATE_DATA + rsp_payload = struct.pack("<10i", + TreatmentStates.TREATMENT_BLOOD_PRIME_STATE.value, # 0 Treatment Submode + 0, # 1 UF state + 0, # 2 Saline bolus state + 0, # 3 Hep state + 0, # 4 Rinseback state + 0, # 5 Recirc state + 0, # 6 Blood Prime state + 0, # 7 End state + 0, # 8 Stop state + 0, # 9 Dialysis state + ) + parent.demoSelection = 22 # Complete Blood Prime -> Dialysis + parent.demoCountdownId = MsgIds.MSG_ID_HD_BLOOD_PRIME_PROGRESS_DATA + parent.demoCount = int(120 / 8) # TBD! fix const numbers + parent.demoCounter = -1 # give slight delay + return rsp_id, rsp_payload + + +def start_dialysis(parent): + rsp_id = None + rsp_payload = None + # preset timing info + parent.treatment_start_time_s = time() + parent.cmd_set_treatment_time(sec_total=parent.treatment_time_sec, sec_elapsed=0, + sec_remain=parent.treatment_time_sec) + parent.heparin_out_ml = parent.heparin_bolus_ml + if parent.heparin_bolus_ml > 0: + parent.heparin_state = HeparinStates.HEPARIN_STATE_INITIAL_BOLUS # Initial heparin bolus delivery in progress + else: + parent.heparin_state = HeparinStates.HEPARIN_STATE_STOPPED # Heparin delivery stopped by alarm or not yet started + parent.uf_state = TreatmentDialysisStates.DIALYSIS_START_STATE # 0 Treatment Submode + + parent.demoCount = parent.demoSpeed - 1 + parent.demoGroupCount = parent.treatment_time_sec # TBD!! replace with user setting + parent.demoGroupCounter = 0 + parent.demoSelection = 29 # start dialysis + return rsp_id, rsp_payload + + +def enter_normal_uf(parent): + rsp_id = MsgIds.MSG_ID_TREATMENT_STATE_DATA + parent.uf_state = TreatmentDialysisStates.DIALYSIS_UF_STATE # 1 UF state + parent.saline_state = SalineBolusStates.SALINE_BOLUS_STATE_IDLE # 2 Saline bolus state + rsp_payload = struct.pack("<10i", + TreatmentStates.TREATMENT_DIALYSIS_STATE.value, # 0 Treatment Submode + parent.uf_state.value, # 1 UF state + parent.saline_state.value, # 2 Saline bolus state + parent.heparin_state.value, # 3 Hep state + 0, # 4 Rinseback state + 0, # 5 Recirc state + 0, # 6 Blood Prime state + 0, # 7 End state + 0, # 8 Stop state + 0, # 9 Dialysis state + ) + parent.demoSelection = 30 # ongoing data update + return rsp_id, rsp_payload + + +def dialysis_data_update(parent): + rsp_id = None + rsp_payload = None + parent.blood_stop_time_s = time() # reset timer + parent.treatment_stop_time_s = parent.blood_stop_time_s + prev_heparin_state = parent.heparin_state + prev_saline_state = parent.saline_state + + # MSG_ID_BLOOD_FLOW_DATA + parent.blood_flow_measured_ml_per_min += (random() - 0.5) * 10 # TBD! replace magic numbers + if parent.blood_flow_measured_ml_per_min > (parent.blood_flow_set_point_ml_per_min + 30): + parent.blood_flow_measured_ml_per_min -= 5 + parent.cmd_set_treatment_blood_flow_rate(flow_set_pt=parent.blood_flow_set_point_ml_per_min, + measured_flow=parent.blood_flow_measured_ml_per_min, + rot_speed=0, mot_speed=0, mc_speed=0, + mc_current=0, pwm=0, rotor_count=0, + pres_flow=parent.blood_flow_set_point_ml_per_min, rotor_hall=0) + + # MSG_ID_DIALYSATE_FLOW_DATA + parent.dialysate_flow_measured_ml_per_min += (random() - 0.5) * 5 # TBD! replace magic numbers + if parent.dialysate_flow_measured_ml_per_min > (parent.dialysate_flow_set_point_ml_per_min + 30): + parent.dialysate_flow_measured_ml_per_min -= 5 + parent.cmd_set_treatment_dialysate_flow_rate(flow_set_pt=parent.dialysate_flow_set_point_ml_per_min, + measured_flow=parent.dialysate_flow_measured_ml_per_min, + rot_speed=0.0, + mot_speed=0.0, + mc_speed=0.0, + mc_current=0.0, + pwm=0.0, + rotor_count=0, + presFlow=parent.dialysate_flow_set_point_ml_per_min, + rotorHall=0) + + # MSG_ID_PRESSURE_OCCLUSION_DATA + + arterial_min_limit = int(parent.arterial_pressure_mid_mmHg - (parent.demo_treatment_params.data_int[ + TreatmentParameters.TREATMENT_PARAM_ART_PRES_LIMIT_WINDOW.value] / 2)) + + arterial_max_limit = int(parent.arterial_pressure_mid_mmHg + (parent.demo_treatment_params.data_int[ + TreatmentParameters.TREATMENT_PARAM_ART_PRES_LIMIT_WINDOW.value] / 2)) + + venous_min_limit = int(parent.venous_pressure_mid_mmHg - (parent.demo_treatment_params.data_int[ + TreatmentParameters.TREATMENT_PARAM_VEN_PRES_LIMIT_WINDOW.value] / 2)) + + venous_max_limit = int(parent.venous_pressure_mid_mmHg + (parent.demo_treatment_params.data_int[ + TreatmentParameters.TREATMENT_PARAM_VEN_PRES_LIMIT_WINDOW.value] / 2)) + + parent.arterial_pressure_mmHg += (random() - 0.5) * 10 # TBD! replace magic wander numbers + + if parent.arterial_pressure_mmHg > (parent.arterial_pressure_mid_mmHg + 30): + parent.arterial_pressure_mmHg -= 5 + # Stay within limits + if int(parent.arterial_pressure_mmHg) < arterial_min_limit: + parent.arterial_pressure_mmHg = arterial_min_limit + elif int(parent.arterial_pressure_mmHg) > arterial_max_limit: + parent.arterial_pressure_mmHg = arterial_max_limit + + parent.venous_pressure_mmHg += (random() - 0.5) * 10 + if parent.venous_pressure_mmHg > (parent.venous_pressure_mid_mmHg + 30): + parent.venous_pressure_mmHg -= 5 + # Stay within limits + if int(parent.venous_pressure_mmHg) < venous_min_limit: + parent.venous_pressure_mmHg = venous_min_limit + elif int(parent.venous_pressure_mmHg) > venous_max_limit: + parent.venous_pressure_mmHg = venous_max_limit + parent.cmd_set_pressure_occlusion_data(arterial_prs=parent.arterial_pressure_mmHg, + venous_prs=parent.venous_pressure_mmHg, + blood_pump_occlusion=0, + pressure_limit_state=0, + arterial_min_limt=arterial_min_limit, + arterial_max_limt=arterial_max_limit, + venous_min_limit=venous_min_limit, + venous_max_limit=venous_max_limit, + arterial_long_filtered_pressure=parent.arterial_pressure_mmHg, + venous_long_filtered_pressure=parent.venous_pressure_mmHg) + # MSG_ID_RTC_EPOCH + # tbd! + + # MSG_ID_DIALYSATE_OUT_FLOW_DATA + # TBD!! parameters seem swapped and off by 1000x ?? + # parent.cmd_set_treatment_ultrafiltration_outlet_flow_data(ref_uf_vol=parent.uf_volume_set_l, + # measured_uf_vol=parent.uf_volume_out_l, + # rot_speed=0.0, mot_speed=0.0, mc_speed=0.0, + # mc_current=0.0, pwm=0.0) + parent.uf_volume_out_l = min(parent.uf_volume_out_l + parent.uf_rate_l_per_sec, parent.uf_volume_set_l) + parent.cmd_set_treatment_ultrafiltration_outlet_flow_data(ref_uf_vol=parent.uf_volume_out_l * 1000.0, + measured_uf_vol=parent.uf_volume_set_l * 1000.0, + rot_speed=0.0, mot_speed=0.0, mc_speed=0.0, + mc_current=0.0, pwm=0.0, corr_offset=0.0, + pump_calculated_rate=0.0, uf_calculated_rate=0.0, + rotor_hall=0, current_uf_rate=(parent.uf_rate_l_per_sec * 60)) + + # MSG_ID_LOAD_CELL_READINGS + + # MSG_ID_TREATMENT_TIME + if parent.treatment_time_sec != parent.demoGroupCount: # handle user change in treatment time + parent.demoGroupCount = max(parent.treatment_time_sec, parent.demoGroupCounter) + + ctr_elapsed_sec = min(parent.demoGroupCounter, parent.demoGroupCount) + ctr_remain_sec = parent.demoGroupCount - parent.demoGroupCounter + + parent.cmd_set_treatment_time(sec_total=parent.demoGroupCount, sec_elapsed=ctr_elapsed_sec, + sec_remain=ctr_remain_sec) + + parent.demoGroupCounter -= 1 # TBD! effectively freeze countdown MAYBE? + + # MSG_ID_HD_HEPARIN_DATA_BROADCAST + if ctr_remain_sec < (parent.heparin_stop_min * 60.0): + parent.heparin_state = HeparinStates.HEPARIN_STATE_COMPLETED + else: + if parent.heparin_pause == False: + parent.heparin_out_ml += parent.heparin_rate_ml_per_s * parent.demoSpeed + parent.heparin_state = HeparinStates.HEPARIN_STATE_DISPENSING + else: + parent.heparin_state = HeparinStates.HEPARIN_STATE_PAUSED + + parent.heparin_expected_ml = (ctr_remain_sec - ( + parent.heparin_stop_min * 60.0)) * parent.heparin_rate_ml_per_s + parent.heparin_out_ml + parent.cmd_set_treatment_heparin_data(cumulative=parent.heparin_out_ml, required=parent.heparin_expected_ml) + + # sub selections within Dialysis Data Update + if parent.demoSelection == 30: # Standard UF Dialysis . . . . . . . . . . + parent.demoGroupCounter += 1 # TBD! effectively unfreeze countdown MAYBE? + if parent.demoGroupCounter >= parent.demoGroupCount: # end of Treatment + parent.demoGroupCount = None + parent.demoGroupCounter = 0 + parent.demoSelection = 40 + + elif parent.demoSelection == 31: # Saline Bolus . . . . . . . . . . . . . + parent.uf_state = TreatmentDialysisStates.DIALYSIS_SALINE_BOLUS_STATE + parent.saline_state = SalineBolusStates.SALINE_BOLUS_STATE_IN_PROGRESS # 2 Saline bolus state + parent.demoSelection = 32 + parent.salineVolume_ml = 0.0 # reset + + elif parent.demoSelection == 32: # Saline Bolus delivery + rsp_id = MsgIds.MSG_ID_SALINE_BOLUS_DATA + bolus_target_ml = parent.demo_treatment_params.data_int[ + TreatmentParameters.TREATMENT_PARAM_SALINE_BOLUS_VOLUME_ML.value] + new_volume_ml = bolus_target_ml - parent.salineVolume_ml + if parent.salineBolusRate_mlpersec <= new_volume_ml: + new_volume_ml = parent.salineBolusRate_mlpersec # incremental + else: + parent.demoSelection = 33 # done after this, so move on + parent.salineVolume_ml += new_volume_ml + parent.salineVolCum_ml += new_volume_ml + rsp_payload = struct.pack(" 0.199): + # parent.demoSpeed = int(hbv * 10 + 0.5) + # else: + # parent.demoSpeed = 1 + + return rsp_id, rsp_payload + + +def ui_user_confirm_treatment_request(parent, params): + if params.data_int[0] == EResponse.Accepted: + parent.salineVolume_ml = 0.0 + parent.salineVolCum_ml = 0.0 + rsp_id = MsgIds.MSG_ID_PRE_TREATMENT_STATE_DATA + rsp_payload = struct.pack( + "<" + str(PreTreatmentSubModes.NUM_OF_HD_PRE_TREATMENT_STATES.value + 1) + "i", + PreTreatmentSubModes.HD_PRE_TREATMENT_WATER_SAMPLE_STATE.value, + PreTreatmentSampleWaterStates.SAMPLE_WATER_SETUP_STATE.value, # 0 Water sample state + 0, # 1 Consumable self-tests state + 0, # 2 No cartridge self-tests state + 0, # 3 Consumable and cartridge installation state + 0, # 4 Self-tests when the cartridge is dry state + 0, # 5 Prime blood and dialysate circuits and run wet self-tests state + 0, # 6 Re-circulate blood and dialysate circuits state + 0, # 7 Patient connection state + 0, + 0 + ) + parent.demoSelection = 4 # TBD setup event to change to Filter Flush + parent.demoCount = 0 # immediately act on next timer tick + parent.demoCounter = 0 + else: # elif request_val == EResponse.Rejected: + rsp_id = MsgIds.MSG_ID_HD_NEW_TREATMENT_PARAMS_RESPONSE + rsp_payload = integer_to_bytearray(EResponse.Rejected) + rsp_payload += integer_to_bytearray(0) + + return rsp_id, rsp_payload + + +def ui_sample_water_result(parent, params): + if params.data_int[0] == EResponse.Accepted: + ## TBD!!! FOLLOWING IS FUTILE ATTEMPT TO SET UF MAX + calc_max_uf_volume = min(int(parent.MAX_UF_RATE_ML_PER_SEC * parent.treatment_time_sec / 100.0) * 100.0, + parent.MAX_UF_ML_PER_TX) + parent.cmd_set_treatment_parameter_ranges(min_treatment_duration=0, max_treatment_duration=480, + min_uf_volume=0.0, + max_uf_volume=calc_max_uf_volume, + min_dialysate_flow_rate=100, max_dialysate_flow_rate=600) + parent.demoTimedIncValue = PreTreatmentConsumableSelfTestStates.CONSUMABLE_SELF_TESTS_INSTALL_STATE.value + rsp_id = MsgIds.MSG_ID_PRE_TREATMENT_STATE_DATA + rsp_payload = struct.pack( + "<" + str(PreTreatmentSubModes.NUM_OF_HD_PRE_TREATMENT_STATES.value + 1) + "i", + PreTreatmentSubModes.HD_PRE_TREATMENT_SELF_TEST_CONSUMABLE_STATE.value, + 0, # 0 Water sample state + parent.demoTimedIncValue, # 1 Consumable self-tests state + 0, # 2 No cartridge self-tests state + 0, # 3 Consumable and cartridge installation state + 0, # 4 Self-tests when the cartridge is dry state + 0, # 5 Prime blood and dialysate circuits and run wet self-tests state + 0, # 6 Re-circulate blood and dialysate circuits state + 0, # 7 Patient connection state + 0, + 0 + ) + parent.demoSelection = 0 # Wait for user + parent.demoCount = 3 # TBD! setup quick action: 3 timer ticks each step + parent.demoCounter = 0 + else: # elif request_val == EResponse.Rejected: + # 'Secret' jump over pre-treatment when user fails the water test + rsp_id = MsgIds.MSG_ID_PRE_TREATMENT_STATE_DATA + rsp_payload = struct.pack( + "<" + str(PreTreatmentSubModes.NUM_OF_HD_PRE_TREATMENT_STATES.value + 1) + "i", + PreTreatmentSubModes.HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE.value, + 0, # 0 Water sample state + 0, # 1 Consumable self-tests state + 0, # 2 No cartridge self-tests state + 0, # 3 Consumable and cartridge installation state + 0, # 4 Self-tests when the cartridge is dry state + 0, # 5 Prime blood and dialysate circuits and run wet self-tests state + 0, # 6 Re-circulate blood and dialysate circuits state + 0, # 7 TBD! Patient connection state + 0, + 0 + ) + parent.demoSelection = 0 # Wait for user + return rsp_id, rsp_payload + + +def ui_consumable_install_confirm_request(parent, params): + rsp_id = None + rsp_payload = None + ## TBD!!! Does this work? + calc_max_uf_volume = min(int(parent.MAX_UF_RATE_ML_PER_SEC * parent.treatment_time_sec / 100.0) * 100.0, + parent.MAX_UF_ML_PER_TX) + # assuming everything is setup in preceding MSG_ID_UI_SAMPLE_WATER_RESULT handling + parent.demoSelection = 6 # TBD setup event to change to + parent.demoCounter = parent.demoCount # next tick + parent.demoCount = 3 # TBD redundant with above? + parent.demoCounter = parent.demoCount # immediate + + # 1. TBD Note: this will be skipped as an output + parent.demoTimedIncValue = PreTreatmentConsumableSelfTestStates.CONSUMABLE_SELF_TESTS_PRIME_STATE.value + return rsp_id, rsp_payload + + +def ui_installation_confirm_request(parent, params): + rsp_id = None + rsp_payload = None + + # TBD!! Is this needed to clear UI from presenting old data? + parent.cmd_set_treatment_saline_bolus_data(target=parent.demo_treatment_params.data_int[ + TreatmentParameters.TREATMENT_PARAM_SALINE_BOLUS_VOLUME_ML.value], + cumulative=0.0, delivered=0.0) + parent.demoTimedIncValue = PreTreatmentDrySelfTestsStates.DRY_SELF_TESTS_START_STATE.value + parent.demoSelection = 9 # TBD setup event to change to test completions + parent.demoCount = 4 # 4 timer ticks each for 12-16 TBD?? + parent.demoCounter = parent.demoCount + parent.demoCountdownId = MsgIds.MSG_ID_HD_DRY_SELF_TEST_PROGRESS_DATA + # aggregate + # PreTreatmentDrySelfTestsStates.NUM_OF_DRY_SELF_TESTS_STATES * 2 + parent.demoGroupCounter = -parent.demoCounter # start displayed timer progressing with the Counter + + # aggregate counter TBD! calc the 13 + parent.demoGroupCount = PreTreatmentDrySelfTestsStates.NUM_OF_DRY_SELF_TESTS_STATES.value * parent.demoCount + return rsp_id, rsp_payload + + +def ui_start_prime_request(parent, params): + rsp_id = None + rsp_payload = None + parent.demoSelection = 10 # continue on, picking up from previous state setup by selection 9 + parent.demoCount = 5 + parent.demoCounter = parent.demoCount # TBD! creates illusion of starting + parent.demoGroupCount = PreTreatmentPrimeStates.NUM_OF_HD_PRIME_STATES.value * parent.demoCount # aggregate counter + parent.demoGroupCounter = 0 # aggregate counter TBD SHOULD be handled by previous group end logic (?) + return rsp_id, rsp_payload + + +def ui_patient_connection_begin_request(parent, params): + rsp_id = None + rsp_payload = None + # TBD!!! Setup UF Range before this + rsp_id = MsgIds.MSG_ID_HD_PATIENT_CONNECTION_BEGIN_RESPONSE + rsp_payload = integer_to_bytearray(EResponse.Accepted) + rsp_payload += integer_to_bytearray(RequestRejectReasons.REQUEST_REJECT_REASON_NONE.value) + parent.demoSelection = 12 + return rsp_id, rsp_payload + + +def ui_set_uf_volume_parameter_request(parent, params): + rsp_id = MsgIds.MSG_ID_HD_SET_UF_VOLUME_PARAMETER_RESPONSE + rsp_payload = integer_to_bytearray(EResponse.Accepted) + rsp_payload += integer_to_bytearray(RequestRejectReasons.REQUEST_REJECT_REASON_NONE.value) + rsp_payload += integer_to_bytearray(params.data_int[0]) # echo back setting + parent.uf_volume_set_l = params.data_float[0] / 1000.0 # TBD!! passed as mL instead + + if (parent.uf_volume_set_l is not None) and (parent.uf_volume_set_l >= 0.0009) and ( + parent.uf_stop_time_sec is not None): + parent.uf_rate_l_per_sec = parent.uf_volume_set_l / (parent.treatment_time_sec - parent.uf_stop_time_sec) + else: + parent.uf_rate_l_per_sec = 0 + + parent.demoSelection = 0 # Wait for user + return rsp_id, rsp_payload + + +def ui_patient_connection_confirm_request(parent, params): + rsp_id = MsgIds.MSG_ID_HD_PATIENT_CONNECTION_CONFIRM_RESPONSE + rsp_payload = integer_to_bytearray(EResponse.Accepted) + rsp_payload += integer_to_bytearray(RequestRejectReasons.REQUEST_REJECT_REASON_NONE.value) + parent.demoSelection = 0 # Wait for user + return rsp_id, rsp_payload + + +def ui_start_treatment_request(parent, params): + rsp_id = MsgIds.MSG_ID_HD_START_TREATMENT_RESPONSE + rsp_payload = integer_to_bytearray(EResponse.Accepted) + rsp_payload += integer_to_bytearray(RequestRejectReasons.REQUEST_REJECT_REASON_NONE.value) + parent.demoSelection = 20 # Start Treatment + parent.demoCount = 0 # immediately + return rsp_id, rsp_payload + + +def ui_user_treatment_time_change_request(parent, params): + rsp_id = MsgIds.MSG_ID_USER_TREATMENT_TIME_CHANGE_RESPONSE + + if params.data_int[0] is not None: + if params.data_int[0] == 4 * 60 + 30: # 'secret' means to force end if 0 duration is unavailable + params.data_int[0] = 0 + parent.treatment_time_sec = params.data_int[0] * 60 + rsp_payload = integer_to_bytearray(EResponse.Accepted) + rsp_payload += integer_to_bytearray(RequestRejectReasons.REQUEST_REJECT_REASON_NONE.value) + else: + rsp_payload = integer_to_bytearray(EResponse.Rejected) + rsp_payload += integer_to_bytearray( + RequestRejectReasons.REQUEST_REJECT_REASON_TREATMENT_TIME_OUT_OF_RANGE.value) + + rsp_payload += integer_to_bytearray(int(parent.treatment_time_sec / 60)) + rsp_payload += float_to_bytearray(parent.uf_volume_set_l * 1000.0) + + return rsp_id, rsp_payload + + +def ui_user_saline_bolus_request(parent, params): + rsp_id = MsgIds.MSG_ID_USER_SALINE_BOLUS_RESPONSE + rsp_payload = integer_to_bytearray(EResponse.Accepted) + rsp_payload += integer_to_bytearray(RequestRejectReasons.REQUEST_REJECT_REASON_NONE.value) + rsp_payload += integer_to_bytearray( + parent.demo_treatment_params.data_int[TreatmentParameters.TREATMENT_PARAM_SALINE_BOLUS_VOLUME_ML.value]) + + if params.data_int[0] == EResponse.Accepted: + parent.demoSelection = 31 # Saline Bolus + else: + parent.demoSelection = 33 # Bolus Stop request + return rsp_id, rsp_payload + + +def ui_heparin_pause_resume_request(parent, params): + rsp_id = MsgIds.MSG_ID_HD_HEPARIN_PAUSE_RESUME_RESPONSE + rsp_payload = integer_to_bytearray(EResponse.Accepted) + rsp_payload += integer_to_bytearray(RequestRejectReasons.REQUEST_REJECT_REASON_NONE.value) + if params.data_int[0] != EResponse.Accepted: + parent.heparin_pause = True # Heparin Pause + else: + parent.heparin_pause = False # Heparin Resume + return rsp_id, rsp_payload + + +def ui_pressure_limits_change_request(parent, params): + rsp_id = MsgIds.MSG_ID_HD_PRESSURE_LIMITS_CHANGE_RESPONSE + rsp_payload = integer_to_bytearray(EResponse.Accepted) + rsp_payload += integer_to_bytearray(RequestRejectReasons.REQUEST_REJECT_REASON_NONE.value) + # apply new settings + parent.demo_treatment_params.data_int[TreatmentParameters.TREATMENT_PARAM_ART_PRES_LIMIT_WINDOW.value] = \ + params.data_int[0] + parent.demo_treatment_params.data_int[TreatmentParameters.TREATMENT_PARAM_VEN_PRES_LIMIT_WINDOW.value] = \ + params.data_int[1] + parent.demo_treatment_params.data_int[TreatmentParameters.TREATMENT_PARAM_VEN_PRES_LIMIT_ASYMMETRIC.value] = \ + params.data_int[2] + rsp_payload += integer_to_bytearray(params.data_int[0]) # reply with as set + rsp_payload += integer_to_bytearray(params.data_int[1]) + rsp_payload += integer_to_bytearray(params.data_int[2]) + return rsp_id, rsp_payload + + +def ui_user_blood_dial_rate_change_request(parent, params): + rsp_id = MsgIds.MSG_ID_USER_BLOOD_DIAL_RATE_CHANGE_RESPONSE + rsp_payload = integer_to_bytearray(EResponse.Accepted) + rsp_payload += integer_to_bytearray(RequestRejectReasons.REQUEST_REJECT_REASON_NONE.value) + # apply new settings + parent.demo_treatment_params.data_int[TreatmentParameters.TREATMENT_PARAM_BLOOD_FLOW_RATE_ML_MIN.value] = \ + params.data_int[0] + parent.demo_treatment_params.data_int[TreatmentParameters.TREATMENT_PARAM_DIALYSATE_FLOW_RATE_ML_MIN.value] = \ + params.data_int[1] + parent.dialysate_flow_set_point_ml_per_min = params.data_int[1] + parent.blood_flow_set_point_ml_per_min = params.data_int[0] + rsp_payload += integer_to_bytearray(parent.blood_flow_set_point_ml_per_min) + rsp_payload += integer_to_bytearray(parent.dialysate_flow_set_point_ml_per_min) # reply with as set + + return rsp_id, rsp_payload + + +def ui_rinseback_cmd_request(parent, params): + rsp_id = MsgIds.MSG_ID_HD_RINSEBACK_CMD_RESPONSE + rsp_payload = integer_to_bytearray(EResponse.Accepted) + rsp_payload += integer_to_bytearray(RequestRejectReasons.REQUEST_REJECT_REASON_NONE.value) + if params.data_int[0] == 0: # 0 Start Rinseback + parent.rinseback_volume_out_ml = 0 # reset these + parent.demoSelection = 41 + elif params.data_int[0] == 1: # 1 Accelerate ++25 mL/min (R) + parent.rinsebackVelocity_ml_per_sec = min(parent.rinsebackVelocity_ml_per_sec + 25.0 / 60.0, + parent.rinsebackVelocity_max_ml_per_sec) + elif params.data_int[0] == 2: # 2 Decelerate --25 mL/min (R) + parent.rinsebackVelocity_ml_per_sec = max(parent.rinsebackVelocity_ml_per_sec - 25.0 / 60.0, + parent.rinsebackVelocity_min_ml_per_sec) + elif params.data_int[0] == 3: # 3 Pause + parent.demoSelection = 44 + elif params.data_int[0] == 4: # 4 Resume + parent.demoSelection = 41 + elif params.data_int[0] == 5: # 5 = "End" during rinseback + rsp_id = MsgIds.MSG_ID_HD_OP_MODE_DATA + rsp_payload = integer_to_bytearray(HDOpModes.MODE_POST.value) + rsp_payload += integer_to_bytearray(PostTreatmentStates.HD_POST_TREATMENT_DRAIN_RESERVOIRS_STATE.value) + parent.demoSelection = 0 # Complete Treatment + parent.demoCount = 0 # immediately + + elif params.data_int[0] == 6: # TBD!! Additional + # TreatmentRinsebackStates.RINSEBACK_RUN_ADDITIONAL_STATE.value + # #TBD!! # 4 Additional rinseback volume (10 mL) state of the rinseback sub-mode state machine + parent.rinseback_volume_set_ml += 10.0 # ++10 mL (R) + parent.demoSelection = 45 + + elif params.data_int[0] == 8: # "END" 8 = Disconnect without further rinseback + parent.demoSelection = 60 # Prompt User + parent.demoCount = 0 # immediately + + elif params.data_int[0] == 9: # TBD!! Additional not implemented 9 = return to treatment + rsp_payload = integer_to_bytearray(EResponse.Rejected) + + return rsp_id, rsp_payload + + +def ui_displosal_removal_confirm_request(parent, params): + rsp_id = MsgIds.MSG_ID_HD_DISPOSABLE_REMOVAL_CONFIRM_RESPONSE + rsp_payload = integer_to_bytearray(EResponse.Accepted) + rsp_payload += integer_to_bytearray(RequestRejectReasons.REQUEST_REJECT_REASON_NONE.value) + parent.demoSelection = 1 # Reset to beginning (rather than Disinfect choices '= 50') + parent.demoCount = 0 # immediately + return rsp_id, rsp_payload + + +def ui_post_tx_next_request(parent, params): + rsp_id = MsgIds.MSG_ID_HD_POST_TX_NEXT_CMD_RESPONSE + rsp_payload = integer_to_bytearray(EResponse.Accepted) + rsp_payload += integer_to_bytearray(RequestRejectReasons.REQUEST_REJECT_REASON_NONE.value) + parent.demoCount = 0 # immediately + return rsp_id, rsp_payload \ No newline at end of file Index: dialin/ui/hd_simulator.py =================================================================== diff -u -rd45ebd9da5b356cb88f9e1cc2b3d71f8cb0ddbab -r1e9de03223eeeec426716c6157ce88ddd60e4d5a --- dialin/ui/hd_simulator.py (.../hd_simulator.py) (revision d45ebd9da5b356cb88f9e1cc2b3d71f8cb0ddbab) +++ dialin/ui/hd_simulator.py (.../hd_simulator.py) (revision 1e9de03223eeeec426716c6157ce88ddd60e4d5a) @@ -6,7 +6,7 @@ # WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. # # @file hd_simulator.py -# +# @author (last) Mohammad Suleiman # @author (last) Darren Cox # @date (last) 08-Nov-2022 # @author (original) Peter Lucia @@ -27,6 +27,10 @@ from math import copysign import threading as threads_here from time import time, sleep +from . import dd_ui_request_handler as uim +from . import dd_selection_handler as sel +from . import pressure_ranges as pr + def catch_exception(f): @functools.wraps(f) def func(*args, **kwargs): @@ -51,15 +55,7 @@ self.data_int = [None] * self.MAX_NUM_PARAMETERS self.data_float = [None] * self.MAX_NUM_PARAMETERS -class PressureRanges: - PRESSURE_STEPS = 10 - ARTERIAL_PRESSURE_LIMIT_MAX_MMHG = 100 - ARTERIAL_PRESSURE_LIMIT_MIN_MMHG = -300 - VENOUS_PRESSURE_LIMIT_MAX_MMHG = 400 - VENOUS_PRESSURE_LIMIT_MIN_MMHG = 20 - - class HDSimulator(AbstractSubSystem): __metaclass__ = ErrorCatcher ## TBD! DEBUG only: remove @@ -274,380 +270,91 @@ # UI RESET -------------------------------------------------------- if msg_id == MsgIds.MSG_ID_UI_POST_FINAL_TEST_RESULT.value: - self.demoSelection = 1 # setup event to change Mode - self.demoCount = 0 - self.demoCounter = 1 + rsp_id, rsp_payload = uim.ui_post_final_test_result(self, params) # RESET/JUMP FORWARD DIALOG HANDLER ------------------------------- if (msg_id == MsgIds.MSG_ID_UI_CONFIRMATION_RESULT_RESPONSE.value) and \ (params.data_int[0] == 99) and \ (params.data_int[1] == EResponse.Accepted): # TBD! Use const for 99 - rsp_id = MsgIds.MSG_ID_HD_UI_CONFIRMATION_REQUEST - rsp_payload = integer_to_bytearray(98) - rsp_payload += integer_to_bytearray(0) # TBD use consts - rsp_payload += integer_to_bytearray(0) - self.pause_demoSelection = self.demoSelection # setup event to change state on demoTimer - self.pause_demoCount = self.demoCount - self.pause_demoId = self.demoCountdownId - self.demoGroupCounter += self.demoCounter - self.demoSelection = 0 # setup event to change state on demoTimer - self.demoCount = 0 + rsp_id, rsp_payload = uim.ui_confirmation_result_response_99(self, params) elif (msg_id == MsgIds.MSG_ID_UI_CONFIRMATION_RESULT_RESPONSE.value) and \ (params.data_int[0] == 98): - rsp_id = MsgIds.MSG_ID_HD_UI_CONFIRMATION_REQUEST - rsp_payload = integer_to_bytearray(98) # TBD! Use const for 99 - rsp_payload += integer_to_bytearray(3) # TBD use consts - rsp_payload += integer_to_bytearray(0) - if params.data_int[1] == EResponse.Accepted: # Reset the Demo - self.demoSelection = 1 # setup event to change Mode - self.demoCount = 0 - self.demoCounter = 1 - else: # EResponse.Rejected - Just Jump Forward on any current counter - self.demoSelection = self.pause_demoSelection # setup event to change state on demoTimer - self.demoCountdownId = self.pause_demoId - self.demoCount = self.pause_demoCount - self.demoCounter = self.demoCount - 1 - if self.demoSelection == 42: # Rinseback in process; short cycle it - self.rinseback_volume_out_ml = self.rinseback_volume_set_ml - 1 - self.rinseback_volume_all_ml = self.rinseback_volume_out_ml - if self.demoSelection == 5: - self.demoCountdownChannel = DenaliChannels.dg_to_ui_ch_id + rsp_id, rsp_payload = uim.ui_confirmation_result_98(self, params) elif (msg_id == MsgIds.MSG_ID_UI_CONFIRMATION_RESULT_RESPONSE.value) and \ (params.data_int[0] == 6): - rsp_id = MsgIds.MSG_ID_HD_UI_CONFIRMATION_REQUEST - rsp_payload = integer_to_bytearray(6) - if params.data_int[1] == EResponse.Accepted: - rsp_payload += integer_to_bytearray(1) - rsp_payload += integer_to_bytearray(0) - self.demoSelection = 61 # setup event to change Mode - elif params.data_int[1] == 0: - rsp_payload += integer_to_bytearray(3) - rsp_payload += integer_to_bytearray(0) - self.demoCount = 0 - self.demoCounter = 0 + rsp_id, rsp_payload = uim.ui_confirmation_result_response_6(self, params) # SERVICE MODE elif msg_id == MsgIds.MSG_ID_UI_SERVICE_MODE_REQUEST.value: # 0xB0 - rsp_id = MsgIds.MSG_ID_HD_OP_MODE_DATA - rsp_payload = integer_to_bytearray(HDOpModes.MODE_SERV.value) - rsp_payload += integer_to_bytearray(0) + rsp_id, rsp_payload = uim.ui_service_mode_request(self, params) # INITIATE A NEW TREATMENT SETUP ---------------------------------- elif msg_id == MsgIds.MSG_ID_UI_INITIATE_TREATMENT_REQUEST.value: - rsp_id = MsgIds.MSG_ID_HD_OP_MODE_DATA - if params.data_int[0] == EResponse.Accepted: - rsp_payload = integer_to_bytearray(HDOpModes.MODE_TPAR.value) - else: - rsp_payload = integer_to_bytearray(HDOpModes.MODE_STAN.value) - rsp_payload += integer_to_bytearray(0) + rsp_id, rsp_payload = uim.ui_initiate_treatment_request(self, params) elif msg_id == MsgIds.MSG_ID_UI_NEW_TREATMENT_PARAMS_REQUEST.value: - rsp_id = MsgIds.MSG_ID_HD_NEW_TREATMENT_PARAMS_RESPONSE - rsp_payload = struct.pack("<" + str(TreatmentParameters.NUM_OF_TREATMENT_PARAMS.value + 1) + "i", - 1, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0 - ) - self.demo_treatment_params = deepcopy(params) # keep a complete copy - # UF Treatment - self.treatment_time_sec = params.data_int[TreatmentParameters.TREATMENT_PARAM_TREATMENT_DURATION_MIN.value] * 60 - self.uf_volume_set_l = 0 # TBD not in this message - self.uf_volume_out_l = 0 # reset status - self.uf_rate_l_per_sec = 0 - self.salineVolume_ml = 0.0 # status - self.salineVolCum_ml = 0.0 # status - self.dialysate_flow_set_point_ml_per_min = params.data_int[TreatmentParameters.TREATMENT_PARAM_DIALYSATE_FLOW_RATE_ML_MIN.value] - self.blood_flow_set_point_ml_per_min = params.data_int[TreatmentParameters.TREATMENT_PARAM_BLOOD_FLOW_RATE_ML_MIN.value] - # rsp_id = MsgIds.MSG_ID_HD_PRESSURE_LIMITS_CHANGE_RESPONSE - self.cmd_send_treatment_adjust_pressures_limit_response( accepted=EResponse.Accepted, - reason=RequestRejectReasons.REQUEST_REJECT_REASON_NONE.value, - arterial_pressure_limit_window=self.demo_treatment_params.data_int[TreatmentParameters.TREATMENT_PARAM_ART_PRES_LIMIT_WINDOW.value], - venous_pressure_limit_window=self.demo_treatment_params.data_int[TreatmentParameters.TREATMENT_PARAM_VEN_PRES_LIMIT_WINDOW.value], - venous_pressure_limit_asymmetric=self.demo_treatment_params.data_int[TreatmentParameters.TREATMENT_PARAM_VEN_PRES_LIMIT_ASYMMETRIC.value] ) - self.arterial_pressure_mid_mmHg = ( PressureRanges.ARTERIAL_PRESSURE_LIMIT_MIN_MMHG + PressureRanges.ARTERIAL_PRESSURE_LIMIT_MAX_MMHG ) / 2 - self.venous_pressure_mid_mmHg = ( PressureRanges.VENOUS_PRESSURE_LIMIT_MIN_MMHG + PressureRanges.VENOUS_PRESSURE_LIMIT_MAX_MMHG ) / 2 - self.arterial_pressure_mmHg = self.arterial_pressure_mid_mmHg - 32.0 # simulation - self.venous_pressure_mmHg = self.venous_pressure_mid_mmHg + 32 # simulation - # Rinseback - self.rinseback_volume_set_ml = 80 + 120 # TBD! 80 + should be based on dialyzer blood volume? - self.rinsebackVelocity_ml_per_sec = params.data_int[TreatmentParameters.TREATMENT_PARAM_RINSEBACK_FLOW_RATE_ML_MIN.value] / 60.0 - self.rinseback_volume_out_ml = 0 # reset status - self.rinseback_volume_all_ml = 0 - # Heparin - self.heparin_stop_min = params.data_int[TreatmentParameters.TREATMENT_PARAM_HEPARIN_PRESTOP_MIN.value] - self.heparin_rate_ml_per_hr = params.data_float[TreatmentParameters.TREATMENT_PARAM_HEPARIN_DISPENSE_RATE_ML_HR.value] - self.heparin_rate_ml_per_s = self.heparin_rate_ml_per_hr / 3600.0 - self.heparin_bolus_ml = params.data_float[TreatmentParameters.TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME_ML.value] - self.heparin_out_ml = 0 # reset status - self.heparin_pause = False # setting - self.heparin_expected_ml = ((self.treatment_time_sec / 60.0) - self.heparin_stop_min) / 60.0 * self.heparin_rate_ml_per_hr + self.heparin_bolus_ml - # 'Secret' speed setting: 10x heparin bolus volume, when heparinStopTime=430 and heparinRate is OFF - # if math.isclose(sto, 430) and math.isclose(hdr, 0) and (hbv > 0.199): - # self.demoSpeed = int(hbv * 10 + 0.5) - # else: - # self.demoSpeed = 1 + rsp_id, rsp_payload = uim.ui_new_treatment_params_request(self, params) elif msg_id == MsgIds.MSG_ID_UI_USER_CONFIRM_TREATMENT_PARAMS_REQUEST.value: - if params.data_int[0] == EResponse.Accepted: - self.salineVolume_ml = 0.0 - self.salineVolCum_ml = 0.0 - rsp_id = MsgIds.MSG_ID_PRE_TREATMENT_STATE_DATA - rsp_payload = struct.pack( - "<" + str(PreTreatmentSubModes.NUM_OF_HD_PRE_TREATMENT_STATES.value + 1) + "i", - PreTreatmentSubModes.HD_PRE_TREATMENT_WATER_SAMPLE_STATE.value, - PreTreatmentSampleWaterStates.SAMPLE_WATER_SETUP_STATE.value, # 0 Water sample state - 0, # 1 Consumable self-tests state - 0, # 2 No cartridge self-tests state - 0, # 3 Consumable and cartridge installation state - 0, # 4 Self-tests when the cartridge is dry state - 0, # 5 Prime blood and dialysate circuits and run wet self-tests state - 0, # 6 Re-circulate blood and dialysate circuits state - 0, # 7 Patient connection state - 0, - 0 - ) - self.demoSelection = 4 # TBD setup event to change to Filter Flush - self.demoCount = 0 # immediately act on next timer tick - self.demoCounter = 0 + rsp_id, rsp_payload = uim.ui_user_confirm_treatment_request(self, params) - else: # elif request_val == EResponse.Rejected: - rsp_id = MsgIds.MSG_ID_HD_NEW_TREATMENT_PARAMS_RESPONSE - rsp_payload = integer_to_bytearray(EResponse.Rejected) - rsp_payload += integer_to_bytearray(0) - # WATER SAMPLING -------------------------------------------------- elif msg_id == MsgIds.MSG_ID_UI_SAMPLE_WATER_RESULT.value: # sample water completed, prime filter... - if params.data_int[0] == EResponse.Accepted: - ## TBD!!! FOLLOWING IS FUTILE ATTEMPT TO SET UF MAX - calc_max_uf_volume = min(int(self.MAX_UF_RATE_ML_PER_SEC * self.treatment_time_sec/100.0)*100.0, self.MAX_UF_ML_PER_TX) - self.cmd_set_treatment_parameter_ranges(min_treatment_duration=0, max_treatment_duration=480, - min_uf_volume=0.0, - max_uf_volume=calc_max_uf_volume, - min_dialysate_flow_rate=100, max_dialysate_flow_rate=600) - self.demoTimedIncValue = PreTreatmentConsumableSelfTestStates.CONSUMABLE_SELF_TESTS_INSTALL_STATE.value - rsp_id = MsgIds.MSG_ID_PRE_TREATMENT_STATE_DATA - rsp_payload = struct.pack( - "<" + str(PreTreatmentSubModes.NUM_OF_HD_PRE_TREATMENT_STATES.value + 1) + "i", - PreTreatmentSubModes.HD_PRE_TREATMENT_SELF_TEST_CONSUMABLE_STATE.value, - 0, # 0 Water sample state - self.demoTimedIncValue, # 1 Consumable self-tests state - 0, # 2 No cartridge self-tests state - 0, # 3 Consumable and cartridge installation state - 0, # 4 Self-tests when the cartridge is dry state - 0, # 5 Prime blood and dialysate circuits and run wet self-tests state - 0, # 6 Re-circulate blood and dialysate circuits state - 0, # 7 Patient connection state - 0, - 0 - ) - self.demoSelection = 0 # Wait for user - self.demoCount = 3 # TBD! setup quick action: 3 timer ticks each step - self.demoCounter = 0 - else: # elif request_val == EResponse.Rejected: - # 'Secret' jump over pre-treatment when user fails the water test - rsp_id = MsgIds.MSG_ID_PRE_TREATMENT_STATE_DATA - rsp_payload = struct.pack( - "<" + str(PreTreatmentSubModes.NUM_OF_HD_PRE_TREATMENT_STATES.value + 1) + "i", - PreTreatmentSubModes.HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE.value, - 0, # 0 Water sample state - 0, # 1 Consumable self-tests state - 0, # 2 No cartridge self-tests state - 0, # 3 Consumable and cartridge installation state - 0, # 4 Self-tests when the cartridge is dry state - 0, # 5 Prime blood and dialysate circuits and run wet self-tests state - 0, # 6 Re-circulate blood and dialysate circuits state - 0, # 7 TBD! Patient connection state - 0, - 0 - ) - self.demoSelection = 0 # Wait for user + rsp_id, rsp_payload = uim.ui_sample_water_result(self, params) # PRETREATMENT INSTALL AND TESTS --------------------------------- elif msg_id == MsgIds.MSG_ID_UI_CONSUMABLE_INSTALL_CONFIRM_REQUEST.value: - ## TBD!!! Does this work? - calc_max_uf_volume = min(int(self.MAX_UF_RATE_ML_PER_SEC * self.treatment_time_sec / 100.0) * 100.0, - self.MAX_UF_ML_PER_TX) - # assuming everything is setup in preceding MSG_ID_UI_SAMPLE_WATER_RESULT handling - self.demoSelection = 6 # TBD setup event to change to - self.demoCounter = self.demoCount # next tick - self.demoCount = 3 # TBD redundant with above? - self.demoCounter = self.demoCount # immediate - self.demoTimedIncValue = PreTreatmentConsumableSelfTestStates.CONSUMABLE_SELF_TESTS_PRIME_STATE.value # 1. TBD Note: this will be skipped as an output + rsp_id, rsp_payload = uim.ui_consumable_install_confirm_request(self, params) elif msg_id == MsgIds.MSG_ID_UI_INSTALLATION_CONFIRM_REQUEST.value: - ## TBD!! Is this needed to clear UI from presenting old data? - self.cmd_set_treatment_saline_bolus_data(target=self.demo_treatment_params.data_int[ - TreatmentParameters.TREATMENT_PARAM_SALINE_BOLUS_VOLUME_ML.value], - cumulative=0.0, delivered=0.0) - self.demoTimedIncValue = PreTreatmentDrySelfTestsStates.DRY_SELF_TESTS_START_STATE.value - self.demoSelection = 9 # TBD setup event to change to test completions - self.demoCount = 4 # 4 timer ticks each for 12-16 TBD?? - self.demoCounter = self.demoCount - self.demoCountdownId = MsgIds.MSG_ID_HD_DRY_SELF_TEST_PROGRESS_DATA - # aggregate - # PreTreatmentDrySelfTestsStates.NUM_OF_DRY_SELF_TESTS_STATES * 2 - self.demoGroupCounter = -self.demoCounter # start displayed timer progressing with the Counter - self.demoGroupCount = PreTreatmentDrySelfTestsStates.NUM_OF_DRY_SELF_TESTS_STATES.value * self.demoCount # aggregate counter TBD! calc the 13 + rsp_id, rsp_payload = uim.ui_installation_confirm_request(self, params) elif msg_id == MsgIds.MSG_ID_UI_START_PRIME_REQUEST.value: # _60 x3C 'Start Prime' - self.demoSelection = 10 # continue on, picking up from previous state setup by selection 9 - self.demoCount = 5 - self.demoCounter = self.demoCount # TBD! creates illusion of starting - self.demoGroupCount = PreTreatmentPrimeStates.NUM_OF_HD_PRIME_STATES.value * self.demoCount # aggregate counter - self.demoGroupCounter = 0 # aggregate counter TBD SHOULD be handled by previous group end logic (?) + rsp_id, rsp_payload = uim.ui_start_prime_request(self, params) # TREATMENT: PATIENT CONNECT -------------------------------------- elif msg_id == MsgIds.MSG_ID_UI_PATIENT_CONNECTION_BEGIN_REQUEST.value: # 100 x64 'Continue' Priming Complete - # TBD!!! Setup UF Range before this - rsp_id = MsgIds.MSG_ID_HD_PATIENT_CONNECTION_BEGIN_RESPONSE - rsp_payload = integer_to_bytearray(EResponse.Accepted) - rsp_payload += integer_to_bytearray(RequestRejectReasons.REQUEST_REJECT_REASON_NONE.value) - self.demoSelection = 12 + rsp_id, rsp_payload = uim.ui_patient_connection_begin_request(self, params) elif msg_id == MsgIds.MSG_ID_UI_SET_UF_VOLUME_PARAMETER_REQUEST.value: # _79 x4F - rsp_id = MsgIds.MSG_ID_HD_SET_UF_VOLUME_PARAMETER_RESPONSE - rsp_payload = integer_to_bytearray(EResponse.Accepted) - rsp_payload += integer_to_bytearray(RequestRejectReasons.REQUEST_REJECT_REASON_NONE.value) - rsp_payload += integer_to_bytearray(params.data_int[0]) # echo back setting - self.uf_volume_set_l = params.data_float[0] / 1000.0 # TBD!! passed as mL instead - if (self.uf_volume_set_l is not None) and (self.uf_volume_set_l >= 0.0009 ) and (self.uf_stop_time_sec is not None): - self.uf_rate_l_per_sec = self.uf_volume_set_l / (self.treatment_time_sec - self.uf_stop_time_sec) # param - else: - self.uf_rate_l_per_sec = 0 - self.demoSelection = 0 # Wait for user + rsp_id, rsp_payload = uim.ui_set_uf_volume_parameter_request(self, params) elif msg_id == MsgIds.MSG_ID_UI_PATIENT_CONNECTION_CONFIRM_REQUEST.value: # 102 x66 - rsp_id = MsgIds.MSG_ID_HD_PATIENT_CONNECTION_CONFIRM_RESPONSE - rsp_payload = integer_to_bytearray(EResponse.Accepted) - rsp_payload += integer_to_bytearray(RequestRejectReasons.REQUEST_REJECT_REASON_NONE.value) - self.demoSelection = 0 # Wait for user + rsp_id, rsp_payload = uim.ui_patient_connection_confirm_request(self, params) elif msg_id == MsgIds.MSG_ID_UI_START_TREATMENT_REQUEST.value: # 113 x71 - rsp_id = MsgIds.MSG_ID_HD_START_TREATMENT_RESPONSE - rsp_payload = integer_to_bytearray(EResponse.Accepted) - rsp_payload += integer_to_bytearray(RequestRejectReasons.REQUEST_REJECT_REASON_NONE.value) - self.demoSelection = 20 # Start Treatment - self.demoCount = 0 # immediately + rsp_id, rsp_payload = uim.ui_start_treatment_request(self, params) # DIALYSIS --------------------------------------------------- elif msg_id == MsgIds.MSG_ID_USER_TREATMENT_TIME_CHANGE_REQUEST.value: # _22 x16 - rsp_id = MsgIds.MSG_ID_USER_TREATMENT_TIME_CHANGE_RESPONSE - if params.data_int[0] is not None: - if params.data_int[0] == 4 * 60 + 30: # 'secret' means to force end if 0 duration is unavailable - params.data_int[0] = 0 - self.treatment_time_sec = params.data_int[0] * 60 - rsp_payload = integer_to_bytearray(EResponse.Accepted) - rsp_payload += integer_to_bytearray(RequestRejectReasons.REQUEST_REJECT_REASON_NONE.value) - else: - rsp_payload = integer_to_bytearray(EResponse.Rejected) - rsp_payload += integer_to_bytearray(RequestRejectReasons.REQUEST_REJECT_REASON_TREATMENT_TIME_OUT_OF_RANGE.value) - rsp_payload += integer_to_bytearray(int(self.treatment_time_sec / 60)) - rsp_payload += float_to_bytearray(self.uf_volume_set_l * 1000.0) + rsp_id, rsp_payload = uim.ui_user_treatment_time_change_request(self, params) elif msg_id == MsgIds.MSG_ID_USER_SALINE_BOLUS_REQUEST.value: # _18 x12 - rsp_id = MsgIds.MSG_ID_USER_SALINE_BOLUS_RESPONSE - rsp_payload = integer_to_bytearray(EResponse.Accepted) - rsp_payload += integer_to_bytearray(RequestRejectReasons.REQUEST_REJECT_REASON_NONE.value) - rsp_payload += integer_to_bytearray(self.demo_treatment_params.data_int[TreatmentParameters.TREATMENT_PARAM_SALINE_BOLUS_VOLUME_ML.value]) + rsp_id, rsp_payload = uim.ui_user_saline_bolus_request(self, params) - if params.data_int[0] == EResponse.Accepted: - self.demoSelection = 31 # Saline Bolus - else: - self.demoSelection = 33 # Bolus Stop request - elif msg_id == MsgIds.MSG_ID_UI_HEPARIN_PAUSE_RESUME_REQUEST.value: # _.. x4B - rsp_id = MsgIds.MSG_ID_HD_HEPARIN_PAUSE_RESUME_RESPONSE - rsp_payload = integer_to_bytearray(EResponse.Accepted) - rsp_payload += integer_to_bytearray(RequestRejectReasons.REQUEST_REJECT_REASON_NONE.value) - if params.data_int[0] != EResponse.Accepted: - self.heparin_pause = True # Heparin Pause - else: - self.heparin_pause = False # Heparin Resume + rsp_id, rsp_payload = uim.ui_heparin_pause_resume_request(self, params) elif msg_id == MsgIds.MSG_ID_UI_PRESSURE_LIMITS_CHANGE_REQUEST.value: # _70 x46 - rsp_id = MsgIds.MSG_ID_HD_PRESSURE_LIMITS_CHANGE_RESPONSE - rsp_payload = integer_to_bytearray(EResponse.Accepted) - rsp_payload += integer_to_bytearray(RequestRejectReasons.REQUEST_REJECT_REASON_NONE.value) - # apply new settings - self.demo_treatment_params.data_int[TreatmentParameters.TREATMENT_PARAM_ART_PRES_LIMIT_WINDOW.value] =\ - params.data_int[0] - self.demo_treatment_params.data_int[TreatmentParameters.TREATMENT_PARAM_VEN_PRES_LIMIT_WINDOW.value] =\ - params.data_int[1] - self.demo_treatment_params.data_int[TreatmentParameters.TREATMENT_PARAM_VEN_PRES_LIMIT_ASYMMETRIC.value] =\ - params.data_int[2] - rsp_payload += integer_to_bytearray(params.data_int[0]) # reply with as set - rsp_payload += integer_to_bytearray(params.data_int[1]) - rsp_payload += integer_to_bytearray(params.data_int[2]) + rsp_id, rsp_payload = uim.ui_pressure_limits_change_request(self, params) elif msg_id == MsgIds.MSG_ID_USER_BLOOD_DIAL_RATE_CHANGE_REQUEST.value: # _70 x46 - rsp_id = MsgIds.MSG_ID_USER_BLOOD_DIAL_RATE_CHANGE_RESPONSE - rsp_payload = integer_to_bytearray(EResponse.Accepted) - rsp_payload += integer_to_bytearray(RequestRejectReasons.REQUEST_REJECT_REASON_NONE.value) - # apply new settings - self.demo_treatment_params.data_int[TreatmentParameters.TREATMENT_PARAM_BLOOD_FLOW_RATE_ML_MIN.value] =\ - params.data_int[0] - self.demo_treatment_params.data_int[TreatmentParameters.TREATMENT_PARAM_DIALYSATE_FLOW_RATE_ML_MIN.value] =\ - params.data_int[1] - self.dialysate_flow_set_point_ml_per_min = params.data_int[1] - self.blood_flow_set_point_ml_per_min = params.data_int[0] - rsp_payload += integer_to_bytearray(self.blood_flow_set_point_ml_per_min) - rsp_payload += integer_to_bytearray(self.dialysate_flow_set_point_ml_per_min) # reply with as set + rsp_id, rsp_payload = uim.ui_user_blood_dial_rate_change_request(self, params) # RINSEBACK ------------------------- elif msg_id == MsgIds.MSG_ID_UI_RINSEBACK_CMD_REQUEST.value: # _82 x52 - rsp_id = MsgIds.MSG_ID_HD_RINSEBACK_CMD_RESPONSE - rsp_payload = integer_to_bytearray(EResponse.Accepted) - rsp_payload += integer_to_bytearray(RequestRejectReasons.REQUEST_REJECT_REASON_NONE.value) - if params.data_int[0] ==0: # 0 Start Rinseback - self.rinseback_volume_out_ml = 0 # reset these - self.demoSelection = 41 - elif params.data_int[0] == 1: # 1 Accelerate ++25 mL/min (R) - self.rinsebackVelocity_ml_per_sec = min( self.rinsebackVelocity_ml_per_sec + 25.0 / 60.0, - self.rinsebackVelocity_max_ml_per_sec ) - elif params.data_int[0] == 2: # 2 Decelerate --25 mL/min (R) - self.rinsebackVelocity_ml_per_sec = max( self.rinsebackVelocity_ml_per_sec - 25.0 / 60.0, - self.rinsebackVelocity_min_ml_per_sec ) - elif params.data_int[0] == 3: # 3 Pause - self.demoSelection = 44 - elif params.data_int[0] == 4: # 4 Resume - self.demoSelection = 41 - elif params.data_int[0] == 5: # 5 = "End" during rinseback - rsp_id = MsgIds.MSG_ID_HD_OP_MODE_DATA - rsp_payload = integer_to_bytearray(HDOpModes.MODE_POST.value) - rsp_payload += integer_to_bytearray(PostTreatmentStates.HD_POST_TREATMENT_DRAIN_RESERVOIRS_STATE.value) - self.demoSelection = 0 # Complete Treatment - self.demoCount = 0 # immediately + rsp_id, rsp_payload = uim.ui_rinseback_cmd_request(self, params) - elif params.data_int[0] == 6: # TBD!! Additional - # TreatmentRinsebackStates.RINSEBACK_RUN_ADDITIONAL_STATE.value #TBD!! # 4 Additional rinseback volume (10 mL) state of the rinseback sub-mode state machine - self.rinseback_volume_set_ml += 10.0 # ++10 mL (R) - self.demoSelection = 45 - - elif params.data_int[0] == 8: # "END" 8 = Disconnect without further rinseback - self.demoSelection = 60 # Prompt User - self.demoCount = 0 # immediately - - elif params.data_int[0] == 9: # TBD!! Additional not implemented 9 = return to treatment - rsp_payload = integer_to_bytearray(EResponse.Rejected) - elif msg_id == MsgIds.MSG_ID_UI_TREATMENT_LOG_DATA_REQUEST.value: # _74 x4A self._send_treatment_log() elif msg_id == MsgIds.MSG_ID_UI_DISPOSABLE_REMOVAL_CONFIRM_REQUEST.value: # 115 x73 - rsp_id = MsgIds.MSG_ID_HD_DISPOSABLE_REMOVAL_CONFIRM_RESPONSE - rsp_payload = integer_to_bytearray(EResponse.Accepted) - rsp_payload += integer_to_bytearray(RequestRejectReasons.REQUEST_REJECT_REASON_NONE.value) - self.demoSelection = 1 # Reset to beginning (rather than Disinfect choices '= 50') - self.demoCount = 0 # immediately + rsp_id, rsp_payload = uim.ui_displosal_removal_confirm_request(self, params) elif msg_id == MsgIds.MSG_ID_UI_POST_TX_NEXT_REQUEST.value: # 0x6 - rsp_id = MsgIds.MSG_ID_HD_POST_TX_NEXT_CMD_RESPONSE - rsp_payload = integer_to_bytearray(EResponse.Accepted) - rsp_payload += integer_to_bytearray(RequestRejectReasons.REQUEST_REJECT_REASON_NONE.value) - self.demoCount = 0 # immediately + rsp_id, rsp_payload = uim.ui_post_tx_next_request(self, params) # # -------------------------------------------------- @@ -698,531 +405,72 @@ self.demoTimedIncValue += 1 # RESET INIT TO STANDBY ------------------------------------------- if self.demoSelection == 1: # TBD Reset to start INIT - rsp_id = MsgIds.MSG_ID_HD_OP_MODE_DATA - rsp_payload = integer_to_bytearray(HDOpModes.MODE_INIT.value) - rsp_payload += integer_to_bytearray(HDInitStates.POST_STATE_START.value) - self.demoSelection = 2 # setup event to change state on demoTimer - self.demoCount = 3 - self.demoGroupCount = None + rsp_id, rsp_payload = sel.reset(self) elif self.demoSelection == 2: # TBD Auto transit to standby - rsp_id = MsgIds.MSG_ID_HD_OP_MODE_DATA - rsp_payload = integer_to_bytearray(HDOpModes.MODE_STAN.value) - rsp_payload += integer_to_bytearray(HDStandbyStates.STANDBY_START_STATE.value) - self.demoSelection = 0 # wait for user + rsp_id, rsp_payload = sel.auto_transit_to_standby(self) # PRETREATMENT ---------------------------------------------------- elif self.demoSelection == 4: # = PreTreatmentConsumableSelfTestStates.CONSUMABLE_SELF_TESTS_COMPLETE_STATE.value: self.demoSelection = 7 # TBD! setup event to change to else: pass # repeat this selection elif self.demoSelection == 7: # No Cartridge Self Tests - rsp_id = MsgIds.MSG_ID_PRE_TREATMENT_STATE_DATA - rsp_payload = struct.pack( - "<" + str(PreTreatmentSubModes.NUM_OF_HD_PRE_TREATMENT_STATES.value + 1) + "i", - PreTreatmentSubModes.HD_PRE_TREATMENT_SELF_TEST_NO_CART_STATE.value, - 0, # 0 Water sample state - 0, # 1 Consumable self-tests state - PreTreatmentNoCartSelfTestStates.NO_CART_SELF_TESTS_PRESSURE_CHECKS_STATE.value, - # TBD! 2 No cartridge self-tests state - 0, # 3 Consumable and cartridge installation state - 0, # 4 Self-tests when the cartridge is dry state - 0, # 5 Prime blood and dialysate circuits and run wet self-tests state - 0, # 6 Re-circulate blood and dialysate circuits state - 0, # 7 Patient connection state - 0, - 0 - ) - self.demoCountdownId = MsgIds.MSG_ID_HD_NO_CART_SELF_TEST_PROGRESS_DATA - self.demoSelection = 8 # Setup event to change to HD_PRE_TREATMENT_CART_INSTALL_STATE - self.demoCount = 30 + rsp_id, rsp_payload = sel.cartridge_self_test(self) elif self.demoSelection == 8: # Cartridge Installation - rsp_id = MsgIds.MSG_ID_PRE_TREATMENT_STATE_DATA - rsp_payload = struct.pack( - "<" + str(PreTreatmentSubModes.NUM_OF_HD_PRE_TREATMENT_STATES.value + 1) + "i", - PreTreatmentSubModes.HD_PRE_TREATMENT_CART_INSTALL_STATE.value, - 0, # 0 Water sample state - 0, # 1 Consumable self-tests state - 0, # 2 No cartridge self-tests state - 0, # TBD! 3 Consumable and cartridge installation state - 0, # 4 Self-tests when the cartridge is dry state - 0, # 5 Prime blood and dialysate circuits and run wet self-tests state - 0, # 6 Re-circulate blood and dialysate circuits state - 0, # 7 Patient connection state - 0, - 0 - ) - self.demoSelection = 0 # TBD! setup event to change to // Wait for user + rsp_id, rsp_payload = sel.cartridge_installation(self) elif self.demoSelection == 9: # Dry Self Tests; init by MSG_ID_UI_INSTALLATION_CONFIRM - if self.demoTimedIncValue == PreTreatmentDrySelfTestsStates.DRY_SELF_TESTS_STOPPED_STATE.value: # Skip Stop state - self.demoTimedIncValue = PreTreatmentDrySelfTestsStates.DRY_SELF_TESTS_COMPLETE_STATE.value # And move to Complete state - rsp_id = MsgIds.MSG_ID_PRE_TREATMENT_STATE_DATA - rsp_payload = struct.pack( - "<" + str(PreTreatmentSubModes.NUM_OF_HD_PRE_TREATMENT_STATES.value + 1) + "i", - PreTreatmentSubModes.HD_PRE_TREATMENT_SELF_TEST_DRY_STATE.value, - 0, # 0 Water sample state - 0, # 1 Consumable self-tests state - 0, # 2 No cartridge self-tests state - 0, # 3 Consumable and cartridge installation state - self.demoTimedIncValue, # 4 Self-tests when the cartridge is dry state - 0, # 5 Prime blood and dialysate circuits and run wet self-tests state - 0, # 6 Re-circulate blood and dialysate circuits state - 0, # 7 Patient connection state - 0, - 0 - ) - if self.demoTimedIncValue >= PreTreatmentDrySelfTestsStates.NUM_OF_DRY_SELF_TESTS_STATES.value - 1: - self.demoTimedIncValue = PreTreatmentPrimeStates.HD_PRIME_WAIT_FOR_USER_START_STATE.value - 1 # 1st pass is v+1 - self.demoSelection = 10 # TBD! setup event to change to ... Wait for User - self.demoCount = 0 # TBD! don't advance until user 'Start Prime' - else: - self.demoCountdownId = MsgIds.MSG_ID_HD_DRY_SELF_TEST_PROGRESS_DATA - # TBD setup above: self.demoGroupCount = 14 * 4 # aggregate counter + rsp_id, rsp_payload = sel.dry_self_test(self) # DIALYSATE PRIME CIRCUITS ---------------------------------------- elif self.demoSelection == 10: # Prime circuits with dialysate - rsp_id = MsgIds.MSG_ID_PRE_TREATMENT_STATE_DATA - rsp_payload = struct.pack( - "<" + str(PreTreatmentSubModes.NUM_OF_HD_PRE_TREATMENT_STATES.value + 1) + "i", - PreTreatmentSubModes.HD_PRE_TREATMENT_PRIME_STATE.value, - 0, # 2 No cartridge self-tests state - 0, # 3 Consumable and cartridge installation state - 0, # 0 Water sample state - 0, # 1 Consumable self-tests state - 0, # 4 Self-tests when the cartridge is dry state - self.demoTimedIncValue, # 5 Prime blood and dialysate circuits and run wet self-tests state - 0, # 6 Re-circulate blood and dialysate circuits state - 0, # 7 Patient connection state - 0, - 0 - ) - self.demoCountdownId = MsgIds.MSG_ID_HD_PRIMING_STATUS_DATA - self.demoGroupCount = PreTreatmentPrimeStates.NUM_OF_HD_PRIME_STATES.value * 5 # aggregate count up to TBD! cleanup numbers - if self.demoTimedIncValue == PreTreatmentPrimeStates.HD_PRIME_WAIT_FOR_USER_START_STATE.value: - self.demoSelection = 0 # Wait for User - # self.demoGroupCounter = 0 # aggregate counter - # TBD! could skip HD_PRIME_PAUSE? - elif self.demoTimedIncValue >= PreTreatmentPrimeStates.NUM_OF_HD_PRIME_STATES.value - 1: - self.demoTimedIncValue = None ## TBD!! - self.demoSelection = 11 # on next countdown transition - self.demoCount = 0 # immediate timeout # TBD!! Hack to make counter neat - self.demoGroupCounter = self.demoGroupCount # aggregate counter - # TBD else: - # TBD self.demoCountdownId = MsgIds.MSG_ID_HD_PRIMING_STATUS_DATA # TBD! need an aggregate time/timer + rsp_id, rsp_payload = sel.prime_circuits_with_dialysate(self) elif self.demoSelection == 11: # Recirculate primed circuits - rsp_id = MsgIds.MSG_ID_PRE_TREATMENT_STATE_DATA - rsp_payload = struct.pack( - "<" + str(PreTreatmentSubModes.NUM_OF_HD_PRE_TREATMENT_STATES.value + 1) + "i", - PreTreatmentSubModes.HD_PRE_TREATMENT_RECIRCULATE_STATE.value, - 0, # 0 Water sample state - 0, # 1 Consumable self-tests state - 0, # 2 No cartridge self-tests state - 0, # 3 Consumable and cartridge installation state - 0, # 4 Self-tests when the cartridge is dry state - 0, # 5 Prime blood and dialysate circuits and run wet self-tests state - PreTreatmentRecircStates.PRE_TREATMENT_RECIRC_STATE.value, - # 6 Re-circulate blood and dialysate circuits state - 0, # 7 Patient connection state - 0, - 0 - ) - self.demoSelection = 0 # Then wait for User - self.demoGroupCount = None # clear aggregate count + rsp_id, rsp_payload = sel.recirculate_primed_circuits_1(self) elif self.demoSelection == 12: # Recirculate primed circuits - rsp_id = MsgIds.MSG_ID_PRE_TREATMENT_STATE_DATA - rsp_payload = struct.pack( - "<" + str(PreTreatmentSubModes.NUM_OF_HD_PRE_TREATMENT_STATES.value + 1) + "i", - PreTreatmentSubModes.HD_PRE_TREATMENT_PATIENT_CONNECTION_STATE.value, - 0, # 0 Water sample state - 0, # 1 Consumable self-tests state - 0, # 2 No cartridge self-tests state - 0, # 3 Consumable and cartridge installation state - 0, # 4 Self-tests when the cartridge is dry state - 0, # 5 Prime blood and dialysate circuits and run wet self-tests state - 0, # 6 Re-circulate blood and dialysate circuits state - PreTreatmentPatientConnectionStates.PRE_TREATMENT_PAT_CONN_WAIT_FOR_UF_VOL_STATE.value, # 7 Patient connection state - 0, - 0 - ) - self.demoSelection = 0 # Then wait for User - self.demoGroupCount = None # clear aggregate count + rsp_id, rsp_payload = sel.recirculate_primed_circuits_2(self) # ## START TREATMENT GROUP ----------------------------------------- elif self.demoSelection == 20: # Start Treatment - rsp_id = MsgIds.MSG_ID_HD_OP_MODE_DATA - rsp_payload = integer_to_bytearray(HDOpModes.MODE_TREA.value) - rsp_payload += integer_to_bytearray(0) - self.demoCountdownId = MsgIds.MSG_ID_HD_BLOOD_PRIME_PROGRESS_DATA - self.demoCount = 0 - self.demoCounter = 1 - # self.demoGroupCount = int(120 / 8) # TBD! fix const numbers - # self.demoGroupCount = -1 - self.demoSelection = 21 # Initiate Blood Prime - self.blood_prime_set_point_blood_flow = 20 + rsp_id, rsp_payload = sel.start_treatment(self) elif self.demoSelection == 21: # Blood Prime - rsp_id = MsgIds.MSG_ID_TREATMENT_STATE_DATA - rsp_payload = struct.pack("<10i", - TreatmentStates.TREATMENT_BLOOD_PRIME_STATE.value, # 0 Treatment Submode - 0, # 1 UF state - 0, # 2 Saline bolus state - 0, # 3 Hep state - 0, # 4 Rinseback state - 0, # 5 Recirc state - 0, # 6 Blood Prime state - 0, # 7 End state - 0, # 8 Stop state - 0, # 9 Dialysis state - ) - self.demoSelection = 22 # Complete Blood Prime -> Dialysis - self.demoCountdownId = MsgIds.MSG_ID_HD_BLOOD_PRIME_PROGRESS_DATA - self.demoCount = int(120 / 8) # TBD! fix const numbers - self.demoCounter = -1 # give slight delay + rsp_id, rsp_payload = sel.blood_prime(self) ## DIALYSIS GROUP ------------------------------------------------- elif self.demoSelection == 22: # Dialysis - # preset timing info - self.treatment_start_time_s = time() - self.cmd_set_treatment_time(sec_total=self.treatment_time_sec, sec_elapsed=0, - sec_remain=self.treatment_time_sec) - self.heparin_out_ml = self.heparin_bolus_ml - if self.heparin_bolus_ml > 0: - self.heparin_state = HeparinStates.HEPARIN_STATE_INITIAL_BOLUS # Initial heparin bolus delivery in progress - else: - self.heparin_state = HeparinStates.HEPARIN_STATE_STOPPED # Heparin delivery stopped by alarm or not yet started - self.uf_state = TreatmentDialysisStates.DIALYSIS_START_STATE # 0 Treatment Submode + rsp_id, rsp_payload = sel.start_dialysis(self) - self.demoCount = self.demoSpeed - 1 - self.demoGroupCount = self.treatment_time_sec #TBD!! replace with user setting - self.demoGroupCounter = 0 - self.demoSelection = 29 # start dialysis - elif self.demoSelection == 29: # Enter/Return to normal UF Dialysis - rsp_id = MsgIds.MSG_ID_TREATMENT_STATE_DATA - self.uf_state = TreatmentDialysisStates.DIALYSIS_UF_STATE # 1 UF state - self.saline_state = SalineBolusStates.SALINE_BOLUS_STATE_IDLE # 2 Saline bolus state - rsp_payload = struct.pack("<10i", - TreatmentStates.TREATMENT_DIALYSIS_STATE.value, # 0 Treatment Submode - self.uf_state.value, # 1 UF state - self.saline_state.value, # 2 Saline bolus state - self.heparin_state.value, # 3 Hep state - 0, # 4 Rinseback state - 0, # 5 Recirc state - 0, # 6 Blood Prime state - 0, # 7 End state - 0, # 8 Stop state - 0, # 9 Dialysis state - ) - self.demoSelection = 30 # ongoing data update + rsp_id, rsp_payload = sel.enter_normal_uf(self) elif self.demoSelection >= 30 and self.demoSelection < 40 : # Dialysis Data Update ---------------- - self.blood_stop_time_s = time() # reset timer - self.treatment_stop_time_s = self.blood_stop_time_s - prev_heparin_state = self.heparin_state - prev_saline_state = self.saline_state + rsp_id, rsp_payload = sel.dialysis_data_update(self) - # MSG_ID_BLOOD_FLOW_DATA - self.blood_flow_measured_ml_per_min += (random() - 0.5) * 10 # TBD! replace magic numbers - if self.blood_flow_measured_ml_per_min > (self.blood_flow_set_point_ml_per_min + 30): - self.blood_flow_measured_ml_per_min -= 5 - self.cmd_set_treatment_blood_flow_rate(flow_set_pt=self.blood_flow_set_point_ml_per_min, - measured_flow=self.blood_flow_measured_ml_per_min, - rot_speed=0, mot_speed=0, mc_speed=0, - mc_current=0, pwm=0, rotor_count=0, - pres_flow=self.blood_flow_set_point_ml_per_min, rotor_hall=0) - - # MSG_ID_DIALYSATE_FLOW_DATA - self.dialysate_flow_measured_ml_per_min += (random() - 0.5) * 5 # TBD! replace magic numbers - if self.dialysate_flow_measured_ml_per_min > (self.dialysate_flow_set_point_ml_per_min + 30): - self.dialysate_flow_measured_ml_per_min -= 5 - self.cmd_set_treatment_dialysate_flow_rate(flow_set_pt=self.dialysate_flow_set_point_ml_per_min, - measured_flow=self.dialysate_flow_measured_ml_per_min, - rot_speed=0.0, - mot_speed=0.0, - mc_speed=0.0, - mc_current=0.0, - pwm=0.0, - rotor_count=0, - presFlow=self.dialysate_flow_set_point_ml_per_min, - rotorHall=0) - - # MSG_ID_PRESSURE_OCCLUSION_DATA - - arterial_min_limit = int(self.arterial_pressure_mid_mmHg - (self.demo_treatment_params.data_int[TreatmentParameters.TREATMENT_PARAM_ART_PRES_LIMIT_WINDOW.value] / 2)) - arterial_max_limit = int(self.arterial_pressure_mid_mmHg + (self.demo_treatment_params.data_int[TreatmentParameters.TREATMENT_PARAM_ART_PRES_LIMIT_WINDOW.value] / 2)) - venous_min_limit = int(self.venous_pressure_mid_mmHg - (self.demo_treatment_params.data_int[TreatmentParameters.TREATMENT_PARAM_VEN_PRES_LIMIT_WINDOW.value] / 2)) - venous_max_limit = int(self.venous_pressure_mid_mmHg + (self.demo_treatment_params.data_int[TreatmentParameters.TREATMENT_PARAM_VEN_PRES_LIMIT_WINDOW.value] / 2)) - - self.arterial_pressure_mmHg += (random() - 0.5) * 10 # TBD! replace magic wander numbers - if self.arterial_pressure_mmHg > (self.arterial_pressure_mid_mmHg + 30): - self.arterial_pressure_mmHg -= 5 - # Stay within limits - if int(self.arterial_pressure_mmHg) < arterial_min_limit: - self.arterial_pressure_mmHg = arterial_min_limit - elif int(self.arterial_pressure_mmHg) > arterial_max_limit: - self.arterial_pressure_mmHg = arterial_max_limit - - self.venous_pressure_mmHg += (random() - 0.5) * 10 - if self.venous_pressure_mmHg > (self.venous_pressure_mid_mmHg + 30): - self.venous_pressure_mmHg -= 5 - # Stay within limits - if int(self.venous_pressure_mmHg) < venous_min_limit: - self.venous_pressure_mmHg = venous_min_limit - elif int(self.venous_pressure_mmHg) > venous_max_limit: - self.venous_pressure_mmHg = venous_max_limit - self.cmd_set_pressure_occlusion_data(arterial_prs=self.arterial_pressure_mmHg, - venous_prs=self.venous_pressure_mmHg, - blood_pump_occlusion=0, - pressure_limit_state=0, - arterial_min_limt=arterial_min_limit, - arterial_max_limt=arterial_max_limit, - venous_min_limit=venous_min_limit, - venous_max_limit=venous_max_limit, - arterial_long_filtered_pressure=self.arterial_pressure_mmHg, - venous_long_filtered_pressure=self.venous_pressure_mmHg ) - # MSG_ID_RTC_EPOCH - # tbd! - - # MSG_ID_DIALYSATE_OUT_FLOW_DATA - # TBD!! parameters seem swapped and off by 1000x ?? - # self.cmd_set_treatment_ultrafiltration_outlet_flow_data(ref_uf_vol=self.uf_volume_set_l, - # measured_uf_vol=self.uf_volume_out_l, - # rot_speed=0.0, mot_speed=0.0, mc_speed=0.0, - # mc_current=0.0, pwm=0.0) - self.uf_volume_out_l = min(self.uf_volume_out_l + self.uf_rate_l_per_sec, self.uf_volume_set_l) - self.cmd_set_treatment_ultrafiltration_outlet_flow_data(ref_uf_vol=self.uf_volume_out_l * 1000.0, - measured_uf_vol=self.uf_volume_set_l * 1000.0, - rot_speed=0.0, mot_speed=0.0, mc_speed=0.0, - mc_current=0.0, pwm=0.0, corr_offset=0.0, - pump_calculated_rate=0.0, uf_calculated_rate=0.0, - rotor_hall=0,current_uf_rate= ( self.uf_rate_l_per_sec * 60 )) - - # MSG_ID_LOAD_CELL_READINGS - - # MSG_ID_TREATMENT_TIME - if self.treatment_time_sec != self.demoGroupCount: # handle user change in treatment time - self.demoGroupCount = max(self.treatment_time_sec, self.demoGroupCounter) - - ctr_elapsed_sec = min(self.demoGroupCounter, self.demoGroupCount) - ctr_remain_sec = self.demoGroupCount - self.demoGroupCounter - - self.cmd_set_treatment_time(sec_total=self.demoGroupCount, sec_elapsed=ctr_elapsed_sec, - sec_remain=ctr_remain_sec) - - self.demoGroupCounter -= 1 # TBD! effectively freeze countdown MAYBE? - - # MSG_ID_HD_HEPARIN_DATA_BROADCAST - if ctr_remain_sec < (self.heparin_stop_min * 60.0): - self.heparin_state = HeparinStates.HEPARIN_STATE_COMPLETED - else: - if self.heparin_pause == False: - self.heparin_out_ml += self.heparin_rate_ml_per_s * self.demoSpeed - self.heparin_state = HeparinStates.HEPARIN_STATE_DISPENSING - else: - self.heparin_state = HeparinStates.HEPARIN_STATE_PAUSED - - self.heparin_expected_ml = (ctr_remain_sec - (self.heparin_stop_min * 60.0)) * self.heparin_rate_ml_per_s + self.heparin_out_ml - self.cmd_set_treatment_heparin_data(cumulative=self.heparin_out_ml, required=self.heparin_expected_ml) - - # sub selections within Dialysis Data Update - if self.demoSelection == 30: # Standard UF Dialysis . . . . . . . . . . - self.demoGroupCounter += 1 # TBD! effectively unfreeze countdown MAYBE? - if self.demoGroupCounter >= self.demoGroupCount: # end of Treatment - self.demoGroupCount = None - self.demoGroupCounter = 0 - self.demoSelection = 40 - - elif self.demoSelection == 31: # Saline Bolus . . . . . . . . . . . . . - self.uf_state = TreatmentDialysisStates.DIALYSIS_SALINE_BOLUS_STATE - self.saline_state = SalineBolusStates.SALINE_BOLUS_STATE_IN_PROGRESS # 2 Saline bolus state - self.demoSelection = 32 - self.salineVolume_ml = 0.0 # reset - - elif self.demoSelection == 32: # Saline Bolus delivery - rsp_id = MsgIds.MSG_ID_SALINE_BOLUS_DATA - bolus_target_ml = self.demo_treatment_params.data_int[TreatmentParameters.TREATMENT_PARAM_SALINE_BOLUS_VOLUME_ML.value] - new_volume_ml = bolus_target_ml - self.salineVolume_ml - if self.salineBolusRate_mlpersec <= new_volume_ml: - new_volume_ml = self.salineBolusRate_mlpersec # incremental - else: - self.demoSelection = 33 # done after this, so move on - self.salineVolume_ml += new_volume_ml - self.salineVolCum_ml += new_volume_ml - rsp_payload = struct.pack("= 40) and (self.demoSelection < 50): - set_rinseback_state = None - new_volume_ml = self.rinsebackVelocity_ml_per_sec # incremental - self.demoCount = 0 - self.demoGroupCount = None # int(self.rinseback_volume_set_ml / self.rinsebackVelocity_ml_per_sec + 0.99) - self.demoCountdownId = None + rsp_id, rsp_payload = sel.rinseback(self) - if self.demoSelection == 40: # Rinseback stop before - set_rinseback_state = TreatmentRinsebackStates.RINSEBACK_STOP_INIT_STATE - self.rinseback_volume_out_ml = 0 - self.demoSelection = 49 # then wait for user - - elif self.demoSelection == 41: # Rinseback running - set_rinseback_state = TreatmentRinsebackStates.RINSEBACK_RUN_STATE - self.demoSelection = 42 # next state - - elif self.demoSelection == 42: # Rinseback in process - remain_volume_ml = self.rinseback_volume_set_ml - self.rinseback_volume_out_ml - if remain_volume_ml <= new_volume_ml: - new_volume_ml = remain_volume_ml - self.demoSelection = 43 # done after this, so move on - self.rinseback_volume_out_ml += new_volume_ml - self.rinseback_volume_all_ml += new_volume_ml - - elif self.demoSelection == 43: # Rinseback stop after - set_rinseback_state = TreatmentRinsebackStates.RINSEBACK_STOP_STATE - self.demoSelection = 49 - - elif self.demoSelection == 44: # Rinseback pause - set_rinseback_state = TreatmentRinsebackStates.RINSEBACK_PAUSED_STATE - self.demoSelection = 49 - - elif self.demoSelection == 45: # Additional Rinseback - set_rinseback_state = TreatmentRinsebackStates.RINSEBACK_RUN_ADDITIONAL_STATE - self.demoSelection = 42 - - elif self.demoSelection == 49: # Rinseback wait for user - pass - - # for all Rinseback states: - if self.demoSelection <= 42: # actively/recently moving blood - self.blood_stop_time_s = time() # reset timer - - rsp_id = MsgIds.MSG_ID_HD_RINSEBACK_PROGRESS - used_time = max( 0, 120 - (int(time() - self.blood_stop_time_s))) - rsp_payload = struct.pack("<2f 4i", - self.rinseback_volume_set_ml, # 0 (float) the target volume in mL - float(self.rinseback_volume_all_ml), # 1 (float) the current volume in mL - int(round(new_volume_ml * 60)), # 2 (uint ) the current flow rate in mL/min - 120, # 3 (uint ) Total Timeout - used_time, # 4 (uint ) Current Timeout count down - (self.demoSelection == 43) # 5 (int/bool) complete - ) - tmr_message = DenaliMessage.build_message(channel_id=rsp_channel_id, # TBD!! dup code with below - message_id=rsp_id.value, - payload=rsp_payload) - print("\nT send message:", MsgIds(rsp_id).name, tmr_message) - self.can_interface.send(tmr_message, 0) - - # on Rinsback state changes: - if set_rinseback_state is not None: - rsp_id = MsgIds.MSG_ID_TREATMENT_STATE_DATA - rsp_payload = struct.pack("<10i", - TreatmentStates.TREATMENT_RINSEBACK_STATE.value, # 0 Treatment Submode - TreatmentDialysisStates.DIALYSIS_UF_STATE.value, # 1 UF state - 0, # 2 Saline bolus state - 0, # 3 Hep state - set_rinseback_state.value, # 4 Rinseback state - 0, # 5 Recirc state - 0, # 6 Blood Prime state - 0, # 7 End state - 0, # 8 Stop state - 0, # 9 Dialysis state - ) elif self.demoSelection == 60: - rsp_id = MsgIds.MSG_ID_HD_UI_CONFIRMATION_REQUEST - rsp_payload = integer_to_bytearray(6) - rsp_payload += integer_to_bytearray(0) - rsp_payload += integer_to_bytearray(0) - self.demoSelection = 0 # Wait for User - self.demoCount = 0 + rsp_id, rsp_payload = sel.confirmation_request(self) elif self.demoSelection == 61: - rsp_id = MsgIds.MSG_ID_HD_OP_MODE_DATA - rsp_payload = integer_to_bytearray(HDOpModes.MODE_POST.value) - rsp_payload += integer_to_bytearray(PostTreatmentStates.HD_POST_TREATMENT_DRAIN_RESERVOIRS_STATE.value) - self.message_queue_mutex.acquire() - # self._send_treatment_log() - self.message_queue_mutex.release() - self.demoSelection = 0 - self.demoCount = 0 + rsp_id, rsp_payload = sel.op_mode_data(self) elif self.demoSelection == 100: - rsp_id = MsgIds.MSG_ID_HD_OP_MODE_DATA - rsp_payload = integer_to_bytearray(HDOpModes.MODE_STAN.value) - rsp_payload += integer_to_bytearray(HDStandbyStates.STANDBY_WAIT_FOR_DISINFECT_STATE.value) - self.demoSelection = 0 # wait for user + rsp_id, rsp_payload = sel.wait_for_disinfect_state(self) # x94 MSG_ID_HD_TREATMENT_LOG_PERIODIC_DATA, # 1, 2, @@ -1286,10 +534,10 @@ venous_prs=self.venous_pressure_mmHg, blood_pump_occlusion=0, pressure_limit_state=0, - arterial_min_limt= PressureRanges.ARTERIAL_PRESSURE_LIMIT_MIN_MMHG, - arterial_max_limt= PressureRanges.ARTERIAL_PRESSURE_LIMIT_MAX_MMHG, - venous_min_limit= PressureRanges.VENOUS_PRESSURE_LIMIT_MIN_MMHG, - venous_max_limit= PressureRanges.VENOUS_PRESSURE_LIMIT_MAX_MMHG, + arterial_min_limt= pr.PressureRanges.ARTERIAL_PRESSURE_LIMIT_MIN_MMHG, + arterial_max_limt= pr.PressureRanges.ARTERIAL_PRESSURE_LIMIT_MAX_MMHG, + venous_min_limit= pr.PressureRanges.VENOUS_PRESSURE_LIMIT_MIN_MMHG, + venous_max_limit= pr.PressureRanges.VENOUS_PRESSURE_LIMIT_MAX_MMHG, arterial_long_filtered_pressure=self.arterial_pressure_mmHg, venous_long_filtered_pressure=self.venous_pressure_mmHg ) self.message_queue_mutex.release() Index: dialin/ui/pressure_ranges.py =================================================================== diff -u --- dialin/ui/pressure_ranges.py (revision 0) +++ dialin/ui/pressure_ranges.py (revision 1e9de03223eeeec426716c6157ce88ddd60e4d5a) @@ -0,0 +1,20 @@ +########################################################################### +# +# Copyright (c) 2020-2023 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 pressure_ranges.py +# @author (last) Mohammad Suleiman +# @date (original) 11--2023 +# +############################################################################ + +class PressureRanges: + PRESSURE_STEPS = 10 + + ARTERIAL_PRESSURE_LIMIT_MAX_MMHG = 100 + ARTERIAL_PRESSURE_LIMIT_MIN_MMHG = -300 + VENOUS_PRESSURE_LIMIT_MAX_MMHG = 400 + VENOUS_PRESSURE_LIMIT_MIN_MMHG = 20 \ No newline at end of file