Files
GUI/src/device/DeviceManager.cpp

1507 lines
47 KiB
C++

#include "DeviceManager.h"
#include <QVariant>
#include <QTimerEvent>
#include <QTimer>
#include <QDate>
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>
#include <QProcess>
#include <QtMath>
#include <qdebug.h>
#include "appvals/AppGlobalValues.h"
#include "json/ScanJson.h"
#include "json/jsonobject.h"
#include "event/EventCenter.h"
#include "db/SQLHelper.h"
#include "InfoReceiveWorker.h"
#include "DmsSyncAction.h"
#include "DmsAsyncAction.h"
#include "dms_mq.h"
#include "recon/ReconManager.h"
#include "dialogs/MultyMessageDialog.h"
#include "UsctStateManager.h"
#include "utilities/ScanProcessSequence.h"
#include "utilities/AlarmHelper.h"
#include "log/LogManager.h"
#define TRIGGER_EVENT EventCenter::Default()->triggerEvent
#define THROW_ERROR(errormsg)\
TRIGGER_EVENT(GUIEvents::GUIErrorRaise, nullptr, (QObject*)&errormsg);
namespace
{
const int PREVIEW_IMAGE_WH = 140;
const unsigned int GET_TEMPERATURE_TIME = 60000;
const int CHECK_RECON_CONNECTION_TIME = 30000;
const int SHUT_DOWN_TIMEOUT = 180000;//3 minitues
const int PUMP_TIMEOUT = 3000;//3 seconds
const int GETDMSVERSION_TIMEOUT = 5000;
const int EFFECTIVE_POSITION_RADIUS = 125;
const int EFFECTIVE_POSITION_Z_START = 150;
const int EFFECTIVE_POSITION_Z_END = 225;
const QString DEFAULT_DMS_START_FAILED = "Dms start failed.";
QJsonObject toJsonObject(const QString& aJsonString)
{
QJsonDocument jsonDoc = QJsonDocument::fromJson(aJsonString.toUtf8());
if(!jsonDoc.isNull() && jsonDoc.isObject())
{
return jsonDoc.object();
}
return QJsonObject();
}
}
const char* getStatusString(DeviceStatus aStatus)
{
switch (aStatus) {
case DeviceStatus::Scanning:
return "SCANNING";
case DeviceStatus::Rready:
return "Ready";
case DeviceStatus::Busy:
return "BUSY";
case DeviceStatus::Error:
return "ERROR";
case DeviceStatus::Unkonw:
return "Unkonw";
default:
return nullptr;
}
}
QString getFullScanJson(QObject* obj)
{
QString* msg = (QString*)obj;
QJsonDocument patientInfo = QJsonDocument::fromJson(msg->toUtf8());
QJsonObject fullJson;
fullJson["Patient Info"] = patientInfo.object()["Patient Info"];
fullJson["mode"] = "0";
fullJson["active report"] = "0";
return QString::fromUtf8(QJsonDocument(fullJson).toJson(QJsonDocument::Compact));
}
void DeviceManager::initDevice()
{
mReconTransferPath = JsonObject::Instance()->getReconTransferPath();
dmsmq_init(0);
// empty scan
connect(EventCenter::Default(), &EventCenter::RequestEmptyScan, [=](QObject* sender, QObject* detail)
{
startScan(getFullScanJson(detail), true);
});
// Patient scan
connect(EventCenter::Default(), &EventCenter::RequestPatientScan, [=](QObject* sender, QObject* detail)
{
startScan(getFullScanJson(detail));
});
// stop
connect(EventCenter::Default(), &EventCenter::RequestFullScanStop,this, &DeviceManager::stopFullScan);
connect(EventCenter::Default(), &EventCenter::RequestPreviewStop,this, &DeviceManager::stopPreviewScan);
// preview
connect(EventCenter::Default(), &EventCenter::RequestPreviewScan,this, &DeviceManager::startPreview);
//shutdown
connect(EventCenter::Default(), &EventCenter::RequestShutdown, this, &DeviceManager::shutdownDms);
//Drainage
connect(EventCenter::Default(), &EventCenter::RequestDrainage, this, [this](QObject* sender, QObject* detail)
{
controlDrainage(*(QString*)detail);
});
//AutoLocate
connect(EventCenter::Default(), &EventCenter::StartScanProcess, this, &DeviceManager::startScanProcess);
connect(EventCenter::Default(), &EventCenter::StopScanProcess, this, &DeviceManager::stopScanProcess);
//Sync action
mGetDeviceStatusAction = new DmsSyncAction(USRV_SCAN, ACT_SCAN_STATUS, this, "responseGetDeviceStatus(const QString&)", this);
mFullScanAction = new DmsSyncAction(USRV_SCAN, ACT_SCAN_FULLSCAN, this, "responseFullScan(const QString&)", this);
mStopScanAction = new DmsSyncAction(USRV_SCAN, ACT_SCAN_STOP, this, "responseStopScan(const QString&)", this);
mPreviewScanAction = new DmsSyncAction(USRV_SCAN, ACT_SCAN_PREVIEW, this, "responsePreviewScan(const QString&)", this);
mTransferAction = new DmsSyncAction(USRV_XFR, ACT_XFR_START, this, "responseTransfer(const QString&)", this);
mGetTransferProgressAction = new DmsSyncAction(USRV_XFR, ACT_XFR_PROGRESS_PASSIVE, this, "responseGetTransferProgress(const QString&)", this);
mCEScanAction = new DmsSyncAction(USRV_SCAN, ACT_SCAN_CE, this, "responseCEScan(const QString&)", this);
mGetCEStatusAction = new DmsSyncAction(USRV_SCAN, ACT_SCAN_CE_STATUS, this, "responseGetCEStatus(const QString&)", this);
mSetSimulatorModeAction = new DmsSyncAction(USRV_SCAN, ACT_SCAN_SIMULATOR, this, "responseSetSimulatorMode(const QString&)", this);
mSetHeartBeatAction = new DmsSyncAction(USRV_INFOCFG, ACT_IFCFG_HBCFG, this, "responseSetHeartBeat(const QString&)", this);
mCheckInitStatusAction = new DmsSyncAction(USRV_INFOCFG, ACT_IFCFG_INIT_STATUS, this, "responseCheckInitStatus(const QString&)", this);
mStartAutoLocateAction = new DmsSyncAction(USRV_CONTROL, ACT_CTL_MOTION_START, this, "responseStartAutoLocate(const QString&)", this);
mStopAutoLocateAction = new DmsSyncAction(USRV_CONTROL, ACT_CTL_MOTION_STOP, this, "responseStopAutoLocate(const QString&)", this);
mCheckDataQualityAction = new DmsSyncAction(USRV_SCAN, ACT_SCAN_IMGQUALITI, this, "responseCheckDataQuality(const QString&)", this);
//Async action
mGetScanProgressAction = new DmsAsyncAction(USRV_SCAN, ACT_SCAN_PROGRESS_PASSIVE, this,"responseGetScanProgress(const QString&)", this);
mGetDeviceTemperatureAction = new DmsAsyncAction(USRV_SCAN, ACT_SCAN_TEMP, this, "responseGetDeviceTemperature(const QString&)", this);
mStopTransferAction = new DmsAsyncAction(USRV_XFR, ACT_XFR_STOP, this, "responseStopTransfer(const QString&)", this);
mShutDownAction = new DmsAsyncAction(USRV_CONTROL, ACT_CTL_PWRDOWN, this, "responseShutDown(const QString&)", this);
mShutDownAction->setTimeoutInterval(SHUT_DOWN_TIMEOUT);
mPumpControlAction = new DmsAsyncAction(USRV_CONTROL, ACT_CTL_PUMP, this, "responsePumpControl(const QString&)", this);
mPumpControlAction->setTimeoutInterval(PUMP_TIMEOUT);
mGetAutoLocatePositionAction = new DmsAsyncAction(USRV_CONTROL, ACT_CTL_MOTION_POSITION, this, "responseGetAutoLocatePosition(const QString&)", this);
mGetSoftwareVersionAction = new DmsAsyncAction(USRV_INFOCFG, ACT_IFCFG_VERINFO, this,"responseGetSoftwareVersion(const QString&)", this);
mGetSoftwareVersionAction->setTimeoutInterval(GETDMSVERSION_TIMEOUT);
mEmergencyResetAction = new DmsAsyncAction(USRV_CONTROL, ACT_CTL_EMG_RESET, this,"responseEmergencyButtonReset(const QString&)", this);
connect(mGetSoftwareVersionAction, &DmsAsyncAction::timeout, [this]()
{
emit getDmsVersionResponsed("DMS Version Fetch Error");
});
connect(mPumpControlAction, &DmsAsyncAction::timeout, [this]()
{
this->processPumpResult("{\"code\":-1}");
});
connect(mGetScanProgressAction, &DmsAsyncAction::timeout, this, &DeviceManager::scanTimeout);
connect(mShutDownAction, &DmsAsyncAction::timeout, this, &DeviceManager::shutdownDmsFailed);
connect(mGetAutoLocatePositionAction, &DmsAsyncAction::timeout, [this]()
{
if(mGetAutoLocatePositionTimer != -1)
{
this->killTimer(mGetAutoLocatePositionTimer);
mGetAutoLocatePositionTimer = -1;
}
TRIGGER_EVENT(StopScanProcess, nullptr, nullptr);
QString errorMessage = tr("DMS connection error");
THROW_ERROR(errorMessage)
});
//dmsInfoReceiverThread
mDmsInfoReceiveThread = new QThread(this);
mInfoReceiveWorker = new InfoReceiveWorker(nullptr);
mInfoReceiveWorker->moveToThread(mDmsInfoReceiveThread);
connect(mDmsInfoReceiveThread, &QThread::started, mInfoReceiveWorker, &InfoReceiveWorker::startListen);
connect(mDmsInfoReceiveThread, &QThread::finished, mInfoReceiveWorker, &InfoReceiveWorker::deleteLater);
connect(mInfoReceiveWorker, &InfoReceiveWorker::infoReceived, this, &DeviceManager::processReceiveDMSInfoResult);
mDmsInfoReceiveThread->start();
//reconHttpThread
mReconHttpThread = new QThread(this);
QTimer* reconConnectionTimer = new QTimer(this);
ReconManager::getInstance()->moveToThread(mReconHttpThread);
connect(EventCenter::Default(), &EventCenter::LoginSuccess, [reconConnectionTimer, this]()
{
emit checkReconConnection();
if(!reconConnectionTimer->isActive())
{
reconConnectionTimer->start(CHECK_RECON_CONNECTION_TIME);
}
});
connect(ReconManager::getInstance(), &ReconManager::reconStateResponsed, UsctStateManager::getInstance(), &UsctStateManager::updateReconState);
connect(this, &DeviceManager::checkReconConnection, ReconManager::getInstance(), &ReconManager::checkReconConnection);
connect(reconConnectionTimer, &QTimer::timeout, this, &DeviceManager::prepareCheckReconConnection);
connect(this, &DeviceManager::createEmptyScanToRecon, ReconManager::getInstance(), &ReconManager::createEmptyScan);
connect(this, &DeviceManager::createScanToRecon, ReconManager::getInstance(), &ReconManager::createScan);
connect(ReconManager::getInstance(), &ReconManager::createScanResponsed, this, &DeviceManager::processReconCreateScan);
connect(ReconManager::getInstance(), &ReconManager::createEmptyScanResponsed, this, &DeviceManager::processReconCreateEmptyScan);
connect(this, &DeviceManager::queryScanStatusToRecon, ReconManager::getInstance(), &ReconManager::queryReconStatus);
connect(ReconManager::getInstance(), &ReconManager::queryReconStateResponsed, this, &DeviceManager::processReconQueryScanState);
connect(ReconManager::getInstance(), &ReconManager::restartCreatReconRecord, this, &DeviceManager::startCreateReconRecord);
connect(ReconManager::getInstance(), &ReconManager::checkReconConnectionResponsed, this, &DeviceManager::updateReconConnectionState);
mReconHttpThread->start();
mTemperatureTimer = startTimer(GET_TEMPERATURE_TIME);
//init dms status--------------------make a function future
if(JsonObject::Instance()->isDmsSimulator())
{
//set simulator
mSetSimulatorModeAction->setSendData("{ \"code\":0, \"info\":\"1\"}");
mSetSimulatorModeAction->execute();
}
mSetHeartBeatAction->setSendData("{ \"code\":0, \"info\":\"0\"}");
mSetHeartBeatAction->execute();
mSoftwareVersion = "DMS Version Loading";
mGetSoftwareVersionAction->execute();
mCheckInitStatusTimer = startTimer(500);
}
void DeviceManager::initGUI(bool aIsInitSucceed)
{
if(!AppGlobalValues::DBconnected().toBool())
{
emitErrorCallback(tr("Fail to connect to DB!Reboot device to try!"));
emit initializeFinished();
return;
}
if(aIsInitSucceed)
{
if(getDeviceStatus() != DeviceStatus::Rready)
{
mStopScanAction->execute();
}
if(!getCEStatus() && startCEScan())
{
mIsInitializing = true;
mScanProgressTimer = startTimer(500);
}
else
{
emit initializeProgress("33");
QThread::msleep(500);
emit initializeProgress("66");
QThread::msleep(500);
emit initializeProgress("100");
emit initializeFinished();
}
}
else
{
UsctStateManager::getInstance()->setState(DmsState, false);
QString msg = tr("Initialize Failed.");
THROW_ERROR(msg);
emit initializeProgress("33");
QThread::msleep(500);
emit initializeProgress("66");
QThread::msleep(500);
emit initializeProgress("100");
emit initializeFinished();
}
initEmptyScanMeasurementID();
//process expired patient list
QDate date = QDate::currentDate().addDays(-JsonObject::Instance()->getPatientListExpireDays());
SQLHelper::exec(QString("DELETE FROM Patient WHERE AddDate <= %1").arg(date.toString("yyyy-MM-dd")));
//process expired scan list
date = QDate::currentDate().addDays(-JsonObject::Instance()->getScanListExpireDays());
SQLHelper::exec(QString("DELETE FROM Scan WHERE ScanDateTime <= \"%1\"").arg(date.toString("yyyy-MM-dd")));
}
void DeviceManager::processInitializeProgress(const QString& aProgress)
{
if(!mIsInitializing)
{
return;
}
QJsonObject jsonObj = toJsonObject(aProgress);
int code = jsonObj["code"].toInt();
QString msg = jsonObj["info"].toString();
switch (code)
{
case 1:
//emit initializeProgress(msg);
break;
case 2:
emit initializeProgress(msg);
break;
case 3:
prepareFinishInitialize();
emit initializeFinished();
break;
case -1:
prepareFinishInitialize();
THROW_ERROR(msg);
break;
default:
break;
}
}
bool DeviceManager::hasValidEmptyScan()
{
return !mCurrentEmptyMeasurementID.isEmpty();
}
void DeviceManager::startScan(const QString& json, bool empty)
{
DeviceStatus inf = getDeviceStatus();
if(inf == DeviceStatus::Unkonw)
{
return;
}
if (inf != DeviceStatus::Rready)
{
QString errMsg(empty ? tr("Device is not ready, start empty scan operation failed!") : tr("Device is not ready, start scan operation failed!"));
THROW_ERROR(errMsg);
TRIGGER_EVENT(StopScanProcess, nullptr, nullptr);
return;
}
AppGlobalValues::setEmptyScanFlag(empty);
if (startFullScan(json))
{
QString msg = "Start scan...";
TRIGGER_EVENT(GUIEvents::InvokeOperationStart, nullptr, (QObject*)&msg);
mIsScanning = true;
mIsEmptyScan = empty;
QJsonObject patientInfo = QJsonDocument::fromJson(json.toUtf8()).object()["Patient Info"].toObject();
mCurrentPatientID = patientInfo["PatientID"].toString();
mCurrentAccessionNumber = patientInfo["AccessionNumber"].toString();
mCurrentPatientName = patientInfo["PatientName"].toString();
mCurrentLaterality = patientInfo["Laterality"].toString();
mCurrentOperatorName = patientInfo["OperatorName"].toString();
mCurrentMPPSUID = patientInfo["MPPSUID"].toString();
mCurrentModality = patientInfo["Modality"].toString();
mCurrentStudyUID = patientInfo["StudyUID"].toString();
mScanProgressTimer = startTimer(500);
}
}
void DeviceManager::processScanProgress(const QString& aProgress)
{
if(mIsScanning == false)
{
return;
}
QJsonObject jsonObj = toJsonObject(aProgress);
if(!jsonObj.contains("code") || !jsonObj.contains("info"))
{
prepareFinishScan(false);
return;
}
int code = jsonObj["code"].toInt();
QString msg = jsonObj["info"].toString();
switch (code)
{
case 1:
{
QVariant var(tr("progress:%1%").arg(msg));
TRIGGER_EVENT(InvokeOperationProgress, nullptr, (QObject *) &var);
break;
}
case 2:
{
QVariant var;
if(mIsEmptyScan)
{
var = QVariant(tr("progress:%1%").arg(msg));
}
else
{
ScanProcessSequence::getInstance()->fullScanDataExport();
var = QVariant(tr("Patient can leave.\nprogress:%1%").arg(msg));
}
TRIGGER_EVENT(InvokeOperationProgress, nullptr, (QObject *) &var);
break;
}
case 3:
{
QVariant var( tr("Data quality assessment in progress\nprogress:99%"));
TRIGGER_EVENT(InvokeOperationProgress, nullptr, (QObject *) &var);
break;
}
case 4:
checkDataQuality();
break;
default:
prepareFinishScan(false, msg);
break;
}
}
void DeviceManager::prepareFinishScan(bool isNormalFinish, const QString& aReason)
{
if(!mIsScanning)
{
return;
}
if(mScanProgressTimer != -1)
{
killTimer(mScanProgressTimer);
mScanProgressTimer = -1;
}
mIsScanning = false;
QString message = aReason;
QObject* var = message.isEmpty() ? nullptr : (QObject*)&message;
bool isCompleteNotify = JsonObject::Instance()->getCompleteNotify();
if(!isNormalFinish)
{
if(!mIsEmptyScan)
{
TRIGGER_EVENT(StopScanProcess, nullptr, nullptr);
}
TRIGGER_EVENT(InvokeOperationEnd, nullptr, var);
return;
}
if(mIsEmptyScan)
{
insertEmptyScanRecord();
TRIGGER_EVENT(EmptyScanFinished, nullptr, nullptr);
}
else
{
insertScanRecord();
}
startTransfer();
if(isCompleteNotify)
{
QString msg = ScanProcessSequence::getInstance()->getScanPositionSize() == 2 ? tr("Scan completed! Please prepare for the next scan. \nAfter lying down, click the confirm button"
"to start scanning on the next side.") : tr("Scan completed!") ;
TRIGGER_EVENT(InvokeOperationEnd, nullptr, (QObject *)&msg);
}
else
{
TRIGGER_EVENT(InvokeOperationEnd, nullptr, var);
}
if(!mIsEmptyScan)
{
ScanProcessSequence::getInstance()->popPosition();
startAutoLocate();
}
}
void DeviceManager::prepareFinishInitialize()
{
mIsInitializing = false;
if(mScanProgressTimer != -1)
{
killTimer(mScanProgressTimer);
mScanProgressTimer = -1;
}
}
void DeviceManager::stopFullScan()
{
// DeviceStatus inf = getDeviceStatus();
// if (inf != DeviceStatus::Scanning)
// {
// return;
// }
DmsSyncActionResult result = mStopScanAction->execute();
if(!result.mIsSucessful)
{
prepareFinishScan(false, "");
THROW_ERROR(result.mData);
return;
}
prepareFinishScan(false, "");
}
void DeviceManager::stopPreviewScan()
{
DeviceStatus inf = getDeviceStatus();
if (inf == DeviceStatus::Unkonw)
{
return;
}
DmsSyncActionResult result = mStopScanAction->execute();
if(!result.mIsSucessful)
{
THROW_ERROR(result.mData);
return;
}
TRIGGER_EVENT(ResponseStopPreview, nullptr, nullptr);
mIsPreviewing = false;
AppGlobalValues::setInProcessing(false);
}
void DeviceManager::close()
{
}
void DeviceManager::processPreviewData(const QString& aPreviewData)
{
if(!mIsPreviewing)
{
return;
}
QJsonObject jsonObj = toJsonObject(aPreviewData);
if(!jsonObj.contains("code") || jsonObj["code"].toInt() != 0)
{
return;
}
QString path = jsonObj["info"].toString();
QFile file(path);
if (!file.open(QIODevice::ReadOnly))
{
qDebug() << "Preview file path error. Path : " + path;
return;
}
QByteArray data = file.readAll();
QByteArray bytes = QByteArray::fromRawData(data, PREVIEW_IMAGE_WH * PREVIEW_IMAGE_WH);
TRIGGER_EVENT(ResponsePreviewData, nullptr, (QObject *) (&bytes));
}
void DeviceManager::startPreview()
{
DeviceStatus status = getDeviceStatus();
if(status == DeviceStatus::Unkonw)
{
emit startPreviewScanResult(false);
return;
}
if (status != DeviceStatus::Rready)
{
emit startPreviewScanResult(false);
QString msg(status != DeviceStatus::Rready ? "Can't start preview,Device is not ready!" : "Start preview operation fail!");
THROW_ERROR(msg);
return;
}
DmsSyncActionResult result = mPreviewScanAction->execute();
if(!result.mIsSucessful)
{
emit startPreviewScanResult(false);
THROW_ERROR(result.mData);
return;
}
QJsonObject jsonObj = toJsonObject(result.mData);
if(!jsonObj.contains("code") || jsonObj["code"].toInt() !=0)
{
emit startPreviewScanResult(false);
QString msg = jsonObj.contains("info") ? jsonObj["info"].toString() : DEFAULT_DMS_START_FAILED;
THROW_ERROR(msg);
return;
}
AppGlobalValues::setInProcessing(true);
mIsPreviewing = true;
emit startPreviewScanResult(true);
TRIGGER_EVENT(ResponsePreview, nullptr, nullptr);
}
void DeviceManager::checkInitStatus()
{
DmsSyncActionResult result = mCheckInitStatusAction->execute();
if(!result.mIsSucessful)
{
if(mCheckInitStatusTimer != -1)
{
killTimer(mCheckInitStatusTimer);
mCheckInitStatusTimer = -1;
}
initGUI(false);
return;
}
QJsonObject jsonObj = toJsonObject(result.mData);
if(jsonObj["code"].toInt() == 1)
{
if(mCheckInitStatusTimer != -1)
{
killTimer(mCheckInitStatusTimer);
mCheckInitStatusTimer = -1;
}
initGUI(true);
}
else if(jsonObj["code"].toInt() == 2)
{
if(mCheckInitStatusTimer != -1)
{
killTimer(mCheckInitStatusTimer);
mCheckInitStatusTimer = -1;
}
initGUI(false);
}
}
void DeviceManager::timerEvent(QTimerEvent* event)
{
if(event->timerId() == mScanProgressTimer)
{
getScanProcess();
return QObject::timerEvent(event);
}
if(event->timerId() == mGetAutoLocatePositionTimer)
{
getAutoLocatePosition();
return QObject::timerEvent(event);
}
if(event->timerId() == mCheckInitStatusTimer)
{
checkInitStatus();
return QObject::timerEvent(event);
}
if (event->timerId() == mTemperatureTimer)
{
getDeviceTemperature();
return QObject::timerEvent(event);
}
}
void DeviceManager::emitErrorCallback(const QString& msg)
{
emit raiseGlobalError(msg);
}
void DeviceManager::emitInfoCallback(const QString& aMessage,const unsigned int aInfoType)
{
emit raiseGlobalInfo(QPair<QString,unsigned int>(aMessage,aInfoType));
}
QString DeviceManager::getSoftwareVersion()
{
return mSoftwareVersion;
}
void DeviceManager::processReceiveDMSInfoResult(int aServerID, int aActionID, const QString& aContents)
{
qDebug()<<"processReceiveDMSInfoResult " <<aServerID << aActionID << aContents;
LOG_SYS_OPERATION(QString("DMS -> GUI : %1-%2, Message:%3").arg(aServerID).arg(aActionID).arg(aContents));
switch(aServerID)
{
case USRV_SCAN :
switch(aActionID)
{
case ACT_SCAN_STATUS :
emit responseGetDeviceStatus(aContents);
break;
case ACT_SCAN_FULLSCAN :
emit responseFullScan(aContents);
break;
case ACT_SCAN_PREVIEW:
emit responsePreviewScan(aContents);
break;
case ACT_SCAN_TEMP :
emit responseGetDeviceTemperature(aContents);
processDeviceTemperature(aContents);
break;
case ACT_SCAN_PROGRESS_PASSIVE :
emit responseGetScanProgress(aContents);
if(mIsInitializing)
{
processInitializeProgress(aContents);
}
else
{
processScanProgress(aContents);
}
break;
case ACT_SCAN_PRESIG:
processPreviewData(aContents);
break;
case ACT_SCAN_STOP :
emit responseStopScan(aContents);
break;
case ACT_SCAN_CE :
emit responseCEScan(aContents);
break;
case ACT_SCAN_CE_STATUS :
emit responseGetCEStatus(aContents);
break;
case ACT_SCAN_SIMULATOR:
emit responseSetSimulatorMode(aContents);
break;
case ACT_SCAN_IMGQUALITI:
emit responseCheckDataQuality(aContents);
default:
break;
}
break;
case USRV_LOGALARM :
switch (aActionID)
{
case ACT_LOGALM_RPT :
processAlarm(aContents);
break;
default:
break;
}
break;
case USRV_XFR :
switch(aActionID)
{
case ACT_XFR_START :
emit responseTransfer(aContents);
break;
case ACT_XFR_STOP :
emit responseStopTransfer(aContents);
break;
case ACT_XFR_PROGRESS_PASSIVE :
emit responseGetTransferProgress(aContents);
break;
case ACT_XFR_PROGRESS_ACTIVE :
processTransferProgress(aContents);
break;
}
break;
case USRV_INFOCFG:
switch(aActionID)
{
case ACT_IFCFG_VERINFO :
emit responseGetSoftwareVersion(aContents);
processGetSoftwareVersion(aContents);
break;
case ACT_IFCFG_HBCFG :
emit responseSetHeartBeat(aContents);
break;
case ACT_IFCFG_INIT_STATUS :
emit responseCheckInitStatus(aContents);
break;
}
break;
case USRV_CONTROL:
switch(aActionID)
{
case ACT_CTL_PUMP:
emit responsePumpControl(aContents);
processPumpResult(aContents);
break;
case ACT_CTL_PWRDOWN:
emit responseShutDown(aContents);
processShutDownDms(aContents);
break;
case ACT_CTL_MOTION_START:
emit responseStartAutoLocate(aContents);
break;
case ACT_CTL_MOTION_STOP:
emit responseStopAutoLocate(aContents);
break;
case ACT_CTL_MOTION_POSITION:
emit responseGetAutoLocatePosition(aContents);
processAutoLocatePosition(aContents);
break;
case ACT_CTL_EMG_RESET:
processEmergencyButtonReset(aContents);
break;
}
break;
default:
break;
}
}
void DeviceManager::processAlarm(const QString& aAlarm)
{
QJsonObject jsonObj = toJsonObject(aAlarm);
int alarmCode = jsonObj["code"].toInt();
QString alarm = tr("Error: ") + QString::number(alarmCode) + AlarmHelper::getAlarmString(alarmCode);
qDebug()<<"processAlarm : "<<alarmCode;
if(alarmCode >= 400 && alarmCode < 500)
{
switch (alarmCode)
{
case 492://left emergency button pushed
prepareFinishScan(false,"");
emit emergencyButtonPushed(true, false);
return;
case 494://right emergency button pushed
prepareFinishScan(false,"");
emit emergencyButtonPushed(false, false);
return;
default:
break;
}
if(mIsScanning)
{
prepareFinishScan(false, alarm);
}
else
{
THROW_ERROR(alarm);
}
}
else if(alarmCode >= 500 && alarmCode < 600)
{
emitInfoCallback(alarm, MessageLevel::Warning);
}
else if(alarmCode >= 600 && alarmCode < 700)
{
emitInfoCallback(alarm, MessageLevel::Info);
}
}
void DeviceManager::processGetSoftwareVersion(const QString& aSoftwareVersion)
{
QJsonObject jsonObj = toJsonObject(aSoftwareVersion);
if(jsonObj["code"].toInt() != 0)
{
mSoftwareVersion = "DMS Version Fetch Error";
}
mSoftwareVersion = jsonObj["info"].toString();
emit getDmsVersionResponsed(mSoftwareVersion);
}
void DeviceManager::scanTimeout()
{
prepareFinishScan(false, tr("DMS connection error"));
}
DeviceStatus DeviceManager::getDeviceStatus()
{
DmsSyncActionResult result = mGetDeviceStatusAction->execute();
if(!result.mIsSucessful)
{
QString message = tr("DMS connection error");
THROW_ERROR(message);
return DeviceStatus::Unkonw;
}
QJsonObject jsonObj = toJsonObject(result.mData);
if(!jsonObj.contains("code") || jsonObj["code"].toInt() != 0)
{
return DeviceStatus::Error;
}
int status = jsonObj["info"].toString().toInt();
switch (status)
{
case 0 : return DeviceStatus::Busy;
case 1 : return DeviceStatus::Rready;
case 2 : return DeviceStatus::Scanning;
case 3 : return DeviceStatus::Error;
default: return DeviceStatus::Error;
}
}
bool DeviceManager::startFullScan(const QString& aPatientInfo)
{
mFullScanAction->setSendData(aPatientInfo);
DmsSyncActionResult result = mFullScanAction->execute();
if(!result.mIsSucessful)
{
QString message = tr("Start scan failed. Reason:time out.");
THROW_ERROR(message);
LOG_SYS_OPERATION("Start full scan failed. " + message);
TRIGGER_EVENT(StopScanProcess, nullptr, nullptr);
return false;
}
QJsonObject jsonObj = toJsonObject(result.mData);
int code = jsonObj["code"].toInt();
if(code != 0)
{
QString msg = tr("Start scan failed. Reason:%1").arg(jsonObj["info"].toString()) + AlarmHelper::getAlarmString(code);
LOG_SYS_OPERATION("Start full scan failed. " + msg);
THROW_ERROR(msg);
TRIGGER_EVENT(StopScanProcess, nullptr, nullptr);
return false;
}
mCurrentScanMeasurementID = jsonObj["measurement id"].toString();
return true;
}
bool DeviceManager::startCEScan()
{
DmsSyncActionResult result = mCEScanAction->execute();
if(!result.mIsSucessful)
{
QString message = tr("Initialize Failed.");
THROW_ERROR(message);
return false;
}
QJsonObject jsonObj = toJsonObject(result.mData);
if(jsonObj.contains("code") && jsonObj["code"].toInt() != 0)
{
QString msg = tr("Initialize Failed.");
THROW_ERROR(msg);
msg = tr("Start CE Scan Failed.");
EventCenter::Default()->triggerEvent(WarningMessageRaise, nullptr, (QObject*)&msg);
return false;
}
return true;
}
void DeviceManager::getDeviceTemperature()
{
mGetDeviceTemperatureAction->execute();
}
void DeviceManager::processDeviceTemperature(const QString& aResponseTemperature)
{
QJsonObject jsonObj = toJsonObject(aResponseTemperature);
if(jsonObj["code"].toInt() != 0)
{
return;
}
QString temp = jsonObj["info"].toString();
TRIGGER_EVENT(GUIEvents::ResponseDeviceTemperature, nullptr, (QObject *) &temp);
}
void DeviceManager::getScanProcess()
{
mGetScanProgressAction->execute();
}
void DeviceManager::shutdownDms()
{
if(mIsTransfering)
{
QString msg = tr("Data is currently being transmitted, please shut down later.");
THROW_ERROR(msg);
return;
}
if(!mShutDownAction->execute())
{
QString msg = tr("Shut down failed, please push emergency button to shutdown.");
THROW_ERROR(msg);
return;
}
AppGlobalValues::setInProcessing(true);
emit shutdownDmsSended();
}
void DeviceManager::processShutDownDms(const QString& aResponse)
{
QJsonObject jsonObj = toJsonObject(aResponse);
if(jsonObj.contains("code") && jsonObj["code"].toInt() == 0)
{
shutdownOperationSystem();
return;
}
AppGlobalValues::setInProcessing(false);
emit shutdownDmsFailed();
}
void DeviceManager::shutdownOperationSystem()
{
qDebug()<< "shut down OS";
QProcess::startDetached("shutdown", QStringList() << "-h" << "now");
}
void DeviceManager::insertEmptyScanRecord()
{
QString sql = QString("INSERT INTO EScan (ScanID, ScanDateTime, State) VALUES ('%1','%2',%3)")
.arg(mCurrentScanMeasurementID)
.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"))
.arg(0);
if(!SQLHelper::exec(sql))
{
QString msg = "DB Error. G401";
THROW_ERROR(msg);
return;
}
mCurrentEmptyMeasurementID = mCurrentScanMeasurementID;
}
void DeviceManager::insertScanRecord()
{
QString sql = QString("INSERT INTO Scan (ScanID, ReferenceID, PatientID, AccessionNumber, PatientName, ScanDateTime, Laterality, OperatorName, State, StudyUID, Modality, MPPSUID) VALUES ('%1','%2','%3','%4','%5','%6','%7','%8', %9, '%10', '%11', '%12')")
.arg(mCurrentScanMeasurementID)
.arg(mCurrentEmptyMeasurementID)
.arg(mCurrentPatientID)
.arg(mCurrentAccessionNumber)
.arg(mCurrentPatientName)
.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"))
.arg(mCurrentLaterality)
.arg(mCurrentOperatorName)
.arg(0)
.arg(mCurrentStudyUID)
.arg(mCurrentModality)
.arg(mCurrentMPPSUID);
if(!SQLHelper::exec(sql))
{
QString msg = "DB Error. G401";
THROW_ERROR(msg);
}
}
void DeviceManager::startTransfer()
{
if(mIsTransfering)
{
return;
}
QString sql = "SELECT ScanID FROM %1 WHERE State<200 ORDER BY ScanDateTime ASC LIMIT 1";
QString table = "EScan";
QVariant sqlResult = SQLHelper::queryValue(sql.arg(table));
mIsTransferEmptyScan = true;
if(sqlResult.isNull())
{
mIsTransferEmptyScan = false;
table = "Scan";
sqlResult = SQLHelper::queryValue(sql.arg(table));
if(sqlResult.isNull())
{
return;
}
}
QString scanID = sqlResult.toString();
auto host = JsonObject::Instance()->getServer(JsonObject::RECON);
mTransferAction->setSendData("{\"MD5\":1, \"dst\":\"" + host.ae + "@" + host.ip +":" + mReconTransferPath + "\", \"src\":\"" + scanID + "\",\"delete\":1,\"active report\":0}");
DmsSyncActionResult result = mTransferAction->execute();
if(!result.mIsSucessful)
{
QString msg = tr("Scan data transfer failed.");
emitInfoCallback(msg, MessageLevel::Error);
return;
}
QJsonObject jsonObj = toJsonObject(result.mData);
int code = jsonObj["code"].toInt();
if(code != 0)
{
mStopTransferAction->execute();
QString msg = tr("Scan data transfer failed.");
emitInfoCallback(msg, MessageLevel::Error);
return;
}
mIsTransfering = true;
mCurrentTransferMeasurementID = scanID;
mCurrentTransferPatientID = mIsTransferEmptyScan ? "" : SQLHelper::queryValue(QString("SELECT PatientID FROM %1 WHERE ScanID = '%2'").arg(table).arg(scanID)).toString();
sql = QString("UPDATE %1 set State = 100 where ScanID = '%2'")
.arg(mIsTransferEmptyScan ? "EScan" : "Scan")
.arg(mCurrentTransferMeasurementID);
if(!SQLHelper::exec(sql))
{
QString msg = "DB Error. Code:G501";
emitInfoCallback(msg, MessageLevel::Error);
}
else
{
updateTransferState();
}
}
void DeviceManager::processTransferProgress(const QString& aProgress)
{
if(!mIsTransfering)
{
return;
}
QJsonObject jsonObj = toJsonObject(aProgress);
int code = jsonObj["code"].toInt();
QString msg = jsonObj["info"].toString();
switch (code)
{
case 1:
{
break;
}
case 2:
{
QString sql = QString("UPDATE %1 set State = 200 where ScanID = '%2'")
.arg(mIsTransferEmptyScan ? "EScan" : "Scan")
.arg(mCurrentTransferMeasurementID);
mIsTransfering = false;
mTransferProgress = 0;
mCurrentTransferMeasurementID.clear();
if(!SQLHelper::exec(sql))
{
QString msg = "DB Error. Code:G502";
emitInfoCallback(msg, MessageLevel::Error);
break;
}
emitInfoCallback(tr("Scan data transfer Succeeded!"), MessageLevel::Sucess);
updateTransferState();
if(ReconManager::getInstance()->isConnected())
{
startCreateReconRecord();
}
startTransfer();
break;
}
default:
QString sql = QString("UPDATE %1 set State = 104 where ScanID = '%2'")
.arg(mIsTransferEmptyScan ? "EScan" : "Scan")
.arg(mCurrentTransferMeasurementID);
mIsTransfering = false;
mTransferProgress = 0;
mCurrentTransferMeasurementID.clear();
if(!SQLHelper::exec(sql))
{
QString msg = "DB Error. Code:G503";
emitInfoCallback(msg, MessageLevel::Error);
break;
}
QString message = tr("Scan data transfer failed.");
emitInfoCallback(message, MessageLevel::Error);
updateTransferState();
break;
}
}
void DeviceManager::processReconCreateEmptyScan(bool aResult, const QString& aScanID, const QString& aMessage, bool aIsConnectSucceed)
{
if(aResult)
{
UsctStateManager::getInstance()->setEmptyScanUpdateFlag(false);
QString sql = QString("UPDATE EScan set State = 300 where ScanID = '%1'").arg(aScanID);
if(!SQLHelper::exec(sql))
{
QString msg = "DB Error. Code:G504";
emitInfoCallback(msg, MessageLevel::Error);
}
EventCenter::Default()->triggerEvent(EmptyScanDataStateUpdated, nullptr, nullptr);
return;
}
emitInfoCallback(tr("Create empty scan data failed"), MessageLevel::Error);
QString sql = QString("UPDATE EScan set State = %1 where ScanID = '%2'").arg(aIsConnectSucceed ? "304" : "204").arg(aScanID);
if(!SQLHelper::exec(sql))
{
QString msg = "DB Error. Code:G505";
emitInfoCallback(msg, MessageLevel::Error);
}
EventCenter::Default()->triggerEvent(EmptyScanDataStateUpdated, nullptr, nullptr);
}
void DeviceManager::processReconCreateScan(bool aResult, const QString& aScanID, const QString& aMessage, bool aIsConnectSucceed)
{
if(aResult)
{
QString sql = QString("UPDATE Scan set State = 300 where ScanID = '%1'").arg(aScanID);
if(!SQLHelper::exec(sql))
{
QString msg = "DB Error. Code:G504";
emitInfoCallback(msg, MessageLevel::Error);
}
return;
}
emitInfoCallback(tr("Create scan data failed"), MessageLevel::Error);
QString sql = QString("UPDATE Scan set State = %1 where ScanID = '%2'").arg(aIsConnectSucceed ? "304" : "204").arg(aScanID);
if(!SQLHelper::exec(sql))
{
QString msg = "DB Error. Code:G505";
emitInfoCallback(msg, MessageLevel::Error);
}
}
void DeviceManager::processReconQueryScanState(bool aResult, const QVariant& aState)
{
if(!aResult)
{
emitInfoCallback(aState.toString(), MessageLevel::Error);
return;
}
QMap<QString, int> states = aState.value<QMap<QString, int>>();
for(auto itor= states.constBegin(); itor != states.constEnd(); ++itor)
{
QString sql = QString("UPDATE Scan set State = %1 where ScanID = '%2'").arg(itor.value()).arg(itor.key());
if(!SQLHelper::exec(sql))
{
QString msg = "DB Error. Code:G506";
emitInfoCallback(msg, MessageLevel::Error);
}
}
emit updateReconStateFinished();
}
void DeviceManager::startCreateReconRecord()
{
QString sql = "SELECT ScanID FROM EScan WHERE State < 300 And State >= 200 ORDER BY ScanDateTime ASC";
auto result = SQLHelper::queryValues(sql);
for (const QVariant &variant : result)
{
QString scanid = variant.value<QList<QVariant>>()[0].toString();
emit createEmptyScanToRecon(scanid, mReconTransferPath + "/" + scanid);
}
sql = "SELECT ScanID, ReferenceID, PatientID, AccessionNumber, StudyUID, MPPSUID FROM Scan WHERE State < 300 And State >= 200 ORDER BY ScanDateTime ASC";
result = SQLHelper::queryValues(sql);
for (const QVariant &variant : result)
{
QList<QVariant> record = variant.value<QList<QVariant>>();
QString scanID = record[0].toString();
QString referenceID = record[1].toString();
QString patientID = record[2].toString();
QString AccessionNumber = record[3].toString();
QString studyUID = record[4].toString();
QString mppsUID = record[5].toString();
emit createScanToRecon(scanID, mppsUID, referenceID, mReconTransferPath + "/" + scanID);
}
startTransfer();
}
void DeviceManager::initEmptyScanMeasurementID()
{
QString sql = "SELECT ScanID FROM EScan ORDER BY ScanDateTime DESC LIMIT 1";
mCurrentEmptyMeasurementID = SQLHelper::queryValue(sql).toString();
}
void DeviceManager::updateReconState()
{
if(!ReconManager::getInstance()->isConnected())
{
emitInfoCallback(tr("Recon disconnected."), MessageLevel::Error);
return;
}
QString sql = "SELECT ScanID FROM Scan WHERE State < 999 And State >= 300 And State != 304";
auto result = SQLHelper::queryValues(sql);
QStringList scanIDs;
for (const QVariant &variant : result)
{
scanIDs << variant.value<QList<QVariant>>()[0].toString();
}
if(scanIDs.isEmpty())
{
emit updateReconStateFinished();
return;
}
emit queryScanStatusToRecon(scanIDs);
}
bool DeviceManager::updateTransferProgress()
{
if(!mIsTransfering)
{
return false;
}
mTransferProgress = 0;
auto result = mGetTransferProgressAction->execute();
QJsonObject jsonObj = toJsonObject(result.mData);
if(jsonObj["code"].toInt() == 1 )
{
mTransferProgress = jsonObj["info"].toString().toInt();
return true;
}
return false;
}
void DeviceManager::updateTransferState()
{
if(mIsTransferEmptyScan)
{
EventCenter::Default()->triggerEvent(EmptyScanDataStateUpdated, nullptr, nullptr);
}
else
{
emit transferStatusUpdated();
}
}
int DeviceManager::getTransferProgress()
{
return mTransferProgress;
}
bool DeviceManager::getCEStatus()
{
auto result = mGetCEStatusAction->execute();
if(result.mIsSucessful)
{
QJsonObject jsonObj = toJsonObject(result.mData);
if(jsonObj["code"].toInt() == 0 )
{
if(jsonObj["info"].toString().toInt() == 0)
{
return false;
}
}
}
return true;
}
void DeviceManager::controlDrainage(const QString& aCode)
{
mPumpControlAction->setSendData(QString("{\"valve\":%1}").arg(aCode));
if(!mPumpControlAction->execute())
{
emit startPumpControlResult(false);
QString msg = tr("Open pump failed.");
THROW_ERROR(msg);
}
}
void DeviceManager::processPumpResult(const QString& aResponse)
{
QJsonObject jsonObj = toJsonObject(aResponse);
if(jsonObj["code"].toInt() == 0 )
{
emit startPumpControlResult(true);
return;
}
emit startPumpControlResult(false);
QString msg = tr("Open pump failed.");
THROW_ERROR(msg);
}
void DeviceManager::updateReconConnectionState(bool aIsConnected)
{
EventCenter::Default()->triggerEvent(ReconConnectionUpdated, nullptr, (QObject*)&aIsConnected);
}
void DeviceManager::startScanProcess()
{
LOG_SYS_OPERATION("Start scan process.");
if( !JsonObject::Instance()->getScanCanWithoutRecon() &&
(!UsctStateManager::getInstance()->getState(ReconConnectionState) ||
!UsctStateManager::getInstance()->getState(ReconState) ||
!UsctStateManager::getInstance()->getState(ReconDBState)))
{
QString errorMessage = tr("Recon error, can't start scan process");
LOG_SYS_OPERATION(errorMessage)
TRIGGER_EVENT(StopScanProcess, nullptr, nullptr);
THROW_ERROR(errorMessage);
return;
}
AppGlobalValues::setInProcessing(true);
mIsScanning = true;
startAutoLocate();
}
void DeviceManager::stopScanProcess()
{
AppGlobalValues::setInProcessing(false);
mIsScanning = false;
LOG_SYS_OPERATION("Stop scan process.")
stopAutoLocate();
}
bool DeviceManager::startAutoLocate()
{
if(ScanProcessSequence::getInstance()->getScanPositionSize() == 0)
{
TRIGGER_EVENT(StopScanProcess, nullptr, nullptr);
return false;
}
auto result = mStartAutoLocateAction->execute();
if(result.mIsSucessful)
{
mIsAutoLocating = true;
QJsonObject jsonObj = toJsonObject(result.mData);
if(jsonObj["code"].toInt() == 0 )
{
emit startAutoLocateResult(true);
mEffectivePositionCount = 0;
mGetAutoLocatePositionTimer = startTimer(1000);
return true;
}
}
emit startAutoLocateResult(false);
TRIGGER_EVENT(StopScanProcess, nullptr, nullptr);
QString errorMessage = tr("Start auto locate failed") + AlarmHelper::getAlarmString(toJsonObject(result.mData)["info"].toInt());
THROW_ERROR(errorMessage)
LOG_SYS_OPERATION("Start auto locate failed.")
return false;
}
void DeviceManager::stopAutoLocate()
{
if(mIsAutoLocating)
{
mStopAutoLocateAction->execute();
mIsAutoLocating = false;
}
if(mGetAutoLocatePositionTimer != -1)
{
killTimer(mGetAutoLocatePositionTimer);
mGetAutoLocatePositionTimer = -1;
}
}
void DeviceManager::getAutoLocatePosition()
{
mGetAutoLocatePositionAction->execute();
}
void DeviceManager::processAutoLocatePosition(const QString& aProgress)
{
QJsonObject jsonObj = toJsonObject(aProgress);
int code = jsonObj["code"].toInt();
int x = jsonObj["x"].toInt();
int y = jsonObj["y"].toInt();
int z = jsonObj["z"].toInt();
if(code == 0)
{
if(qSqrt(x*x + y*y)<EFFECTIVE_POSITION_RADIUS && z > EFFECTIVE_POSITION_Z_START && z< EFFECTIVE_POSITION_Z_END)
{
if(++mEffectivePositionCount >= 5)
{
mEffectivePositionCount = 0;
stopAutoLocate();
emit autolocatePositionEffective();
}
}
else
{
mEffectivePositionCount = 0;;
}
emit updateAutoLocatePosition(x, y, z);
}
else
{
TRIGGER_EVENT(StopScanProcess, nullptr, nullptr);
QString errorMessage = tr("Start auto locate failed");
THROW_ERROR(errorMessage);
}
}
void DeviceManager::checkDataQuality()
{
auto result = mCheckDataQualityAction->execute();
if(result.mIsSucessful)
{
QJsonObject jsonObj = toJsonObject(result.mData);
if(jsonObj["qualities"].toInt() == 1 )
{
LOG_SYS_OPERATION("Check data quality succeed. Data quality is good.")
prepareFinishScan(true);
return;
}
else
{
LOG_SYS_OPERATION("Check data quality succeed. Data quality is bad.")
QString errorMessage = tr("The data quality is low, please restart the data scan.") + jsonObj["info"].toString();
prepareFinishScan(false, errorMessage);
TRIGGER_EVENT(StopScanProcess, nullptr, nullptr);
return;
}
}
QString errorMessage = tr("DMS connection error");
prepareFinishScan(false, errorMessage);
TRIGGER_EVENT(StopScanProcess, nullptr, nullptr);
LOG_SYS_OPERATION("Check data quality failed. " + errorMessage)
return;
}
void DeviceManager::prepareCheckReconConnection()
{
if(AppGlobalValues::InProcessing().toBool())
{
return;
}
emit checkReconConnection();
}
void DeviceManager::processEmergencyButtonReset(const QString& aResponse)
{
QJsonObject jsonObj = toJsonObject(aResponse);
int code = jsonObj["code"].toInt();
if(code == -1)
{
QString errorMessage = tr("Device reset failed, please contact maintenance person");
THROW_ERROR(errorMessage);
}
if(jsonObj["info"].toString() == "left" )
{
emit emergencyButtonPushed(true, true);
return;
}
if(jsonObj["info"].toString() == "right" )
{
emit emergencyButtonPushed(false, true);
return;
}
}
void DeviceManager::prepareEmergencyReset()
{
mEmergencyResetAction->execute();
}