Index: denali.pro =================================================================== diff -u -r06d10ee1174f0947a01087554f3da3109b47aef6 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- denali.pro (.../denali.pro) (revision 06d10ee1174f0947a01087554f3da3109b47aef6) +++ denali.pro (.../denali.pro) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -40,6 +40,7 @@ sources/model/dg/data \ sources/view \ sources/view/hd/adjustment \ + sources/view/hd/alarm \ sources/view/hd/data \ sources/view/dg/data @@ -54,11 +55,11 @@ sources/model/MDGDebugText.h \ sources/model/MHDDebugText.h \ sources/storage/DriveWatcher.h \ - sources/threads.h \ - sources/maintimer.h \ - sources/applicationpost.h \ + sources/Threads.h \ + sources/MainTimer.h \ + sources/ApplicationPost.h \ \ # Controllers - sources/applicationcontroller.h \ + sources/ApplicationController.h \ \ # ---------- Models ---------- sources/model/MModel.h \ sources/model/MAbstract.h \ @@ -95,42 +96,42 @@ sources/model/dg/data/MDGTemperaturesData.h \ sources/model/dg/data/MDGValvesStatesData.h \ \ # CANBus - sources/canbus/caninterface.h \ - sources/canbus/frameinterface.h \ + sources/canbus/CanInterface.h \ + sources/canbus/FrameInterface.h \ \ # Denali Message - sources/canbus/messageglobals.h \ - sources/canbus/messageacknowmodel.h \ - sources/canbus/messagebuilder.h \ - sources/canbus/messageinterpreter.h \ - sources/canbus/messagedispatcher.h \ + sources/canbus/MessageGlobals.h \ + sources/canbus/MessageAcknowModel.h \ + sources/canbus/MessageBuilder.h \ + sources/canbus/MessageInterpreter.h \ + sources/canbus/MessageDispatcher.h \ \ # Gui - sources/gui/guiglobals.h \ - sources/gui/guiview.h \ - sources/gui/guicontroller.h \ + sources/gui/GuiGlobals.h \ + sources/gui/GuiView.h \ + sources/gui/GuiController.h \ \ # ---------- Views ---------- sources/view/VEventSpy.h \ - sources/view/hd/data/VHDTreatmentStatesData.h \ - sources/view/vview.h \ - sources/view/vpoweroff.h \ + sources/view/VView.h \ + sources/view/VPowerOff.h \ \ # ---------- Views - Alarm - sources/view/valarmstatus.h \ + sources/view/hd/alarm/VAlarmStatus.h \ \ # ---------- Views - HD - Adjustment - In-Treatment - sources/view/vtreatmentadjustmentresponsebase.h \ - sources/view/vtreatmentadjustmentduration.h \ - sources/view/vtreatmentadjustmentflows.h \ - sources/view/vtreatmentadjustmentultrafiltrationstate.h \ - sources/view/vtreatmentadjustmentultrafiltrationedit.h \ - sources/view/vtreatmentadjustmentultrafiltrationconfirm.h \ + sources/view/hd/adjustment/VTreatmentAdjustmentResponseBase.h \ + sources/view/hd/adjustment/VTreatmentAdjustmentDuration.h \ + sources/view/hd/adjustment/VTreatmentAdjustmentFlows.h \ + sources/view/hd/adjustment/VTreatmentAdjustmentUltrafiltrationState.h \ + sources/view/hd/adjustment/VTreatmentAdjustmentUltrafiltrationEdit.h \ + sources/view/hd/adjustment/VTreatmentAdjustmentUltrafiltrationConfirm.h \ sources/view/hd/adjustment/VTreatmentAdjustmentSaline.h \ \ # ---------- Views - HD - Data - sources/view/vtreatmenttime.h \ - sources/view/vtreatmentbloodflow.h \ - sources/view/vtreatmentdialysateflow.h \ - sources/view/vtreatmentultrafiltration.h \ - sources/view/vtreatmentranges.h \ - sources/view/vtreatmentpressureocclusion.h \ + sources/view/hd/data/VTreatmentTime.h \ + sources/view/hd/data/VTreatmentBloodFlow.h \ + sources/view/hd/data/VTreatmentDialysateFlow.h \ + sources/view/hd/data/VTreatmentUltrafiltration.h \ + sources/view/hd/data/VTreatmentRanges.h \ + sources/view/hd/data/VTreatmentPressureOcclusion.h \ sources/view/hd/data/VHDOperationModeData.h \ sources/view/hd/data/VTreatmentSalineData.h \ + sources/view/hd/data/VHDTreatmentStatesData.h \ \ # ---------- Views - DG - Data sources/view/dg/data/VDGDrainPumpData.h \ sources/view/dg/data/VDGHeatersData.h \ @@ -142,9 +143,9 @@ sources/view/dg/data/VDGTemperaturesData.h \ sources/view/dg/data/VDGValvesStatesData.h \ \ # Storage - sources/storage/storageglobals.h \ - sources/storage/filehandler.h \ - sources/storage/logger.h \ + sources/storage/StorageGlobals.h \ + sources/storage/Logger.h \ + sources/storage/FileHandler.h \ \ # Utility sources/utility/crc.h \ sources/utility/format.h \ @@ -157,14 +158,11 @@ \ # common \ # Main main.cpp \ - sources/model/MDGDebugText.cpp \ - sources/model/MHDDebugText.cpp \ - sources/storage/DriveWatcher.cpp \ - sources/threads.cpp \ - sources/maintimer.cpp \ - sources/applicationpost.cpp \ + sources/Threads.cpp \ + sources/MainTimer.cpp \ + sources/ApplicationPost.cpp \ \ # Controllers - sources/applicationcontroller.cpp \ + sources/ApplicationController.cpp \ \ # ---------- Models ---------- sources/model/MAbstract.cpp \ sources/model/MPowerOff.cpp \ @@ -180,6 +178,7 @@ sources/model/hd/adjustment/MTreatmentAdjustUltrafiltrationConfirmResponse.cpp \ sources/model/hd/adjustment/MTreatmentAdjustSalineResponse.cpp \ \ # ---------- Models - HD - Data + sources/model/MHDDebugText.cpp \ sources/model/hd/data/MTreatmentTimeData.cpp \ sources/model/hd/data/MTreatmentFlowsData.cpp \ sources/model/hd/data/MTreatmentOutletFlowData.cpp \ @@ -189,6 +188,7 @@ sources/model/hd/data/MHDOperationModeData.cpp \ sources/model/hd/data/MTreatmentSalineData.cpp \ \ # ---------- Models - DG - Data + sources/model/MDGDebugText.cpp \ sources/model/dg/data/MDGDrainPumpData.cpp \ sources/model/dg/data/MDGHeatersData.cpp \ sources/model/dg/data/MDGLoadCellReadingsData.cpp \ @@ -199,40 +199,40 @@ sources/model/dg/data/MDGTemperaturesData.cpp \ sources/model/dg/data/MDGValvesStatesData.cpp \ \ # CANBus - sources/canbus/caninterface.cpp \ - sources/canbus/frameinterface.cpp \ + sources/canbus/CanInterface.cpp \ + sources/canbus/FrameInterface.cpp \ \ # Denali Message - sources/canbus/messageacknowmodel.cpp \ - sources/canbus/messagebuilder.cpp \ - sources/canbus/messagedispatcher.cpp \ - sources/canbus/messageinterpreter.cpp \ + sources/canbus/MessageAcknowModel.cpp \ + sources/canbus/MessageBuilder.cpp \ + sources/canbus/MessageDispatcher.cpp \ + sources/canbus/MessageInterpreter.cpp \ \ # Gui - sources/gui/guiglobals.cpp \ - sources/gui/guiview.cpp \ - sources/gui/guicontroller.cpp \ + sources/gui/GuiGlobals.cpp \ + sources/gui/GuiView.cpp \ + sources/gui/GuiController.cpp \ \ # ---------- Views ---------- sources/view/VEventSpy.cpp \ - sources/view/hd/data/VHDTreatmentStatesData.cpp \ - sources/view/vpoweroff.cpp \ + sources/view/VPowerOff.cpp \ \ # ---------- Views - Alarm - sources/view/valarmstatus.cpp \ + sources/view/hd/alarm/VAlarmStatus.cpp \ \ # ---------- Views - HD - Adjustment - In-Treatment - sources/view/vtreatmentadjustmentresponsebase.cpp \ - sources/view/vtreatmentadjustmentduration.cpp \ - sources/view/vtreatmentadjustmentflows.cpp \ - sources/view/vtreatmentadjustmentultrafiltrationstate.cpp \ - sources/view/vtreatmentadjustmentultrafiltrationedit.cpp \ - sources/view/vtreatmentadjustmentultrafiltrationconfirm.cpp \ + sources/view/hd/adjustment/VTreatmentAdjustmentResponseBase.cpp \ + sources/view/hd/adjustment/VTreatmentAdjustmentDuration.cpp \ + sources/view/hd/adjustment/VTreatmentAdjustmentFlows.cpp \ + sources/view/hd/adjustment/VTreatmentAdjustmentUltrafiltrationConfirm.cpp \ + sources/view/hd/adjustment/VTreatmentAdjustmentUltrafiltrationEdit.cpp \ + sources/view/hd/adjustment/VTreatmentAdjustmentUltrafiltrationState.cpp \ sources/view/hd/adjustment/VTreatmentAdjustmentSaline.cpp \ \ # ---------- Views - HD - Data - sources/view/vtreatmenttime.cpp \ - sources/view/vtreatmentbloodflow.cpp \ - sources/view/vtreatmentdialysateflow.cpp \ - sources/view/vtreatmentultrafiltration.cpp \ - sources/view/vtreatmentranges.cpp \ - sources/view/vtreatmentpressureocclusion.cpp \ + sources/view/hd/data/VTreatmentTime.cpp \ + sources/view/hd/data/VTreatmentBloodFlow.cpp \ + sources/view/hd/data/VTreatmentDialysateFlow.cpp \ + sources/view/hd/data/VTreatmentUltrafiltration.cpp \ + sources/view/hd/data/VTreatmentRanges.cpp \ + sources/view/hd/data/VTreatmentPressureOcclusion.cpp \ sources/view/hd/data/VHDOperationModeData.cpp \ sources/view/hd/data/VTreatmentSalineData.cpp \ + sources/view/hd/data/VHDTreatmentStatesData.cpp \ \ # ---------- Views - DG - Data sources/view/dg/data/VDGDrainPumpData.cpp \ sources/view/dg/data/VDGHeatersData.cpp \ @@ -244,9 +244,10 @@ sources/view/dg/data/VDGTemperaturesData.cpp \ sources/view/dg/data/VDGValvesStatesData.cpp \ \ # Storage - sources/storage/storageglobals.cpp \ - sources/storage/filehandler.cpp \ - sources/storage/logger.cpp \ + sources/storage/StorageGlobals.cpp \ + sources/storage/FileHandler.cpp \ + sources/storage/Logger.cpp \ + sources/storage/DriveWatcher.cpp \ \ # Utility sources/utility/crc.cpp \ sources/utility/format.cpp \ Index: denali.pro.user =================================================================== diff -u -r4df19fe88c454bd54abcdaf983be59464c5ef5bc -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- denali.pro.user (.../denali.pro.user) (revision 4df19fe88c454bd54abcdaf983be59464c5ef5bc) +++ denali.pro.user (.../denali.pro.user) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -1,6 +1,6 @@ - + EnvironmentId @@ -1187,7 +1187,7 @@ Qt 5.12.5 (iMX8) Qt 5.12.5 (iMX8) {5d6458ef-f917-4aef-a092-c77bbe106149} - 0 + 1 0 0 Index: main.cpp =================================================================== diff -u -r61d776c2405c22848f1182cba903477d44e7163f -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- main.cpp (.../main.cpp) (revision 61d776c2405c22848f1182cba903477d44e7163f) +++ main.cpp (.../main.cpp) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -31,16 +31,16 @@ #include // Project -#include "maintimer.h" -#include "caninterface.h" -#include "frameinterface.h" -#include "messageacknowmodel.h" -#include "messagedispatcher.h" -#include "applicationcontroller.h" -#include "guicontroller.h" -#include "logger.h" +#include "MainTimer.h" +#include "CanInterface.h" +#include "FrameInterface.h" +#include "MessageAcknowModel.h" +#include "MessageDispatcher.h" +#include "ApplicationController.h" +#include "GuiController.h" +#include "Logger.h" #include "DriveWatcher.h" -#include "threads.h" +#include "Threads.h" // kernel #include Index: sources/ApplicationController.cpp =================================================================== diff -u --- sources/ApplicationController.cpp (revision 0) +++ sources/ApplicationController.cpp (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,426 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file ApplicationController.cpp + * \author (last) Peter Lucia + * \date (last) 25-Jun-2020 + * \author (original) Behrouz NematiPour + * \date (original) 24-Sep-2019 + * + */ +#include "ApplicationController.h" + +// Qt + +// Project +#include "MainTimer.h" +#include "MessageDispatcher.h" +#include "Logger.h" +#include "DriveWatcher.h" +#include "FileHandler.h" +#include "GuiController.h" + +/*! + * \brief ApplicationController::ApplicationController + * \details Constructor + * \param parent - QObject parent owner object. + * Qt handles the children destruction by their parent objects life-cycle. + */ +ApplicationController::ApplicationController(QObject *parent) : QObject(parent) +{ + _applicationPost = new ApplicationPost(this); +} + +/*! + * \brief ApplicationController initializer + */ +bool ApplicationController::init() +{ + if ( _init ) return false; + _init = true; + + initConnections(); + // coco begin validated: The class ApplicationPost has not been implemented Yet. + if (!_applicationPost->init()) return false; + // coco end + LOG_EVENT("UI," + tr("%1 Initialized").arg(metaObject()->className())); + + return true; +} + +/*! + * \brief ApplicationController::init + * \details Initialized the Class by calling the init() method first + * And initializes the thread vThread by calling initThread + * on success init(). + * \param vThread - the thread + * \return returns the return value of the init() method + */ +bool ApplicationController::init(QThread &vThread) +{ + if ( ! init() ) return false; + initThread(vThread); + return true; +} + +/*! + * \brief ApplicationController::quit + * \details quits the class + * Calls quitThread + */ +void ApplicationController::quit() +{ + // coco begin validated: Application termination is not correctly done in coco!!! + // it has been tested and works perfectly fine in normal run. + quitThread(); // validated +} +// coco end + +/*! + * \brief ApplicationController::initConnections + * \details Initializes the required signal/slot connection between this class and other objects + * to be able to communicate. + */ +void ApplicationController::initConnections() +{ + connect(&_MainTimer , SIGNAL( didTimeout()), + this , SLOT(onMainTimerTimeout())); + + // From GUI + connect(&_GuiController , SIGNAL(didActionTransmit(GuiActionType, const QVariantList &)), + this , SLOT( onActionTransmit(GuiActionType, const QVariantList &))); + + // From HD/DG + connect(&_MessageDispatcher, SIGNAL(didActionReceive(GuiActionType, const QVariantList &)), + this , SLOT( onActionReceive(GuiActionType, const QVariantList &))); + + connect(&_MessageDispatcher, SIGNAL(didFailedTransmit(Sequence)), + this , SLOT( onFailedTransmit(Sequence))); + + // USB drive + connect(&_GuiController , SIGNAL(didUSBDriveUmount()), + this , SLOT( onUSBDriveUmount())); + connect(&_DriveWatcher , SIGNAL(didUSBDriveMount ()), + this , SLOT( onUSBDriveMount ())); + connect(&_DriveWatcher , SIGNAL(didUSBDriveRemove()), + this , SLOT( onUSBDriveRemove())); + + // SD Card + connect(&_DriveWatcher , SIGNAL(didSDCardStateChange(bool, bool)), + this , SLOT( onSDCardStateChange(bool, bool))); + + + connect(&_GuiController , SIGNAL(didExportLog()), + this , SLOT( onExportLog())); + + connect(&_Logger , SIGNAL(didExportLogs()), + this , SLOT( onExport())); + + // ---- Signal/Slots + ADJUST_TRANSMT_MODEL_BRIDGE_CONNECTIONS(_GuiController ) + ACTION_RECEIVE_MODEL_BRIDGE_CONNECTIONS(_MessageDispatcher) +} + +/*! + * \brief ApplicationController::initThread + * \details Moves this object into the thread vThread. + * And checks that this method is called from main thread. + * Also connects quitThread to application aboutToQuit. + * \param vThread - the thread + */ +void ApplicationController::initThread(QThread &vThread) +{ + // runs in main thread + Q_ASSERT_X(QThread::currentThread() == qApp->thread() , __func__, "The Class initialization must be done in Main Thread" ); + _thread = &vThread; + _thread->setObjectName(QString("%1_Thread").arg(metaObject()->className())); + connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(quit())); + _thread->start(); + moveToThread(_thread); +} + +/*! + * \brief ApplicationController::quitThread + * \details Moves this object to main thread to be handled by QApplicaiton + * And to be destroyed there. + */ +void ApplicationController::quitThread() +{ + // coco begin validated: Application termination is not correctly done in coco!!! + // it has been tested and works perfectly fine in normal run. + + if ( ! _thread ) return; + + // runs in thread + moveToThread(qApp->thread()); // validated +} +// coco end + +/*! + * \brief ApplicationController::onFailedTransmit + * Called when we failed to get a response back from the HD + * \param seq - The sequence that failed to send to the HD. + */ +void ApplicationController::onFailedTransmit(Sequence seq) +{ + emit didFailedTransmit(seq); +} + +/*! + * \brief Process the requested action + * \details Processes the requested action + * \param vAction - User requested Action + * \param vData - Action data to be transmitted. + */ +void ApplicationController::onActionTransmit(GuiActionType vAction, const QVariantList &vData) +{ + emit didActionTransmit(vAction, vData); +} + +/*! + * \brief An action has been confirmed + * \details GUI requested an action. + * In response HD confirmed the action. + * \param vAction + * \param vData + */ +void ApplicationController::onActionReceive (GuiActionType vAction, const QVariantList &vData) +{ + emit didActionReceive (vAction, vData); +} + +/*! + * \brief ApplicationController::onMainTimerTimeout + * \details This slot is called by MainTimer::didTimeout each second + * to call required methods like keepAlive + */ +void ApplicationController::onMainTimerTimeout() +{ + keepAlive(); +} + +/*! + * \brief ApplicationController::onUSBDriveMount + * \details This is the slot which connects to the _DriveWatcher didUSBDriveMount signal + * and notifies the other classes (GuiController) by emitting its signal didUSBDriveMount + */ +void ApplicationController::onUSBDriveMount () +{ + // coco begin validated: This needs user interaction to plug-in USB device + // has been tested manually + emit didUSBDriveMount(); +} +// coco end + +/*! + * \brief ApplicationController::onUSBDriveRemove + * \details This is the slot which connects to the _GuiController didUSBDriveUmount signal + * and notifies the other classes (DriveWatcher) by emitting its signal didUSBDriveUmount + */ +void ApplicationController::onUSBDriveUmount() +{ + // coco begin validated: This needs user interaction to plug-in USB device + // has been tested manually + emit didUSBDriveUmount(); +} +// coco end + +/*! + * \brief ApplicationController::onUSBDriveRemove + * \details This is the slot which connects to the _DriveWatcher didUSBDriveRemove signal + * and notifies the other classes (GuiController) by emitting its signal didUSBDriveRemove + */ +void ApplicationController::onUSBDriveRemove() +{ + // coco begin validated: This needs user interaction to plug-in USB device + // has been tested manually + emit didUSBDriveRemove(); +} +// coco end + +/*! + * \brief ApplicationController::onSDCardStateChange + * \details This is the slot which connects to the _DriveWatcher didSDCardStateChange signal + * and notifies the other classes (GuiController) by emitting its signal didSDCardStateChange + * \param vIsReady - SDCard is Ready + * \param vIsReadOnly - SDCard is ReadOnly + */ +void ApplicationController::onSDCardStateChange(bool vIsReady, bool vIsReadOnly) +{ + // coco begin validated: This needs user interaction to plug-in SD Card + // has been tested manually + emit didSDCardStateChange(vIsReady, vIsReadOnly); +} +// coco end + +/*! + * \brief ApplicationController::onExportLog + * \details the slot which will be called by UI to so the log export. + */ +void ApplicationController::onExportLog() +{ + // coco begin validated: This needs user interaction to plug-in USB device + // has been tested manually + LOG_EXPORT; +} +// coco end + +/*! + * \brief ApplicationController::onExport + * \details the slot which will be called by logger is done exporting. + */ +void ApplicationController::onExport() +{ + // coco begin validated: This needs user interaction to plug-in USB device + // has been tested manually + emit didExport(); +} +// coco end + +/*! + * \brief ApplicationController::keepAlive + * \details This is the message which has to be send over the CANBus + * as an monitor for other nodes on the bus to notify UI is alive + */ +void ApplicationController::keepAlive() +{ +#ifndef DISABLE_KEEP_ALIVE + QVariantList mData; + int mFakeDataLen = gFakeData.length(); + // coco begin validated: This is a fake data generator for CANBus missing/swapped frames Testing + // will never be executed on the product + // has been tested manually + if (mFakeDataLen) { + if (gFakeSeqAtBegin) { + createFakeSeqAtBeginLongMessage(mData, mFakeDataLen); + } else { + createFakeSequencedLongMessage (mData, mFakeDataLen); + } + } + // coco end + else { + mData += static_cast(GuiActionData::NoData); + } + onActionTransmit(GuiActionType::ID_KeepAlive, mData); +#endif +} + +/*! + * \brief ApplicationController::createFakeSequencedLongMessage + * \details This method is creating the fake message with frame sequence + * which we use for Denali Message test + * \param vFakeDataLen + */ +void ApplicationController::createFakeSequencedLongMessage(QVariantList &vData, const int vFakeDataLen) +{ + // coco begin validated: This is a fake data generator for CANBus missing/swapped frames Testing + // will never be executed on the product + // has been tested manually + QByteArray data; + if (vFakeDataLen == 1 && gFakeData == QByteArray::fromHex(gFakeData_default)) { + static quint16 txCount = 0; + Types::U16 seq; + quint8 dataBytesLeft = 0; + const quint8 crcBytesLen = 2; + for (int i = 0; i < 13; i++) { + switch (i) { + case 0: // First frame : HEAD + seq.value = txCount; + data += seq.bytes[0]; + data += seq.bytes[1]; + break; + + case 12: // Last frame with CRC + dataBytesLeft = 8 - sizeof(seq) - crcBytesLen; + for (int j = 0; j < dataBytesLeft; j++) { + data += (char)(0); + } + seq.value = txCount; + data += seq.bytes[0]; + data += seq.bytes[1]; + break; + + default: // Middle Frames + dataBytesLeft = 8 - sizeof(seq); + for (int j = 0; j < dataBytesLeft; j++) { + data += (char)(0); + } + seq.value = txCount; + data += seq.bytes[0]; + data += seq.bytes[1]; + break; + + } + Types::safeIncrement(txCount); + } + vData += QByteArray::fromHex(data.toHex()); + } else { + vData += gFakeData; + } +} +// coco end + +/*! + * \brief ApplicationController::createFakeSequencedAtBeginLongMessage + * \details This method is creating the fake message with frame sequence + * which we use for Denali Message test + * \param vFakeDataLen + */ +void ApplicationController::createFakeSeqAtBeginLongMessage(QVariantList &vData, const int vFakeDataLen) +{ + // coco begin validated: This is a fake data generator for CANBus missing/swapped frames Testing + // will never be executed on the product + // has been tested manually + QByteArray data; + if (vFakeDataLen == 1 && gFakeData == QByteArray::fromHex(gFakeData_default)) { + static quint32 txCount = 0; + Types::U32 seq; + quint8 dataBytesLeft = 0; + const quint8 crcBytesLen = 2; + for (int i = 0; i < 13; i++) { + switch (i) { + case 0: // First frame : HEAD + seq.value = txCount; + data += seq.bytes[0]; + data += seq.bytes[1]; + //data += seq.bytes[3]; // Chopped off + //data += seq.bytes[4]; // Chopped off + break; + + case 12: // Last frame with CRC + seq.value = txCount; + data += seq.bytes[0]; + data += seq.bytes[1]; + data += seq.bytes[2]; + data += seq.bytes[3]; + dataBytesLeft = 8 - sizeof(seq) - crcBytesLen; + for (int j = 0; j < dataBytesLeft; j++) { + data += (char)(0); + } + break; + + default: // Middle Frames + dataBytesLeft = 8 - sizeof(seq); + seq.value = txCount; + data += seq.bytes[0]; + data += seq.bytes[1]; + data += seq.bytes[2]; + data += seq.bytes[3]; + for (int j = 0; j < dataBytesLeft; j++) { + data += (char)(0); + } + break; + + } + Types::safeIncrement(txCount); + } + vData += QByteArray::fromHex(data.toHex()); + } else { + vData += gFakeData; + } +} +// coco end Index: sources/ApplicationController.h =================================================================== diff -u --- sources/ApplicationController.h (revision 0) +++ sources/ApplicationController.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,106 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file ApplicationController.h + * \author (last) Peter Lucia + * \date (last) 25-Jun-2020 + * \author (original) Behrouz NematiPour + * \date (original) 24-Sep-2019 + * + */ +#pragma once + +// Qt +#include + +// Project +#include "main.h" +#include "GuiGlobals.h" +#include "ApplicationPost.h" +#include "MModel.h" +#include "MessageGlobals.h" + +// define +#define _ApplicationController ApplicationController::I() + +// forward declarations +class tst_initializations; + +// namespace +using namespace Gui; +using namespace Can; + +class ApplicationController : public QObject +{ + Q_OBJECT + + // friends + friend class ::tst_initializations; + + ApplicationPost *_applicationPost = nullptr; + + QThread *_thread = nullptr; + bool _init = false; + +// Singleton +SINGLETON(ApplicationController); + +public slots: + bool init(); + bool init(QThread &vThread); + +private slots: + void quit(); + +private: + void initConnections(); + + void initThread(QThread &vThread); + void quitThread(); + + void keepAlive(); + + void createFakeSequencedLongMessage (QVariantList &vData, const int vFakeDataLen); + void createFakeSeqAtBeginLongMessage(QVariantList &vData, const int vFakeDataLen); + +private slots: // Should be private for thread safety and is connected internally. + void onActionReceive (GuiActionType vAction, const QVariantList &vData); // UI <= HD/DG + void onActionTransmit(GuiActionType vAction, const QVariantList &vData); // UI => HD/DG + + void onMainTimerTimeout(); + + void onUSBDriveMount (); + void onUSBDriveUmount(); + void onUSBDriveRemove(); + + void onSDCardStateChange(bool vIsReady, bool vIsReadOnly); + + void onExportLog (); + void onExport (); + + void onFailedTransmit(Sequence seq); + +signals: + void didActionReceive (GuiActionType vAction, const QVariantList &vData); // UI <= HD/DG + void didActionTransmit(GuiActionType vAction, const QVariantList &vData); // UI => HD/DG + + void didUSBDriveMount (); + void didUSBDriveUmount(); + void didUSBDriveRemove(); + + void didSDCardStateChange(bool vIsReady, bool vIsReadOnly); + + void didExport (); + + void didAdjustBloodDialysateFlows(quint32 vBloodFlow, quint32 vDialysateFlow); + void didAdjustDuration(quint32 vDuration); + void didFailedTransmit(Sequence seq); + + // ---- Signal/Slots + ADJUST_TRANSMT_MODEL_BRIDGE_DEFINITIONS + ACTION_RECEIVE_MODEL_BRIDGE_DEFINITIONS +}; Index: sources/ApplicationPost.cpp =================================================================== diff -u --- sources/ApplicationPost.cpp (revision 0) +++ sources/ApplicationPost.cpp (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,38 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file ApplicationPost.cpp + * \author (last) Behrouz NematiPour + * \date (last) 13-Apr-2020 + * \author (original) Behrouz NematiPour + * \date (original) 24-Sep-2019 + * + */ +#include "ApplicationPost.h" + +/*! + * \brief ApplicationPost::ApplicationPost + * \details Constructor + * \param parent - QObject parent owner object. + * Qt handles the children destruction by their parent objects life-cycle. + */ +ApplicationPost::ApplicationPost(QObject *parent) : QObject(parent) +{ + +} + +bool ApplicationPost::init() +{ + return true; +} + +bool ApplicationPost::start() +{ + // coco begin validated: Is a placeholder and has not been implemented yet + return true; +} +// coco end Index: sources/ApplicationPost.h =================================================================== diff -u --- sources/ApplicationPost.h (revision 0) +++ sources/ApplicationPost.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,30 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file ApplicationPost.h + * \author (last) Behrouz NematiPour + * \date (last) 21-Oct-2019 + * \author (original) Behrouz NematiPour + * \date (original) 24-Sep-2019 + * + */ +#pragma once + +#include + +class ApplicationPost : public QObject +{ + Q_OBJECT +public: + explicit ApplicationPost(QObject *parent = nullptr); + bool init(); + bool start(); + +signals: + +public slots: +}; Index: sources/MainTimer.cpp =================================================================== diff -u --- sources/MainTimer.cpp (revision 0) +++ sources/MainTimer.cpp (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,125 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file maintimer.cpp + * \author (last) Behrouz NematiPour + * \date (last) 13-Apr-2020 + * \author (original) Behrouz NematiPour + * \date (original) 24-Sep-2019 + * + */ +#include "MainTimer.h" + +//Qt +#include + +//Project +#include "Logger.h" +#include "FileHandler.h" + +/*! + * \brief MainTimer::MainTimer + * \details Constructor + * \param parent - QObject parent owner object. + * Qt handles the children destruction by their parent objects life-cycle. + */ +MainTimer::MainTimer(QObject *parent) : QObject(parent) { } + +/*! + * \brief MainTimer::init + * \details starts the timer ans sets the timer interval + * \return + */ +bool MainTimer::init() +{ + // coco begin validated: This is a fake data generator for CANBus missing/swapped frames Testing + // will never be executed on the product + // has been tested manually + if (gFakeInterval) { + startTimer(gFakeInterval); + } + // coco end + else { + startTimer(_interval); + } + LOG_EVENT("UI," + tr("Main Timer Initialized")); + return true; +} + +/*! + * \brief MainTimer::quit + * \details Does nothing for now + */ +void MainTimer::quit() { } + +/*! + * \brief MainTimer::isDateChanged + * \details Checks the date has been changed + * \return true if date changed. + */ +bool MainTimer::isDateChanged(bool vIncludeTime) +{ + // old date // current date + static int oy,om,od; int cy,cm,cd; + // old time // current time + static int oH,oM,oS; int cH,cM,cS; + + QDateTime::currentDateTime().date().getDate(&cy, &cm, &cd); + // coco begin validated: Decided to not to check each second + // has been tested manually + if (vIncludeTime) { + QTime currentTime = QDateTime::currentDateTime().time(); + cH = currentTime.hour(); + cM = currentTime.minute(); + cS = currentTime.second(); + } + + if (oy == cy && om == cm && od == cd) { + if (vIncludeTime) { + if (oH == cH && oM == cM && oS == cS) { + return false; + } + else { + // date + oy = cy; + om = cm; + od = cd; + // time + oH = cH; + oM = cM; + oS = cS; + } + // coco end + } + else + return false; + } + else { + oy = cy; + om = cm; + od = cd; + } + return true; +} + +/*! + * \brief MainTimer::timerEvent + * \details This event handler has been re-implemented in here + * to receive timer events for the object + * for the timer which has been set to _checkInterval + * Emits the didTimeout signal on each interval. + */ +void MainTimer::timerEvent(QTimerEvent *) +{ + emit didTimeout(); + // I'm not sure how often we need to check for this. + // if it needs to be checked each second pass true + // if it needs to be checked each day pass false + if (isDateChanged(false)) { + emit didDateChange(); + } +} Index: sources/MainTimer.h =================================================================== diff -u --- sources/MainTimer.h (revision 0) +++ sources/MainTimer.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,50 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file maintimer.h + * \author (last) Behrouz NematiPour + * \date (last) 15-Jan-2020 + * \author (original) Behrouz NematiPour + * \date (original) 24-Sep-2019 + * + */ +#pragma once + +// Qt +#include + +// Project +#include "main.h" + +// Define +#define _MainTimer MainTimer::I() + +/*! + * \brief The MainTimer class + * \details This class is going to be used for subjects which want to keep track of time to a second resolution. + */ +class MainTimer : public QObject +{ + Q_OBJECT + + static const int _interval = 1000; //ms + +// Singleton +SINGLETON(MainTimer); +public: + bool init(); + void quit(); + +private: + bool isDateChanged(bool vIncludeTime = false); +signals: + void didTimeout(); + void didDateChange(); + +protected: + void timerEvent(QTimerEvent *) override; +}; Index: sources/Threads.cpp =================================================================== diff -u --- sources/Threads.cpp (revision 0) +++ sources/Threads.cpp (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,97 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file threads.cpp + * \author (last) Behrouz NematiPour + * \date (last) 07-May-2020 + * \author (original) Behrouz NematiPour + * \date (original) 07-Jan-2020 + * + */ +#include "Threads.h" + +// Qt +#include +#include + +// Application +#include "MessageGlobals.h" +#include "Logger.h" + +/*! + * \details All the Thread has been and shall be defined in here + * And will be assigned to a required class from main thread. + * \note quitThreads() needs to be called when the application execution event loop is done + * this has currently been done in main.cpp in main() after the qpp.exe() is done. + */ +namespace Threads { + QThread _CanFrame_Thread ; + QThread _CanAcknow_Thread ; + QThread _CanMessage_Thread ; + QThread _DriveWatcher_Thread ; + QThread _Logger_Thread ; + QThread _Application_Thread ; + + /*! + * \brief registerTypes + * \details this method has to be called before any class which uses these types + * and also is handled by threads + * It seems qt is using the meta objects for threading signal/slots + * and it requires any type which has been used in this context to be registered. + */ + void registerTypes() + { + // Logger : This is required for Signal/Slots in threading. + qRegisterMetaType("LogType"); + + // CanInterface : This is required for Signal/Slots in threading. + qRegisterMetaType("QCanBusFrame"); + + // FrameInterface : This is required for Signal/Slots in threading. + qRegisterMetaType("Can_Id"); + + // MessageAcknowModel : This is required for Signal/Slots in threading. + qRegisterMetaType("Sequence"); + + // MessageAcknowModel : This is required for Signal/Slots in threading. + qRegisterMetaType("FrameList"); + } + + /*! + * \brief quitThread + * \details quits the thread vThread and wait for it to be destroyed. + * \param vThread - the thread + */ + void quitThread(QThread &vThread) + { + // coco begin validated: Application termination is not correctly done in coco!!! + // it has been tested and works perfectly fine in normal run. + // runs in main thread + vThread.quit(); // validated + vThread.wait(); // validated + } + // coco end + + /*! + * \brief quitThreads + * \details quits the list of the threads which has been defined + * int the Threads namespace + * \note It requires to be updated by developer if any more thread has been added + */ + void quitThreads() + { + // coco begin validated: Application termination is not correctly done in coco!!! + // it has been tested and works perfectly fine in normal run. + quitThread(_CanFrame_Thread ); // validated + quitThread(_CanAcknow_Thread ); // validated + quitThread(_CanMessage_Thread ); // validated + quitThread(_DriveWatcher_Thread ); // validated + quitThread(_Logger_Thread ); // validated + quitThread(_Application_Thread ); // validated + } + // coco end +} Index: sources/Threads.h =================================================================== diff -u --- sources/Threads.h (revision 0) +++ sources/Threads.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,41 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file threads.h + * \author (last) Behrouz NematiPour + * \date (last) 07-May-2020 + * \author (original) Behrouz NematiPour + * \date (original) 07-Jan-2020 + * + */ +#pragma once + +// Qt +#include +#include + +// Application +#define PRINT_THREAD_NAME_ENABLE 1 +#if (PRINT_THREAD_NAME_ENABLE) + #define PRINT_THREAD_NAME qDebug() << __func__ << QThread::currentThread()->objectName() +#else + #define PRINT_THREAD_NAME +#endif + +namespace Threads { + extern QThread _CanFrame_Thread ; + extern QThread _CanAcknow_Thread ; + extern QThread _CanMessage_Thread ; + extern QThread _DriveWatcher_Thread ; + extern QThread _Logger_Thread ; + extern QThread _Application_Thread ; + + void registerTypes(); + void quitThread (QThread &vThread); + void quitThreads(); +} + Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/abstract/singleton.h'. Fisheye: No comparison available. Pass `N' to diff? Index: sources/abstract/singleton.h._ =================================================================== diff -u --- sources/abstract/singleton.h._ (revision 0) +++ sources/abstract/singleton.h._ (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,96 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file singleton.h + * \author (last) Behrouz NematiPour + * \date (last) 02-Jan-2020 + * \author (original) Behrouz NematiPour + * \date (original) 02-Jan-2020 + * + */ +#pragma once + +// Qt +#include +#include +#include +#include +// Project + + +#define SINGLETON(vCLASS) \ +private: \ + explicit vCLASS(QObject *parent = nullptr); \ + vCLASS(vCLASS const &); \ + vCLASS & operator = (vCLASS const &) = delete; \ +public: \ + static vCLASS &I() { \ + static vCLASS _instance; \ + return _instance; \ + } + + +class Singleton : public QObject +{ + Q_OBJECT + + static QVector _threads; + + Singleton (Singleton const &); + Singleton & operator = (Singleton const &) = delete; + +protected: + bool _initialized = false; + + explicit Singleton(QObject *parent = nullptr) : QObject(parent) {} + virtual ~Singleton() { + _quit_(); + } + + static Singleton &I() { + static Singleton _instance; + return _instance; + } + + void initThread(QThread *vThread) { + qDebug() << this->metaObject()->className(); + if (! vThread) return; + vThread->setObjectName(QString("%1_Thread").arg(this->metaObject()->className())); + moveToThread(vThread); + QObject::connect(qApp, &QApplication::aboutToQuit, vThread, [vThread]() { + vThread->quit(); + vThread->wait(); + }); + QObject::connect(vThread, &QThread::finished, this, [this](){ + moveToThread(qApp->thread()); + }); + vThread->start(); + } + + virtual bool _init_() { + return true; + + } + + virtual void _quit_() { + _initialized = false; + } + + virtual void initConnections() { + + } + +public: + virtual bool init(QThread *thread = nullptr) final { + _init_(); + initConnections(); + initThread(thread); + _initialized = true; + return true; + } +}; + Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/applicationcontroller.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/applicationcontroller.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/applicationpost.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/applicationpost.h'. Fisheye: No comparison available. Pass `N' to diff? Index: sources/canbus/CanInterface.cpp =================================================================== diff -u --- sources/canbus/CanInterface.cpp (revision 0) +++ sources/canbus/CanInterface.cpp (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,435 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file CanInterface.cpp + * \author (last) Behrouz NematiPour + * \date (last) 07-May-2020 + * \author (original) Behrouz NematiPour + * \date (original) 28-Oct-2019 + * + */ +#include "CanInterface.h" + +// Qt +#include +#include + +// stl +#include + +// Project +#include "Logger.h" +#include "MessageGlobals.h" +#include "FrameInterface.h" + +// namespace +using namespace Can; + +/*! + * \brief CanInterface::CanInterface + * \details Constructor + * \param parent - QObject parent owner object. + * Qt handles the children destruction by their parent objects life-cycle. + */ +CanInterface::CanInterface(QObject *parent) : QObject(parent) { } + +/*! + * \brief CanInterface Initialization + * \details Initializes the CANBUS and checks if can be connected + * \return true if connected, false otherwise + */ +bool CanInterface::init() +{ + if ( _init ) return false; + _init = true; + + // coco begin validated: Manually tested since required to disable and enable the CANBus + if ( ! initDevice() ) return false; + // coco end + if ( ! testDevice() ) return false; + + initConnections(); + + status(tr("Connected")); + QString logMessage = QString("UI,%1,%2") + .arg(tr("%1 Initialized").arg(metaObject()->className())) + .arg(status()); + LOG_EVENT(logMessage); + + return true; +} + +/*! + * \brief CanInterface::init + * \details Initialized the Class by calling the init() method first + * And initializes the thread vThread by calling initThread + * on success init(). + * \param vThread - the thread + * \return returns the return value of the init() method + */ +bool CanInterface::init(QThread &vThread) +{ + // coco begin validated: Manually tested since required to disable and enable the CANBus + if ( ! init() ) return false; + // coco end + initThread(vThread); + return true; +} + +/*! + * \brief CanInterface quit + * \details quits the class + * Calls quitThread + */ +void CanInterface::quit() +{ + // coco begin validated: Application termination is not correctly done in coco!!! + // it has been tested and works perfectly fine in normal run. + quitThread(); // verified +} +// coco end + +/*! + * \brief CanInterface status + * \details CanInterface status description + * \return The current stores status + */ +QString CanInterface::status() const +{ + return _canStatus; +} + +/*! + * \brief CanInterface::enableConsoleOut + * \details Enable or Disables the console output and logs the status + * \param vEnabled - Enable console output if true + */ +void CanInterface::enableConsoleOut(bool vEnabled) { + // coco begin validated: This code meant to be used only for debugging and tested manually + if (_enableConsoleOut == vEnabled) return; + _enableConsoleOut = vEnabled; + if (_enableConsoleOut) { + LOG_DEBUG("Console out CanInterface enabled"); + } else { + LOG_DEBUG("Console out CanInterface disabled"); + } +} +// coco end + +/*! + * \brief CanInterface connections definition + * \details Initializes the required signal/slot connection between this class and other objects + * to be able to communicate. + */ +void CanInterface::initConnections() +{ + // coco begin validated: Manually tested since required to disable and enable the CANBus + if (_canDevice) { + // coco end + connect(_canDevice, SIGNAL( framesReceived()), + this , SLOT (onFrameReceive ())); + + connect(_canDevice, SIGNAL( errorOccurred(QCanBusDevice::CanBusError)), + this , SLOT (onFrameError (QCanBusDevice::CanBusError))); + + connect(_canDevice, SIGNAL( framesWritten(qint64)), + this , SLOT (onFrameWritten (qint64))); + } + connect(&_FrameInterface, SIGNAL(didFrameTransmit(QCanBusFrame)), + this , SLOT( onFrameTransmit(QCanBusFrame))); +} + +/*! + * \brief CanInterface::initThread + * \details Moves this object into the thread vThread. + * And checks that this method is called from main thread. + * Also connects quitThread to application aboutToQuit. + * \param vThread - the thread + */ +void CanInterface::initThread(QThread &vThread) +{ + // runs in main thread + Q_ASSERT_X(QThread::currentThread() == qApp->thread() , __func__, "The Class initialization must be done in Main Thread" ); + _thread = &vThread; + _thread->setObjectName(QString("%1_Thread").arg(metaObject()->className())); + connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(quit())); + _thread->start(); + moveToThread(_thread); +} + +/*! + * \brief CanInterface::quitThread + * \details Moves this object to main thread to be handled by QApplicaiton + * And to be destroyed there. + */ +void CanInterface::quitThread() +{ + // coco begin validated: Application termination is not correctly done in coco!!! + // it has been tested and works perfectly fine in normal run. + + if (! _thread) return; + + // runs in thread + moveToThread(qApp->thread()); // verified +} +// coco end + +/*! + * \brief CanInterface::createDevice + * \details Creates the CANBus device + * \return false if can't create the device + */ +bool CanInterface::initDevice() +{ + QString mError; + _canDevice = QCanBus::instance()->createDevice(_canType, _canInterface, &mError); + // coco begin validated: Manually tested since required to disable and enable the CANBus + if (!_canDevice) { + status(tr("Device Creation"), mError); + LOG_DEBUG(status()); + return false; + } + // coco end + return true; +} + +/*! + * \brief CanInterface::checkDevice + * \details Checks if the device has been connected. + * \return + */ +bool CanInterface::testDevice() +{ + if (!_canDevice->connectDevice()) { + status(tr("Connection")); + LOG_DEBUG(status()); + delete _canDevice; + _canDevice = nullptr; + return false; + } + return true; +} + +/*! + * \brief CanInterface::deleteDevice + * \details Disconnect the CANBus device and deletes the pointer + */ +void CanInterface::quitDevice() +{ + // coco begin validated: Manually tested since required to disable and enable the CANBus + if (!_canDevice) return; + // coco end + _canDevice->disconnectDevice(); + delete _canDevice; + _canDevice = nullptr; + status(tr("Disconnected")); +} + +/*! + * \brief CanInterface status + * \details Sets the Can interface status description + * \param vDescription - Description about the CANBUS Interface errors + * \param vError - Qt CANBUS Interface Error + */ +void CanInterface::status(const QString &vDescription, QString vError) +{ + QString mError=""; + if (_canDevice) { + mError = _canDevice->errorString() + vError; + } + else { + mError = vError; + } + _canStatus = tr("%1 '%2[%3]', %4") + .arg(vDescription) + .arg(_canType) + .arg(_canInterface) + .arg(mError) + ; + qDebug() << _canStatus; +} + +/*! + * \brief CanInterface send + * \details send a frame over the CANBUS + * \param vFrame - CANBUS message frame + */ +bool CanInterface::transmit(const QCanBusFrame &vFrame) +{ + // coco begin validated: Manually tested since required to disable and enable the CANBus + if( !_canDevice ) return false; + //coco end + return _canDevice->writeFrame(vFrame); +} + +/*! + * \brief CanInterface console Output messaging + * \details Sends out formatted CANBUS message to the console + * for debugging purposes. + * \param vFrame - The CANBUS frame to be sent out + */ +void CanInterface::consoleOut(const QCanBusFrame &vFrame, const QString &vFrameCount) +{ + // coco begin validated: This code is only for debugging purposes and had been tested manually. + if ( ! _enableConsoleOut ) return; + + const QString time = QString::fromLatin1("%1.%2 ") + .arg(vFrame.timeStamp().seconds(), 10, 10, QLatin1Char(' ')) + .arg(vFrame.timeStamp().microSeconds() / 100, 4, 10, QLatin1Char('0')); + const QString flags = frameFlags(vFrame); + QString view; + if (vFrame.frameType() == QCanBusFrame::ErrorFrame) { + view = _canDevice->interpretErrorFrame(vFrame); + } + else { + view = vFrame.payload().toHex('.').replace(QByteArray("a5"),QByteArray("\033[1;33mA5\033[0m")); + } + fprintf(stderr, "%s %s %s %i %s\n", vFrameCount.toLatin1().constData(), time.toLatin1().constData(), flags.toLatin1().constData(), vFrame.frameId(), view.toLatin1().constData()); +} +// coco end + +/*! + * \brief CanInterface::rxCount + * \details count received frames up the size of the FrameCount type size + * \return frame count + */ +FrameCount CanInterface::rxCount() +{ + Types::safeIncrement(_rxFrameCount); + return _rxFrameCount; +} + +/*! + * \brief CanInterface::txCount + * \details count transmitted frames up the size of the FrameCount type size + * \return frame count + */ +FrameCount CanInterface::txCount() +{ + Types::safeIncrement(_txFrameCount); + return _txFrameCount; +} + +/*! + * \brief CanInterface::erCount + * \details count errors happened + * \return error count + */ +FrameCount CanInterface::erCount() +{ + // coco begin validated: CANBus error handling has been tested manually. + // since it requires massive can messages sent/received to catch the error + Types::safeIncrement(_erFrameCount); + return _erFrameCount; + // coco end +} + +/*! + * \brief frameFlags + * \details CANBUS message frame type as flags + * \param vFrame - CANBUS message frame + * \return Frame flag as QString + */ +QString CanInterface::frameFlags(const QCanBusFrame &vFrame) +{ + // coco begin validated: CANBus error handling has been tested manually. + // since it requires massive can messages sent/received to catch the error + QString result = QLatin1String(" --- "); + + if (vFrame.hasBitrateSwitch()) + result[1] = QLatin1Char('B'); + if (vFrame.hasErrorStateIndicator()) + result[2] = QLatin1Char('E'); + if (vFrame.hasLocalEcho()) + result[3] = QLatin1Char('L'); + + return result; + // coco end +} + +/*! + * \brief CanInterface onError + * \details Can Bus error handler which sets the can status description + * \param vError - CANBUS error + */ +void CanInterface::onFrameError(QCanBusDevice::CanBusError vError) +{ + // coco begin validated: CANBus error handling has been tested manually. + // since it requires massive can messages sent/received to catch the error + erCount(); + switch (vError) { + case QCanBusDevice::ReadError: + case QCanBusDevice::WriteError: + case QCanBusDevice::ConnectionError: + case QCanBusDevice::ConfigurationError: + case QCanBusDevice::UnknownError: + // log the error each 100k frame and if error is different + if (_canStatus != _canDevice->errorString() || !(_erFrameCount % 100000)) { + _canStatus = _canDevice->errorString(); + LOG_DEBUG(QString("%1 - %2").arg(_erFrameCount).arg(_canStatus)); + } + break; + + default: + break; + + } + emit didFrameError(_canStatus); +} +// coco end + +/*! + * \brief CanInterface::onFrameWritten + * \details This is the slot connected to the signal + * which is emitted every time a payload of frames + * has been written to the CANBUS bus. + * \param vFramesCount - The framesCount argument is set to the number of frames + * that were written in this payload. + */ +void CanInterface::onFrameWritten(qint64 vFramesCount) +{ + static FrameCount mFrameCount = 0; + Types::safeIncrement(mFrameCount, vFramesCount); + emit didFrameWritten(vFramesCount); +} + +/*! + * \brief CanInterface onFrameReceived + * \details CANBUS message read handler + */ +void CanInterface::onFrameReceive () +{ + // coco begin validated: Manually tested since required to disable and enable the CANBus + if (!_canDevice) return; + // coco end + while (_canDevice->framesAvailable()) { + const QCanBusFrame frame = _canDevice->readFrame(); + rxCount(); + // coco begin validated: This code is only for debugging purposes and had been tested manually. + if ( _enableConsoleOut ) + consoleOut(frame, QString("Rx:%1").arg(_rxFrameCount)); + // coco end + emit didFrameReceive(frame); + } +} + +/*! + * \brief CanInterface onActionPerform + * \details sends a CANBUS message frame of the CANBUS message of the performed action + * This is a response from application UI to HD device + * \param vFrame - CANBUS message frame + */ +void CanInterface::onFrameTransmit(const QCanBusFrame &vFrame) +{ + bool ok = transmit(vFrame); + txCount(); + // coco begin validated: This code is only for debugging purposes and had been tested manually. + if ( _enableConsoleOut ) + consoleOut(vFrame, QString("Tx:%1").arg(_txFrameCount)); + // coco end + emit didFrameTransmit(ok); +} Index: sources/canbus/CanInterface.h =================================================================== diff -u --- sources/canbus/CanInterface.h (revision 0) +++ sources/canbus/CanInterface.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,144 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file CanInterface.h + * \author (last) Behrouz NematiPour + * \date (last) 02-Mar-2020 + * \author (original) Behrouz NematiPour + * \date (original) 28-Oct-2019 + * + */ +#pragma once + +// Qt +#include +#include + +// Project +#include "main.h" +#include "MessageGlobals.h" + + +// Define +#define _CanInterface Can::CanInterface::I() + +// forward declarations +class tst_canbus; +class tst_acknow; + +// namespace +namespace Can { + +/*! + * \brief CANBUS interface + * \details This class contains the interface to CANBUS + * And utilizes Qt QCanBus to interact with the CANBUS + * This class works only with the QCanBusFrame frames. + * On the OS side there is a driver installed to convert SPI to CAN + * Since the GUI Board by itself doesn't contain the CAN Bus. + * Application would know nothing about the SPI-TO-CAN + */ +class CanInterface : public QObject +{ + Q_OBJECT + + // friends + friend class ::tst_canbus; + friend class ::tst_acknow; + + // constants + const char *_canType = "socketcan"; + QString _canInterface = "can0"; + const int _canBitRate = 250000; + + // member variables + QCanBusDevice *_canDevice = nullptr; + QString _canStatus = ""; + bool _enableConsoleOut = false; + + QThread *_thread = nullptr; + bool _init = false; + + FrameCount _rxFrameCount = 0; + FrameCount _txFrameCount = 0; + FrameCount _erFrameCount = 0; + +// Singleton +SINGLETON(CanInterface); + +public slots: + bool init(); + bool init(QThread &vThread); + +private slots: + void quit(); + +public: + QString status() const; + void enableConsoleOut(bool vEnabled); + + void quitDevice(); +private: + void initConnections(); + + void initThread(QThread &vThread); + void quitThread(); + + bool initDevice(); + bool testDevice(); + + void status (const QString &vDescription, QString vError = ""); + bool transmit (const QCanBusFrame &vFrame); + void consoleOut (const QCanBusFrame &vFrame, const QString &vFrameCount); + + FrameCount rxCount(); + FrameCount txCount(); + FrameCount erCount(); + + static QString frameFlags(const QCanBusFrame &vFrame); + +signals: + /*! + * \brief didFrameReceive + * \details This signal will be emitted when a frame has been received + * \param vFrame - The Frame which has been received + */ + void didFrameReceive (const QCanBusFrame &vFrame ); + + /*! + * \brief didFrameError + * \details If and error occurs on CanDevice after the error is processed + * this signal can be used as a notifier. + * \param vStatus - CanDevice status with some extra information. + */ + void didFrameError (const QString &vStatus); + + /*! + * \brief didFrameTransmit + * \details After the frame has been transmitted this signal can be used as a notifier. + * \param ok - is true if the frame has been transmitted successfully + */ + void didFrameTransmit(bool ok); + + /*! + * \brief didFrameWritten + * \details After the frame transmission is done + * and acknowledged by a node on the CANBus, + * this signal is emitted. + * \param vCount is the number of frame which has been written + */ + void didFrameWritten(qint64 vCount); + +public slots: +private slots: + void onFrameTransmit (const QCanBusFrame &vFrame); + void onFrameReceive (); + void onFrameError (QCanBusDevice::CanBusError vError); + void onFrameWritten (qint64 vFramesCount); + +}; +} Index: sources/canbus/FrameInterface.cpp =================================================================== diff -u --- sources/canbus/FrameInterface.cpp (revision 0) +++ sources/canbus/FrameInterface.cpp (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,340 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file FrameInterface.cpp + * \author (last) Behrouz NemaiPour + * \date (last) 22-Jun-2020 + * \author (original) Behrouz NematiPour + * \date (original) 18-Dec-2019 + * + */ +#include "FrameInterface.h" + +// Qt +#include +#include +#include + +// Project +#include "Logger.h" +#include "MessageDispatcher.h" +#include "CanInterface.h" + +// namespace +using namespace Can; + + +/*! + * \brief FrameInterface::FrameInterface + * \details Constructor + * \param parent - QObject parent owner object. + * Qt handles the children destruction by their parent objects life-cycle. + */ +FrameInterface::FrameInterface(QObject *parent) : QObject(parent) { } + +/*! + * \brief Message Handler initializer + */ +bool FrameInterface::init() +{ + if ( _init ) return false; + _init = true; + + initConnections(); + + startTimer(1, Qt::PreciseTimer); + + LOG_EVENT("UI," + tr("%1 Initialized").arg(metaObject()->className())); + + return true; +} + +/*! + * \brief FrameInterface::init + * \details Initialized the Class by calling the init() method first + * And initializes the thread vThread by calling initThread + * on success init(). + * \param vThread - the thread + * \return returns the return value of the init() method + */ +bool FrameInterface::init(QThread &vThread) +{ + if ( ! init() ) return false; + initThread(vThread); + return true; +} + +/*! + * \brief FrameInterface::quit + * \details quits the class + * Calls quitThread + */ +void FrameInterface::quit() +{ + // coco begin validated: Application termination is not correctly done in coco!!! + // it has been tested and works perfectly fine in normal run. + quitThread(); // validated +} +// coco end + +/*! + * \brief FrameInterface connections definition + * \details Initializes the required signal/slot connection between this class and other objects + * to be able to communicate. + */ +void FrameInterface::initConnections() +{ + // From GUI + connect(&_MessageDispatcher, SIGNAL(didFrameTransmit(Can_Id, const QByteArray &)), + this , SLOT( onFrameTransmit(Can_Id, const QByteArray &))); + + // From CAN + connect(&_CanInterface , SIGNAL( didFrameReceive( const QCanBusFrame &)), + this , SLOT( onFrameReceive( const QCanBusFrame &))); + connect(&_CanInterface , SIGNAL( didFrameWritten(qint64 )), + this , SLOT( onFrameWritten(qint64 ))); +} + +/*! + * \brief ApplicationController::initThread + * \details Moves this object into the thread vThread. + * And checks that this method is called from main thread. + * Also connects quitThread to application aboutToQuit. + * \param vThread - the thread + */ +void FrameInterface::initThread(QThread &vThread) +{ + // runs in main thread + Q_ASSERT_X(QThread::currentThread() == qApp->thread() , __func__, "The Class initialization must be done in Main Thread" ); + _thread = &vThread; + _thread->setObjectName(QString("%1_Thread").arg(metaObject()->className())); + connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(quit())); + _thread->start(); + moveToThread(_thread); +} + +/*! + * \brief FrameInterface::quitThread + * \details Moves this object to main thread to be handled by QApplicaiton + * And to be destroyed there. + */ +void FrameInterface::quitThread() +{ + // coco begin validated: Application termination is not correctly done in coco!!! + // it has been tested and works perfectly fine in normal run. + + if ( ! _thread ) return; + + // runs in thread + moveToThread(qApp->thread()); // validated +} +// coco end + +/*! + * \brief FrameInterface::transmitFrame + * \details Prepares a frame to be transmitted + * and emit signal didFrameTransmit with the frame as its argument + * \param vFrameId - Channel id of the CANBUS frame + * \param vData - The Data this frame is going to carry + * \note This frame is created by MessageBuilder + * and it can be one of the frames of a message + * which has been chopped into frames. + */ +void FrameInterface::transmitFrame(Can_Id vCan_Id, const QByteArray &vData) +{ + QCanBusFrame mFrame; + mFrame.setFrameId(vCan_Id); + if (vData.length() > Can::eLenCanFrame) { + LOG_DEBUG(QString("Payload can't be larger than %1 bytes").arg(Can::eLenCanFrame)); + return; + } + mFrame.setPayload(vData); + emit didFrameTransmit(mFrame); +} + +/*! + * \brief FrameInterface::checkChannel + * \details Checks for the channel id of the received frame + * which needs to be handled or ignored. + * \param vFrameId - Channel id of the frame + * \param vOK - will be set to true if the channel + * is valid and a variable has been passed to + * \return The Category if the channels from the UI + * perspective FrameInterface::ChannelGroup + */ +FrameInterface::ChannelGroup FrameInterface::checkChannel(quint32 vFrameId, bool *vOK) +{ + bool ok = true; + FrameInterface::ChannelGroup channelGroup = ChannelGroup::eChannel_Unknown; + switch (vFrameId) { + case eChlid_HD_DG : + channelGroup = ChannelGroup::eChannel_Ignores; + break; + // coco begin validated: The HD/DG communication has not been defined and implemented yet. + case eChlid_DG_HD : + // coco end + // this channel is used for DG CheckIn for HW support and testing for now. + //channelGroup = ChannelGroup::eChannel_Ignores; + //break; + + case eChlid_HD_UI : + case eChlid_HD_Alarm : + case eChlid_HD_Sync : + // coco begin validated: The UI/DG communication has not been defined and implemented yet. + case eChlid_DG_Alarm : + case eChlid_DG_UI : + case eChlid_DG_Sync : + // coco end + //case eChlid_DG_UI : // has duplicate value as eChlid_DG_Alarm + channelGroup = ChannelGroup::eChannel_Listens; + break; + + // coco begin validated: The UI Alarm and Sync messages has not been defined and implemented yet. + case eChlid_UI_Alarm : + case eChlid_UI_Sync : + //case eChlid_UI_DG : + channelGroup = ChannelGroup::eChannel_Outputs; + break; + // coco end + default: + ok = false; + break; + + } + // coco begin validated: manually tested + if (vOK) *vOK = ok; + // coco end + return channelGroup; +} + +/*! + * \brief FrameInterface::onFrameReceive + * \details This the slot connected to the CanInterface didFrameReceive signal. + * When a frame received over the CANBUS, + * this slot will be called to check the channel if should be listened to. + * and will emit didFrameReceive if should be handled and ignored otherwise. + * \param vFrame - The frame has to be sent + */ +void FrameInterface::onFrameReceive(const QCanBusFrame &vFrame) +{ + bool ok = false; + quint32 mFrameId = vFrame.frameId(); + ChannelGroup channelGroup = checkChannel(mFrameId, &ok); + + if (!ok) { + LOG_DEBUG("Unexpected Channel\r\n" + + Format::toHexString(mFrameId, false, eLenChannelDigits) + " -- " + vFrame.payload().toHex(' ')); + return; + } + + if ( channelGroup != ChannelGroup::eChannel_Listens) { + return; + } + + Can_Id mCan_Id = static_cast(mFrameId); + emit didFrameReceive(mCan_Id, vFrame.payload()); +} + +/*! + * \brief FrameInterface::onFrameTransmit + * \details This the slot connected to the MessageDispatcher didFrameTransmit signal. + * When a frame needs to be send to CANBUS, + * this slot will call transmitFrame method to do the job. + * \param vCan_Id - CANBUS Can Id target of the frame. + * \param vData - The data which this frame will carry. + */ +void FrameInterface::onFrameTransmit(Can_Id vCan_Id, const QByteArray &vData) +{ + appendHead(vCan_Id, vData); + // Test : qDebug() << _timestamp << "apnd #" << _txFrameList.count(); +} + +/*! + * \brief FrameInterface::onFrameWritten + * \param vCount + */ +void FrameInterface::onFrameWritten(qint64 /*vCount*/) +{ + _transmitted = true; + removeHead(); + // Test : qDebug() << _timestamp << "Sent #" << _txFrameList.count() << vCount; +} + +/*! + * \brief FrameInterface::timerEvent + * \details This event handler is re-implemented in this subclass to receive timer events for this object. + */ +void FrameInterface::timerEvent(QTimerEvent *) +{ + static quint8 count = 0; + // Test : _timestamp = QTime::currentTime().toString("HH:mm:ss.zzz"); + + if (++count != _interval) return; + // Test : qDebug() << _timestamp; + count = 0; + _transmitted = false; + trnsmtHead(); +} + +/*! + * \brief FrameInterface::trnsmtHead + * \details Transmits the head of the transmit buffer + * Sends an empty frame with lowest priority if the transmit buffer is empty + * to keep the UI board Can-driver awake. + */ +void FrameInterface::trnsmtHead() +{ + if ( _txFrameList.isEmpty() ) { + // coco begin validated: This is a fake data generator for CANBus missing/swapped frames Testing + // will never be executed on the product and shall be removed after the CANBus issues has been resolved. + // has been tested manually + if ( gSendEmptyKeepAwake ) { + transmitFrame(eChlid_LOWEST,QByteArray()); // Keep the CANBus awake. + return; + } + } + // coco end + else { + Frame frame = _txFrameList.first(); + transmitFrame(frame.can_Id, frame.data); + // Test : qDebug() << _timestamp << "Tsmt #" << _txFrameList.count(); + } +} + +/*! + * \brief FrameInterface::removeHead + * \details Removes the frame from the head of the transmit buffer + * in case transmission has been confirmed by the CANBus driver + * in the FrameInterface::onFrameWritten slot + * which is connected to CanInterface::didFrameWritten. + */ +void FrameInterface::removeHead() +{ + if ( _txFrameList.isEmpty() ) { + return; + } + _txFrameList.removeFirst(); +} + +/*! + * \brief FrameInterface::appendHead + * \details Appends the frame to the transmit buffer to be sent later + * \param vCan_Id - the CANBus id + * \param vData - the data to be sent + */ +void FrameInterface::appendHead(Can_Id vCan_Id, const QByteArray &vData) +{ + // coco begin validated: has been manually tested by sending over 4000 frames and not received by any other node. + if (_txFrameList.count() >= _txFrameList_Max) { + LOG_DEBUG(QString("Transmit buffer overflow of %1").arg(_txFrameList_Max)); + return; + // coco end + } + + Frame frame = Frame(vCan_Id, vData); + _txFrameList.append(frame); +} Index: sources/canbus/FrameInterface.h =================================================================== diff -u --- sources/canbus/FrameInterface.h (revision 0) +++ sources/canbus/FrameInterface.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,140 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file FrameInterface.h + * \author (last) Behrouz NematiPour + * \date (last) 07-May-2020 + * \author (original) Behrouz NematiPour + * \date (original) 18-Dec-2019 + * + */ +#pragma once + +// Qt +#include +#include + +// Project +#include "main.h" +#include "MessageGlobals.h" + +// Define +#define _FrameInterface Can::FrameInterface::I() + +// forward declarations +class tst_canbus; +class tst_acknow; +class tst_initializations; + +// namespace +namespace Can { + +/*! + * \brief The FrameInterface class + * \details This class is an interface between QByteArray and QCanBusFrame + * and gets the data as QByteArray and creates a frame + * and sends it to the CanInterface to deal with the CANBUS. + * And does it in reverse when receives a frame from CanInterface. + */ +class FrameInterface : public QObject +{ + Q_OBJECT + + // friends + friend class ::tst_canbus; + friend class ::tst_acknow; + friend class ::tst_initializations; + + /*! + * \brief The ChannelGroup enum + * \details The enum which represent the categories of the CANBUS channel + */ + enum class ChannelGroup { + eChannel_Unknown, ///< An Unknown channels category + eChannel_Ignores, ///< The Channels which will be ignored by UI + eChannel_Listens, ///< The Channels that UI is listening to + eChannel_Outputs, ///< The Channels that are related to UI frames out. + }; + + QThread *_thread = nullptr; + bool _init = false; + + + struct Frame { + Can_Id can_Id; + QByteArray data ; + + Frame(Can_Id vCan_Id, const QByteArray &vData) { + can_Id = vCan_Id; + data = vData ; + } + }; + QList _txFrameList; + const quint16 _txFrameList_Max = 4000; // maximum number of frames in the transmit buffer + bool _transmitted = false; + + const quint8 _interval = 7; // keep awake call of the UI board in ms + + QString _timestamp; + +// Singleton +SINGLETON(FrameInterface); + +protected: + void timerEvent(QTimerEvent *); + +public slots: + bool init(); + bool init(QThread &vThread); + +private slots: + void quit(); + +private: + void initConnections(); + + void initThread(QThread &vThread); + void quitThread(); + + ChannelGroup checkChannel(quint32 vFrameId, bool *vOK = nullptr); + void transmitFrame (Can_Id vCan_Id, const QByteArray &vData = 0); + void appendHead (Can_Id vCan_Id, const QByteArray &vData ); + void trnsmtHead (); + void removeHead (); + +private slots: // Should be private for thread safety and is connected internally. + void onFrameTransmit(Can_Id vCan_Id, const QByteArray &vData ); // GUI => CAN + void onFrameReceive ( const QCanBusFrame &vFrame ); // GUI <= CAN + void onFrameWritten (qint64 vCount ); // GUI <= CAN + +signals: + /*! + * \brief didFrameReceive + * \details After CanInterface receives a frame notifies FrameInterface + * by emitting CanInterface::didFrameReceive signal, + * then Message Handler calls its slot FrameInterface::onFrameReceive to handle the message, + * And when the message has been processed vCan_Id of type Can_Id which is the Channel ID of the frame + * and vPayload of the frame of type QByteArray has been extracted, + * This signal will be emitted to notify MessageDispatcher to start collecting data + * for this message over this channel. + * \param vCan_Id - Channel Id of the frame. + * \param vPayload - Payload of the frame. + */ + void didFrameReceive (Can_Id vCan_Id, const QByteArray &vPayload); // GUI <= CAN + + /*! + * \brief didFrameTransmit + * \details After MessageDispatcher requests FrameInterface to transmit a message, + * And FrameInterface calls its slot FrameInterface::onFrameTransmit to handle the message, + * And when the message has been processed and a Frame has been created, + * this signal will be emitted to notify CanInterface to send the frame. + * \ref CanInterface::onFrameTransmit + * \param vFrame - The frame which has been created to be transmitted. + */ + void didFrameTransmit( const QCanBusFrame &vFrame ); // GUI => CAN +}; +} Index: sources/canbus/MessageAcknowModel.cpp =================================================================== diff -u --- sources/canbus/MessageAcknowModel.cpp (revision 0) +++ sources/canbus/MessageAcknowModel.cpp (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,196 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file MessageAcknowModel.cpp + * \author (last) Behrouz NematiPour + * \date (last) 07-May-2020 + * \author (original) Behrouz NematiPour + * \date (original) 17-Jan-2020 + * + */ +#include "MessageAcknowModel.h" + +// Qt +#include +#include + +// Project +#include "MessageDispatcher.h" + +// namespace +using namespace Can; + +/*! + * \brief MessageAcknowModel::MessageAcknowModel + * \details Constructor + * \param parent - QObject parent owner object. + * Qt handles the children destruction by their parent objects life-cycle. + */ +MessageAcknowModel::MessageAcknowModel(QObject *parent) : QObject(parent) { } + + +/*! + * \brief MessageAcknowModel::init + * \details Initializes the class by setting the connections and starting the timer + * \return False if it has been called before. + */ +bool MessageAcknowModel::init() +{ + if ( _init ) return false; + _init = true; + + // runs in MessageAcknowModel thread + initConnections(); + + return true; +} + +/*! + * \brief MessageAcknowModel::init + * \details Initialized the Class by calling the init() method first + * And initializes the thread vThread by calling initThread + * on success init(). + * \param vThread - the thread + * \return returns the return value of the init() method + */ +bool MessageAcknowModel::init(QThread &vThread) +{ + if ( ! init() ) return false; + initThread(vThread); + return true; +} + +/*! + * \brief MessageAcknowModel::quit + * \details quits the class + * Calls quitThread + */ +void MessageAcknowModel::quit() +{ + // coco begin validated: Application termination is not correctly done in coco!!! + // it has been tested and works perfectly fine in normal run. + quitThread(); // validated +} +// coco end + +/*! + * \brief MessageAcknowModel::initConnections + * \details Initializes the required signal/slot connection between this class and other objects + * to be able to communicate. + */ +void MessageAcknowModel::initConnections() +{ + connect(&_MessageDispatcher, SIGNAL(didAcknowTransmit(Can_Id, Sequence, const FrameList &)), + this , SLOT( onAcknowTransmit(Can_Id, Sequence, const FrameList &))); + connect(&_MessageDispatcher, SIGNAL(didAcknowReceive ( Sequence )), + this , SLOT( onAcknowReceive ( Sequence ))); +} + +/*! + * \brief ApplicationController::initThread + * \details Moves this object into the thread vThread. + * And checks that this method is called from main thread. + * Also connects quitThread to application aboutToQuit. + * \param vThread - the thread + */ +void MessageAcknowModel::initThread(QThread &vThread) +{ + // runs in main thread + Q_ASSERT_X(QThread::currentThread() == qApp->thread() , __func__, "The Class initialization must be done in Main Thread" ); + _thread = &vThread; + _thread->setObjectName(QString("%1_Thread").arg(metaObject()->className())); + connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(quit())); + _thread->start(); + moveToThread(_thread); +} + +/*! + * \brief MessageAcknowModel::quitThread + * \details Moves this object to main thread to be handled by QApplicaiton + * And to be destroyed there. + */ +void MessageAcknowModel::quitThread() +{ + // coco begin validated: Application termination is not correctly done in coco!!! + // it has been tested and works perfectly fine in normal run. + + if ( ! _thread ) return; + + // runs in thread + moveToThread(qApp->thread()); // validated +} +// coco end + +/*! + * \brief MessageAcknowModel::onAcknowTransmit + * \details This slot is called MessageDispatcher sends a message from UI which requires Acknow. + * An Acknow model will be added to list of the Acknow required messages. + * The connection will be made to be notified by that message when it's timed out. + * And the timer for that message will be started. + * \param vCan_Id - Denali message Can channel + * \param vSequence - Sequence number of the message which requires Acknow + * \param vFrameList - List of the frames to be sent on retries. + */ +void MessageAcknowModel::onAcknowTransmit(Can_Id vCan_Id, Sequence vSequence, const FrameList &vFrameList) +{ + _acknowList[vSequence] = new Private::AcknowModel(vCan_Id, vSequence, vFrameList); + connect(_acknowList[vSequence] , SIGNAL(didFramesTransmit(Can_Id, Sequence, const FrameList &)), + this , SLOT( onFramesTransmit(Can_Id, Sequence, const FrameList &))); + connect(_acknowList[vSequence] , SIGNAL(didFailedTransmit( Sequence )), + this , SLOT( onFailedTransmit( Sequence ))); + _acknowList[vSequence]->start(); +} + +/*! + * \brief Private::AcknowModel::start + * \details It starts the message timer which is waiting for the Acknow + * on each interval will notify the MessageDispatcher to retry + */ +void Private::AcknowModel::start() { + _timerId = startTimer(_interval); +} + +/*! + * \brief MessageAcknowModel::onAcknowReceive + * \details This slot is called when the Acknow request for the specific message with the sequence number vSequence + * has been received. + * \param vSequence - Sequence number of the message which required Acknow + */ +void MessageAcknowModel::onAcknowReceive(Sequence vSequence) +{ + if (_acknowList.contains(vSequence)) { + _acknowList[vSequence]->deleteLater(); + _acknowList.remove(vSequence); + } +} + +/*! + * \brief MessageAcknowModel::onFramesTransmit + * \details This slot will be called when a message which is waiting for Acknow didn't get the Acknow + * during the interval and retries to transmit the message again. + * \param vCan_Id - The can channel for the Denali message + * \param vSequence - The sequence number of the message + * \param vFrameList - The list of the frame(s) needs to be sent. + */ +void MessageAcknowModel::onFramesTransmit(Can_Id vCan_Id, Sequence vSequence, const FrameList &vFrameList) +{ + emit didFramesTransmit(vCan_Id, vSequence, vFrameList); +} + +/*! + * \brief MessageAcknowModel::onFailedTransmit + * \details After the _retry amount of retries this slot will be called + * to notify the outside of the failure Acknow. + * \param vSequence - The sequence number of the message + */ +void MessageAcknowModel::onFailedTransmit(Sequence vSequence) +{ + _acknowList[vSequence]->deleteLater(); + _acknowList.remove(vSequence); + emit didFailedTransmit(vSequence); + LOG_DEBUG( QString("Acknow retry failed for sequence %1").arg(vSequence) ); +} Index: sources/canbus/MessageAcknowModel.h =================================================================== diff -u --- sources/canbus/MessageAcknowModel.h (revision 0) +++ sources/canbus/MessageAcknowModel.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,163 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file MessageAcknowModel.h + * \author (last) Behrouz NematiPour + * \date (last) 07-May-2020 + * \author (original) Behrouz NematiPour + * \date (original) 17-Jan-2020 + * + */ +#pragma once + +// Qt +#include + +// Project +#include "MessageGlobals.h" + +// Define +#define _MessageAcknowModel Can::MessageAcknowModel::I() + +class tst_acknow; + +// namespace +namespace Can { + +namespace Private { +/*! + * \brief The AcknowModel class + * \details This is the private class of the MessageAcknowModel + * which keeps list of the messages require Acknow. + * but since Qt doesn't support nested meta objects, + * it has been moved out with a meaningful namespace. + */ +class AcknowModel : public QObject { // Private Model + + Q_OBJECT + + friend class ::tst_acknow; + + const int _interval = 1000; // in ms + int _timerId = 0; + quint8 _retry = 5; + + Can_Id _can_Id = Can_Id::eChlid_NONE; + Sequence _sequence = 0; + FrameList _frameList ; + explicit AcknowModel(QObject *parent = nullptr) : QObject (parent) { } + +public: + AcknowModel(Can_Id vCan_Id, Sequence vSequence, const FrameList &vFrameList) : AcknowModel (nullptr) + { + _can_Id = vCan_Id ; + _sequence = vSequence ; + _frameList = vFrameList; + } + + void start(); + +protected: + /*! + * \brief MessageAcknowModel::timerEvent + * \details This event handler has been overrode in here + * to receive timer events for the object + * for the timer which has been set to _interval + * emits the didFramesTransmit signal to retry transmitting the frames + * emits the didFailedTransmit signal if exceeds retry limit. + */ + void timerEvent(QTimerEvent *) override + { + if ( _retry -- ) { + emit didFramesTransmit(_can_Id, _sequence, _frameList); + } else { + killTimer(_timerId); + emit didFailedTransmit(_sequence); + } + } + +signals: + + /*! + * \brief didFramesTransmit + * \details This signal is emitted when the requested Acknow has not been received during the _interval to retry to send message. + * \param vCan_Id - Denali message Can channel + * \param vSequence - Sequence number of the message which requires Acknow + * \param vFrameList - List of the frames to be sent on retries. + */ + void didFramesTransmit(Can_Id vCan_Id, Sequence vSequence, const FrameList &vFrameList); // Retry + + /*! + * \brief didFailedTransmit + * \details This signal is emitted when the requested Acknow has not been received after all the _retry times of retries. + * \param vSequence + */ + void didFailedTransmit( Sequence vSequence ); // Retry failed +}; +} + +/*! + * \brief The MessageAcknowModel class + * \details The wrapper class of the AcknowModel which does the thread handling. + */ +class MessageAcknowModel : public QObject +{ + Q_OBJECT + + friend class ::tst_acknow; + + typedef QHash AcknowList; + AcknowList _acknowList; + + QThread *_thread = nullptr; + bool _init = false; + +// Singleton +SINGLETON(MessageAcknowModel); + +public slots: + bool init(); + bool init(QThread &vThread); + +private slots: + void quit(); + +private: + void initConnections(); + + void initThread(QThread &vThread); + void quitThread(); + +signals: + + /*! + * \brief didFramesTransmit + * \details This signal is the propagation signal to propagate the AcknowModel Message signal of the same name + * when the requested Acknow has not been received during the _interval to retry to send message. + * \param vCan_Id - Denali message Can channel + * \param vSequence - Sequence number of the message which requires Acknow + * \param vFrameList - List of the frames to be sent on retries. + */ + void didFramesTransmit(Can_Id vCan_Id, Sequence vSequence, const FrameList &vFrameList); // Retry + + /*! + * \brief didFailedTransmit + * \details This signal is the propagation signal to propagate the AcknowModel Message signal of the same name + * when the requested Acknow has not been received after all the _retry times of retries. + * \param vSequence + */ + void didFailedTransmit( Sequence vSequence ); // Retry failed + +private slots: + void onFramesTransmit(Can_Id vCan_Id, Sequence vSequence, const FrameList &vFrameList); // Retry + void onFailedTransmit( Sequence vSequence ); // Retry failed + + void onAcknowTransmit(Can_Id vCan_Id, Sequence vSequence, const FrameList &vFrameList); // Add + void onAcknowReceive ( Sequence vSequence ); // Del + +}; +} Index: sources/canbus/MessageBuilder.cpp =================================================================== diff -u --- sources/canbus/MessageBuilder.cpp (revision 0) +++ sources/canbus/MessageBuilder.cpp (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,487 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file MessageBuilder.cpp + * \author (last) Behrouz NematiPour + * \date (last) 07-May-2020 + * \author (original) Behrouz NematiPour + * \date (original) 09-Dec-2019 + * + */ +#include "MessageBuilder.h" + +// Qt + +// Project +#include "Logger.h" +#include "crc.h" +#include "format.h" + +// namespace +using namespace Can; + +/*! + * \brief MessageBuilder::MessageBuilder + * \details Constructor + * \param parent - QObject parent owner object. + * Qt handles the children destruction by their parent objects life-cycle. + */ +MessageBuilder::MessageBuilder(QObject *parent) : QObject(parent) { } + +/*! + * \brief MessageBuilder::buildFrames + * \details This method builds list of frames out of the vActions of type GuiActionType + * and vData of type QByteArray which has been requested to be sent by UI. + * The message will be chopped into 8 bytes frames to be able to be send + * by fixed length CANBUS protocol. + * \param vAction - The ActionID of the requested message. + * \param vData - The payload of the message. + * \param vFrameList - The list of frames which has been created by vAction and vData to be sent. + * \return false on error + */ +bool MessageBuilder::buildFrames(Gui::GuiActionType vAction, const QByteArray &vData, FrameList &vFrameList, Sequence vSequence) +{ + QByteArray mPayload ; + addSyncByte (mPayload); // Sync Byte + addSequence (mPayload, vSequence); // adding sequence + if ( ! addActionId (mPayload, vAction ) ) { // MessageID + return false; + } + if ( ! addData (mPayload, vAction, vData) ) { // Regarding Payload Length, Adding required Data + return false; + } + addCRC (mPayload); // CRC + + quint16 len = mPayload.length(); + if (len > eLenCanFrame) { + quint8 frameCount = len / eLenCanFrame; + if (len % eLenCanFrame) ++frameCount; + for (quint8 i = 0; i < frameCount; i++) { + vFrameList += mPayload.mid(i * eLenCanFrame, eLenCanFrame); + } + } else { + vFrameList += mPayload; + } + + addPadding (vFrameList.last()); // Padded to 8 byte frame + return true; +} + +/*! + * \brief MessageBuilder::addSyncByte + * \details Adds the sync/start byte at the end of the Payload vPayload of type QByteArray + * \param vPayload - payload which is going to be constructed by appending byte + */ +void MessageBuilder::addSyncByte(QByteArray &vPayload) +{ + vPayload.append(ePayload_Sync); // Sync byte +} + +/*! + * \brief MessageBuilder::addSequence + * \details Adds the sequence number to the Denali message. + * \param vPayload - The message payload to be used for adding the sequence number to. + * \param vSequence - The sequence number + */ +void MessageBuilder::addSequence(QByteArray &vPayload, Sequence vSequence) +{ + Sequence_Bytes mSequence; + mSequence.value = vSequence; + for (quint8 index = 0; index < sizeof(mSequence); index++) { + vPayload += mSequence.bytes[index]; + } +} + +/*! + * \brief MessageBuilder::addActionId + * \details Adds the sync/start byte at the end of the Payload vPayload of type QByteArray + * \param vPayload - payload which is going to be constructed by appending byte + * \param vAction - The ActionID of the message which needs to be appended + * to the Payload vPayload + */ +bool MessageBuilder::addActionId(QByteArray &vPayload, Gui::GuiActionType vAction) +{ + if (vAction != Gui::GuiActionType::ID_Unknown) { + quint16 mAction = static_cast(vAction); + vPayload += (mAction >> 8) & 0xFF; // high byte + vPayload += mAction & 0xFF; // low byte + } else { + QString mHexString = Format::toHexString(vAction, false, eLenMessageIDDigits); + LOG_DEBUG(QString("Incorrect Action ID '%1'").arg(mHexString)); + return false; + } + return true; +} + +/*! + * \brief MessageBuilder::addData + * \details Regarding ActionID appends correct bytes amount of vData to the vPayload + * \param vPayload - payload which is going to be constructed by appending byte + * \param vAction - The ActionID of the message which needs to be appended + * \param vData - The data which is going to be message payload. + * \return false if the vData of type QByteArray is not sufficient regarding vAction + */ +bool MessageBuilder::addData(QByteArray &vPayload, Gui::GuiActionType vAction, const QByteArray &vData) +{ + quint8 len = payloadLen[vAction]; + // if len has been set to max(255) + // it means it has no limit and can be as long as 255 bytes + if (len == eLenMaxData) { + if (vData.length() > eLenMaxData) { + len = eLenMaxData ; + } else { + len = vData.length(); + } + } + if (vData.length() < len) { + QString mHexMIdString = Format::toHexString(vAction, false, eLenMessageIDDigits); + QString mHexDatString = vData.toHex('.').toUpper(); + LOG_DEBUG(QString("Not enough data has been provided for the Message ID '%1'\r\n%2") + .arg(mHexMIdString) + .arg(mHexDatString) + ); + return false; + } + vPayload += len; + vPayload += vData.mid(0, len); // Adding required Data + return true; +} + +/*! + * \brief MessageBuilder::addCRC + * \details Appends calculated crc8 (1 byte) of the vPayload at the end of the vPayload + * \param vPayload - The Payload which is going to be used for crc8 calculation + * \note The first byte will be excluded and is not part of the crc8 calculation. + * Since the first byte is the Sync and has always constant value of A5. + * SW/FW agreement. + */ +void MessageBuilder::addCRC(QByteArray &vPayload) +{ + // sync byte should not be Used for crc calculation + vPayload += calcCRC(vPayload.mid(1)); +} + +/*! + * \brief MessageBuilder::addPadding + * \details This method is appending bytes containing 0x00 + * to keep the length of the frame 8 bytes. + * \param vPayload - The payload of the CANBUS message + */ +void MessageBuilder::addPadding(QByteArray &vPayload) +{ + vPayload = vPayload.leftJustified(eLenCanFrame, '\0'); +} + +/*! + * \brief MessageBuilder::calcCRC + * \details Calculates the crc8 + * \param vData - The data of type QByteArray to be used for crc8 calculation. + * \return returns a byte contains crc8 + */ +quint8 MessageBuilder::calcCRC(const QByteArray &vData) +// TODO : This section better to be in the MessageModel +{ + quint8 crc = crc8(vData); + return crc; +} + +// CRC is always next byte after Data +/*! + * \brief MessageBuilder::checkCRC + * \details This method checks the crc8 of the vData of type QByteArray + * by using the last byte as the crc8 of the rest of the data + * \param vData - The data of type QByteArray to be used for crc8 calculation. + * \param vExpected - The expected CRC value + * \param vActual - The actual value which has been read + * \return returns false if the crc8 is not correct or the data is empty. + */ +bool MessageBuilder::checkCRC(const QByteArray &vData, quint8 &vExpected, quint8 &vActual) +// TODO : This section better to be in the MessageModel +{ +#ifndef DISABLE_CRC + int len = vData.length(); + if ( ! len ) return false; + vActual = vData.back(); + vExpected = calcCRC(vData.mid(0, len - 1)); + bool ok = vExpected == vActual; + // it's very good but I'm not sure if it's correct. + //bool ok = calcCRC(vData) == 0; + return ok; +#else + return true; +#endif +} + +/*! + * \brief MessageBuilder::checkCRC + * \details Overloaded CheckCRC which checks the CRC and Log the error if there is. + * \param vMessage - The message to check for the CRC + * \return false if has error + */ +bool MessageBuilder::checkCRC(const Message &vMessage) +{ + consoleOut("", false, Can_Id::eChlid_NONE); + QByteArray crcData = vMessage.head + vMessage.data; + quint8 mExpected = 0; + quint8 mBeenRead = 0; + if ( ! checkCRC(crcData, mExpected, mBeenRead ) ) { // CRC is always next byte after Data + static quint64 erCRC = 0; + LOG_DEBUG(QString("%1 - CRC error, expected %2 but got %3 : %4") + .arg(++erCRC) + .arg(Format::toHexString(mExpected, true, eLenCRCDigits)) + .arg(Format::toHexString(mBeenRead, true, eLenCRCDigits)) + .arg(Format::toHexString(vMessage.data)) + ); + return false; + } + return true; +} + +/*! + * \brief MessageBuilder::buildMessage + * \details Builds Message out of vPayload of type QByteArray + * by adding Sync byte, ActionID(MessageID), data length, data, CANBUS channel id for header + * and keeps collecting data from payload up until the specified length. + * \param vPayload - The payload of the CANBUS message + * \param vMessage - The Message variable which is going to be built + * \param vCan_Id - The CANBUS frame channel id + * \return false if the payload doesn't contain sync byte (Payload_Data::ePayload_Sync) + */ +bool MessageBuilder::buildMessage(const QByteArray &vPayload, Message &vMessage, Can_Id vCan_Id) +{ + QByteArray mPayload = vPayload; + if (vMessage.data.isEmpty()) { // message is empty so expected a header + if (hasSyncByte(mPayload)) { // Got header + consoleOut(vPayload, true, vCan_Id); + vMessage.can_id = vCan_Id; + vMessage.head = getHeader (mPayload); // keep header before taking it out of the payload. doesn't affect payload + vMessage.sequence = getSequence (mPayload); + vMessage.actionId = static_cast(getActionId(mPayload)); + vMessage.length = getLength (mPayload); + vMessage.data = getData (mPayload, vMessage.length); + vMessage.initialized = true; + } else { // Expected Header but got pure data + LOG_DEBUG(QString("Expected Header, got frame without Sync byte")); + printPayload(vPayload, false ,vCan_Id); + return false; + } + } else { + consoleOut(vPayload, false ,vCan_Id); + vMessage.data += vPayload.mid(0, vMessage.length - vMessage.data.length()); + } + + // TODO : This section better to be in the MessageModel + // and when Message model identifies the message is complete + // will SIGNAL builder to check for crc. + if (vMessage.isComplete()) { + bool ok = checkCRC(vMessage); + if (!ok) return false; + } + + return true; +} + +/*! + * \brief MessageBuilder::enableConsoleOut + * \details + * \param vEnabled + */ +void MessageBuilder::enableConsoleOut(bool vEnabled) { + // coco begin validated: This code meant to be used only for debugging and tested manually + if (_enableConsoleOut == vEnabled) return; + _enableConsoleOut = vEnabled; + if (_enableConsoleOut) { + LOG_DEBUG("Console out MessageBuilder enabled"); + } else { + LOG_DEBUG("Console out MessageBuilder disabled"); + } +} +// coco end + +/*! + * \brief MessageBuilder::hasSyncByte + * \details Checks for Sync byte and take it out of vPayload + * \param vPayload - The payload of type QByteArray + * \return true if the first byte of the vPayload is sync byte + * (Payload_Data::ePayload_Sync) + * \note Removes the first 1 byte of sync byte from vPayload + * It starts from the first byte. + */ +bool MessageBuilder::hasSyncByte(QByteArray &vPayload) +{ + quint8 mSyncByte = vPayload[0]; + if (mSyncByte == ePayload_Sync) { + vPayload = vPayload.mid(eLenSyncByte); + return true; + } + return false; +} + +/*! + * \brief MessageBuilder::getSequence + * \details Extract the 2 bytes of the sequence + * out of the vPayload of type QByteArray + * \param vPayload - The payload of the CANBUS message + * \return Returns ActionId of type GuiActionType + * \note Removes the 2 bytes of ActionID from vPayload + * It starts from the first byte so those 2 bytes should be the first 2 bytes. + */ +Sequence MessageBuilder::getSequence(QByteArray &vPayload) +{ + Sequence_Bytes mSequence; + int index = 0; + Types::getValue<>(vPayload, index, mSequence); + vPayload = vPayload.mid(eLenSequence); + return mSequence.value; +} + +/*! + * \brief MessageBuilder::getHeader + * \details Collect the 3 bytes (Frame_Data::eLenHeaderInfo) + * as header portion of the payload + * which is the MessageID (2 bytes) , data length (1 byte) + * It doesn't contain sync byte (Payload_Data::ePayload_Sync) + * as this value will be used for crc8 calculation + * and that doesn't include sync byte (Payload_Data::ePayload_Sync) + * \param vPayload - The payload of the CANBUS message + * \return Returns 3 byte of header data of type QByteArray + * \note As it's obvious from the function parameter it's not changing the vPayload + * Just has been mentioned to be consistent with the other methods of buildMessage. + * It starts from the first byte so the vPayload should not have the sync byte. + */ +QByteArray MessageBuilder::getHeader(const QByteArray &vPayload) +{ + QByteArray headInfo; + if (vPayload.length() < eLenHeaderInfo) { + LOG_DEBUG("Incorrect Message Header"); + return headInfo; + } + for (int i = 0; i < eLenHeaderInfo; i++) { + headInfo += vPayload[i]; + } + return headInfo; +} + +/*! + * \brief MessageBuilder::getActionId + * \details Extracts the 2 bytes ActionID (Frame_Data::eLenActionId) + * out of the vPayload of type QByteArray + * \param vPayload - The payload of the CANBUS message + * \return Returns ActionId of type GuiActionType + * \note Removes the 2 bytes of ActionID from vPayload + * It starts from the first byte so those 2 bytes should be the first 2 bytes. + */ +quint16 MessageBuilder::getActionId(QByteArray &vPayload) +{ + quint16 mActionId = vPayload.mid(0,eLenActionId).toHex().toUInt(0,16); + vPayload = vPayload.mid(eLenActionId); + return mActionId; +} + +/*! + * \brief MessageBuilder::getLength + * \details Extracts the 1 byte data length out of the vPayload + * and removes the first 1 byte + * \param vPayload - The payload of the CANBUS message + * \return returns the length of the data which is added by 1 to include 1 byte crc + * \note the length of the data should not be more than 255 which requires 1 byte only + * so technically it doesn't need to return a value of type more than 1 byte + * But some room reserved for later huge buffer passing + * And also as 1 byte crc8 is included as part of data + * it make it 256 which is going to be more than a byte. + * \note Removes the 1 byte of data length from vPayload + * It starts from the first byte so that byte should be the first 1 byte. + */ +int MessageBuilder::getLength(QByteArray &vPayload) +{ + // on the line bellow it has to be cast to unsigned otherwise FF will be converted to -1 and + 1 becomes 0. + int mlen = static_cast(vPayload[0]) + 1; // Add CRC to the length of data + vPayload = vPayload.mid(eLenLength); + return mlen; +} + +/*! + * \brief MessageBuilder::getData + * \details Extract data from vPayload + * if vLen is less or equal to Frame_Data::eLenMaxHeaderData + * it gets data of first byte up to the len of vLen + * otherwise returns the whole vPayload as the data + * \param vPayload - The payload of the CANBUS message + * \param vLen - the length of the data + * \return The data to be returned + */ +QByteArray MessageBuilder::getData(const QByteArray &vPayload, int vLen) +{ + QByteArray mData; + if (vLen <= eLenMaxHeaderData) { + mData = vPayload.mid(0, vLen); + } else { + mData = vPayload; + } + return mData; +} + +/*! + * \brief MessageBuilder::printPayload + * \details Sends out formatted message to the console + * for debugging purposes. + * Since this method is only formatting the payload + * and doesn't extract the content of the payload + * it gets required information from outside through it's parameters. + * \param vPayload - The payload of the CANBUS message + * \param vIsHeader - Should be sent as true if this payload contains header data + * \param vCan_Id - CANBUS channel id + * \param vUseColor - Use coloring or just space formatted output + * if vUseColor passed true is uses different color for Sync byte, MessageID & data + */ +void MessageBuilder::printPayload(const QByteArray &vPayload, bool vIsHeader, Can_Id vCan_Id, bool vUseColor) +{ + if (vCan_Id == Can_Id::eChlid_NONE) { + qDebug() << " "; + return; + } + QByteArray view; + // coco begin validated: printPayload and specially vUseColor is for debugging purposes and has been validated manually. + if (vUseColor) { + QList byteList; + byteList = vPayload.toHex('.').split('.'); + for (int i = 0; i < byteList.length(); i++) { + if (vIsHeader) { + if(i == 0) { + byteList[i] = QByteArray("\033[32m") + byteList[i].constData(); + } + if (i == 1 || i == 2) { + byteList[i] = QByteArray("\033[33m") + byteList[i].constData(); + } + if (i > 2) { + byteList[i] = QByteArray("\033[36m") + byteList[i].constData() + QByteArray("\033[0m"); + } + } else { + byteList[i] = QByteArray("\033[36m") + byteList[i].constData() + QByteArray("\033[0m"); + } + } + view = Format::toHexString(vCan_Id, false, eLenChannelDigits).toLatin1() + " " + byteList.join('.'); + fprintf(stderr, "%s\n", view.constData()); + } else { + view = Format::toHexString(vCan_Id, false, eLenChannelDigits).toLatin1() + " " + vPayload.toHex('.'); + fprintf(stderr, "%s\n", view.constData()); + } + // coco end +} + +/*! + * \brief MessageBuilder::consoleOut + * \details An overloaded method of the MessageBuilder::printPayload + * which is only printPayload if the console output is enabled + * by setting MessageBuilder::enableConsoleOut + * \note please refer to MessageBuilder::printPayload + */ +void MessageBuilder::consoleOut(const QByteArray &vPayload, bool vIsHeader, Can_Id vCan_Id, bool vUseColor) +{ + if ( ! _enableConsoleOut) return; + printPayload(vPayload, vIsHeader, vCan_Id, vUseColor); +} Index: sources/canbus/MessageBuilder.h =================================================================== diff -u --- sources/canbus/MessageBuilder.h (revision 0) +++ sources/canbus/MessageBuilder.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,96 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file messagebuilder.h + * \author (last) Behrouz NematiPour + * \date (last) 07-May-2020 + * \author (original) Behrouz NematiPour + * \date (original) 09-Dec-2019 + * + */ +#pragma once + +// Qt +#include +//#include + +// Project +#include "GuiGlobals.h" +#include "MessageGlobals.h" + +// forward declaration +class tst_messaging; + +namespace Can { + +/*! + * + * \brief The Message Builder class + * \details This class is handling the can message by building and striping it. + * \verbatim + * \table + * // -- CAN PAYLOAD STRUCTURE -- + * | #0| #1| #2| #3| #4| #5| #6| #7| #8| ........ | + * |---|-------|-------|---|-------|---|-----------| + * | A5| Seq# | MsgId |Len| Data |CRC|..padding..| + * +---+-------+-------+---+-------+---+-----------+ + * + * Header Frame: + * 1 - CRC is last after payload + * Ex1 - If Len=0 then CRC is #4 + * Ex2 - If Len=1 then CRC is #5 and payload is #4 + * 2 - If CRC is not the last by in the frame + * then there is padding 0x00 to make the frame 8 byte fix + * + * Tail Frame: + * 3 - Partial frames only have Payload and CRC ( and padded) + * \endverbatim + */ +class MessageBuilder : public QObject +{ + Q_OBJECT + + friend class ::tst_messaging; + + bool _enableConsoleOut = false; + + void addSyncByte ( QByteArray &vPayload); + void addSequence (QByteArray &vPayload, Sequence vSequence); + bool addActionId ( QByteArray &vPayload, Gui::GuiActionType vAction) __attribute_warn_unused_result__; + bool addData ( QByteArray &vPayload, Gui::GuiActionType vAction, const QByteArray &vData) __attribute_warn_unused_result__; + void addCRC ( QByteArray &vPayload); + void addPadding ( QByteArray &vPayload); + + quint8 calcCRC (const QByteArray &vData ); + bool checkCRC (const QByteArray &vData , quint8 &vExpected, quint8 &vActual); + bool checkCRC (const Message &vMessage); + + bool hasSyncByte ( QByteArray &vPayload); + Sequence getSequence ( QByteArray &vPayload); + QByteArray getHeader (const QByteArray &vPayload); + quint16 getActionId ( QByteArray &vPayload); + int getLength ( QByteArray &vPayload); + QByteArray getData (const QByteArray &vPayload, int vLen); + + void printPayload(const QByteArray &vPayload, bool vIsHeader, Can_Id vCan_Id, bool vUseColor = true); + void consoleOut (const QByteArray &vPayload, bool vIsHeader, Can_Id vCan_Id, bool vUseColor = true); + +public: + explicit MessageBuilder(QObject *parent = nullptr); + + // build message to be sent frame by frame + bool buildFrames (Gui::GuiActionType vAction , const QByteArray &vData, FrameList &vFrameList, Sequence vSequence) __attribute_warn_unused_result__; + // build message from received frames + bool buildMessage(const QByteArray &vPayload, Message &vMessage, Can_Id vCan_Id) __attribute_warn_unused_result__; + + void enableConsoleOut(bool vEnabled); + +signals: + +public slots: +}; +} Index: sources/canbus/MessageDispatcher.cpp =================================================================== diff -u --- sources/canbus/MessageDispatcher.cpp (revision 0) +++ sources/canbus/MessageDispatcher.cpp (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,479 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file messagedispatcher.cpp + * \author (last) Peter Lucia + * \date (last) 29-Jun-2020 + * \author (original) Behrouz NematiPour + * \date (original) 09-Dec-2019 + * + */ +#include "MessageDispatcher.h" + +// Qt +#include +#include + +// Project +#include "Logger.h" +#include "ApplicationController.h" +#include "FrameInterface.h" +#include "MessageAcknowModel.h" + +//#define DEBUG_ACKBACK_HD_TO_UI +//#define DEBUG_OUT_OF_SYNC + +using namespace Can; + +/*! + * \brief MessageDispatcher::MessageDispatcher + * \details Constructor + * \param parent - QObject parent owner object. + * Qt handles the children destruction by their parent objects life-cycle. + */ +MessageDispatcher::MessageDispatcher(QObject *parent) : QObject(parent) { } + +/*! + * \brief Message Handler initializer + */ +bool MessageDispatcher::init() +{ + if ( _init ) return false; + _init = true; + + // runs in DriveWatcher thread + initConnections(); + + LOG_EVENT("UI," + tr("%1 Initialized").arg(metaObject()->className())); + + return true; +} + +/*! + * \brief MessageDispatcher::init + * \details Initialized the Class by calling the init() method first + * And initializes the thread vThread by calling initThread + * on success init(). + * \param vThread - the thread + * \return returns the return value of the init() method + */ +bool MessageDispatcher::init(QThread &vThread) +{ + if ( ! init() ) return false; + initThread(vThread); + return true; +} + +/*! + * \brief MessageDispatcher::quit + * \details quits the class + * Calls quitThread + */ +void MessageDispatcher::quit() +{ + // coco begin validated: Application termination is not correctly done in coco!!! + // it has been tested and works perfectly fine in normal run. + quitThread(); // validated +} +// coco end + +/*! + * \brief Message Handler connections definition + * \details Initializes the required signal/slot connection between this class and other objects + * to be able to communicate. + */ +void MessageDispatcher::initConnections() +{ + // From GUI + connect(&_ApplicationController, SIGNAL(didActionTransmit(GuiActionType , const QVariantList &)), + this , SLOT( onActionTransmit(GuiActionType , const QVariantList &))); + + // From HD + connect(&_FrameInterface , SIGNAL(didFrameReceive (Can_Id , const QByteArray &)), + this , SLOT( onFrameReceive (Can_Id , const QByteArray &))); + + // From Message Acknow Model timer timeout. + connect(&_MessageAcknowModel , SIGNAL(didFramesTransmit(Can_Id, Sequence, const FrameList &)), + this , SLOT( onFramesTransmit(Can_Id, Sequence, const FrameList &))); + + connect(&_MessageAcknowModel , SIGNAL(didFailedTransmit( Sequence )), + this , SLOT( onFailedTransmit( Sequence ))); + + // ---- Signal/Slots + ADJUST_TRANSMT_MODEL_BRIDGE_CONNECTIONS(_ApplicationController) + ACTION_RECEIVE_MODEL_BRIDGE_CONNECTIONS(_interpreter ) +} + +/*! + * \brief ApplicationController::initThread + * \details Moves this object into the thread vThread. + * And checks that this method is called from main thread. + * Also connects quitThread to application aboutToQuit. + * \param vThread - the thread + */ +void MessageDispatcher::initThread(QThread &vThread) +{ + // runs in main thread + Q_ASSERT_X(QThread::currentThread() == qApp->thread() , __func__, "The Class initialization must be done in Main Thread" ); + _thread = &vThread; + _thread->setObjectName(QString("%1_Thread").arg(metaObject()->className())); + connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(quit())); + _thread->start(); + moveToThread(_thread); +} + +/*! + * \brief MessageDispatcher::quitThread + * \details Moves this object to main thread to be handled by QApplicaiton + * And to be destroyed there. + */ +void MessageDispatcher::quitThread() +{ + // coco begin validated: Application termination is not correctly done in coco!!! + // it has been tested and works perfectly fine in normal run. + + if ( ! _thread ) return; + + // runs in thread + moveToThread(qApp->thread()); // validated +} +// coco end + +/*! + * \brief MessageDispatcher::onFrameReceive + * \details Upon message has been received over CANBUS this slot will be called + * by FrameInterface::didFrameReceive signal to process the frame + * Upon completion of collected all the required frames + * on successful interpretation of the message, emits didActionReceived signal. + * The message will be removed from list of the channel vCan_Id messages. + * \param vCan_Id - CANBUS channel of the frame + * \param vPayload - Payload of the frame + */ +void MessageDispatcher::onFrameReceive(Can_Id vCan_Id, const QByteArray &vPayload) +{ + // Append a message to the list + // coco begin validated: if empty (first condition) is true, it must never check for the complete (second condition) + // because if the list is empty there is no last() item + if (_messageList[vCan_Id].isEmpty() || _messageList[vCan_Id].last().isComplete()) { + // coco end + _messageList[vCan_Id].append(Message()); + } + + // build the message and check. + if (! buildMessage(vCan_Id, vPayload)) { + return; + } + Message mMessage = _messageList[vCan_Id].last(); + + // TODO : must be moved to a MessageModel class + if (mMessage.isComplete()) { + rxCount(); + #ifdef DEBUG_OUT_OF_SYNC + if (_rxSequence != mMessage.sequence) { + qDebug() << tr("Out of Sync : %1 , %2").arg(_rxSequence).arg(mMessage.sequence); + } + #endif + interpretMessage(mMessage); + } +} + +/*! + * \brief MessageDispatcher::onFramesTransmit + * \details this slots calls the framesTransmit to emit the didFrameTransmit signal + * to queue the frame(s) to be sent + * \param vSequence - sequence of the message which is going to be resent. (not used) + * \param vFrameList - frame(s) to be sent + */ +void MessageDispatcher::onFramesTransmit(Can_Id vCan_Id, Sequence vSequence, const FrameList &vFrameList) +{ + Q_UNUSED(vSequence) + framesTransmit(vCan_Id, vFrameList); +} + +void MessageDispatcher::onFailedTransmit(Sequence vSequence) +{ + // coco begin validated: Is a placeholder and has not been implemented yet + emit didFailedTransmit(vSequence); +} +// coco end + +/*! + * \brief MessageDispatcher::onActionTransmit + * \details This slot will be called by ApplicationController::didActionTransmit + * upon UI message transmit request and calls MessageDispatcher::actionTransmit method. + * \param vActionId - The ActionID of the message + * \param vData - The data of the Message + */ +void MessageDispatcher::onActionTransmit(GuiActionType vActionId, const QVariantList &vData) +{ + actionTransmit(vActionId, vData); +} + +/*! + * \brief MessageDispatcher::onAdjustment + * \details This method transmits the Blood/Dialysate Adjustment Denali message. + * \param vData - Data model contains Blood Flow Rate + and Dialysate Flow Rate + * \return void + */ +void MessageDispatcher::onAdjustment(const AdjustBloodDialysateRequestData &vData) +{ + QVariantList mData; + mData += vData.bloodFlow; + mData += vData.dialysateFlow; + onActionTransmit(GuiActionType::ID_AdjustBloodDialysateReq, mData); +} + +/*! + * \brief MessageDispatcher::onAdjustment + * \details This method transmits the treatment duration Adjustment Denali message. + * \param vData - Data model contains treatment duration adjustment value in minutes + * \return void + */ +void MessageDispatcher::onAdjustment(const AdjustDurationRequestData &vData) +{ + QVariantList mData; + mData += vData.duration; + onActionTransmit(GuiActionType::ID_AdjustDurationReq, mData); +} + +/*! + * \brief MessageDispatcher::onAdjustment + * \details This method transmits the Ultrafiltration State Adjustment Denali message. + * \param vData - Data model contains treatment ultrafiltration state adjustment + * \return void + */ +void MessageDispatcher::onAdjustment(const AdjustUltrafiltrationStateRequestData &vData) +{ + QVariantList mData; + mData += vData.requestedState; + actionTransmit(GuiActionType::ID_AdjustUltrafiltrationStateReq, mData); +} + +/*! + * \brief MessageDispatcher::onAdjustment + * \details This method transmits the Ultrafiltration Adjustment Denali message. + * \param vData - Data model contains treatment ultrafiltration adjustment volume + * \return void + */ +void MessageDispatcher::onAdjustment(const AdjustUltrafiltrationEditRequestData &vData) +{ + QVariantList mData; + mData += vData.volume; + onActionTransmit(GuiActionType::ID_AdjustUltrafiltrationEditReq, mData); +} + +/*! + * \brief MessageDispatcher::onAdjustment + * \details This method transmits the Ultrafiltration Adjustment User Selected Option Denali message. + * \param vData - Data model contains treatment ultrafiltration adjustment volume and user selected option. + * \return void + */ +void MessageDispatcher::onAdjustment(const AdjustUltrafiltrationConfirmRequestData &vData) +{ + QVariantList mData; + mData += vData.volume; + mData += vData.option; + onActionTransmit(GuiActionType::ID_AdjustUltrafiltrationConfirmReq, mData); +} + +/*! + * \brief MessageDispatcher::onAdjustment + * \details This method transmits the Saline Bolus Adjustment Denali message. + * \param vData - Data model contains treatment Saline Bolus adjustment state. + * \return void + */ +void MessageDispatcher::onAdjustment(const AdjustSalineRequestData &vData) +{ + QVariantList mData; + mData += vData.requestedState; + onActionTransmit(GuiActionType::ID_AdjustSalineReq, mData); +} + + +/*! + * \brief MessageDispatcher::actionTransmit + * \details This method is called by slot MessageDispatcher::onActionTransmit + * which emits didFrameTransmit on successful interpretation of the requested message + * and successfully creating of frame(s). + * \param vActionId - The ActionID of the message + * \param vData - The data of the Message + */ +void MessageDispatcher::actionTransmit(GuiActionType vActionId, const QVariantList &vData, Sequence vSequence) +{ + txCount(); + if (vSequence == 0) { // initialize + // it's obvious that this assignment does not effect outside of the function. + // but is make it easier to just assume the correct value has been passed + // and still using the same variable (function parameter) as a local variable. + vSequence = _txSequence; + } + + QByteArray mData; + + if (! _interpreter.interpretMessage(vActionId, vData, mData)) { + LOG_DEBUG(QString("Incorrect Message, can't be interpreted, %1").arg(Format::toHexString(vActionId))); // TODO : LogInfo Improvement + return; + } + + // TODO : Create a buildFrames method + FrameList frameList; + Sequence mSequence = vSequence; + bool mNeedsAcknow = needsAcknow(vActionId); + if (mNeedsAcknow) { + mSequence = -mSequence; + LOG_EVENT(tr("UI,Ack Req, Sq:%1, ID:%2").arg(mSequence).arg(Format::toHexString(vActionId))); +#ifdef DEBUG_ACKBACK_HD_TO_UI + qDebug() << tr(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ UI AckReq : %1 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ").arg(mSequence); +#endif + } + + // coco begin validated: Has been tested manually but in this function this can't be false because the message interpreter is doing the same validation. + // still checking here in case the logic has changed therefore buildFrame should still validate the message for developer safety. + if ( ! _builder.buildFrames(vActionId, mData, frameList, mSequence) ) { + LOG_DEBUG(QString("Incorrect Message can't be built")); // TODO : LogInfo Improvement + return; + } + // coco end + if (mNeedsAcknow) { + // NOTE : here vSequence should be used which is not negative + // because when we get the Acknow it is not the negative + // since it does not need Re-Acknow + // and this is the sequence number which will be used + // to remove the message from the Acknow list. + emit didAcknowTransmit(eChlid_UI_HD, vSequence, frameList); + } + framesTransmit(eChlid_UI_HD, frameList); +} + +/*! + * \brief MessageDispatcher::framesTransmit + * \details iterates through all the frames and emits to send the frames + * \param vCan_Id - The channel to send the frames to + * \param vFrameList - List of the frames to be sent + */ +void MessageDispatcher::framesTransmit(Can_Id vCan_Id, const FrameList &vFrameList) +{ + for (const auto &frame : vFrameList) { + emit didFrameTransmit(vCan_Id, frame); + } +} + +/*! + * \brief MessageDispatcher::buildMessage + * \details Calls the messageBuilder buildMessage method. + * \param vCan_Id - CANBUS channel of the frame + * \param vPayload - Payload of the frame + * \return false on error + */ +bool MessageDispatcher::buildMessage(Can_Id vCan_Id, const QByteArray &vPayload) +{ + if (vPayload.length() < eLenCanFrame) { + // Each frame has to have exactly 8 (eLenCanFrame) bytes of data and unused bytes should be passed as 00. + LOG_DEBUG(QString("Incorrect frame length. Exp:%1,got:%2").arg(eLenCanFrame).arg(vPayload.length())); + return false; + } + if (! _builder.buildMessage(vPayload, _messageList[vCan_Id].last(), vCan_Id)) { + _messageList[vCan_Id].removeLast(); + return false; + } + return true; +} + +/*! + * \brief MessageDispatcher::interpretMessage + * \details Calls the MessageInterpreter interpretMessage method + * Regarding the Message Id and the sequence emit different signals + * to handle the normal or acknowledge messages. + * \param vMessage - The Message + * \return false on error + */ +bool MessageDispatcher::interpretMessage(const Message &vMessage) +{ + bool ok = false; + QVariantList mData; + Sequence mSequence = vMessage.sequence; + // coco begin validated: Has been validated manually. If MessageInterpreter::interpretMessage fails, this also returns false + if (_interpreter.interpretMessage(vMessage, mData)) { + // coco end + ok = true; + GuiActionType mActionId = vMessage.actionId; + switch (mActionId) { + case GuiActionType::ID_Acknow: + LOG_EVENT(tr("HD,Ack Bak, Sq:%1").arg(mSequence)); + #ifdef DEBUG_ACKBACK_HD_TO_UI + qDebug() << tr(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ HD AckBak : %1 %2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ").arg(mSequence).arg(vMessage.actionId); + #endif + emit didAcknowReceive(mSequence); + break; + + default: + if (mSequence < 0) { + LOG_EVENT(tr("HD,Ack Req, Sq:%1, ID:%2").arg(mSequence).arg(Format::toHexString(mActionId))); + #ifdef DEBUG_ACKBACK_HD_TO_UI + qDebug() << tr(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ HD AckReq : %1 %2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ").arg(mSequence).arg(vMessage.actionId); + #endif + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ UI AckBak is immediately handled at the same place. + actionTransmit(GuiActionType::ID_Acknow, {}, -mSequence); + LOG_EVENT(tr("UI,Ack Bak, Sq:%1").arg(-mSequence)); + #ifdef DEBUG_ACKBACK_HD_TO_UI + qDebug() << tr(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ UI AckBak : %1 %2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ").arg(-mSequence).arg(vMessage.actionId); + #endif + } + emit didActionReceive(mActionId, mData); + break; + + } + } + _messageList[vMessage.can_id].removeLast(); + return ok; +} + +/*! + * \brief MessageDispatcher::rxCount + * \details count received messages up the size of the Sequence type size + * \return message count + */ +Sequence MessageDispatcher::rxCount() +{ + // coco begin validated: has been manually validated since it requires so many received messages to reset the seq + if ( _rxSequence < SEQUENCE_MAX ) { + ++_rxSequence; + } else { + _rxSequence = 1; + } + return _rxSequence; +} +// coco end + +/*! + * \brief MessageDispatcher::txCount + * \details count transmitted messages up the size of the Sequence type size + * \return message count + */ +Sequence MessageDispatcher::txCount() +{ + // coco begin validated: has been manually validated since it requires so many received messages to reset the seq + if ( _txSequence < SEQUENCE_MAX ) { + ++_txSequence; + } else { + _txSequence = 1; + } + return _txSequence; +} +// coco end + +/*! + * \brief MessageDispatcher::needsAcknow + * \details List of the Action types which need Acknow + * \param vActionId - Action Type id + * \return true if needs an Acknow + */ +bool MessageDispatcher::needsAcknow(GuiActionType vActionId) +{ + return _needsAcknow.contains(vActionId); +} Index: sources/canbus/MessageDispatcher.h =================================================================== diff -u --- sources/canbus/MessageDispatcher.h (revision 0) +++ sources/canbus/MessageDispatcher.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,211 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file messagedispatcher.h + * \author (last) Peter Lucia + * \date (last) 25-Jun-2020 + * \author (original) Behrouz NematiPour + * \date (original) 09-Dec-2019 + * + */ +#pragma once + +// Qt +#include + +// Project +#include "main.h" +#include "MessageBuilder.h" +#include "MessageInterpreter.h" + +// define +#define _MessageDispatcher Can::MessageDispatcher::I() + +// forward declarations +class tst_canbus; +class tst_acknow; +class tst_messaging; + +// since this class is the interface between GUI and Can +// it needs to use Gui namespace otherwise it makes code hard to read. +using namespace Gui; +namespace Can { +/*! + * \brief The MessageDispatcher class \n + * \details Message Dispatcher is the class which is the mediator between CanBus Frames \n + * and Application Messages. \n + * The massages and frames need to be interpreted form/to hex \n + * and also need to be split into frames or constructor from frames to be a message. \n + * ---------------------------------------------------------------------------------------- \n + * \n + * Interpreter : message [ toHex , fromHex] \n + * \n + * Builder : message [ toFrame , fromFrame ] \n + * \n + * Dispatcher : signal->Handler( .. frame .. ) \n + * \n + * Handler : signal->Dispatcher( .. frame .. ) \n + * \n + * ---------------------------------------------------------------------------------------- \n + * \n + * *** UI <-> AppController <-> Dispatcher <-> Handler <-> HD *** \n + * \n + * ---------------------------------------------------------------------------------------- \n + * \n + * UI -> message -> \n + * AppController { \n + * signal->Dispatcher ( .. message .. ) \n + * } \n + * \n + * Dispatcher { \n + * .. \n + * messageList[ch][frameList] += Builder.toFrame ( Interpreter.toHex ( message ) ) \n + * .. \n + * signal->Handler( .. frame .. ) \n + * } \n + * \n + * ---------------------------------------------------------------------------------------- \n + * \n + * HD -> frame -> \n + * Handler { \n + * signal->Dispatcher ( .. frame .. ) \n + * } \n + * \n + * Dispatcher { \n + * messageList[ch][frameList] += Interpreter.fromHex( frame ) \n + * isComplete => Builder.fromFrame( frameList ) : signal->AppController \n + * } \n + * \n + * ---------------------------------------------------------------------------------------- \n + */ +class MessageDispatcher : public QObject +{ + Q_OBJECT + + // friends + friend class ::tst_canbus; + friend class ::tst_acknow; + friend class ::tst_messaging; + + QHash _messageList; + + Sequence _txSequence = 0; + Sequence _rxSequence = 0; + + MessageBuilder _builder; + MessageInterpreter _interpreter; + + QThread *_thread = nullptr; + bool _init = false; + + QList _needsAcknow { + GuiActionType::ID_AdjustBloodDialysateReq , + GuiActionType::ID_AdjustDurationReq , + GuiActionType::ID_AdjustUltrafiltrationStateReq , + GuiActionType::ID_AdjustUltrafiltrationEditReq , + GuiActionType::ID_AdjustUltrafiltrationConfirmReq , + GuiActionType::ID_AlarmSilenceReq , + }; + +// Singleton +SINGLETON(MessageDispatcher); + +public slots: + bool init(); + bool init(QThread &vThread); + +private slots: + void quit(); + +public: + void enableConsoleOut(bool vEnable) { _builder.enableConsoleOut(vEnable); } + +private: + void initConnections(); + + void initThread(QThread &vThread); + void quitThread(); + + void actionTransmit (GuiActionType vActionId, const QVariantList &vData, Sequence vSequence = 0); + void framesTransmit (Can_Id vCan_Id, const FrameList &vFrameList); + + bool needsAcknow (GuiActionType vActionId); + + bool buildMessage (Can_Id vCan_Id, const QByteArray &vPayload); + bool interpretMessage(const Message &vMessage); + + Sequence txCount(); + Sequence rxCount(); + +signals: + /*! + * \brief didActionReceive + * \details When a message received over the CANBUS this signal is emitted + * on successful collecting all required payloads from different frames if any + * and successfully has been built into a message and can be interpreted + * \param vAction - The action has been extracted from CANBUS message header to be done + * \param vData - The data has been collected from CANBUS frame(s) + */ + void didActionReceive (GuiActionType vAction , const QVariantList &vData); + + /*! + * \brief didActionReceive + * \details Emits when a message requires + * \param vData + */ + void didActionReceive (const Message &vMessage); + + /*! + * \brief didAcknowReceive + * \details if the type the received message id is and Acknow this signal will be emitted + * \param vData - the data of the Acknow message which is the message Sequence + * which we got the Ack for. + */ + void didAcknowReceive (Sequence vSequence); + + /*! + * \brief didAcknowTransmit + * \details this signal will be emitted when the message which has been sent + * needs Acknowledge back. + * \param vFrameList - the frames which has been send + * and will be used to be send on retries. + */ + void didAcknowTransmit(Can_Id vCan_Id, Sequence vSequence, const FrameList &vFrameList); + + /*! + * \brief didFrameTransmit + * \details When a message is requested to be transmitted this signal is emitted + * on successful interpretation and building the message into frames + * \param vCan_Id - Target channel of the CANBUS message + * \param vPayload - The payload of the message to be sent + */ + void didFrameTransmit (Can_Id vCan_Id, const QByteArray &vPayload); + + /*! + * \brief didFailedTransmit + * \details When a message fails to transmit to the HD, emit this signal. + * \param vSequence - The message Sequence we that failed to send. + */ + void didFailedTransmit(Sequence vSequence); + +private slots: + // A Frame has been received from CanInterface + void onFrameReceive (Can_Id vCan_Id, const QByteArray &vPayload); + + // + void onFramesTransmit (Can_Id vCan_Id, Sequence vSequence, const FrameList &vFrameList); + void onFailedTransmit ( Sequence vSequence); + + // An Action has been requested to be transmitted. + void onActionTransmit (GuiActionType vActionId, const QVariantList &vData); + + // ---- Signal/Slots + ADJUST_TRANSMT_MODEL_BRIDGE_DEFINITIONS_NOEMIT + ACTION_RECEIVE_MODEL_BRIDGE_DEFINITIONS + +}; +} Index: sources/canbus/MessageGlobals.h =================================================================== diff -u --- sources/canbus/MessageGlobals.h (revision 0) +++ sources/canbus/MessageGlobals.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,213 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file messageglobals.h + * \author (last) Peter Lucia + * \date (last) 25-Jun-2020 + * \author (original) Behrouz NematiPour + * \date (original) 06-Dec-2019 + * + */ +#pragma once + +// Qt +#include + +// Project +#include "GuiGlobals.h" +#include "types.h" + +namespace Can { + +/*! + * \brief Sequence + * \details the messages sequence type + */ +typedef qint16 Sequence; +typedef Types::S16 Sequence_Bytes; +#define SEQUENCE_MAX INT16_MAX + +/*! + * \brief FrameCount + * \details The maximum unsigned integer value to be used as the frame count + */ +typedef quint64 FrameCount; + +/*! + * \brief Payload Length + * \details List of each ActionID required data (in byte) length in the message. + * So the data collector has to collect this amount of bytes as payload of a message. + */ +const QHash payloadLen { + // ---- + {Gui::GuiActionType::ID_PowerOff , 1 }, + {Gui::GuiActionType::ID_ShuttingDown , 0 }, + {Gui::GuiActionType::ID_KeepAlive , 255 }, // 0 => 255 to be able to run a multi-frame test. + + // ----- + {Gui::GuiActionType::ID_TreatmentTime , 3 * 4 }, // 3 parameters each 4bytes + {Gui::GuiActionType::ID_BloodFlow , 7 * 4 }, // 7 parameters each 4bytes + {Gui::GuiActionType::ID_DialysateInletFlow , 7 * 4 }, // 7 parameters each 4bytes + {Gui::GuiActionType::ID_DialysateOutletFlow , 7 * 4 }, // 7 parameters each 4bytes + {Gui::GuiActionType::ID_PressureOcclusion , 5 * 4 }, // 5 parameters each 4bytes + {Gui::GuiActionType::ID_Saline , 3 * 4 }, // 3 parameters each 4bytes + + // ---- + {Gui::GuiActionType::ID_HDOperationModeData , 1 * 4 }, // 1 parameter each 4bytes + + // ---- + {Gui::GuiActionType::ID_DGROPumpData , 3 * 4 }, // 3 parameters each 4bytes + {Gui::GuiActionType::ID_DGPressuresData , 4 * 4 }, // 4 parameters each 4bytes + {Gui::GuiActionType::ID_DGDrainPumpData , 2 * 4 }, // 2 parameters each 4bytes + {Gui::GuiActionType::ID_DGOperationModeData , 1 * 4 }, // 1 parameter each 4bytes + {Gui::GuiActionType::ID_DGReservoirData , 3 * 4 }, // 3 parameters each 4bytes + {Gui::GuiActionType::ID_DGValvesStatesData , 1 * 2 }, // 1 parameters each 2bytes + {Gui::GuiActionType::ID_DGHeatersData , 3 * 4 }, // 3 parameters each 4bytes + {Gui::GuiActionType::ID_DGLoadCellReadingsData , 4 * 4 }, // 4 parameters each 4bytes + {Gui::GuiActionType::ID_DGTemperaturesData , 12 * 4 }, // 12 parameters each 4bytes + + // ---- + {Gui::GuiActionType::ID_AlarmStatus , 4 * 4 + 2 }, // 4 parameters each 4bytes + 1 parameter 2bytes + {Gui::GuiActionType::ID_AlarmTriggered , 1 * 4 }, // 1 parameter each 4bytes + {Gui::GuiActionType::ID_AlarmCleared , 1 * 4 }, // 1 parameter each 4bytes + {Gui::GuiActionType::ID_AlarmSilenceReq , 5 * 4 }, // 5 parameters each 4bytes + {Gui::GuiActionType::ID_AlarmSilenceRsp , 5 * 4 }, // 5 parameters each 4bytes + + // ---- + {Gui::GuiActionType::ID_TreatmentRanges , 6 * 4 }, // 6 parameters each 4bytes + {Gui::GuiActionType::ID_TreatmentStates , 3 * 4 }, // 3 parameters each 4bytes + + // ---- + {Gui::GuiActionType::ID_AdjustBloodDialysateReq , 2 * 4 }, // 2 parameters each 4bytes + {Gui::GuiActionType::ID_AdjustBloodDialysateRsp , 4 * 4 }, // 4 parameters each 4bytes + + // ---- + {Gui::GuiActionType::ID_AdjustDurationReq , 1 * 4 }, // 1 parameter each 4bytes + {Gui::GuiActionType::ID_AdjustDurationRsp , 4 * 4 }, // 4 parameters each 4bytes + + // ---- + {Gui::GuiActionType::ID_AdjustUltrafiltrationStateReq , 1 * 4 }, // 1 parameter each 4bytes + + // ---- + {Gui::GuiActionType::ID_AdjustUltrafiltrationEditReq , 1 * 4 }, // 1 parameter each 4bytes + {Gui::GuiActionType::ID_AdjustUltrafiltrationEditRsp , 8 * 4 }, // 8 parameters each 4bytes + + // ---- + {Gui::GuiActionType::ID_AdjustUltrafiltrationConfirmReq , 2 * 4 }, // 2 parameters each 4bytes + {Gui::GuiActionType::ID_AdjustUltrafiltrationConfirmRsp , 5 * 4 }, + + // ---- + {Gui::GuiActionType::ID_AdjustSalineReq , 1 * 4 }, // 1 parameter each 4bytes + {Gui::GuiActionType::ID_AdjustSalineRsp , 3 * 4 }, // 3 parameters each 4bytes + + // ---- + {Gui::GuiActionType::ID_CANBusFaultCount , 1 }, + {Gui::GuiActionType::ID_RawData , 255 }, + {Gui::GuiActionType::ID_Acknow , 0 }, + {Gui::GuiActionType::ID_AcknowGeneric , 1 }, + + {Gui::GuiActionType::ID_HDDebugText , 40 + 1 }, // ASCII text - 40 bytes + null term + {Gui::GuiActionType::ID_DGDebugText , 40 + 1 }, // ASCII text - 40 bytes + null term + +}; + +/*! + * \brief The Payload_Data enum + * \details Global information for message packet. + */ +enum Payload_Data : quint8 { + ePayload_None = 0x00, + ePayload_Sync = 0xA5, +}; + +/*! + * \brief The Frame_Data enum + * \details Global information for each message frame. + */ +enum Frame_Data : quint8 { + eLenCanFrame = 8, ///< The length of each can frame. Should be padded by 0x00 if is less. + eLenHeaderInfo = 5, ///< The Header length witch is included in CRC after Sync byte (it's the sum of eLenSequence + eLenActionId + eLenLength) + eLenMaxHeaderData = 3, ///< Maximum data byte can be in one frame as header data portion + eLenMaxData = 255, ///< Maximum data length in a Can Message since data length value kept in one byte + + eLenSyncByte = 1, ///< The length of Sync byte at the beginning of each header frame + eLenSequence = 2, ///< The length of Sequence number bytes (2) at the beginning of each header frame after sync + eLenActionId = 2, ///< The length of MessageID bytes + eLenLength = 1, ///< The length of data length value byte at the beginning of each header frame after MessageID + + eLenCRCDigits = 2, + eLenChannelDigits = 3, + eLenMessageIDDigits = 4, + +}; + +/*! + * \brief The Can_Id enum + * \details The Valid Can Bus MessageID of each frame + */ +enum Can_Id : quint16 { + eChlid_LOWEST = 0x7FF, + eChlid_NONE = 0x7FF, + + // Broadcasts + //// Alarm + eChlid_HD_Alarm = 0x001, ///< HD alarm broadcast + eChlid_DG_Alarm = 0x002, ///< DG alarm broadcast + eChlid_UI_Alarm = 0x004, ///< UI alarm broadcast [Out] + //// Sync + eChlid_HD_Sync = 0x040, ///< HD sync broadcast + eChlid_DG_Sync = 0x080, ///< DG sync broadcast + eChlid_UI_Sync = 0x200, ///< UI sync broadcast [Out] + + // UI not listening + eChlid_HD_DG = 0x008, ///< HD => DG + eChlid_DG_HD = 0x010, ///< DG => HD + + // UI is listening + eChlid_HD_UI = 0x020, ///< HD => UI + eChlid_UI_HD = 0x100, ///< UI => HD [Out] + + // UI lessens occasionally + eChlid_DG_UI = 0x070, ///< DG => UI + eChlid_UI_DG = eChlid_UI_Sync , ///< No direct channel has been defined between DG&UI, May be required for logging +}; + +/*! + * \brief The Message struct + * \details The message structure after it's been converted form hex bytes to meaningful struct for UI. + */ +struct Message { // TODO : Should be converted to MessageModel class // no time left for now !!! + Can_Id can_id; + Sequence sequence = 0; // seq 0 is invalid + Gui::GuiActionType actionId = Gui::GuiActionType::ID_Unknown; + int length = 0; + QByteArray head; + QByteArray data; + bool initialized = false; + + bool isEmpty () { + // coco begin validated:Has been validated manually. + // Since the crc is part of the data and there is no message without crc + // initialized flag and data.length() == 0 became the same. + // It is preferred to keep it as is so that the initialization is independent of data. + return !initialized || !data.length(); + // coco end + } + bool isComplete() { + // coco begin validated:Has been validated manually. + // Since the crc is part of the data and there is no message without crc + // then a message would never be empty. + // It is preferred to keep it as is so that the initialization is independent of data. + return !isEmpty() && data.length() == length; + // coco end + } +}; + +typedef QList MessageList; +typedef QList FrameList; + +} Index: sources/canbus/MessageInterpreter.cpp =================================================================== diff -u --- sources/canbus/MessageInterpreter.cpp (revision 0) +++ sources/canbus/MessageInterpreter.cpp (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,587 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file messageinterpreter.cpp + * \author (last) Peter Lucia + * \date (last) 29-Jun-2020 + * \author (original) Behrouz NematiPour + * \date (original) 13-Dec-2019 + * + */ +#include "MessageInterpreter.h" + +// Qt +#include +// #include + +// Project +#include "Logger.h" +#include "format.h" + +using namespace Can; + +#define DEBUG_RECEIVE_SIGNAL(vID, vMODEL) //qDebug() << vID << vMODEL; + +/*! + * \brief MessageInterpreter::MessageInterpreter + * \details Constructor + * \param parent - QObject parent owner object. + * Qt handles the children destruction by their parent objects life-cycle. + */ +MessageInterpreter::MessageInterpreter(QObject *parent) : QObject(parent) { } + +/*! + * \brief MessageInterpreter::notify + * \details Checks and prepares the model with the Message Data + * Regarding the type of message logs the message received. + * Notifies observers by emitting the didActionReceive( < Data > ) signal + * \param vMessage - The Denali message + * \param vID - The Message ID to be checked against + * \param vModel - The appropriate model for the Message Data + * \param vData - A QVariant list of the Message Data which will be used for debugging if needed. + * \return true on successful check and prepare. + */ +template +bool MessageInterpreter::notify(const Message &vMessage, QVariantList &vData, Gui::GuiActionType vIdCheck) +{ + bool ok = false; + TModel tModel; + if ( ! isValidMessage(vMessage, vIdCheck) ) return ok; + ok = tModel.fromByteArray(vMessage.data); + tModel.toVariantList(vData); + // coco begin validated : Tested manually. This code will never go false + // because the isValidMessage is catching errors. + // only is checking here for developer safety if logic has changed. + if ( ! ok ) return false; + // coco end + emit didActionReceive(tModel.data()); + logReceivedMessage(tModel); + DEBUG_RECEIVE_SIGNAL(vIdCheck, typeid(TModel).name()) + return ok; +} + +/*! + * \brief MessageInterpreter::isType + * \details Checks if this is the message intended to be + * \param vMessage - The message + * \param vType - The type of the message to be checked against + * \return true on correct type + */ +bool MessageInterpreter::isType(const Message &vMessage, Gui::GuiActionType vType) const +{ + if ( vMessage.actionId != vType ) { + return false; + } + return true; +} + +/*! + * \brief MessageInterpreter::isPayloadLenValid + * \details Checks if the Data length has been defined for this type of message + * if not logs Undefined Data Length error + * if defined checks if the correct length of data is provided for this type of message. + * if not logs Incorrect Data Length error + * otherwise returns true + * \param vMessage - The message + * \param vType - The type of the message to be checked against + * \return true on correct data length for the type vType + */ +bool MessageInterpreter::isPayloadLenValid(const Message &vMessage, Gui::GuiActionType vType) const +{ + QString mActionIdHexString = Format::toHexString(vMessage.actionId); + if ( ! payloadLen.contains(vType) ) { + LOG_DEBUG(QString("Undefined data length for received Message with ID '%1'").arg(mActionIdHexString)); + return false; + } + if ( vMessage.data.length() < payloadLen[vType] ) { + LOG_DEBUG(QString("Incorrect data length for received Message with ID '%1'").arg(mActionIdHexString)); + return false; + } + return true; +} + +/*! + * \brief MessageInterpreter::logInvalidLength + * \details Logs invalid data length for the message type vActionId + * \param vActionId - Message Type + */ +void MessageInterpreter::logInvalidLength(const Gui::GuiActionType &vActionId) +{ + QString mActionIdHexString = Format::toHexString(vActionId); + LOG_DEBUG(QString("Incorrect data length for transmit message with ID '%1'") + .arg(mActionIdHexString)); +} + +/*! + * \brief MessageInterpreter::validateMessage + * \details Validate the message by checking its type and data + * \param vMessage - The message + * \param vType - The type of the message to be checked against + * \return true on valid massage + */ +bool MessageInterpreter::isValidMessage(const Message &vMessage, Gui::GuiActionType vType) const +{ + if ( ! isType (vMessage, vType) ) return false; + if ( ! isPayloadLenValid(vMessage, vType) ) return false; + return true; +} + +/*! + * \brief MessageInterpreter::printUnhandled + * \details Prints out the formatted string of the vMessage of type Message + * In case the Message ID of received CANBUS message + * is known to the interpreter but has not been handled/implemented. + * \param vMessage - The message contains Unhandled Message ID + */ +void MessageInterpreter::printUnhandled(const Message &vMessage) const +{ + if ( gDisableUnhandledReport ) return; + QString mActionIdHexString = Format::toHexString(vMessage.actionId, false, eLenMessageIDDigits); + QString logMessage = tr("Unhandled Message ID (HD)") + '\n' + + QString("%1 # %2 %3") + .arg(int(vMessage.can_id), 3, 16, QChar('0')) + .arg(mActionIdHexString) + .arg(QString(vMessage.data.toHex('.'))); + LOG_DEBUG(logMessage); +} + +/*! + * \brief MessageInterpreter::logReceived + * \details Regarding the type of message logs the message received. + * \param vModel - the MAbstract model type + */ +void MessageInterpreter::logReceivedMessage(const Model::MAbstract &vModel) +{ + switch (vModel.typeText()) { + case Model::MAbstract::Type_Enum::eDatum: + LOG_DATUM(vModel.toString()); + break; + case Model::MAbstract::Type_Enum::eEvent: + LOG_EVENT(vModel.toString()); + break; + } +} + +/*! + * \brief MessageInterpreter::interpretMessage + * \details This method will be called + * to interpret messages from UI regarding vActionId. + * \param vActionId - The ActionID of type GuiActionType + * to be interpreted to hex representation of Message ID. + * \param vData - The data which has to be sent over the CANBUS. + * \param vPayload - The Payload of the frame of Type QByteArray of hex values + * Which has been interpreted from vData of Type QVariantList + * \return true if the vActionId is valid. + * This return value will be used later for error handling. + */ +bool MessageInterpreter::interpretMessage(const Gui::GuiActionType &vActionId, const QVariantList &vData, QByteArray &vPayload) +{ + bool ok = true; + QString mSenderID = "UI,"; + + vPayload.clear(); + int count = vData.length(); + + switch (vActionId) { // notice we are in transmit mode + case Gui::GuiActionType::ID_Acknow: // len: 0, can have zero len + break; // No data, Just registered + + + case Gui::GuiActionType::ID_KeepAlive: // len: 255, can have any len + if ( count ) { // this message has a variable length + vPayload = Format::fromVariant(vData[0]); + } + LOG_EVENT(mSenderID + QString("CheckIn")); + break; + + case Gui::GuiActionType::ID_RawData: // len: 255, can have any len + if ( count ) { // this message has a variable length + vPayload = Format::fromVariant(vData[0]); + } + LOG_EVENT(mSenderID + QString("RawData")); + break; + + case Gui::GuiActionType::ID_PowerOff: + if ( ! count ) { logInvalidLength(vActionId); return false; } + vPayload += Format::fromVariant(vData); + LOG_EVENT(AdjustPowerOffRequestData::toString(vData)); + break; + + case Gui::GuiActionType::ID_AdjustBloodDialysateReq: + if ( ! count ) { logInvalidLength(vActionId); return false; } + vPayload = Format::fromVariant(vData); + LOG_EVENT(AdjustBloodDialysateRequestData::toString(vData)); + break; + + case Gui::GuiActionType::ID_AdjustDurationReq: + if ( ! count ) { logInvalidLength(vActionId); return false; } + vPayload = Format::fromVariant(vData); + LOG_EVENT(AdjustDurationRequestData::toString(vData)); + break; + + case Gui::GuiActionType::ID_AdjustUltrafiltrationStateReq: + if ( ! count ) { logInvalidLength(vActionId); return false; } + vPayload = Format::fromVariant(vData); + LOG_EVENT(AdjustUltrafiltrationStateRequestData::toString(vData)); + break; + + case Gui::GuiActionType::ID_AdjustUltrafiltrationEditReq: + if ( ! count ) { logInvalidLength(vActionId); return false; } + vPayload = Format::fromVariant(vData); + LOG_EVENT(AdjustUltrafiltrationEditRequestData::toString(vData)); + break; + + case Gui::GuiActionType::ID_AdjustUltrafiltrationConfirmReq: + if ( ! count ) { logInvalidLength(vActionId); return false; } + vPayload = Format::fromVariant(vData); + LOG_EVENT(AdjustUltrafiltrationConfirmRequestData::toString(vData)); + break; + + case Gui::GuiActionType::ID_AdjustSalineReq: + if ( ! count ) { logInvalidLength(vActionId); return false; } + vPayload = Format::fromVariant(vData); + LOG_EVENT(AdjustSalineRequestData::toString(vData)); + break; + + case Gui::GuiActionType::ID_AlarmSilenceReq: + if ( ! count ) { logInvalidLength(vActionId); return false; } + vPayload = Format::fromVariant(vData); + LOG_EVENT(AlarmSilenceRequestData::toString(vData)); + break; + + default: + QString mActionIdHexString = Format::toHexString(vActionId); + LOG_DEBUG(mSenderID + tr("Unknown transmit Message with ID '%1'").arg(mActionIdHexString)); + ok = false; + break; + + } + return ok; +} + +/*! + * \brief MessageInterpreter::interpretMessage + * \details This method will call appropriate message interpreter + * for received messages from HD or DG regarding the Can_Id. + * \param vCan_Id - The Channel Id of the CANBUS frame. + * \param vMessage - The complete message of type Message which needs to be interpreted. + * \param vActionId - The ActionId of GuiActionType which will be extracted from vMessage. + * \param vData - The values of QVariantList which is understandable for UI + * and has been extracted from hex values of the CANBUS Message Payload + * regarding each Message Id definition. + * \return true if the message channel is in the range which can be interpreted, false otherwise. + * This return value will be used later to emit MessageDispatcher::didActionReceive signal or not + */ +bool MessageInterpreter::interpretMessage(const Message &vMessage, QVariantList &vData) +{ + bool ok = false; + switch (vMessage.can_id) { + case eChlid_HD_UI : + case eChlid_HD_Alarm: + case eChlid_HD_Sync : ok = interpretMessage_HD(vMessage, vData); break; + + case eChlid_DG_HD : + + case eChlid_DG_UI : + // case eChlid_DG_Alarm: // commented out for now. Currently there is no message in this category. + case eChlid_DG_Sync : ok = interpretMessage_DG(vMessage, vData); break; + + default: + break; + } + return ok; +} + +/*! + * \brief MessageInterpreter::interpretMessage_HD + * \details This method will be called + * for received messages from HD to interpret the vMessage of type Message + * to vData of type QVariantList which UI understands regarding the Can_Id. + * \param vMessage - The complete message of type Message which needs to be interpreted. + * \param vActionId - The ActionId of GuiActionType which will be extracted from vMessage. + * \param vData - The values of QVariantList which is understandable for UI + * and has been extracted from hex values of the CANBUS Message Payload + * in vMessage of type Message regarding each Message Id definition. + * \return true if the message CANBUS channel is in the range which can be interpreted, false otherwise. + * This return value will be used later to emit MessageDispatcher::didActionReceive signal or not + */ +bool MessageInterpreter::interpretMessage_HD(const Message &vMessage, QVariantList &vData) +{ + bool ok = false; + vData.clear(); + switch (vMessage.actionId) { // notice we are in receive mode + // ----- Debug + case Gui::GuiActionType::ID_CANBusFaultCount : ok = canbusFaultCountData (vMessage, vData); break; // TODO : implement notify<>() + + // ----- Datum + case Gui::GuiActionType::ID_TreatmentTime : ok = notify(vMessage, vData, Gui::GuiActionType::ID_TreatmentTime ); break; + case Gui::GuiActionType::ID_BloodFlow : ok = notify(vMessage, vData, Gui::GuiActionType::ID_BloodFlow ); break; + case Gui::GuiActionType::ID_DialysateInletFlow : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DialysateInletFlow ); break; + case Gui::GuiActionType::ID_DialysateOutletFlow : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DialysateOutletFlow ); break; + case Gui::GuiActionType::ID_TreatmentRanges : ok = notify(vMessage, vData, Gui::GuiActionType::ID_TreatmentRanges ); break; + case Gui::GuiActionType::ID_PressureOcclusion : ok = notify(vMessage, vData, Gui::GuiActionType::ID_PressureOcclusion ); break; + case Gui::GuiActionType::ID_TreatmentStates : ok = notify(vMessage, vData, Gui::GuiActionType::ID_TreatmentStates ); break; + case Gui::GuiActionType::ID_Saline : ok = notify(vMessage, vData, Gui::GuiActionType::ID_Saline ); break; + + // ----- Events + case Gui::GuiActionType::ID_HDOperationModeData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_HDOperationModeData ); break; + case Gui::GuiActionType::ID_HDDebugText : ok = notify(vMessage, vData, Gui::GuiActionType::ID_HDDebugText ); break; + + case Gui::GuiActionType::ID_Acknow : ok = true; break; // TODO : implement notify<>() + case Gui::GuiActionType::ID_PowerOff : ok = notify(vMessage, vData, Gui::GuiActionType::ID_PowerOff ); break; + case Gui::GuiActionType::ID_ShuttingDown : ok = true; LOG_EVENT("HD,ShuttingDown"); break; // TODO : implement notify<>() + case Gui::GuiActionType::ID_AlarmStatus : ok = alarmStatus (vMessage, vData); break; // TODO : implement notify<>() + case Gui::GuiActionType::ID_AlarmTriggered : ok = alarmTriggered (vMessage, vData); break; // TODO : implement notify<>() + case Gui::GuiActionType::ID_AlarmCleared : ok = alarmCleared (vMessage, vData); break; // TODO : implement notify<>() + + // Adjustment Response Messages + case Gui::GuiActionType::ID_AdjustDurationRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustDurationRsp ); break; + case Gui::GuiActionType::ID_AdjustBloodDialysateRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustBloodDialysateRsp); break; + case Gui::GuiActionType::ID_AdjustSalineRsp : ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustSalineRsp ); break; + + // ok = notify(vMessage, vData, Gui::GuiActionType::ID_AdjustUltrafiltrationStateReq); break; + // this message has been inherited from MAbstract and should use notify but since the response message is not standard can't use notify yet. + // when received gets payload len error and can't be interpreted. + case Gui::GuiActionType::ID_AdjustUltrafiltrationStateReq : ok = adjustUltrafiltrationState (vMessage, vData); break; // TODO : implement notify<>() + case Gui::GuiActionType::ID_AdjustUltrafiltrationEditRsp : ok = adjustUltrafiltrationEdit (vMessage, vData); break; // TODO : implement notify<>() + case Gui::GuiActionType::ID_AdjustUltrafiltrationConfirmRsp : ok = adjustUltrafiltrationConfirm (vMessage, vData); break; // TODO : implement notify<>() + + // unhandled messages: these will only be logged as received message + // there has nothing been defined for these messages. + default : printUnhandled (vMessage ); break; + } + + return ok; +} + +/*! + * \brief MessageInterpreter::interpretMessage_DG + * \details This method will be called + * for received messages from DG to interpret the vMessage of type Message + * to vData of type QVariantList which UI understands regarding the Can_Id. + * \param vMessage - The complete message of type Message which needs to be interpreted. + * \param vActionId - The ActionId of GuiActionType which will be extracted from vMessage. + * \param vData - The values of QVariantList which is understandable for UI + * and has been extracted from hex values of the CANBUS Message Payload + * in vMessage of type Message regarding each Message Id definition. + * \return true if the message CANBUS channel is in the range which can be interpreted, false otherwise. + * This return value will be used later to emit MessageDispatcher::didActionReceive signal or not + */ +bool MessageInterpreter::interpretMessage_DG(const Message &vMessage, QVariantList &vData) +{ + bool ok = false; + vData.clear(); + switch (vMessage.actionId) { // notice we are in receive mode + case Gui::GuiActionType::ID_DGCheckIn: // TODO : implement notify<>() + ok = true; + LOG_EVENT(QString("DG,CheckIn," + QVariant(vData).toStringList().join(','))); + break; + + case Gui::GuiActionType::ID_DGROPumpData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DGROPumpData ); break; + case Gui::GuiActionType::ID_DGPressuresData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DGPressuresData ); break; + case Gui::GuiActionType::ID_DGDrainPumpData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DGDrainPumpData ); break; + case Gui::GuiActionType::ID_DGOperationModeData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DGOperationModeData ); break; + case Gui::GuiActionType::ID_DGReservoirData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DGReservoirData ); break; + case Gui::GuiActionType::ID_DGValvesStatesData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DGValvesStatesData ); break; + case Gui::GuiActionType::ID_DGHeatersData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DGHeatersData ); break; + case Gui::GuiActionType::ID_DGLoadCellReadingsData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DGLoadCellReadingsData); break; + case Gui::GuiActionType::ID_DGTemperaturesData : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DGTemperaturesData ); break; + case Gui::GuiActionType::ID_DGDebugText : ok = notify(vMessage, vData, Gui::GuiActionType::ID_DGDebugText ); break; + + // unhandled messages: these will only be logged as received message + // there has nothing been defined for these messages. + default: + printUnhandled (vMessage); + break; + + } + + return ok; +} + +// ---------- ---------- Message handlers ---------- ---------- // + +// ---------- ---------- ---------- ---------- ---------- Debug ---------- ---------- ---------- ---------- ---------- // +/*! + * \brief MessageInterpreter::canbusFaultCountData + * \details This method interprets Fault Count message data + * in vMessage of type Message. This message is only used for debugging purposes. + * \param vMessage - The vMessage of type Message which contains all the data, + * require to be interpreted. + * \param vData - Fault Count data + * \return true if the data can be extracted as defined for Fault Count Message ID + */ +bool MessageInterpreter::canbusFaultCountData(const Message &vMessage, QVariantList &vData) +{ + // TODO : review other methods + bool ok = false; + if ( ! isValidMessage(vMessage, Gui::GuiActionType::ID_CANBusFaultCount) ) return ok; + + QVariantList mData; + int index = 0; + Types::U32 mCanBUSFaultCount; + ok = GetValue(vMessage.data, index, mCanBUSFaultCount); + // coco begin validated : developer safety if for any reason length of CanBUSFaultCount set to 0 + if (ok) { + // coco end + vData += mCanBUSFaultCount.value; + } + return ok; +} + +// ---------- ---------- ---------- ---------- ---------- Events ---------- ---------- ---------- ---------- ---------- // +// ---------- ---------- ---------- ---------- ---------- - HD ---------- ---------- ---------- ---------- ---------- // + +/*! + * \brief MessageInterpreter::alarmStatus + * \details This method interprets Alarm Status message data + * in vMessage of type Message. + * \param vMessage - The vMessage of type Message which contains all the data, + * require to be interpreted. + * \param vData - Alarm Status data + * \return true if the data can be extracted as defined for Alarm Status Message ID + */ +bool MessageInterpreter::alarmStatus(const Message &vMessage, QVariantList &vData) { + // TODO : review other methods + bool ok = false; + if ( ! isValidMessage(vMessage, Gui::GuiActionType::ID_AlarmStatus) ) return ok; + + Model::MAlarmStatus mData; + ok = mData.fromByteArray(vMessage.data); + LOG_EVENT("HD," + mData.toString()); + + mData.toVariantList(vData); + emit didActionReceive(mData.data()); + + return ok; +} + +/*! + * \brief MessageInterpreter::alarmTriggered + * \details This method interprets Alarm Triggered message data + * in vMessage of type Message. + * \param vMessage - The vMessage of type Message which contains all the data, + * require to be interpreted. + * \param vData - Alarm Triggered data + * \return true if the data can be extracted as defined for Alarm Triggered Message ID + */ +bool MessageInterpreter::alarmTriggered(const Message &vMessage, QVariantList &vData) +{ + // TODO : review other methods + bool ok = false; + if ( ! isValidMessage(vMessage, Gui::GuiActionType::ID_AlarmTriggered) ) return ok; + + Model::MAlarmTriggered mData; + ok = mData.fromByteArray(vMessage.data); + LOG_EVENT("HD," + mData.toString()); + + mData.toVariantList(vData); + emit didActionReceive(mData.data()); + + return ok; +} + +/*! + * \brief MessageInterpreter::alarmCleared + * \details This method interprets Alarm Cleared message data + * in vMessage of type Message. + * \param vMessage - The vMessage of type Message which contains all the data, + * require to be interpreted. + * \param vData - Alarm Cleared data + * \return true if the data can be extracted as defined for Alarm Cleared Message ID + */ +bool MessageInterpreter::alarmCleared(const Message &vMessage, QVariantList &vData) +{ + // TODO : review other methods + bool ok = false; + if ( ! isValidMessage(vMessage, Gui::GuiActionType::ID_AlarmCleared) ) return ok; + + Model::MAlarmCleared mData; + ok = mData.fromByteArray(vMessage.data); + LOG_EVENT("HD," + mData.toString()); + + mData.toVariantList(vData); + emit didActionReceive(mData.data()); + + return ok; +} + +// ---------- ---------- ---------- ---------- ---------- Adjustments ---------- ---------- ---------- ---------- ---------- // + +/*! + * \brief MessageInterpreter::ultrafiltrationState + * \details This method interprets Treatment Ultrafiltration State Adjustment Response message data + * in vMessage of type Message. + * \param vMessage - The vMessage of type Message which contains all the data, + * require to be interpreted. + * \param vData - Treatment Ultrafiltration State Adjustment Response data + * \return true if the data can be extracted as defined for Treatment Ultrafiltration State Adjustment Response Message ID + */ +bool MessageInterpreter::adjustUltrafiltrationState(const Message &vMessage, QVariantList &vData) +{ + bool ok = false; + // TODO : In HD the Ultrafiltration State change shall have the rejection reason like other responses. + if ( ! isType (vMessage, Gui::GuiActionType::ID_AdjustUltrafiltrationStateReq) ) return ok; + if ( ! isPayloadLenValid(vMessage, Gui::GuiActionType::ID_AcknowGeneric ) ) return ok; // This is an exception It has to be changed. + + Model::MAdjustUltrafiltrationStateResponse mData; + ok = mData.fromByteArray(vMessage.data); + LOG_EVENT(mData.toString()); + + mData.toVariantList(vData); + emit didActionReceive(mData.data()); + + return ok; +} + +/*! + * \brief MessageInterpreter::adjustUltrafiltrationEditData + * \details This method interprets Treatment Ultrafiltration Volume Adjustment Response message data + * in vMessage of type Message. + * \param vMessage - The vMessage of type Message which contains all the data, + * require to be interpreted. + * \param vData - Treatment Ultrafiltration Volume Adjustment Response data + * \return true if the data can be extracted as defined for Treatment Ultrafiltration Volume Adjustment Response Message ID + */ +bool MessageInterpreter::adjustUltrafiltrationEdit(const Message &vMessage, QVariantList &vData) +{ + bool ok = false; + if ( ! isValidMessage(vMessage, Gui::GuiActionType::ID_AdjustUltrafiltrationEditRsp) ) return ok; + + Model::MAdjustUltrafiltrationEditResponse mData; + ok = mData.fromByteArray(vMessage.data); + LOG_EVENT("HD," + mData.toString()); + + mData.toVariantList(vData); + emit didActionReceive(mData.data()); + + return ok; +} + +/*! + * \brief MessageInterpreter::adjustUltrafiltrationConfirmData + * \details This method interprets Treatment Ultrafiltration Volume Adjustment Confirm Response message data + * in vMessage of type Message. + * \param vMessage - The vMessage of type Message which contains all the data, + * require to be interpreted. + * \param vData - Treatment Ultrafiltration Volume Adjustment Confirm Response data + * \return true if the data can be extracted as defined for Treatment Ultrafiltration Volume Adjustment Confirm Response Message ID + */ +bool MessageInterpreter::adjustUltrafiltrationConfirm(const Message &vMessage, QVariantList &vData) +{ + bool ok = false; + if ( ! isValidMessage(vMessage, Gui::GuiActionType::ID_AdjustUltrafiltrationConfirmRsp) ) return ok; + + Model::MAdjustUltrafiltrationConfirmResponse mData; + ok = mData.fromByteArray(vMessage.data); + LOG_EVENT("HD," + mData.toString()); + + mData.toVariantList(vData); + emit didActionReceive(mData.data()); + + return ok; +} Index: sources/canbus/MessageInterpreter.h =================================================================== diff -u --- sources/canbus/MessageInterpreter.h (revision 0) +++ sources/canbus/MessageInterpreter.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,87 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file messageinterpreter.h + * \author (last) Behrouz NemaiPour + * \date (last) 22-Jun-2020 + * \author (original) Behrouz NematiPour + * \date (original) 13-Dec-2019 + * + */ +#pragma once + +// Qt +#include + +// Project +#include "MessageGlobals.h" +#include "MModel.h" + +// forward declaration +class tst_messaging; +class tst_logging; + +namespace Can { + +/*! + * \brief The MessageInterpreter class + * \details This the class that interprets the messages to/from frames. + * UI only understands GuiActionType and QVariantList data types + * And CANBUS only understands QCanBusFrame with Hex values in QByteArrays + * This is the class which interpret this data to/from. + */ +class MessageInterpreter : public QObject +{ + Q_OBJECT + + // friend + friend class ::tst_messaging; + friend class ::tst_logging; + + bool isType (const Message &vMessage, Gui::GuiActionType vType) const; + bool isPayloadLenValid (const Message &vMessage, Gui::GuiActionType vType) const; + bool isValidMessage (const Message &vMessage, Gui::GuiActionType vType) const; + + void logInvalidLength (const Gui::GuiActionType &vActionId); + + void printUnhandled (const Message &vMessage ) const; + void logReceivedMessage (const Model::MAbstract &vModel); + + bool interpretMessage_HD (const Message &vMessage, QVariantList &vData) __attribute_warn_unused_result__; + bool interpretMessage_DG (const Message &vMessage, QVariantList &vData) __attribute_warn_unused_result__; + + // ----- Debug + bool canbusFaultCountData (const Message &vMessage, QVariantList &vData) __attribute_warn_unused_result__; + + // ----- Events + // ----- - HD + bool alarmStatus (const Message &vMessage, QVariantList &vData) __attribute_warn_unused_result__; + bool alarmTriggered (const Message &vMessage, QVariantList &vData) __attribute_warn_unused_result__; + bool alarmCleared (const Message &vMessage, QVariantList &vData) __attribute_warn_unused_result__; + + // ----- - DG + + // ----- Adjustments + bool adjustUltrafiltrationState (const Message &vMessage, QVariantList &vData) __attribute_warn_unused_result__; + bool adjustUltrafiltrationEdit (const Message &vMessage, QVariantList &vData) __attribute_warn_unused_result__; + bool adjustUltrafiltrationConfirm (const Message &vMessage, QVariantList &vData) __attribute_warn_unused_result__; + + template + bool notify (const Message &vMessage, QVariantList &vData, Gui::GuiActionType vIdCheck) __attribute_warn_unused_result__; + +public: + explicit MessageInterpreter(QObject *parent = nullptr); + + // interpret the data into GUI understandable Actions/Data + bool interpretMessage(const Message &vMessage, QVariantList &vData) __attribute_warn_unused_result__; + bool interpretMessage(const Gui::GuiActionType &vActionId, const QVariantList &vData, QByteArray &vPayload) __attribute_warn_unused_result__; + +signals: + ACTION_RECEIVE_SIGNALS + +}; +} Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/canbus/caninterface.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/canbus/caninterface.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/canbus/frameinterface.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/canbus/frameinterface.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/canbus/messageacknowmodel.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/canbus/messageacknowmodel.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/canbus/messagebuilder.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/canbus/messagebuilder.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/canbus/messagedispatcher.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/canbus/messagedispatcher.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/canbus/messageglobals.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/canbus/messageinterpreter.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/canbus/messageinterpreter.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/configuration/display.cpp'. Fisheye: No comparison available. Pass `N' to diff? Index: sources/configuration/display.cpp._ =================================================================== diff -u --- sources/configuration/display.cpp._ (revision 0) +++ sources/configuration/display.cpp._ (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,28 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file display.cpp + * \author (last) Behrouz NematiPour + * \date (last) 16-Jan-2020 + * \author (original) Behrouz NematiPour + * \date (original) 24-Sep-2019 + * + */ +#include "display.h" + +using namespace Configuration; + +/*! + * \brief display::display + * \details Constructor + * \param parent - QObject parent owner object. + * Qt handles the children destruction by their parent objects life-cycle. + */ +display::display(QObject *parent) : QObject(parent) +{ + +} Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/configuration/display.h'. Fisheye: No comparison available. Pass `N' to diff? Index: sources/configuration/display.h._ =================================================================== diff -u --- sources/configuration/display.h._ (revision 0) +++ sources/configuration/display.h._ (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,35 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file display.h + * \author (last) Behrouz NematiPour + * \date (last) 24-Oct-2019 + * \author (original) Behrouz NematiPour + * \date (original) 24-Sep-2019 + * + */ +#pragma once + +#include +namespace Configuration { + +/*! + * \brief display brightness and configuration + * \details The display class The Display class controls the display brightness and any other later required display configuration. + */ +class display : public QObject +{ + Q_OBJECT +public: + explicit display(QObject *parent = nullptr); + +signals: + +public slots: +}; + +} Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/configuration/sound.cpp'. Fisheye: No comparison available. Pass `N' to diff? Index: sources/configuration/sound.cpp._ =================================================================== diff -u --- sources/configuration/sound.cpp._ (revision 0) +++ sources/configuration/sound.cpp._ (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,28 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file sound.cpp + * \author (last) Behrouz NematiPour + * \date (last) 16-Jan-2020 + * \author (original) Behrouz NematiPour + * \date (original) 24-Sep-2019 + * + */ +#include "sound.h" + +using namespace Configuration; + +/*! + * \brief sound::sound + * \details Constructor + * \param parent - QObject parent owner object. + * Qt handles the children destruction by their parent objects life-cycle. + */ +sound::sound(QObject *parent) : QObject(parent) +{ + +} Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/configuration/sound.h'. Fisheye: No comparison available. Pass `N' to diff? Index: sources/configuration/sound.h._ =================================================================== diff -u --- sources/configuration/sound.h._ (revision 0) +++ sources/configuration/sound.h._ (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,36 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file sound.h + * \author (last) Behrouz NematiPour + * \date (last) 24-Oct-2019 + * \author (original) Behrouz NematiPour + * \date (original) 24-Sep-2019 + * + */ +#pragma once + +#include + +namespace Configuration { + +/*! + * \brief sound volume and configuration + * \details The sound class The Sound class controls the sound volume and any other later required sound configuration. +*/ +class sound : public QObject +{ + Q_OBJECT +public: + explicit sound(QObject *parent = nullptr); + +signals: + +public slots: +}; + +} Index: sources/gui/GuiController.cpp =================================================================== diff -u --- sources/gui/GuiController.cpp (revision 0) +++ sources/gui/GuiController.cpp (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,323 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file guicontroller.cpp + * \author (last) Peter Lucia + * \date (last) 25-Jun-2020 + * \author (original) Behrouz NematiPour + * \date (original) 24-Sep-2019 + * + */ +#include "GuiController.h" + +// Qt +#include +#include + +// Project +#include "Logger.h" +#include "ApplicationController.h" + +// namespace +using namespace Gui; + +/*! + * \brief GuiController::GuiController + * \details Constructor + * \param parent - QObject parent owner object. + * Qt handles the children destruction by their parent objects life-cycle. + */ +GuiController::GuiController(QObject *parent) : QObject(parent) {} + +/*! + * \brief GuiController::init + * \details Initialized the Class by calling the init() method first + * And initializes the thread vThread by calling initThread + * on success init(). + * \param vThread - the thread + * \return returns the return value of the init() method + */ +bool GuiController::init(QThread &vThread) +{ + if ( ! init() ) return false; + initThread(vThread); + return true; +} + +/*! + * \brief GuiController::quit + * \details quits the class + * Calls quitThread + */ +void GuiController::quit() +{ + // coco begin validated: Application termination is not correctly done in coco!!! + // it has been tested and works perfectly fine in normal run. + quitThread(); // validated +} +// coco end + +/*! + * \brief GuiController::initConnections + * \details Initializes the required signal/slot connection between this class and other objects + * to be able to communicate. + */ +void GuiController::initConnections() +{ + // From HD/DG + connect(&_ApplicationController, SIGNAL(didActionReceive (GuiActionType, const QVariantList &)), + this , SLOT( onActionReceive (GuiActionType, const QVariantList &))); + + + // From OS : USB Drive has been removed physically. + // USB drive + connect(&_ApplicationController, SIGNAL(didUSBDriveMount ()), + this , SLOT( onUSBDriveMount ())); + connect(&_ApplicationController, SIGNAL(didUSBDriveRemove()), + this , SLOT( onUSBDriveRemove())); + + // SD card + connect(&_ApplicationController, SIGNAL(didSDCardStateChange(bool,bool)), + this , SLOT( onSDCardStateChange(bool,bool))); + + // Export + connect(&_ApplicationController, SIGNAL(didExport()), + this , SLOT( onExport())); + + // transmission fail + connect(&_ApplicationController, SIGNAL(didFailedTransmit(Sequence)), + this , SLOT( onFailedTransmit(Sequence))); + + // ---- Signal/Slots + ACTION_RECEIVE_MODEL_BRIDGE_CONNECTIONS(_ApplicationController) +} + +/*! + * \brief ApplicationController::initThread + * \details Moves this object into the thread vThread. + * And checks that this method is called from main thread. + * Also connects quitThread to application aboutToQuit. + * \param vThread - the thread + */ +void GuiController::initThread(QThread &vThread) +{ + // coco begin validated: Application termination is not correctly done in coco!!! + // it has been tested and works perfectly fine in normal run. + // runs in main thread + Q_ASSERT_X(QThread::currentThread() == qApp->thread() , __func__, "The Class initialization must be done in Main Thread" ); + _thread = &vThread; + _thread->setObjectName(QString("%1_Thread").arg(metaObject()->className())); + connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(quit())); + _thread->start(); + moveToThread(_thread); +} +// coco end + +/*! + * \brief GuiController::quitThread + * \details Moves this object to main thread to be handled by QApplicaiton + * And to be destroyed there. + */ +void GuiController::quitThread() +{ + // coco begin validated: Application termination is not correctly done in coco!!! + // it has been tested and works perfectly fine in normal run. + if ( ! _thread ) return; + + // runs in thread + moveToThread(qApp->thread()); // validated +} +// coco end + +/*! + * \brief GuiController initializer + */ +bool GuiController::init() +{ + if ( _init ) return false; + _init = true; + + initConnections(); + + LOG_EVENT("UI," + tr("%1 Initialized").arg(metaObject()->className())); + + return true; +} + +/*! + * \brief An Action has been requested + * \details This method Confirmed that if the action is accepted or not, + * Regarding the current state and the action. + * These actions are only user actions and there is only one user interaction, + * So no need to capture from which screen this action comes since we have the current state. + * Sometimes GuiController requires to investigate with the ApplicationController to get approval from HD device. + * \param vAction - User requested Action + * \param vData - Message data to be transmitted. + */ +void GuiController::doActionTransmit(GuiActionType vAction, const QVariantList &vData) +{ + // coco begin validated: This is a sample code and currently does nothing + // The handleTransmit is a place holder and currently has not been used. + if (! handleTransmit(vAction, vData)) { + // coco end + emit didActionTransmit(vAction, vData); + } +} + +/*! + * \brief GuiController::handleTransmit + * \details If an action request from Gui can be handled in Gui Controller + * without passing to HD, then can be handled here. + * \param vAction - the Requested action + * \param vData - Data of the action + * \return if handled returns true to not to pass to the lower level (Application Controller) + * to not to send to HD then. + */ +bool GuiController::handleTransmit(GuiActionType vAction, const QVariantList &vData) +{ + // coco begin validated: This is a sample code and currently does nothing + Q_UNUSED(vAction) + Q_UNUSED(vData) + + // This is an example implementation of how to handle actions + // which does not require HD approval in GuiController + // Process the GuiView Request. + // It can be processed in GuiController take action and notify GuiView + switch (vAction) { + case GuiActionType::ID_PowerOff: + //qApp->quit(); + + // GUI Controller decides (loop back) + //if (vData == GuiActionData::NoData){ + // // PowerOff noData is a request + // emit didActionReceive (vAction, GuiActionData::Accepted); + // return true; + //} + break; + + //case Another_Command_Which_Doesn't_Require_HD_Approval: + //return true; + //break; + default: + break; + + } + return false; +} +// coco end + +/*! + * \brief Action commanded by HD + * \details An action has been commanded by HD, + * Gui requires to be notified to perform the action. + * \param vAction - Message Action + * \param vData - The data to be translated. + */ +void GuiController::onActionReceive (GuiActionType vAction, const QVariantList &vData) +{ + // Process the command and notify GuiView + // Process ... + emit didActionReceive (vAction, vData); +} + +/*! + * \brief GuiController::onUSBDriveMount + * \details emits didUSBDriveMount signal to notify other classes (GuiView) + * , the USB drive has been mounted. + */ +void GuiController::onUSBDriveMount() +{ + // coco begin validated: This needs user interaction to plug-in USB device + // has been tested manually + emit didUSBDriveMount(); +} +// coco end + +/*! + * \brief GuiController::doUSBDriveUmount + * \details emits didUSBDriveUmount signal to notify other classes (GuiView) + * , the USB drive has been unmounted. + */ +void GuiController::doUSBDriveUmount() +{ + // coco begin validated: This needs user interaction to plug-out the USB device + // has been tested manually + emit didUSBDriveUmount(); +} +// coco end + +/*! + * \brief GuiController::onUSBDriveRemove + * \details emits didUSBDriveRemove signal to notify other classes (GuiView) + * , the USB drive has been removed. + */ +void GuiController::onUSBDriveRemove() +{ + // coco begin validated: This needs user interaction to plug-out the USB device + // has been tested manually + emit didUSBDriveRemove(); +} +// coco end + +/*! + * \brief GuiController::onSDCardStateChange + * \details emits didSDCardStateChange signal to notify other classes (GuiView) + * , the SD Card state has been changed. + * \param vIsReady - SdCard is Ready + * \param vIsReadOnly - SdCard is ReadOnly + */ +void GuiController::onSDCardStateChange(bool vIsReady, bool vIsReadOnly) +{ + // coco begin validated: This needs user interaction to plug-out the SD Card + // has been tested manually + emit didSDCardStateChange(vIsReady, vIsReadOnly); +} +// coco end + +/*! + * \brief GuiController::onExport + * \details The slot which will be called to notify the export is done + * by emitting the didExport signal. + */ +void GuiController::onExport() +{ + // coco begin validated: This needs user interaction to export to USB device + // has been tested manually + emit didExport(); +} +// coco end + +/*! + * \brief GuiController::doExportLog + * \details emits didExportLog signal to notify other classes (ApplicationController) + * , the User requested to export the log. + */ +void GuiController::doExportLog() +{ + // coco begin validated: This needs user interaction to export to USB device + // has been tested manually + emit didExportLog(); +} +// coco end + +/*! + * \brief GuiController::didFailedTransmit + * Raises an HD communication timeout alarm if communication with HD is lost. + * \param seq - Sequence that failed to transmit + */ +void GuiController::onFailedTransmit(Sequence seq) +{ + Q_UNUSED(seq); + AlarmStatusData data; + data.mState = GuiAlarmPriority::ALARM_PRIORITY_HIGH; // Alarm priority + data.mTop = GuiAlarmID::ALARM_ID_HD_COMM_TIMEOUT; // Alarm ID + data.mMuteTimeout = 0; // Alarm timeout + data.mEscalatesIn = 0; // Alarm Escalate Time Period + data.mFlags = QBitArray(16, false); // 16 QBitArray of flags, if needed + emit didActionReceive(data); +} + Index: sources/gui/GuiController.h =================================================================== diff -u --- sources/gui/GuiController.h (revision 0) +++ sources/gui/GuiController.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,94 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file guicontroller.h + * \author (last) Peter Lucia + * \date (last) 25-Jun-2020 + * \author (original) Behrouz NematiPour + * \date (original) 24-Sep-2019 + * + */ +#pragma once + +// Qt +#include + +// Project +#include "main.h" +#include "GuiGlobals.h" +#include "MModel.h" +#include "MessageGlobals.h" + +// define +#define _GuiController GuiController::I() + +using namespace Can; + +// namespace +namespace Gui { + +class GuiController : public QObject +{ + Q_OBJECT + + QThread *_thread = nullptr; + bool _init = false; + +// singleton +SINGLETON(GuiController); + +public slots: + bool init(); + bool init(QThread &vThread); + +private slots: + void quit(); + +private: + void initConnections(); + + void initThread(QThread &vThread); + void quitThread(); + + bool handleTransmit(GuiActionType vAction, const QVariantList &vData); + +public slots: + void doActionTransmit(GuiActionType vAction, const QVariantList &vData); // UI => HD/DG + + void doUSBDriveUmount(); // UI => OS + void doExportLog (); // UI => OS + + +private slots: // Should be private for thread safety and is connected internally. + void onActionReceive (GuiActionType vAction, const QVariantList &vData); // UI <= HD/DG + + void onUSBDriveMount (); // OS => UI + void onUSBDriveRemove(); // OS => UI + + void onSDCardStateChange(bool vIsReady, bool vIsReadOnly); // OS => UI + + void onExport (); // OS => UI + void onFailedTransmit(Sequence seq); + +signals: + void didActionReceive (GuiActionType vAction, const QVariantList &vData); // UI <= HD/DG + void didActionTransmit(GuiActionType vAction, const QVariantList &vData); // UI => HD/DG + + void didUSBDriveMount (); + void didUSBDriveUmount(); + void didUSBDriveRemove(); + + void didSDCardStateChange(bool vIsReady, bool vIsReadOnly); + + void didExportLog(); + void didExport (); + + // ---- Signal/Slots + ADJUST_TRANSMT_MODEL_BRIDGE_DEFINITIONS_PUBLIC + ACTION_RECEIVE_MODEL_BRIDGE_DEFINITIONS +}; +} Index: sources/gui/GuiGlobals.cpp =================================================================== diff -u --- sources/gui/GuiGlobals.cpp (revision 0) +++ sources/gui/GuiGlobals.cpp (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,132 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file guiglobals.cpp + * \author (last) Behrouz NemaiPour + * \date (last) 12-Jun-2020 + * \author (original) Behrouz NematiPour + * \date (original) 28-Oct-2019 + * + */ +#include "GuiGlobals.h" + +// Qt +#include + +// Project +#include "Logger.h" +#include "GuiView.h" +#include "VEventSpy.h" + +// Project +#include "MModel.h" +#include "VView.h" + +#include "VAlarmStatus.h" +#include "VPowerOff.h" + +#include "VTreatmentBloodFlow.h" +#include "VTreatmentDialysateFlow.h" +#include "VTreatmentUltrafiltration.h" +#include "VTreatmentAdjustmentUltrafiltrationState.h" +#include "VTreatmentPressureOcclusion.h" +#include "VTreatmentTime.h" +#include "VTreatmentRanges.h" +#include "VHDOperationModeData.h" +#include "VTreatmentSalineData.h" +#include "VHDTreatmentStatesData.h" + +#include "VDGDrainPumpData.h" +#include "VDGHeatersData.h" +#include "VDGLoadCellReadingsData.h" +#include "VDGOperationModeData.h" +#include "VDGPressuresData.h" +#include "VDGROPumpData.h" +#include "VDGReservoirData.h" +#include "VDGTemperaturesData.h" +#include "VDGValvesStatesData.h" + +#include "VTreatmentAdjustmentDuration.h" +#include "VTreatmentAdjustmentFlows.h" +#include "VTreatmentAdjustmentUltrafiltrationEdit.h" +#include "VTreatmentAdjustmentUltrafiltrationConfirm.h" +#include "VTreatmentAdjustmentSaline.h" + +namespace Gui { + MainView *_viewer = nullptr; + + /*! + * \brief registerTypes + * \details registering meta types + */ + void registerTypes() + { + qRegisterMetaType ("GuiActionType" ); + qRegisterMetaType ("GuiActionData" ); + + qRegisterMetaType ("GuiAlarmID" ); + qRegisterMetaType ("GuiAlarmPriority"); + + qRegisterMetaType ("GuiRequestReasons"); + + + // Note that this Models are not used in the qml + // but Qt needs them to be registered to be able to use them in between threads queue + // by their metadata information. + REGISTER_MODEL_METATYPES + LOG_DEBUG("Models Registered"); + } + + /*! + * \brief registerQmlTypes + * \details registering QML types + */ + void registerQmlTypes() + { + //using namespace View; + qmlRegisterType ("Gui.View" , 0, 1, "GuiView"); + qmlRegisterUncreatableType ("Gui.Actions" , 0, 1, "GuiActions" , QStringLiteral("Used only for enumerations no need to have an object")); + qmlRegisterSingletonType ("Gui.VEventSpy", 0, 1, "GuiEventSpy", [](QQmlEngine *, QJSEngine *) -> QObject * { + return &_VEventSpy; + }); + + REGISTER_VIEW_TYPES + LOG_DEBUG("Views Registered"); + } + + /*! + * \brief startGui + * \details the GUI initializer/starter function + */ + bool startGui() { + _viewer = new MainView; + registerTypes(); + registerQmlTypes(); + + QObject::connect(_viewer, &MainView::statusChanged, qApp, [=](MainView::Status vStatus) { + // coco begin validated: this portion of the code is handling application initialization + // and if not initialized correctly will terminate the application . + // So it had been manually tested. + bool ok = vStatus == MainView::Ready; + if (ok) { + _viewer->show(); + } + else if (vStatus == MainView::Error || vStatus == MainView::Null) { + for (const auto &error : _viewer->errors()) { + LOG_DEBUG(QString("Application Terminated: %1").arg(error.toString())); + } + QCoreApplication::exit(-1); + } + // coco end + }, Qt::QueuedConnection ); + + LOG_DEBUG("MainView Starting"); + _viewer->setSource(QStringLiteral("qrc:/main.qml")); + LOG_DEBUG("MainView started"); + return true; + } +} Index: sources/gui/GuiGlobals.h =================================================================== diff -u --- sources/gui/GuiGlobals.h (revision 0) +++ sources/gui/GuiGlobals.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,181 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file guiglobals.h + * \author (last) Peter Lucia + * \date (last) 25-Jun-2020 + * \author (original) Behrouz NematiPour + * \date (original) 28-Oct-2019 + * + */ +#pragma once + +// Qt +#include + +// Project + +namespace Gui { + class MainView : public QQuickView { + Q_OBJECT + + bool event(QEvent* vEvent) override + { + emit eventSpy(vEvent); + return QQuickView::event(vEvent); + } + signals: + void eventSpy(QEvent* vEvent); + }; + extern MainView *_viewer; + + class GuiActions + { + Q_GADGET + explicit GuiActions(); + + public: + /*! + * \brief The GuiActionsType_Enum enum + * \details + * *** This enum could use the Msg_IDs enum in MsgDefs.h, ***\n + * *** But that enum has values in Normal (BigEndian) ***\n + * *** So it has to be converted, each time it is referenced. ***\n + * *** Since an enum is a constant value, ***\n + * *** There is no point in calculating it on each reference. ***\n + * *** Therefore it is preferred to keep them as constant values ***\n + * *** Exactly as it is going to be shown/used in Denali Messages ***\n + * *** then it can be compared exactly the way it is with no conversion.***\n + */ + enum GuiActionsType_Enum /* : quint16 QML doesn't support enum types */ { + ID_Unknown = 0x0000, + + ID_CANBusFaultCount = 0x9909, + + ID_RawData = 0xFFFE, + + ID_Acknow = 0xFFFF, + ID_AcknowGeneric = 0x0000, //< Generic Acknowledgment is not a unique message ID and inherits its Id from the actual message. Zero is a placeholder + + ID_HDDebugText = 0xF1FF, + ID_DGDebugText = 0xF2FF, + + ID_DGCheckIn = 0x0600, + ID_KeepAlive = 0x0700, + + ID_PowerOff = 0x0100, + ID_ShuttingDown = 0x0E00, + ID_TreatmentTime = 0x0D00, + ID_BloodFlow = 0x0500, + ID_DialysateInletFlow = 0x0800, + ID_DialysateOutletFlow = 0x0B00, + ID_TreatmentRanges = 0x1A00, // 26 + ID_PressureOcclusion = 0x0900, + ID_TreatmentStates = 0x0F00, // 15 + ID_Saline = 0x2F00, // 47 + + ID_AlarmStatus = 0x0200, + ID_AlarmTriggered = 0x0300, + ID_AlarmCleared = 0x0400, + ID_AlarmSilenceReq = 0x3200, // 50 - Not implemented yet on FW side + ID_AlarmSilenceRsp = 0x0000, // Needs to be removed. + + ID_HDOperationModeData = 0x2500, // 37 + + ID_DGROPumpData = 0x1F00, // 31 + ID_DGPressuresData = 0x2000, // 32 + ID_DGDrainPumpData = 0x2400, // 36 + ID_DGOperationModeData = 0x2700, // 39 + ID_DGReservoirData = 0x2800, // 40 + ID_DGValvesStatesData = 0x2A00, // 42 + ID_DGHeatersData = 0x2C00, // 44 + ID_DGLoadCellReadingsData = 0x0C00, // 12 + ID_DGTemperaturesData = 0x2D00, // 45 + + ID_AdjustBloodDialysateReq = 0x1700, // 23 + ID_AdjustBloodDialysateRsp = 0x1800, // 24 + + ID_AdjustUltrafiltrationStateReq = 0x1000, // 16 + // idAcknowGeneric : the response is the AcknowGeneric with the same msgID + + ID_AdjustUltrafiltrationEditReq = 0x1100, // 17 + ID_AdjustUltrafiltrationEditRsp = 0x1300, // 19 + + ID_AdjustUltrafiltrationConfirmReq = 0x1500, // 21 + ID_AdjustUltrafiltrationConfirmRsp = 0x2E00, // 46 + + ID_AdjustDurationReq = 0x1600, // 22 + ID_AdjustDurationRsp = 0x1B00, // 27 + + ID_AdjustSalineReq = 0x1200, // 18 + ID_AdjustSalineRsp = 0x1400, // 20 + + }; + + enum class GuiActionsData_Enum /*: quint8 QML doesn't support*/ { + NoData = 0x00, + + Command = 0x00, // HD=>UI : should be handled in receive + Request = 0x00, // UI=>HD : should be handled in transmit + + // UI=>HD : should be handled in transmit + Accepted = 0x01, + Rejected = 0x02, + + // Power-Off Data // HD=>UI : should be handled in receive + Timeout = 0x01, + }; + + enum Saline_States { // FW currently doesn't have enum for Saline Bolus when provided better to be replaced. + SALINE_STOP_STATE = 0, ///< Saline is not delivered + SALINE_START_STATE , ///< Saline being Delivered + SALINE_DISABLE_STATE , ///< Saline cumulative volume delivery has reached the maximum + }; + + Q_ENUM(GuiActionsType_Enum) + Q_ENUM(GuiActionsData_Enum) + + #include "AlarmDefs.h" + Q_ENUM(Alarm_Priorities) + Q_ENUM(Alarm_List ) + + #include "MsgDefs.h" + Q_ENUM(Request_Reject_Reasons) + + #include "HDDefs.h" + Q_ENUM(HD_Op_Modes) + Q_ENUM(UF_Adjustments) + Q_ENUM(Treatment_States) + Q_ENUM(UF_States) + Q_ENUM(Saline_States) + + #include "DGDefs.h" + Q_ENUM(DG_Op_Modes) + }; + + // to be able to use the enum as signal/slot parameter + typedef GuiActions::GuiActionsType_Enum GuiActionType; + typedef GuiActions::GuiActionsData_Enum GuiActionData; + + typedef GuiActions::Alarm_Priorities GuiAlarmPriority; + typedef GuiActions::Alarm_List GuiAlarmID; + + typedef GuiActions::Request_Reject_Reasons GuiRequestReasons; + + typedef GuiActions::HD_Op_Modes GuiHDOpModes; + typedef GuiActions::DG_Op_Modes GuiDGOpModes; + + typedef GuiActions::UF_Adjustments GuiUFAdjustment; + typedef GuiActions::Treatment_States GuiTreatment_States; + typedef GuiActions::UF_States GuiUFStates; + typedef GuiActions::Saline_States GuiSalineStates; + + void registerTypes(); + void registerQmlTypes(); + + bool startGui(); +} Index: sources/gui/GuiView.cpp =================================================================== diff -u --- sources/gui/GuiView.cpp (revision 0) +++ sources/gui/GuiView.cpp (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,200 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file guiview.cpp + * \author (last) Behrouz NematiPour + * \date (last) 21-May-2020 + * \author (original) Behrouz NematiPour + * \date (original) 24-Sep-2019 + * + */ +#include "GuiView.h" + +// Project +#include "GuiController.h" + +// namespace +using namespace Gui; + +/*! + * \brief GuiView::GuiView + * \details Constructor + * \param parent - QObject parent owner object. + * Qt handles the children destruction by their parent objects life-cycle. + */ +GuiView::GuiView(QObject *parent) +{ + Q_UNUSED(parent) + initConnections(); +} + +/*! + * \brief GuiView::initConnections + * \details Initializes the required signal/slot connection between this class and other objects + * to be able to communicate. + */ +void GuiView::initConnections() +{ + connect(&_GuiController, SIGNAL(didActionReceive (GuiActionType, const QVariantList &)), + this , SLOT( onActionReceive (GuiActionType, const QVariantList &))); + + // since we don't have access to this object because it is created in Qml. + // Connection to the GuiController made here + // It should be defined in the class which wants to connect to signal. + connect(this , SIGNAL(didActionTransmit(GuiActionType,const QVariantList &)), + &_GuiController, SLOT( doActionTransmit(GuiActionType,const QVariantList &))); + + // From UI : USB drive umount + connect(this , SIGNAL(didUSBDriveUmount()), + &_GuiController, SLOT( doUSBDriveUmount())); + // From OS : USB drive removed + connect(&_GuiController, SIGNAL(didUSBDriveMount ()), + this , SLOT( doUSBDriveMount ())); + connect(&_GuiController, SIGNAL(didUSBDriveRemove()), + this , SLOT( doUSBDriveRemove())); + + // SD Card + connect(&_GuiController, SIGNAL(didSDCardStateChange(bool,bool)), + this , SLOT( doSDCardStateChange(bool,bool))); + + connect(&_GuiController, SIGNAL(didExport()), + this , SLOT( doExport())); + + // From UI : Export Log + connect(this , SIGNAL(didExportLog()), + &_GuiController, SLOT( doExportLog())); +} + +/*! + * \brief GuiView::onActionReceive + * \details emits didActionReceive signal to notify other classes (Gui) + * , an action has been received. + * \param vAction - the action + * \param vData - the action data + */ +void GuiView::onActionReceive (GuiActionType vAction, const QVariantList &vData) +{ + // process the evaluation and notify GUI + emit didActionReceive (vAction, vData); +} + +/*! + * \brief GuiView::doActionTransmit + * \details emits didActionTransmit signal to notify other classes (GuiController) + * , an action has been required to be transmitted. + * \param vAction - the action + * \param vData - the action data + */ +void GuiView::doActionTransmit(GuiActionType vAction, const QVariantList &vData) +{ + // TODO : Remove this code later when Investigated thoroughly. + // coco begin validated: This code later needs to be removed when Investigated thoroughly. + // has been tested manually + emit didActionTransmit(vAction, vData); +} +// coco end + +/*! + * \brief GuiView::doActionTransmit + * \details emits didActionTransmit signal to notify other classes (GuiController) + * , an action has been required to be transmitted. + * \note The overloaded method with only one data parameter, for easier use in qml. + * \param vAction - the action + * \param vData - the action data + */ + +void GuiView::doActionTransmit(GuiActionType vAction, const QVariant &vData) +{ + // TODO : Remove this code later when Investigated thoroughly. + // coco begin validated: This code later needs to be removed when Investigated thoroughly. + // has been tested manually + QVariantList mData; + mData += vData; + emit didActionTransmit(vAction, mData); +} +// coco end + +/*! + * \brief GuiView::doUSBDriveMount + * \details emits didUSBDriveMount signal to notify other classes (UI) + * , the USB drive has been mounted. + */ +void GuiView::doUSBDriveMount () +{ + // coco begin validated: This needs user interaction to plug-in USB device + // has been tested manually + emit didUSBDriveMount (); +} +// coco end + +/*! + * \brief GuiView::doUSBDriveUmount + * \details emits didUSBDriveRemove signal to notify other classes (GuiController) + * , the USB drive has been removed. + */ +void GuiView::doUSBDriveUmount() +{ + // coco begin validated: This needs user interaction to plug-in USB device + // has been tested manually + emit didUSBDriveUmount(); +} +// coco end + +/*! + * \brief GuiView::doUSBDriveRemove + * \details emits didUSBDriveRemove signal to notify other classes (UI) + * , the USB drive has been removed. + */ +void GuiView::doUSBDriveRemove() +{ + // coco begin validated: This needs user interaction to plug-in USB device + // has been tested manually + emit didUSBDriveRemove(); +} +// coco end + +/*! + * \brief GuiView::doSDCardStateChange + * \details emits didSDCardStateChange signal to notify other classes (UI) + * , the SD Card Stte has been changed. + * \param vIsReady - SdCard is Ready + * \param vIsReadOnly - SdCard is ReadOnly + */ +void GuiView::doSDCardStateChange(bool vIsReady, bool vIsReadOnly) +{ + // coco begin validated: This needs user interaction to plug-in USB device + // has been tested manually + sdIsReady (vIsReady ); + sdIsReadOnly(vIsReadOnly); +} +// coco end + +/*! + * \brief GuiView::onExport + * \details The slot which will be called to notify the export is done + * by emitting the didExport signal. + */ +void GuiView::doExport() +{ + // coco begin validated: This needs user interaction to plug-in USB device + // has been tested manually + emit didExport(); +} +// coco end + +/*! + * \brief GuiView::doExportLog + * \details emits didExportLog signal to notify other classes (GuiController) + * , the User requested to export the log. + */ +void GuiView::doExportLog() +{ + // coco begin validated: This needs user interaction to plug-in USB device + // has been tested manually + emit didExportLog(); +} +// coco end Index: sources/gui/GuiView.h =================================================================== diff -u --- sources/gui/GuiView.h (revision 0) +++ sources/gui/GuiView.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,75 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file guiview.h + * \author (last) Peter Lucia + * \date (last) 29-Jun-2020 + * \author (original) Behrouz NematiPour + * \date (original) 24-Sep-2019 + * + */ +#pragma once + +// Qt +#include + +// Project +#include "main.h" +#include "GuiGlobals.h" + + +// define +// ... + +// namespace +namespace Gui { + +class GuiView : public QObject +{ + Q_OBJECT + + // coco begin validated: This needs user interaction to plug-in/out SD Card + // has been tested manually + PROPERTY(bool, sdIsReady , false); + PROPERTY(bool, sdIsReadOnly, false); + // coco end + +public: + explicit GuiView(QObject *parent = nullptr); + +private: + void initConnections(); + +private slots: + void onActionReceive (GuiActionType vAction, const QVariantList &vData); // UI <= HD/DG + + void doUSBDriveMount (); + void doUSBDriveRemove(); + + void doExport (); + +public slots: // is public since will be used in the UI and is in the same thread. + void doActionTransmit(GuiActionType vAction, const QVariantList &vData); // UI => HD/DG + void doActionTransmit(GuiActionType vAction, const QVariant &vData); // UI => HD/DG + void doUSBDriveUmount(); + + void doSDCardStateChange(bool vIsReady, bool vIsReadOnly); + + void doExportLog (); + +signals: + void didActionReceive (GuiActionType vAction, const QVariantList &vData); // UI <= HD/DG + void didActionTransmit(GuiActionType vAction, const QVariantList &vData); // UI => HD/DG + + void didUSBDriveMount (); + void didUSBDriveUmount(); + void didUSBDriveRemove(); + + void didExportLog(); + void didExport (); +}; +} Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/gui/guicontroller.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/gui/guicontroller.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/gui/guiglobals.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/gui/guiglobals.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/gui/guiview.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/gui/guiview.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/maintimer.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/maintimer.h'. Fisheye: No comparison available. Pass `N' to diff? Index: sources/model/MAbstract.h =================================================================== diff -u -r618891879f5cdc68e37ee68eea005afb76dd4e5b -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/model/MAbstract.h (.../MAbstract.h) (revision 618891879f5cdc68e37ee68eea005afb76dd4e5b) +++ sources/model/MAbstract.h (.../MAbstract.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -32,7 +32,8 @@ enum class Type_Enum { eDatum, eEvent, - }; + }; + enum class Unit_Enum { eUI, eHD, @@ -65,5 +66,4 @@ QString toString ( ) const; QString description ( ) const; }; - } Index: sources/model/MDGDebugText.h =================================================================== diff -u -r9cc1608f615e66d0f1c3a022aa6d19579d76b241 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/model/MDGDebugText.h (.../MDGDebugText.h) (revision 9cc1608f615e66d0f1c3a022aa6d19579d76b241) +++ sources/model/MDGDebugText.h (.../MDGDebugText.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -48,7 +48,6 @@ bool fromByteArray (const QByteArray &vByteArray , int *vIndex = nullptr) override; Data data ( ) const; }; - } typedef Model::MDGDebugText::Data DGDebugTextData; Index: sources/model/MHDDebugText.h =================================================================== diff -u -r9cc1608f615e66d0f1c3a022aa6d19579d76b241 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/model/MHDDebugText.h (.../MHDDebugText.h) (revision 9cc1608f615e66d0f1c3a022aa6d19579d76b241) +++ sources/model/MHDDebugText.h (.../MHDDebugText.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -47,7 +47,6 @@ bool fromByteArray (const QByteArray &vByteArray , int *vIndex = nullptr) override; Data data ( ) const; }; - } typedef Model::MHDDebugText::Data HDDebugTextData; Index: sources/model/MPowerOff.h =================================================================== diff -u -r15de0cd12dad1ea5107c52e5ed89280bc9e29b1d -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/model/MPowerOff.h (.../MPowerOff.h) (revision 15de0cd12dad1ea5107c52e5ed89280bc9e29b1d) +++ sources/model/MPowerOff.h (.../MPowerOff.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -44,7 +44,6 @@ bool fromByteArray (const QByteArray &vByteArray , int *vIndex = nullptr) override; Data data ( ) const ; }; - } typedef Model::MPowerOff::Data PowerOffData; Index: sources/model/dg/data/MDGDrainPumpData.h =================================================================== diff -u -r3aab84456cfbdc4c4f495975ba9b8968eb844309 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/model/dg/data/MDGDrainPumpData.h (.../MDGDrainPumpData.h) (revision 3aab84456cfbdc4c4f495975ba9b8968eb844309) +++ sources/model/dg/data/MDGDrainPumpData.h (.../MDGDrainPumpData.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -54,7 +54,6 @@ bool fromByteArray (const QByteArray &vByteArray , int *vIndex = nullptr) override; Data data ( ) const ; }; - } typedef Model::MDGDrainPump::Data DGDrainPumpData; Index: sources/model/dg/data/MDGHeatersData.h =================================================================== diff -u -r3aab84456cfbdc4c4f495975ba9b8968eb844309 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/model/dg/data/MDGHeatersData.h (.../MDGHeatersData.h) (revision 3aab84456cfbdc4c4f495975ba9b8968eb844309) +++ sources/model/dg/data/MDGHeatersData.h (.../MDGHeatersData.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -56,7 +56,6 @@ bool fromByteArray (const QByteArray &vByteArray , int *vIndex = nullptr) override; Data data ( ) const ; }; - } typedef Model::MDGHeaters::Data DGHeatersData; Index: sources/model/dg/data/MDGLoadCellReadingsData.h =================================================================== diff -u -r3aab84456cfbdc4c4f495975ba9b8968eb844309 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/model/dg/data/MDGLoadCellReadingsData.h (.../MDGLoadCellReadingsData.h) (revision 3aab84456cfbdc4c4f495975ba9b8968eb844309) +++ sources/model/dg/data/MDGLoadCellReadingsData.h (.../MDGLoadCellReadingsData.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -58,7 +58,6 @@ bool fromByteArray (const QByteArray &vByteArray , int *vIndex = nullptr) override; Data data ( ) const ; }; - } typedef Model::MDGLoadCellReadings::Data DGLoadCellReadingsData; Index: sources/model/dg/data/MDGOperationModeData.h =================================================================== diff -u -r3aab84456cfbdc4c4f495975ba9b8968eb844309 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/model/dg/data/MDGOperationModeData.h (.../MDGOperationModeData.h) (revision 3aab84456cfbdc4c4f495975ba9b8968eb844309) +++ sources/model/dg/data/MDGOperationModeData.h (.../MDGOperationModeData.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -52,7 +52,6 @@ bool fromByteArray (const QByteArray &vByteArray , int *vIndex = nullptr) override; Data data ( ) const ; }; - } typedef Model::MDGOperationMode::Data DGOperationModeData; Index: sources/model/dg/data/MDGPressuresData.h =================================================================== diff -u -r3aab84456cfbdc4c4f495975ba9b8968eb844309 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/model/dg/data/MDGPressuresData.h (.../MDGPressuresData.h) (revision 3aab84456cfbdc4c4f495975ba9b8968eb844309) +++ sources/model/dg/data/MDGPressuresData.h (.../MDGPressuresData.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -58,7 +58,6 @@ bool fromByteArray (const QByteArray &vByteArray , int *vIndex = nullptr) override; Data data ( ) const ; }; - } typedef Model::MDGPressures::Data DGPressuresData; Index: sources/model/dg/data/MDGROPumpData.h =================================================================== diff -u -r3aab84456cfbdc4c4f495975ba9b8968eb844309 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/model/dg/data/MDGROPumpData.h (.../MDGROPumpData.h) (revision 3aab84456cfbdc4c4f495975ba9b8968eb844309) +++ sources/model/dg/data/MDGROPumpData.h (.../MDGROPumpData.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -56,7 +56,6 @@ bool fromByteArray (const QByteArray &vByteArray , int *vIndex = nullptr) override; Data data ( ) const ; }; - } typedef Model::MDGROPump::Data DGROPumpData; Index: sources/model/dg/data/MDGReservoirData.h =================================================================== diff -u -r3aab84456cfbdc4c4f495975ba9b8968eb844309 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/model/dg/data/MDGReservoirData.h (.../MDGReservoirData.h) (revision 3aab84456cfbdc4c4f495975ba9b8968eb844309) +++ sources/model/dg/data/MDGReservoirData.h (.../MDGReservoirData.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -56,7 +56,6 @@ bool fromByteArray (const QByteArray &vByteArray , int *vIndex = nullptr) override; Data data ( ) const ; }; - } typedef Model::MDGReservoir::Data DGReservoirData; Index: sources/model/dg/data/MDGTemperaturesData.h =================================================================== diff -u -r3aab84456cfbdc4c4f495975ba9b8968eb844309 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/model/dg/data/MDGTemperaturesData.h (.../MDGTemperaturesData.h) (revision 3aab84456cfbdc4c4f495975ba9b8968eb844309) +++ sources/model/dg/data/MDGTemperaturesData.h (.../MDGTemperaturesData.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -77,7 +77,6 @@ bool fromByteArray (const QByteArray &vByteArray , int *vIndex = nullptr) override; Data data ( ) const ; }; - } typedef Model::MDGTemperatures::Data DGTemperaturesData; Index: sources/model/dg/data/MDGValvesStatesData.h =================================================================== diff -u -r3aab84456cfbdc4c4f495975ba9b8968eb844309 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/model/dg/data/MDGValvesStatesData.h (.../MDGValvesStatesData.h) (revision 3aab84456cfbdc4c4f495975ba9b8968eb844309) +++ sources/model/dg/data/MDGValvesStatesData.h (.../MDGValvesStatesData.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -70,7 +70,6 @@ bool fromByteArray (const QByteArray &vByteArray , int *vIndex = nullptr) override; Data data ( ) const ; }; - } typedef Model::MDGValvesStates::Data DGValvesStatesData; Index: sources/model/hd/adjustment/MTreatmentAdjustBloodDialysateResponse.h =================================================================== diff -u -r618891879f5cdc68e37ee68eea005afb76dd4e5b -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/model/hd/adjustment/MTreatmentAdjustBloodDialysateResponse.h (.../MTreatmentAdjustBloodDialysateResponse.h) (revision 618891879f5cdc68e37ee68eea005afb76dd4e5b) +++ sources/model/hd/adjustment/MTreatmentAdjustBloodDialysateResponse.h (.../MTreatmentAdjustBloodDialysateResponse.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -57,7 +57,6 @@ bool fromByteArray (const QByteArray &vByteArray , int *vIndex = nullptr) override; Data data ( ) const ; }; - } typedef Model::MAdjustBloodDialysateResponse::Data AdjustBloodDialysateResponseData; Index: sources/model/hd/adjustment/MTreatmentAdjustDurationResponse.h =================================================================== diff -u -r3aab84456cfbdc4c4f495975ba9b8968eb844309 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/model/hd/adjustment/MTreatmentAdjustDurationResponse.h (.../MTreatmentAdjustDurationResponse.h) (revision 3aab84456cfbdc4c4f495975ba9b8968eb844309) +++ sources/model/hd/adjustment/MTreatmentAdjustDurationResponse.h (.../MTreatmentAdjustDurationResponse.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -58,7 +58,6 @@ bool fromByteArray (const QByteArray &vByteArray , int *vIndex = nullptr) override; Data data ( ) const ; }; - } typedef Model::MAdjustDurationResponse::Data AdjustDurationResponseData; Index: sources/model/hd/adjustment/MTreatmentAdjustRequests.h =================================================================== diff -u -r3b4b381d23c267fbc5af29f29e231f03e26ca23b -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/model/hd/adjustment/MTreatmentAdjustRequests.h (.../MTreatmentAdjustRequests.h) (revision 3b4b381d23c267fbc5af29f29e231f03e26ca23b) +++ sources/model/hd/adjustment/MTreatmentAdjustRequests.h (.../MTreatmentAdjustRequests.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -18,7 +18,7 @@ #include //project -#include "guiglobals.h" +#include "GuiGlobals.h" namespace Model { @@ -90,7 +90,8 @@ enum State{ ePaused = 0, eRunning = 1, - }; + }; + State requestedState = ePaused; // the requested state. Initially it's running => paused. // coco begin validated : Has been validated manually. // This object is used statically for now, kept the logic for later usage. @@ -122,7 +123,8 @@ enum Options : quint32 { eDuration = Gui::GuiActions::UF_ADJ_TREATMENT_TIME, eRate = Gui::GuiActions::UF_ADJ_UF_RATE, - }; + }; + float volume = 0; Options option = eDuration; // coco begin validated : Has been validated manually. @@ -141,7 +143,8 @@ enum State { eStop = 0, eStart = 1, - }; + }; + State requestedState = eStop; // the requested state. Initially it's Stop => start. // coco begin validated : Has been validated manually. // This object is used statically for now, kept the logic for later usage. Index: sources/model/hd/adjustment/MTreatmentAdjustUltrafiltrationConfirmResponse.h =================================================================== diff -u -r246bf68b01c9249f2a74dddbba67f49807937fa2 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/model/hd/adjustment/MTreatmentAdjustUltrafiltrationConfirmResponse.h (.../MTreatmentAdjustUltrafiltrationConfirmResponse.h) (revision 246bf68b01c9249f2a74dddbba67f49807937fa2) +++ sources/model/hd/adjustment/MTreatmentAdjustUltrafiltrationConfirmResponse.h (.../MTreatmentAdjustUltrafiltrationConfirmResponse.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -59,7 +59,6 @@ Data data() const; }; - } typedef Model::MAdjustUltrafiltrationConfirmResponse::Data AdjustUltrafiltrationConfirmResponseData; Index: sources/model/hd/adjustment/MTreatmentAdjustUltrafiltrationEditResponse.h =================================================================== diff -u -r246bf68b01c9249f2a74dddbba67f49807937fa2 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/model/hd/adjustment/MTreatmentAdjustUltrafiltrationEditResponse.h (.../MTreatmentAdjustUltrafiltrationEditResponse.h) (revision 246bf68b01c9249f2a74dddbba67f49807937fa2) +++ sources/model/hd/adjustment/MTreatmentAdjustUltrafiltrationEditResponse.h (.../MTreatmentAdjustUltrafiltrationEditResponse.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -55,7 +55,6 @@ Data data() const; }; - } typedef Model::MAdjustUltrafiltrationEditResponse::Data AdjustUltrafiltrationEditResponseData; Index: sources/model/hd/adjustment/MTreatmentAdjustUltrafiltrationStateResponse.h =================================================================== diff -u -r0e528e5f706308c7b0e8f22a4d9dbb5b5715db7c -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/model/hd/adjustment/MTreatmentAdjustUltrafiltrationStateResponse.h (.../MTreatmentAdjustUltrafiltrationStateResponse.h) (revision 0e528e5f706308c7b0e8f22a4d9dbb5b5715db7c) +++ sources/model/hd/adjustment/MTreatmentAdjustUltrafiltrationStateResponse.h (.../MTreatmentAdjustUltrafiltrationStateResponse.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -53,7 +53,6 @@ bool fromByteArray (const QByteArray &vByteArray , int *vIndex = nullptr) override; Data data ( ) const ; }; - } typedef Model::MAdjustUltrafiltrationStateResponse::Data AdjustUltrafiltrationStateResponseData; Index: sources/model/hd/alarm/MAlarmCleared.h =================================================================== diff -u -r6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/model/hd/alarm/MAlarmCleared.h (.../MAlarmCleared.h) (revision 6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5) +++ sources/model/hd/alarm/MAlarmCleared.h (.../MAlarmCleared.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -49,7 +49,6 @@ Data data() const; }; - } typedef Model::MAlarmCleared::Data AlarmClearedData; Index: sources/model/hd/alarm/MAlarmStatusData.h =================================================================== diff -u -rbf645acccabb7b5a84801620c4f7fa0b0e6878e0 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/model/hd/alarm/MAlarmStatusData.h (.../MAlarmStatusData.h) (revision bf645acccabb7b5a84801620c4f7fa0b0e6878e0) +++ sources/model/hd/alarm/MAlarmStatusData.h (.../MAlarmStatusData.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -18,7 +18,7 @@ // Project #include "types.h" -#include "guiglobals.h" +#include "GuiGlobals.h" // forward declarations class tst_models; @@ -44,6 +44,7 @@ eFlag_alarmsSilenced , eFlag_Bits_Length = 16, }; + QString stringPrefix = "Alarm Status"; struct Data { quint32 mState = 0; /*!< State - Alarm Priority value of type unsigned int as 4 bytes extracted out */ @@ -72,7 +73,6 @@ Data data() const ; }; - } typedef Model::MAlarmStatus::Data AlarmStatusData; Index: sources/model/hd/alarm/MAlarmTriggered.h =================================================================== diff -u -r6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/model/hd/alarm/MAlarmTriggered.h (.../MAlarmTriggered.h) (revision 6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5) +++ sources/model/hd/alarm/MAlarmTriggered.h (.../MAlarmTriggered.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -49,7 +49,6 @@ Data data() const; }; - } typedef Model::MAlarmTriggered::Data AlarmTriggeredData; Index: sources/model/hd/data/MHDOperationModeData.h =================================================================== diff -u -r3aab84456cfbdc4c4f495975ba9b8968eb844309 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/model/hd/data/MHDOperationModeData.h (.../MHDOperationModeData.h) (revision 3aab84456cfbdc4c4f495975ba9b8968eb844309) +++ sources/model/hd/data/MHDOperationModeData.h (.../MHDOperationModeData.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -52,7 +52,6 @@ bool fromByteArray (const QByteArray &vByteArray , int *vIndex = nullptr) override; Data data ( ) const ; }; - } typedef Model::MHDOperationMode::Data HDOperationModeData; Index: sources/model/hd/data/MTreatmentFlowsData.h =================================================================== diff -u -raa0772fe1b0ff6b07e9f64e8c38acad66ad5468d -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/model/hd/data/MTreatmentFlowsData.h (.../MTreatmentFlowsData.h) (revision aa0772fe1b0ff6b07e9f64e8c38acad66ad5468d) +++ sources/model/hd/data/MTreatmentFlowsData.h (.../MTreatmentFlowsData.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -105,7 +105,6 @@ Data data() const; }; - } typedef Model:: MBloodFlow::Data BloodFlowData; Index: sources/model/hd/data/MTreatmentOutletFlowData.h =================================================================== diff -u -raa0772fe1b0ff6b07e9f64e8c38acad66ad5468d -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/model/hd/data/MTreatmentOutletFlowData.h (.../MTreatmentOutletFlowData.h) (revision aa0772fe1b0ff6b07e9f64e8c38acad66ad5468d) +++ sources/model/hd/data/MTreatmentOutletFlowData.h (.../MTreatmentOutletFlowData.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -63,7 +63,6 @@ bool fromByteArray (const QByteArray &vByteArray , int *vIndex = nullptr) override; Data data ( ) const ; }; - } typedef Model::MOutletFlow::Data OutletFlowData; Index: sources/model/hd/data/MTreatmentPressureOcclusionData.h =================================================================== diff -u -raa0772fe1b0ff6b07e9f64e8c38acad66ad5468d -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/model/hd/data/MTreatmentPressureOcclusionData.h (.../MTreatmentPressureOcclusionData.h) (revision aa0772fe1b0ff6b07e9f64e8c38acad66ad5468d) +++ sources/model/hd/data/MTreatmentPressureOcclusionData.h (.../MTreatmentPressureOcclusionData.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -59,7 +59,6 @@ bool fromByteArray (const QByteArray &vByteArray , int *vIndex = nullptr) override; Data data ( ) const ; }; - } typedef Model::MPressureOcclusion::Data PressureOcclusionData; Index: sources/model/hd/data/MTreatmentRangesData.h =================================================================== diff -u -r3aab84456cfbdc4c4f495975ba9b8968eb844309 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/model/hd/data/MTreatmentRangesData.h (.../MTreatmentRangesData.h) (revision 3aab84456cfbdc4c4f495975ba9b8968eb844309) +++ sources/model/hd/data/MTreatmentRangesData.h (.../MTreatmentRangesData.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -62,7 +62,6 @@ bool fromByteArray (const QByteArray &vByteArray , int *vIndex = nullptr) override; Data data ( ) const ; }; - } typedef Model::MTreatmentRanges::Data TreatmentRangesData; Index: sources/model/hd/data/MTreatmentSalineData.h =================================================================== diff -u -r7ed86349cdad43d311f776a69ed54c2023265e53 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/model/hd/data/MTreatmentSalineData.h (.../MTreatmentSalineData.h) (revision 7ed86349cdad43d311f776a69ed54c2023265e53) +++ sources/model/hd/data/MTreatmentSalineData.h (.../MTreatmentSalineData.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -57,7 +57,6 @@ bool fromByteArray (const QByteArray &vByteArray , int *vIndex = nullptr) override; Data data ( ) const ; }; - } typedef Model::MTreatmentSaline::Data TreatmentSalineData; Index: sources/model/hd/data/MTreatmentStatesData.h =================================================================== diff -u -r3aab84456cfbdc4c4f495975ba9b8968eb844309 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/model/hd/data/MTreatmentStatesData.h (.../MTreatmentStatesData.h) (revision 3aab84456cfbdc4c4f495975ba9b8968eb844309) +++ sources/model/hd/data/MTreatmentStatesData.h (.../MTreatmentStatesData.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -55,7 +55,6 @@ bool fromByteArray (const QByteArray &vByteArray , int *vIndex = nullptr) override; Data data ( ) const ; }; - } typedef Model::MTreatmentStates::Data TreatmentStatesData; Index: sources/model/hd/data/MTreatmentTimeData.h =================================================================== diff -u -r618891879f5cdc68e37ee68eea005afb76dd4e5b -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/model/hd/data/MTreatmentTimeData.h (.../MTreatmentTimeData.h) (revision 618891879f5cdc68e37ee68eea005afb76dd4e5b) +++ sources/model/hd/data/MTreatmentTimeData.h (.../MTreatmentTimeData.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -57,7 +57,6 @@ bool fromByteArray (const QByteArray &vByteArray , int *vIndex = nullptr) override; Data data ( ) const ; }; - } typedef Model::MTreatmentTime::Data TreatmentTimeData; Index: sources/storage/DriveWatcher.cpp =================================================================== diff -u -r4df19fe88c454bd54abcdaf983be59464c5ef5bc -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/storage/DriveWatcher.cpp (.../DriveWatcher.cpp) (revision 4df19fe88c454bd54abcdaf983be59464c5ef5bc) +++ sources/storage/DriveWatcher.cpp (.../DriveWatcher.cpp) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -23,10 +23,10 @@ #include // Project -#include "storageglobals.h" -#include "logger.h" -#include "applicationcontroller.h" -#include "filehandler.h" +#include "StorageGlobals.h" +#include "Logger.h" +#include "ApplicationController.h" +#include "FileHandler.h" // namespace using namespace Storage; @@ -193,7 +193,7 @@ } /*! - * \brief DriveWatcher::usbcheck + * \brief DriveWatcher::usbCheck * \details Runs usbSeek to mount or umount or remove it * regarding the state it's in. */ Index: sources/storage/DriveWatcher.h =================================================================== diff -u -rb5238b7e7b9973a54a0402f4d6d609989a76629f -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/storage/DriveWatcher.h (.../DriveWatcher.h) (revision b5238b7e7b9973a54a0402f4d6d609989a76629f) +++ sources/storage/DriveWatcher.h (.../DriveWatcher.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -18,7 +18,7 @@ // Project #include "main.h" -#include "threads.h" +#include "Threads.h" // Define #define _DriveWatcher Storage::DriveWatcher::I() @@ -53,7 +53,7 @@ bool _init = false; // Singleton -SINGLETON(DriveWatcher) +SINGLETON(DriveWatcher); public slots: bool init(); @@ -111,12 +111,12 @@ /*! * \brief didSDCardStateChange - * \details If sdcard state changes like removed or is not present this signal will emit. + * \details If SDCard state changes like removed or is not present this signal will emit. */ void didSDCardStateChange(bool vIsReady, bool vIsReadOnly); private slots: - // ----- usb + // ----- USB void usbCheck(); bool usbMount (const QString &vDevice); @@ -126,7 +126,7 @@ void onUSBDriveUmount(); - // ----- sdcard + // ----- SDCard void sdcardSpaceCheck(); }; } Index: sources/storage/FileHandler.cpp =================================================================== diff -u --- sources/storage/FileHandler.cpp (revision 0) +++ sources/storage/FileHandler.cpp (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,209 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file FileHandler.cpp + * \author (last) Behrouz NematiPour + * \date (last) 22-Apr-2020 + * \author (original) Behrouz NematiPour + * \date (original) 24-Sep-2019 + * + */ +#include "FileHandler.h" + +//Qt +#include +#include +#include +#include +#include +#include +#include + +// Project +#include "Logger.h" + +// namespace +using namespace Storage; + +/*! + * \brief FileHandler::write + * \details Writes the content of vContent into the file vFileName. + * \param vFileName - Source file name + * \param vContent - The content which is going to be written in the file. + * \param vAppend - if set to true the content will be appended at the end of the file. + * \return false if file can't be opened. + */ +void FileHandler::errOut(const QString &vMessage) +{ + static uint count; + static QString mCritical; + // coco begin validated : This has been manually test. Needs file system access to produce errors for hundred times. + if (mCritical != vMessage || !(count % 1000)) { + // coco end + count = 0; + mCritical = vMessage; + QTextStream err(stderr); + err << "FS" << " " + << QDate::currentDate().toString("yyyy_MM_dd") << " " + << QTime::currentTime().toString("HH:mm:ss" ) << " " + << mCritical + << endl; + } + ++count; +} + +bool FileHandler::write(const QString &vFileName, const QString &vContent, bool vAppend) +{ + QFile file(vFileName); + QFile::OpenMode openMode = vAppend ? + QFile::Text | QFile::Append : + QFile::Text | QFile::WriteOnly; + // coco begin validated : This has been manually test. Needs file system access to make file the way it can't be opened for writing. + if (! file.open(openMode)) { + QString msg = QString("Can't open file for write (%1).Possible corrupted file system").arg(vFileName); + // here can't use LOG_XXXX because if the folder can't be created then the log can't be written. + errOut (msg); + return false; + } + // coco end + QTextStream out(&file); + out << vContent; + out.flush(); + return true; +} + +/*! + * \brief FileHandler::read + * \details reads file vFilename content into vContent variable. + * \param vFileName - Source file name + * \param vContent - The content of the file which will be set when done. + * \return false if file can't be opened. + */ +bool FileHandler::read(const QString &vFileName, QString &vContent) +{ + QFile file(vFileName); + if (! file.open(QFile::Text | QFile::ReadOnly)) { + QString msg = QString("Can't open file for read (%1).Possible corrupted file system").arg(vFileName); + // here can't use LOG_XXXX because if the folder can't be created then the log can't be written. + errOut (msg); + return false; + } + QTextStream in(&file); + vContent = in.readAll(); + return true; +} + +/*! + * \brief FileHandler::copyFolder + * \details Copies all the file and folders recursively. + * \param vSource - The source folder + * \param vDestination - The destination folder + * \return Tue on successful execution. + * \note This method uses the Linux "cp -r vSource vDestination" command + * Not a Thread-Safe. + * + */ +int FileHandler::copyFolder(const QString &vSource, const QString &vDestination ) +{ + // coco begin validated: This needs user interaction to export to USB device + // has been tested manually since currently it is the only place it has been used. + QString cp = "cp"; + QStringList arguments; + arguments << "-r" << vSource << vDestination; + int result = QProcess::execute(cp, arguments); + return result; +} +// coco end + +/*! + * \brief FileHandler::removeFiles + * \details + * \param vFolder + * \param vFilter + * \param vDateOlderThan + * \return + */ +int FileHandler::removeFiles(const QStringList &vFolders, const QStringList &vNameFilter, const QDate &vDateOlderThan) +{ + int countRemoved = 0; + for (const auto &folder : vFolders) { + QDir dir(folder); + dir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks); + dir.setSorting(QDir::Time | QDir::Reversed); + QFileInfoList infoList = dir.entryInfoList(vNameFilter); + for (const auto &info : infoList) { + QDateTime fileTime = info.lastModified(); + QString fileName = info.absoluteFilePath(); + // coco begin validated : This has been manually tested since requires to change in file system to reproduce the error. + if (fileTime.isValid()) { + if (fileTime.date() <= vDateOlderThan) { + if (QFile::remove(fileName)) { + ++countRemoved; + errOut(QString("%1 File(s) %2 removed").arg(countRemoved).arg(fileName)); + } + else { + errOut(QString("Can't delete file : ") + fileName); + } + } + } + else { + errOut(QString("Can't get last modified date of file : ") + fileName); + } + // coco end + } + } + return countRemoved; +} + +/*! + * \brief FileHandler::makeFolder + * \details Create the folder vFolder if it doesn't exist. + * \param vFolder - the folder to create + * \return true on successful creation + */ +bool FileHandler::makeFolder(const QString &vFolder) +{ + QDir dir(vFolder); + if ( ! dir.exists(vFolder) ) { + if ( ! dir.mkpath(vFolder) ) { + QString msg = "Can't create folder " + vFolder; + // here can't use LOG_XXXX because if the folder can't be created then the log can't be written. + errOut(msg); + return false; + } + } + return true; +} + +/*! + * \brief FileHandler::isMounted + * \param vPath - the rootPath of the device mount point + * \return true - if the given vPath is not empty and is in list of mounted devices + * if so it also has to be ready and valid. + */ +bool FileHandler::isMounted(const QString &vPath, bool *vIsReadOnly) +{ + // coco begin validated: Needed User Interaction to make the device not ready so tested manually + bool mounted = false; + // removing the extra '/' from the vPath if there is to be able to compare to the root path of the storage + QString path = vPath.trimmed(); + if (path.isEmpty()) return false; + int lastIndex = path.size() - 1; + if (path.at(lastIndex) == "/") path.remove(lastIndex, 1); + // check to see if the path in the list of mounted rootPaths + foreach (const QStorageInfo &storage, QStorageInfo::mountedVolumes()) { + if (storage.isValid() && storage.isReady()) { + if ( storage.rootPath() == path ) { + if (vIsReadOnly) *vIsReadOnly = storage.isReadOnly(); + mounted = true; + break; + } + } + } + return mounted; +} +// coco end Index: sources/storage/FileHandler.h =================================================================== diff -u --- sources/storage/FileHandler.h (revision 0) +++ sources/storage/FileHandler.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,43 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file filehandler.h + * \author (last) Behrouz NematiPour + * \date (last) 02-Apr-2020 + * \author (original) Behrouz NematiPour + * \date (original) 24-Sep-2019 + * + */ +#pragma once + +// Qt +#include +class QDate; + +namespace Storage { + +/*! + * \brief The FileHandler class + * This class is suppose to be the static class + * which contains methods to manipulate files and folders + * Since it is static it doesn't have thread so needs to be used with care + * and the class(es) which is using it needs to be taking care of the threading + */ +class FileHandler +{ + static void errOut(const QString &vMessage); + +public: + static bool write(const QString &vFileName, const QString &vContent, bool vAppend = true); + static bool read (const QString &vFileName, QString &vContent); + + static int copyFolder (const QString &vSource, const QString &vDestination); + static int removeFiles(const QStringList &vFolders, const QStringList &vNameFilter, const QDate &vDateOlderThan); + static bool makeFolder (const QString &vFolder); + static bool isMounted (const QString &vPath, bool *vIsReadOnly = nullptr); +}; +} Index: sources/storage/Logger.cpp =================================================================== diff -u --- sources/storage/Logger.cpp (revision 0) +++ sources/storage/Logger.cpp (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,399 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file logger.cpp + * \author (last) Behrouz NematiPour + * \date (last) 13-Apr-2020 + * \author (original) Behrouz NematiPour + * \date (original) 24-Sep-2019 + * + */ +#include "Logger.h" + +// Qt +#include +#include +#include +#include +#include +#include + +// Project +#include "DriveWatcher.h" +#include "Threads.h" +#include "StorageGlobals.h" +#include "MainTimer.h" +#include "FileHandler.h" +#include "format.h" + +using namespace Storage; + +/*! + * \brief Logger::Logger + * \details Constructor + * \param parent - QObject parent owner object. + * Qt handles the children destruction by their parent objects life-cycle. + */ +Logger::Logger(QObject *parent) : QObject(parent) { + _logFileNamePrefix = QFileInfo(qApp->applicationFilePath()).baseName(); +} + +/*! + * \brief Logger::init + * \details Initializes the Class. + * \return False if it has been called before. + */ +bool Logger::init() +{ + if ( _init ) return false; + _init = true; + + // runs in thread + checkLogPath(); + initConnections(); + + LOG_EVENT("UI," + tr("%1 Initialized").arg(metaObject()->className())); + + return true; +} + +/*! + * \brief Logger::init + * \details Initialized the Class by calling the init() method first + * And initializes the thread vThread by calling initThread + * on success init(). + * \param vThread - the thread + * \return returns the return value of the init() method + */ +bool Logger::init(QThread &vThread) +{ + // coco begin validated: Application is not running in multi-threaded mode for testing + // it has been tested and works perfectly fine in normal run. + if ( ! init() ) return false; + initThread(vThread); + return true; +} +// coco end + +/*! + * \brief Logger quit + * \details quits the class + * Calls quitThread + */ +void Logger::quit() +{ + // coco begin validated: Application termination is not correctly done in coco!!! + // it has been tested and works perfectly fine in normal run. + quitThread(); // validated +} +// coco end + +/*! + * \brief Logger::initConnections + * \details Initializes the required signal/slot connection between this class and other objects + * to be able to communicate. + * \note No connection has been defined yet. + */ +void Logger::initConnections() +{ + connect(&_exportLogsWatcher, SIGNAL(finished ()), + this , SLOT(onExportLogs())); + + connect(this, SIGNAL(didLog(QString,LogType)), + this, SLOT( onLog(QString,LogType))); + + + connect(&_MainTimer, SIGNAL( didDateChange ()), + this , SLOT( concurrentRemoveLogs())); + + connect(&_removeLogsWatcher, SIGNAL(finished ()), + this , SLOT(onRemoveLogs())); + + connect(&_DriveWatcher, SIGNAL( didSDCardSpaceChange(bool, qint64, qint64, quint8)), + this , SLOT( onSDCardSpaceChange(bool, qint64, qint64, quint8))); +} + +/*! + * \brief Logger::initThread + * \details Moves this object into the thread vThread. + * And checks that this method is called from main thread. + * Also connects quitThread to application aboutToQuit. + * \param vThread - the thread + */ +void Logger::initThread(QThread &vThread) +{ + // coco begin validated: Application is not running in multi-threaded mode for testing + // it has been tested and works perfectly fine in normal run. + // runs in main thread + Q_ASSERT_X(QThread::currentThread() == qApp->thread() , __func__, "The Class initialization must be done in Main Thread" ); + _thread = &vThread; + _thread->setObjectName(QString("%1_Thread").arg(metaObject()->className())); + connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(quit())); + _thread->start(); + moveToThread(_thread); +} +// coco end +/*! + * \brief Logger::quitThread + * \details Moves this object to main thread to be handled by QApplicaiton + * And to be destroyed there. + */ +void Logger::quitThread() +{ + // coco begin validated: Application termination is not correctly done in coco!!! + // it has been tested and works perfectly fine in normal run. + if (! _thread) return; + + // runs in thread + moveToThread(qApp->thread()); // validated +} +// coco end + +void Logger::onLog(const QString &vContent, LogType vLogType) +{ + log(vContent,vLogType); +} + +/*! + * \brief Logger::checkLogPath + * \details Sets the log paths and creates them if didn't exist. + */ +void Logger::checkLogPath() +{ + setLogBasePath(); // try to use /media/sd_card on device + // coco begin validated: It can only happen if the file system is readonly for any reason. + // it has been tested and works perfectly fine in normal run. + if (! setLogPath()) { // check and create log folders & if unsuccessful then + // coco end + setLogBasePath(true); // try to use application folder + setLogPath ( ); // check and create log folders // Note: it may require to check for write access regarding device setup + } +} + +/*! + * \brief Logger::setLogBasePath + * \details Tries to the set the log path to the default log path (Log_Base_Path_Name) + * Will set the application folder as the base log path if can't set the log path to the default. + * Will log the event in that case. + * \param vUseApplicationDirPath + */ +void Logger::setLogBasePath(bool vUseApplicationDirPath) +{ + if (vUseApplicationDirPath) { + _dir.setPath(qApp->applicationDirPath()); + // Don't use LOG_XXXXX, At this moment Logger has not been initialized yet + qDebug() << QString("Application path used for events logging (%1)").arg(_dir.path()); + } + else { + _dir.setPath(SDCard_Base_Path_Name); + } +} + +/*! + * \brief Logger::setLogPath + * \details set the log path for each of the Datum, Event, Error log types + * \return False if can not st the log paths. + */ +bool Logger::setLogPath() +{ + bool ok = true; + // coco begin validated: Has been tested manually, this needs user interaction to check the file system + if ( ok && ! setLogPath(LogType::eLogDebug) ) ok = false; + if ( ok && ! setLogPath(LogType::eLogEvent) ) ok = false; + if ( ok && ! setLogPath(LogType::eLogDatum) ) ok = false; + return ok; +} +// coco end + +/*! + * \brief Logger::setLogPath + * \details Sets the log path for the log type vLogType + * Creates the folder if not exists. + * \param vLogType - log type + * \return returns false if the path doesn't exist and folder can't be created. + */ +bool Logger::setLogPath(LogType vLogType) +{ + bool ok = false; + switch (vLogType) { + case LogType::eLogDebug: + _logPathNames[vLogType] = _dir.path() + "/" + _logBasePathNames[vLogType]; + break; + + default: + _logPathNames[vLogType] = _dir.path() + "/" + _logBasePathNames[vLogType]; + break; + } + ok = FileHandler::makeFolder(_logPathNames[vLogType]); + return ok; +} + +/*! + * \brief Logger::log + * \details Logs the content vContent in log type of vLogType. + * \param vContent - Log content + * \param vLogType - Log type + * \note This method is not thread-safe so is private and needs to be called by concurrentLog + * Which uses QtConcurrent::run to run in thread and thread-safe. + */ +void Logger::log(const QString &vContent, LogType vLogType) +{ + QString date = QDate::currentDate().toString(_dateFormat); + QString fileName = date + _dateSeparator + _logFileNamePrefix; + switch (vLogType) { + case LogType::eLogEvent: + case LogType::eLogDatum: + case LogType::eLogDebug: + fileName += _logFileNameExt[vLogType]; + break; + + default: + fileName += _logFileNameExt[eLogDebug]; + LOG_DEBUG(QString("Incorrect type of logging %1").arg(vLogType)); + } + + QString mContent = QTime::currentTime().toString(_timeFormat) + _separator; + + QString logPrefix = _logPrefix[vLogType]; + if ( ! logPrefix.isEmpty()) { + mContent += logPrefix; + mContent += _separator; + } + mContent += vContent; + + QString logPathName = _logPathNames[vLogType]; + if (logPathName.isEmpty()) + logPathName = _logPathNames[eLogDebug]; + _logFileName = logPathName + fileName; + FileHandler::write(_logFileName, mContent + "\r\n", true); + if (vLogType == eLogDebug) { +#ifdef QT_DEBUG + //mContent.prepend("\033[1;31m --- @ --- \033[0m"); + mContent.prepend(" @ "); +#endif + qDebug().noquote() << mContent; + } +} + + +bool Logger::exportLogs() +{ + // coco begin validated: This needs user interaction to check the old files deleted + // has been tested manually + int result = 0; + static QString mOSource; + QString mDestination = USB_Mount_Point; + for ( const auto &iType : { eLogEvent , eLogDatum } ) { + QString mCSource = _logPathNames[iType]; + if (mOSource != mCSource) { + mOSource = mCSource; + // Copy Folder + result = FileHandler::copyFolder( mCSource, mDestination); + } + } + mOSource = ""; + return result >= 0; // refer to QProcess::execute(hit F1 on execute) doc. +} +// coco end + +/*! + * \brief Logger::concurrentExportLogs + * \details Exports the log files from log folder (Storage::Log_Base_Path_Name_Location) + * into USB drive folder (Storage::USB_Mount_Point) + * \return always returns true for now. + * \note This method uses QtConcurrent run to execute the FileHandler copyFolder method. + */ +bool Logger::concurrentExportLogs() +{ + // coco begin validated: This needs user interaction to export to USB device + // has been tested manually + LOG_DEBUG("Export Logs Start"); + QFuture future = QtConcurrent::run(this, &Logger::exportLogs); + _exportLogsWatcher.setFuture(future); + return true; +} +// coco end + +void Logger::onExportLogs() +{ + // coco begin validated: This needs user interaction to export to USB device + // has been tested manually + LOG_DEBUG(QString("Export Logs Ended: %1").arg(_exportLogsWatcher.result())); + emit didExportLogs(); +} +// coco end + +/*! + * \brief Logger::removeLogs + * \details Remove old logs by iterating in the log/service folders and look for expired logs. + * \return count file(s) have been removed. + */ +int Logger::removeLogs() +{ + // coco begin validated: This needs user interaction to check the old files deleted + // has been tested manually + static QString mOSource; + int countRemoved = 0; + QStringList mLogFileFilter; + QDate mOlderThan ; + for ( const auto &iType : { eLogEvent , eLogDatum , eLogDebug } ) { + QString mCSource = _logPathNames[iType]; + if (mOSource != mCSource) { + mOSource = mCSource; + // Remove Logs + if (_logTypeExpiryDay.value(iType)) { + mOlderThan = QDate().currentDate().addDays( _logTypeExpiryDay.value(iType) * -1 /*Please Notice (-1)*/ ); + mLogFileFilter = Format::toStringList(_logFileNameExt .values(iType), true, "*"); + LOG_DEBUG(QString("Removing logs older than %1 from folder %2").arg(mOlderThan.toString("yyyy-MM-dd")).arg(mCSource)); + countRemoved += FileHandler::removeFiles({ mCSource }, mLogFileFilter, mOlderThan); + } + else { + LOG_DEBUG("Current day logs cannot be deleted"); + } + } + } + mOSource = ""; + return countRemoved; +} +// coco end + +/*! + * \brief Logger::concurrentRemoveLogs + * \details + * + * \return always returns true for now. + * \note This method uses QtConcurrent run to execute the FileHandler copyFolder method. + */ +bool Logger::concurrentRemoveLogs() +{ + // coco begin validated: This needs user interaction to check the old files deleted + // has been tested manually + LOG_DEBUG("Remove Logs Start"); + QFuture mFuture = QtConcurrent::run(this,&Logger::removeLogs); + _removeLogsWatcher.setFuture(mFuture); + return true; +} +// coco end + +void Logger::onRemoveLogs() +{ + // coco begin validated: This needs user interaction to export to USB device + // has been tested manually + LOG_DEBUG(QString("Remove Logs Ended: %1").arg(_removeLogsWatcher.result())); + emit didRemoveLogs(); +} + +void Logger::onSDCardSpaceChange(bool vReady, qint64 vTotal, qint64 vAvailable, quint8 vPercent) +{ + Q_UNUSED(vTotal ) + Q_UNUSED(vAvailable ) + if ( ! vReady ) return; + if (vPercent < _availableSpacePercent ) { + concurrentRemoveLogs(); + } +} +// coco end Index: sources/storage/Logger.h =================================================================== diff -u --- sources/storage/Logger.h (revision 0) +++ sources/storage/Logger.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,184 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file logger.h + * \author (last) Behrouz NematiPour + * \date (last) 04-Feb-2020 + * \author (original) Behrouz NematiPour + * \date (original) 24-Sep-2019 + * + */ +#pragma once + +// Qt +#include +#include +#include + +// Project +#include "main.h" +#include "StorageGlobals.h" + + +// Define +#define _Logger Storage::Logger::I() + +#define LOG_EXPORT _Logger.concurrentExportLogs() + + +#define LOG_DEBUG(vCONTENT) emit Storage::Logger::I().didLog(vCONTENT, Storage::Logger::LogType::eLogDebug) + +#define LOG_EVENT(vCONTENT) emit Storage::Logger::I().didLog(vCONTENT, Storage::Logger::LogType::eLogEvent) +#define LOG_DATUM(vCONTENT) emit Storage::Logger::I().didLog(vCONTENT, Storage::Logger::LogType::eLogDatum) + +// forward declarations +class tst_logging; + +namespace Storage { + +/*! + * \brief The Logger class + * \details Main logger class that has all the required implementation for logging. + * The provided interface is the LOG_DATUM, LOG_EVENT, LOG_DEBUG, LOG_EXPORT defines + * and no other methods. + * This should have its own thread. + * \note + * PLEASE BE CAREFUL THIS CLASS IS USING QtConcurrent::run FOR THE EXPORT LOG FILES. + * AND ONLY PRIVATE VOID LOG (,) IS CALLING IN POOLED THREAD + * PLEASE BE VERY CAREFUL. + * ALL THE OTHER CLASSES TO USE THIS CLASS SHOULD ONLY USE LOG_DATUM, LOG_EVENT, LOG_DEBUG + * TO DO THE LOGGING + */ +class Logger : public QObject +{ + Q_OBJECT + + // friends + friend class ::tst_logging; + +public : + enum LogType { + eLogDebug, ///< Application Error : CANBus messages doesn't have error it's Event/Data only + + eLogEvent, ///< Massages on the CANBus : Error is an event type + eLogDatum, ///< Massages on the CANBus : Broadcast data type + + eLogType_Count, + }; + +private: + QDir _dir; + QString _logFileNamePrefix; + QHash _logPathNames; + const QHash _logBasePathNames { + { LogType::eLogEvent, "log/" }, + { LogType::eLogDatum, "log/" }, + { LogType::eLogDebug, "service/" }, + }; + + const QHash _logPrefix { // Will be used for the logging in the file + { LogType::eLogEvent, "E" }, + { LogType::eLogDatum, "D" }, + { LogType::eLogDebug, "" }, // it has its own file and all the content is Error + }; + + const QHash _logTypeName { // Will be used for for information + { LogType::eLogEvent, "Event" }, + { LogType::eLogDatum, "Datum" }, + { LogType::eLogDebug, "Error" }, // it has its own file and all the content is Error + }; + + const QHash _logFileNameExt { + { LogType::eLogEvent, ".log" }, + { LogType::eLogDatum, ".log" }, + { LogType::eLogDebug, ".err" }, + }; + + const QHash _logTypeExpiryDay { + { LogType::eLogEvent, 15 }, + { LogType::eLogDatum, 15 }, + { LogType::eLogDebug, 5 }, + }; + + const qint8 _availableSpacePercent = 25; // currently 16G SD-Card so 4G should always be available. + + const char *_dateFormat = "yyyy_MM_dd"; + const char *_timeFormat = "HH:mm:ss"; + + const char *_dateSeparator = "_"; // used in filename + const char *_separator = ","; + + QString _logFileName = ""; + + QFutureWatcher _exportLogsWatcher; + QFutureWatcher _removeLogsWatcher; + + QThread *_thread = nullptr; + bool _init = false; + +// Singleton +SINGLETON(Logger); + +public slots: + bool init(); + bool init(QThread &vThread); + +private slots: + void quit(); + +private: + void initConnections(); + + void initThread(QThread &vThread); + void quitThread(); + +private: +// ----- setting up + void checkLogPath (); + void setLogBasePath (bool vUseApplicationDirPath = false); + bool setLogPath (); + bool setLogPath (LogType vLogType); + +// ----- Export structure +private : + bool exportLogs(); +public slots: // this slot is thread safe and can be called from outside by LOG_EXPORT. + bool concurrentExportLogs(); + void onExportLogs(); +signals: + void didExportLogs(); + +// ----- Remove Old Logs structure +private: + int removeLogs(); +private slots: // this slot is thread safe and can be called from outside but preferred not to. + bool concurrentRemoveLogs(); + void onRemoveLogs(); +signals: + void didRemoveLogs(); + +// ----- Available space is low +private slots: + void onSDCardSpaceChange(bool vReady, qint64 vTotal, qint64 vAvailable, quint8 vPercent); + + +// ----- logging structure +private slots: + void onLog (const QString &vContent, LogType vLogType); +private: + void log (const QString &vContent, LogType vLogType); + +signals: + /*! + * \brief didLog + * \details Notifies the logger on a request for log + * \param vContent - content as type of string to be logged + * \param vLogType - the type of logging of type Storage::Logger::LogType + */ + void didLog (const QString &vContent, LogType vLogType); +}; +} Index: sources/storage/StorageGlobals.cpp =================================================================== diff -u --- sources/storage/StorageGlobals.cpp (revision 0) +++ sources/storage/StorageGlobals.cpp (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,26 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file storageglobals.cpp + * \author (last) Behrouz NematiPour + * \date (last) 07-May-2020 + * \author (original) Behrouz NematiPour + * \date (original) 02-Jan-2020 + * + */ + +#include "StorageGlobals.h" + +namespace Storage +{ + // USB + const char *USB_Mount_Point = "/media/usb/"; + const char *USB_File_System = "vfat"; + + // Log + const char *SDCard_Base_Path_Name = "/media/sd-card/"; +} Index: sources/storage/StorageGlobals.h =================================================================== diff -u --- sources/storage/StorageGlobals.h (revision 0) +++ sources/storage/StorageGlobals.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,29 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file storageglobals.h + * \author (last) Behrouz NematiPour + * \date (last) 07-May-2020 + * \author (original) Behrouz NematiPour + * \date (original) 02-Jan-2020 + * + */ +#pragma once + +/*! + * Contains the shared constants between storage classes. + */ +namespace Storage +{ + // USB + extern const char *USB_Mount_Point; + extern const char *USB_File_System; + + // Log + extern const char *SDCard_Base_Path_Name; + +} Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/storage/filehandler.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/storage/filehandler.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/storage/logger.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/storage/logger.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/storage/settings.cpp'. Fisheye: No comparison available. Pass `N' to diff? Index: sources/storage/settings.cpp._ =================================================================== diff -u --- sources/storage/settings.cpp._ (revision 0) +++ sources/storage/settings.cpp._ (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,28 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file settings.cpp + * \author (last) Behrouz NematiPour + * \date (last) 16-Jan-2020 + * \author (original) Behrouz NematiPour + * \date (original) 24-Sep-2019 + * + */ +#include "settings.h" + +using namespace Storage; + +/*! + * \brief Settings::Settings + * \details Constructor + * \param parent - QObject parent owner object. + * Qt handles the children destruction by their parent objects life-cycle. + */ +Settings::Settings(QObject *parent) : QObject(parent) +{ + +} Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/storage/settings.h'. Fisheye: No comparison available. Pass `N' to diff? Index: sources/storage/settings.h._ =================================================================== diff -u --- sources/storage/settings.h._ (revision 0) +++ sources/storage/settings.h._ (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,32 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file settings.h + * \author (last) Behrouz NematiPour + * \date (last) 21-Oct-2019 + * \author (original) Behrouz NematiPour + * \date (original) 24-Sep-2019 + * + */ +#pragma once + +#include + +namespace Storage { + +class Settings : public QObject +{ + Q_OBJECT +public: + explicit Settings(QObject *parent = nullptr); + +signals: + +public slots: +}; + +} Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/storage/storageglobals.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/storage/storageglobals.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/threads.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/threads.h'. Fisheye: No comparison available. Pass `N' to diff? Index: sources/utility/format.h =================================================================== diff -u -rd2035a8728794afeefaa244bf8d1597926d945f5 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/utility/format.h (.../format.h) (revision d2035a8728794afeefaa244bf8d1597926d945f5) +++ sources/utility/format.h (.../format.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -1,16 +1,16 @@ /*! - * + * * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. * \copyright * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. - * + * * \file format.h * \author (last) Behrouz NematiPour * \date (last) 07-May-2020 * \author (original) Behrouz NematiPour * \date (original) 16-Dec-2019 - * + * */ #pragma once @@ -31,4 +31,3 @@ static QByteArray fromVariant (const QVariant &vData ); static QStringList toStringList (const QList vList, bool vRemoveDuplicate = false, QString vPrefix = ""); }; - Index: sources/utility/types.h =================================================================== diff -u -rd2035a8728794afeefaa244bf8d1597926d945f5 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/utility/types.h (.../types.h) (revision d2035a8728794afeefaa244bf8d1597926d945f5) +++ sources/utility/types.h (.../types.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -1,16 +1,16 @@ /*! - * + * * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. * \copyright * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. - * + * * \file types.h * \author (last) Behrouz NematiPour * \date (last) 07-May-2020 * \author (original) Behrouz NematiPour * \date (original) 16-Dec-2019 - * + * */ #pragma once @@ -24,7 +24,7 @@ // Project #include "format.h" -#include "logger.h" +#include "Logger.h" // defines #define GetValue(vData, vIndex, vValue ) Types::getValue<>(vData, vIndex, vValue, QT_STRINGIFY(vValue)) @@ -131,7 +131,6 @@ } }; - template < typename T > bool Types::getValue(const QByteArray &vData, int &vStartIndex, T &vValue, QString vValueName) { int end = vStartIndex + sizeof(T); Index: sources/view/VEventSpy.cpp =================================================================== diff -u -rda52c90a17adea2160ac93042e0632a4cda46b1a -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/view/VEventSpy.cpp (.../VEventSpy.cpp) (revision da52c90a17adea2160ac93042e0632a4cda46b1a) +++ sources/view/VEventSpy.cpp (.../VEventSpy.cpp) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -18,8 +18,8 @@ #include // Project -#include "guiglobals.h" -#include "logger.h" +#include "GuiGlobals.h" +#include "Logger.h" using namespace View; Index: sources/view/VEventSpy.h =================================================================== diff -u -rfc6ab39520d3af729bbdedf1fa2dc4cc84a7c655 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/view/VEventSpy.h (.../VEventSpy.h) (revision fc6ab39520d3af729bbdedf1fa2dc4cc84a7c655) +++ sources/view/VEventSpy.h (.../VEventSpy.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -31,16 +31,17 @@ Q_OBJECT // singleton - SINGLETON(VEventSpy) + SINGLETON(VEventSpy); // coco begin validated: this code has been manually tested. // the only intention of this code is to be used for EMC testing and has been tested and is working fine. - PROPERTY(quint64, touchCount , 0) - PROPERTY(quint64, touchPoints, 0) + PROPERTY( quint64 , touchCount , 0 ); + PROPERTY( quint64 , touchPoints , 0 ); - PROPERTY(quint64, mouseCount, 0) - PROPERTY(QPoint , mousePoint, QPoint()) + PROPERTY( quint64 , mouseCount , 0 ); + PROPERTY( QPoint , mousePoint , QPoint() ); // coco end + private: void initConnections(); void mouseEventSpy(QEvent *vEvent, const QString &vTypeName); Index: sources/view/VPowerOff.cpp =================================================================== diff -u --- sources/view/VPowerOff.cpp (revision 0) +++ sources/view/VPowerOff.cpp (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,25 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file vpoweroff.cpp + * \author (last) Behrouz NematiPour + * \date (last) 07-May-2020 + * \author (original) Behrouz NematiPour + * \date (original) 10-Mar-2020 + * + */ +#include "VPowerOff.h" + +// Project +#include "GuiController.h" + +VIEW_DEF(VPowerOff, PowerOffData) + +void VPowerOff::onActionReceive(const PowerOffData &vData) +{ + poweroff(vData.mStatus); +} Index: sources/view/VPowerOff.h =================================================================== diff -u --- sources/view/VPowerOff.h (revision 0) +++ sources/view/VPowerOff.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,40 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file vpoweroff.h + * \author (last) Behrouz NematiPour + * \date (last) 07-May-2020 + * \author (original) Behrouz NematiPour + * \date (original) 10-Mar-2020 + * + */ +#pragma once + +// Qt +#include + +// Project +#include "MModel.h" +#include "VView.h" + +// namespace +namespace View { + +class VPowerOff : public QObject +{ + Q_OBJECT + + // coco begin validated: This property is power off request data and is always true + // to be always trigger the GUI + // also since the signal passe parameter value is used the property getter in not currently used. + // manually tested and all of them are working. + TRIGGER( quint8, poweroff, 0); + // coco end + + VIEW_DEC(VPowerOff, PowerOffData) +}; +} Index: sources/view/VView.h =================================================================== diff -u --- sources/view/VView.h (revision 0) +++ sources/view/VView.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,127 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file VView.h + * \author (last) Behrouz NemaiPour + * \date (last) 12-Jun-2020 + * \author (original) Behrouz NematiPour + * \date (original) 10-Mar-2020 + * + */ +#pragma once + +/*! + * \brief Denali Message UI usage instruction + * \details This comment explains how to use a Denali Message populated data in Denali UI Application + * + * 1 - Look at the message structure in the "message list.xlsx" + * + * 2 - View Implementation : + * Implement a view like VPressureOcclusion by copy/paste the closest model .h/.cpp file + * and adding it to project and modify to fit the new model. + * + * 3 - Register View : + * Add the required lines like the other models in the vview.h file. + * Also add the #include in the guiglobals.cpp + * + * 4 - Usage in UI : + * Import : import VTreatmentPressureOcclusion 0.1; + * Instantiate : VTreatmentPressureOcclusion { id: vTreatmentPressureOcclusion } + * Access : value: vTreatmentPressureOcclusion.pressureocclusion_ArterialPressure + * + */ +//--------------------------------------------------------------------------------// +//--------------------------------------------------------------------------------// +// The child declaration in header +#define VIEW_DEC_CLASS(vCLASS) \ +private: \ + void initConnections(); \ +public: \ + explicit vCLASS(QObject *parent = nullptr); +//--------------------------------------------------------------------------------// +#define VIEW_DEC_SLOT(vDATATYPE) \ +private Q_SLOTS: \ + void onActionReceive (const vDATATYPE &vData); +//--------------------------------------------------------------------------------// +#define VIEW_DEC(vCLASS, vDATATYPE) \ + VIEW_DEC_CLASS(vCLASS) \ + VIEW_DEC_SLOT(vDATATYPE) \ +private: +//--------------------------------------------------------------------------------// + +//--------------------------------------------------------------------------------// +// The child definition in cpp +#define VIEW_DEF_CLASS(vCLASS) \ +using namespace View; \ +vCLASS::vCLASS(QObject *parent) : QObject(parent) { \ + initConnections(); \ +} +//--------------------------------------------------------------------------------// +#define VIEW_DEF_CONNECTION(vCLASS, vDATATYPE) \ +void vCLASS::initConnections() { \ + ACTION_RECEIVE_BRIDGE_CONNECTION( \ + Gui::_GuiController, vDATATYPE); \ +} +//--------------------------------------------------------------------------------// +#define VIEW_DEF(vCLASS, vDATATYPE) \ + VIEW_DEF_CLASS(vCLASS) \ + VIEW_DEF_CONNECTION(vCLASS, vDATATYPE) +//--------------------------------------------------------------------------------// + +//--------------------------------------------------------------------------------// +// The Adjustment child definition in cpp +#define VIEW_DEC_CLASS_ADJUSTMENT(vCLASS, vDATATYPE) \ + VIEW_DEC_CLASS(vCLASS) \ + VIEW_DEC_SLOT (vDATATYPE) +//--------------------------------------------------------------------------------// +#define VIEW_DEF_CLASS_ADJUSTMENT(vCLASS, vDATATYPE) \ + using namespace View; \ + vCLASS::vCLASS(QObject *parent) : VTreatmentAdjustmentResponseBase(parent) { \ + initConnections(); \ + } + +//--------------------------------------------------------------------------------// + +//--------------------------------------------------------------------------------// +//--------- Please add the view type to the lists below to register them ---------// +//--------------------------------------------------------------------------------// +//--------------------------------------------------------------------------------// +#define REGISTER_VIEW_TYPES \ + using namespace View; \ + \ + REGISTER_TYPE( VAlarmStatus ) \ + REGISTER_TYPE( VPowerOff ) \ + \ + REGISTER_TYPE( VTreatmentBloodFlow ) \ + REGISTER_TYPE( VTreatmentDialysateFlow ) \ + REGISTER_TYPE( VTreatmentUltrafiltration ) \ + REGISTER_TYPE( VTreatmentPressureOcclusion ) \ + REGISTER_TYPE( VTreatmentTime ) \ + REGISTER_TYPE( VTreatmentRanges ) \ + REGISTER_TYPE( VTreatmentSaline ) \ + REGISTER_TYPE( VHDOperationMode ) \ + REGISTER_TYPE( VHDTreatmentStates ) \ + \ + REGISTER_TYPE( VDGDrainPump ) \ + REGISTER_TYPE( VDGHeaters ) \ + REGISTER_TYPE( VDGLoadCellReadings ) \ + REGISTER_TYPE( VDGOperationMode ) \ + REGISTER_TYPE( VDGPressures ) \ + REGISTER_TYPE( VDGROPump ) \ + REGISTER_TYPE( VDGReservoir ) \ + REGISTER_TYPE( VDGTemperatures ) \ + REGISTER_TYPE( VDGValvesStates ) \ + \ + REGISTER_TYPE( VTreatmentAdjustmentDuration ) \ + REGISTER_TYPE( VTreatmentAdjustmentFlows ) \ + REGISTER_TYPE( VTreatmentAdjustmentUltrafiltrationState ) \ + REGISTER_TYPE( VTreatmentAdjustmentUltrafiltrationEdit ) \ + REGISTER_TYPE( VTreatmentAdjustmentUltrafiltrationConfirm ) \ + REGISTER_TYPE( VTreatmentAdjustmentSaline ) \ + +//--------------------------------------------------------------------------------// + Index: sources/view/dg/data/VDGDrainPumpData.cpp =================================================================== diff -u -r6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/view/dg/data/VDGDrainPumpData.cpp (.../VDGDrainPumpData.cpp) (revision 6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5) +++ sources/view/dg/data/VDGDrainPumpData.cpp (.../VDGDrainPumpData.cpp) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -14,7 +14,7 @@ #include "VDGDrainPumpData.h" // Project -#include "guicontroller.h" +#include "GuiController.h" VIEW_DEF(VDGDrainPump, DGDrainPumpData) Index: sources/view/dg/data/VDGDrainPumpData.h =================================================================== diff -u -r6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/view/dg/data/VDGDrainPumpData.h (.../VDGDrainPumpData.h) (revision 6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5) +++ sources/view/dg/data/VDGDrainPumpData.h (.../VDGDrainPumpData.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -18,7 +18,7 @@ // Project #include "MModel.h" -#include "vview.h" +#include "VView.h" // namespace namespace View { @@ -27,10 +27,9 @@ { Q_OBJECT - PROPERTY( quint32 , rpm , 0) - PROPERTY( quint32 , dac , 0) + PROPERTY( quint32 , rpm , 0); + PROPERTY( quint32 , dac , 0); VIEW_DEC(VDGDrainPump, DGDrainPumpData) - }; } Index: sources/view/dg/data/VDGHeatersData.cpp =================================================================== diff -u -r6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/view/dg/data/VDGHeatersData.cpp (.../VDGHeatersData.cpp) (revision 6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5) +++ sources/view/dg/data/VDGHeatersData.cpp (.../VDGHeatersData.cpp) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -14,7 +14,7 @@ #include "VDGHeatersData.h" // Project -#include "guicontroller.h" +#include "GuiController.h" VIEW_DEF(VDGHeaters, DGHeatersData) Index: sources/view/dg/data/VDGHeatersData.h =================================================================== diff -u -r6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/view/dg/data/VDGHeatersData.h (.../VDGHeatersData.h) (revision 6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5) +++ sources/view/dg/data/VDGHeatersData.h (.../VDGHeatersData.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -18,7 +18,7 @@ // Project #include "MModel.h" -#include "vview.h" +#include "VView.h" // namespace namespace View { @@ -27,11 +27,10 @@ { Q_OBJECT - PROPERTY( quint32, mainPrimaryDC , 0) - PROPERTY( quint32, smallPrimaryDC , 0) - PROPERTY( quint32, trimmerDC , 0) + PROPERTY( quint32, mainPrimaryDC , 0); + PROPERTY( quint32, smallPrimaryDC , 0); + PROPERTY( quint32, trimmerDC , 0); VIEW_DEC(VDGHeaters, DGHeatersData) - }; } Index: sources/view/dg/data/VDGLoadCellReadingsData.cpp =================================================================== diff -u -r6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/view/dg/data/VDGLoadCellReadingsData.cpp (.../VDGLoadCellReadingsData.cpp) (revision 6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5) +++ sources/view/dg/data/VDGLoadCellReadingsData.cpp (.../VDGLoadCellReadingsData.cpp) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -14,7 +14,7 @@ #include "VDGLoadCellReadingsData.h" // Project -#include "guicontroller.h" +#include "GuiController.h" VIEW_DEF(VDGLoadCellReadings, DGLoadCellReadingsData) Index: sources/view/dg/data/VDGLoadCellReadingsData.h =================================================================== diff -u -r6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/view/dg/data/VDGLoadCellReadingsData.h (.../VDGLoadCellReadingsData.h) (revision 6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5) +++ sources/view/dg/data/VDGLoadCellReadingsData.h (.../VDGLoadCellReadingsData.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -18,7 +18,7 @@ // Project #include "MModel.h" -#include "vview.h" +#include "VView.h" // namespace namespace View { @@ -27,12 +27,11 @@ { Q_OBJECT - PROPERTY( float , reservoir1Prim , 0) - PROPERTY( float , reservoir1Bkup , 0) - PROPERTY( float , reservoir2Prim , 0) - PROPERTY( float , reservoir2Bkup , 0) + PROPERTY( float , reservoir1Prim , 0); + PROPERTY( float , reservoir1Bkup , 0); + PROPERTY( float , reservoir2Prim , 0); + PROPERTY( float , reservoir2Bkup , 0); VIEW_DEC(VDGLoadCellReadings, DGLoadCellReadingsData) - }; } Index: sources/view/dg/data/VDGOperationModeData.cpp =================================================================== diff -u -r6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/view/dg/data/VDGOperationModeData.cpp (.../VDGOperationModeData.cpp) (revision 6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5) +++ sources/view/dg/data/VDGOperationModeData.cpp (.../VDGOperationModeData.cpp) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -14,7 +14,7 @@ #include "VDGOperationModeData.h" // Project -#include "guicontroller.h" +#include "GuiController.h" VIEW_DEF(VDGOperationMode, DGOperationModeData) Index: sources/view/dg/data/VDGOperationModeData.h =================================================================== diff -u -r6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/view/dg/data/VDGOperationModeData.h (.../VDGOperationModeData.h) (revision 6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5) +++ sources/view/dg/data/VDGOperationModeData.h (.../VDGOperationModeData.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -18,8 +18,8 @@ // Project #include "MModel.h" -#include "vview.h" -#include "guiglobals.h" +#include "VView.h" +#include "GuiGlobals.h" // namespace using namespace Gui; @@ -29,7 +29,7 @@ { Q_OBJECT - PROPERTY( quint32 , opMode , 0) + PROPERTY( quint32 , opMode , 0); VIEW_DEC(VDGOperationMode, DGOperationModeData) @@ -40,6 +40,5 @@ public slots: QString text(); - }; } Index: sources/view/dg/data/VDGPressuresData.cpp =================================================================== diff -u -r6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/view/dg/data/VDGPressuresData.cpp (.../VDGPressuresData.cpp) (revision 6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5) +++ sources/view/dg/data/VDGPressuresData.cpp (.../VDGPressuresData.cpp) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -14,7 +14,7 @@ #include "VDGPressuresData.h" // Project -#include "guicontroller.h" +#include "GuiController.h" VIEW_DEF(VDGPressures, DGPressuresData) Index: sources/view/dg/data/VDGPressuresData.h =================================================================== diff -u -r6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/view/dg/data/VDGPressuresData.h (.../VDGPressuresData.h) (revision 6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5) +++ sources/view/dg/data/VDGPressuresData.h (.../VDGPressuresData.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -18,7 +18,7 @@ // Project #include "MModel.h" -#include "vview.h" +#include "VView.h" // namespace namespace View { @@ -27,12 +27,11 @@ { Q_OBJECT - PROPERTY( float , roInletPSI , 0) - PROPERTY( float , roOutletPSI , 0) - PROPERTY( float , drainInletPSI , 0) - PROPERTY( float , drainOutletPSI , 0) + PROPERTY( float , roInletPSI , 0); + PROPERTY( float , roOutletPSI , 0); + PROPERTY( float , drainInletPSI , 0); + PROPERTY( float , drainOutletPSI , 0); VIEW_DEC(VDGPressures, DGPressuresData) - }; } Index: sources/view/dg/data/VDGROPumpData.cpp =================================================================== diff -u -r6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/view/dg/data/VDGROPumpData.cpp (.../VDGROPumpData.cpp) (revision 6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5) +++ sources/view/dg/data/VDGROPumpData.cpp (.../VDGROPumpData.cpp) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -14,7 +14,7 @@ #include "VDGROPumpData.h" // Project -#include "guicontroller.h" +#include "GuiController.h" VIEW_DEF(VDGROPump, DGROPumpData) Index: sources/view/dg/data/VDGROPumpData.h =================================================================== diff -u -r6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/view/dg/data/VDGROPumpData.h (.../VDGROPumpData.h) (revision 6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5) +++ sources/view/dg/data/VDGROPumpData.h (.../VDGROPumpData.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -18,7 +18,7 @@ // Project #include "MModel.h" -#include "vview.h" +#include "VView.h" // namespace namespace View { @@ -27,11 +27,10 @@ { Q_OBJECT - PROPERTY( quint32 , pressure , 0) - PROPERTY( float , flowRate , 0) - PROPERTY( float , pwm , 0) + PROPERTY( quint32 , pressure , 0); + PROPERTY( float , flowRate , 0); + PROPERTY( float , pwm , 0); VIEW_DEC(VDGROPump, DGROPumpData) - }; } Index: sources/view/dg/data/VDGReservoirData.cpp =================================================================== diff -u -r6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/view/dg/data/VDGReservoirData.cpp (.../VDGReservoirData.cpp) (revision 6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5) +++ sources/view/dg/data/VDGReservoirData.cpp (.../VDGReservoirData.cpp) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -14,7 +14,7 @@ #include "VDGReservoirData.h" // Project -#include "guicontroller.h" +#include "GuiController.h" VIEW_DEF(VDGReservoir, DGReservoirData) Index: sources/view/dg/data/VDGReservoirData.h =================================================================== diff -u -r6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/view/dg/data/VDGReservoirData.h (.../VDGReservoirData.h) (revision 6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5) +++ sources/view/dg/data/VDGReservoirData.h (.../VDGReservoirData.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -18,7 +18,7 @@ // Project #include "MModel.h" -#include "vview.h" +#include "VView.h" // namespace namespace View { @@ -27,11 +27,10 @@ { Q_OBJECT - PROPERTY( float , activeReservoir , 0) - PROPERTY( float , fillToVol , 0) - PROPERTY( float , drainToVol , 0) + PROPERTY( float , activeReservoir , 0); + PROPERTY( float , fillToVol , 0); + PROPERTY( float , drainToVol , 0); VIEW_DEC(VDGReservoir, DGReservoirData) - }; } Index: sources/view/dg/data/VDGTemperaturesData.cpp =================================================================== diff -u -r6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/view/dg/data/VDGTemperaturesData.cpp (.../VDGTemperaturesData.cpp) (revision 6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5) +++ sources/view/dg/data/VDGTemperaturesData.cpp (.../VDGTemperaturesData.cpp) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -14,7 +14,7 @@ #include "VDGTemperaturesData.h" // Project -#include "guicontroller.h" +#include "GuiController.h" VIEW_DEF(VDGTemperatures, DGTemperaturesData) Index: sources/view/dg/data/VDGTemperaturesData.h =================================================================== diff -u -r6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/view/dg/data/VDGTemperaturesData.h (.../VDGTemperaturesData.h) (revision 6ae83fa9a1a3204864fc5b50fe906ac09e9c1ea5) +++ sources/view/dg/data/VDGTemperaturesData.h (.../VDGTemperaturesData.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -18,7 +18,7 @@ // Project #include "MModel.h" -#include "vview.h" +#include "VView.h" // namespace namespace View { @@ -27,20 +27,19 @@ { Q_OBJECT - PROPERTY( float , inletPrimaryHeater , 0) - PROPERTY( float , outletPrimaryHeater , 0) - PROPERTY( float , conductivitySensor1 , 0) - PROPERTY( float , conductivitySensor2 , 0) - PROPERTY( float , outletRedundancy , 0) - PROPERTY( float , inletDialysate , 0) - PROPERTY( float , primaryHeaterThermoCouple , 0) - PROPERTY( float , trimmerHeaterThermoCouple , 0) - PROPERTY( float , primaryHeaterColdJunction , 0) - PROPERTY( float , trimmerHeaterColdJunction , 0) - PROPERTY( float , primaryHeaterInternal , 0) - PROPERTY( float , trimmerHeaterInternal , 0) + PROPERTY( float , inletPrimaryHeater , 0); + PROPERTY( float , outletPrimaryHeater , 0); + PROPERTY( float , conductivitySensor1 , 0); + PROPERTY( float , conductivitySensor2 , 0); + PROPERTY( float , outletRedundancy , 0); + PROPERTY( float , inletDialysate , 0); + PROPERTY( float , primaryHeaterThermoCouple , 0); + PROPERTY( float , trimmerHeaterThermoCouple , 0); + PROPERTY( float , primaryHeaterColdJunction , 0); + PROPERTY( float , trimmerHeaterColdJunction , 0); + PROPERTY( float , primaryHeaterInternal , 0); + PROPERTY( float , trimmerHeaterInternal , 0); VIEW_DEC(VDGTemperatures, DGTemperaturesData) - }; } Index: sources/view/dg/data/VDGValvesStatesData.cpp =================================================================== diff -u -r3453d86e870b126f49f9582321dbf58928c4f396 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/view/dg/data/VDGValvesStatesData.cpp (.../VDGValvesStatesData.cpp) (revision 3453d86e870b126f49f9582321dbf58928c4f396) +++ sources/view/dg/data/VDGValvesStatesData.cpp (.../VDGValvesStatesData.cpp) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -14,7 +14,7 @@ #include "VDGValvesStatesData.h" // Project -#include "guicontroller.h" +#include "GuiController.h" VIEW_DEF(VDGValvesStates, DGValvesStatesData) Index: sources/view/dg/data/VDGValvesStatesData.h =================================================================== diff -u -raa0772fe1b0ff6b07e9f64e8c38acad66ad5468d -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/view/dg/data/VDGValvesStatesData.h (.../VDGValvesStatesData.h) (revision aa0772fe1b0ff6b07e9f64e8c38acad66ad5468d) +++ sources/view/dg/data/VDGValvesStatesData.h (.../VDGValvesStatesData.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -18,7 +18,7 @@ // Project #include "MModel.h" -#include "vview.h" +#include "VView.h" // namespace namespace View { @@ -28,29 +28,27 @@ Q_OBJECT // coco begin validated: Has been tested manually. This is a general messages received trigger, but is not used yet. - TRIGGER ( bool , refresh , false) + TRIGGER ( bool , refresh , false); // coco end - PROPERTY( bool , valveStates_01 , false) - PROPERTY( bool , valveStates_02 , false) - PROPERTY( bool , valveStates_03 , false) - PROPERTY( bool , valveStates_04 , false) - PROPERTY( bool , valveStates_05 , false) - PROPERTY( bool , valveStates_06 , false) - PROPERTY( bool , valveStates_07 , false) - PROPERTY( bool , valveStates_08 , false) - PROPERTY( bool , valveStates_09 , false) - PROPERTY( bool , valveStates_10 , false) - PROPERTY( bool , valveStates_11 , false) - PROPERTY( bool , valveStates_12 , false) + PROPERTY( bool , valveStates_01 , false); + PROPERTY( bool , valveStates_02 , false); + PROPERTY( bool , valveStates_03 , false); + PROPERTY( bool , valveStates_04 , false); + PROPERTY( bool , valveStates_05 , false); + PROPERTY( bool , valveStates_06 , false); + PROPERTY( bool , valveStates_07 , false); + PROPERTY( bool , valveStates_08 , false); + PROPERTY( bool , valveStates_09 , false); + PROPERTY( bool , valveStates_10 , false); + PROPERTY( bool , valveStates_11 , false); + PROPERTY( bool , valveStates_12 , false); VIEW_DEC(VDGValvesStates, DGValvesStatesData) Q_PROPERTY(QString text READ text NOTIFY refreshTriggered) public slots: QString text(); - }; - } Index: sources/view/hd/adjustment/VTreatmentAdjustmentDuration.cpp =================================================================== diff -u --- sources/view/hd/adjustment/VTreatmentAdjustmentDuration.cpp (revision 0) +++ sources/view/hd/adjustment/VTreatmentAdjustmentDuration.cpp (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,37 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file vtreatmentadjustmentduration.cpp + * \author (last) Behrouz NemaiPour + * \date (last) 09-Jun-2020 + * \author (original) Behrouz NematiPour + * \date (original) 19-May-2020 + * + */ +#include "VTreatmentAdjustmentDuration.h" + +// Project +#include "GuiController.h" + +VIEW_DEF_CLASS_ADJUSTMENT(VTreatmentAdjustmentDuration, AdjustDurationResponseData) + +void VTreatmentAdjustmentDuration::initConnections() { + ACTION_VIEW_CONNECTION(AdjustDurationResponseData); + ADJUST_VIEW_CONNECTION( AdjustDurationRequestData); +} + +void VTreatmentAdjustmentDuration::onActionReceive(const AdjustDurationResponseData &vData) +{ + adjustment_Accepted ( vData.mAccepted ); + adjustment_Reason ( vData.mReason ); + duration ( vData.mDuration ); + ultrafiltration ( vData.mUFVolume / 1000 ); // mL => L + + // *** has to be the last to let the information to be set and then emit the signal *** + // *** otherwise will use the previous values before being set. *** + adjustment ( true ); +} Index: sources/view/hd/adjustment/VTreatmentAdjustmentDuration.h =================================================================== diff -u --- sources/view/hd/adjustment/VTreatmentAdjustmentDuration.h (revision 0) +++ sources/view/hd/adjustment/VTreatmentAdjustmentDuration.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,56 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file vtreatmentadjustmentduration.h + * \author (last) Behrouz NemaiPour + * \date (last) 12-Jun-2020 + * \author (original) Behrouz NematiPour + * \date (original) 19-May-2020 + * + */ +#pragma once + +#include + +// Project +#include "VTreatmentAdjustmentResponseBase.h" + +namespace View { + +class VTreatmentAdjustmentDuration : public VTreatmentAdjustmentResponseBase +{ + Q_OBJECT + + // friends + friend class ::tst_views; + + AdjustDurationRequestData _data; + + // coco begin validated: + // The property adjustment_Triggered has to be always true + // and to always trigger the change event to work as a notifier for GUI + // has been manually tested that it works perfectly fine + TRIGGER( bool , adjustment , 0); + // coco end + + // Treatment Duration data + PROPERTY( quint32 , duration , 0); + PROPERTY( float , ultrafiltration , 0); + + VIEW_DEC_CLASS_ADJUSTMENT(VTreatmentAdjustmentDuration, AdjustDurationResponseData) + +public slots: + // ----- Adjust Duration + void doAdjustment(quint32 vDuration) { + _data.duration = vDuration; + emit didAdjustment(_data); + } + +signals: + void didAdjustment(const AdjustDurationRequestData &vData); +}; +} Index: sources/view/hd/adjustment/VTreatmentAdjustmentFlows.cpp =================================================================== diff -u --- sources/view/hd/adjustment/VTreatmentAdjustmentFlows.cpp (revision 0) +++ sources/view/hd/adjustment/VTreatmentAdjustmentFlows.cpp (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,37 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file vtreatmentadjustmentflows.cpp + * \author (last) Behrouz NemaiPour + * \date (last) 09-Jun-2020 + * \author (original) Behrouz NematiPour + * \date (original) 19-May-2020 + * + */ +#include "VTreatmentAdjustmentFlows.h" + +// Project +#include "GuiController.h" + +VIEW_DEF_CLASS_ADJUSTMENT(VTreatmentAdjustmentFlows, AdjustBloodDialysateResponseData) +void VTreatmentAdjustmentFlows::initConnections() { + ACTION_VIEW_CONNECTION(AdjustBloodDialysateResponseData); + ADJUST_VIEW_CONNECTION( AdjustBloodDialysateRequestData); +} + +void VTreatmentAdjustmentFlows::onActionReceive(const AdjustBloodDialysateResponseData &vData) +{ + adjustment_Accepted ( vData.mAccepted ); + adjustment_Reason ( vData.mReason ); + bloodFlow_FlowSetPoint ( vData.mBloodRate ); + dialysateFlow_FlowSetPoint ( vData.mDialydateReate ); + + // *** has to be the last to let the information to be set and then emit the signal *** + // *** otherwise will use the previous values before being set. *** + adjustment ( true ); +} + Index: sources/view/hd/adjustment/VTreatmentAdjustmentFlows.h =================================================================== diff -u --- sources/view/hd/adjustment/VTreatmentAdjustmentFlows.h (revision 0) +++ sources/view/hd/adjustment/VTreatmentAdjustmentFlows.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,58 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file vtreatmentadjustmentflows.h + * \author (last) Behrouz NemaiPour + * \date (last) 08-Jun-2020 + * \author (original) Behrouz NematiPour + * \date (original) 19-May-2020 + * + */ +#pragma once + +// Qt +#include + +// Project +#include "VTreatmentAdjustmentResponseBase.h" + +namespace View { + +class VTreatmentAdjustmentFlows : public VTreatmentAdjustmentResponseBase +{ + Q_OBJECT + // friends + friend class ::tst_views; + + AdjustBloodDialysateRequestData _data; + + // coco begin validated: + // The property adjustment_Triggered has to be always true + // and to always trigger the change event to work as a notifier for GUI + // has been manually tested that it works perfectly fine + TRIGGER( bool , adjustment , 0); + // coco end + + // Treatment Blood/Dialysate Flow data + PROPERTY( quint32 , bloodFlow_FlowSetPoint , 0); + PROPERTY( quint32 , dialysateFlow_FlowSetPoint , 0); + + VIEW_DEC_CLASS_ADJUSTMENT(VTreatmentAdjustmentFlows, AdjustBloodDialysateResponseData) + +public slots: + // ----- Adjust Blood/Dialysate Flows + void doAdjustment(quint32 vBloodFlow, quint32 vDialysateFlow) { + _data. bloodFlow = vBloodFlow; + _data.dialysateFlow = vDialysateFlow; + emit didAdjustment(_data); + } + +signals: + void didAdjustment(const AdjustBloodDialysateRequestData &vData); +}; + +} Index: sources/view/hd/adjustment/VTreatmentAdjustmentResponseBase.cpp =================================================================== diff -u --- sources/view/hd/adjustment/VTreatmentAdjustmentResponseBase.cpp (revision 0) +++ sources/view/hd/adjustment/VTreatmentAdjustmentResponseBase.cpp (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,57 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file vtreatmentadjustmentresponsebase.cpp + * \author (last) Behrouz NemaiPour + * \date (last) 19-Jun-2020 + * \author (original) Behrouz NemaiPour + * \date (original) 08-Jun-2020 + * + */ +#include "VTreatmentAdjustmentResponseBase.h" + +// Project +#include "GuiController.h" + +VIEW_DEF_CLASS(VTreatmentAdjustmentResponseBase) +void VTreatmentAdjustmentResponseBase::initConnections() { } + + +/*! + * \brief VTreatmentAdjustmentResponseBase::reasonText + * \details this code is the place holder for the alarms description mapping + * since it is another feature + * it returns the enum name for now + * \param vEnum - The Rejection Reason enum + * \return String representation of the Rejection Reason enum name + */ +QString VTreatmentAdjustmentResponseBase::reasonText(GuiRequestReasons vEnum) +{ + // TEST : this code is the place holder for the alarms description mapping + // since it is another feature + // it returns the enum name for now + const QMetaObject *mo = qt_getEnumMetaObject(vEnum); + int enumIdx = mo->indexOfEnumerator(qt_getEnumName(vEnum)); + QString mText = mo->enumerator(enumIdx).valueToKey(vEnum); + if ( ! mText.isEmpty() ) { + return mText; + } + return QString("[%1] Unknown Error").arg(vEnum); +} + +/*! + * \brief View::VTreatmentAdjustmentResponseBase::text + * \details The slot to ge the Reason Description + * \return Reason description as string + */ +QString View::VTreatmentAdjustmentResponseBase::text() +{ + QString text; + if (_adjustment_Reason != GuiRequestReasons::REQUEST_REJECT_REASON_NONE) + text = reasonText(static_cast(_adjustment_Reason)); + return text; +} Index: sources/view/hd/adjustment/VTreatmentAdjustmentResponseBase.h =================================================================== diff -u --- sources/view/hd/adjustment/VTreatmentAdjustmentResponseBase.h (revision 0) +++ sources/view/hd/adjustment/VTreatmentAdjustmentResponseBase.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,59 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file vtreatmentadjustmentresponsebase.h + * \author (last) Behrouz NemaiPour + * \date (last) 08-Jun-2020 + * \author (original) Behrouz NemaiPour + * \date (original) 08-Jun-2020 + * + */ +#pragma once + +// Qt +#include + +// Project +#include "MModel.h" +#include "VView.h" +#include "GuiGlobals.h" + +// forward declarations +class tst_views; + +// namespace +using namespace Gui; +namespace View { + +class VTreatmentAdjustmentResponseBase : public QObject +{ + + Q_OBJECT + + // friends + friend class ::tst_views; + + // coco begin validated: + // The adjustment_Reason property as quint32 is not used directly in GUI + // it will be used as QString text. + // has been manually tested that it works perfectly fine if used. + PROPERTY( quint32 , adjustment_Reason , 0); + // coco end + + PROPERTY( bool , adjustment_Accepted , 0); + + Q_PROPERTY(QString adjustment_ReasonText READ text NOTIFY adjustment_ReasonChanged) + + VIEW_DEC_CLASS(VTreatmentAdjustmentResponseBase) + +private: + QString reasonText (GuiRequestReasons vEnum); + +protected slots: + QString text(); +}; +} Index: sources/view/hd/adjustment/VTreatmentAdjustmentSaline.cpp =================================================================== diff -u -r474e5b3680d8acbf0ac79062124352d0b3d43b65 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/view/hd/adjustment/VTreatmentAdjustmentSaline.cpp (.../VTreatmentAdjustmentSaline.cpp) (revision 474e5b3680d8acbf0ac79062124352d0b3d43b65) +++ sources/view/hd/adjustment/VTreatmentAdjustmentSaline.cpp (.../VTreatmentAdjustmentSaline.cpp) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -15,7 +15,7 @@ #include "VTreatmentAdjustmentSaline.h" // Project -#include "guicontroller.h" +#include "GuiController.h" VIEW_DEF_CLASS_ADJUSTMENT(VTreatmentAdjustmentSaline, AdjustSalineResponseData) Index: sources/view/hd/adjustment/VTreatmentAdjustmentSaline.h =================================================================== diff -u -raaf98fec556f719e9a65ce3f0376e2fd1d504bde -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/view/hd/adjustment/VTreatmentAdjustmentSaline.h (.../VTreatmentAdjustmentSaline.h) (revision aaf98fec556f719e9a65ce3f0376e2fd1d504bde) +++ sources/view/hd/adjustment/VTreatmentAdjustmentSaline.h (.../VTreatmentAdjustmentSaline.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -17,7 +17,7 @@ #include // Project -#include "vtreatmentadjustmentresponsebase.h" +#include "VTreatmentAdjustmentResponseBase.h" namespace View { @@ -34,15 +34,15 @@ // The property adjustment_Triggered has to be always true // and to always trigger the change event to work as a notifier for GUI // has been manually tested that it works perfectly fine - TRIGGER( bool , adjustment , 0 ) + TRIGGER( bool , adjustment , 0 ); // coco end - PROPERTY( qint32 , target , 0 ) - PROPERTY( bool , isStarted , false ) - PROPERTY( bool , isDisabled , false ) // the Saline is disabled due to maximum cumulative volume reached. + PROPERTY( qint32 , target , 0 ); + PROPERTY( bool , isStarted , false ); + PROPERTY( bool , isDisabled , false ); // the Saline is disabled due to maximum cumulative volume reached. - VIEW_DEC_CLASS_ADJUSTMENT(VTreatmentAdjustmentSaline, AdjustSalineResponseData) - VIEW_DEC_SLOT(TreatmentStatesData) + VIEW_DEC_CLASS_ADJUSTMENT(VTreatmentAdjustmentSaline, AdjustSalineResponseData); + VIEW_DEC_SLOT(TreatmentStatesData); // ---------- Start/Stop Saline Bolus public slots: Index: sources/view/hd/adjustment/VTreatmentAdjustmentUltrafiltrationConfirm.cpp =================================================================== diff -u --- sources/view/hd/adjustment/VTreatmentAdjustmentUltrafiltrationConfirm.cpp (revision 0) +++ sources/view/hd/adjustment/VTreatmentAdjustmentUltrafiltrationConfirm.cpp (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,53 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file vtreatmentadjustmentultrafiltrationconfirm.cpp + * \author (last) Behrouz NemaiPour + * \date (last) 09-Jun-2020 + * \author (original) Behrouz NemaiPour + * \date (original) 09-Jun-2020 + * + */ +#include "VTreatmentAdjustmentUltrafiltrationConfirm.h" + +// Project +#include "GuiController.h" + +VIEW_DEF_CLASS_ADJUSTMENT(VTreatmentAdjustmentUltrafiltrationConfirm, AdjustUltrafiltrationConfirmResponseData) + +void VTreatmentAdjustmentUltrafiltrationConfirm::initConnections() { + ACTION_VIEW_CONNECTION(AdjustUltrafiltrationConfirmResponseData); + ADJUST_VIEW_CONNECTION( AdjustUltrafiltrationConfirmRequestData); +} + +void VTreatmentAdjustmentUltrafiltrationConfirm::onActionReceive(const AdjustUltrafiltrationConfirmResponseData &vData) +{ + adjustment_Accepted ( vData.mAccepted ); + adjustment_Reason ( vData.mReason ); + + volume ( vData.mVolume / 1000 ); // mL => L + duration ( vData.mDuration ); + rate ( vData.mRate ); + + // *** has to be the last to let the information to be set and then emit the signal *** + // *** otherwise will use the previous values before being set. *** + adjustment ( true ); +} + +void View::VTreatmentAdjustmentUltrafiltrationConfirm::doOptionRate(float vVolume) +{ + _data.volume = int(vVolume * 1000); // cast to int to truncate the float after convert to mL + _data.option = AdjustUltrafiltrationConfirmRequestData::eRate; + emit didAdjustment(_data); +} + +void View::VTreatmentAdjustmentUltrafiltrationConfirm::doOptionDuration(float vVolume) +{ + _data.volume = int(vVolume * 1000); // cast to int to truncate the float after convert to mL + _data.option = AdjustUltrafiltrationConfirmRequestData::eDuration; + emit didAdjustment(_data); +} Index: sources/view/hd/adjustment/VTreatmentAdjustmentUltrafiltrationConfirm.h =================================================================== diff -u --- sources/view/hd/adjustment/VTreatmentAdjustmentUltrafiltrationConfirm.h (revision 0) +++ sources/view/hd/adjustment/VTreatmentAdjustmentUltrafiltrationConfirm.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,57 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file vtreatmentadjustmentultrafiltrationconfirm.h + * \author (last) Behrouz NemaiPour + * \date (last) 22-Jun-2020 + * \author (original) Behrouz NemaiPour + * \date (original) 09-Jun-2020 + * + */ +#pragma once + +#include + +// Project +#include "VTreatmentAdjustmentResponseBase.h" + +namespace View { + +class VTreatmentAdjustmentUltrafiltrationConfirm : public VTreatmentAdjustmentResponseBase +{ + Q_OBJECT + + // friends + friend class ::tst_views; + + AdjustUltrafiltrationConfirmRequestData _data; + + // coco begin validated: + // The property adjustment_Triggered has to be always true + // and to always trigger the change event to work as a notifier for GUI + // has been manually tested that it works perfectly fine + TRIGGER( bool , adjustment , 0); + // coco end + + // Treatment Ultrafiltration data + PROPERTY( float , volume , 0); + // coco begin validated: Manually validated + // Duration is not used since will be passed each second by TreatmentTime message + PROPERTY( quint32 , duration , 0); + // Rate has not been decided to be used anywhere yet. + PROPERTY( float , rate , 0); + // coco end + VIEW_DEC_CLASS_ADJUSTMENT(VTreatmentAdjustmentUltrafiltrationConfirm, AdjustUltrafiltrationConfirmResponseData) + +public slots: + void doOptionRate (float vVolume); + void doOptionDuration(float vVolume); + +signals: + void didAdjustment(const AdjustUltrafiltrationConfirmRequestData &vData); +}; +} Index: sources/view/hd/adjustment/VTreatmentAdjustmentUltrafiltrationEdit.cpp =================================================================== diff -u --- sources/view/hd/adjustment/VTreatmentAdjustmentUltrafiltrationEdit.cpp (revision 0) +++ sources/view/hd/adjustment/VTreatmentAdjustmentUltrafiltrationEdit.cpp (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,47 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file vtreatmentadjustmentultrafiltrationedit.cpp + * \author (last) Behrouz NemaiPour + * \date (last) 09-Jun-2020 + * \author (original) Behrouz NemaiPour + * \date (original) 09-Jun-2020 + * + */ +#include "VTreatmentAdjustmentUltrafiltrationEdit.h" + +// Project +#include "GuiController.h" + +VIEW_DEF_CLASS_ADJUSTMENT(VTreatmentAdjustmentUltrafiltrationEdit, AdjustUltrafiltrationEditResponseData) + +void VTreatmentAdjustmentUltrafiltrationEdit::initConnections() { + ACTION_VIEW_CONNECTION(AdjustUltrafiltrationEditResponseData); + ADJUST_VIEW_CONNECTION( AdjustUltrafiltrationEditRequestData); +} + +void VTreatmentAdjustmentUltrafiltrationEdit::onActionReceive(const AdjustUltrafiltrationEditResponseData &vData) +{ + adjustment_Accepted ( vData.mAccepted ); + adjustment_Reason ( vData.mReason ); + + volume ( vData.mVolume / 1000 ); // mL => L + duration ( vData.mDuration ); + durationDiff ( vData.mDurationDiff ); + rate ( vData.mRate ); + rateDiff ( vData.mRateDiff ); + rateOld ( vData.mRateOld ); + + // *** has to be the last to let the information to be set and then emit the signal *** + // *** otherwise will use the previous values before being set. *** + adjustment ( true ); +} + +void View::VTreatmentAdjustmentUltrafiltrationEdit::doAdjustment(float vVolume) { + _data.volume = vVolume * 1000; // L => mL + emit didAdjustment(_data); +} Index: sources/view/hd/adjustment/VTreatmentAdjustmentUltrafiltrationEdit.h =================================================================== diff -u --- sources/view/hd/adjustment/VTreatmentAdjustmentUltrafiltrationEdit.h (revision 0) +++ sources/view/hd/adjustment/VTreatmentAdjustmentUltrafiltrationEdit.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,57 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file vtreatmentadjustmentultrafiltrationedit.h + * \author (last) Behrouz NemaiPour + * \date (last) 09-Jun-2020 + * \author (original) Behrouz NemaiPour + * \date (original) 09-Jun-2020 + * + */ +#pragma once + +#include + +// Project +#include "VTreatmentAdjustmentResponseBase.h" + +namespace View { + +class VTreatmentAdjustmentUltrafiltrationEdit : public VTreatmentAdjustmentResponseBase +{ + Q_OBJECT + + // friends + friend class ::tst_views; + + AdjustUltrafiltrationEditRequestData _data; + + // coco begin validated: + // The property adjustment_Triggered has to be always true + // and to always trigger the change event to work as a notifier for GUI + // has been manually tested that it works perfectly fine + TRIGGER( bool , adjustment , 0); + // coco end + + // Treatment Ultrafiltration data + PROPERTY( float , volume , 0); + PROPERTY( quint32 , duration , 0); + PROPERTY( qint32 , durationDiff , 0); + PROPERTY( float , rate , 0); + PROPERTY( float , rateDiff , 0); + PROPERTY( float , rateOld , 0); + + VIEW_DEC_CLASS_ADJUSTMENT(VTreatmentAdjustmentUltrafiltrationEdit, AdjustUltrafiltrationEditResponseData) + +// ----------- Adjust Ultrafiltration +public slots: + void doAdjustment(float vVolume); +signals: + void didAdjustment(const AdjustUltrafiltrationEditRequestData &vData); +}; + +} Index: sources/view/hd/adjustment/VTreatmentAdjustmentUltrafiltrationState.cpp =================================================================== diff -u --- sources/view/hd/adjustment/VTreatmentAdjustmentUltrafiltrationState.cpp (revision 0) +++ sources/view/hd/adjustment/VTreatmentAdjustmentUltrafiltrationState.cpp (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,77 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file vtreatmentadjustmentultrafiltrationstate.cpp + * \author (last) Behrouz NemaiPour + * \date (last) 23-Jun-2020 + * \author (original) Behrouz NemaiPour + * \date (original) 09-Jun-2020 + * + */ +#include "VTreatmentAdjustmentUltrafiltrationState.h" + +// Project +#include "GuiController.h" + +VIEW_DEF_CLASS_ADJUSTMENT(VTreatmentAdjustmentUltrafiltrationState, AdjustUltrafiltrationStateResponseData) + +void VTreatmentAdjustmentUltrafiltrationState::initConnections() { + ACTION_VIEW_CONNECTION(AdjustUltrafiltrationStateResponseData); + ADJUST_VIEW_CONNECTION( AdjustUltrafiltrationStateRequestData); +} + +void VTreatmentAdjustmentUltrafiltrationState::onActionReceive(const AdjustUltrafiltrationStateResponseData &vData) +{ + adjustment_Accepted ( vData.mAccepted ); + if (adjustment_Accepted()) { + // the response doesn't have the state so the requested state which has been accepted is used. + isPaused ( _data.requestedState == AdjustUltrafiltrationStateRequestData::ePaused ); + } + + // *** has to be the last to let the information to be set and then emit the signal *** + // *** otherwise will use the previous values before being set. *** + adjustment ( true ); +} + +void View::VTreatmentAdjustmentUltrafiltrationState::doPause() +{ + _data.requestedState = AdjustUltrafiltrationStateRequestData::ePaused; + emit didAdjustment(_data); +} + +void View::VTreatmentAdjustmentUltrafiltrationState::doResume() +{ + _data.requestedState = AdjustUltrafiltrationStateRequestData::eRunning; + emit didAdjustment(_data); +} + +/*! + * \brief View::VTreatmentAdjustmentUltrafiltrationState::text + * \details The slot to ge the Reason Description + * \return Reason description as string + * \note The ultrafiltration state (Resume/Pause) change has no returned reason code and it's only bool. + */ +QString View::VTreatmentAdjustmentUltrafiltrationState::text() +{ + if (adjustment_Accepted()) return ""; + + // if there is a reason (passed) it will be used + QString mText = VTreatmentAdjustmentResponseBase::text(); + // coco begin validated : Manually tested. + // Although currently there is no reason passed in the corresponding message. + // But kept this code which seems reasonable to have a reason later. + if (! mText.isEmpty()) return mText; + // coco end + // otherwise a general message will be created/passed. + if (isPaused()) { + mText = tr("Unable to Resume Ultrafiltration or already running"); + } else { + mText = tr("Unable to Pause Ultrafiltration or already paused"); + + } + return mText; +} Index: sources/view/hd/adjustment/VTreatmentAdjustmentUltrafiltrationState.h =================================================================== diff -u --- sources/view/hd/adjustment/VTreatmentAdjustmentUltrafiltrationState.h (revision 0) +++ sources/view/hd/adjustment/VTreatmentAdjustmentUltrafiltrationState.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,53 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file vtreatmentadjustmentultrafiltrationstate.h + * \author (last) Behrouz NemaiPour + * \date (last) 09-Jun-2020 + * \author (original) Behrouz NemaiPour + * \date (original) 09-Jun-2020 + * + */ +#pragma once + +#include + +// Project +#include "VTreatmentAdjustmentResponseBase.h" + +namespace View { + +class VTreatmentAdjustmentUltrafiltrationState : public VTreatmentAdjustmentResponseBase +{ + Q_OBJECT + + // friends + friend class ::tst_views; + + AdjustUltrafiltrationStateRequestData _data; + + // coco begin validated: + // The property adjustment_Triggered has to be always true + // and to always trigger the change event to work as a notifier for GUI + // has been manually tested that it works perfectly fine + TRIGGER( bool , adjustment , 0); + // coco end + + PROPERTY( bool , isPaused , false); + + VIEW_DEC_CLASS_ADJUSTMENT(VTreatmentAdjustmentUltrafiltrationState, AdjustUltrafiltrationStateResponseData) + +// ---------- Pause Ultrafiltration +public slots: + void doPause (); + void doResume(); + QString text(); + +signals: + void didAdjustment(const AdjustUltrafiltrationStateRequestData &vData); +}; +} Index: sources/view/hd/alarm/VAlarmStatus.cpp =================================================================== diff -u --- sources/view/hd/alarm/VAlarmStatus.cpp (revision 0) +++ sources/view/hd/alarm/VAlarmStatus.cpp (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,143 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file valarmstatus.cpp + * \author (last) Peter Lucia + * \date (last) 29-Jun-2020 + * \author (original) Behrouz NematiPour + * \date (original) 10-Mar-2020 + * + */ +#include "VAlarmStatus.h" + +using namespace Gui; +using namespace View; + +VAlarmStatus::VAlarmStatus(QObject *parent) +{ + Q_UNUSED(parent); + + connect(&_GuiController, SIGNAL(didActionReceive(AlarmStatusData)), + this , SLOT(onActionReceive(AlarmStatusData))); + + connect(this, SIGNAL(requestActionTransmit(GuiActionType,QVariantList)), + &_GuiController, SLOT(doActionTransmit(GuiActionType,QVariantList))); +} + +void VAlarmStatus::onActionReceive(const AlarmStatusData &vData) +{ + GuiAlarmID alarmID = static_cast(vData.mTop); + + if (gDisableTimeout && alarmID == GuiAlarmID::ALARM_ID_HD_COMM_TIMEOUT) { + LOG_EVENT(tr("Suppressing HD communication timeout.")); + return; + } + + if (acknowledgedAlarms.contains(alarmID)) { + LOG_EVENT(tr("Alarm ID %0 has been acknowledged and is visible. ").arg(alarmID)); + return; + } + + if (vData.mTop <= GuiAlarmID::ALARM_ID_NO_ALARM) { + emit hideAlarm(); + return; + } + + alarm_Priority (vData.mState ); + alarm_AlarmID (vData.mTop ); + alarm_EscalateIn (vData.mMuteTimeout ); + alarm_MuteTimeout (vData.mEscalatesIn ); + alarm_Flag_systemFault (vData.mFlags.at(AlarmStatusFlag::eFlag_systemFault )); + alarm_Flag_stop (vData.mFlags.at(AlarmStatusFlag::eFlag_stop )); + alarm_Flag_noClear (vData.mFlags.at(AlarmStatusFlag::eFlag_noClear )); + alarm_Flag_noResume (vData.mFlags.at(AlarmStatusFlag::eFlag_noResume )); + alarm_Flag_noRinseback (vData.mFlags.at(AlarmStatusFlag::eFlag_noRinseback )); + alarm_Flag_noEndTreatment (vData.mFlags.at(AlarmStatusFlag::eFlag_noEndTreatment )); + alarm_Flag_noNewTreatment (vData.mFlags.at(AlarmStatusFlag::eFlag_noNewTreatment )); + alarm_Flag_bypassDialyzer (vData.mFlags.at(AlarmStatusFlag::eFlag_bypassDialyzer )); + alarm_Flag_alarmsToEscalate (vData.mFlags.at(AlarmStatusFlag::eFlag_alarmsToEscalate)); + alarm_Flag_alarmsSilenced (vData.mFlags.at(AlarmStatusFlag::eFlag_alarmsSilenced )); + + emit raiseAlarm(); + + +} + +/*! + * \brief VAlarmStatus::alarmPriorityText + * \details this code is the place holder for the alarms description mapping + * since it is another feature + * it returns the enum name for now + * \param vEnum - The Alarm priority + * \return String representation of the Alarm priority Enum name + */ +QString VAlarmStatus::alarmPriorityText(GuiAlarmPriority vEnum) +{ + // coco begin validated: this code is the place holder for the alarms description mapping + // since it is another feature + // it returns the enum name for now + const QMetaObject *mo = qt_getEnumMetaObject(vEnum); + int enumIdx = mo->indexOfEnumerator(qt_getEnumName(vEnum)); + const char *key = mo->enumerator(enumIdx).valueToKey(vEnum); + if (key) + return qPrintable(key); + else + return QString("ALARM_PRIORITY_UNDEFINED [%1]").arg(vEnum); +} +// coco end + +/*! + * \brief VAlarmStatus::alarmIDText + * \details Looks up the alarm text from the alarm ID + * \param vEnum - The Alarm ID + * \return The alarm text (QString) + */ +QString VAlarmStatus::alarmIDText(GuiAlarmID vEnum) +{ + return Model::MAlarmStatus::toText(vEnum); +} + +/*! + * \brief VAlarmStatus::text + * \return Gets the alarm text from the alarm ID and returns it as a QString + */ +QString VAlarmStatus::text() +{ + return alarmIDText(static_cast(alarm_AlarmID())); +} + +/*! + * \brief VAlarmStatus::id + * \return Gets the id of the alarm and returns the ID number as a QString + */ +QString VAlarmStatus::id() +{ + // coco begin validated: Has been validated manually + return QString("%0").arg(static_cast(alarm_AlarmID())); + // coco end +} + +/*! + * \brief VAlarmStatus::requestOkay + * Send out a request to acknowledge alarms. + */ +void VAlarmStatus::requestOkay(GuiAlarmID alarmID) +{ + acknowledgedAlarms.append(alarmID); +} + +/*! + * \brief VAlarmStatus::requestSilence + * Send out a request to silence alarms. + */ +void VAlarmStatus::requestSilence() +{ + // TODO: Update with needed data. Placeholder for now. + QVariantList messageData = {1,2,3,4,5}; + GuiActionType messageAction = GuiActions::ID_AlarmSilenceReq; + emit requestActionTransmit(messageAction, messageData); +} Index: sources/view/hd/alarm/VAlarmStatus.h =================================================================== diff -u --- sources/view/hd/alarm/VAlarmStatus.h (revision 0) +++ sources/view/hd/alarm/VAlarmStatus.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,79 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file valarmstatus.h + * \author (last) Peter Lucia + * \date (last) 29-Jun-2020 + * \author (original) Behrouz NematiPour + * \date (original) 10-Mar-2020 + * + */ +#pragma once + +// Qt +#include + +// Project +#include "MModel.h" +#include "VView.h" +#include "GuiGlobals.h" +#include "MessageGlobals.h" +#include "GuiController.h" +#include "format.h" + +using namespace Can; +// namespace +using namespace Gui; +namespace View { + +class VAlarmStatus : public QObject +{ + Q_OBJECT +public: + VAlarmStatus(QObject *parent = NULL); + +private: + // coco begin validated: Has been validated manually + PROPERTY( quint32 , alarm_Priority , 0); + PROPERTY( quint32 , alarm_AlarmID , 0); + PROPERTY( quint32 , alarm_EscalateIn , 0); + PROPERTY( quint32 , alarm_MuteTimeout , 0); + PROPERTY( bool , alarm_Flag_systemFault , false); + PROPERTY( bool , alarm_Flag_stop , false); + PROPERTY( bool , alarm_Flag_noClear , false); + PROPERTY( bool , alarm_Flag_noResume , false); + PROPERTY( bool , alarm_Flag_noRinseback , false); + PROPERTY( bool , alarm_Flag_noEndTreatment , false); + PROPERTY( bool , alarm_Flag_noNewTreatment , false); + PROPERTY( bool , alarm_Flag_bypassDialyzer , false); + PROPERTY( bool , alarm_Flag_alarmsToEscalate , false); + PROPERTY( bool , alarm_Flag_alarmsSilenced , false); + // coco end + + Q_PROPERTY(QString text READ text NOTIFY alarm_AlarmIDChanged) + Q_PROPERTY(QString id READ id NOTIFY alarm_AlarmIDChanged) + +signals: + void raiseAlarm(); + void hideAlarm(); + void requestActionTransmit(GuiActionType vAction, const QVariantList &vData); + +private: + QString alarmPriorityText (GuiAlarmPriority vEnum); + QString alarmIDText (GuiAlarmID vEnum); + QList acknowledgedAlarms; + +private slots: + void onActionReceive(const AlarmStatusData &vData); + +public slots: + QString text(); + QString id(); + void requestOkay(GuiAlarmID alarmID); + void requestSilence(); +}; +} Index: sources/view/hd/data/VHDOperationModeData.cpp =================================================================== diff -u -r0e528e5f706308c7b0e8f22a4d9dbb5b5715db7c -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/view/hd/data/VHDOperationModeData.cpp (.../VHDOperationModeData.cpp) (revision 0e528e5f706308c7b0e8f22a4d9dbb5b5715db7c) +++ sources/view/hd/data/VHDOperationModeData.cpp (.../VHDOperationModeData.cpp) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -14,7 +14,7 @@ #include "VHDOperationModeData.h" // Project -#include "guicontroller.h" +#include "GuiController.h" VIEW_DEF(VHDOperationMode, HDOperationModeData) Index: sources/view/hd/data/VHDOperationModeData.h =================================================================== diff -u -r0e528e5f706308c7b0e8f22a4d9dbb5b5715db7c -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/view/hd/data/VHDOperationModeData.h (.../VHDOperationModeData.h) (revision 0e528e5f706308c7b0e8f22a4d9dbb5b5715db7c) +++ sources/view/hd/data/VHDOperationModeData.h (.../VHDOperationModeData.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -18,8 +18,8 @@ // Project #include "MModel.h" -#include "vview.h" -#include "guiglobals.h" +#include "VView.h" +#include "GuiGlobals.h" // namespace using namespace Gui; @@ -29,7 +29,7 @@ { Q_OBJECT - PROPERTY( quint32 , opMode , 0) + PROPERTY( quint32 , opMode , 0); VIEW_DEC(VHDOperationMode, HDOperationModeData) @@ -40,6 +40,5 @@ public slots: QString text(); - }; } Index: sources/view/hd/data/VHDTreatmentStatesData.cpp =================================================================== diff -u -r0e528e5f706308c7b0e8f22a4d9dbb5b5715db7c -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/view/hd/data/VHDTreatmentStatesData.cpp (.../VHDTreatmentStatesData.cpp) (revision 0e528e5f706308c7b0e8f22a4d9dbb5b5715db7c) +++ sources/view/hd/data/VHDTreatmentStatesData.cpp (.../VHDTreatmentStatesData.cpp) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -14,7 +14,7 @@ #include "VHDTreatmentStatesData.h" // Project -#include "guicontroller.h" +#include "GuiController.h" VIEW_DEF(VHDTreatmentStates, TreatmentStatesData) Index: sources/view/hd/data/VHDTreatmentStatesData.h =================================================================== diff -u -r0e528e5f706308c7b0e8f22a4d9dbb5b5715db7c -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/view/hd/data/VHDTreatmentStatesData.h (.../VHDTreatmentStatesData.h) (revision 0e528e5f706308c7b0e8f22a4d9dbb5b5715db7c) +++ sources/view/hd/data/VHDTreatmentStatesData.h (.../VHDTreatmentStatesData.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -18,8 +18,8 @@ // Project #include "MModel.h" -#include "vview.h" -#include "guiglobals.h" +#include "VView.h" +#include "GuiGlobals.h" // namespace using namespace Gui; @@ -29,11 +29,11 @@ { Q_OBJECT - PROPERTY( quint32, subMode , 0) - PROPERTY( quint32, ufState , 0) + PROPERTY( quint32, subMode , 0); + PROPERTY( quint32, ufState , 0); // coco begin validated: Validated manually, but has not been used yet. // instead VTreatmentAdjustmentSaline::isStarted is used which has more control over the saline state. - PROPERTY( quint32, salineState , 0) + PROPERTY( quint32, salineState , 0); // coco end VIEW_DEC(VHDTreatmentStates, TreatmentStatesData) Index: sources/view/hd/data/VTreatmentBloodFlow.cpp =================================================================== diff -u --- sources/view/hd/data/VTreatmentBloodFlow.cpp (revision 0) +++ sources/view/hd/data/VTreatmentBloodFlow.cpp (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,31 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file vtreatmentbloodflow.cpp + * \author (last) Behrouz NematiPour + * \date (last) 07-May-2020 + * \author (original) Behrouz NematiPour + * \date (original) 10-Mar-2020 + * + */ +#include "VTreatmentBloodFlow.h" + +// Project +#include "GuiController.h" + +VIEW_DEF(VTreatmentBloodFlow, BloodFlowData) + +void VTreatmentBloodFlow::onActionReceive(const BloodFlowData &vData) +{ + bloodFlow_FlowSetPoint (vData.mFlowSetPoint ); + bloodFlow_MeasuredFlow (vData.mMeasuredFlow ); + bloodFlow_RotorSpeed (vData.mRotorSpeed ); + bloodFlow_MotorSpeed (vData.mMotorSpeed ); + bloodFlow_MotorCtlSpeed (vData.mMotorCtlSpeed ); + bloodFlow_MotorCtlCurrent (vData.mMotorCtlCurrent); + bloodFlow_PWMDutyCycle (vData.mPWMDutyCycle ); +} Index: sources/view/hd/data/VTreatmentBloodFlow.h =================================================================== diff -u --- sources/view/hd/data/VTreatmentBloodFlow.h (revision 0) +++ sources/view/hd/data/VTreatmentBloodFlow.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,41 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file vtreatmentbloodflow.h + * \author (last) Behrouz NematiPour + * \date (last) 07-May-2020 + * \author (original) Behrouz NematiPour + * \date (original) 10-Mar-2020 + * + */ +#pragma once + +// Qt +#include + +// Project +#include "MModel.h" +#include "VView.h" + +// namespace +namespace View { + +class VTreatmentBloodFlow : public QObject +{ + Q_OBJECT + + PROPERTY( qint32 , bloodFlow_FlowSetPoint , 0); + PROPERTY( float , bloodFlow_MeasuredFlow , 0); + PROPERTY( float , bloodFlow_RotorSpeed , 0); + PROPERTY( float , bloodFlow_MotorSpeed , 0); + PROPERTY( float , bloodFlow_MotorCtlSpeed , 0); + PROPERTY( float , bloodFlow_MotorCtlCurrent, 0); + PROPERTY( float , bloodFlow_PWMDutyCycle , 0); + + VIEW_DEC(VTreatmentBloodFlow, BloodFlowData) +}; +} Index: sources/view/hd/data/VTreatmentDialysateFlow.cpp =================================================================== diff -u --- sources/view/hd/data/VTreatmentDialysateFlow.cpp (revision 0) +++ sources/view/hd/data/VTreatmentDialysateFlow.cpp (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,31 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file vtreatmentdialysateflow.cpp + * \author (last) Behrouz NematiPour + * \date (last) 07-May-2020 + * \author (original) Behrouz NematiPour + * \date (original) 10-Mar-2020 + * + */ +#include "VTreatmentDialysateFlow.h" + +// Project +#include "GuiController.h" + +VIEW_DEF(VTreatmentDialysateFlow, DialysateFlowData) + +void VTreatmentDialysateFlow::onActionReceive(const DialysateFlowData &vData) +{ + dialysateFlow_FlowSetPoint (vData.mFlowSetPoint ); + dialysateFlow_MeasuredFlow (vData.mMeasuredFlow ); + dialysateFlow_RotorSpeed (vData.mRotorSpeed ); + dialysateFlow_MotorSpeed (vData.mMotorSpeed ); + dialysateFlow_MotorCtlSpeed (vData.mMotorCtlSpeed ); + dialysateFlow_MotorCtlCurrent (vData.mMotorCtlCurrent); + dialysateFlow_PWMDutyCycle (vData.mPWMDutyCycle ); +} Index: sources/view/hd/data/VTreatmentDialysateFlow.h =================================================================== diff -u --- sources/view/hd/data/VTreatmentDialysateFlow.h (revision 0) +++ sources/view/hd/data/VTreatmentDialysateFlow.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,41 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file vtreatmentdialysateflow.h + * \author (last) Behrouz NematiPour + * \date (last) 07-May-2020 + * \author (original) Behrouz NematiPour + * \date (original) 10-Mar-2020 + * + */ +#pragma once + +// Qt +#include + +// Project +#include "MModel.h" +#include "VView.h" + +// namespace +namespace View { + +class VTreatmentDialysateFlow : public QObject +{ + Q_OBJECT + + PROPERTY( qint32 , dialysateFlow_FlowSetPoint , 0); + PROPERTY( float , dialysateFlow_MeasuredFlow , 0); + PROPERTY( float , dialysateFlow_RotorSpeed , 0); + PROPERTY( float , dialysateFlow_MotorSpeed , 0); + PROPERTY( float , dialysateFlow_MotorCtlSpeed , 0); + PROPERTY( float , dialysateFlow_MotorCtlCurrent, 0); + PROPERTY( float , dialysateFlow_PWMDutyCycle , 0); + + VIEW_DEC(VTreatmentDialysateFlow, DialysateFlowData) +}; +} Index: sources/view/hd/data/VTreatmentPressureOcclusion.cpp =================================================================== diff -u --- sources/view/hd/data/VTreatmentPressureOcclusion.cpp (revision 0) +++ sources/view/hd/data/VTreatmentPressureOcclusion.cpp (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,29 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file vtreatmentpressureocclusion.cpp + * \author (last) Behrouz NematiPour + * \date (last) 07-May-2020 + * \author (original) Behrouz NematiPour + * \date (original) 24-Mar-2020 + * + */ +#include "VTreatmentPressureOcclusion.h" + +// Project +#include "GuiController.h" + +VIEW_DEF(VTreatmentPressureOcclusion, PressureOcclusionData) + +void VTreatmentPressureOcclusion::onActionReceive(const PressureOcclusionData &vData) +{ + pressureocclusion_ArterialPressure ( vData.mArterialPressure ); + pressureocclusion_VenousPressure ( vData.mVenousPressure ); + pressureocclusion_BloodPumpOcclusion ( vData.mBloodPumpOcclusion ); + pressureocclusion_DialysateInletPumpOcclusion ( vData.mDialysateInletPumpOcclusion ); + pressureocclusion_DialysateOutletPumpOcclusion ( vData.mDialysateOutletPumpOcclusion ); +} Index: sources/view/hd/data/VTreatmentPressureOcclusion.h =================================================================== diff -u --- sources/view/hd/data/VTreatmentPressureOcclusion.h (revision 0) +++ sources/view/hd/data/VTreatmentPressureOcclusion.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,41 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file vtreatmentpressureocclusion.h + * \author (last) Behrouz NematiPour + * \date (last) 07-May-2020 + * \author (original) Behrouz NematiPour + * \date (original) 24-Mar-2020 + * + */ +#pragma once + +// Qt +#include + +// Project +#include "MModel.h" +#include "VView.h" + +// namespace +namespace View { + +class VTreatmentPressureOcclusion : public QObject +{ + Q_OBJECT + + PROPERTY( float, pressureocclusion_ArterialPressure , 0); + PROPERTY( float, pressureocclusion_VenousPressure , 0); + // coco begin validated: These three properties have not been used in GUI. + // has been manually tested that it works perfectly fine if used. + PROPERTY( float, pressureocclusion_BloodPumpOcclusion , 0); + PROPERTY( float, pressureocclusion_DialysateInletPumpOcclusion , 0); + PROPERTY( float, pressureocclusion_DialysateOutletPumpOcclusion , 0); + // coco end + VIEW_DEC(VTreatmentPressureOcclusion, PressureOcclusionData) +}; +} Index: sources/view/hd/data/VTreatmentRanges.cpp =================================================================== diff -u --- sources/view/hd/data/VTreatmentRanges.cpp (revision 0) +++ sources/view/hd/data/VTreatmentRanges.cpp (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,30 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file vtreatmentranges.cpp + * \author (last) Behrouz NemaiPour + * \date (last) 04-Jun-2020 + * \author (original) Behrouz NematiPour + * \date (original) 31-Mar-2020 + * + */ +#include "VTreatmentRanges.h" + +// Project +#include "GuiController.h" + +VIEW_DEF(VTreatmentRanges, TreatmentRangesData) + +void VTreatmentRanges::onActionReceive(const TreatmentRangesData &vData) +{ + treatmentRanges_Duration_Min ( vData.mDuration_Min ); + treatmentRanges_Duration_Max ( vData.mDuration_Max ); + treatmentRanges_Ultrafiltration_Volume_Min ( vData.mUltrafiltration_Volume_Min / 1000 ); // mL => L + treatmentRanges_Ultrafiltration_Volume_Max ( vData.mUltrafiltration_Volume_Max / 1000 ); // mL => L + treatmentRanges_Dialysate_Flow_Min ( vData.mDialysate_Flow_Min ); + treatmentRanges_Dialysate_Flow_Max ( vData.mDialysate_Flow_Max ); +} Index: sources/view/hd/data/VTreatmentRanges.h =================================================================== diff -u --- sources/view/hd/data/VTreatmentRanges.h (revision 0) +++ sources/view/hd/data/VTreatmentRanges.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,40 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file vtreatmentranges.h + * \author (last) Behrouz NematiPour + * \date (last) 07-May-2020 + * \author (original) Behrouz NematiPour + * \date (original) 31-Mar-2020 + * + */ +#pragma once + +// Qt +#include + +// Project +#include "MModel.h" +#include "VView.h" + +// namespace +namespace View { + +class VTreatmentRanges : public QObject +{ + Q_OBJECT + + PROPERTY( quint32, treatmentRanges_Duration_Min , 0); + PROPERTY( quint32, treatmentRanges_Duration_Max , 0); + PROPERTY( float , treatmentRanges_Ultrafiltration_Volume_Min, 0); + PROPERTY( float , treatmentRanges_Ultrafiltration_Volume_Max, 0); + PROPERTY( quint32, treatmentRanges_Dialysate_Flow_Min , 0); + PROPERTY( quint32, treatmentRanges_Dialysate_Flow_Max , 0); + + VIEW_DEC(VTreatmentRanges, TreatmentRangesData) +}; +} Index: sources/view/hd/data/VTreatmentSalineData.cpp =================================================================== diff -u -r0e528e5f706308c7b0e8f22a4d9dbb5b5715db7c -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/view/hd/data/VTreatmentSalineData.cpp (.../VTreatmentSalineData.cpp) (revision 0e528e5f706308c7b0e8f22a4d9dbb5b5715db7c) +++ sources/view/hd/data/VTreatmentSalineData.cpp (.../VTreatmentSalineData.cpp) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -15,7 +15,7 @@ #include "VTreatmentSalineData.h" // Project -#include "guicontroller.h" +#include "GuiController.h" VIEW_DEF(VTreatmentSaline, TreatmentSalineData) Index: sources/view/hd/data/VTreatmentSalineData.h =================================================================== diff -u -raaf98fec556f719e9a65ce3f0376e2fd1d504bde -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- sources/view/hd/data/VTreatmentSalineData.h (.../VTreatmentSalineData.h) (revision aaf98fec556f719e9a65ce3f0376e2fd1d504bde) +++ sources/view/hd/data/VTreatmentSalineData.h (.../VTreatmentSalineData.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -19,7 +19,7 @@ // Project #include "MModel.h" -#include "vview.h" +#include "VView.h" // namespace namespace View { @@ -28,9 +28,9 @@ { Q_OBJECT - PROPERTY( quint32 , target , 0) - PROPERTY( float , cumulative , 0) - PROPERTY( float , delivered , 0) + PROPERTY( quint32 , target , 0); + PROPERTY( float , cumulative , 0); + PROPERTY( float , delivered , 0); VIEW_DEC(VTreatmentSaline, TreatmentSalineData) }; Index: sources/view/hd/data/VTreatmentTime.cpp =================================================================== diff -u --- sources/view/hd/data/VTreatmentTime.cpp (revision 0) +++ sources/view/hd/data/VTreatmentTime.cpp (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,27 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file vtreatmenttime.cpp + * \author (last) Behrouz NematiPour + * \date (last) 07-May-2020 + * \author (original) Behrouz NematiPour + * \date (original) 10-Mar-2020 + * + */ +#include "VTreatmentTime.h" + +// Project +#include "GuiController.h" + +VIEW_DEF(VTreatmentTime, TreatmentTimeData) + +void VTreatmentTime::onActionReceive(const TreatmentTimeData &vData) +{ + time_Total (vData.mTotal ); + time_Elapsed (vData.mElapsed ); + time_Remaining (vData.mRemaining ); +} Index: sources/view/hd/data/VTreatmentTime.h =================================================================== diff -u --- sources/view/hd/data/VTreatmentTime.h (revision 0) +++ sources/view/hd/data/VTreatmentTime.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,37 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file vtreatmenttime.h + * \author (last) Behrouz NematiPour + * \date (last) 07-May-2020 + * \author (original) Behrouz NematiPour + * \date (original) 10-Mar-2020 + * + */ +#pragma once + +// Qt +#include + +// Project +#include "MModel.h" +#include "VView.h" + +// namespace +namespace View { + +class VTreatmentTime : public QObject +{ + Q_OBJECT + + PROPERTY( quint32 , time_Total , 0); + PROPERTY( quint32 , time_Elapsed , 0); + PROPERTY( quint32 , time_Remaining , 0); + + VIEW_DEC(VTreatmentTime, TreatmentTimeData) +}; +} Index: sources/view/hd/data/VTreatmentUltrafiltration.cpp =================================================================== diff -u --- sources/view/hd/data/VTreatmentUltrafiltration.cpp (revision 0) +++ sources/view/hd/data/VTreatmentUltrafiltration.cpp (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,31 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file vtreatmentultrafiltration.cpp + * \author (last) Behrouz NemaiPour + * \date (last) 04-Jun-2020 + * \author (original) Behrouz NematiPour + * \date (original) 10-Mar-2020 + * + */ +#include "VTreatmentUltrafiltration.h" + +// Project +#include "GuiController.h" + +VIEW_DEF(VTreatmentUltrafiltration, OutletFlowData) + +void VTreatmentUltrafiltration::onActionReceive(const OutletFlowData &vData) +{ + ultrafiltration_RefUFVol ( vData.mRefUFVol / 1000 ); // mL => L + ultrafiltration_MeasUFVol ( vData.mMeasUFVol / 1000 ); // mL => L + ultrafiltration_RotorSpeed ( vData.mRotorSpeed ); + ultrafiltration_MotorSpeed ( vData.mMotorSpeed ); + ultrafiltration_MotorCtlSpeed ( vData.mMotorCtlSpeed ); + ultrafiltration_MotorCtlCurrent ( vData.mMotorCtlCurrent ); + ultrafiltration_PWMDtCycle ( vData.mPWMDtCycle ); +} Index: sources/view/hd/data/VTreatmentUltrafiltration.h =================================================================== diff -u --- sources/view/hd/data/VTreatmentUltrafiltration.h (revision 0) +++ sources/view/hd/data/VTreatmentUltrafiltration.h (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -0,0 +1,50 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file vtreatmentultrafiltration.h + * \author (last) Behrouz NemaiPour + * \date (last) 22-Jun-2020 + * \author (original) Behrouz NematiPour + * \date (original) 10-Mar-2020 + * + */ +#pragma once + +// Qt +#include + +// Project +#include "MModel.h" +#include "VView.h" + +// namespace +namespace View { + +class VTreatmentUltrafiltration : public QObject +{ + Q_OBJECT + + // coco begin validated : Manually validated + PROPERTY( float, precision , 3); // Centralized Gui value : none model property + // ~~~~~ Prescription values which we currently don't have. + // TODO : min/max should come from pre-treatment prescription parameters which we don't have now (2020/05/12) + PROPERTY( float, minimum , 0.000); + PROPERTY( float, maximum , 0.600); + // ~~~~~ + // coco end + + PROPERTY( float, ultrafiltration_RefUFVol , 0); + PROPERTY( float, ultrafiltration_MeasUFVol , 0); + PROPERTY( float, ultrafiltration_RotorSpeed , 0); + PROPERTY( float, ultrafiltration_MotorSpeed , 0); + PROPERTY( float, ultrafiltration_MotorCtlSpeed , 0); + PROPERTY( float, ultrafiltration_MotorCtlCurrent, 0); + PROPERTY( float, ultrafiltration_PWMDtCycle , 0); + + VIEW_DEC(VTreatmentUltrafiltration, OutletFlowData) +}; +} Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/view/valarmstatus.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/view/valarmstatus.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/view/vpoweroff.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/view/vpoweroff.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/view/vtreatmentadjustmentduration.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/view/vtreatmentadjustmentduration.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/view/vtreatmentadjustmentflows.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/view/vtreatmentadjustmentflows.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/view/vtreatmentadjustmentresponsebase.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/view/vtreatmentadjustmentresponsebase.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/view/vtreatmentadjustmentultrafiltrationconfirm.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/view/vtreatmentadjustmentultrafiltrationconfirm.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/view/vtreatmentadjustmentultrafiltrationedit.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/view/vtreatmentadjustmentultrafiltrationedit.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/view/vtreatmentadjustmentultrafiltrationstate.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/view/vtreatmentadjustmentultrafiltrationstate.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/view/vtreatmentbloodflow.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/view/vtreatmentbloodflow.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/view/vtreatmentdialysateflow.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/view/vtreatmentdialysateflow.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/view/vtreatmentpressureocclusion.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/view/vtreatmentpressureocclusion.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/view/vtreatmentranges.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/view/vtreatmentranges.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/view/vtreatmenttime.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/view/vtreatmenttime.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/view/vtreatmentultrafiltration.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/view/vtreatmentultrafiltration.h'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 00d9bb06ec2bad14f6dc2db678b750c244f694ef refers to a dead (removed) revision in file `sources/view/vview.h'. Fisheye: No comparison available. Pass `N' to diff? Index: unittests/tst_acknow.cpp =================================================================== diff -u -r618891879f5cdc68e37ee68eea005afb76dd4e5b -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- unittests/tst_acknow.cpp (.../tst_acknow.cpp) (revision 618891879f5cdc68e37ee68eea005afb76dd4e5b) +++ unittests/tst_acknow.cpp (.../tst_acknow.cpp) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -15,9 +15,9 @@ #include "tst_acknow.h" // Project -#include "caninterface.h" -#include "frameinterface.h" -#include "messageacknowmodel.h" +#include "CanInterface.h" +#include "FrameInterface.h" +#include "MessageAcknowModel.h" #define DEBUG_ACKBACK_HD_TO_UI Index: unittests/tst_acknow.h =================================================================== diff -u -red5d989264015440d9da6d0830679394a323cf55 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- unittests/tst_acknow.h (.../tst_acknow.h) (revision ed5d989264015440d9da6d0830679394a323cf55) +++ unittests/tst_acknow.h (.../tst_acknow.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -19,7 +19,7 @@ #include // Project -#include "messagedispatcher.h" +#include "MessageDispatcher.h" using namespace Can; class tst_acknow : public QObject Index: unittests/tst_canbus.cpp =================================================================== diff -u -rd2035a8728794afeefaa244bf8d1597926d945f5 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- unittests/tst_canbus.cpp (.../tst_canbus.cpp) (revision d2035a8728794afeefaa244bf8d1597926d945f5) +++ unittests/tst_canbus.cpp (.../tst_canbus.cpp) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -1,22 +1,22 @@ /*! - * + * * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. * \copyright * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. - * + * * \file tst_canbus.cpp * \author (last) Behrouz NemaiPour * \date (last) 23-Jun-2020 * \author (original) Behrouz NematiPour * \date (original) 19-Dec-2019 - * + * */ #include "tst_canbus.h" // Project -#include "caninterface.h" -#include "frameinterface.h" +#include "CanInterface.h" +#include "FrameInterface.h" using namespace Can; Index: unittests/tst_canbus.h =================================================================== diff -u -red5d989264015440d9da6d0830679394a323cf55 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- unittests/tst_canbus.h (.../tst_canbus.h) (revision ed5d989264015440d9da6d0830679394a323cf55) +++ unittests/tst_canbus.h (.../tst_canbus.h) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -19,7 +19,7 @@ #include // Project -#include "messagedispatcher.h" +#include "MessageDispatcher.h" using namespace Can; class tst_canbus : public QObject Index: unittests/tst_initializations.cpp =================================================================== diff -u -rd2035a8728794afeefaa244bf8d1597926d945f5 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- unittests/tst_initializations.cpp (.../tst_initializations.cpp) (revision d2035a8728794afeefaa244bf8d1597926d945f5) +++ unittests/tst_initializations.cpp (.../tst_initializations.cpp) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -17,13 +17,13 @@ // Qt // Project -#include "applicationcontroller.h" -#include "guicontroller.h" +#include "ApplicationController.h" +#include "GuiController.h" #include "DriveWatcher.h" -#include "caninterface.h" -#include "frameinterface.h" -#include "messagedispatcher.h" -#include "messageacknowmodel.h" +#include "CanInterface.h" +#include "FrameInterface.h" +#include "MessageDispatcher.h" +#include "MessageAcknowModel.h" tst_initializations::tst_initializations(QObject *parent) : QObject(parent) { } Index: unittests/tst_logging.cpp =================================================================== diff -u -rd2035a8728794afeefaa244bf8d1597926d945f5 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- unittests/tst_logging.cpp (.../tst_logging.cpp) (revision d2035a8728794afeefaa244bf8d1597926d945f5) +++ unittests/tst_logging.cpp (.../tst_logging.cpp) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -15,13 +15,13 @@ #include "tst_logging.h" // Qt -#include +#include #include // Project -#include "filehandler.h" -#include "logger.h" -#include "messageinterpreter.h" +#include "FileHandler.h" +#include "Logger.h" +#include "MessageInterpreter.h" using namespace Storage; Index: unittests/tst_messaging.cpp =================================================================== diff -u -raaf98fec556f719e9a65ce3f0376e2fd1d504bde -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- unittests/tst_messaging.cpp (.../tst_messaging.cpp) (revision aaf98fec556f719e9a65ce3f0376e2fd1d504bde) +++ unittests/tst_messaging.cpp (.../tst_messaging.cpp) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -18,10 +18,10 @@ // Project #include "main.h" -#include "messageinterpreter.h" -#include "messagebuilder.h" +#include "MessageInterpreter.h" +#include "MessageBuilder.h" #include "MPowerOff.h" -#include "messagedispatcher.h" +#include "MessageDispatcher.h" tst_messaging::tst_messaging(QObject *parent) : QObject(parent) { } Index: unittests/tst_threads.cpp =================================================================== diff -u -rd2035a8728794afeefaa244bf8d1597926d945f5 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- unittests/tst_threads.cpp (.../tst_threads.cpp) (revision d2035a8728794afeefaa244bf8d1597926d945f5) +++ unittests/tst_threads.cpp (.../tst_threads.cpp) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -17,14 +17,14 @@ // Qt // Project -#include "threads.h" -#include "applicationcontroller.h" -#include "guicontroller.h" +#include "Threads.h" +#include "ApplicationController.h" +#include "GuiController.h" #include "DriveWatcher.h" -#include "caninterface.h" -#include "frameinterface.h" -#include "messagedispatcher.h" -#include "messageacknowmodel.h" +#include "CanInterface.h" +#include "FrameInterface.h" +#include "MessageDispatcher.h" +#include "MessageAcknowModel.h" tst_threads::tst_threads(QObject *parent) : QObject(parent) { } Index: unittests/tst_views.cpp =================================================================== diff -u -r44a85c96ab55e424866ec4cca0270aa218355f82 -r00d9bb06ec2bad14f6dc2db678b750c244f694ef --- unittests/tst_views.cpp (.../tst_views.cpp) (revision 44a85c96ab55e424866ec4cca0270aa218355f82) +++ unittests/tst_views.cpp (.../tst_views.cpp) (revision 00d9bb06ec2bad14f6dc2db678b750c244f694ef) @@ -17,8 +17,8 @@ // Qt // Project -#include "vtreatmentadjustmentresponsebase.h" -#include "vtreatmentadjustmentultrafiltrationstate.h" +#include "VTreatmentAdjustmentResponseBase.h" +#include "VTreatmentAdjustmentUltrafiltrationState.h" tst_views::tst_views(QObject *parent) : QObject(parent) { }