Index: LeahiDryDemoXMLStates.scxml =================================================================== diff -u -r61e26e538aae580369385eb78a966e74240d79c4 -r6d7f1800f7f56813c0824df509487f527a4026b2 --- LeahiDryDemoXMLStates.scxml (.../LeahiDryDemoXMLStates.scxml) (revision 61e26e538aae580369385eb78a966e74240d79c4) +++ LeahiDryDemoXMLStates.scxml (.../LeahiDryDemoXMLStates.scxml) (revision 6d7f1800f7f56813c0824df509487f527a4026b2) @@ -2,38 +2,46 @@ - + - + - + - + + + + - + - + - + - + + + + + + Index: sources/MessageGlobals.h =================================================================== diff -u -r61e26e538aae580369385eb78a966e74240d79c4 -r6d7f1800f7f56813c0824df509487f527a4026b2 --- sources/MessageGlobals.h (.../MessageGlobals.h) (revision 61e26e538aae580369385eb78a966e74240d79c4) +++ sources/MessageGlobals.h (.../MessageGlobals.h) (revision 6d7f1800f7f56813c0824df509487f527a4026b2) @@ -128,25 +128,36 @@ }; enum Message_ID_Enum { - ID_NONE = 0x0000, - ID_TD_OP_MODE_DATA = 0x1200, - ID_TD_TREATMENT_TIME_DATA = 0x3B00, - ID_TD_TREATMENT_STATE_DATA = 0x3C00, - ID_UI_TREATMENT_PARAMS_TO_VALIDATE = 0x3F00, - ID_TD_RESP_TREATMENT_PARAMS_TO_VALIDATE = 0x4000, - ID_INITIATE_TREATMENT = 0x4500, - ID_TD_RESP_INITIATE_TREATMENT = 0x4600, - ID_TD_TREATMENT_SET_POINTS = 0x4F00, - ID_UI_TREATMENT_SET_POINT_BLOOD_FLOW_CHANGE_RQST = 0x7C00, - ID_TD_TREATMENT_SET_POINT_BLOOD_FLOW_CHANGE_RESP = 0x7D00, - ID_UI_ADJUST_DISPOSABLES_CONFIRM_RQST = 0x9200, - ID_TD_ADJUST_DISPOSSABLES_CONFIRM_RESP = 0x9300, - ID_TD_BLOOD_PRIME_PROGRESS_DATA = 0x9700, - ID_UI_BLOOD_PRIME_CMD_RQST = 0x9800, - ID_TD_BLOOD_PRIME_CMD_RESP = 0x9900, - ID_UI_ADJUST_START_TREATMENT_RQST = 0xA100, - ID_TD_ADJUST_START_TREATMENT_RESP = 0xA200, - ID_UI_CONFIRMATION_RESULT_RESP = 0xB600, + ID_NONE = 0x0000, + ID_TD_OP_MODE_DATA = 0x1200, + 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_UI_TREATMENT_PARAMS_TO_VALIDATE = 0x3F00, + ID_TD_RESP_TREATMENT_PARAMS_TO_VALIDATE = 0x4000, + ID_INITIATE_TREATMENT = 0x4500, + ID_TD_RESP_INITIATE_TREATMENT = 0x4600, + ID_TD_TREATMENT_SET_POINTS = 0x4F00, + ID_UI_FLUID_BOLUS_RQST = 0x5F00, + ID_TD_FLUID_BOLUS_RESP = 0x6000, + 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_ADJUST_DISPOSABLES_CONFIRM_RQST = 0x9200, + ID_TD_ADJUST_DISPOSSABLES_CONFIRM_RESP = 0x9300, + ID_TD_BLOOD_PRIME_PROGRESS_DATA = 0x9700, + ID_UI_BLOOD_PRIME_CMD_RQST = 0x9800, + ID_TD_BLOOD_PRIME_CMD_RESP = 0x9900, + ID_UI_ADJUST_START_TREATMENT_RQST = 0xA100, + ID_TD_ADJUST_START_TREATMENT_RESP = 0xA200, + ID_UI_PRESSURE_LIMIT_WIDEN_RQST = 0xA400, + ID_TD_PRESSURE_LIMIT_WIDEN_RESP = 0xA500, + ID_UI_CONFIRMATION_RESULT_RESP = 0xB600, }; enum TD_OP_MODE { Index: sources/drydemo/StateController.cpp =================================================================== diff -u -r756496932decbaae7bb3c9f694afc0402eeb1349 -r6d7f1800f7f56813c0824df509487f527a4026b2 --- sources/drydemo/StateController.cpp (.../StateController.cpp) (revision 756496932decbaae7bb3c9f694afc0402eeb1349) +++ sources/drydemo/StateController.cpp (.../StateController.cpp) (revision 6d7f1800f7f56813c0824df509487f527a4026b2) @@ -19,12 +19,14 @@ _dryDemo.connectToState("Pre_Tx" , this, &StateController::onPretreatmentStateChange ); _dryDemo.connectToState("Blood_Prime" , this, &StateController::onBloodPrimeStateChange ); _dryDemo.connectToState("Treatment" , this, &StateController::onTreatmentStateChange ); + _dryDemo.connectToState("Treatment_End" , this, &StateController::onTreatmentEndStateChange ); - _transitionEventsFromStandby.clear(); + _transitionEventsFromStandby[CMD_STAND_BY ] = {"T_Back_2_SB" , static_cast(MODE_STAN)}; _transitionEventsFromStandby[CMD_PRE_TX ] = {"T_SB_2_Pretx", static_cast(MODE_PRET)}; _transitionEventsFromStandby[CMD_BLOOD_PRIME ] = {"T_SB_2_BP" , static_cast(MODE_TREA)}; _transitionEventsFromStandby[CMD_MAIN_TX ] = {"T_SB_2_Tx" , static_cast(MODE_TREA)}; + _transitionEventsFromStandby[CMD_END_TX ] = {"T_SB_2_TE" , static_cast(MODE_TREA)}; //connect(&_dryDemo, &QScxmlStateMachine::runningChanged, this, &StateController::onBackToStanbyEvent); // TODO remove } @@ -42,9 +44,12 @@ { case ID_INITIATE_TREATMENT: case ID_UI_TREATMENT_PARAMS_TO_VALIDATE: + case ID_UI_FLUID_BOLUS_RQST: case ID_UI_BLOOD_PRIME_CMD_RQST: case ID_UI_CONFIRMATION_RESULT_RESP: 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: _treatmentRcvdMessages[receivedMsgID] = msg[1]; break; @@ -77,6 +82,14 @@ case ID_TD_TREATMENT_SET_POINT_BLOOD_FLOW_CHANGE_RESP: case ID_TD_TREATMENT_SET_POINTS: case ID_TD_TREATMENT_TIME_DATA: + case ID_TD_FLUID_BOLUS_RESP: + case ID_TD_FLUID_BOLUS_DATA: + case ID_TD_PRESSURE_DATA: + case ID_UI_PRESSURE_LIMIT_WIDEN_RQST: + case ID_TD_PRESSURE_LIMIT_WIDEN_RESP: + 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: // Do nothing break; } @@ -149,12 +162,6 @@ } } -void StateController::onBackToStanbyEvent() -{ - // TODO remove - qDebug() << "Active State" << _dryDemo.activeStateNames(); -} - // ----------- State transition methods ---------------- // void StateController::onStandbyStateChange(bool active) { @@ -171,16 +178,9 @@ auto onAction = [=](){ status = STATE_ON_ACTION; + handleBackToStandbyEvent(status); + handleInitiateTreatmentRequestMessage(status); - if (! _treatmentRcvdMessages[ID_INITIATE_TREATMENT].isNull()){ - _treatmentRcvdMessages[ID_INITIATE_TREATMENT].clear(); - - _treatmentStatus.stateTransitionEvent = _transitionEventsFromStandby[CMD_PRE_TX][0].toString(); - - handleUIResponseMessage(ID_TD_RESP_INITIATE_TREATMENT, ACCEPT_VALUE); - status = STATE_ON_EXIT; - } - if (_treatmentStatus.userCmd != CMD_NONE){ if ((_treatmentStatus.userCmd > CMD_STAND_BY) && (_treatmentStatus.userCmd <= CMD_DISINFECTION)) { _treatmentStatus.stateTransitionEvent = _transitionEventsFromStandby[_treatmentStatus.userCmd][0].toString(); @@ -191,8 +191,8 @@ status = STATE_ON_EXIT; } } + // Keep broadcasting the standby state in case the UI and dry-demo got out of sync handleTDOpModeTransitionBroadcastData(MODE_STAN, 0, BC_DELAYED); - handleBackToStandbyEvent(status); }; auto onExit = [=](){ @@ -220,6 +220,9 @@ auto onAction = [=](){ status = STATE_ON_ACTION; + handleBackToStandbyEvent(status); + handleInitiateTreatmentRequestMessage(status); + if (! _treatmentRcvdMessages[ID_UI_ADJUST_DISPOSABLES_CONFIRM_RQST].isNull()){ _treatmentRcvdMessages[ID_UI_ADJUST_DISPOSABLES_CONFIRM_RQST].clear(); handleUIResponseMessage(ID_TD_ADJUST_DISPOSSABLES_CONFIRM_RESP, ACCEPT_VALUE); @@ -236,7 +239,6 @@ status = STATE_ON_EXIT; _treatmentStatus.stateTransitionEvent = "T_Pretx_2_BP"; } - handleBackToStandbyEvent(status); }; auto onExit = [=](){ @@ -258,60 +260,63 @@ static float accumBloodVolML = 0.0; static quint32 currBloodFlowMLPM = BLOOD_PRIME_START_FLOW_MLPM; static bool resume = true; - static quint32 bloodPrimeResume = 1; - static quint32 bloodPrimePause = 2; static float rampStepML = 0.0; static bool hasFlowChngeRequested = false; + static quint32 pauseResumeState = 0; + static QList txStates; auto onEntry = [=](){ handleTDOpModeTransitionBroadcastData(MODE_TREA, 0, BC_IMMEDIATELY); // Clear the blood prime data immediately to prevent residual accumulated volume from a previous run handleBloodPrimeBroadcastData(0.0, 0, 0, BC_IMMEDIATELY); - accumBloodVolML = 0.0; - currBloodFlowMLPM = BLOOD_PRIME_START_FLOW_MLPM; - resume = true; - hasFlowChngeRequested = false; - - quint32 bloodPrimeStateRamp = 1; - QList txStates = {TREAT_BLOOD_PRIME_STATE, bloodPrimeStateRamp, 0, 0, 0, 0, 0, 0, 0, 0}; + accumBloodVolML = 0.0; + currBloodFlowMLPM = BLOOD_PRIME_START_FLOW_MLPM; + resume = true; + hasFlowChngeRequested = false; + _treatmentStatus.txState = TREAT_BLOOD_PRIME_STATE; + txStates = {TREAT_BLOOD_PRIME_STATE, BLOOD_PRIME_RAMP_STATE, 0, 0, 0, 0, 0, 0, 0, 0}; handleTreatmentStatesBroadcastData(txStates, BC_IMMEDIATELY); - rampStepML = getBloodPrimeRampStepML(); - qDebug() << "Rmpa" << rampStepML; - status = STATE_ON_ACTION; qDebug() << "Blood prime on entry"; }; auto onAction = [=](){ status = STATE_ON_ACTION; + txStates = {TREAT_BLOOD_PRIME_STATE, pauseResumeState, 0, 0, 0, 0, 0, 0, _treatmentStatus.fluidBolusState, 0}; + handleTreatmentStatesBroadcastData(txStates, BC_DELAYED); + handleBackToStandbyEvent(status); + if (! _treatmentRcvdMessages[ID_UI_BLOOD_PRIME_CMD_RQST].isNull()){ handleUIResponseMessage(ID_TD_BLOOD_PRIME_CMD_RESP, ACCEPT_VALUE); quint32 resumeStatus = extractU32DataFromReceivedMessage(ID_UI_BLOOD_PRIME_CMD_RQST, 0); - resume = (resumeStatus == bloodPrimeResume ? true : false); - quint32 state = (resumeStatus == bloodPrimeResume ? bloodPrimeResume : bloodPrimePause); + resume = (resumeStatus == BLOOD_PRIME_RESUME ? true : false); + pauseResumeState = (resumeStatus == BLOOD_PRIME_RESUME ? BLOOD_PRIME_RESUME : BLOOD_PRIME_PAUSE); - QList txStates = {TREAT_BLOOD_PRIME_STATE, state, 0, 0, 0, 0, 0, 0, 0, 0}; + // Send the results immediately + txStates = {TREAT_BLOOD_PRIME_STATE, BLOOD_PRIME_PAUSE, 0, 0, 0, 0, 0, 0, 0, 0}; handleTreatmentStatesBroadcastData(txStates, BC_IMMEDIATELY); _treatmentRcvdMessages[ID_UI_BLOOD_PRIME_CMD_RQST].clear(); } - if (! _treatmentRcvdMessages[ID_UI_TREATMENT_SET_POINT_BLOOD_FLOW_CHANGE_RQST].isNull()){ - // TODO do we need to check the range - currBloodFlowMLPM = extractU32DataFromReceivedMessage(ID_UI_TREATMENT_SET_POINT_BLOOD_FLOW_CHANGE_RQST, 0); - handleUIResponseMessage(ID_TD_TREATMENT_SET_POINT_BLOOD_FLOW_CHANGE_RESP, ACCEPT_VALUE); - hasFlowChngeRequested = true; - qDebug() << "FLow" << currBloodFlowMLPM; - - _treatmentRcvdMessages[ID_UI_TREATMENT_SET_POINT_BLOOD_FLOW_CHANGE_RQST].clear(); + handleSetPointBloodFlowChange(currBloodFlowMLPM, hasFlowChngeRequested); + handleTDPressureProcessAndBroadcastData(BC_DELAYED); + handleFluidBolusRequestMessage(); + if (_treatmentStatus.fluidBolusState == FLUID_BOLUS_SALINE_IN_PROGRESS_STATE){ + handleFluidBolusFluidDelivery(currBloodFlowMLPM); + handleFluidBolusBroadcastData(BC_DELAYED); + // If fluid bolus is in progress, do not run the blood prime + // TODO remove the return like TREATMENT + return; } + handleFluidBolusBroadcastData(BC_DELAYED); handleBloodPrimeVolML(resume, rampStepML, hasFlowChngeRequested, currBloodFlowMLPM, accumBloodVolML); handleTreatmentSetpointsBroadcastData(currBloodFlowMLPM, _treatmentParams.dialysateFlowRateMLPM, - _treatmentParams.dialysateTemperatureC); + _treatmentParams.dialysateTemperatureC, BC_IMMEDIATELY); if (accumBloodVolML > BLOOD_PRIME_VOLUME_ML) { _treatmentStatus.stateTransitionEvent = "T_BP_2_Tx"; @@ -320,10 +325,6 @@ handleBloodPrimeBroadcastData(accumBloodVolML, 0, 0, BC_IMMEDIATELY); qDebug() << "VOL" << accumBloodVolML; } - - handleBackToStandbyEvent(status); - - //qDebug() << "Blood state" << status; }; auto onExit = [=](){ @@ -342,26 +343,46 @@ void StateController::onTreatmentStateChange(bool active) { static State_Status status = STATE_ON_ENTRY; + static bool hasFlowChngeRequested = false; + static QList txStates; - auto onEntry = [=](){ handleTDOpModeTransitionBroadcastData(MODE_TREA, 0, BC_IMMEDIATELY); - QList txStates = {TREAT_START_STATE, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + txStates = {TREAT_START_STATE, 0, 0, 0, 0, 0, 0, 0, 0, 0}; handleTreatmentStatesBroadcastData(txStates, BC_IMMEDIATELY); txStates = {TREAT_DIALYSIS_STATE, 0, 0, 0, 0, 0, 0, 0, 0, 0}; handleTreatmentStatesBroadcastData(txStates, BC_IMMEDIATELY); - + handleTreatmentSetpointsBroadcastData(_treatmentParams.bloodFlowRateMLPM, _treatmentParams.dialysateFlowRateMLPM, + _treatmentParams.dialysateTemperatureC, 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; } status = STATE_ON_ACTION; - qDebug() << "Tx on entry"; }; auto onAction = [=](){ status = STATE_ON_ACTION; + handleBackToStandbyEvent(status); handleTDOpModeTransitionBroadcastData(MODE_TREA, 0, BC_DELAYED); - QList txStates = {TREAT_DIALYSIS_STATE, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + txStates = {TREAT_DIALYSIS_STATE, 0, 0, 0, 0, 0, 0, 0, _treatmentStatus.fluidBolusState, 0}; handleTreatmentStatesBroadcastData(txStates, BC_DELAYED); - handleBackToStandbyEvent(status); + 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, hasFlowChngeRequested); + handleTreatmentSetpointsBroadcastData(_treatmentParams.bloodFlowRateMLPM, _treatmentParams.dialysateFlowRateMLPM, + _treatmentParams.dialysateTemperatureC, BC_DELAYED); + handleDDGenDialysateModeBroadcastData(BC_DELAYED); + handleSetPointDialysateFlowChange(); + if ((_treatmentStatus.treatmentElapsedTimeMS / MILLISECONDS_PER_SECOND) >= (_treatmentParams.treatmentDurationMin * SECONDS_PER_MINUTE)) { + _treatmentStatus.stateTransitionEvent = "T_Tx_2_TE"; + status = STATE_ON_EXIT; + } }; auto onExit = [=](){ @@ -377,8 +398,63 @@ } } +void StateController::onTreatmentEndStateChange(bool active) +{ + static State_Status status = STATE_ON_ENTRY; + + auto onEntry = [=](){ + status = STATE_ON_ACTION; + qDebug() << "Tx 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); + }; + + auto onExit = [=](){ + qDebug() << "Tx in exit"; + _dryDemo.submitEvent(_treatmentStatus.stateTransitionEvent); + status = STATE_ON_ENTRY; + }; + + switch (status) { // TODO macro it later + case STATE_ON_ENTRY : if (active) onEntry (); break; + case STATE_ON_ACTION: if (active) onAction(); break; + case STATE_ON_EXIT : if (active) onExit (); break; + } +} + // ************* Hepler functions ************* // +void StateController::handleInitiateTreatmentRequestMessage(State_Status &status) +{ + if (! _treatmentRcvdMessages[ID_INITIATE_TREATMENT].isNull()){ + + quint32 treatmentStatus = extractU32DataFromReceivedMessage(ID_INITIATE_TREATMENT, 0); + User_Command_ID cmdID = CMD_STAND_BY; + + // The initiate payload message payload. By default assume we are going back to standby + if (treatmentStatus == INITIATE_TREATMENT) { cmdID = CMD_PRE_TX; } + + _treatmentStatus.stateTransitionEvent = _transitionEventsFromStandby[cmdID][0].toString(); + _treatmentRcvdMessages[ID_INITIATE_TREATMENT].clear(); + handleUIResponseMessage(ID_TD_RESP_INITIATE_TREATMENT, ACCEPT_VALUE); + // Set the state to be on exit because the state has to exit + status = STATE_ON_EXIT; + } +} + void StateController::handleTDOpModeTransitionBroadcastData(const TD_OP_MODE mode, const quint32 subMode, const Broadcast_Type BCType) { static quint32 broadcastCounter = 0; @@ -513,13 +589,17 @@ _isSendListReady = true; } -void StateController::handleUIResponseMessage(const Can::Message_ID_Enum msgID, const quint32 acceptReject) +void StateController::handleUIResponseMessage(const Message_ID_Enum msgID, const quint32 acceptReject) { 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); } + _isSendListReady = false; _sendMessages.append(resp); _isSendListReady = true; @@ -528,9 +608,13 @@ void StateController::resetDryDemoVariables() { _treatmentStatus.hasTxParamsBeenInitialized = false; - _treatmentStatus.treatmentElapsedTimeS = DEF_TX_ELAPSED_TIME_S; - _treatmentStatus.remainingTreatmentTimeS = DEF_TX_PARAM_PRESCRIBED_DUR_S - _treatmentStatus.treatmentElapsedTimeS; + _treatmentStatus.treatmentElapsedTimeMS = DEF_TX_ELAPSED_TIME_S * MILLISECONDS_PER_SECOND; + _treatmentStatus.remainingTreatmentTimeS = DEF_TX_PARAM_PRESCRIBED_DUR_S - (_treatmentStatus.treatmentElapsedTimeMS / MILLISECONDS_PER_SECOND); _treatmentStatus.stateTransitionEvent = ""; + _treatmentStatus.totalFluidBolusDeliveredML = 0.0; + _treatmentStatus.accumFluidBolusDeliveredML = 0.0; + _treatmentStatus.fluidBolusState = FLUID_BOLUS_IDLE_STATE; + _treatmentStatus.txState = TREAT_START_STATE; } quint32 StateController::extractU32DataFromReceivedMessage(const Message_ID_Enum msgID, qint32 index) Index: sources/drydemo/StateController.h =================================================================== diff -u -r756496932decbaae7bb3c9f694afc0402eeb1349 -r6d7f1800f7f56813c0824df509487f527a4026b2 --- sources/drydemo/StateController.h (.../StateController.h) (revision 756496932decbaae7bb3c9f694afc0402eeb1349) +++ sources/drydemo/StateController.h (.../StateController.h) (revision 6d7f1800f7f56813c0824df509487f527a4026b2) @@ -29,7 +29,6 @@ void timerEvent(QTimerEvent *) override; private: - // TODO REMOVE // General defines #define UI_MSG_BB_STATUS_INDEX 4 @@ -40,7 +39,6 @@ #define MILLILITERS_PER_LITER 1000 #define ACCEPT_VALUE 1 #define REJECT_VALUE 0 - #define START_TX_FROM_MSG_38 1 #define CONFIRM_CMD_ACCEPT_CLOSE 3 #define PASS_RESULT 1 #define DEVICE_ID 1234 @@ -51,7 +49,7 @@ #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 + #define NUM_OF_COUNTS_TO_BC_MSG 3 // TODO remove // Treatment params #define MIN_DIAL_RATE_MLPM 100 @@ -66,7 +64,7 @@ #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 + #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 @@ -76,8 +74,8 @@ #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 600 - #define DEF_TX_PARAM_SALINE_BOLUS_VOL_ML 200 + #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 @@ -87,22 +85,25 @@ // 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 0.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 FLOW_INTEGRATOR (1.0 / (SECONDS_PER_MINUTE * (MILLISECONDS_PER_SECOND / QOBJECT_TIMER_TIMEOUT_MS))) - #define MAX_DIALYSATE_VOLUME_ML 150000 + #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 - // Treatment substates - #define BLOOD_RPIME_SUB_STATE 1 - #define DIALYSIS_SUB_STATE 2 - #define RINSEBACK_SUBSTATE 4 - #define TX_END_SUB_STATE 6 // Heparin substates #define HEPARIN_OFF_SUBSTATE 0 #define HEPARIN_PAUSED_SUBSTATE 2 @@ -124,15 +125,9 @@ #define RINSEBACK_PAUSE_STATE 2 #define RINSEBACK_STOP_STATE 3 - // Saline Bolus defines - #define SALINE_BOLUS_IDLE_STATE 0 - #define SALINE_BOLUS_IN_PROG_STATE 2 - #define SALINE_BOLUS_MAX_DELIVERED 3 + // Fluid Bolus defines + #define FLUID_BOLUS_START_CMD 1 - #define SALINE_BOLUS_START_CMD 1 - #define SALINE_BOLUS_MAX_VOL_ML 800 - #define SALINE_BOLUS_TARGET_FLOW_MLPM 250 - enum Treatment_States { TREAT_START_STATE = 0, TREAT_BLOOD_PRIME_STATE = 1, @@ -146,6 +141,13 @@ 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, @@ -174,11 +176,15 @@ struct Treatment_Status_Vars { bool hasTxParamsBeenInitialized; - quint32 treatmentElapsedTimeS; + quint32 treatmentElapsedTimeMS; quint32 remainingTreatmentTimeS; quint32 prescribedTreatmentTimeS; User_Command_ID userCmd; QString stateTransitionEvent; + float accumFluidBolusDeliveredML; + float totalFluidBolusDeliveredML; + Fluid_Bolus_States fluidBolusState; + Treatment_States txState; }; struct Treatment_Params { @@ -226,28 +232,42 @@ void handleDryDemoMenuRequestMessage(); // State handlers - void onBackToStanbyEvent(); // TODO remove - void onStandbyStateChange(bool active); void onPretreatmentStateChange(bool active); void onBloodPrimeStateChange(bool active); void onTreatmentStateChange(bool active); + void onTreatmentEndStateChange(bool active); - // Helper functions + // 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 resetDryDemoVariables(); void handleBackToStandbyEvent(State_Status &status); quint32 extractU32DataFromReceivedMessage(const Can::Message_ID_Enum msgID, qint32 index); + // Standby methods + void handleInitiateTreatmentRequestMessage(State_Status &status); + // Blood prime methods float getBloodPrimeRampStepML(); void handleBloodPrimeBroadcastData(const float accumulatedVolML, const quint32 primeTimeOutS, const quint32 pauseCountDownS, const Broadcast_Type BCType); - void handleBloodPrimeVolML(const bool resume, const float rampStepML, const bool hasFlowChanged, quint32 &currBlodFlowMLPM, float &accumBloodVolML); + void handleBloodPrimeVolML(const bool resume, const float rampStepML, const bool hasFlowChanged, quint32 &currBloodFlowMLPM, float &accumBloodVolML); // Treatment methods void setTreatmentParametersToDefault(); - void handleTreatmentSetpointsBroadcastData(const quint32 bloodFlowMLPM, const quint32 dialFlowMLPM, const float dialTempC); + 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(); + void handleFluidBolusFluidDelivery(const quint32 bloodFlowMLPM); + void handleFluidBolusBroadcastData(const Broadcast_Type BCType); + void handleTDPressureProcessAndBroadcastData(const Broadcast_Type BCType); + void handleTreatmentTimeProcessAndBroadcastData(const Broadcast_Type BCType); + void handleTreatmentPrescriptionEditRequestMessage(); + void handleSetPointBloodFlowChange(quint32 &bloodFlowMLPM, bool &hasBloodFlowChanged); + void handleDDGenDialysateModeBroadcastData(const Broadcast_Type BCType); + void handleSetPointDialysateFlowChange(); + + // Treatment end methods + }; Index: sources/drydemo/StateControllerTreatment.cpp =================================================================== diff -u -r756496932decbaae7bb3c9f694afc0402eeb1349 -r6d7f1800f7f56813c0824df509487f527a4026b2 --- sources/drydemo/StateControllerTreatment.cpp (.../StateControllerTreatment.cpp) (revision 756496932decbaae7bb3c9f694afc0402eeb1349) +++ sources/drydemo/StateControllerTreatment.cpp (.../StateControllerTreatment.cpp) (revision 6d7f1800f7f56813c0824df509487f527a4026b2) @@ -1,4 +1,6 @@ +#include + #include "StateController.h" #include "ApplicationController.h" #include "types.h" @@ -52,7 +54,7 @@ return; } - accumBloodVolML += (currBloodFlowMLPM * FLOW_INTEGRATOR); + accumBloodVolML += (currBloodFlowMLPM * BLOOD_PRIME_FLOW_INTEGRATOR); if (++controlCounter % NUM_OF_COUNTS_TIMER_2_CONTROL != 0) { return; } @@ -89,13 +91,15 @@ _treatmentParams.treatmentDurationMin = DEF_TX_PARAM_PRESCRIBED_DUR_MIN; _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; } -void StateController::handleTreatmentSetpointsBroadcastData(const quint32 bloodFlowMLPM, const quint32 dialFlowMLPM, const float dialTempC) +void StateController::handleTreatmentSetpointsBroadcastData(const quint32 bloodFlowMLPM, const quint32 dialFlowMLPM, const float dialTempC, + const Broadcast_Type BCType) { - static quint32 broadcastCounter = 0; + static quint32 broadcastCounter = 3; - if (++broadcastCounter % NUM_OF_COUNTS_TIMER_BC_EMIT != 0) { return; } + if ((++broadcastCounter % NUM_OF_COUNTS_TIMER_BC_EMIT != 0) && (BCType == BC_DELAYED)) { return; } QVariantList msg; msg.append(static_cast(ID_TD_TREATMENT_SET_POINTS)); @@ -122,5 +126,246 @@ _isBroadcastListReady = false; _broadcastMessages.append(msg); _isBroadcastListReady = true; +} +void StateController::handleFluidBolusRequestMessage() +{ + if (! _treatmentRcvdMessages[ID_UI_FLUID_BOLUS_RQST].isNull()){ + + quint32 fluidBolusCmd = extractU32DataFromReceivedMessage(ID_UI_FLUID_BOLUS_RQST, 0); + + // Assume the fluid bolus is not in progress + _treatmentStatus.fluidBolusState = FLUID_BOLUS_IDLE_STATE; + + if (fluidBolusCmd == FLUID_BOLUS_START_CMD){ + _treatmentStatus.fluidBolusState = FLUID_BOLUS_SALINE_IN_PROGRESS_STATE; + } + else { + _treatmentStatus.totalFluidBolusDeliveredML += _treatmentStatus.accumFluidBolusDeliveredML; + } + + _treatmentRcvdMessages[ID_UI_FLUID_BOLUS_RQST].clear(); + handleUIResponseMessage(ID_TD_FLUID_BOLUS_RESP, ACCEPT_VALUE); + } } + +void StateController::handleFluidBolusFluidDelivery(const quint32 bloodFlowMLPM) +{ + float timeSinceLastTimeMin = static_cast(QOBJECT_TIMER_TIMEOUT_MS) / static_cast(MILLISECONDS_PER_SECOND * SECONDS_PER_MINUTE); + + _treatmentStatus.accumFluidBolusDeliveredML += static_cast(bloodFlowMLPM) * timeSinceLastTimeMin; + + float deliveredFluidML = qAbs(_treatmentStatus.totalFluidBolusDeliveredML - _treatmentStatus.accumFluidBolusDeliveredML); + + if (deliveredFluidML >= _treatmentParams.fluidBlousVolumeML) { + _treatmentStatus.fluidBolusState = FLUID_BOLUS_IDLE_STATE; + _treatmentStatus.totalFluidBolusDeliveredML += _treatmentStatus.accumFluidBolusDeliveredML; + } + + qDebug() << "Bolus" << deliveredFluidML << _treatmentStatus.accumFluidBolusDeliveredML << _treatmentStatus.totalFluidBolusDeliveredML; +} + + +void StateController::handleFluidBolusBroadcastData(const Broadcast_Type BCType) +{ + static quint32 broadcastCounter = 5; + + if ((++broadcastCounter % NUM_OF_COUNTS_TIMER_BC_EMIT != 0) && (BCType == BC_DELAYED)) { return; } + + QVariantList msg; + msg.append(static_cast(ID_TD_FLUID_BOLUS_DATA)); + msg.append(Can_Id::eChlid_TD_Sync); + msg.append(_treatmentParams.fluidBlousVolumeML); + msg.append(_treatmentStatus.accumFluidBolusDeliveredML); + msg.append(_treatmentStatus.totalFluidBolusDeliveredML); + msg.append(0); + _isBroadcastListReady = false; + _broadcastMessages.append(msg); + _isBroadcastListReady = true; +} + +void StateController::handleTDPressureProcessAndBroadcastData(const Broadcast_Type BCType) +{ + static quint32 broadcastCounter = 10; + + if (! _treatmentRcvdMessages[ID_UI_PRESSURE_LIMIT_WIDEN_RQST].isNull()){ + _treatmentRcvdMessages[ID_UI_PRESSURE_LIMIT_WIDEN_RQST].clear(); + // TODo address the increase per request + handleUIResponseMessage(ID_TD_PRESSURE_LIMIT_WIDEN_RESP, ACCEPT_VALUE); + } + + // TODO update the pressures + float h2ArtPresMMHG = 12.2; + float h14VenPresMMHG = 80.1; + quint32 presLimitState = 1; + qint32 h2ArtMinLimitMMHG = MIN_ART_PRES_LIMIT_MMHG; + qint32 h2ArtMaxLimitMMHG = MAX_ART_PRES_LIMIT_MMHG; + qint32 h14VenMinLimitMMGH = MIN_VEN_PRES_LIMIT_MMHG; + qint32 h14VenMaxLimitMMHG = MAX_VEN_PRES_LIMIT_MMHG; + float h2ArtLongFilterPresMMHG = -23.0; + float h14VenLongFilterPresMMHG = 67.5; + float tmpPresMMHG = 45.03; + float tmpLongFilter = 45.5; + float tmpMinLimitMMHG = MIN_TMP_PRES_LIMIT_MMHG; + float tmpMaxLimitMMHG = MAX_TMP_PRES_LIMIT_MMHG; + float h23BaroPresPSI = 14.2l; + + if ((++broadcastCounter % NUM_OF_COUNTS_TIMER_BC_EMIT != 0) && (BCType == BC_DELAYED)) { return; } + + QVariantList msg; + msg.append(static_cast(ID_TD_PRESSURE_DATA)); + msg.append(Can_Id::eChlid_TD_Sync); + msg.append(h2ArtPresMMHG); + msg.append(h14VenPresMMHG); + msg.append(presLimitState); + msg.append(h2ArtMinLimitMMHG); + msg.append(h2ArtMaxLimitMMHG); + msg.append(h14VenMinLimitMMGH); + msg.append(h14VenMaxLimitMMHG); + msg.append(h2ArtLongFilterPresMMHG); + msg.append(h14VenLongFilterPresMMHG); + msg.append(tmpPresMMHG); + msg.append(tmpLongFilter); + msg.append(tmpMinLimitMMHG); + msg.append(tmpMaxLimitMMHG); + msg.append(h23BaroPresPSI); + _isBroadcastListReady = false; + _broadcastMessages.append(msg); + _isBroadcastListReady = true; +} + +void StateController::handleTreatmentTimeProcessAndBroadcastData(const Broadcast_Type BCType) +{ + static quint32 broadcastCounter = 12; + + if (_treatmentStatus.fluidBolusState == FLUID_BOLUS_IDLE_STATE) { + _treatmentStatus.treatmentElapsedTimeMS += QOBJECT_TIMER_TIMEOUT_MS; + } + + if ((++broadcastCounter % NUM_OF_COUNTS_TIMER_BC_EMIT != 0) && (BCType == BC_DELAYED)) { return; } + + quint32 prescribedTimeS = _treatmentParams.treatmentDurationMin * SECONDS_PER_MINUTE; + quint32 elapsedTimeS = _treatmentStatus.treatmentElapsedTimeMS / MILLISECONDS_PER_SECOND; + quint32 remainingTimeS = prescribedTimeS - elapsedTimeS; + + //qDebug() << "Times" << prescribedTimeS << elapsedTimeS << remainingTimeS; + + QVariantList msg; + msg.append(static_cast(ID_TD_TREATMENT_TIME_DATA)); + msg.append(Can_Id::eChlid_TD_Sync); + msg.append(prescribedTimeS); + msg.append(elapsedTimeS); + msg.append(remainingTimeS); + _isBroadcastListReady = false; + _broadcastMessages.append(msg); + _isBroadcastListReady = true; +} + +void StateController::handleTreatmentPrescriptionEditRequestMessage() +{ + if (! _treatmentRcvdMessages[ID_UI_TREATMENT_SET_POINTS_CHANGE_RQST].isNull()){ + + // TODO range check the parameters + QVariantList resp; + resp.append(static_cast(ID_TD_TREATMENT_SET_POINTS_CHANGE_RESP)); + resp.append(Can_Id::eChlid_TD_UI); + resp.append(ACCEPT_VALUE); + + QVariant payload = _treatmentRcvdMessages[ID_UI_TREATMENT_SET_POINTS_CHANGE_RQST]; + qint32 index = 0; + Types::U32 u32Var; + Types::F32 f32Var; + + GetValue(payload.toByteArray(), index, u32Var); + _treatmentParams.bloodFlowRateMLPM = u32Var.value; + resp.append(0); + + GetValue(payload.toByteArray(), index, u32Var); + _treatmentParams.dialysateFlowRateMLPM = u32Var.value; + resp.append(0); + + GetValue(payload.toByteArray(), index, f32Var); + _treatmentParams.dialysateTemperatureC = f32Var.value; + resp.append(0); + + GetValue(payload.toByteArray(), index, u32Var); + _treatmentParams.acidConcentrate = u32Var.value; + resp.append(0); + + GetValue(payload.toByteArray(), index, f32Var); + _treatmentParams.acidKConcentrateConversionFactor = f32Var.value; + resp.append(0); + + GetValue(payload.toByteArray(), index, u32Var); + _treatmentParams.bicarbobateMEQL = u32Var.value; + resp.append(0); + + GetValue(payload.toByteArray(), index, u32Var); + _treatmentParams.treatmentModality = u32Var.value; + resp.append(0); + + GetValue(payload.toByteArray(), index, u32Var); + _treatmentParams.hepatitisBStatus = u32Var.value; + resp.append(0); + + GetValue(payload.toByteArray(), index, u32Var); + _treatmentParams.sodiumMEQL = u32Var.value; + resp.append(0); + + GetValue(payload.toByteArray(), index, u32Var); + _treatmentParams.bicarbobateMEQL = u32Var.value; + resp.append(0); + _isSendListReady = false; + _sendMessages.append(resp); + _isSendListReady = true; + _treatmentRcvdMessages[ID_UI_TREATMENT_SET_POINTS_CHANGE_RQST].clear(); + } +} + +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(); + } +} + +void StateController::handleDDGenDialysateModeBroadcastData(const Broadcast_Type BCType) +{ + static quint32 broadcastCounter = 15; + + if ((++broadcastCounter % NUM_OF_COUNTS_TIMER_BC_EMIT != 0) && (BCType == BC_DELAYED)) { return; } + + quint32 dummyData = 1; + float dummyFloat = 150.2; + + QVariantList msg; + msg.append(static_cast(ID_DD_GEN_DIALYSATE_MODE_DATA)); + msg.append(Can_Id::eChlid_DD_Sync); + msg.append(dummyData); + msg.append(dummyData); + msg.append(ALLOW_DIALYSATE_DELIVER); + msg.append(dummyFloat); + _isBroadcastListReady = false; + _broadcastMessages.append(msg); + _isBroadcastListReady = true; +} + +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(); + } +} + +