Index: sources/MessageGlobals.h =================================================================== diff -u -r6e0ddbfa4863bb12a64dfde5baeada941acadaf8 -r75ca4bd322b1b11b7feb113086645979c95533a3 --- sources/MessageGlobals.h (.../MessageGlobals.h) (revision 6e0ddbfa4863bb12a64dfde5baeada941acadaf8) +++ sources/MessageGlobals.h (.../MessageGlobals.h) (revision 75ca4bd322b1b11b7feb113086645979c95533a3) @@ -138,6 +138,10 @@ ID_HD_PRIMING_TIME_BC = 0x4300, ID_UI_SET_UF_VOLUME_RQST = 0x4F00, ID_HD_SET_UF_VOLUME_RESP = 0x5000, + ID_UI_RINSEBACK_CMD_RQST = 0x5200, + ID_HD_RINSEBACK_CMD_RESP = 0x5300, + ID_HD_RINSEBACK_DATA_BC = 0x5600, + ID_UI_TX_END_RQST = 0x5700, ID_HD_BLOOD_PRIME_BC = 0x5900, ID_PRE_TX_STATES_BC = 0x5C00, ID_SAMPLE_WATER_RESULT = 0x5F00, Index: sources/StateController.cpp =================================================================== diff -u -r646712b99c608c9bc67b555497d5a666a0db1fea -r75ca4bd322b1b11b7feb113086645979c95533a3 --- sources/StateController.cpp (.../StateController.cpp) (revision 646712b99c608c9bc67b555497d5a666a0db1fea) +++ sources/StateController.cpp (.../StateController.cpp) (revision 75ca4bd322b1b11b7feb113086645979c95533a3) @@ -65,6 +65,14 @@ _hasUserConfirmedToProceed = true; break; + case ID_UI_RINSEBACK_CMD_RQST: + _treatmentRcvdMessages[receivedMsgID] = msg[1]; + break; + + case ID_UI_TX_END_RQST: + _hasUserConfirmedToProceed = true; + break; + case ID_SAMPLE_WATER_RESULT: _treatmentRcvdMessages[receivedMsgID] = msg[1]; break; @@ -117,6 +125,8 @@ case ID_HD_PATINET_CONNECTION_CONF_RESP: case ID_USER_TX_TIME_CHANGES_RESP: case ID_HD_BLOOD_PRIME_BC: + case ID_HD_RINSEBACK_CMD_RESP: + case ID_HD_RINSEBACK_DATA_BC: // Do nothing break; } @@ -138,18 +148,10 @@ // ---------------------- Private methods ------------------ // void StateController::resetVariables() { - _index = 0; - _broadcastMsgCount = 0; - _timerBroadcastCount = 0; - _hasUserConfirmedToProceed = false; - _currentCounterValue = COUNTER_VAR_DEFAULT_VALUE; - _prescribedTreatmentTimeS = PRESC_TIME_DEFAULT_VALUE; - _isBroadcastListReady = false; _isSendListReady = false; _treatmentVars.broadcastIntervalCount = 0; - _treatmentVars.broadcastIntervalCount = 0; _broadcastMessages.clear(); _sendMessages.clear(); @@ -322,13 +324,13 @@ _isBroadcastListReady = true; } -void StateController::prepareBloodFlowBroadcastData() +void StateController::prepareBloodFlowBroadcastData(quint32 flowMLPM) { QVariantList msg; msg.append(static_cast(ID_HD_BLOOD_FLOW_DATA_BC)); msg.append(Can_Id::eChlid_HD_Sync); - msg.append(_treatmentParams.bloodFlowRateMLPM); - msg.append(_treatmentParams.bloodFlowRateMLPM - 0.1); + msg.append(flowMLPM); + msg.append(flowMLPM - 0.1); msg.append(0.0); msg.append(0.0); msg.append(0.0); msg.append(0.0); msg.append(0.0); msg.append(0); msg.append(_treatmentParams.bloodFlowRateMLPM); msg.append(0); @@ -450,6 +452,24 @@ _isBroadcastListReady = true; } +void StateController::prepareRinsebackBroadcastData(const QList &volsML, const QList &payload) +{ + QVariantList msg; + msg.append(static_cast(ID_HD_RINSEBACK_DATA_BC)); + msg.append(Can_Id::eChlid_HD_Sync); + + for (auto item: volsML) { + msg.append(item); + } + + for (auto item: payload) { + msg.append(item); + } + _isBroadcastListReady = false; + _broadcastMessages.append(msg); + _isBroadcastListReady = true; +} + void StateController::handleTreatmentTimeChangeRequest(const QVariant &payload) { quint32 accept = REJECT_VALUE; @@ -594,7 +614,6 @@ } QVariantList msg; - msg.clear(); msg.append(static_cast(ID_HD_SET_UF_VOLUME_RESP)); msg.append(Can_Id::eChlid_HD_UI); msg.append(accept); @@ -605,6 +624,41 @@ _isSendListReady = true; } +void StateController::handleRinsebackSubstate(const QVariant &payload, quint32 &rbState) +{ + qint32 cmdIndex = 0; + Types::U32 param; + GetValue(payload.toByteArray(), cmdIndex, param); + + switch (param.value) + { + case RINSEBACK_START: + rbState = 1; + break; + + case RINSEBACK_END_TX: + rbState = 999; + break; + + case RINSEBACK_SALINE_BOLUS: + break; + + case RINSEBACK_BACK: + rbState--; + break; + } + + QVariantList msg; + msg.append(static_cast(ID_HD_RINSEBACK_CMD_RESP)); + msg.append(Can_Id::eChlid_HD_UI); + msg.append(ACCEPT_VALUE); + msg.append(0); + _isSendListReady = false; + _sendMessages.append(msg); + _isSendListReady = true; + +} + // ----------- State transition methods ---------------- // void StateController::onIdleStateChange(bool active) { @@ -639,12 +693,12 @@ qint32 cmd = handleMsgBBPayload(_treatmentRcvdMessages[ID_UI_CONFIRM_RESP]); User_Command_ID cmdIDEnum = static_cast(cmd); _treatmentRcvdMessages[ID_UI_CONFIRM_RESP].clear(); - + // TODO SEND MESSAGE 0XBA BACK TO UI if ((cmdIDEnum > CMD_STAND_BY) && (cmdIDEnum < NUM_OF_USER_CMDS)) { qDebug() << "Submit event" << _transitionEventsFromIdle[cmdIDEnum]; _dryDemo.submitEvent(_transitionEventsFromIdle[cmdIDEnum]); isMsgBBRequested = true; - status = STATE_ON_ENTRY; + status = STATE_ON_EXIT; } qDebug() << "Idle in action" << cmdIDEnum; @@ -658,13 +712,15 @@ if (param.value == START_TX_FROM_MSG_38) { _dryDemo.submitEvent(_transitionEventsFromIdle[CMD_TX_PARAMS]); + status = STATE_ON_EXIT; qDebug() << "Idle starting Tx"; } _treatmentRcvdMessages[ID_UI_RQST_TX].clear(); } }; auto inExit = [=](){ + qDebug() << "Idle in exit"; status = STATE_ON_ENTRY; }; @@ -804,7 +860,6 @@ auto inAction = [=]() { if (_hasUserConfirmedToProceed) { - qDebug() << " State " << state; if (state < 4) { // TODO #define for this state++; QList preTxStates({1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}); @@ -1121,10 +1176,11 @@ resetVariables(); prepareHDModeTransitionBroadcastData(MODE_TREA, 0); - QList txStates({1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}); + QList txStates({BLOOD_RPIME_SUB_STATE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}); prepareStatesBroadcastData(ID_HD_TX_STATES_BC, txStates); - // Get the default treatment params in case the user did not start from the treatment params + // Get the default treatment params in case the user did not start from + // the treatment params QVariant emptyVariantList; setTreatmentParams(false, emptyVariantList); @@ -1161,7 +1217,7 @@ auto inAction = [=](){ _treatmentVars.broadcastIntervalCount++; - accumBloodVolML += (DEF_TX_PARAM_BLOOD_FLOW_RATE_MLPM * BLOOD_FLOW_INTEGRATOR); + accumBloodVolML += (DEF_TX_PARAM_BLOOD_FLOW_RATE_MLPM * FLOW_INTEGRATOR); if (_treatmentVars.broadcastIntervalCount % NUM_OF_COUNTS_TIMER_BC_EMIT == 0) { prepareBloodPrimeBroadcastData(accumBloodVolML); @@ -1219,13 +1275,13 @@ _treatmentVars.refUFVolumeML += (timeSinceLastCallMS / SECONDS_PER_MINUTE) * _treatmentVars.prescribedUFRate; _treatmentVars.measUFVolumeML = _treatmentVars.refUFVolumeML; - //qDebug() << "UF Va;ue" << QTime::currentTime() << _treatmentVars.refUFVolumeML << _treatmentVars.prescribedUFRate; + //qDebug() << "UF Value" << QTime::currentTime() << _treatmentVars.refUFVolumeML << _treatmentVars.prescribedUFRate; if (_treatmentVars.broadcastIntervalCount % NUM_OF_COUNTS_TIMER_BC_EMIT == 0) { - QList txStates({2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}); + QList txStates({DIALYSIS_SUB_STATE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}); prepareStatesBroadcastData(ID_HD_TX_STATES_BC, txStates); prepareOcclusionBroadcastData(); prepareTreatmentTimeBroadcastData(); - prepareBloodFlowBroadcastData(); + prepareBloodFlowBroadcastData(_treatmentParams.bloodFlowRateMLPM); prepareDialysateFlowBroadcastData(); prepareDialysateOutFlowBroadcastData(); prepareTreatmentParamsRangesBroadcastData(); @@ -1262,10 +1318,110 @@ void StateController::onEndTreatmentStateChange(bool active) { - if (active) { - qDebug() << "Treatment end active"; - //QVariantList msg = _dryDemoCmds[_dryDemoCurrentCmd][_index].mid(RESP_MSG_START_INDEX); - //emit _ApplicationController.didActionTransmit(msg); + static State_Status status = STATE_ON_ENTRY; + static quint32 txSubState = DIALYSIS_SUB_STATE; + static quint32 rbSubState = 0; + // The default rinseback volume is 300 mL but the demo should be done in 10 seconds so it is recalculated here + static float rbTargetVolML = 0.0; + static float rbAcuumVolML = 0.0; + + auto inEntry = [=](){ + // Call the treatment params first in case the use just started from the end treatment + // but we need rinseback flow rate in mL/min that comes from the treatment params + QVariant empty; + setTreatmentParams(false, empty); + // In order to jump to end treatment page, first the UI needs to be on another + // treatment page, so on entry we first land on the dialysis page then we transition + // to end treatment. + txSubState = DIALYSIS_SUB_STATE; + rbSubState = 0; + rbAcuumVolML = 0.0; + rbTargetVolML = (_treatmentParams.rinsebackFlowRateMLPM * DEFAULT_TIMEOUT_S) / SECONDS_PER_MINUTE; + prepareHDModeTransitionBroadcastData(MODE_TREA, 0); + QList txStates({txSubState, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}); + prepareStatesBroadcastData(ID_HD_TX_STATES_BC, txStates); + + txSubState = TX_END_SUB_STATE; + txStates[0] = txSubState; + txStates[4] = rbSubState; + prepareStatesBroadcastData(ID_HD_TX_STATES_BC, txStates); + + qDebug() << "End treatment on entry"; + + _treatmentVars.broadcastIntervalCount = 0; + _hasUserConfirmedToProceed = false; + status = STATE_ON_ACTION; + }; + + auto inAction = [=](){ + _treatmentVars.broadcastIntervalCount++; + + QList txStates({0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}); + QList rinsebackVolsML({rbTargetVolML, rbAcuumVolML}); + QList rinsebackBC({_treatmentParams.rinsebackFlowRateMLPM, + DEFAULT_TIMEOUT_S, DEFAULT_TIMEOUT_S, 0}); + + if (_hasUserConfirmedToProceed) { + // Switching to the rinseback send the screen change quickly + txSubState = RINSEBACK_SUBSTATE; + txStates[0] = txSubState; + txStates[4] = rbSubState; + prepareStatesBroadcastData(ID_HD_TX_STATES_BC, txStates); + _hasUserConfirmedToProceed = false; + } + + if (!_treatmentRcvdMessages[ID_UI_RINSEBACK_CMD_RQST].isNull()) { + qDebug() << "Msg 52" << rbSubState; + handleRinsebackSubstate(_treatmentRcvdMessages[ID_UI_RINSEBACK_CMD_RQST], rbSubState); + qDebug() << "Msg 52 after" << rbSubState; + if (rbSubState != 999) { + txStates[0] = txSubState; + txStates[4] = rbSubState; + qDebug() << "Tx substates" << txStates; + prepareStatesBroadcastData(ID_HD_TX_STATES_BC, txStates); + prepareRinsebackBroadcastData(rinsebackVolsML, rinsebackBC); + } + else { + // Done with end treatment go back to standby as the dry demo currently does not have + // post treatment + qDebug() << "Done with end tx"; + status = STATE_ON_ENTRY; + _dryDemo.submitEvent("Transition_back_2_idle"); + } + _treatmentRcvdMessages[ID_UI_RINSEBACK_CMD_RQST].clear(); + } + + if (rbSubState == 1) { + rbAcuumVolML += _treatmentParams.rinsebackFlowRateMLPM * FLOW_INTEGRATOR; + } + + if (rbAcuumVolML >= rbTargetVolML) { + rbSubState = 3; + txStates[0] = txSubState; + txStates[4] = rbSubState; + prepareStatesBroadcastData(ID_HD_TX_STATES_BC, txStates); + } + + if (!_treatmentRcvdMessages[ID_UI_CONFIRM_RESP].isNull()) { + status = STATE_ON_ENTRY; + _dryDemo.submitEvent("Transition_back_2_idle"); + } + + if (_treatmentVars.broadcastIntervalCount % NUM_OF_COUNTS_TIMER_BC_EMIT == 0) { + prepareStatesBroadcastData(ID_HD_TX_STATES_BC, txStates); + prepareRinsebackBroadcastData(rinsebackVolsML, rinsebackBC); + } + }; + + auto inExit = [=](){ + qDebug() << "End treatment on exit"; + status = STATE_ON_ENTRY; + }; + + switch (status) { // TODO macro it later + case STATE_ON_ENTRY : if (active) inEntry (); break; + case STATE_ON_ACTION: if (active) inAction(); break; + case STATE_ON_EXIT : if (active) inExit (); break; } } @@ -1282,7 +1438,6 @@ }; auto inAction = [=](){ - if (!_treatmentRcvdMessages[ID_UI_CONFIRM_RESP].isNull()) { status = STATE_ON_ENTRY; _dryDemo.submitEvent("Transition_back_2_idle"); Index: sources/StateController.h =================================================================== diff -u -r646712b99c608c9bc67b555497d5a666a0db1fea -r75ca4bd322b1b11b7feb113086645979c95533a3 --- sources/StateController.h (.../StateController.h) (revision 646712b99c608c9bc67b555497d5a666a0db1fea) +++ sources/StateController.h (.../StateController.h) (revision 75ca4bd322b1b11b7feb113086645979c95533a3) @@ -31,8 +31,6 @@ // General defines #define UI_MSG_BB_STATUS_INDEX 4 #define UI_MSG_BB_PAYLOAD_ID 0x63 - #define COUNTER_VAR_DEFAULT_VALUE -1 // TODO remove - #define PRESC_TIME_DEFAULT_VALUE -1 // TODO remove #define SECONDS_PER_MINUTE 60 #define MINUTES_PER_HOUR 60 #define MILLISECONDS_PER_SECOND 1000 @@ -41,16 +39,8 @@ #define REJECT_VALUE 0 #define START_TX_FROM_MSG_38 1 - // Pre treatment defines - #define DEFAULT_TIMEOUT_S 10 - #define TRANSITION_EVENT_INDEX 0 // TODO remove - #define RESP_MSG_START_INDEX 3 - #define IS_TIMER_INDEX 0 - #define IS_WAIT_NEEDED_INDEX 1 - #define NEXT_AUTO_TRANSITION_INDEX 2 - #define COUNT_DOWN_TIMER_INDEX 6 // TODo remove - // 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) @@ -73,17 +63,23 @@ #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_RINSEBACK_FLOW_RATE_MLPM 200 + #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 // Treatment defines #define BLOOD_PRIME_VOLUME_ML (106.6 + 40) - #define BLOOD_FLOW_INTEGRATOR (1.0 / (SECONDS_PER_MINUTE * (MILLISECONDS_PER_SECOND /QOBJECT_TIMER_TIMEOUT_MS))) + #define FLOW_INTEGRATOR (1.0 / (SECONDS_PER_MINUTE * (MILLISECONDS_PER_SECOND /QOBJECT_TIMER_TIMEOUT_MS))) #define MAX_DIALYSATE_VOLUME_ML 150000 + // Treatment substates + #define BLOOD_RPIME_SUB_STATE 1 + #define DIALYSIS_SUB_STATE 2 + #define RINSEBACK_SUBSTATE 4 + #define TX_END_SUB_STATE 6 + enum User_Command_ID { CMD_NONE = -1, CMD_STAND_BY = 0, @@ -107,16 +103,13 @@ STATE_ON_EXIT, }; + enum Rinseback_Rqst { + RINSEBACK_START = 0, + RINSEBACK_SALINE_BOLUS = 6, + RINSEBACK_END_TX = 8, + RINSEBACK_BACK = 9, - QHash > _dryDemoCmds; // TODO remove - quint16 _index; // TODo remove - quint16 _broadcastMsgCount; // TODO remove - quint16 _timerBroadcastCount; // TOdo remove - bool _hasUserConfirmedToProceed; - int _currentCounterValue; // TODO remove???? - int _prescribedTreatmentTimeS; // TODO remove - User_Command_ID _dryDemoCurrentCmd; // ToDo remove - drydemoXMLstates _dryDemo; + }; struct Pre_Treatment_Params { bool hasTxParamsBeenInitialized; @@ -160,26 +153,30 @@ bool _isSendListReady; // Todo use a mutex Treatment_Variables _treatmentVars; Pre_Treatment_Params _treatmentParams; + bool _hasUserConfirmedToProceed; + drydemoXMLstates _dryDemo; void resetVariables(); void sendMessages(bool isBroadcast); void setTreatmentParams(bool isFromUI, const QVariant &payload); void prepareOcclusionBroadcastData(); void prepareTreatmentTimeBroadcastData(); - void prepareBloodFlowBroadcastData(); + void prepareBloodFlowBroadcastData(quint32 flowMLPM); void prepareDialysateFlowBroadcastData(); void prepareDialysateOutFlowBroadcastData(); void prepareTreatmentParamsRangesBroadcastData(); void prepareHDModeTransitionBroadcastData(Can::HD_OP_MODE mode, quint32 subMode); void prepareStatesBroadcastData(Can::Message_ID_Enum msgID, const QList &preTxStates); void prepareBloodPrimeBroadcastData(float accumulatedVolML); + void prepareRinsebackBroadcastData(const QList &volsML, const QList &payload); void handleTreatmentTimeChangeRequest(const QVariant &payload); qint32 handleMsgBBPayload(const QVariant &payload); bool hasPreTxTimerElapsed(Can::Message_ID_Enum msgID, Can::Can_Id canChan, quint32 &timerCountDownS, quint32 defaultTimeoutS); void handleUltrafiltrationValidation(const QVariant &payload); + void handleRinsebackSubstate(const QVariant &payload, quint32 &rbState); // State handlers void onIdleStateChange(bool active);