Index: LeahiDryDemoXMLStates.scxml =================================================================== diff -u -r6d7f1800f7f56813c0824df509487f527a4026b2 -r6e845078107f7d15a3e471be421d5bce31fc51da --- LeahiDryDemoXMLStates.scxml (.../LeahiDryDemoXMLStates.scxml) (revision 6d7f1800f7f56813c0824df509487f527a4026b2) +++ LeahiDryDemoXMLStates.scxml (.../LeahiDryDemoXMLStates.scxml) (revision 6e845078107f7d15a3e471be421d5bce31fc51da) @@ -1,47 +1,81 @@ - + - + - + - + - + - + - + + + + + + + - + - + - + - + - + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + Index: drydemo.pro =================================================================== diff -u -r9edc9ba3995ca25a29bb74eeeae71f7d72965284 -r6e845078107f7d15a3e471be421d5bce31fc51da --- drydemo.pro (.../drydemo.pro) (revision 9edc9ba3995ca25a29bb74eeeae71f7d72965284) +++ drydemo.pro (.../drydemo.pro) (revision 6e845078107f7d15a3e471be421d5bce31fc51da) @@ -101,7 +101,10 @@ sources/ApplicationController.cpp \ \ # ---------- States ---------- sources/drydemo/StateController.cpp \ + sources/drydemo/StateControllerRinseback.cpp \ + sources/drydemo/StateControllerStandby.cpp \ sources/drydemo/StateControllerTreatment.cpp \ + sources/drydemo/StateControllerTreatmentBroadcasts.cpp \ sources/storage/Settings.cpp \ \ # ---------- Models ---------- sources/model/MAbstract.cpp \ Index: sources/MessageGlobals.h =================================================================== diff -u -r8aa65ae1bbef5f6121783026efeeb99114c14414 -r6e845078107f7d15a3e471be421d5bce31fc51da --- sources/MessageGlobals.h (.../MessageGlobals.h) (revision 8aa65ae1bbef5f6121783026efeeb99114c14414) +++ sources/MessageGlobals.h (.../MessageGlobals.h) (revision 6e845078107f7d15a3e471be421d5bce31fc51da) @@ -129,6 +129,9 @@ enum Message_ID_Enum { ID_NONE = 0x0000, + ID_ALARM_STATUS_DATA = 0x0100, + ID_ALARM_CLEARED = 0x0300, + ID_UI_ALARM_USER_ACTION_REQUEST = 0x0600, ID_TD_OP_MODE_DATA = 0x1200, ID_DD_CONDUCTIVITY_DATA = 0x1F00, ID_TD_PRESSURE_DATA = 0x2400, @@ -168,6 +171,9 @@ ID_TD_TREATMENT_SET_POINT_DIALYSATE_FLOW_CHANGE_RESP = 0x7F00, ID_UI_TREATMENT_SET_POINT_DIALYSATE_TEMP_CHANGE_RQST = 0x8000, ID_TD_TREATMENT_SET_POINT_DIALYSATE_TEMP_CHANGE_RESP = 0x8100, + ID_TD_RINSEBACK_DATA = 0x8F00, + ID_UI_RINSEBACK_CMD_RQST = 0x9000, + ID_TD_RINSEBACK_CMD_RESP = 0x9100, ID_UI_ADJUST_DISPOSABLES_CONFIRM_RQST = 0x9200, ID_TD_ADJUST_DISPOSSABLES_CONFIRM_RESP = 0x9300, ID_TD_BLOOD_PRIME_PROGRESS_DATA = 0x9700, @@ -177,6 +183,7 @@ ID_TD_ADJUST_START_TREATMENT_RESP = 0xA200, ID_UI_PRESSURE_LIMIT_WIDEN_RQST = 0xA400, ID_TD_PRESSURE_LIMIT_WIDEN_RESP = 0xA500, + ID_TD_UI_GENERIC_CONFIRMATION_REQUEST = 0xB500, ID_UI_CONFIRMATION_RESULT_RESP = 0xB600, }; Index: sources/drydemo/DryDemoDefines.h =================================================================== diff -u -r8aa65ae1bbef5f6121783026efeeb99114c14414 -r6e845078107f7d15a3e471be421d5bce31fc51da --- sources/drydemo/DryDemoDefines.h (.../DryDemoDefines.h) (revision 8aa65ae1bbef5f6121783026efeeb99114c14414) +++ sources/drydemo/DryDemoDefines.h (.../DryDemoDefines.h) (revision 6e845078107f7d15a3e471be421d5bce31fc51da) @@ -50,7 +50,8 @@ #define DEF_TX_PARAM_BLOOD_FLOW_RATE_MLPM 400 #define DEF_TX_PARAM_DIAL_FLOW_RATE_MLPM 350 #define DEF_TX_PARAM_SALINE_BOLUS_VOL_ML 100 -#define DEF_TX_PARAM_RINSEBACK_FLOW_RATE_MLPM 250 +#define DEF_TX_PARAM_RINSEBACK_FLOW_RATE_MLPM 200 +#define DEF_TX_PARAM_RINSEBACK_VOLUME_ML 300 #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 @@ -72,6 +73,7 @@ #define INITIATE_TREATMENT 1 #define ALLOW_DIALYSATE_DELIVER 1 #define BYPASS_DIALYSATE_DELIVER 0 +#define TRIGGER_STOP_ALARM_TIME_MS (2 * MILLISECONDS_PER_SECOND) // Treatment defines #define BLOOD_PRIME_VOLUME_ML (106.6 + 40) @@ -93,29 +95,33 @@ #define UF_RUNNING_STATE 1 // Rinseback defines +#define RINSEBACK_FLOW_INTEGRATOR 1.0 / (SECONDS_PER_MINUTE * (MILLISECONDS_PER_SECOND / QOBJECT_TIMER_TIMEOUT_MS)) #define RINSEBACK_MIN_FLOW_RATE_MLPM 100 -#define RINSEBACK_MAX_RLOW_RATE_MLPM 300 -#define RINSEBACK_ADJ_FLOW_RATE_MLPM 25 -#define RINSEBACK_BACK_MAX_TIME_S (5 * SECONDS_PER_MINUTE) -#define RINSEBACK_END_TREATMENT_SIGNAL 999 -#define RINSEBACK_STOP_INIT_STATE 0 -#define RINSEBACK_RUN_STATE 1 -#define RINSEBACK_PAUSE_STATE 2 -#define RINSEBACK_STOP_STATE 3 +#define RINSEBACK_MAX_RLOW_RATE_MLPM 500 +#define RINSEBACK_ADJ_FLOW_RATE_MLPM 10 +#define RINSEBACK_BACK_MAX_TIME_MS (5 * SECONDS_PER_MINUTE * MILLISECONDS_PER_SECOND) +#define RINSEBACK_END_TREATMENT_SIGNAL 999 // TODO remove? // Fluid Bolus defines #define FLUID_BOLUS_START_CMD 1 #define ENABLE_BOLUS 1 +// Alarms +#define ALARM_TABLE_PRIORITY_INDEX 0 +#define ALARM_TABLE_PROPERTIES_INDEX 1 +#define ALARM_NO_ALARM_PROPERTIES 0 +#define ALARM_STOP_TX_PROPERTIES 6 enum User_Command_ID { CMD_NONE = -1, CMD_STAND_BY = 0, CMD_PRE_TX = 1, CMD_BLOOD_PRIME = 2, CMD_MAIN_TX = 3, + CMD_RINSEBACK = 4, + CMD_RICIRCULATE = 5, + CMD_END_TX = 6, - CMD_END_TX = 11, CMD_DISINFECTION = 12, CMD_HIGH_PRIO_ALARM = 13, CMD_MEDIUM_PRIO_ALARM = 14, @@ -149,6 +155,26 @@ DIALYSIS_UF_FLUID_BOLUS_STATE = 2, }; +enum Rinseback_States { + RINSEBACK_STOP_INIT_STATE = 0, + RINSEBACK_RUN_STATE = 1, + RINSEBACK_PAUSED_STATE = 2, + RINSEBACK_STOP_STATE = 3, + RINSEBACK_RUN_ADDITIONAL_STATE = 4, +}; + +enum Requested_Rinseback_User_Actions +{ + REQUESTED_USER_ACTION_RINSEBACK_CONFIRM_START = 0, + REQUESTED_USER_ACTION_RINSEBACK_INCREASE_RATE = 1, + REQUESTED_USER_ACTION_RINSEBACK_DECREASE_RATE = 2, + REQUESTED_USER_ACTION_RINSEBACK_PAUSE = 3, + REQUESTED_USER_ACTION_RINSEBACK_RESUME = 4, + REQUESTED_USER_ACTION_RINSEBACK_ADDITIONAL = 5, + REQUESTED_USER_ACTION_RINSEBACK_CONFIRM_RECIRCULATE = 6, + REQUESTED_USER_ACTION_RINSEBACK_END_TREATMENT = 7, +}; + enum State_Status { STATE_ON_ENTRY = 0, STATE_ON_ACTION, @@ -160,6 +186,54 @@ BC_IMMEDIATELY, }; +// Alarm related enums +enum Alarm_Priorities { + ALARM_PRIORITY_NONE = 0, + ALARM_PRIORITY_LOW = 1, + ALARM_PRIORITY_MEDIUM = 2, + ALARM_PRIORITY_HIGH = 3, +}; + +enum Alarm_User_Actions { + ALARM_USER_ACTION_RESUME = 0, + ALARM_USER_ACTION_RINSEBACK = 1, + ALARM_USER_ACTION_END_TREATMENT = 2, + ALARM_USER_ACTION_ACK = 3, + ALARM_USER_ACTION_TEMPOARY_BREAK = 4, +}; + +enum Alarm_List { + ALARM_ID_NO_ALARM = 0, + ALARM_ID_TD_TREATMENT_STOPPED_BY_USER = 96, +}; + +enum Generic_Confirm_Id +{ + GENERIC_CONFIRM_ID_NONE = 0, + GENERIC_CONFIRM_ID_SHUT_DOWN = 1, + GENERIC_CONFIRM_ID_TREATMENT_END = 2, + GENERIC_CONFIRM_ID_RINSEBACK = 3, + GENERIC_CONFIRM_ID_TEMPORARY_BREAK = 4, +}; + +enum Generic_Confirm_Command +{ + GENERIC_CONFIRM_CMD_REQUEST_OPEN = 0, + GENERIC_CONFIRM_CMD_TIMEOUT_CLOSE = 1, + GENERIC_CONFIRM_CMD_REJECT = 2, + GENERIC_CONFIRM_CMD_ACCEPT_CLOSE = 3, +}; + +enum Confirmation_Status +{ + CONFIRMATION_REQUEST_STATUS_REJECTED = 0, + CONFIRMATION_REQUEST_STATUS_ACCEPTED, + CONFIRMATION_REQUEST_STATUS_TIMEOUT, + CONFIRMATION_REQUEST_STATUS_PENDING, + CONFIRMATION_REQUEST_STATUS_UNUSED, +}; + +// Reject reason enums enum Reject_Reasons { REQUEST_REJECT_REASON_NONE = 0, REQUEST_REJECT_REASON_INVALID_TREATMENT_STATE = 4, @@ -170,6 +244,7 @@ REQUEST_REJECT_REASON_UF_NOT_IN_PROGESS = 14, REQUEST_REJECT_REASON_UF_NOT_PAUSED = 15, REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE = 17, + REQUEST_REJECT_REASON_ACTION_DISABLED_IN_CURRENT_STATE = 21, REQUEST_REJECT_REASON_CONFIRMATION_NOT_EXPECTED = 58, REQUEST_REJECT_REASON_CONFIRMATION_MISMATCH = 59, }; Index: sources/drydemo/StateController.cpp =================================================================== diff -u -r8aa65ae1bbef5f6121783026efeeb99114c14414 -r6e845078107f7d15a3e471be421d5bce31fc51da --- sources/drydemo/StateController.cpp (.../StateController.cpp) (revision 8aa65ae1bbef5f6121783026efeeb99114c14414) +++ sources/drydemo/StateController.cpp (.../StateController.cpp) (revision 6e845078107f7d15a3e471be421d5bce31fc51da) @@ -15,19 +15,33 @@ connect(&_ApplicationController, SIGNAL(didUnhandledMsgAppController(const QVariantList &)), this , SLOT(doStateControllerUnhandledMsgReceived(const QVariantList &))); - _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_End" , this, &StateController::onTreatmentEndStateChange ); + // 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 } @@ -57,6 +71,8 @@ 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; @@ -100,6 +116,11 @@ 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; } @@ -137,27 +158,6 @@ for (auto item: msgList){ emit _ApplicationController.didActionTransmit(item); } } -void StateController::handleDryDemoMenuRequestMessage() -{ - quint32 msgPayload = extractU32DataFromReceivedMessage(ID_UI_CONFIRMATION_RESULT_RESP, 0); - if (msgPayload != UI_MSG_BB_PAYLOAD_ID) { return; } - - msgPayload = extractU32DataFromReceivedMessage(ID_UI_CONFIRMATION_RESULT_RESP, UI_MSG_BB_STATUS_INDEX); - _treatmentStatus.userCmd = static_cast(msgPayload); - _treatmentRcvdMessages[ID_UI_CONFIRMATION_RESULT_RESP].clear(); -} - -void StateController::handleBackToStandbyEvent(State_Status &status) -{ - if (_treatmentRcvdMessages[ID_UI_CONFIRMATION_RESULT_RESP].isNull()) { return; } - - // Check for the user request message from the dry-demo menu - handleDryDemoMenuRequestMessage(); - _treatmentStatus.stateTransitionEvent = "T_Back_2_SB"; - status = STATE_ON_EXIT; - _treatmentRcvdMessages[ID_UI_CONFIRMATION_RESULT_RESP].clear(); -} - // ----------- State transition methods ---------------- // void StateController::onStandbyStateChange(bool active) { @@ -167,6 +167,8 @@ 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"; }; @@ -337,11 +339,14 @@ void StateController::onTreatmentStateChange(bool active) { - static State_Status status = STATE_ON_ENTRY; + 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; @@ -391,15 +396,62 @@ handleTreatmentSettingBroadcastData(BC_DELAYED); handleTreatmentTimeChangeValidation(); handleTreatmentTimeChangeConfirm(); - if ((_treatmentStatus.treatmentElapsedTimeMS / MILLISECONDS_PER_SECOND) >= (_treatmentParams.treatmentDurationMin * SECONDS_PER_MINUTE)) { + 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; }; @@ -409,7 +461,90 @@ 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; @@ -448,26 +583,9 @@ // ************* Hepler functions ************* // -void StateController::handleInitiateTreatmentRequestMessage(State_Status &status) -{ - if (_treatmentRcvdMessages[ID_INITIATE_TREATMENT].isNull()){ return; } - - 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; - if ((++broadcastCounter % NUM_OF_COUNTS_TIMER_BC_EMIT != 0) && (BCType == BC_DELAYED)) { return; } QVariantList msg; @@ -598,37 +716,6 @@ _isSendListReady = true; } -void StateController::handleUIResponseMessage(const Message_ID_Enum msgID, const quint32 acceptReject, const QVariantList &rejectReasons) -{ - QVariantList resp; - resp.append(static_cast(msgID)); - resp.append(Can_Id::eChlid_TD_UI); - resp.append(acceptReject); - if (rejectReasons.isEmpty()) { - // If the default reject reasons is empty, it means there were no reject reasons or extra payloads so assume none - resp.append(static_cast(REQUEST_REJECT_REASON_NONE)); - qDebug() << "Empty"; - } - else { - for (auto item: rejectReasons) { resp.append(item); } - } - _isSendListReady = false; - _sendMessages.append(resp); - _isSendListReady = true; -} - -void StateController::resetDryDemoVariables() -{ - _treatmentStatus.hasTxParamsBeenInitialized = false; - _treatmentStatus.treatmentElapsedTimeMS = DEF_TX_ELAPSED_TIME_S * MILLISECONDS_PER_SECOND; - _treatmentStatus.stateTransitionEvent = ""; - _treatmentStatus.totalFluidBolusDeliveredML = 0.0; - _treatmentStatus.accumFluidBolusDeliveredML = 0.0; - _treatmentStatus.fluidBolusState = FLUID_BOLUS_IDLE_STATE; - _treatmentStatus.txState = TREAT_START_STATE; - _treatmentStatus.ufVolDeliveredL = 0.0; -} - quint32 StateController::extractU32DataFromReceivedMessage(const Message_ID_Enum msgID, qint32 index) { Types::U32 u32Var; @@ -645,3 +732,6 @@ return f32Var.value; } + + + Index: sources/drydemo/StateController.h =================================================================== diff -u -r8aa65ae1bbef5f6121783026efeeb99114c14414 -r6e845078107f7d15a3e471be421d5bce31fc51da --- sources/drydemo/StateController.h (.../StateController.h) (revision 8aa65ae1bbef5f6121783026efeeb99114c14414) +++ sources/drydemo/StateController.h (.../StateController.h) (revision 6e845078107f7d15a3e471be421d5bce31fc51da) @@ -30,15 +30,18 @@ void timerEvent(QTimerEvent *) override; private: - struct Treatment_Status_Vars { - bool hasTxParamsBeenInitialized; - quint32 treatmentElapsedTimeMS; + bool hasTxParamsBeenInitialized; User_Command_ID userCmd; QString stateTransitionEvent; + bool requestTreatmentReset; + // Treatment time variable(s) + quint32 treatmentElapsedTimeMS; + // Fluid bolus + Fluid_Bolus_States fluidBolusState; float accumFluidBolusDeliveredML; float totalFluidBolusDeliveredML; - Fluid_Bolus_States fluidBolusState; + // Treatment states Treatment_States txState; Dialysis_States dialysisSubState; // UF variables @@ -47,12 +50,19 @@ bool validateUFVolReceived; float validateUFVolGoalL; float validateUFRateLHR; - // Tx dur variables + // Treatment duration variables bool validateTxDurReceived; quint32 validateTxDurMin; quint32 validateHepDurMin; - // Alarm variabls - bool isAnAlarmActive; + // Alarm variables + Alarm_List activeAlarm; + // Rinseback variables + Rinseback_States rinsebackStates; + quint32 rinsebackFlowMLPM; + float accumRinsebackVolML; + float additionalRinsebackVolML; + bool isRinsebackComplete; + quint32 rinsebackTimerCounter; }; struct Treatment_Params { @@ -83,7 +93,8 @@ float ufVolumeL; }; - QHash_transitionEventsFromStandby; + QHash _transitionEventsFromStandby; + QHash _alarmTriggerSpecs; QList _broadcastMessages; QList _sendMessages; QHash _treatmentRcvdMessages; @@ -92,18 +103,20 @@ Treatment_Status_Vars _treatmentStatus; bool _isBroadcastListReady; // TODO use a mutex? bool _isSendListReady; // Todo use a mutex? - bool _hasUserConfirmedToProceed; // TODO remove? drydemoXMLStates _dryDemo; // CAN function(s) void sendMessages(bool isBroadcast); - void handleDryDemoMenuRequestMessage(); + bool handleDryDemoMenuRequestMessage(); // State handlers void onStandbyStateChange(bool active); void onPretreatmentStateChange(bool active); void onBloodPrimeStateChange(bool active); void onTreatmentStateChange(bool active); + void onTreatmentPauseStateChange(bool active); + void onTreatmentRinsebackStateChange(bool active); + void onTreatmentRecriculateStateChange(bool active); void onTreatmentEndStateChange(bool active); // Helper methods @@ -113,10 +126,13 @@ void resetDryDemoVariables(); void handleBackToStandbyEvent(State_Status &status); quint32 extractU32DataFromReceivedMessage(const Can::Message_ID_Enum msgID, qint32 index); - float extractF32DataFromReceivedMessage(const Can::Message_ID_Enum msgID, qint32 index); + float extractF32DataFromReceivedMessage(const Can::Message_ID_Enum msgID, qint32 index); + void triggerAnAlarm(Alarm_List alarmID); + void handleAlarmUserAction(State_Status &status); // Standby methods void handleInitiateTreatmentRequestMessage(State_Status &status); + void handleSendUIConfirmationMessage(const Generic_Confirm_Id confirmID, const Generic_Confirm_Command confirmCmd, const Reject_Reasons rejectReason = REQUEST_REJECT_REASON_NONE); // Blood prime methods float getBloodPrimeRampStepML(); @@ -148,6 +164,12 @@ void handleTreatmentTimeChangeValidation(); void handleTreatmentTimeChangeConfirm(); + // Treatment rinseback methods + void initializeRinseback(); + void handleRinsebackRequestMessage(); + void handleRinsebackDelivery(); + void handleRinsebackBroadcastData(const Broadcast_Type BCType); + // Treatment end methods }; Index: sources/drydemo/StateControllerRinseback.cpp =================================================================== diff -u --- sources/drydemo/StateControllerRinseback.cpp (revision 0) +++ sources/drydemo/StateControllerRinseback.cpp (revision 6e845078107f7d15a3e471be421d5bce31fc51da) @@ -0,0 +1,128 @@ + +#include "StateController.h" +#include "ApplicationController.h" +#include "types.h" + + +void StateController::initializeRinseback() +{ + _treatmentStatus.rinsebackFlowMLPM = DEF_TX_PARAM_RINSEBACK_FLOW_RATE_MLPM; + _treatmentStatus.accumFluidBolusDeliveredML = 0.0; + _treatmentStatus.additionalRinsebackVolML = _treatmentParams.rinsebackVolumeML; + _treatmentStatus.isRinsebackComplete = false; + _treatmentStatus.rinsebackTimerCounter = 0; +} + +void StateController::handleRinsebackRequestMessage() +{ + // TODO should we check if an alarm is active? + if (_treatmentRcvdMessages[ID_UI_RINSEBACK_CMD_RQST].isNull()) { return; } + QVariantList reason; + quint32 acceptReject = REJECT_VALUE; + quint32 rinsebackCmd = extractU32DataFromReceivedMessage(ID_UI_RINSEBACK_CMD_RQST, 0); + + switch (rinsebackCmd) { + case REQUESTED_USER_ACTION_RINSEBACK_CONFIRM_START: + if (_treatmentStatus.rinsebackStates == RINSEBACK_STOP_INIT_STATE) { + acceptReject = ACCEPT_VALUE; + _treatmentStatus.rinsebackStates = RINSEBACK_RUN_STATE; + } + else { reason.append(REQUEST_REJECT_REASON_ACTION_DISABLED_IN_CURRENT_STATE); } + break; + + case REQUESTED_USER_ACTION_RINSEBACK_INCREASE_RATE: + if ((_treatmentStatus.rinsebackFlowMLPM + RINSEBACK_ADJ_FLOW_RATE_MLPM) <= RINSEBACK_MAX_RLOW_RATE_MLPM) { + if (_treatmentStatus.rinsebackStates == RINSEBACK_RUN_STATE) { + acceptReject = ACCEPT_VALUE; + _treatmentStatus.rinsebackFlowMLPM += RINSEBACK_ADJ_FLOW_RATE_MLPM; + } + else { reason.append(REQUEST_REJECT_REASON_ACTION_DISABLED_IN_CURRENT_STATE); } + } + else { reason.append(REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE); } + break; + + case REQUESTED_USER_ACTION_RINSEBACK_DECREASE_RATE: + if ((_treatmentStatus.rinsebackFlowMLPM - RINSEBACK_ADJ_FLOW_RATE_MLPM) >= RINSEBACK_MIN_FLOW_RATE_MLPM) { + if (_treatmentStatus.rinsebackStates == RINSEBACK_RUN_STATE) { + acceptReject = ACCEPT_VALUE; + _treatmentStatus.rinsebackFlowMLPM -= RINSEBACK_ADJ_FLOW_RATE_MLPM; + } + else { reason.append(REQUEST_REJECT_REASON_ACTION_DISABLED_IN_CURRENT_STATE); } + } + else { reason.append(REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE); } + break; + + case REQUESTED_USER_ACTION_RINSEBACK_PAUSE: + if (_treatmentStatus.rinsebackStates == RINSEBACK_RUN_STATE) { + acceptReject = ACCEPT_VALUE; + _treatmentStatus.rinsebackStates = RINSEBACK_PAUSED_STATE; + } + else { reason.append(REQUEST_REJECT_REASON_ACTION_DISABLED_IN_CURRENT_STATE); } + break; + + case REQUESTED_USER_ACTION_RINSEBACK_RESUME: + if (_treatmentStatus.rinsebackStates == RINSEBACK_PAUSED_STATE) { + acceptReject = ACCEPT_VALUE; + _treatmentStatus.rinsebackStates = RINSEBACK_RUN_STATE; + } + else { reason.append(REQUEST_REJECT_REASON_ACTION_DISABLED_IN_CURRENT_STATE); } + break; + + case REQUESTED_USER_ACTION_RINSEBACK_ADDITIONAL: + break; + + case REQUESTED_USER_ACTION_RINSEBACK_CONFIRM_RECIRCULATE: + break; + + case REQUESTED_USER_ACTION_RINSEBACK_END_TREATMENT: + handleSendUIConfirmationMessage(GENERIC_CONFIRM_ID_TREATMENT_END, GENERIC_CONFIRM_CMD_REQUEST_OPEN); + break; + } + + handleUIResponseMessage(ID_TD_RINSEBACK_CMD_RESP, acceptReject, reason); + _treatmentRcvdMessages[ID_UI_RINSEBACK_CMD_RQST].clear(); +} + +void StateController::handleRinsebackDelivery() +{ + _treatmentStatus.rinsebackTimerCounter++; + + if (_treatmentStatus.rinsebackStates == RINSEBACK_RUN_STATE) { + _treatmentStatus.accumRinsebackVolML += _treatmentStatus.rinsebackFlowMLPM * RINSEBACK_FLOW_INTEGRATOR; + } + + if (_treatmentStatus.accumRinsebackVolML >= _treatmentParams.rinsebackVolumeML) { + _treatmentStatus.rinsebackStates = RINSEBACK_STOP_STATE; + _treatmentStatus.additionalRinsebackVolML = _treatmentStatus.accumRinsebackVolML; + } +} + +void StateController::handleRinsebackBroadcastData(const Broadcast_Type BCType) +{ + static quint32 broadcastCounter = 47; + if ((++broadcastCounter % NUM_OF_COUNTS_TIMER_BC_EMIT != 0) && (BCType == BC_DELAYED)) { return; } + + quint32 rinsebackTimeoutS = RINSEBACK_BACK_MAX_TIME_MS / MILLISECONDS_PER_SECOND; + quint32 rinsebackTimerCounterMS = _treatmentStatus.rinsebackTimerCounter * QOBJECT_TIMER_TIMEOUT_MS; + quint32 countdownS = ( rinsebackTimerCounterMS <= RINSEBACK_BACK_MAX_TIME_MS ? RINSEBACK_BACK_MAX_TIME_MS - rinsebackTimerCounterMS : 0) / MILLISECONDS_PER_SECOND; + bool isRecircAllowed = true; + + if (_treatmentStatus.isRinsebackComplete || (_treatmentStatus.rinsebackTimerCounter == 0)) { + countdownS = 0; + rinsebackTimeoutS = 0; + } + + QVariantList msg; + msg.append(static_cast(ID_TD_RINSEBACK_DATA)); + msg.append(Can_Id::eChlid_TD_Sync); + msg.append(_treatmentStatus.additionalRinsebackVolML); + msg.append(_treatmentStatus.accumRinsebackVolML); + msg.append(_treatmentStatus.rinsebackFlowMLPM); + msg.append(rinsebackTimeoutS); + msg.append(countdownS); + msg.append(static_cast(_treatmentStatus.isRinsebackComplete)); + msg.append(static_cast(isRecircAllowed)); // Is recirculation allowed? TODO check this + _isBroadcastListReady = false; + _broadcastMessages.append(msg); + _isBroadcastListReady = true; +} Index: sources/drydemo/StateControllerStandby.cpp =================================================================== diff -u --- sources/drydemo/StateControllerStandby.cpp (revision 0) +++ sources/drydemo/StateControllerStandby.cpp (revision 6e845078107f7d15a3e471be421d5bce31fc51da) @@ -0,0 +1,152 @@ + +#include "StateController.h" +#include "ApplicationController.h" +#include "types.h" + +bool StateController::handleDryDemoMenuRequestMessage() +{ + quint32 msgPayload = extractU32DataFromReceivedMessage(ID_UI_CONFIRMATION_RESULT_RESP, 0); + if (msgPayload != UI_MSG_BB_PAYLOAD_ID) { return false; } + + msgPayload = extractU32DataFromReceivedMessage(ID_UI_CONFIRMATION_RESULT_RESP, UI_MSG_BB_STATUS_INDEX); + _treatmentStatus.userCmd = static_cast(msgPayload); + _treatmentRcvdMessages[ID_UI_CONFIRMATION_RESULT_RESP].clear(); + return true; +} + +void StateController::handleBackToStandbyEvent(State_Status &status) +{ + if (_treatmentRcvdMessages[ID_UI_CONFIRMATION_RESULT_RESP].isNull()) { return; } + // Check for the user request message from the dry-demo menu + if (!handleDryDemoMenuRequestMessage()) { return; } + + _treatmentStatus.stateTransitionEvent = "T_Back_2_SB"; + status = STATE_ON_EXIT; + _treatmentRcvdMessages[ID_UI_CONFIRMATION_RESULT_RESP].clear(); +} + +void StateController::handleInitiateTreatmentRequestMessage(State_Status &status) +{ + if (_treatmentRcvdMessages[ID_INITIATE_TREATMENT].isNull()){ return; } + + 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::handleUIResponseMessage(const Message_ID_Enum msgID, const quint32 acceptReject, const QVariantList &rejectReasons) +{ + QVariantList resp; + resp.append(static_cast(msgID)); + resp.append(Can_Id::eChlid_TD_UI); + resp.append(acceptReject); + if (rejectReasons.isEmpty()) { + // If the default reject reasons is empty, it means there were no reject reasons or extra payloads so assume none + resp.append(REQUEST_REJECT_REASON_NONE); + } + else { + for (auto item: rejectReasons) { resp.append(item); } + } + _isSendListReady = false; + _sendMessages.append(resp); + _isSendListReady = true; +} + +void StateController::resetDryDemoVariables() +{ + _treatmentStatus.hasTxParamsBeenInitialized = false; + _treatmentStatus.requestTreatmentReset = true; + _treatmentStatus.treatmentElapsedTimeMS = DEF_TX_ELAPSED_TIME_S * MILLISECONDS_PER_SECOND; + _treatmentStatus.stateTransitionEvent = ""; + _treatmentStatus.totalFluidBolusDeliveredML = 0.0; + _treatmentStatus.accumFluidBolusDeliveredML = 0.0; + _treatmentStatus.fluidBolusState = FLUID_BOLUS_IDLE_STATE; + _treatmentStatus.txState = TREAT_START_STATE; + _treatmentStatus.rinsebackStates = RINSEBACK_STOP_INIT_STATE; + _treatmentStatus.ufVolDeliveredL = 0.0; +} + +void StateController::triggerAnAlarm(Alarm_List alarmID) +{ + if (!_alarmTriggerSpecs.contains(alarmID)) { return; } + + quint32 state = _alarmTriggerSpecs[alarmID][ALARM_TABLE_PRIORITY_INDEX].toInt(); + quint16 properties = _alarmTriggerSpecs[alarmID][ALARM_TABLE_PROPERTIES_INDEX].toInt(); + quint32 alarmExpires = 0; + + _treatmentStatus.activeAlarm = alarmID; + + QVariantList resp; + resp.append(static_cast(ID_ALARM_STATUS_DATA)); + resp.append(Can_Id::eChlid_TD_Alarm); + resp.append(state); + resp.append(alarmID); + resp.append(alarmExpires); + resp.append(properties); + _isSendListReady = false; + _sendMessages.append(resp); + _isSendListReady = true; +} + +void StateController::handleAlarmUserAction(State_Status &status) +{ + if (_treatmentRcvdMessages[ID_UI_ALARM_USER_ACTION_REQUEST].isNull()) { return; } + + quint32 userAction = extractU32DataFromReceivedMessage(ID_UI_ALARM_USER_ACTION_REQUEST, 0); + + switch (userAction) { + case ALARM_USER_ACTION_RESUME: + _treatmentStatus.dialysisSubState = DIALYSIS_UF_STATE; + _treatmentStatus.txState = TREAT_DIALYSIS_STATE; + _treatmentStatus.stateTransitionEvent = "T_TP_2_Tx"; + break; + + case ALARM_USER_ACTION_RINSEBACK: + case ALARM_USER_ACTION_TEMPOARY_BREAK: + _treatmentStatus.stateTransitionEvent = "T_TP_2_RB"; + break; + + case ALARM_USER_ACTION_END_TREATMENT: + _treatmentStatus.stateTransitionEvent = "T_TP_2_TE"; + break; + } + + // User action has been selected so do not stay in treatment pause + status = STATE_ON_EXIT; + triggerAnAlarm(ALARM_ID_NO_ALARM); + + QVariantList msg; + msg.append(static_cast(ID_ALARM_CLEARED)); + msg.append(Can_Id::eChlid_TD_Alarm); + msg.append(_treatmentStatus.activeAlarm); + _isBroadcastListReady = false; + _broadcastMessages.append(msg); + _isBroadcastListReady = true; + // Send the alarm clear command and then clear the variable + _treatmentStatus.activeAlarm = ALARM_ID_NO_ALARM; + _treatmentRcvdMessages[ID_UI_ALARM_USER_ACTION_REQUEST].clear(); +} + +void StateController::handleSendUIConfirmationMessage(const Generic_Confirm_Id confirmID, const Generic_Confirm_Command confirmCmd, const Reject_Reasons rejectReason) +{ + QVariantList resp; + resp.append(static_cast(ID_TD_UI_GENERIC_CONFIRMATION_REQUEST)); + resp.append(Can_Id::eChlid_TD_UI); + resp.append(confirmID); + resp.append(confirmCmd); + resp.append(rejectReason); + resp.append(0.0); + resp.append(0.0); + resp.append(0.0); + resp.append(0.0); + _isSendListReady = false; + _sendMessages.append(resp); + _isSendListReady = true; +} Index: sources/drydemo/StateControllerTreatment.cpp =================================================================== diff -u -r8aa65ae1bbef5f6121783026efeeb99114c14414 -r6e845078107f7d15a3e471be421d5bce31fc51da --- sources/drydemo/StateControllerTreatment.cpp (.../StateControllerTreatment.cpp) (revision 8aa65ae1bbef5f6121783026efeeb99114c14414) +++ sources/drydemo/StateControllerTreatment.cpp (.../StateControllerTreatment.cpp) (revision 6e845078107f7d15a3e471be421d5bce31fc51da) @@ -16,25 +16,6 @@ return rampStepML; } - -void StateController::handleBloodPrimeBroadcastData(const float accumulatedVolML, const quint32 primeTimeOutS, const quint32 pauseCountDownS, const Broadcast_Type BCType) -{ - static quint32 broadcastCounter = 0; - if ((++broadcastCounter % NUM_OF_COUNTS_TIMER_BC_EMIT != 0) && (BCType == BC_DELAYED)) { return; } - - // 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(primeTimeOutS); - msg.append(pauseCountDownS); - _isBroadcastListReady = false; - _broadcastMessages.append(msg); - _isBroadcastListReady = true; -} - void StateController::handleBloodPrimeVolML(const bool resume, const float rampStepML, const bool hasFlowChanged, quint32 &currBloodFlowMLPM, float &accumBloodVolML) { @@ -91,6 +72,7 @@ _treatmentParams.dialysateTemperatureC = DEF_TX_PARAM_DIA_TEMPERATURE_C; _treatmentParams.fluidBlousVolumeML = DEF_TX_PARAM_SALINE_BOLUS_VOL_ML; _treatmentParams.ufVolumeL = DEF_TX_PARAM_UF_VOLUME_L; + _treatmentParams.rinsebackVolumeML = DEF_TX_PARAM_RINSEBACK_VOLUME_ML; } void StateController::initializeTreatmentTimeAndUltrafiltration() @@ -107,36 +89,6 @@ qDebug() << "UF Init" << presUFRateLHR << UFVolLMS << _treatmentStatus.ufVolDeliveredL; } -void StateController::handleTreatmentSetpointsBroadcastData(const quint32 bloodFlowMLPM, const quint32 dialFlowMLPM, const float dialTempC, - const Broadcast_Type BCType) -{ - static quint32 broadcastCounter = 3; - if ((++broadcastCounter % NUM_OF_COUNTS_TIMER_BC_EMIT != 0) && (BCType == BC_DELAYED)) { return; } - - QVariantList msg; - msg.append(static_cast(ID_TD_TREATMENT_SET_POINTS)); - msg.append(Can_Id::eChlid_TD_Sync); - msg.append(bloodFlowMLPM); msg.append(dialFlowMLPM); msg.append(dialTempC); - _isBroadcastListReady = false; - _broadcastMessages.append(msg); - _isBroadcastListReady = true; -} - -void StateController::handleTreatmentStatesBroadcastData(const QList &txStates, const Broadcast_Type BCType) -{ - static quint32 broadcastCounter = 0; - if ((++broadcastCounter % NUN_OF_COUNTS_QART_BC_EMIT != 0) && (BCType == BC_DELAYED)) { return; } - - QVariantList msg; - msg.append(static_cast(ID_TD_TREATMENT_STATE_DATA)); - msg.append(Can_Id::eChlid_TD_Sync); - - for (auto item: txStates) { msg.append(item);} - _isBroadcastListReady = false; - _broadcastMessages.append(msg); - _isBroadcastListReady = true; -} - void StateController::handleFluidBolusRequestMessage() { if (! _treatmentRcvdMessages[ID_UI_FLUID_BOLUS_RQST].isNull()){ @@ -186,98 +138,6 @@ 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(ENABLE_BOLUS); - _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()){ @@ -352,27 +212,7 @@ _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; - quint32 dialBypass = (_treatmentStatus.fluidBolusState == FLUID_BOLUS_SALINE_IN_PROGRESS_STATE ? BYPASS_DIALYSATE_DELIVER : ALLOW_DIALYSATE_DELIVER); - - 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(dialBypass); - 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()) { return; } @@ -385,66 +225,11 @@ _treatmentRcvdMessages[ID_UI_TREATMENT_SET_POINT_DIALYSATE_FLOW_CHANGE_RQST].clear(); } -void StateController::handleDDConductivityBroadcastData(const Broadcast_Type BCType) -{ - static quint32 broadcastCounter = 22; - if ((++broadcastCounter % NUM_OF_COUNTS_TIMER_BC_EMIT != 0) && (BCType == BC_DELAYED)) { return; } - - float d27Cond = 250.63; - - QVariantList msg; - msg.append(static_cast(ID_DD_CONDUCTIVITY_DATA)); - msg.append(Can_Id::eChlid_DD_Sync); - msg.append(0.0); - msg.append(d27Cond); - msg.append(0.0); - msg.append(0.0); - msg.append(0.0); - _isBroadcastListReady = false; - _broadcastMessages.append(msg); - _isBroadcastListReady = true; -} - -void StateController::handleTDBloodPressureBroadcastData(const Broadcast_Type BCType) -{ - static quint32 broadcastCounter = 22; - if ((++broadcastCounter % NUM_OF_COUNTS_TIMER_BC_EMIT != 0) && (BCType == BC_DELAYED)) { return; } - // TODO copmlete -} - -void StateController::handleUltrafiltrationBroadcastData(const Broadcast_Type BCType) -{ - static quint32 broadcastCounter = 31; - if ((++broadcastCounter % NUM_OF_COUNTS_TIMER_BC_EMIT != 0) && (BCType == BC_DELAYED)) { return; } - // Only count for UF when the dialysis state is in UF - if (_treatmentStatus.dialysisSubState != DIALYSIS_UF_STATE) { return; } - - float presUFVolL = _treatmentParams.ufVolumeL; - float presUFRateLHR = presUFVolL / (static_cast(_treatmentParams.treatmentDurationMin) / static_cast(MINUTES_PER_HOUR)); - float targetUFRateLHR = (_treatmentStatus.presUFRateMLPM * MINUTES_PER_HOUR) / static_cast(MILLILITERS_PER_LITER); - float UFVolLMS = presUFRateLHR / (static_cast(MINUTES_PER_HOUR * SECONDS_PER_MINUTE * MILLISECONDS_PER_SECOND)); - - _treatmentStatus.ufVolDeliveredL += UFVolLMS * PROGRESS_TIME_BC_INTERVAL_MS; - - //qDebug() << "UF" << presUFRateLHR << targetUFRateLHR << UFVolLMS << _treatmentStatus.ufVolDeliveredL; - - QVariantList msg; - msg.append(static_cast(ID_TD_ULTRAFILTRATION_DATA)); - msg.append(Can_Id::eChlid_TD_Sync); - msg.append(presUFVolL); - msg.append(targetUFRateLHR); - msg.append(_treatmentStatus.ufVolDeliveredL); - msg.append(static_cast(_treatmentStatus.dialysisSubState)); - _isBroadcastListReady = false; - _broadcastMessages.append(msg); - _isBroadcastListReady = true; -} - void StateController::handleSetPointDialysateTemperatureChange() { if (_treatmentRcvdMessages[ID_UI_TREATMENT_SET_POINT_DIALYSATE_TEMP_CHANGE_RQST].isNull()){ return; } - // TODO range check + // TODO range check _treatmentParams.dialysateTemperatureC = extractF32DataFromReceivedMessage(ID_UI_TREATMENT_SET_POINT_DIALYSATE_TEMP_CHANGE_RQST, 0); handleUIResponseMessage(ID_TD_TREATMENT_SET_POINT_DIALYSATE_TEMP_CHANGE_RESP, ACCEPT_VALUE); handleTreatmentSetpointsBroadcastData(_treatmentParams.bloodFlowRateMLPM, _treatmentParams.dialysateFlowRateMLPM, @@ -465,6 +250,7 @@ _treatmentStatus.dialysisSubState = DIALYSIS_UF_STATE; _treatmentStatus.dialysisSubState = (cmd == 0 ? DIALYSIS_UF_PAUSED_STATE : _treatmentStatus.dialysisSubState); acceptReject = ACCEPT_VALUE; + qDebug() << "UF Pa" << _treatmentStatus.dialysisSubState; } else if (_treatmentStatus.txState != TREAT_DIALYSIS_STATE) { reason.append(REQUEST_REJECT_REASON_INVALID_TREATMENT_STATE); } else { @@ -494,7 +280,7 @@ qDebug() << "UF CLAC" << elapsedTimeMin << measuredUFVolML << treatmentDurMin << requestedUFVolL << requestedUFVolML; - if ((requestedUFVolL >= MIN_UF_VOL_L) && (requestedUFVolL <= MAX_UF_VOL_L)){ + if ((requestedUFVolL >= MIN_UF_VOL_L) && (requestedUFVolL <= MAX_UF_VOL_L)) { if (requestedUFVolML > measuredUFVolML) { if (treatmentDurMin > elapsedTimeMin) { float remainingUFVolML = requestedUFVolML - measuredUFVolML; @@ -521,40 +307,6 @@ _treatmentRcvdMessages[ID_UI_TREATMENT_UF_VOLUME_VALIDATE_RQST].clear(); } -void StateController::handleTreatmentSettingBroadcastData(const Broadcast_Type BCType) -{ - static quint32 broadcastCounter = 38; - if ((++broadcastCounter % NUM_OF_COUNTS_TIMER_BC_EMIT != 0) && (BCType == BC_DELAYED)) { return; } - - quint32 elapsedTimeMin = _treatmentStatus.treatmentElapsedTimeMS / static_cast(SECONDS_PER_MINUTE * MILLISECONDS_PER_SECOND); - // NOTE: min tx time macro was converted to quint32 to prevent compilation error in qMax - quint32 minTxTimeMin = qMax(elapsedTimeMin + 2, static_cast(MIN_TX_TIME_MINS)); - // TOOD fix maxTime once firmware is done - quint32 maxTxTime1Min = minTxTimeMin; // TODO add the UF to it - quint32 maxTxTime2Min = MAX_TX_TIME_MINS; - quint32 maxTxTimeMin = qMax(maxTxTime1Min, maxTxTime2Min); - - float minUFVolML = 0.0; // TODO check with firmware for min - float maxUFVol1ML = minUFVolML + (static_cast(_treatmentParams.treatmentDurationMin - elapsedTimeMin) * MAX_UF_RATE_MLPM); - float maxUFVol2ML = (_treatmentStatus.presUFRateMLPM > 0.0 ? minUFVolML + static_cast(MAX_TX_TIME_MINS - elapsedTimeMin - 1) : minUFVolML); - float maxUFVolML = qMax(maxUFVol1ML, maxUFVol2ML); - qDebug() << "TIME settings" << elapsedTimeMin << minTxTimeMin << maxTxTime1Min << maxTxTime2Min << maxTxTimeMin - << maxUFVol1ML << maxUFVol2ML << maxUFVolML; - - QVariantList msg; - msg.append(static_cast(ID_TD_TREATMENT_PARAM_RANGES_DATA)); - msg.append(Can_Id::eChlid_TD_Sync); - msg.append(minTxTimeMin); - msg.append(maxTxTimeMin); - msg.append(minUFVolML); - msg.append(maxUFVolML); - msg.append(MIN_DIAL_RATE_MLPM); - msg.append(MAX_DIAL_RATE_MLPM); - _isBroadcastListReady = false; - _broadcastMessages.append(msg); - _isBroadcastListReady = true; -} - void StateController::handleUltrafiltrationVolumeChangeConfirm() { if (_treatmentRcvdMessages[ID_UI_ULTRAFILTRATION_CHANGE_CONFIRM_RQST].isNull()) { return; } @@ -678,3 +430,4 @@ } + Index: sources/drydemo/StateControllerTreatmentBroadcasts.cpp =================================================================== diff -u --- sources/drydemo/StateControllerTreatmentBroadcasts.cpp (revision 0) +++ sources/drydemo/StateControllerTreatmentBroadcasts.cpp (revision 6e845078107f7d15a3e471be421d5bce31fc51da) @@ -0,0 +1,256 @@ + +#include "StateController.h" +#include "ApplicationController.h" +#include "types.h" + +void StateController::handleBloodPrimeBroadcastData(const float accumulatedVolML, const quint32 primeTimeOutS, const quint32 pauseCountDownS, const Broadcast_Type BCType) +{ + static quint32 broadcastCounter = 0; + if ((++broadcastCounter % NUM_OF_COUNTS_TIMER_BC_EMIT != 0) && (BCType == BC_DELAYED)) { return; } + + // 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(primeTimeOutS); + msg.append(pauseCountDownS); + _isBroadcastListReady = false; + _broadcastMessages.append(msg); + _isBroadcastListReady = true; +} + +void StateController::handleTreatmentSetpointsBroadcastData(const quint32 bloodFlowMLPM, const quint32 dialFlowMLPM, const float dialTempC, + const Broadcast_Type BCType) +{ + static quint32 broadcastCounter = 3; + if ((++broadcastCounter % NUM_OF_COUNTS_TIMER_BC_EMIT != 0) && (BCType == BC_DELAYED)) { return; } + + QVariantList msg; + msg.append(static_cast(ID_TD_TREATMENT_SET_POINTS)); + msg.append(Can_Id::eChlid_TD_Sync); + msg.append(bloodFlowMLPM); msg.append(dialFlowMLPM); msg.append(dialTempC); + _isBroadcastListReady = false; + _broadcastMessages.append(msg); + _isBroadcastListReady = true; +} + +void StateController::handleTreatmentStatesBroadcastData(const QList &txStates, const Broadcast_Type BCType) +{ + static quint32 broadcastCounter = 0; + if ((++broadcastCounter % NUN_OF_COUNTS_QART_BC_EMIT != 0) && (BCType == BC_DELAYED)) { return; } + + QVariantList msg; + msg.append(static_cast(ID_TD_TREATMENT_STATE_DATA)); + msg.append(Can_Id::eChlid_TD_Sync); + + for (auto item: txStates) { msg.append(item);} + _isBroadcastListReady = false; + _broadcastMessages.append(msg); + _isBroadcastListReady = true; +} + +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(ENABLE_BOLUS); + _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::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; + quint32 dialBypass = (_treatmentStatus.fluidBolusState == FLUID_BOLUS_SALINE_IN_PROGRESS_STATE ? BYPASS_DIALYSATE_DELIVER : ALLOW_DIALYSATE_DELIVER); + + 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(dialBypass); + msg.append(dummyFloat); + _isBroadcastListReady = false; + _broadcastMessages.append(msg); + _isBroadcastListReady = true; +} + +void StateController::handleDDConductivityBroadcastData(const Broadcast_Type BCType) +{ + static quint32 broadcastCounter = 22; + if ((++broadcastCounter % NUM_OF_COUNTS_TIMER_BC_EMIT != 0) && (BCType == BC_DELAYED)) { return; } + + float d27Cond = 250.63; + + QVariantList msg; + msg.append(static_cast(ID_DD_CONDUCTIVITY_DATA)); + msg.append(Can_Id::eChlid_DD_Sync); + msg.append(0.0); + msg.append(d27Cond); + msg.append(0.0); + msg.append(0.0); + msg.append(0.0); + _isBroadcastListReady = false; + _broadcastMessages.append(msg); + _isBroadcastListReady = true; +} + +void StateController::handleTDBloodPressureBroadcastData(const Broadcast_Type BCType) +{ + static quint32 broadcastCounter = 22; + if ((++broadcastCounter % NUM_OF_COUNTS_TIMER_BC_EMIT != 0) && (BCType == BC_DELAYED)) { return; } + // TODO copmlete +} + +void StateController::handleUltrafiltrationBroadcastData(const Broadcast_Type BCType) +{ + static quint32 broadcastCounter = 31; + if ((++broadcastCounter % NUM_OF_COUNTS_TIMER_BC_EMIT != 0) && (BCType == BC_DELAYED)) { return; } + + float presUFVolL = _treatmentParams.ufVolumeL; + float presUFRateLHR = presUFVolL / (static_cast(_treatmentParams.treatmentDurationMin) / static_cast(MINUTES_PER_HOUR)); + float targetUFRateLHR = (_treatmentStatus.presUFRateMLPM * MINUTES_PER_HOUR) / static_cast(MILLILITERS_PER_LITER); + float UFVolLMS = presUFRateLHR / (static_cast(MINUTES_PER_HOUR * SECONDS_PER_MINUTE * MILLISECONDS_PER_SECOND)); + + // Only count for UF when the dialysis state is in UF + if (_treatmentStatus.dialysisSubState == DIALYSIS_UF_STATE) { + _treatmentStatus.ufVolDeliveredL += UFVolLMS * PROGRESS_TIME_BC_INTERVAL_MS; + } + + //qDebug() << "UF" << presUFRateLHR << targetUFRateLHR << UFVolLMS << _treatmentStatus.ufVolDeliveredL; + + QVariantList msg; + msg.append(static_cast(ID_TD_ULTRAFILTRATION_DATA)); + msg.append(Can_Id::eChlid_TD_Sync); + msg.append(presUFVolL); + msg.append(targetUFRateLHR); + msg.append(_treatmentStatus.ufVolDeliveredL); + msg.append(static_cast(_treatmentStatus.dialysisSubState)); + _isBroadcastListReady = false; + _broadcastMessages.append(msg); + _isBroadcastListReady = true; +} + +void StateController::handleTreatmentSettingBroadcastData(const Broadcast_Type BCType) +{ + static quint32 broadcastCounter = 38; + if ((++broadcastCounter % NUM_OF_COUNTS_TIMER_BC_EMIT != 0) && (BCType == BC_DELAYED)) { return; } + + quint32 elapsedTimeMin = _treatmentStatus.treatmentElapsedTimeMS / static_cast(SECONDS_PER_MINUTE * MILLISECONDS_PER_SECOND); + // NOTE: min tx time macro was converted to quint32 to prevent compilation error in qMax + quint32 minTxTimeMin = qMax(elapsedTimeMin + 2, static_cast(MIN_TX_TIME_MINS)); + // TOOD fix maxTime once firmware is done + quint32 maxTxTime1Min = minTxTimeMin; // TODO add the UF to it + quint32 maxTxTime2Min = MAX_TX_TIME_MINS; + quint32 maxTxTimeMin = qMax(maxTxTime1Min, maxTxTime2Min); + + float minUFVolML = 0.0; // TODO check with firmware for min + float maxUFVol1ML = minUFVolML + (static_cast(_treatmentParams.treatmentDurationMin - elapsedTimeMin) * MAX_UF_RATE_MLPM); + float maxUFVol2ML = (_treatmentStatus.presUFRateMLPM > 0.0 ? minUFVolML + static_cast(MAX_TX_TIME_MINS - elapsedTimeMin - 1) : minUFVolML); + float maxUFVolML = qMax(maxUFVol1ML, maxUFVol2ML); + //qDebug() << "TIME settings" << elapsedTimeMin << minTxTimeMin << maxTxTime1Min << maxTxTime2Min << maxTxTimeMin + // << maxUFVol1ML << maxUFVol2ML << maxUFVolML; + + QVariantList msg; + msg.append(static_cast(ID_TD_TREATMENT_PARAM_RANGES_DATA)); + msg.append(Can_Id::eChlid_TD_Sync); + msg.append(minTxTimeMin); + msg.append(maxTxTimeMin); + msg.append(minUFVolML); + msg.append(maxUFVolML); + msg.append(MIN_DIAL_RATE_MLPM); + msg.append(MAX_DIAL_RATE_MLPM); + _isBroadcastListReady = false; + _broadcastMessages.append(msg); + _isBroadcastListReady = true; +} +