#include #include #include #include "StateController.h" #include "ApplicationController.h" #include "types.h" StateController::StateController(QObject *parent) : QObject(parent) {} void StateController::init() { startTimer(QOBJECT_TIMER_TIMEOUT_MS); connect(&_ApplicationController, SIGNAL(didUnhandledMsgAppController(const QVariantList &)), this , SLOT(doStateControllerUnhandledMsgReceived(const QVariantList &))); // State machine methods _dryDemo.connectToState("Standby" , this, &StateController::onStandbyStateChange ); _dryDemo.connectToState("Pre_Tx" , this, &StateController::onPretreatmentStateChange ); _dryDemo.connectToState("Blood_Prime" , this, &StateController::onBloodPrimeStateChange ); _dryDemo.connectToState("Treatment" , this, &StateController::onTreatmentStateChange ); _dryDemo.connectToState("Treatment_Pause" , this, &StateController::onTreatmentPauseStateChange ); _dryDemo.connectToState("Treatment_Rinseback" , this, &StateController::onTreatmentRinsebackStateChange ); _dryDemo.connectToState("Treatment_Recirculate" , this, &StateController::onTreatmentRecriculateStateChange ); _dryDemo.connectToState("Treatment_End" , this, &StateController::onTreatmentEndStateChange ); // Transition to standby commands and events _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_RINSEBACK ] = {"T_SB_2_RB" , static_cast(MODE_TREA)}; _transitionEventsFromStandby[CMD_RICIRCULATE ] = {"T_SB_2_RC" , static_cast(MODE_TREA)}; _transitionEventsFromStandby[CMD_END_TX ] = {"T_SB_2_TE" , static_cast(MODE_TREA)}; // Alarms specs and properties _alarmTriggerSpecs[ALARM_ID_NO_ALARM ] = {ALARM_PRIORITY_NONE, ALARM_NO_ALARM_PROPERTIES}; _alarmTriggerSpecs[ALARM_ID_TD_TREATMENT_STOPPED_BY_USER ] = {ALARM_PRIORITY_HIGH, ALARM_STOP_TX_PROPERTIES}; //connect(&_dryDemo, &QScxmlStateMachine::runningChanged, this, &StateController::onBackToStanbyEvent); // TODO remove } void StateController::quit() { // TODo fill up } void StateController::doStateControllerUnhandledMsgReceived(const QVariantList &msg) { MessageID receivedMsgID = static_cast(msg[0].toUInt()); // TODO check the length before reading the index switch(receivedMsgID) { 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: 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: case ID_UI_ULTRAFILTRATION_CHANGE_CONFIRM_RQST: case ID_UI_DURATION_VALIDATE_RQST: case ID_UI_DURATION_CONFIRM_RQST: case ID_UI_ALARM_USER_ACTION_REQUEST: case ID_UI_RINSEBACK_CMD_RQST: _treatmentRcvdMessages[receivedMsgID] = msg[1]; break; //// These messages do not have a payload in from UI so a fake payload is added to be consumed //// and processed case ID_UI_ADJUST_DISPOSABLES_CONFIRM_RQST: case ID_UI_ADJUST_START_TREATMENT_RQST: _treatmentRcvdMessages[receivedMsgID] = 0; break; case ID_NONE: case ID_TD_OP_MODE_DATA: case ID_TD_TREATMENT_STATE_DATA: case ID_TD_RESP_INITIATE_TREATMENT: case ID_TD_ADJUST_DISPOSSABLES_CONFIRM_RESP: case ID_TD_RESP_TREATMENT_PARAMS_TO_VALIDATE: case ID_TD_BLOOD_PRIME_PROGRESS_DATA: case ID_TD_BLOOD_PRIME_CMD_RESP: case ID_TD_ADJUST_START_TREATMENT_RESP: 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: 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: case ID_TD_TREATMENT_PARAM_RANGES_DATA: case ID_TD_ULTRAFILTRATION_CHANGE_CONFIRM_RESP: case ID_TD_DURATION_VALIDATE_RESP: case ID_TD_DURATION_CONFIRM_RESP: case ID_ALARM_STATUS_DATA: case ID_ALARM_CLEARED: case ID_TD_RINSEBACK_CMD_RESP: case ID_TD_RINSEBACK_DATA: case ID_TD_UI_GENERIC_CONFIRMATION_REQUEST: // Do nothing break; } } void StateController::timerEvent(QTimerEvent *) { if (!_dryDemo.isRunning()){ _dryDemo.start(); } _dryDemo.submitEvent("TimeoutEvent"); if (_isBroadcastListReady){ sendMessages(true); } if (_isSendListReady){ sendMessages(false); } //if (! _treatmentRcvdMessages[ID_UI_CONFIRMATION_RESULT_RESP].isNull()){ // // Check for the user request message from the dry-deme menu // handleDryDemoMenuRequestMessage(); //} //qDebug() << "Active State" << _dryDemo.activeStateNames(); } // ---------------------- Private methods ------------------ // void StateController::sendMessages(bool isBroadcast) { QList msgList = _broadcastMessages; if (isBroadcast){ _broadcastMessages.clear(); } else{ msgList = _sendMessages; _sendMessages.clear(); } for (auto item: msgList){ emit _ApplicationController.didActionTransmit(item); } } // ----------- State transition methods ---------------- // void StateController::onStandbyStateChange(bool active) { static State_Status status = STATE_ON_ENTRY; auto onEntry = [=](){ handleTDOpModeTransitionBroadcastData(MODE_STAN, 0, BC_IMMEDIATELY); setTreatmentParametersToDefault(); resetDryDemoVariables(); // Clear all the alarms triggerAnAlarm(ALARM_ID_NO_ALARM); status = STATE_ON_ACTION; qDebug() << "Standby on entry"; }; auto onAction = [=](){ status = STATE_ON_ACTION; handleBackToStandbyEvent(status); handleInitiateTreatmentRequestMessage(status); if (_treatmentStatus.userCmd != CMD_NONE){ if ((_treatmentStatus.userCmd > CMD_STAND_BY) && (_treatmentStatus.userCmd <= CMD_DISINFECTION)) { _treatmentStatus.stateTransitionEvent = _transitionEventsFromStandby[_treatmentStatus.userCmd][0].toString(); TD_OP_MODE opMode = static_cast(_transitionEventsFromStandby[_treatmentStatus.userCmd][1].toUInt()); qDebug() << "Submit event" << _treatmentStatus.stateTransitionEvent << opMode; handleTDOpModeTransitionBroadcastData(opMode, 0, BC_IMMEDIATELY); _treatmentStatus.userCmd = CMD_NONE; 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); }; auto onExit = [=](){ qDebug() << "Standby 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; } } void StateController::onPretreatmentStateChange(bool active) { static State_Status status = STATE_ON_ENTRY; auto onEntry = [=](){ handleTDOpModeTransitionBroadcastData(MODE_PRET, 0, BC_IMMEDIATELY); status = STATE_ON_ACTION; qDebug() << "PreTx on entry"; }; 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); } if (! _treatmentRcvdMessages[ID_UI_TREATMENT_PARAMS_TO_VALIDATE].isNull()){ setTreatmentParametersFromUI(_treatmentRcvdMessages[ID_UI_TREATMENT_PARAMS_TO_VALIDATE]); _treatmentRcvdMessages[ID_UI_TREATMENT_PARAMS_TO_VALIDATE].clear(); } if (! _treatmentRcvdMessages[ID_UI_ADJUST_START_TREATMENT_RQST].isNull()){ _treatmentRcvdMessages[ID_UI_ADJUST_START_TREATMENT_RQST].clear(); handleUIResponseMessage(ID_TD_ADJUST_START_TREATMENT_RESP, ACCEPT_VALUE); status = STATE_ON_EXIT; _treatmentStatus.stateTransitionEvent = "T_Pretx_2_BP"; } }; auto onExit = [=](){ qDebug() << "PreTx 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; } } void StateController::onBloodPrimeStateChange(bool active) { static State_Status status = STATE_ON_ENTRY; static float accumBloodVolML = 0.0; static quint32 currBloodFlowMLPM = BLOOD_PRIME_START_FLOW_MLPM; static bool resume = true; 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; _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(); 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 == BLOOD_PRIME_RESUME ? true : false); pauseResumeState = (resumeStatus == BLOOD_PRIME_RESUME ? BLOOD_PRIME_RESUME : BLOOD_PRIME_PAUSE); // 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(); } 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, BC_IMMEDIATELY); if (accumBloodVolML > BLOOD_PRIME_VOLUME_ML) { _treatmentStatus.stateTransitionEvent = "T_BP_2_Tx"; status = STATE_ON_EXIT; // Send the final volume value prior to trnasiotining to treatment handleBloodPrimeBroadcastData(accumBloodVolML, 0, 0, BC_IMMEDIATELY); qDebug() << "VOL" << accumBloodVolML; } }; auto onExit = [=](){ //qDebug() << "Blood prime on 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; } } void StateController::onTreatmentStateChange(bool active) { static State_Status status = STATE_ON_ENTRY; static bool hasFlowChngeRequested = false; static QList txStates; if (_treatmentStatus.requestTreatmentReset) { status = STATE_ON_ENTRY; _treatmentStatus.requestTreatmentReset = false; } auto onEntry = [=](){ hasFlowChngeRequested = false; // 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, _treatmentStatus.dialysisSubState, 0, 0, 0, 0, 0, 0, 0}; handleTreatmentStatesBroadcastData(txStates, BC_IMMEDIATELY); 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); initializeTreatmentTimeAndUltrafiltration(); handleTreatmentSettingBroadcastData(BC_IMMEDIATELY); status = STATE_ON_ACTION; qDebug() << "Tx on entry"; }; auto onAction = [=](){ status = STATE_ON_ACTION; handleBackToStandbyEvent(status); handleTDOpModeTransitionBroadcastData(MODE_TREA, 0, BC_DELAYED); txStates = {_treatmentStatus.txState, 0, _treatmentStatus.dialysisSubState, 0, 0, 0, 0, 0, _treatmentStatus.fluidBolusState, 0}; handleTreatmentStatesBroadcastData(txStates, BC_DELAYED); // Fluid bolus functions handleFluidBolusRequestMessage(); if (_treatmentStatus.fluidBolusState == FLUID_BOLUS_SALINE_IN_PROGRESS_STATE){ handleFluidBolusFluidDelivery(_treatmentParams.bloodFlowRateMLPM); } handleFluidBolusBroadcastData(BC_DELAYED); // Broadcast functions handleTreatmentTimeProcessAndBroadcastData(BC_DELAYED); handleTreatmentPrescriptionEditRequestMessage(); handleSetPointBloodFlowChange(_treatmentParams.bloodFlowRateMLPM, hasFlowChngeRequested); handleTreatmentSetpointsBroadcastData(_treatmentParams.bloodFlowRateMLPM, _treatmentParams.dialysateFlowRateMLPM, _treatmentParams.dialysateTemperatureC, BC_DELAYED); handleDDGenDialysateModeBroadcastData(BC_DELAYED); handleDDConductivityBroadcastData(BC_DELAYED); handleSetPointDialysateFlowChange(); handleSetPointDialysateTemperatureChange(); handleTDPressureProcessAndBroadcastData(BC_DELAYED); // UF functions funcntios handleUltrafiltrationPauseResume(); handleUltrafiltrationVolumeChangeValidation(); handleUltrafiltrationVolumeChangeConfirm(); handleUltrafiltrationBroadcastData(BC_DELAYED); // Tx Time setting functions handleTreatmentSettingBroadcastData(BC_DELAYED); handleTreatmentTimeChangeValidation(); handleTreatmentTimeChangeConfirm(); if ((_treatmentStatus.treatmentElapsedTimeMS / MILLISECONDS_PER_SECOND) > (_treatmentParams.treatmentDurationMin * SECONDS_PER_MINUTE)) { _treatmentStatus.stateTransitionEvent = "T_Tx_2_TE"; status = STATE_ON_EXIT; } }; auto onExit = [=](){ qDebug() << "Tx in exit"; status = STATE_ON_ENTRY; if (_treatmentStatus.userCmd == CMD_END_TX) { _treatmentStatus.stateTransitionEvent = "T_Tx_2_TP"; status = STATE_ON_ACTION; _treatmentStatus.userCmd = CMD_NONE; } _dryDemo.submitEvent(_treatmentStatus.stateTransitionEvent); }; 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; } } void StateController::onTreatmentPauseStateChange(bool active) { static State_Status status = STATE_ON_ENTRY; static QList txStates; auto onEntry = [=](){ triggerAnAlarm(ALARM_ID_TD_TREATMENT_STOPPED_BY_USER); // Start with UF state in dialysis _treatmentStatus.dialysisSubState = DIALYSIS_UF_PAUSED_STATE; _treatmentStatus.txState = TREAT_PAUSED_STATE; handleTDOpModeTransitionBroadcastData(MODE_TREA, 0, BC_IMMEDIATELY); txStates = {TREAT_START_STATE, 0, _treatmentStatus.dialysisSubState, 0, 0, 0, 0, 0, 0, 0}; handleTreatmentStatesBroadcastData(txStates, BC_IMMEDIATELY); txStates = {_treatmentStatus.txState, 0, _treatmentStatus.dialysisSubState, 0, 0, 0, 0, 0, 0, 0}; handleTreatmentStatesBroadcastData(txStates, BC_IMMEDIATELY); status = STATE_ON_ACTION; qDebug() << "Tx pause on entry"; }; auto onAction = [=](){ status = STATE_ON_ACTION; handleBackToStandbyEvent(status); handleAlarmUserAction(status); handleTDOpModeTransitionBroadcastData(MODE_TREA, 0, BC_DELAYED); txStates = {_treatmentStatus.txState, 0, _treatmentStatus.dialysisSubState, 0, 0, 0, 0, 0, _treatmentStatus.fluidBolusState, 0}; handleTreatmentStatesBroadcastData(txStates, BC_DELAYED); }; auto onExit = [=](){ qDebug() << "Tx pasue 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; } } void StateController::onTreatmentRinsebackStateChange(bool active) { static State_Status status = STATE_ON_ENTRY; static QList txStates; auto onEntry = [=](){ // Start with UF state in dialysis _treatmentStatus.dialysisSubState = DIALYSIS_UF_PAUSED_STATE; _treatmentStatus.txState = TREAT_RINSEBACK_STATE; _treatmentStatus.rinsebackStates = RINSEBACK_STOP_INIT_STATE; handleTDOpModeTransitionBroadcastData(MODE_TREA, 0, BC_IMMEDIATELY); txStates = {TREAT_START_STATE, 0, _treatmentStatus.dialysisSubState, 0, 0, 0, 0, 0, 0, 0}; handleTreatmentStatesBroadcastData(txStates, BC_IMMEDIATELY); txStates = {_treatmentStatus.txState, 0, _treatmentStatus.dialysisSubState, 0, 0, _treatmentStatus.rinsebackStates, 0, 0, 0, 0}; initializeRinseback(); handleTreatmentStatesBroadcastData(txStates, BC_IMMEDIATELY); handleRinsebackBroadcastData(BC_IMMEDIATELY); status = STATE_ON_ACTION; qDebug() << "Tx rinseback on entry"; }; auto onAction = [=](){ status = STATE_ON_ACTION; handleBackToStandbyEvent(status); handleTDOpModeTransitionBroadcastData(MODE_TREA, 0, BC_DELAYED); txStates = {_treatmentStatus.txState, 0, _treatmentStatus.dialysisSubState, 0, 0, _treatmentStatus.rinsebackStates, 0, 0, 0, 0}; handleTreatmentStatesBroadcastData(txStates, BC_DELAYED); handleRinsebackRequestMessage(); handleRinsebackDelivery(); handleRinsebackBroadcastData(BC_DELAYED); handleTDPressureProcessAndBroadcastData(BC_DELAYED); }; auto onExit = [=](){ qDebug() << "Tx rinseback 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; } } void StateController::onTreatmentRecriculateStateChange(bool active) { static State_Status status = STATE_ON_ENTRY; 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, _treatmentStatus.dialysisSubState, 0, 0, 0, 0, 0, 0, 0}; handleTreatmentStatesBroadcastData(txStates, BC_IMMEDIATELY); txStates = {_treatmentStatus.txState, 0, _treatmentStatus.dialysisSubState, 0, 0, 0, 0, 0, 0, 0}; handleTreatmentStatesBroadcastData(txStates, BC_IMMEDIATELY); status = STATE_ON_ACTION; qDebug() << "Tx pause on entry"; }; auto onAction = [=](){ status = STATE_ON_ACTION; handleBackToStandbyEvent(status); handleTDOpModeTransitionBroadcastData(MODE_TREA, 0, BC_DELAYED); txStates = {_treatmentStatus.txState, 0, _treatmentStatus.dialysisSubState, 0, 0, 0, 0, 0, _treatmentStatus.fluidBolusState, 0}; handleTreatmentStatesBroadcastData(txStates, BC_DELAYED); }; auto onExit = [=](){ qDebug() << "Tx pasue 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; } } 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 End on entry"; }; auto onAction = [=](){ status = STATE_ON_ACTION; 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 = [=](){ 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::handleTDOpModeTransitionBroadcastData(const TD_OP_MODE mode, const quint32 subMode, const Broadcast_Type BCType) { static quint32 broadcastCounter = 0; if ((++broadcastCounter % NUM_OF_COUNTS_TIMER_BC_EMIT != 0) && (BCType == BC_DELAYED)) { return; } QVariantList msg; msg.append(static_cast(ID_TD_OP_MODE_DATA)); msg.append(Can_Id::eChlid_TD_Sync); msg.append(mode); msg.append(subMode); _isBroadcastListReady = false; _broadcastMessages.append(msg); _isBroadcastListReady = true; } void StateController::setTreatmentParametersFromUI(const QVariant &payload) { QVariantList resp; resp.append(static_cast(ID_TD_RESP_TREATMENT_PARAMS_TO_VALIDATE)); resp.append(Can_Id::eChlid_TD_UI); resp.append(ACCEPT_VALUE); qint32 index = 0; Types::U32 u32Var; Types::F32 f32Var; GetValue(payload.toByteArray(), index, u32Var); _treatmentParams.finalConfirmation = u32Var.value; resp.append(0); GetValue(payload.toByteArray(), index, u32Var); _treatmentParams.treatmentModality = u32Var.value; resp.append(0); GetValue(payload.toByteArray(), index, u32Var); _treatmentParams.hdfDilution = u32Var.value; resp.append(0); 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, u32Var); _treatmentParams.treatmentDurationMin = u32Var.value; resp.append(0); GetValue(payload.toByteArray(), index, u32Var); _treatmentParams.heparinDeliveryDurationMin = u32Var.value; resp.append(0); GetValue(payload.toByteArray(), index, u32Var); _treatmentParams.heparinType = u32Var.value; resp.append(0); GetValue(payload.toByteArray(), index, u32Var); _treatmentParams.dryBicarbCartSize = 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); GetValue(payload.toByteArray(), index, u32Var); _treatmentParams.dialyzerType = u32Var.value; resp.append(0); GetValue(payload.toByteArray(), index, u32Var); _treatmentParams.fluidBlousVolumeML = u32Var.value; resp.append(0); GetValue(payload.toByteArray(), index, u32Var); _treatmentParams.bloodPressureIntervalMin = u32Var.value; resp.append(0); GetValue(payload.toByteArray(), index, u32Var); _treatmentParams.rinsebackVolumeML = u32Var.value; resp.append(0); GetValue(payload.toByteArray(), index, u32Var); _treatmentParams.hepatitisBStatus = u32Var.value; resp.append(0); GetValue(payload.toByteArray(), index, u32Var); _treatmentParams.acidConcentrate = u32Var.value; resp.append(0); GetValue(payload.toByteArray(), index, f32Var); _treatmentParams.substitutionFluidVolumeL = f32Var.value; resp.append(0); GetValue(payload.toByteArray(), index, f32Var); _treatmentParams.heparinBolusVolumeML = f32Var.value; resp.append(0); GetValue(payload.toByteArray(), index, f32Var); _treatmentParams.heparinDeliveryRateMLHR = f32Var.value; resp.append(0); GetValue(payload.toByteArray(), index, f32Var); _treatmentParams.dialysateTemperatureC = f32Var.value; resp.append(0); GetValue(payload.toByteArray(), index, f32Var); _treatmentParams.acidKConcentrateConversionFactor = f32Var.value; resp.append(0); GetValue(payload.toByteArray(), index, f32Var); _treatmentParams.ufPreWeightKG = f32Var.value; resp.append(0); GetValue(payload.toByteArray(), index, f32Var); _treatmentParams.ufEstimatedTargetWeightKG = f32Var.value; resp.append(0); GetValue(payload.toByteArray(), index, f32Var); _treatmentParams.ufVolumeL = f32Var.value; resp.append(0); _treatmentStatus.hasTxParamsBeenInitialized = true; _isSendListReady = false; _sendMessages.append(resp); _isSendListReady = true; } quint32 StateController::extractU32DataFromReceivedMessage(const Message_ID_Enum msgID, qint32 index) { Types::U32 u32Var; GetValue(_treatmentRcvdMessages[msgID].toByteArray(), index, u32Var); 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; }