Index: sources/StateController.cpp =================================================================== diff -u -r47baa703592f0e21098cb21c0ed267de4e958b2f -rbec9c9856c333399aa5abaf18d2799f6fbc95da3 --- sources/StateController.cpp (.../StateController.cpp) (revision 47baa703592f0e21098cb21c0ed267de4e958b2f) +++ sources/StateController.cpp (.../StateController.cpp) (revision bec9c9856c333399aa5abaf18d2799f6fbc95da3) @@ -15,9 +15,9 @@ connect(&_ApplicationController, SIGNAL(didUnhandledMsgAppController(const QVariantList &)), this , SLOT(doStateControllerUnhandledMsgReceived(const QVariantList &))); - _dryDemo.connectToState("Idle" , this, &StateController::onIdleStateChange ); - //_dryDemo.connectToState("Tx_Params" , this, &StateController::onTreatmentParamsStateChange ); - //_dryDemo.connectToState("Water_Sample" , this, &StateController::onWaterSampleStateChange ); + _dryDemo.connectToState("Standby" , this, &StateController::onStandbyStateChange ); + _dryDemo.connectToState("Pre_Tx" , this, &StateController::onPretreatmentStateChange ); + _dryDemo.connectToState("Blood_Prime" , this, &StateController::onBloodPrimeStateChange ); //_dryDemo.connectToState("Consumables" , this, &StateController::onConsumablesStateChange ); //_dryDemo.connectToState("Disposables" , this, &StateController::onDisposablesStateChange ); //_dryDemo.connectToState("System_Prime" , this, &StateController::onSystemPrimeStateChange ); @@ -32,6 +32,20 @@ //_dryDemo.connectToState("End_Tx" , this, &StateController::onEndTreatmentStateChange ); //_dryDemo.connectToState("Post_Tx" , this, &StateController::onPostTreatmentStateChange ); //_dryDemo.connectToState("Disinfect" , this, &StateController::onDisinfectStateChange ); + + _transitionEventsFromStandby.clear(); + _transitionEventsFromStandby[CMD_PRE_TX ] = "T_SB_2_Pretx"; + _transitionEventsFromStandby[CMD_BLOOD_PRIME ] = "T_SB_2_BP"; + //_transitionEventsFromStandby[CMD_CONSUMABLES ] = "Transition_2_Consumables"; + //_transitionEventsFromStandby[CMD_DISPOSABLES ] = "Transition_2_Disposables"; + //_transitionEventsFromStandby[CMD_SYSTEM_PRIME ] = "Transition_2_Sys_Prime"; + //_transitionEventsFromStandby[CMD_BP_HR ] = "Transition_2_BP_HR"; + //_transitionEventsFromStandby[CMD_ULTRAFILTRATION] = "Transition_2_Ultrafiltraion"; + //_transitionEventsFromStandby[CMD_CONNECTION ] = "Transition_2_Patient_Connection"; + //_transitionEventsFromStandby[CMD_START_TX ] = "Transition_2_Start_Tx"; + //_transitionEventsFromStandby[CMD_END_TX ] = "Transition_2_End_Tx"; + //_transitionEventsFromStandby[CMD_DISINFECTION ] = "Transition_2_Disinfect"; + } void StateController::quit() @@ -45,7 +59,10 @@ switch(receivedMsgID) { - //case ID_UI_RQST_TX: + case ID_INITIATE_TREATMENT: + case ID_UI_TREATMENT_PARAMS_TO_VALIDATE: + case ID_UI_BLOOD_PRIME_CMD_RQST: + case ID_UI_CONFIRMATION_RESULT_RESP: //case ID_UI_TX_PARAMS_RQST: //case ID_UI_CONFIRM_RESP: //case ID_UI_RINSEBACK_CMD_RQST: @@ -58,16 +75,18 @@ //case ID_UI_ALARM_USER_ACTION_RQST: //case ID_USER_BLOOD_DIAL_RATE_CHANGE_RQST: //case ID_UI_HEPARIN_PAUSE_RESUME_RQST: - // _treatmentRcvdMessages[receivedMsgID] = msg[1]; - // break; + _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: //case ID_UI_TREATMENT_LOG_RQST: //case ID_UI_POST_TREATMNET_NEXT_RQST: //case ID_UI_DISPOSABLE_REMOVAL_CONFIRM_RQST: - // _treatmentRcvdMessages[receivedMsgID] = 0; - // break; + _treatmentRcvdMessages[receivedMsgID] = 0; + break; //case ID_UI_TX_END_RQST: //case ID_UI_CONSUMABLES_INSTALL: @@ -89,6 +108,13 @@ //case ID_HD_TX_PARAMS_RANGES_DATA: //case ID_HD_TX_STATES_BC: 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_FILTER_FLUSH_TIME_BC: //case ID_HD_UI_CONFIRM_RQST: //case ID_PRE_TX_STATES_BC: @@ -137,7 +163,7 @@ { QList msgList = _broadcastMessages; - if (isBroadcast) { + if (isBroadcast){ _broadcastMessages.clear(); } else @@ -146,13 +172,13 @@ _sendMessages.clear(); } - for (auto item: msgList) { + for (auto item: msgList){ emit _ApplicationController.didActionTransmit(item); } } // ----------- State transition methods ---------------- // -void StateController::onIdleStateChange(bool active) +void StateController::onStandbyStateChange(bool active) { static State_Status status = STATE_ON_ENTRY; @@ -173,30 +199,107 @@ //// Send message 0xBA in case the dry demo menu stayed open to be closed upon transitioning to standby //prepareMsgBA(MODE_STAN, CONFIRM_CMD_ACCEPT_CLOSE); - //_transitionEventsFromIdle.clear(); - //_transitionEventsFromIdle[CMD_TX_PARAMS ] = "Transition_2_Tx_Parms"; - //_transitionEventsFromIdle[CMD_WATER_SAMPLE ] = "Transition_2_Water_Sample"; - //_transitionEventsFromIdle[CMD_CONSUMABLES ] = "Transition_2_Consumables"; - //_transitionEventsFromIdle[CMD_DISPOSABLES ] = "Transition_2_Disposables"; - //_transitionEventsFromIdle[CMD_SYSTEM_PRIME ] = "Transition_2_Sys_Prime"; - //_transitionEventsFromIdle[CMD_BP_HR ] = "Transition_2_BP_HR"; - //_transitionEventsFromIdle[CMD_ULTRAFILTRATION] = "Transition_2_Ultrafiltraion"; - //_transitionEventsFromIdle[CMD_CONNECTION ] = "Transition_2_Patient_Connection"; - //_transitionEventsFromIdle[CMD_START_TX ] = "Transition_2_Start_Tx"; - //_transitionEventsFromIdle[CMD_END_TX ] = "Transition_2_End_Tx"; - //_transitionEventsFromIdle[CMD_DISINFECTION ] = "Transition_2_Disinfect"; + status = STATE_ON_ACTION; + qDebug() << "Standby on entry"; + }; + + auto inAction = [=](){ status = STATE_ON_ACTION; - qDebug() << "Idle on entry"; + if (! _treatmentRcvdMessages[ID_INITIATE_TREATMENT].isNull()){ + _treatmentRcvdMessages[ID_INITIATE_TREATMENT].clear(); + + QVariantList resp; + resp.append(static_cast(ID_TD_RESP_INITIATE_TREATMENT)); + resp.append(Can_Id::eChlid_TD_UI); + resp.append(1); + resp.append(0); + _isSendListReady = false; + _sendMessages.append(resp); + _isSendListReady = true; + _dryDemo.submitEvent(_transitionEventsFromStandby[CMD_PRE_TX]); + status = STATE_ON_EXIT; + } + + if (! _treatmentRcvdMessages[ID_UI_CONFIRMATION_RESULT_RESP].isNull()){ + qint32 cmd = CMD_NONE; + qint32 IDIndex = 0; + Types::U32 param; + GetValue(_treatmentRcvdMessages[ID_UI_CONFIRMATION_RESULT_RESP].toByteArray(), IDIndex, param); + + if (param.value == UI_MSG_BB_PAYLOAD_ID) { + IDIndex = UI_MSG_BB_STATUS_INDEX; + GetValue(_treatmentRcvdMessages[ID_UI_CONFIRMATION_RESULT_RESP].toByteArray(), IDIndex, param); + cmd = param.value; + + User_Command_ID cmdIDEnum = static_cast(cmd); + _treatmentRcvdMessages[ID_UI_CONFIRMATION_RESULT_RESP].clear(); + if ((cmdIDEnum > CMD_STAND_BY) && (cmdIDEnum <= CMD_DISINFECTION)) { + qDebug() << "Submit event" << _transitionEventsFromStandby[cmdIDEnum]; + _dryDemo.submitEvent(_transitionEventsFromStandby[cmdIDEnum]); + status = STATE_ON_EXIT; + } + + } + + } }; + auto inExit = [=](){ + qDebug() << "Standby in 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; + } +} + +void StateController::onPretreatmentStateChange(bool active) +{ + static State_Status status = STATE_ON_ENTRY; + + auto inEntry = [=](){ + prepareTDOpModeTransitionData(MODE_PRET, 0); + + status = STATE_ON_ACTION; + + qDebug() << "PreTx on entry"; + }; + auto inAction = [=](){ - status = STATE_ON_ACTION; + if (! _treatmentRcvdMessages[ID_UI_ADJUST_DISPOSABLES_CONFIRM_RQST].isNull()){ + _treatmentRcvdMessages[ID_UI_ADJUST_DISPOSABLES_CONFIRM_RQST].clear(); + + QVariantList resp; + resp.append(static_cast(ID_TD_ADJUST_DISPOSSABLES_CONFIRM_RESP)); + resp.append(Can_Id::eChlid_TD_UI); + resp.append(1); + resp.append(0); + _isSendListReady = false; + _sendMessages.append(resp); + _isSendListReady = true; + } + + if (! _treatmentRcvdMessages[ID_UI_TREATMENT_PARAMS_TO_VALIDATE].isNull()){ + setTreatmentParameters(true, _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(); + prepareStartTxResponse(); + _dryDemo.submitEvent(_transitionEventsFromStandby[CMD_BLOOD_PRIME]); + } + + status = STATE_ON_ACTION; }; auto inExit = [=](){ - qDebug() << "Idle in exit"; + qDebug() << "PreTx in exit"; status = STATE_ON_ENTRY; }; @@ -207,7 +310,125 @@ } } +void StateController::onBloodPrimeStateChange(bool active) +{ + static State_Status status = STATE_ON_ENTRY; + static float accumBloodVolML = 0.0; + static quint32 curBloodFlowMLPM = BLOOD_PRIME_START_FLOW_MLPM; + static bool resume = true; + auto inEntry = [=](){ + prepareTDOpModeTransitionData(MODE_TREA, 0); + accumBloodVolML = 0; + QVariantList msg; + msg.append(static_cast(ID_TD_TREATMENT_STATE_DATA)); + msg.append(Can_Id::eChlid_TD_Sync); + msg.append(1); msg.append(1); msg.append(0); msg.append(0); msg.append(0); msg.append(0); msg.append(0); msg.append(0); + msg.append(0); msg.append(0); + _isBroadcastListReady = false; + _broadcastMessages.append(msg); + _isBroadcastListReady = true; + + _treatmentStatus.broadcastIntervalCount = 0; + status = STATE_ON_ACTION; + + qDebug() << "Blood prime on entry"; + }; + + auto inAction = [=](){ + if (! _treatmentRcvdMessages[ID_UI_BLOOD_PRIME_CMD_RQST].isNull()){ + QVariantList resp; + qint32 index = 0; + Types::U32 u32Var; + resp.append(static_cast(ID_TD_BLOOD_PRIME_CMD_RESP)); + resp.append(Can_Id::eChlid_TD_UI); + resp.append(ACCEPT_VALUE); + resp.append(0); + _isSendListReady = false; + _sendMessages.append(resp); + _isSendListReady = true; + GetValue(_treatmentRcvdMessages[ID_UI_BLOOD_PRIME_CMD_RQST].toByteArray(), index, u32Var); + resume = (u32Var.value == 1 ? true : false); + quint32 state = (u32Var.value == 1 ? 1 : 2); + + QVariantList msg; + msg.append(static_cast(ID_TD_TREATMENT_STATE_DATA)); + msg.append(Can_Id::eChlid_TD_Sync); + msg.append(1); msg.append(state); msg.append(0); msg.append(0); msg.append(0); msg.append(0); msg.append(0); msg.append(0); + msg.append(0); msg.append(0); + _isBroadcastListReady = false; + _broadcastMessages.append(msg); + _isBroadcastListReady = true; + + + _treatmentRcvdMessages[ID_UI_BLOOD_PRIME_CMD_RQST].clear(); + } + + if (resume){ + _treatmentStatus.broadcastIntervalCount++; + accumBloodVolML += (curBloodFlowMLPM * FLOW_INTEGRATOR); + } + + if ((_treatmentStatus.broadcastIntervalCount % NUM_OF_COUNTS_TIMER_BC_EMIT == 0) && (resume) ) { + + prepareBloodPrimeBroadcastData(accumBloodVolML); + //prepareOcclusionBroadcastData(); + //prepareTreatmentParamsRangesBroadcastData(true); // Reset the params and get ready for a new treatment + + if (curBloodFlowMLPM < _treatmentParams.bloodFlowRateMLPM) { + // If interim blood flow is less than the target blood flow, keep adding + // to the blood flow ramp + curBloodFlowMLPM += BLOOD_PRIME_FLOW_CHNG_MLPM; + } + + if (curBloodFlowMLPM >= _treatmentParams.bloodFlowRateMLPM) { + // If the interim blood flow is >= target blood flow: + // If target blood flow is less than 250 which is the starting flow in blood prime, + // then keep subtracting the target (e.g. target 110 and we start from 250 mL/min) + // If the target blood flow is > than 250 mL/min set the interim flow to target blood flow + if (_treatmentParams.bloodFlowRateMLPM < BLOOD_PRIME_START_FLOW_MLPM) { + curBloodFlowMLPM -= BLOOD_PRIME_FLOW_CHNG_MLPM; + + if (curBloodFlowMLPM <= _treatmentParams.bloodFlowRateMLPM) { + curBloodFlowMLPM = _treatmentParams.bloodFlowRateMLPM; + } + } + else { + curBloodFlowMLPM = _treatmentParams.bloodFlowRateMLPM; + } + } + } + + status = STATE_ON_ACTION; + + + if (accumBloodVolML > BLOOD_PRIME_VOLUME_ML) { + QVariantList msg; + msg.append(static_cast(ID_TD_TREATMENT_STATE_DATA)); + msg.append(Can_Id::eChlid_TD_Sync); + msg.append(2); msg.append(0); msg.append(0); msg.append(0); msg.append(0); msg.append(0); msg.append(0); msg.append(0); + msg.append(0); msg.append(0); + _isBroadcastListReady = false; + _broadcastMessages.append(msg); + _isBroadcastListReady = true; + + status = STATE_ON_EXIT; + } + }; + + auto inExit = [=](){ + //qDebug() << "Blood prime 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; + } +} + + void StateController::prepareTDOpModeTransitionData(Can::TD_OP_MODE mode, quint32 subMode) { QVariantList msg; @@ -220,4 +441,150 @@ _isBroadcastListReady = true; } +void StateController::setTreatmentParameters(bool isFromUI, const QVariant &payload) +{ + if (isFromUI){ + 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; + } +} + +void StateController::prepareStartTxResponse() +{ + QVariantList resp; + resp.append(static_cast(ID_TD_ADJUST_START_TREATMENT_RESP)); + resp.append(Can_Id::eChlid_TD_UI); + resp.append(ACCEPT_VALUE); + resp.append(0); + _isSendListReady = false; + _sendMessages.append(resp); + _isSendListReady = true; +} + +void StateController::prepareBloodPrimeBroadcastData(float accumulatedVolML) +{ + // Broadcast + QVariantList msg; + msg.append(static_cast(ID_TD_BLOOD_PRIME_PROGRESS_DATA)); + msg.append(Can_Id::eChlid_TD_Sync); + msg.append(BLOOD_PRIME_VOLUME_ML); + msg.append(accumulatedVolML); + msg.append(2000); + msg.append(1000); + _isBroadcastListReady = false; + _broadcastMessages.append(msg); + _isBroadcastListReady = true; +}