Index: drydemo.pro =================================================================== diff -u -r61e26e538aae580369385eb78a966e74240d79c4 -r9edc9ba3995ca25a29bb74eeeae71f7d72965284 --- drydemo.pro (.../drydemo.pro) (revision 61e26e538aae580369385eb78a966e74240d79c4) +++ drydemo.pro (.../drydemo.pro) (revision 9edc9ba3995ca25a29bb74eeeae71f7d72965284) @@ -60,6 +60,7 @@ HEADERS += \ \ # Main \ # ---------- States ---------- + sources/drydemo/DryDemoDefines.h \ sources/drydemo/StateController.h \ sources/main.h \ sources/Threads.h \ Index: sources/MessageGlobals.h =================================================================== diff -u -r6d7f1800f7f56813c0824df509487f527a4026b2 -r9edc9ba3995ca25a29bb74eeeae71f7d72965284 --- sources/MessageGlobals.h (.../MessageGlobals.h) (revision 6d7f1800f7f56813c0824df509487f527a4026b2) +++ sources/MessageGlobals.h (.../MessageGlobals.h) (revision 9edc9ba3995ca25a29bb74eeeae71f7d72965284) @@ -130,24 +130,37 @@ enum Message_ID_Enum { ID_NONE = 0x0000, ID_TD_OP_MODE_DATA = 0x1200, + ID_DD_CONDUCTIVITY_DATA = 0x1F00, ID_TD_PRESSURE_DATA = 0x2400, ID_DD_GEN_DIALYSATE_MODE_DATA = 0x2F00, ID_TD_TREATMENT_TIME_DATA = 0x3B00, ID_TD_TREATMENT_STATE_DATA = 0x3C00, ID_TD_FLUID_BOLUS_DATA = 0x3D00, + ID_TD_ULTRAFILTRATION_DATA = 0x3E00, ID_UI_TREATMENT_PARAMS_TO_VALIDATE = 0x3F00, ID_TD_RESP_TREATMENT_PARAMS_TO_VALIDATE = 0x4000, + ID_UI_TREATMENT_UF_VOLUME_VALIDATE_RQST = 0x4100, + ID_TD_TREATMENT_UF_VOLUME_VALIDATE_RESP = 0x4200, ID_INITIATE_TREATMENT = 0x4500, ID_TD_RESP_INITIATE_TREATMENT = 0x4600, + ID_UI_UF_PAUSE_RESUME_RQST = 0x4700, + ID_TD_UF_PAUSE_RESUME_RESP = 0x4800, ID_TD_TREATMENT_SET_POINTS = 0x4F00, ID_UI_FLUID_BOLUS_RQST = 0x5F00, ID_TD_FLUID_BOLUS_RESP = 0x6000, + ID_UI_BLOOD_PRESSURE_RQST = 0x6300, + ID_TD_BLOOD_PRESSURE_READING_RESP = 0x6400, + ID_TD_BLOOD_PRESSURE_DATA = 0x6500, + ID_UI_BOLUS_VOLUME_CHANGE_RQST = 0x7400, + ID_TD_BOLUS_VOLUME_CHANGE_RESP = 0x7500, ID_UI_TREATMENT_SET_POINTS_CHANGE_RQST = 0x7A00, ID_TD_TREATMENT_SET_POINTS_CHANGE_RESP = 0x7B00, ID_UI_TREATMENT_SET_POINT_BLOOD_FLOW_CHANGE_RQST = 0x7C00, ID_TD_TREATMENT_SET_POINT_BLOOD_FLOW_CHANGE_RESP = 0x7D00, ID_UI_TREATMENT_SET_POINT_DIALYSATE_FLOW_CHANGE_RQST = 0x7E00, ID_TD_TREATMENT_SET_POINT_DIALYSATE_FLOW_CHANGE_RESP = 0x7F00, + ID_UI_TREATMENT_SET_POINT_DIALYSATE_TEMP_CHANGE_RQST = 0x8000, + ID_TD_TREATMENT_SET_POINT_DIALYSATE_TEMP_CHANGE_RESP = 0x8100, ID_UI_ADJUST_DISPOSABLES_CONFIRM_RQST = 0x9200, ID_TD_ADJUST_DISPOSSABLES_CONFIRM_RESP = 0x9300, ID_TD_BLOOD_PRIME_PROGRESS_DATA = 0x9700, Index: sources/drydemo/DryDemoDefines.h =================================================================== diff -u --- sources/drydemo/DryDemoDefines.h (revision 0) +++ sources/drydemo/DryDemoDefines.h (revision 9edc9ba3995ca25a29bb74eeeae71f7d72965284) @@ -0,0 +1,167 @@ +#pragma once + +// TODO REMOVE +// General defines +#define UI_MSG_BB_STATUS_INDEX 4 +#define UI_MSG_BB_PAYLOAD_ID 0x63 +#define SECONDS_PER_MINUTE 60 +#define MINUTES_PER_HOUR 60 +#define MILLISECONDS_PER_SECOND 1000 +#define MILLILITERS_PER_LITER 1000 +#define ACCEPT_VALUE 1 +#define REJECT_VALUE 0 +#define CONFIRM_CMD_ACCEPT_CLOSE 3 // TODo remove +#define PASS_RESULT 1 // TODO remove +#define DEVICE_ID 1234 + +// Timer event defines +#define DEFAULT_TIMEOUT_S 10 +#define QOBJECT_TIMER_TIMEOUT_MS 100 +#define PROGRESS_TIME_BC_INTERVAL_MS 1000 +#define PRORGESS_TIME_BC_QART_INT_MS 250 +#define NUM_OF_COUNTS_TIMER_BC_EMIT (PROGRESS_TIME_BC_INTERVAL_MS / QOBJECT_TIMER_TIMEOUT_MS) +#define NUN_OF_COUNTS_QART_BC_EMIT (PRORGESS_TIME_BC_QART_INT_MS / QOBJECT_TIMER_TIMEOUT_MS) +#define NUM_OF_COUNTS_TIMER_2_CONTROL (PROGRESS_TIME_BC_INTERVAL_MS / QOBJECT_TIMER_TIMEOUT_MS) +#define NUM_OF_COUNTS_TO_BC_MSG 3 // TODO remove + +// Treatment params +#define MIN_DIAL_RATE_MLPM 100 +#define MAX_DIAL_RATE_MLPM 600 +#define MIN_BLOOD_RATE_MLPM 100 +#define MAX_BLOOD_RATE_MLPM 500 +#define MIN_TX_TIME_MINS (1 * MINUTES_PER_HOUR) +#define MAX_TX_TIME_MINS (8 * MINUTES_PER_HOUR) +#define MIN_UF_VOL_L 0.0 +#define MAX_UF_VOL_L 8.0 +#define MAX_UF_VOL_ML (MAX_UF_VOL_L * MILLILITERS_PER_LITER) +#define MIN_UF_RATE_MLPM 0.0 +#define MAX_UF_RATE_MLPM (2000.0 / MINUTES_PER_HOUR) + +#define ACID_TYPES_1251_1_K 1.0 // TODO remove? +#define ACID_TYPES_CALCIUM 2.5 +#define ACID_TYPES_BICARB 33 +#define ACID_TYPES_SODIUM 137 + +#define DEF_TX_ELAPSED_TIME_S (2 * MINUTES_PER_HOUR) * SECONDS_PER_MINUTE +#define DEF_TX_PARAM_PRESCRIBED_DUR_MIN ((4 * MINUTES_PER_HOUR) + 30) +#define DEF_TX_PARAM_PRESCRIBED_DUR_S DEF_TX_PARAM_PRESCRIBED_DUR_MIN * SECONDS_PER_MINUTE +#define DEF_TX_PARAM_UF_VOLUME_L 2.0 +#define DEF_TX_PARAM_BLOOD_FLOW_RATE_MLPM 400 +#define DEF_TX_PARAM_DIAL_FLOW_RATE_MLPM 350 +#define DEF_TX_PARAM_SALINE_BOLUS_VOL_ML 100 +#define DEF_TX_PARAM_RINSEBACK_FLOW_RATE_MLPM 250 +#define DEF_TX_PARAM_ART_PRES_LIMIT_WIN_MMHG 120 +#define DEF_TX_PARAM_VEN_PRES_LIMIT_WIN_MMHG 100 +#define DEF_TX_PARAM_VEN_PRES_LIMIT_ASYM_WIN_MMHG 20 +#define DEF_TX_PARAM_DIA_TEMPERATURE_C 37.0 +#define DEF_TX_SYSTOLIC_PRESSURE 120 +#define DEF_TX_DIASTOLIC_PRESSURE 80 +#define DEF_TX_HEART_BEAT 100 + +// Arterial /Venous limits +#define MIN_ART_PRES_LIMIT_MMHG -300.0 +#define MAX_ART_PRES_LIMIT_MMHG 100.0 +#define MIN_VEN_PRES_LIMIT_MMHG 20.0 +#define MAX_VEN_PRES_LIMIT_MMHG 400.0 +#define MAX_TMP_PRES_LIMIT_MMHG 100.0 +#define MIN_TMP_PRES_LIMIT_MMHG -500.0 +#define OCCLUSION_STABLE_TIME_COUNT (10 * MILLISECONDS_PER_SECOND) / QOBJECT_TIMER_TIMEOUT_MS + +// Initiate treatment +#define INITIATE_TREATMENT 1 +#define ALLOW_DIALYSATE_DELIVER 1 + +// Treatment defines +#define BLOOD_PRIME_VOLUME_ML (106.6 + 40) +#define BLOOD_PRIME_START_FLOW_MLPM 250 +#define BLOOD_PRIME_FLOW_INTEGRATOR (1.0 / (SECONDS_PER_MINUTE * (MILLISECONDS_PER_SECOND / QOBJECT_TIMER_TIMEOUT_MS))) +#define BLOOD_PRIME_PAUSE_TIMEOUT_S (5 * SECONDS_PER_MINUTE) +#define BLOOD_PRIME_RESUME 1 +#define BLOOD_PRIME_PAUSE 2 +#define BLOOD_PRIME_RAMP_STATE 1 + +// Heparin substates +#define HEPARIN_OFF_SUBSTATE 0 +#define HEPARIN_PAUSED_SUBSTATE 2 +#define HEPARIN_DISPENSING_SUBSTATE 4 +#define HEPARIN_COMPLETED_SUBSTATE 5 + +// Ultrafiltration substates +#define UF_PAUSESD_STATE 0 +#define UF_RUNNING_STATE 1 + +// Rinseback defines +#define RINSEBACK_MIN_FLOW_RATE_MLPM 100 +#define RINSEBACK_MAX_RLOW_RATE_MLPM 300 +#define RINSEBACK_ADJ_FLOW_RATE_MLPM 25 +#define RINSEBACK_BACK_MAX_TIME_S (5 * SECONDS_PER_MINUTE) +#define RINSEBACK_END_TREATMENT_SIGNAL 999 +#define RINSEBACK_STOP_INIT_STATE 0 +#define RINSEBACK_RUN_STATE 1 +#define RINSEBACK_PAUSE_STATE 2 +#define RINSEBACK_STOP_STATE 3 + +// Fluid Bolus defines +#define FLUID_BOLUS_START_CMD 1 +#define ENABLE_BOLUS 1 + + +enum User_Command_ID { + CMD_NONE = -1, + CMD_STAND_BY = 0, + CMD_PRE_TX = 1, + CMD_BLOOD_PRIME = 2, + CMD_MAIN_TX = 3, + + CMD_END_TX = 11, + CMD_DISINFECTION = 12, + CMD_HIGH_PRIO_ALARM = 13, + CMD_MEDIUM_PRIO_ALARM = 14, + CMD_LOW_PRIO_ALARM = 15, + NUM_OF_USER_CMDS = 16, +}; + +enum Treatment_States { + TREAT_START_STATE = 0, + TREAT_BLOOD_PRIME_STATE = 1, + TREAT_DIALYSIS_STATE = 2, + TREAT_PAUSED_STATE = 3, + TREAT_RINSEBACK_STATE = 4, + TREAT_RECIRC_STATE = 5, + TREAT_END_STATE = 6, + TREAT_ISO_UF_STATE = 7, + TREAT_SALINE_BOLUS_STATE = 8, + TREAT_DIALYSIS_PAUSED_STATE = 9, +}; + +enum Fluid_Bolus_States { + FLUID_BOLUS_IDLE_STATE = 0, + FLUID_BOLUS_WAIT_FOR_PUMPS_STOP_STATE = 1, + FLUID_BOLUS_SALINE_IN_PROGRESS_STATE = 2, + FLUID_BOLUS_SUBSITUTE_IN_PROGRESS_STATE = 3, +}; + +enum Dialysis_States { + DIALYSIS_UF_STATE = 0, + DIALYSIS_UF_PAUSED_STATE = 1, + DIALYSIS_UF_FLUID_BOLUS_STATE = 2, +}; + +enum State_Status { + STATE_ON_ENTRY = 0, + STATE_ON_ACTION, + STATE_ON_EXIT, +}; + +enum Broadcast_Type { + BC_DELAYED = 0, + BC_IMMEDIATELY, +}; + +enum Reject_Reasons { + REQUEST_REJECT_REASON_NONE = 0, + REQUEST_REJECT_REASON_INVALID_TREATMENT_STATE = 4, + REQUEST_REJECT_REASON_UF_NOT_IN_PROGESS = 14, + REQUEST_REJECT_REASON_UF_NOT_PAUSED = 15, + REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE = 17, +}; Index: sources/drydemo/StateController.cpp =================================================================== diff -u -r6d7f1800f7f56813c0824df509487f527a4026b2 -r9edc9ba3995ca25a29bb74eeeae71f7d72965284 --- sources/drydemo/StateController.cpp (.../StateController.cpp) (revision 6d7f1800f7f56813c0824df509487f527a4026b2) +++ sources/drydemo/StateController.cpp (.../StateController.cpp) (revision 9edc9ba3995ca25a29bb74eeeae71f7d72965284) @@ -50,6 +50,10 @@ case ID_UI_TREATMENT_SET_POINT_BLOOD_FLOW_CHANGE_RQST: case ID_UI_TREATMENT_SET_POINTS_CHANGE_RQST: case ID_UI_TREATMENT_SET_POINT_DIALYSATE_FLOW_CHANGE_RQST: + case ID_UI_BOLUS_VOLUME_CHANGE_RQST: + case ID_UI_TREATMENT_SET_POINT_DIALYSATE_TEMP_CHANGE_RQST: + case ID_UI_UF_PAUSE_RESUME_RQST: + case ID_UI_TREATMENT_UF_VOLUME_VALIDATE_RQST: _treatmentRcvdMessages[receivedMsgID] = msg[1]; break; @@ -90,6 +94,15 @@ case ID_TD_TREATMENT_SET_POINTS_CHANGE_RESP: case ID_DD_GEN_DIALYSATE_MODE_DATA: case ID_TD_TREATMENT_SET_POINT_DIALYSATE_FLOW_CHANGE_RESP: + case ID_DD_CONDUCTIVITY_DATA: + case ID_TD_BOLUS_VOLUME_CHANGE_RESP: + case ID_UI_BLOOD_PRESSURE_RQST: + case ID_TD_BLOOD_PRESSURE_READING_RESP: + case ID_TD_BLOOD_PRESSURE_DATA: + case ID_TD_ULTRAFILTRATION_DATA: + case ID_TD_TREATMENT_SET_POINT_DIALYSATE_TEMP_CHANGE_RESP: + case ID_TD_UF_PAUSE_RESUME_RESP: + case ID_TD_TREATMENT_UF_VOLUME_VALIDATE_RESP: // Do nothing break; } @@ -347,17 +360,20 @@ static QList txStates; auto onEntry = [=](){ + // Start with UF state in dialysis + _treatmentStatus.dialysisSubState = DIALYSIS_UF_STATE; + _treatmentStatus.txState = TREAT_DIALYSIS_STATE; handleTDOpModeTransitionBroadcastData(MODE_TREA, 0, BC_IMMEDIATELY); - txStates = {TREAT_START_STATE, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + txStates = {TREAT_START_STATE, 0, _treatmentStatus.dialysisSubState, 0, 0, 0, 0, 0, 0, 0}; handleTreatmentStatesBroadcastData(txStates, BC_IMMEDIATELY); - txStates = {TREAT_DIALYSIS_STATE, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + txStates = {_treatmentStatus.txState, 0, _treatmentStatus.dialysisSubState, 0, 0, 0, 0, 0, 0, 0}; handleTreatmentStatesBroadcastData(txStates, BC_IMMEDIATELY); handleTreatmentSetpointsBroadcastData(_treatmentParams.bloodFlowRateMLPM, _treatmentParams.dialysateFlowRateMLPM, _treatmentParams.dialysateTemperatureC, BC_IMMEDIATELY); + handleDDConductivityBroadcastData(BC_IMMEDIATELY); handleTreatmentTimeProcessAndBroadcastData(BC_IMMEDIATELY); handleDDGenDialysateModeBroadcastData(BC_IMMEDIATELY); - // The default elapsed time is 2 hours becasue the default tx duration is 4 hours. If the prescribed is less than 2 hours, 0 the elapsed - if ((_treatmentParams.treatmentDurationMin * SECONDS_PER_MINUTE) < DEF_TX_ELAPSED_TIME_S){ _treatmentStatus.treatmentElapsedTimeMS = 0; } + initializeTreatmentTimeAndUltrafiltration(); status = STATE_ON_ACTION; qDebug() << "Tx on entry"; }; @@ -366,7 +382,7 @@ status = STATE_ON_ACTION; handleBackToStandbyEvent(status); handleTDOpModeTransitionBroadcastData(MODE_TREA, 0, BC_DELAYED); - txStates = {TREAT_DIALYSIS_STATE, 0, 0, 0, 0, 0, 0, 0, _treatmentStatus.fluidBolusState, 0}; + txStates = {_treatmentStatus.txState, 0, _treatmentStatus.dialysisSubState, 0, 0, 0, 0, 0, _treatmentStatus.fluidBolusState, 0}; handleTreatmentStatesBroadcastData(txStates, BC_DELAYED); handleTDPressureProcessAndBroadcastData(BC_DELAYED); handleFluidBolusRequestMessage(); @@ -378,10 +394,14 @@ handleTreatmentSetpointsBroadcastData(_treatmentParams.bloodFlowRateMLPM, _treatmentParams.dialysateFlowRateMLPM, _treatmentParams.dialysateTemperatureC, BC_DELAYED); handleDDGenDialysateModeBroadcastData(BC_DELAYED); + handleDDConductivityBroadcastData(BC_DELAYED); handleSetPointDialysateFlowChange(); + handleSetPointDialysateTemperatureChange(); + handleUltrafiltrationBroadcastData(BC_DELAYED); + handleUltrafiltrationPauseResume(); if ((_treatmentStatus.treatmentElapsedTimeMS / MILLISECONDS_PER_SECOND) >= (_treatmentParams.treatmentDurationMin * SECONDS_PER_MINUTE)) { _treatmentStatus.stateTransitionEvent = "T_Tx_2_TE"; - status = STATE_ON_EXIT; + status = STATE_ON_EXIT; } }; @@ -401,25 +421,24 @@ void StateController::onTreatmentEndStateChange(bool active) { static State_Status status = STATE_ON_ENTRY; + static QList txStates; auto onEntry = [=](){ + handleTDOpModeTransitionBroadcastData(MODE_TREA, 0, BC_IMMEDIATELY); + txStates = {TREAT_START_STATE, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + handleTreatmentStatesBroadcastData(txStates, BC_IMMEDIATELY); + txStates = {TREAT_END_STATE, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + handleTreatmentStatesBroadcastData(txStates, BC_IMMEDIATELY); status = STATE_ON_ACTION; - qDebug() << "Tx on entry"; + qDebug() << "Tx End on entry"; }; auto onAction = [=](){ status = STATE_ON_ACTION; - //handleBackToStandbyEvent(status); - //handleTDOpModeTransitionBroadcastData(MODE_TREA, 0, BC_DELAYED); - //txStates = {TREAT_DIALYSIS_STATE, 0, 0, 0, 0, 0, 0, 0, _treatmentStatus.fluidBolusState, 0}; - //handleTreatmentStatesBroadcastData(txStates, BC_DELAYED); - //handleTDPressureProcessAndBroadcastData(BC_DELAYED); - //handleFluidBolusRequestMessage(); - //if (_treatmentStatus.fluidBolusState == FLUID_BOLUS_SALINE_IN_PROGRESS_STATE){ handleFluidBolusFluidDelivery(_treatmentParams.bloodFlowRateMLPM); } - //handleFluidBolusBroadcastData(BC_DELAYED); - //handleTreatmentTimeProcessAndBroadcastData(BC_DELAYED); - //handleTreatmentPrescriptionEditRequestMessage(); - //handleSetPointBloodFlowChange(_treatmentParams.bloodFlowRateMLPM); + handleBackToStandbyEvent(status); + handleTDOpModeTransitionBroadcastData(MODE_TREA, 0, BC_DELAYED); + txStates = {TREAT_END_STATE, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + handleTreatmentStatesBroadcastData(txStates, BC_DELAYED); }; auto onExit = [=](){ @@ -589,17 +608,20 @@ _isSendListReady = true; } -void StateController::handleUIResponseMessage(const Message_ID_Enum msgID, const quint32 acceptReject) +void StateController::handleUIResponseMessage(const Message_ID_Enum msgID, const quint32 acceptReject, const QVariantList &rejectReasons) { QVariantList resp; resp.append(static_cast(msgID)); resp.append(Can_Id::eChlid_TD_UI); resp.append(acceptReject); - resp.append(0); - - // If the messages is fluid bolus, response exceptionally has another payload which is the target fluid blous - if (msgID == ID_TD_FLUID_BOLUS_RESP) { resp.append(_treatmentParams.fluidBlousVolumeML); } - + if (rejectReasons.isEmpty()) { + // If the default reject reasons is empty, it means there were no reject reasons or extra payloads so assume none + resp.append(static_cast(REQUEST_REJECT_REASON_NONE)); + qDebug() << "Empty" << rejectReasons; + } + else { + for (auto item: rejectReasons) { resp.append(item); } + } _isSendListReady = false; _sendMessages.append(resp); _isSendListReady = true; @@ -615,6 +637,7 @@ _treatmentStatus.accumFluidBolusDeliveredML = 0.0; _treatmentStatus.fluidBolusState = FLUID_BOLUS_IDLE_STATE; _treatmentStatus.txState = TREAT_START_STATE; + _treatmentStatus.ufVolDeliveredL = 0.0; } quint32 StateController::extractU32DataFromReceivedMessage(const Message_ID_Enum msgID, qint32 index) @@ -624,3 +647,12 @@ return u32Var.value; } + +float StateController::extractF32DataFromReceivedMessage(const Can::Message_ID_Enum msgID, qint32 index) +{ + Types::F32 f32Var; + GetValue(_treatmentRcvdMessages[msgID].toByteArray(), index, f32Var); + + return f32Var.value; +} + Index: sources/drydemo/StateController.h =================================================================== diff -u -r6d7f1800f7f56813c0824df509487f527a4026b2 -r9edc9ba3995ca25a29bb74eeeae71f7d72965284 --- sources/drydemo/StateController.h (.../StateController.h) (revision 6d7f1800f7f56813c0824df509487f527a4026b2) +++ sources/drydemo/StateController.h (.../StateController.h) (revision 9edc9ba3995ca25a29bb74eeeae71f7d72965284) @@ -5,9 +5,10 @@ #include #include +#include "DryDemoDefines.h" +#include "LeahiDryDemoXMLStates.h" #include "main.h" #include "MessageGlobals.h" -#include "LeahiDryDemoXMLStates.h" #define _StateController StateController::I() @@ -29,151 +30,7 @@ void timerEvent(QTimerEvent *) override; private: - // TODO REMOVE - // General defines - #define UI_MSG_BB_STATUS_INDEX 4 - #define UI_MSG_BB_PAYLOAD_ID 0x63 - #define SECONDS_PER_MINUTE 60 - #define MINUTES_PER_HOUR 60 - #define MILLISECONDS_PER_SECOND 1000 - #define MILLILITERS_PER_LITER 1000 - #define ACCEPT_VALUE 1 - #define REJECT_VALUE 0 - #define CONFIRM_CMD_ACCEPT_CLOSE 3 - #define PASS_RESULT 1 - #define DEVICE_ID 1234 - // Timer event defines - #define DEFAULT_TIMEOUT_S 10 - #define QOBJECT_TIMER_TIMEOUT_MS 100 - #define PROGRESS_TIME_BC_INTERVAL_MS 1000 - #define NUM_OF_COUNTS_TIMER_BC_EMIT (PROGRESS_TIME_BC_INTERVAL_MS / QOBJECT_TIMER_TIMEOUT_MS) - #define NUM_OF_COUNTS_TIMER_2_CONTROL (PROGRESS_TIME_BC_INTERVAL_MS / QOBJECT_TIMER_TIMEOUT_MS) - #define NUM_OF_COUNTS_TO_BC_MSG 3 // TODO remove - - // Treatment params - #define MIN_DIAL_RATE_MLPM 100 - #define MAX_DIAL_RATE_MLPM 600 - #define MIN_BLOOD_RATE_MLPM 100 - #define MAX_BLOOD_RATE_MLPM 500 - #define MIN_TX_TIME_MINS (1 * MINUTES_PER_HOUR) - #define MAX_TX_TIME_MINS (8 * MINUTES_PER_HOUR) - #define MIN_UF_VOL_L 0.0 - #define MAX_UF_VOL_L 8.0 - #define MAX_UF_VOL_ML (MAX_UF_VOL_L * MILLILITERS_PER_LITER) - #define MIN_UF_RATE_MLPM 0.0 - #define MAX_UF_RATE_MLPM (2000.0 / MINUTES_PER_HOUR) - - #define ACID_TYPES_1251_1_K 1.0 // TODO remove? - #define ACID_TYPES_CALCIUM 2.5 - #define ACID_TYPES_BICARB 33 - #define ACID_TYPES_SODIUM 137 - - #define DEF_TX_ELAPSED_TIME_S (2 * MINUTES_PER_HOUR) * SECONDS_PER_MINUTE - #define DEF_TX_PARAM_PRESCRIBED_DUR_MIN ((4 * MINUTES_PER_HOUR) + 30) - #define DEF_TX_PARAM_PRESCRIBED_DUR_S DEF_TX_PARAM_PRESCRIBED_DUR_MIN * SECONDS_PER_MINUTE - #define DEF_TX_PARAM_UF_VOLUME_L 2.0 - #define DEF_TX_PARAM_BLOOD_FLOW_RATE_MLPM 400 - #define DEF_TX_PARAM_DIAL_FLOW_RATE_MLPM 350 - #define DEF_TX_PARAM_SALINE_BOLUS_VOL_ML 100 - #define DEF_TX_PARAM_RINSEBACK_FLOW_RATE_MLPM 250 - #define DEF_TX_PARAM_ART_PRES_LIMIT_WIN_MMHG 120 - #define DEF_TX_PARAM_VEN_PRES_LIMIT_WIN_MMHG 100 - #define DEF_TX_PARAM_VEN_PRES_LIMIT_ASYM_WIN_MMHG 20 - #define DEF_TX_PARAM_DIA_TEMPERATURE_C 37.0 - - // Arterial /Venous limits - #define MIN_ART_PRES_LIMIT_MMHG -300.0 - #define MAX_ART_PRES_LIMIT_MMHG 100.0 - #define MIN_VEN_PRES_LIMIT_MMHG 20.0 - #define MAX_VEN_PRES_LIMIT_MMHG 400.0 - #define MAX_TMP_PRES_LIMIT_MMHG 100.0 - #define MIN_TMP_PRES_LIMIT_MMHG -500.0 - #define OCCLUSION_STABLE_TIME_COUNT (10 * MILLISECONDS_PER_SECOND) / QOBJECT_TIMER_TIMEOUT_MS - - // Initiate treatment - #define INITIATE_TREATMENT 1 - #define ALLOW_DIALYSATE_DELIVER 1 - - // Treatment defines - #define BLOOD_PRIME_VOLUME_ML (106.6 + 40) - #define BLOOD_PRIME_START_FLOW_MLPM 250 - #define BLOOD_PRIME_FLOW_INTEGRATOR (1.0 / (SECONDS_PER_MINUTE * (MILLISECONDS_PER_SECOND / QOBJECT_TIMER_TIMEOUT_MS))) - #define BLOOD_PRIME_PAUSE_TIMEOUT_S (5 * SECONDS_PER_MINUTE) - #define BLOOD_PRIME_RESUME 1 - #define BLOOD_PRIME_PAUSE 2 - #define BLOOD_PRIME_RAMP_STATE 1 - - // Heparin substates - #define HEPARIN_OFF_SUBSTATE 0 - #define HEPARIN_PAUSED_SUBSTATE 2 - #define HEPARIN_DISPENSING_SUBSTATE 4 - #define HEPARIN_COMPLETED_SUBSTATE 5 - - // Ultrafiltration substates - #define UF_PAUSESD_STATE 0 - #define UF_RUNNING_STATE 1 - - // Rinseback defines - #define RINSEBACK_MIN_FLOW_RATE_MLPM 100 - #define RINSEBACK_MAX_RLOW_RATE_MLPM 300 - #define RINSEBACK_ADJ_FLOW_RATE_MLPM 25 - #define RINSEBACK_BACK_MAX_TIME_S (5 * SECONDS_PER_MINUTE) - #define RINSEBACK_END_TREATMENT_SIGNAL 999 - #define RINSEBACK_STOP_INIT_STATE 0 - #define RINSEBACK_RUN_STATE 1 - #define RINSEBACK_PAUSE_STATE 2 - #define RINSEBACK_STOP_STATE 3 - - // Fluid Bolus defines - #define FLUID_BOLUS_START_CMD 1 - - enum Treatment_States { - TREAT_START_STATE = 0, - TREAT_BLOOD_PRIME_STATE = 1, - TREAT_DIALYSIS_STATE = 2, - TREAT_PAUSED_STATE = 3, - TREAT_RINSEBACK_STATE = 4, - TREAT_RECIRC_STATE = 5, - TREAT_END_STATE = 6, - TREAT_ISO_UF_STATE = 7, - TREAT_SALINE_BOLUS_STATE = 8, - TREAT_DIALYSIS_PAUSED_STATE = 9, - }; - - enum Fluid_Bolus_States { - FLUID_BOLUS_IDLE_STATE = 0, - FLUID_BOLUS_WAIT_FOR_PUMPS_STOP_STATE = 1, - FLUID_BOLUS_SALINE_IN_PROGRESS_STATE = 2, - FLUID_BOLUS_SUBSITUTE_IN_PROGRESS_STATE = 3, - }; - - enum User_Command_ID { - CMD_NONE = -1, - CMD_STAND_BY = 0, - CMD_PRE_TX = 1, - CMD_BLOOD_PRIME = 2, - CMD_MAIN_TX = 3, - - CMD_END_TX = 11, - CMD_DISINFECTION = 12, - CMD_HIGH_PRIO_ALARM = 13, - CMD_MEDIUM_PRIO_ALARM = 14, - CMD_LOW_PRIO_ALARM = 15, - NUM_OF_USER_CMDS = 16, - }; - - enum State_Status { - STATE_ON_ENTRY = 0, - STATE_ON_ACTION, - STATE_ON_EXIT, - }; - - enum Broadcast_Type { - BC_DELAYED = 0, - BC_IMMEDIATELY, - }; - struct Treatment_Status_Vars { bool hasTxParamsBeenInitialized; quint32 treatmentElapsedTimeMS; @@ -185,6 +42,9 @@ float totalFluidBolusDeliveredML; Fluid_Bolus_States fluidBolusState; Treatment_States txState; + Dialysis_States dialysisSubState; + float presUFRateMLPM; + float ufVolDeliveredL; }; struct Treatment_Params { @@ -224,7 +84,7 @@ Treatment_Status_Vars _treatmentStatus; bool _isBroadcastListReady; // TODO use a mutex? bool _isSendListReady; // Todo use a mutex? - bool _hasUserConfirmedToProceed; + bool _hasUserConfirmedToProceed; // TODO remove? drydemoXMLStates _dryDemo; // CAN function(s) @@ -241,10 +101,11 @@ // Helper methods void handleTDOpModeTransitionBroadcastData(const Can::TD_OP_MODE mode, const quint32 subMode, const Broadcast_Type BCType); void setTreatmentParametersFromUI(const QVariant &payload); // TODO move the implementation to pretx cpp - void handleUIResponseMessage(const Can::Message_ID_Enum msgID, const quint32 acceptReject); + void handleUIResponseMessage(const Can::Message_ID_Enum msgID, const quint32 acceptReject, const QVariantList &rejectReasons = {}); void resetDryDemoVariables(); void handleBackToStandbyEvent(State_Status &status); quint32 extractU32DataFromReceivedMessage(const Can::Message_ID_Enum msgID, qint32 index); + float extractF32DataFromReceivedMessage(const Can::Message_ID_Enum msgID, qint32 index); // Standby methods void handleInitiateTreatmentRequestMessage(State_Status &status); @@ -256,6 +117,7 @@ // Treatment methods void setTreatmentParametersToDefault(); + void initializeTreatmentTimeAndUltrafiltration(); void handleTreatmentSetpointsBroadcastData(const quint32 bloodFlowMLPM, const quint32 dialFlowMLPM, const float dialTempC, const Broadcast_Type BCType); void handleTreatmentStatesBroadcastData(const QList &txStates, const Broadcast_Type BCType); void handleFluidBolusRequestMessage(); @@ -267,6 +129,12 @@ void handleSetPointBloodFlowChange(quint32 &bloodFlowMLPM, bool &hasBloodFlowChanged); void handleDDGenDialysateModeBroadcastData(const Broadcast_Type BCType); void handleSetPointDialysateFlowChange(); + void handleDDConductivityBroadcastData(const Broadcast_Type BCType); + void handleTDBloodPressureBroadcastData(const Broadcast_Type BCType); + void handleUltrafiltrationBroadcastData(const Broadcast_Type BCType); + void handleSetPointDialysateTemperatureChange(); + void handleUltrafiltrationPauseResume(); + void handleUltrafiltrationVolumeChangeRequest(); // Treatment end methods Index: sources/drydemo/StateControllerTreatment.cpp =================================================================== diff -u -r6d7f1800f7f56813c0824df509487f527a4026b2 -r9edc9ba3995ca25a29bb74eeeae71f7d72965284 --- sources/drydemo/StateControllerTreatment.cpp (.../StateControllerTreatment.cpp) (revision 6d7f1800f7f56813c0824df509487f527a4026b2) +++ sources/drydemo/StateControllerTreatment.cpp (.../StateControllerTreatment.cpp) (revision 9edc9ba3995ca25a29bb74eeeae71f7d72965284) @@ -92,8 +92,25 @@ _treatmentParams.dialysateTemperatureC = DEF_TX_PARAM_DIA_TEMPERATURE_C; _treatmentParams.treatmentDurationMin = DEF_TX_PARAM_PRESCRIBED_DUR_MIN; _treatmentParams.fluidBlousVolumeML = DEF_TX_PARAM_SALINE_BOLUS_VOL_ML; + _treatmentParams.ufVolumeL = DEF_TX_PARAM_UF_VOLUME_L; } +void StateController::initializeTreatmentTimeAndUltrafiltration() +{ + // The default elapsed time is 2 hours becasue the default tx duration is 4 hours. If the prescribed is less than 2 hours, 0 the elapsed + if ((_treatmentParams.treatmentDurationMin * SECONDS_PER_MINUTE) < DEF_TX_ELAPSED_TIME_S){ _treatmentStatus.treatmentElapsedTimeMS = 0; } + _treatmentStatus.presUFRateMLPM = (_treatmentParams.ufVolumeL * MILLILITERS_PER_LITER) / (static_cast(_treatmentParams.treatmentDurationMin)); + + float presUFVolL = _treatmentParams.ufVolumeL; + float presUFRateLHR = presUFVolL / (static_cast(_treatmentParams.treatmentDurationMin) / static_cast(MINUTES_PER_HOUR)); + float UFVolLMS = presUFRateLHR / (static_cast(MINUTES_PER_HOUR * SECONDS_PER_MINUTE * MILLISECONDS_PER_SECOND)); + + _treatmentStatus.ufVolDeliveredL = UFVolLMS * _treatmentStatus.treatmentElapsedTimeMS; + + qDebug() << "UF Init" << presUFRateLHR << UFVolLMS << _treatmentStatus.ufVolDeliveredL; +} + + void StateController::handleTreatmentSetpointsBroadcastData(const quint32 bloodFlowMLPM, const quint32 dialFlowMLPM, const float dialTempC, const Broadcast_Type BCType) { @@ -114,15 +131,13 @@ { static quint32 broadcastCounter = 0; - if ((++broadcastCounter % NUM_OF_COUNTS_TIMER_BC_EMIT != 0) && (BCType == BC_DELAYED)) { return; } + if ((++broadcastCounter % NUN_OF_COUNTS_QART_BC_EMIT != 0) && (BCType == BC_DELAYED)) { return; } QVariantList msg; msg.append(static_cast(ID_TD_TREATMENT_STATE_DATA)); msg.append(Can_Id::eChlid_TD_Sync); - for (auto item: txStates) { - msg.append(item); - } + for (auto item: txStates) { msg.append(item);} _isBroadcastListReady = false; _broadcastMessages.append(msg); _isBroadcastListReady = true; @@ -139,14 +154,26 @@ if (fluidBolusCmd == FLUID_BOLUS_START_CMD){ _treatmentStatus.fluidBolusState = FLUID_BOLUS_SALINE_IN_PROGRESS_STATE; + _treatmentStatus.dialysisSubState = DIALYSIS_UF_FLUID_BOLUS_STATE; } else { _treatmentStatus.totalFluidBolusDeliveredML += _treatmentStatus.accumFluidBolusDeliveredML; } _treatmentRcvdMessages[ID_UI_FLUID_BOLUS_RQST].clear(); - handleUIResponseMessage(ID_TD_FLUID_BOLUS_RESP, ACCEPT_VALUE); + handleUIResponseMessage(ID_TD_FLUID_BOLUS_RESP, ACCEPT_VALUE, {static_cast(REQUEST_REJECT_REASON_NONE), + _treatmentParams.fluidBlousVolumeML}); } + + if (! _treatmentRcvdMessages[ID_UI_BOLUS_VOLUME_CHANGE_RQST].isNull()){ + + quint32 fluidBolusVolML = extractU32DataFromReceivedMessage(ID_UI_BOLUS_VOLUME_CHANGE_RQST, 0); + + // TODO Check the range of the requested bolus volume + _treatmentParams.fluidBlousVolumeML = fluidBolusVolML; + _treatmentRcvdMessages[ID_UI_BOLUS_VOLUME_CHANGE_RQST].clear(); + handleUIResponseMessage(ID_TD_BOLUS_VOLUME_CHANGE_RESP, ACCEPT_VALUE); + } } void StateController::handleFluidBolusFluidDelivery(const quint32 bloodFlowMLPM) @@ -159,13 +186,13 @@ if (deliveredFluidML >= _treatmentParams.fluidBlousVolumeML) { _treatmentStatus.fluidBolusState = FLUID_BOLUS_IDLE_STATE; + _treatmentStatus.accumFluidBolusDeliveredML = 0.0; _treatmentStatus.totalFluidBolusDeliveredML += _treatmentStatus.accumFluidBolusDeliveredML; } qDebug() << "Bolus" << deliveredFluidML << _treatmentStatus.accumFluidBolusDeliveredML << _treatmentStatus.totalFluidBolusDeliveredML; } - void StateController::handleFluidBolusBroadcastData(const Broadcast_Type BCType) { static quint32 broadcastCounter = 5; @@ -178,7 +205,7 @@ msg.append(_treatmentParams.fluidBlousVolumeML); msg.append(_treatmentStatus.accumFluidBolusDeliveredML); msg.append(_treatmentStatus.totalFluidBolusDeliveredML); - msg.append(0); + msg.append(ENABLE_BOLUS); _isBroadcastListReady = false; _broadcastMessages.append(msg); _isBroadcastListReady = true; @@ -324,15 +351,15 @@ void StateController::handleSetPointBloodFlowChange(quint32 &bloodFlowMLPM, bool &hasBloodFlowChanged) { - if (! _treatmentRcvdMessages[ID_UI_TREATMENT_SET_POINT_BLOOD_FLOW_CHANGE_RQST].isNull()){ - // TODO do we need to check the range - bloodFlowMLPM = extractU32DataFromReceivedMessage(ID_UI_TREATMENT_SET_POINT_BLOOD_FLOW_CHANGE_RQST, 0); - handleUIResponseMessage(ID_TD_TREATMENT_SET_POINT_BLOOD_FLOW_CHANGE_RESP, ACCEPT_VALUE); - hasBloodFlowChanged = true; - handleTreatmentSetpointsBroadcastData(bloodFlowMLPM, _treatmentParams.dialysateFlowRateMLPM, - _treatmentParams.dialysateTemperatureC, BC_IMMEDIATELY); - _treatmentRcvdMessages[ID_UI_TREATMENT_SET_POINT_BLOOD_FLOW_CHANGE_RQST].clear(); - } + if (_treatmentRcvdMessages[ID_UI_TREATMENT_SET_POINT_BLOOD_FLOW_CHANGE_RQST].isNull()) { return; } + + // TODO do we need to check the range + bloodFlowMLPM = extractU32DataFromReceivedMessage(ID_UI_TREATMENT_SET_POINT_BLOOD_FLOW_CHANGE_RQST, 0); + handleUIResponseMessage(ID_TD_TREATMENT_SET_POINT_BLOOD_FLOW_CHANGE_RESP, ACCEPT_VALUE); + hasBloodFlowChanged = true; + handleTreatmentSetpointsBroadcastData(bloodFlowMLPM, _treatmentParams.dialysateFlowRateMLPM, + _treatmentParams.dialysateTemperatureC, BC_IMMEDIATELY); + _treatmentRcvdMessages[ID_UI_TREATMENT_SET_POINT_BLOOD_FLOW_CHANGE_RQST].clear(); } void StateController::handleDDGenDialysateModeBroadcastData(const Broadcast_Type BCType) @@ -358,14 +385,112 @@ void StateController::handleSetPointDialysateFlowChange() { - if (! _treatmentRcvdMessages[ID_UI_TREATMENT_SET_POINT_DIALYSATE_FLOW_CHANGE_RQST].isNull()){ - // TODO do we need to check the range - _treatmentParams.dialysateFlowRateMLPM = extractU32DataFromReceivedMessage(ID_UI_TREATMENT_SET_POINT_DIALYSATE_FLOW_CHANGE_RQST, 0); - handleUIResponseMessage(ID_TD_TREATMENT_SET_POINT_BLOOD_FLOW_CHANGE_RESP, ACCEPT_VALUE); - handleTreatmentSetpointsBroadcastData(_treatmentParams.bloodFlowRateMLPM, _treatmentParams.dialysateFlowRateMLPM, - _treatmentParams.dialysateTemperatureC, BC_IMMEDIATELY); - _treatmentRcvdMessages[ID_TD_TREATMENT_SET_POINT_DIALYSATE_FLOW_CHANGE_RESP].clear(); + if (_treatmentRcvdMessages[ID_UI_TREATMENT_SET_POINT_DIALYSATE_FLOW_CHANGE_RQST].isNull()) { return; } + + // TODO do we need to check the range + _treatmentParams.dialysateFlowRateMLPM = extractU32DataFromReceivedMessage(ID_UI_TREATMENT_SET_POINT_DIALYSATE_FLOW_CHANGE_RQST, 0); + handleUIResponseMessage(ID_TD_TREATMENT_SET_POINT_BLOOD_FLOW_CHANGE_RESP, ACCEPT_VALUE); + handleTreatmentSetpointsBroadcastData(_treatmentParams.bloodFlowRateMLPM, _treatmentParams.dialysateFlowRateMLPM, + _treatmentParams.dialysateTemperatureC, BC_IMMEDIATELY); + _treatmentRcvdMessages[ID_UI_TREATMENT_SET_POINT_DIALYSATE_FLOW_CHANGE_RQST].clear(); +} + +void StateController::handleDDConductivityBroadcastData(const Broadcast_Type BCType) +{ + static quint32 broadcastCounter = 22; + + if ((++broadcastCounter % NUM_OF_COUNTS_TIMER_BC_EMIT != 0) && (BCType == BC_DELAYED)) { return; } + + float d27Cond = 250.63; + + QVariantList msg; + msg.append(static_cast(ID_DD_CONDUCTIVITY_DATA)); + msg.append(Can_Id::eChlid_DD_Sync); + msg.append(0.0); + msg.append(d27Cond); + msg.append(0.0); + msg.append(0.0); + msg.append(0.0); + _isBroadcastListReady = false; + _broadcastMessages.append(msg); + _isBroadcastListReady = true; +} + +void StateController::handleTDBloodPressureBroadcastData(const Broadcast_Type BCType) +{ + static quint32 broadcastCounter = 22; + + if ((++broadcastCounter % NUM_OF_COUNTS_TIMER_BC_EMIT != 0) && (BCType == BC_DELAYED)) { return; } + // TODO copmlete +} + +void StateController::handleUltrafiltrationBroadcastData(const Broadcast_Type BCType) +{ + static quint32 broadcastCounter = 31; + + if ((++broadcastCounter % NUM_OF_COUNTS_TIMER_BC_EMIT != 0) && (BCType == BC_DELAYED)) { return; } + + float presUFVolL = _treatmentParams.ufVolumeL; + float presUFRateLHR = presUFVolL / (static_cast(_treatmentParams.treatmentDurationMin) / static_cast(MINUTES_PER_HOUR)); + float targetUFRateLHR = (_treatmentStatus.presUFRateMLPM * MINUTES_PER_HOUR) / static_cast(MILLILITERS_PER_LITER); + float UFVolLMS = presUFRateLHR / (static_cast(MINUTES_PER_HOUR * SECONDS_PER_MINUTE * MILLISECONDS_PER_SECOND)); + + _treatmentStatus.ufVolDeliveredL += UFVolLMS * PROGRESS_TIME_BC_INTERVAL_MS; + + //qDebug() << "UF" << presUFRateLHR << targetUFRateLHR << UFVolLMS << _treatmentStatus.ufVolDeliveredL; + + QVariantList msg; + msg.append(static_cast(ID_TD_ULTRAFILTRATION_DATA)); + msg.append(Can_Id::eChlid_TD_Sync); + msg.append(presUFVolL); + msg.append(targetUFRateLHR); + msg.append(_treatmentStatus.ufVolDeliveredL); + msg.append(static_cast(_treatmentStatus.dialysisSubState)); + _isBroadcastListReady = false; + _broadcastMessages.append(msg); + _isBroadcastListReady = true; +} + +void StateController::handleSetPointDialysateTemperatureChange() +{ + if (_treatmentRcvdMessages[ID_UI_TREATMENT_SET_POINT_DIALYSATE_TEMP_CHANGE_RQST].isNull()){ return; } + + // TODO range check + _treatmentParams.dialysateTemperatureC = extractF32DataFromReceivedMessage(ID_UI_TREATMENT_SET_POINT_DIALYSATE_TEMP_CHANGE_RQST, 0); + handleUIResponseMessage(ID_TD_TREATMENT_SET_POINT_DIALYSATE_TEMP_CHANGE_RESP, ACCEPT_VALUE); + handleTreatmentSetpointsBroadcastData(_treatmentParams.bloodFlowRateMLPM, _treatmentParams.dialysateFlowRateMLPM, + _treatmentParams.dialysateTemperatureC, BC_IMMEDIATELY); + _treatmentRcvdMessages[ID_UI_TREATMENT_SET_POINT_DIALYSATE_TEMP_CHANGE_RQST].clear(); +} + +void StateController::handleUltrafiltrationPauseResume() +{ + if (_treatmentRcvdMessages[ID_UI_UF_PAUSE_RESUME_RQST].isNull()){ return; } + + quint32 cmd = extractU32DataFromReceivedMessage(ID_UI_UF_PAUSE_RESUME_RQST, 0); + QVariantList reason; + + if (_treatmentStatus.txState == TREAT_DIALYSIS_STATE) { + // Assume the default state is UF state + _treatmentStatus.dialysisSubState = DIALYSIS_UF_STATE; + _treatmentStatus.dialysisSubState = (cmd == 0 ? DIALYSIS_UF_PAUSED_STATE : _treatmentStatus.dialysisSubState); } + else if (_treatmentStatus.txState != TREAT_DIALYSIS_STATE) { + reason.append(static_cast(REQUEST_REJECT_REASON_INVALID_TREATMENT_STATE)); + } + else { + quint32 r = static_cast(REQUEST_REJECT_REASON_UF_NOT_PAUSED); + + r = (cmd == 0 ? static_cast(REQUEST_REJECT_REASON_UF_NOT_IN_PROGESS) : r); + reason.append(r); + } + handleUIResponseMessage(ID_TD_UF_PAUSE_RESUME_RESP, ACCEPT_VALUE, reason); + _treatmentRcvdMessages[ID_UI_UF_PAUSE_RESUME_RQST].clear(); } +void StateController::handleUltrafiltrationVolumeChangeRequest() +{ +} + +