Index: denali.pro =================================================================== diff -u -r188d7611230946fc5fde4e3e837a09202dd93eea -rfeb3423b373dc2a2c4267ef9fcb4d924d738423d --- denali.pro (.../denali.pro) (revision 188d7611230946fc5fde4e3e837a09202dd93eea) +++ denali.pro (.../denali.pro) (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -30,11 +30,13 @@ sources/storage \ sources/gui \ sources/canbus \ - sources/utility + sources/utility \ + sources/abstract HEADERS += \ sources/applicationcontroller.h \ sources/applicationpost.h \ + sources/canbus/alarminterpreter.h \ sources/canbus/caninterface.h \ sources/canbus/frameinterface.h \ sources/canbus/messagebuilder.h \ @@ -51,6 +53,8 @@ sources/storage/filehandler.h \ sources/storage/logger.h \ sources/storage/settings.h \ + sources/storage/storageglobals.h \ + sources/storage/usbwatcher.h \ sources/utility/crc.h \ sources/utility/format.h \ sources/utility/types.h @@ -59,6 +63,7 @@ main.cpp \ sources/applicationcontroller.cpp \ sources/applicationpost.cpp \ + sources/canbus/alarminterpreter.cpp \ sources/canbus/caninterface.cpp \ sources/canbus/frameinterface.cpp \ sources/canbus/messagebuilder.cpp \ @@ -73,6 +78,8 @@ sources/storage/filehandler.cpp \ sources/storage/logger.cpp \ sources/storage/settings.cpp \ + sources/storage/storageglobals.cpp \ + sources/storage/usbwatcher.cpp \ sources/utility/crc.cpp \ sources/utility/format.cpp \ sources/utility/types.cpp Index: main.cpp =================================================================== diff -u -r5963f00ffd2c557d3ae06a5deea05032a3a3bd68 -rfeb3423b373dc2a2c4267ef9fcb4d924d738423d --- main.cpp (.../main.cpp) (revision 5963f00ffd2c557d3ae06a5deea05032a3a3bd68) +++ main.cpp (.../main.cpp) (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -36,6 +36,7 @@ #include "applicationcontroller.h" #include "guicontroller.h" #include "logger.h" +#include "usbwatcher.h" #ifdef UNIT_TEST #include TEST_CLASS_INCLUDE @@ -51,17 +52,17 @@ //! - Qt Application initialization and parameters settings // Qt Core Application parameters settings - // Qt Core Application Initialization - QApplication app(argc, argv); - app.thread()->setObjectName("Main Thread"); - qDebug() << app.thread()->objectName(); QApplication::setApplicationName(QLatin1String("Denali")); QApplication::setOrganizationName(QLatin1String("Diality Inc.")); //! - Check the required font(s) present and can be loaded QApplication::setFont(QFont("Barlow")); + // Qt Core Application Initialization + QApplication app(argc, argv); + app.thread()->setObjectName("Main Thread"); + // Test code for debugging can messages bool _consoleoutFrameInterface = false; bool _consoleoutCanInterface = false; @@ -90,38 +91,30 @@ app.installTranslator(&translator); } + //! - Initializing USB Watcher + _USBWatcher->init(); + //! - Initializing File Handler _FileHandler->init(); //! - Initializing Logger - //QThread _Logger_Thread; - //_Logger_Thread.setObjectName("Logger Thread"); _Logger->init(); - //_Logger->moveToThread(&_Logger_Thread); - //QObject::connect(&_Logger_Thread, SIGNAL(finished()), _Logger, SLOT(deleteLater())); - //_Logger_Thread.start(); LOG_EVENT(QObject::tr("Application Started")); //! - Initializing Main Timer _MainTimer->init(); - LOG_EVENT(QObject::tr("Main Timer Initialized")); //! - Initializing CanBus Interface _CanInterface->init(); _CanInterface->enableConsoleOut(_consoleoutCanInterface); - LOG_EVENT(QObject::tr("CanInterface Initialized")); - LOG_EVENT(QObject::tr("console out CanInterface %1").arg(_consoleoutCanInterface)); //! - Initializing CanBus Message Handler _FrameInterface->init(); - LOG_EVENT(QObject::tr("FrameInterface Initialized")); //! - Initializing CanBus Message Dispatcher _MessageDispatcher->init(); _MessageDispatcher->enableConsoleOut(_consoleoutFrameInterface); - LOG_EVENT(QObject::tr("MessageDispatcher Initialized")); - LOG_EVENT(QObject::tr("console out MessageDispatcher %1").arg(_consoleoutFrameInterface)); //! - Initializing Application Controller _ApplicationController->init(); @@ -136,11 +129,12 @@ ////! - Initializing GUI Controller _GuiController->init(); - LOG_EVENT(QObject::tr("Gui Controller Initialized")); //! - Initialize the Qml Viewer and starts GUI startGui(); - return app.exec(); + int app_exec = app.exec(); + + return app_exec; } #endif Index: scripts/run.sh =================================================================== diff -u -r174d5078531f9dfbe9cdc45274b852984bb72647 -rfeb3423b373dc2a2c4267ef9fcb4d924d738423d --- scripts/run.sh (.../run.sh) (revision 174d5078531f9dfbe9cdc45274b852984bb72647) +++ scripts/run.sh (.../run.sh) (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -3,8 +3,13 @@ HOME=/home/root SDCARD_DEV=/dev/mmcblk1p1 SDCARD_MNT=/media/sd-card/ +USB_MNT=/media/usb/ LOG_PATH=$SDCARD_MNT +#create folders for sd-card and usb if not exist +mkdir -p $SDCARD_MNT +mkdir -p $USB_MNT + #setting up can interface ip link set can0 up type can bitrate 250000 if [ $? -eq 0 ]; then @@ -22,10 +27,10 @@ echo ":: Log location set to $LOG_PATH" #launching candump and setting the can log locations -candump can0 1>$LOG_PATH/canmsg.log 2>$LOG_PATH/canmsg.err & -if [ $? -eq 0 ]; then - echo ":: candump launched" -fi +#candump can0 1>$LOG_PATH/canmsg.log 2>$LOG_PATH/canmsg.err & +#if [ $? -eq 0 ]; then +# echo ":: candump launched" +#fi #launching denali application $HOME/denali & Index: sources/abstract/singleton.h =================================================================== diff -u --- sources/abstract/singleton.h (revision 0) +++ sources/abstract/singleton.h (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -0,0 +1,95 @@ +/*! + * + * 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 + * date 12/31/2019 + * author Behrouz NematiPour + * + */ +#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; + } +}; + Index: sources/applicationcontroller.cpp =================================================================== diff -u -r5963f00ffd2c557d3ae06a5deea05032a3a3bd68 -rfeb3423b373dc2a2c4267ef9fcb4d924d738423d --- sources/applicationcontroller.cpp (.../applicationcontroller.cpp) (revision 5963f00ffd2c557d3ae06a5deea05032a3a3bd68) +++ sources/applicationcontroller.cpp (.../applicationcontroller.cpp) (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -21,6 +21,7 @@ #include "guicontroller.h" #include "messagedispatcher.h" #include "logger.h" +#include "usbwatcher.h" // Singleton SINGLETON_INIT(ApplicationController) @@ -63,9 +64,9 @@ connect(_GuiController , SIGNAL(didUSBDriveUmount()), this , SLOT( onUSBDriveUmount())); - connect(_FileHandler , SIGNAL(didUSBDriveMount ()), + connect(_USBWatcher , SIGNAL(didUSBDriveMount ()), this , SLOT( onUSBDriveMount ())); - connect(_FileHandler , SIGNAL(didUSBDriveRemove()), + connect(_USBWatcher , SIGNAL(didUSBDriveRemove()), this , SLOT( onUSBDriveRemove())); connect(_GuiController , SIGNAL(didExportLog()), @@ -113,7 +114,7 @@ void ApplicationController::onUSBDriveUmount() { - _FileHandler->umounted(true); + emit didUSBDriveUmount(); } void ApplicationController::onUSBDriveRemove() @@ -123,7 +124,7 @@ void ApplicationController::onExportLog() { - _Logger->doExportLog(); + emit didExportLog(); } /*! Index: sources/applicationcontroller.h =================================================================== diff -u -r5963f00ffd2c557d3ae06a5deea05032a3a3bd68 -rfeb3423b373dc2a2c4267ef9fcb4d924d738423d --- sources/applicationcontroller.h (.../applicationcontroller.h) (revision 5963f00ffd2c557d3ae06a5deea05032a3a3bd68) +++ sources/applicationcontroller.h (.../applicationcontroller.h) (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -22,7 +22,7 @@ #include "guiglobals.h" #include "filehandler.h" #include "applicationpost.h" -#include "canbus/caninterface.h" +#include "caninterface.h" // define @@ -39,7 +39,9 @@ ApplicationPost *_applicationPost = nullptr; +// Singleton SINGLETON_DECL(ApplicationController) + public: bool init(); @@ -64,8 +66,11 @@ void didActionTransmit(GuiActionType vAction, const QVariantList &vData); // UI => HD/DG void didUSBDriveMount (); + void didUSBDriveUmount(); void didUSBDriveRemove(); + void didExportLog(); + void quit(int retcode=0); }; Index: sources/canbus/alarminterpreter.cpp =================================================================== diff -u --- sources/canbus/alarminterpreter.cpp (revision 0) +++ sources/canbus/alarminterpreter.cpp (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -0,0 +1,19 @@ +/*! + * + * 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 alarmhandler.cpp + * date 12/30/2019 + * author Behrouz NematiPour + * + */ +#include "alarminterpreter.h" + +AlarmInterpreter::AlarmInterpreter(QObject *parent) : QObject(parent) +{ + +} Index: sources/canbus/alarminterpreter.h =================================================================== diff -u --- sources/canbus/alarminterpreter.h (revision 0) +++ sources/canbus/alarminterpreter.h (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -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 alarmhandler.h + * date 12/30/2019 + * author Behrouz NematiPour + * + */ +#pragma once + +#include + +class AlarmInterpreter : public QObject +{ + Q_OBJECT +public: + + + + + + + + explicit AlarmInterpreter(QObject *parent = nullptr); + + + + + + + +signals: + +public slots: +}; + Index: sources/canbus/caninterface.cpp =================================================================== diff -u -r5963f00ffd2c557d3ae06a5deea05032a3a3bd68 -rfeb3423b373dc2a2c4267ef9fcb4d924d738423d --- sources/canbus/caninterface.cpp (.../caninterface.cpp) (revision 5963f00ffd2c557d3ae06a5deea05032a3a3bd68) +++ sources/canbus/caninterface.cpp (.../caninterface.cpp) (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -59,6 +59,7 @@ return false; } status(tr("Connected")); + LOG_EVENT(QObject::tr("CanInterface Initialized")); LOG_EVENT(status()); return true; } @@ -141,6 +142,8 @@ { if ( ! _enableConsoleOut ) return; + LOG_EVENT(QObject::tr("console out CanInterface Enabled")); + const QString time = QString::fromLatin1("%1.%2 ") .arg(vFrame.timeStamp().seconds(), 10, 10, QLatin1Char(' ')) .arg(vFrame.timeStamp().microSeconds() / 100, 4, 10, QLatin1Char('0')); @@ -236,6 +239,7 @@ return; while (_canDevice->framesAvailable()) { + // qDebug() << "framesAvailable : " << _canDevice->framesAvailable(); const QCanBusFrame frame = _canDevice->readFrame(); consoleOut(frame); emit didFrameReceive(frame); Index: sources/canbus/frameinterface.cpp =================================================================== diff -u -r5963f00ffd2c557d3ae06a5deea05032a3a3bd68 -rfeb3423b373dc2a2c4267ef9fcb4d924d738423d --- sources/canbus/frameinterface.cpp (.../frameinterface.cpp) (revision 5963f00ffd2c557d3ae06a5deea05032a3a3bd68) +++ sources/canbus/frameinterface.cpp (.../frameinterface.cpp) (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -42,6 +42,7 @@ void FrameInterface::init() { initConnections(); + LOG_EVENT(QObject::tr("FrameInterface Initialized")); } /*! Index: sources/canbus/messagebuilder.cpp =================================================================== diff -u -r5963f00ffd2c557d3ae06a5deea05032a3a3bd68 -rfeb3423b373dc2a2c4267ef9fcb4d924d738423d --- sources/canbus/messagebuilder.cpp (.../messagebuilder.cpp) (revision 5963f00ffd2c557d3ae06a5deea05032a3a3bd68) +++ sources/canbus/messagebuilder.cpp (.../messagebuilder.cpp) (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -404,5 +404,6 @@ void MessageBuilder::consoleOut(const QByteArray &vPayload, bool vIsHeader, Can_Id vCan_Id, bool vUseColor) { if ( ! _enableConsoleOut) return; + LOG_EVENT(QObject::tr("console out MessageDispatcher Enabled")); printPayload(vPayload, vIsHeader, vCan_Id, vUseColor); } Index: sources/canbus/messagedispatcher.cpp =================================================================== diff -u -r5963f00ffd2c557d3ae06a5deea05032a3a3bd68 -rfeb3423b373dc2a2c4267ef9fcb4d924d738423d --- sources/canbus/messagedispatcher.cpp (.../messagedispatcher.cpp) (revision 5963f00ffd2c557d3ae06a5deea05032a3a3bd68) +++ sources/canbus/messagedispatcher.cpp (.../messagedispatcher.cpp) (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -37,6 +37,7 @@ void MessageDispatcher::init() { initConnections(); + LOG_EVENT(QObject::tr("MessageDispatcher Initialized")); } /*! Index: sources/canbus/messageglobals.h =================================================================== diff -u -r5963f00ffd2c557d3ae06a5deea05032a3a3bd68 -rfeb3423b373dc2a2c4267ef9fcb4d924d738423d --- sources/canbus/messageglobals.h (.../messageglobals.h) (revision 5963f00ffd2c557d3ae06a5deea05032a3a3bd68) +++ sources/canbus/messageglobals.h (.../messageglobals.h) (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -28,10 +28,11 @@ * So the data collector has to collect this amount of bytes as payload of a message. */ const QHash payloadLen { - {GuiActionType::PowerOff , 1 }, - {GuiActionType::KeepAlive , 0 }, - {GuiActionType::BloodFlow , 7 * 4 } , // 7 parameters each 4bytes - {GuiActionType::String , 255 }, + {GuiActionType::PowerOff , 1 }, + {GuiActionType::KeepAlive , 0 }, + {GuiActionType::BloodFlow , 7 * 4 } , // 7 parameters each 4bytes + {GuiActionType::DialysateFlow , 7 * 4 } , // 7 parameters each 4bytes + {GuiActionType::String , 255 }, }; /*! Index: sources/canbus/messageinterpreter.cpp =================================================================== diff -u -r8c5f54b53a19dd29a3b9731d8ec1bf3d1ba3be62 -rfeb3423b373dc2a2c4267ef9fcb4d924d738423d --- sources/canbus/messageinterpreter.cpp (.../messageinterpreter.cpp) (revision 8c5f54b53a19dd29a3b9731d8ec1bf3d1ba3be62) +++ sources/canbus/messageinterpreter.cpp (.../messageinterpreter.cpp) (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -16,8 +16,9 @@ // Qt // Project -#include "logger.h" +#include "types.h" #include "format.h" +#include "logger.h" using namespace Can; @@ -106,6 +107,21 @@ } /*! + * \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) +{ + QString mActionIdHexString = Format::toHexString(vMessage.actionId, false, eLenMessageIDDigits); + qDebug() << "WARNG :" << tr("Unhandled Message ID (HD)"); + qDebug().noquote() << QString(mActionIdHexString + " " + vMessage.data.toHex('.')).toLatin1(); + qDebug() << ""; +} + +/*! * \brief MessageInterpreter::interpretMessage_HD * \details This method will be called * for received messages from HD to interpret the vMessage of type Message @@ -135,50 +151,28 @@ break; } - case GuiActionType::BloodFlow: { - types::S32 mFlowSetPoint ; - types::F32 mMeasuredFlow ; - types::F32 mRotorSpeed ; - types::F32 mMotorSpeed ; - types::F32 mMotorCtlSpeed ; - types::F32 mMotorCtlCurrent ; - types::F32 mPWMDtCycle ; - ok = getBloodFlowData(vMessage, mFlowSetPoint, mMeasuredFlow, mRotorSpeed, mMotorSpeed, mMotorCtlSpeed, mMotorCtlCurrent, mPWMDtCycle); - LOG_DATUM(QString("Blood Flow(%1, %2, %3, %4, %5, %6, %7)") - .arg(mFlowSetPoint .value) - .arg(mMeasuredFlow .value) - .arg(mRotorSpeed .value) - .arg(mMotorSpeed .value) - .arg(mMotorCtlSpeed .value) - .arg(mMotorCtlCurrent .value) - .arg(mPWMDtCycle .value) - ); - if (ok) { - vData += mFlowSetPoint .value; - vData += mMeasuredFlow .value; - vData += mRotorSpeed .value; - vData += mMotorSpeed .value; - vData += mMotorCtlSpeed .value; - vData += mMotorCtlCurrent.value; - vData += mPWMDtCycle .value; - } + case GuiActionType::BloodFlow: + ok = bloodFlowData (vMessage, vData); break; - } + case GuiActionType::DialysateFlow: + ok = dialysateFlowData (vMessage, vData); + break; + case GuiActionType::AlarmStatus: - printUnhandled(vMessage); + ok = alarmStatus (vMessage, vData); break; case GuiActionType::AlarmTriggered: - printUnhandled(vMessage); + printUnhandled (vMessage); break; case GuiActionType::AlarmCleared: - printUnhandled(vMessage); + printUnhandled (vMessage); break; default: - printUnhandled(vMessage); + printUnhandled (vMessage); break; } return ok; @@ -207,11 +201,37 @@ } /*! + * \brief MessageInterpreter::getPowerOffData + * \details This is the method which interprets the PowerOff message data + * in vMessage of type Message. + * to its elements of data. + * \param vMessage - The vMessage of type Message which contains all the data, + * require to be interpreted. + * \param vShowHide - The return value of extracted fro + * \return true if the data can be extracted as defined for PowerOff Message ID + */ +bool MessageInterpreter::getPowerOffData(const Message &vMessage, quint8 &vShowHide) +{ + bool ok = true; + int l = vMessage.data.length(); + quint8 ix = static_cast(GuiActionIndx::PowerOff_ShowHide); + if (l >= ix + 1) { + quint8 tmp = vMessage.data[ix]; + vShowHide = tmp; + } else { + QString mActionIdHexString = Format::toHexString(vMessage.actionId); + LOG_ERROR(tr("Incorrect data for Message ID (HD) '%1'").arg(mActionIdHexString)); + ok = false; + } + return ok; +} + +/*! * \brief MessageInterpreter::getBloodFlowData * \details This is the method which interprets the Blood Flow message data in vMessage of type Message * to its elements of data. * \param vMessage - The vMessage of type Message which contains all the data, require to be interpreted. - * \param vFlowSetPoint - Flow Set Point value of type signed int extracted out. + * \param vFlowSetPoint - Flow Set Point value of type signed int extracted out * \param vMeasuredFlow - Measured Flow value of type float extracted out * \param vRotorSpeed - Rotor Speed value of type float extracted out * \param vMotorSpeed - Motor Speed value of type float extracted out @@ -222,9 +242,9 @@ */ bool MessageInterpreter::getBloodFlowData( const Message &vMessage , - types::S32 &vFlowSetPoint , - types::F32 &vMeasuredFlow , types::F32 &vRotorSpeed , types::F32 &vMotorSpeed, - types::F32 &vMotorCtlSpeed , types::F32 &vMotorCtlCurrent , types::F32 &vPWMDtCycle) + Types::S32 &vFlowSetPoint , + Types::F32 &vMeasuredFlow , Types::F32 &vRotorSpeed , Types::F32 &vMotorSpeed, + Types::F32 &vMotorCtlSpeed , Types::F32 &vMotorCtlCurrent , Types::F32 &vPWMDtCycle) { if ( vMessage.actionId != GuiActionType::BloodFlow ) { return false; @@ -234,106 +254,212 @@ LOG_ERROR(tr("Incorrect data for Message ID (HD) '%1'").arg(mActionIdHexString)); return false; } - int i = 0; - int p = 0; - int j = 0; - p += 4; - j = 0; - while (i < p) { - vFlowSetPoint.bytes[j] = vMessage.data[i]; - j++; - i++; - } + int index = 0; // message data start position + Types::getValue<>(vMessage.data, index, vFlowSetPoint ); + Types::getValue<>(vMessage.data, index, vMeasuredFlow ); + Types::getValue<>(vMessage.data, index, vRotorSpeed ); + Types::getValue<>(vMessage.data, index, vMotorSpeed ); + Types::getValue<>(vMessage.data, index, vMotorCtlSpeed ); + Types::getValue<>(vMessage.data, index, vMotorCtlCurrent); + Types::getValue<>(vMessage.data, index, vPWMDtCycle ); - p += 4; - j = 0; - while (i < p) { - vMeasuredFlow.bytes[j] = vMessage.data[i]; - j++; - i++; - } + return true; +} - p += 4; - j = 0; - while (i < p) { - vRotorSpeed.bytes[j] = vMessage.data[i]; - j++; - i++; +bool MessageInterpreter::bloodFlowData(const Message &vMessage, QVariantList &vData) +{ + bool ok; + Types::S32 mFlowSetPoint ; + Types::F32 mMeasuredFlow ; + Types::F32 mRotorSpeed ; + Types::F32 mMotorSpeed ; + Types::F32 mMotorCtlSpeed ; + Types::F32 mMotorCtlCurrent ; + Types::F32 mPWMDtCycle ; + ok = getBloodFlowData(vMessage , + mFlowSetPoint , + mMeasuredFlow , + mRotorSpeed , + mMotorSpeed , + mMotorCtlSpeed , + mMotorCtlCurrent , + mPWMDtCycle ); + LOG_DATUM(QString("Blood Flow(%1, %2, %3, %4, %5, %6, %7)") + .arg(mFlowSetPoint .value) + .arg(mMeasuredFlow .value) + .arg(mRotorSpeed .value) + .arg(mMotorSpeed .value) + .arg(mMotorCtlSpeed .value) + .arg(mMotorCtlCurrent .value) + .arg(mPWMDtCycle .value) + ); + if (ok) { + vData += mFlowSetPoint .value; + vData += mMeasuredFlow .value; + vData += mRotorSpeed .value; + vData += mMotorSpeed .value; + vData += mMotorCtlSpeed .value; + vData += mMotorCtlCurrent.value; + vData += mPWMDtCycle .value; } + return ok; +} - p += 4; - j = 0; - while (i < p) { - vMotorSpeed.bytes[j] = vMessage.data[i]; - j++; - i++; - } +/*! + * \brief MessageInterpreter::getDialysateFlowData + * \details This is the method which interprets the Dialysate Flow message data in vMessage of type Message + * to its elements of data. + * \param vMessage - The vMessage of type Message which contains all the data, require to be interpreted. + * \param vFlowSetPoint - Flow Set Point value of type signed int extracted out + * \param vMeasuredFlow - Measured Flow value of type float extracted out + * \param vRotorSpeed - Rotor Speed value of type float extracted out + * \param vMotorSpeed - Motor Speed value of type float extracted out + * \param vMotorCtlSpeed - Motor Controller Speed value of type float extracted out + * \param vMotorCtlCurrent - Motor Controller Current value of type float extracted out + * \param vPWMDtCycle - PWM Duty Cycle in % value of type float extracted out + * \return true if the message can be successfully converted to the Blood Flow data elements. + */ +bool MessageInterpreter::getDialysateFlowData( + const Message &vMessage , + Types::S32 &vFlowSetPoint , + Types::F32 &vMeasuredFlow , Types::F32 &vRotorSpeed , Types::F32 &vMotorSpeed, + Types::F32 &vMotorCtlSpeed , Types::F32 &vMotorCtlCurrent , Types::F32 &vPWMDtCycle) - p += 4; - j = 0; - while (i < p) { - vMotorCtlSpeed.bytes[j] = vMessage.data[i]; - j++; - i++; +{ + if ( vMessage.actionId != GuiActionType::DialysateFlow ) { + return false; } - - p += 4; - j = 0; - while (i < p) { - vMotorCtlCurrent.bytes[j] = vMessage.data[i]; - j++; - i++; + if ( vMessage.data.length() < payloadLen[GuiActionType::DialysateFlow] ) { + QString mActionIdHexString = Format::toHexString(vMessage.actionId); + LOG_ERROR(tr("Incorrect data for Message ID (HD) '%1'").arg(mActionIdHexString)); + return false; } - p += 4; - j = 0; - while (i < p) { - vPWMDtCycle.bytes[j] = vMessage.data[i]; - j++; - i++; - } + int index = 0; // message data start position + Types::getValue<>(vMessage.data, index, vFlowSetPoint ); + Types::getValue<>(vMessage.data, index, vMeasuredFlow ); + Types::getValue<>(vMessage.data, index, vRotorSpeed ); + Types::getValue<>(vMessage.data, index, vMotorSpeed ); + Types::getValue<>(vMessage.data, index, vMotorCtlSpeed ); + Types::getValue<>(vMessage.data, index, vMotorCtlCurrent); + Types::getValue<>(vMessage.data, index, vPWMDtCycle ); return true; } +bool MessageInterpreter::dialysateFlowData(const Message &vMessage, QVariantList &vData) +{ + bool ok; + Types::S32 mFlowSetPoint ; + Types::F32 mMeasuredFlow ; + Types::F32 mRotorSpeed ; + Types::F32 mMotorSpeed ; + Types::F32 mMotorCtlSpeed ; + Types::F32 mMotorCtlCurrent ; + Types::F32 mPWMDtCycle ; + ok = getBloodFlowData(vMessage , + mFlowSetPoint , + mMeasuredFlow , + mRotorSpeed , + mMotorSpeed , + mMotorCtlSpeed , + mMotorCtlCurrent , + mPWMDtCycle ); + LOG_DATUM(QString("Dialysate Flow(%1, %2, %3, %4, %5, %6, %7)") + .arg(mFlowSetPoint .value) + .arg(mMeasuredFlow .value) + .arg(mRotorSpeed .value) + .arg(mMotorSpeed .value) + .arg(mMotorCtlSpeed .value) + .arg(mMotorCtlCurrent .value) + .arg(mPWMDtCycle .value) + ); + if (ok) { + vData += mFlowSetPoint .value; + vData += mMeasuredFlow .value; + vData += mRotorSpeed .value; + vData += mMotorSpeed .value; + vData += mMotorCtlSpeed .value; + vData += mMotorCtlCurrent.value; + vData += mPWMDtCycle .value; + } + return ok; +} + /*! - * \brief MessageInterpreter::getPowerOffData - * \details This is the method which interprets the PowerOff message data + * \brief MessageInterpreter::getAlarmStatus + * \details This method interprets AlarmStatus message data * in vMessage of type Message. - * to its elements of data. - * \param vMessage - The vMessage of type Message which contains all the data, - * require to be interpreted. - * \param vShowHide - The return value of extracted fro + * \param vMessage - The vMessage of type Message which contains all the data, + * require to be interpreted. + * \param vState - Alarm Priority value of type unsigned int as 4 bytes extracted out + * \param vTop - Top value of type unsigned int as 4 bytes extracted out + * \param vMuteTimeout - MuteTimeout value of type unsigned int as 4 bytes extracted out + * \param vEscalateTo - EscalateTo value of type unsigned int as 4 bytes extracted out + * \param vFlags - Flags value of type unsigned int as 1 byte extracted out * \return true if the data can be extracted as defined for PowerOff Message ID */ -bool MessageInterpreter::getPowerOffData(const Message &vMessage, quint8 &vShowHide) +bool MessageInterpreter::getAlarmStatus(const Message &vMessage, + Types::U32 &vState , Types::U32 &vTop , + Types::U32 &vMuteTimeout, Types::U32 &vEscalatesIn, + Types::Flags &vFlags) { - bool ok = true; - int l = vMessage.data.length(); - quint8 ix = static_cast(GuiActionIndx::PowerOff_ShowHide); - if (l >= ix + 1) { - quint8 tmp = vMessage.data[ix]; - vShowHide = tmp; - } else { + if ( vMessage.actionId != GuiActionType::AlarmStatus ) { + return false; + } + if ( vMessage.data.length() < payloadLen[GuiActionType::AlarmStatus] ) { QString mActionIdHexString = Format::toHexString(vMessage.actionId); LOG_ERROR(tr("Incorrect data for Message ID (HD) '%1'").arg(mActionIdHexString)); - ok = false; + return false; } - return ok; + + int index = 0; // message data start position + Types::getValue<>(vMessage.data, index, vState ); + Types::getValue<>(vMessage.data, index, vTop ); + Types::getValue<>(vMessage.data, index, vMuteTimeout ); + Types::getValue<>(vMessage.data, index, vEscalatesIn ); + Types::getBits (vMessage.data, index, vFlags , 16); + 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) +bool MessageInterpreter::alarmStatus(const Message &vMessage, QVariantList &vData) { - QString mActionIdHexString = Format::toHexString(vMessage.actionId, false, eLenMessageIDDigits); - qDebug() << "WARNG :" << tr("Unhandled Message ID (HD)"); - qDebug().noquote() << QString(mActionIdHexString + " " + vMessage.data.toHex('.')).toLatin1(); - qDebug() << ""; + bool ok; + Types::U32 mState ; + Types::U32 mTop ; + Types::U32 mMuteTimeout ; + Types::U32 mEscalatesIn ; + Types::Flags mFlags ; + ok = getAlarmStatus(vMessage , + mState , + mTop , + mMuteTimeout , + mEscalatesIn , + mFlags ); + LOG_DATUM(QString("Alarm Status(%1, %2, %3, %4, %5)") + .arg(mState .value ) + .arg(mTop .value ) + .arg(mMuteTimeout .value ) + .arg(mEscalatesIn .value ) + .arg(mFlags .toString()) + ); + if (ok) { + vData += mState .value ; + vData += mTop .value ; + vData += mMuteTimeout .value ; + vData += mEscalatesIn .value ; + for (int i = 0; i < mFlags.count(); i++) { + vData += mFlags.at(i); + } + } + + // --- an example of unit test --- // + // Types::Flags flag; + // int i = 0; + // QByteArray ba; + // ba += 0x83; ba += 0xf8; ba += 0x28; ba += 0xa1; + // Types::getBits(ba, i, flag, 32); + // qDebug() << '@' << flag << flag.toString() << ba; + return ok; } Index: sources/canbus/messageinterpreter.h =================================================================== diff -u -r12f922a6c61b7014345a441e2836e12fd3b0d00e -rfeb3423b373dc2a2c4267ef9fcb4d924d738423d --- sources/canbus/messageinterpreter.h (.../messageinterpreter.h) (revision 12f922a6c61b7014345a441e2836e12fd3b0d00e) +++ sources/canbus/messageinterpreter.h (.../messageinterpreter.h) (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -35,22 +35,42 @@ { Q_OBJECT - bool interpretMessage_HD(const Message &vMessage, GuiActionType &vActionId, QVariantList &vData) __attribute_warn_unused_result__; - bool interpretMessage_DG(const Message &vMessage, GuiActionType &vActionId, QVariantList &vData) __attribute_warn_unused_result__; + void printUnhandled (const Message &vMessage); - bool getBloodFlowData (const Message &vMessage , - types::S32 &vFlowSetPoint , - types::F32 &vMeasuredFlow , types::F32 &vRotorSpeed , types::F32 &vMotorSpeed, - types::F32 &vMotorCtlSpeed , types::F32 &vMotorCtlCurrent , types::F32 &vPWMDtCycle) __attribute_warn_unused_result__; - bool getPowerOffData (const Message &vMessage, quint8 &vShowHide) __attribute_warn_unused_result__; + bool interpretMessage_HD (const Message &vMessage , GuiActionType &vActionId, QVariantList &vData) __attribute_warn_unused_result__; + bool interpretMessage_DG (const Message &vMessage , GuiActionType &vActionId, QVariantList &vData) __attribute_warn_unused_result__; - void printUnhandled (const Message &vMessage); + bool getPowerOffData (const Message &vMessage , quint8 &vShowHide) __attribute_warn_unused_result__; + + // ---- BloodFlowData + bool getBloodFlowData (const Message &vMessage , + Types::S32 &vFlowSetPoint , + Types::F32 &vMeasuredFlow , Types::F32 &vRotorSpeed , Types::F32 &vMotorSpeed, + Types::F32 &vMotorCtlSpeed , Types::F32 &vMotorCtlCurrent , Types::F32 &vPWMDtCycle) __attribute_warn_unused_result__; + bool bloodFlowData (const Message &vMessage, QVariantList &vData) __attribute_warn_unused_result__; + + // ---- Dialysate FlowData + bool getDialysateFlowData (const Message &vMessage , + Types::S32 &vFlowSetPoint , + Types::F32 &vMeasuredFlow , Types::F32 &vRotorSpeed , Types::F32 &vMotorSpeed, + Types::F32 &vMotorCtlSpeed , Types::F32 &vMotorCtlCurrent , Types::F32 &vPWMDtCycle) __attribute_warn_unused_result__; + bool dialysateFlowData (const Message &vMessage, QVariantList &vData) __attribute_warn_unused_result__; + + + // ---- AlarmStatus + bool getAlarmStatus (const Message &vMessage , + Types::U32 &vState , Types::U32 &vTop , + Types::U32 &vMuteTimeout , Types::U32 &vEscalatesIn , + Types::Flags &vFlags ) __attribute_warn_unused_result__; + bool alarmStatus (const Message &vMessage, QVariantList &vData) __attribute_warn_unused_result__; + + public: explicit MessageInterpreter(QObject *parent = nullptr); // interpret the data into GUI understandable Actions/Data - bool interpretMessage(const Can_Id vCan_Id, const Message &vMessage, GuiActionType &vActionId, QVariantList &vData) __attribute_warn_unused_result__; - bool interpretMessage(const GuiActionType &vActionId, const QVariantList &vData, QByteArray &vPayload) __attribute_warn_unused_result__; + bool interpretMessage(const Can_Id vCan_Id, const Message &vMessage, GuiActionType &vActionId, QVariantList &vData) __attribute_warn_unused_result__; + bool interpretMessage(const GuiActionType &vActionId, const QVariantList &vData, QByteArray &vPayload) __attribute_warn_unused_result__; signals: Index: sources/gui/guicontroller.cpp =================================================================== diff -u -r5963f00ffd2c557d3ae06a5deea05032a3a3bd68 -rfeb3423b373dc2a2c4267ef9fcb4d924d738423d --- sources/gui/guicontroller.cpp (.../guicontroller.cpp) (revision 5963f00ffd2c557d3ae06a5deea05032a3a3bd68) +++ sources/gui/guicontroller.cpp (.../guicontroller.cpp) (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -18,6 +18,7 @@ // Project #include "applicationcontroller.h" +#include "logger.h" // namespace using namespace Gui; @@ -53,6 +54,8 @@ void GuiController::init() { initConnections(); + LOG_EVENT(QObject::tr("Gui Controller Initialized")); + } /*! Index: sources/gui/guiglobals.cpp =================================================================== diff -u -r5963f00ffd2c557d3ae06a5deea05032a3a3bd68 -rfeb3423b373dc2a2c4267ef9fcb4d924d738423d --- sources/gui/guiglobals.cpp (.../guiglobals.cpp) (revision 5963f00ffd2c557d3ae06a5deea05032a3a3bd68) +++ sources/gui/guiglobals.cpp (.../guiglobals.cpp) (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -29,9 +29,12 @@ */ void registerTypes() { - qRegisterMetaType ("GuiActionType"); - qRegisterMetaType ("GuiActionData"); - qRegisterMetaType ("GuiActionIndx"); + qRegisterMetaType ("GuiActionType" ); + qRegisterMetaType ("GuiActionData" ); + qRegisterMetaType ("GuiActionIndx" ); + + qRegisterMetaType ("GuiAlarmID" ); + qRegisterMetaType ("GuiAlarmPriority"); } /*! Index: sources/gui/guiglobals.h =================================================================== diff -u -rb84013c76474b0f0931e6be89a4c4def361def0b -rfeb3423b373dc2a2c4267ef9fcb4d924d738423d --- sources/gui/guiglobals.h (.../guiglobals.h) (revision b84013c76474b0f0931e6be89a4c4def361def0b) +++ sources/gui/guiglobals.h (.../guiglobals.h) (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -26,12 +26,14 @@ { Q_GADGET explicit GuiActions(); + public: - enum /*class*/ GuiActionsType_Enum /*: quint16 QML doesn't support*/ { + enum /*class*/ GuiActionsType_Enum /*: quint16 QML doesn't support enum types */ { Unknown = 0x0000, PowerOff = 0x0100, KeepAlive = 0x0700, BloodFlow = 0x0500, + DialysateFlow = 0x0800, AlarmStatus = 0x0200, AlarmTriggered = 0x0300, @@ -41,17 +43,43 @@ }; enum class GuiActionsIndx_Enum { - PowerOff_ShowHide = 0, - PowerOff_Response = 0, + // ---- PowerOff + PowerOff_ShowHide = 0 , + PowerOff_Response = 0 , - BloodFlow_FlowSetPoint = 0, - BloodFlow_MeasuredFlow , - BloodFlow_RotorSpeed , - BloodFlow_MotorSpeed , - BloodFlow_MotorCtlSpeed , - BloodFlow_MotorCtlCurrent , - BloodFlow_PWMDtCycle , + // ---- BloodFlow + BloodFlow_FlowSetPoint = 0 , + BloodFlow_MeasuredFlow , + BloodFlow_RotorSpeed , + BloodFlow_MotorSpeed , + BloodFlow_MotorCtlSpeed , + BloodFlow_MotorCtlCurrent , + BloodFlow_PWMDtCycle , + // ---- DialysateFlow + DialysateFlow_FlowSetPoint = 0 , + DialysateFlow_MeasuredFlow , + DialysateFlow_RotorSpeed , + DialysateFlow_MotorSpeed , + DialysateFlow_MotorCtlSpeed , + DialysateFlow_MotorCtlCurrent , + DialysateFlow_PWMDtCycle , + + // ---- AlarmStatus + AlarmStatus_Priority = 0 , + AlarmStatus_AlarmID , + AlarmStatus_EscalateIn , + AlarmStatus_MuteTimeout , + AlarmStatus_Flag_systemFault , + AlarmStatus_Flag_stop , + AlarmStatus_Flag_noClear , + AlarmStatus_Flag_noResume , + AlarmStatus_Flag_noRinseback , + AlarmStatus_Flag_noEndTreatment , + AlarmStatus_Flag_noNewTreatment , + AlarmStatus_Flag_bypassDialyzer , + AlarmStatus_Flag_alarmsToEscalate , + AlarmStatus_Flag_alarmsSilenced , }; enum class GuiActionsData_Enum /*: quint8 QML doesn't support*/ { @@ -68,16 +96,53 @@ Timeout = 0x01, }; + enum GuiAlarmPriority_Enum { + AlarmPriority_None = 0 , + AlarmPriority_Low , + AlarmPriority_Medium , + AlarmPriority_High , + }; + + enum GuiAlarmID_Enum { + No_Alarm = 0 , + Software_Fault , + Stuck_Button_Test_Failed , + FPGA_Post_Test_Failed , + Watchdog_Post_Test_Failed , + UI_Comm_Post_Failed , // 5 + Blood_pump_Mc_Current_Check , + Blood_Pump_Mc_Speed_Check , + Blood_Pump_Mc_Direction_Check , + Blood_Pump_Rotor_Speed_Check , + Dial_In_pump_Mc_Current_Check , // 10 + Dial_In_pump_Mc_Speed_Check , + Dial_In_pump_Mc_Direction_Check , + Dial_In_pump_Rotor_Speed_Check , + Dial_Out_Pump_Mc_Current_Check , + Dial_Out_Pump_Mc_Speed_Check , // 15 + Dial_Out_Pump_Mc_Direction_Check , + Dial_Out_Pump_Rotor_Speed_Check , + Watchdog_Expired , + Num_Of_Alarm_IDs , + }; + + Q_ENUM(GuiActionsType_Enum) Q_ENUM(GuiActionsData_Enum) Q_ENUM(GuiActionsIndx_Enum) + + Q_ENUM(GuiAlarmPriority_Enum) + Q_ENUM(GuiAlarmID_Enum) }; // to be able to use the enum as signal/slot parameter - typedef GuiActions::GuiActionsType_Enum GuiActionType; - typedef GuiActions::GuiActionsData_Enum GuiActionData; - typedef GuiActions::GuiActionsIndx_Enum GuiActionIndx; + typedef GuiActions::GuiActionsType_Enum GuiActionType; + typedef GuiActions::GuiActionsData_Enum GuiActionData; + typedef GuiActions::GuiActionsIndx_Enum GuiActionIndx; + typedef GuiActions::GuiAlarmPriority_Enum GuiAlarmPriority; + typedef GuiActions::GuiAlarmID_Enum GuiAlarmID; + void registerTypes(); void registerQmlTypes(); Index: sources/gui/guiview.cpp =================================================================== diff -u -r5963f00ffd2c557d3ae06a5deea05032a3a3bd68 -rfeb3423b373dc2a2c4267ef9fcb4d924d738423d --- sources/gui/guiview.cpp (.../guiview.cpp) (revision 5963f00ffd2c557d3ae06a5deea05032a3a3bd68) +++ sources/gui/guiview.cpp (.../guiview.cpp) (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -93,3 +93,22 @@ { emit didExportLog(); } + +QString GuiView::alarmPriorityName(GuiAlarmPriority vEnum) +{ + // 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)); + return mo->enumerator(enumIdx).valueToKey(vEnum); +} +QString GuiView::alarmIDName(GuiAlarmID vEnum) +{ + // 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)); + return mo->enumerator(enumIdx).valueToKey(vEnum); +} Index: sources/gui/guiview.h =================================================================== diff -u -r5963f00ffd2c557d3ae06a5deea05032a3a3bd68 -rfeb3423b373dc2a2c4267ef9fcb4d924d738423d --- sources/gui/guiview.h (.../guiview.h) (revision 5963f00ffd2c557d3ae06a5deea05032a3a3bd68) +++ sources/gui/guiview.h (.../guiview.h) (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -47,6 +47,9 @@ void doUSBDriveUmount(); void doExportLog (); + QString alarmPriorityName (GuiAlarmPriority vEnum); + QString alarmIDName (GuiAlarmID vEnum); + signals: void didActionReceive (GuiActionType vAction, const QVariantList &vData); // UI <= HD/DG void didActionTransmit(GuiActionType vAction, const QVariantList &vData); // UI => HD/DG Index: sources/gui/qml/main.qml =================================================================== diff -u -rfee7fabf49befb065c89248c19e15efc9ca194e4 -rfeb3423b373dc2a2c4267ef9fcb4d924d738423d --- sources/gui/qml/main.qml (.../main.qml) (revision fee7fabf49befb065c89248c19e15efc9ca194e4) +++ sources/gui/qml/main.qml (.../main.qml) (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -37,6 +37,7 @@ GuiView { id: _GuiView onDidActionReceive: { + //console.debug(vData) switch(vAction) { case GuiActions.PowerOff: if (vData[GuiActions.PowerOff_ShowHide] === GuiActions.Command) Index: sources/gui/qml/pages/TreatmentStart.qml =================================================================== diff -u -r188d7611230946fc5fde4e3e837a09202dd93eea -rfeb3423b373dc2a2c4267ef9fcb4d924d738423d --- sources/gui/qml/pages/TreatmentStart.qml (.../TreatmentStart.qml) (revision 188d7611230946fc5fde4e3e837a09202dd93eea) +++ sources/gui/qml/pages/TreatmentStart.qml (.../TreatmentStart.qml) (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -33,91 +33,314 @@ onPressed: backPressed() } - Column { - spacing: Variables.columnSpacing - anchors.centerIn: parent - TitleText { id: _titleText - width: parent.width - text: qsTr("Start Treatment Placeholder") + //Column { + // spacing: Variables.columnSpacing + // anchors.centerIn: parent + // TitleText { id: _titleText + // width: parent.width + // text: qsTr("Start Treatment Placeholder") + // } + //} + + Column { id: _BloodFlowColumn + width: 150 + spacing: 20 + topPadding: 100 + leftPadding: 10 + Text { + id: _BloodFlow_Title + text: qsTr(" Blood ") + width: _BloodFlowColumn.width + horizontalAlignment: Text.AlignHCenter + color: Colors.textMain + font.pixelSize: Fonts.fontPixelTitle + font.underline: true } + Text { + id: _BloodFlow_S32 + text: qsTr("") + width: _BloodFlowColumn.width + horizontalAlignment: Text.AlignRight + color: Colors.textMain + font.pixelSize: Fonts.fontPixelTitle + } + Text { + id: _BloodFlow_F32_1 + text: qsTr("") + width: _BloodFlowColumn.width + horizontalAlignment: Text.AlignRight + color: Colors.textMain + font.pixelSize: Fonts.fontPixelTitle + } + Text { + id: _BloodFlow_F32_2 + text: qsTr("") + width: _BloodFlowColumn.width + horizontalAlignment: Text.AlignRight + color: Colors.textMain + font.pixelSize: Fonts.fontPixelTitle + } + Text { + id: _BloodFlow_F32_3 + text: qsTr("") + width: _BloodFlowColumn.width + horizontalAlignment: Text.AlignRight + color: Colors.textMain + font.pixelSize: Fonts.fontPixelTitle + } + Text { + id: _BloodFlow_F32_4 + text: qsTr("") + width: _BloodFlowColumn.width + horizontalAlignment: Text.AlignRight + color: Colors.textMain + font.pixelSize: Fonts.fontPixelTitle + } + Text { + id: _BloodFlow_F32_5 + text: qsTr("") + width: _BloodFlowColumn.width + horizontalAlignment: Text.AlignRight + color: Colors.textMain + font.pixelSize: Fonts.fontPixelTitle + } + Text { + id: _BloodFlow_F32_6 + text: qsTr("") + width: _BloodFlowColumn.width + horizontalAlignment: Text.AlignRight + color: Colors.textMain + font.pixelSize: Fonts.fontPixelTitle + } } - Column { + Column { id: _DialysateFlowColumn + width: 150 spacing: 20 topPadding: 100 - leftPadding: 10 + leftPadding: 180 Text { - id: _S32 + id: _DialysateFlow_Title + text: qsTr(" Dialysate ") + width: _DialysateFlowColumn.width + horizontalAlignment: Text.AlignLeft + color: Colors.textMain + font.pixelSize: Fonts.fontPixelTitle + font.underline: true + } + Text { + id: _DialysateFlow_S32 text: qsTr("") - width: 250 + width: _DialysateFlowColumn.width horizontalAlignment: Text.AlignRight color: Colors.textMain font.pixelSize: Fonts.fontPixelTitle } Text { - id: _F32_1 + id: _DialysateFlow_F32_1 text: qsTr("") - width: 250 + width: _DialysateFlowColumn.width horizontalAlignment: Text.AlignRight color: Colors.textMain font.pixelSize: Fonts.fontPixelTitle } Text { - id: _F32_2 + id: _DialysateFlow_F32_2 text: qsTr("") - width: 250 + width: _DialysateFlowColumn.width horizontalAlignment: Text.AlignRight color: Colors.textMain font.pixelSize: Fonts.fontPixelTitle } Text { - id: _F32_3 + id: _DialysateFlow_F32_3 text: qsTr("") - width: 250 + width: _DialysateFlowColumn.width horizontalAlignment: Text.AlignRight color: Colors.textMain font.pixelSize: Fonts.fontPixelTitle } Text { - id: _F32_4 + id: _DialysateFlow_F32_4 text: qsTr("") - width: 250 + width: _DialysateFlowColumn.width horizontalAlignment: Text.AlignRight color: Colors.textMain font.pixelSize: Fonts.fontPixelTitle } Text { - id: _F32_5 + id: _DialysateFlow_F32_5 text: qsTr("") - width: 250 + width: _DialysateFlowColumn.width horizontalAlignment: Text.AlignRight color: Colors.textMain font.pixelSize: Fonts.fontPixelTitle } Text { - id: _F32_6 + id: _DialysateFlow_F32_6 text: qsTr("") - width: 250 + width: _DialysateFlowColumn.width horizontalAlignment: Text.AlignRight color: Colors.textMain font.pixelSize: Fonts.fontPixelTitle } } + + Column { id: _AlarmStatusColumn + width: 270 + spacing: 5 + topPadding: 100 + leftPadding: 400 + Text { + id: _AlarmStatus_Title + text: qsTr(" Alarm Status ") + width: _AlarmStatusColumn.width + horizontalAlignment: Text.AlignLeft + color: Colors.textMain + font.pixelSize: Fonts.fontPixelTitle + font.underline: true + } + Text { + id: _AlarmStatus_Priority + text: qsTr("") + width: _AlarmStatusColumn.width + horizontalAlignment: Text.AlignLeft + color: Colors.textMain + font.pixelSize: Fonts.fontPixelButton + } + Text { + id: _AlarmStatus_ID + text: qsTr("") + width: _AlarmStatusColumn.width + horizontalAlignment: Text.AlignLeft + color: Colors.textMain + font.pixelSize: Fonts.fontPixelButton + } + Text { + id: _AlarmStatus_EsclateIn + text: qsTr("") + width: _AlarmStatusColumn.width + horizontalAlignment: Text.AlignLeft + color: Colors.textMain + font.pixelSize: Fonts.fontPixelButton + } + Text { id: _AlarmStatus_MuteTimeout + text: qsTr("") + width: _AlarmStatusColumn.width + horizontalAlignment: Text.AlignLeft + color: Colors.textMain + font.pixelSize: Fonts.fontPixelButton + } + Text { id: _AlarmStatus_systemFault + text: qsTr("") + width: _AlarmStatusColumn.width + horizontalAlignment: Text.AlignLeft + color: Colors.textMain + font.pixelSize: Fonts.fontPixelButton + } + Text { id: _AlarmStatus_stop + text: qsTr("") + width: _AlarmStatusColumn.width + horizontalAlignment: Text.AlignLeft + color: Colors.textMain + font.pixelSize: Fonts.fontPixelButton + } + Text { id: _AlarmStatus_noClear + text: qsTr("") + width: _AlarmStatusColumn.width + horizontalAlignment: Text.AlignLeft + color: Colors.textMain + font.pixelSize: Fonts.fontPixelButton + } + Text { id: _AlarmStatus_noResume + text: qsTr("") + width: _AlarmStatusColumn.width + horizontalAlignment: Text.AlignLeft + color: Colors.textMain + font.pixelSize: Fonts.fontPixelButton + } + Text { id: _AlarmStatus_noRinseback + text: qsTr("") + width: _AlarmStatusColumn.width + horizontalAlignment: Text.AlignLeft + color: Colors.textMain + font.pixelSize: Fonts.fontPixelButton + } + Text { id: _AlarmStatus_noEndTreatment + text: qsTr("") + width: _AlarmStatusColumn.width + horizontalAlignment: Text.AlignLeft + color: Colors.textMain + font.pixelSize: Fonts.fontPixelButton + } + Text { id: _AlarmStatus_noNewTreatment + text: qsTr("") + width: _AlarmStatusColumn.width + horizontalAlignment: Text.AlignLeft + color: Colors.textMain + font.pixelSize: Fonts.fontPixelButton + } + Text { id: _AlarmStatus_bypassDialyzer + text: qsTr("") + width: _AlarmStatusColumn.width + horizontalAlignment: Text.AlignLeft + color: Colors.textMain + font.pixelSize: Fonts.fontPixelButton + } + Text { id: _AlarmStatus_alarmsToEscalate + text: qsTr("") + width: _AlarmStatusColumn.width + horizontalAlignment: Text.AlignLeft + color: Colors.textMain + font.pixelSize: Fonts.fontPixelButton + } + Text { id: _AlarmStatus_alarmsSilenced + text: qsTr("") + width: _AlarmStatusColumn.width + horizontalAlignment: Text.AlignLeft + color: Colors.textMain + font.pixelSize: Fonts.fontPixelButton + } + } Connections { target: _GuiView onDidActionReceive: { if ( ! visible ) return; switch(vAction) { case GuiActions.BloodFlow: - //console.debug(vData) - _S32 .text = vData[GuiActions.BloodFlow_FlowSetPoint ]; - _F32_1.text = vData[GuiActions.BloodFlow_MeasuredFlow ].toFixed(2); - _F32_2.text = vData[GuiActions.BloodFlow_RotorSpeed ].toFixed(2); - _F32_3.text = vData[GuiActions.BloodFlow_MotorSpeed ].toFixed(2); - _F32_4.text = vData[GuiActions.BloodFlow_MotorCtlSpeed ].toFixed(2); - _F32_5.text = vData[GuiActions.BloodFlow_MotorCtlCurrent].toFixed(2); - _F32_6.text = vData[GuiActions.BloodFlow_PWMDtCycle ].toFixed(2) + "%"; + _BloodFlow_S32 .text = vData[GuiActions.BloodFlow_FlowSetPoint ]; + _BloodFlow_F32_1.text = vData[GuiActions.BloodFlow_MeasuredFlow ].toFixed(2); + _BloodFlow_F32_2.text = vData[GuiActions.BloodFlow_RotorSpeed ].toFixed(2); + _BloodFlow_F32_3.text = vData[GuiActions.BloodFlow_MotorSpeed ].toFixed(2); + _BloodFlow_F32_4.text = vData[GuiActions.BloodFlow_MotorCtlSpeed ].toFixed(2); + _BloodFlow_F32_5.text = vData[GuiActions.BloodFlow_MotorCtlCurrent].toFixed(2); + _BloodFlow_F32_6.text = vData[GuiActions.BloodFlow_PWMDtCycle ].toFixed(2) + "%"; break; + case GuiActions.BloodFlow: + _DialysateFlow_S32 .text = vData[GuiActions.DialysateFlow_FlowSetPoint ]; + _DialysateFlow_F32_1.text = vData[GuiActions.DialysateFlow_MeasuredFlow ].toFixed(2); + _DialysateFlow_F32_2.text = vData[GuiActions.DialysateFlow_RotorSpeed ].toFixed(2); + _DialysateFlow_F32_3.text = vData[GuiActions.DialysateFlow_MotorSpeed ].toFixed(2); + _DialysateFlow_F32_4.text = vData[GuiActions.DialysateFlow_MotorCtlSpeed ].toFixed(2); + _DialysateFlow_F32_5.text = vData[GuiActions.DialysateFlow_MotorCtlCurrent].toFixed(2); + _DialysateFlow_F32_6.text = vData[GuiActions.DialysateFlow_PWMDtCycle ].toFixed(2) + "%"; + break; + case GuiActions.AlarmStatus: + _AlarmStatus_Priority .text = _GuiView.alarmPriorityName(vData[GuiActions.AlarmStatus_Priority ]) + _AlarmStatus_ID .text = _GuiView.alarmIDName (vData[GuiActions.AlarmStatus_AlarmID ]) + _AlarmStatus_EsclateIn .text = "Escalates In : " + vData[GuiActions.AlarmStatus_EscalateIn ] + _AlarmStatus_MuteTimeout .text = "MuteTimeout : " + vData[GuiActions.AlarmStatus_MuteTimeout ] + _AlarmStatus_systemFault .text = (vData[GuiActions.AlarmStatus_Flag_systemFault ] ? "1" : "0" ) + " : systemFault " + _AlarmStatus_stop .text = (vData[GuiActions.AlarmStatus_Flag_stop ] ? "1" : "0" ) + " : stop " + _AlarmStatus_noClear .text = (vData[GuiActions.AlarmStatus_Flag_noClear ] ? "1" : "0" ) + " : noClear " + _AlarmStatus_noResume .text = (vData[GuiActions.AlarmStatus_Flag_noResume ] ? "1" : "0" ) + " : noResume " + _AlarmStatus_noRinseback .text = (vData[GuiActions.AlarmStatus_Flag_noRinseback ] ? "1" : "0" ) + " : noRinseback " + _AlarmStatus_noEndTreatment .text = (vData[GuiActions.AlarmStatus_Flag_noEndTreatment ] ? "1" : "0" ) + " : noEndTreatment " + _AlarmStatus_noNewTreatment .text = (vData[GuiActions.AlarmStatus_Flag_noNewTreatment ] ? "1" : "0" ) + " : noNewTreatment " + _AlarmStatus_bypassDialyzer .text = (vData[GuiActions.AlarmStatus_Flag_bypassDialyzer ] ? "1" : "0" ) + " : bypassDialyzer " + _AlarmStatus_alarmsToEscalate.text = (vData[GuiActions.AlarmStatus_Flag_alarmsToEscalate] ? "1" : "0" ) + " : alarmsToEscalate " + _AlarmStatus_alarmsSilenced .text = (vData[GuiActions.AlarmStatus_Flag_alarmsSilenced ] ? "1" : "0" ) + " : alarmsSilenced " + break; } } } Index: sources/maintimer.cpp =================================================================== diff -u -rfee7fabf49befb065c89248c19e15efc9ca194e4 -rfeb3423b373dc2a2c4267ef9fcb4d924d738423d --- sources/maintimer.cpp (.../maintimer.cpp) (revision fee7fabf49befb065c89248c19e15efc9ca194e4) +++ sources/maintimer.cpp (.../maintimer.cpp) (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -14,9 +14,9 @@ #include "maintimer.h" //Qt -#include //Project +#include "logger.h" // Singleton SINGLETON_INIT(MainTimer) @@ -25,27 +25,18 @@ * \brief MainTimer Constructor * \param parent */ -MainTimer::MainTimer(QObject *parent) : QObject(parent) -{ - _timer = new QTimer(this); -} +MainTimer::MainTimer(QObject *parent) : QObject(parent) { } -void MainTimer::init() +bool MainTimer::init() { - connect(_timer, SIGNAL(timeout()), this, SLOT( onTimeout())); - connect(_timer, SIGNAL(timeout()), this, SIGNAL(didTimeout())); - _timer->start(_timeout); + startTimer(_interval); + LOG_EVENT(QObject::tr("Main Timer Initialized")); + return true; } -void MainTimer::quit() -{ - _timer->stop(); - delete _timer; - _timer = nullptr; -} +void MainTimer::quit() { } -void MainTimer::onTimeout() +void MainTimer::timerEvent(QTimerEvent *) { - // no op yet + emit didTimeout(); } - Index: sources/maintimer.h =================================================================== diff -u -rfee7fabf49befb065c89248c19e15efc9ca194e4 -rfeb3423b373dc2a2c4267ef9fcb4d924d738423d --- sources/maintimer.h (.../maintimer.h) (revision fee7fabf49befb065c89248c19e15efc9ca194e4) +++ sources/maintimer.h (.../maintimer.h) (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -22,9 +22,6 @@ // Define #define _MainTimer MainTimer::I() -// Forward declaration -class QTimer; - /*! * \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. @@ -33,17 +30,19 @@ { Q_OBJECT - static const int _timeout = 1000; //ms - QTimer *_timer = nullptr; + static const int _interval = 1000; //ms +// Singleton SINGLETON_DECL(MainTimer) public: - void init(); + bool init(); void quit(); +private: + signals: void didTimeout(); -private slots: - void onTimeout(); +protected: + void timerEvent(QTimerEvent *) override; }; Index: sources/storage/filehandler.cpp =================================================================== diff -u -r5963f00ffd2c557d3ae06a5deea05032a3a3bd68 -rfeb3423b373dc2a2c4267ef9fcb4d924d738423d --- sources/storage/filehandler.cpp (.../filehandler.cpp) (revision 5963f00ffd2c557d3ae06a5deea05032a3a3bd68) +++ sources/storage/filehandler.cpp (.../filehandler.cpp) (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -13,18 +13,15 @@ */ #include "filehandler.h" -// Linux -#include -#include -//#include - //Qt #include #include #include // Project -#include "maintimer.h" +#include "storageglobals.h" +#include "usbwatcher.h" +#include "applicationcontroller.h" // namespace using namespace Storage; @@ -34,16 +31,6 @@ FileHandler::FileHandler(QObject *parent) : QObject(parent) { } -bool FileHandler::umounted() const -{ - return _umounted; -} - -void FileHandler::umounted(bool vUmounted) -{ - _umounted = vUmounted; -} - bool FileHandler::init() { initConnections(); @@ -56,25 +43,10 @@ void FileHandler::initConnections() { - connect(_MainTimer , SIGNAL( didTimeout()), - this , SLOT(onMainTimerTimeout())); - //connect(&_processCopyFolder, SIGNAL(finished(int)), - // this , SLOT(copyFolder)); + connect(_ApplicationController, SIGNAL(didExportLog()), + this , SLOT( onExportLog())); } -bool FileHandler::usbSeek(QString &vDevice) { - QString device = ""; - for (char a = 'a'; a <= 'z'; a++) { - device = QString("/dev/sd%1%2").arg(a).arg('1'); - if (QFileInfo::exists(device)) { - vDevice = device; - return true; // application is deciding on the first existing drive - } - } - vDevice = device; - return false; -} - bool FileHandler::write(const QString &vFileName, const QString &vContent, bool vAppend) { QFile file(vFileName); @@ -103,22 +75,8 @@ return true; } -void FileHandler::doUSBDriveMount() -{ - QString device = ""; - if (usbSeek(device)) { - if (! umounted()) { - usbMount(device); - } else { - usbUmount(_usbMount); // release - qDebug() << tr("USB drive umounted"); - } - } else { - usbRemove(); - } -} -bool FileHandler::doWrite(const QString &vFileName, const QString &vContent, bool vAppend) +bool FileHandler::onWrite(const QString &vFileName, const QString &vContent, bool vAppend) { bool ok = write(vFileName, vContent, vAppend); if (ok) { @@ -127,7 +85,7 @@ return ok; } -bool FileHandler::doRead(const QString &vFileName) +bool FileHandler::onRead(const QString &vFileName) { QString mContent; bool ok = read(vFileName, mContent); @@ -137,70 +95,14 @@ return ok; } -bool FileHandler::doExportFolder(const QString &vFolder) +bool FileHandler::onExportLog() { - if ( _mounted ) { - QString cp = "cp"; - QStringList arguments; - arguments << "-r" << vFolder << _usbMount; - _processCopyFolder.start(cp, arguments); - return true; - } - return false; -} + QString vSource = Storage::Log_Base_Path_Name_Location; + QString vDestination = Storage::USB_Mount_Point; -void FileHandler::usbError(const QString &vDevice) -{ - switch (errno) { - case EBUSY: - qDebug() << tr("%1 - Device or resource busy (%2)").arg(errno).arg(vDevice); - _mounted = true; - break; - default: - qDebug() << tr("%1 - %2 (%3 , %4)").arg(errno).arg(strerror(errno)).arg(vDevice).arg(_usbMount); - break; - } + QString cp = "cp"; + QStringList arguments; + arguments << "-r" << vSource << vDestination; + _processCopyFolder.start(cp, arguments); + return true; } - -bool FileHandler::usbMount(const QString &vDevice) -{ - bool ok; - _usbDrive = vDevice.toLatin1().constData(); - ok = mount(_usbDrive, _usbMount, _usbfsys, 0, "") == 0; - if (ok) { - _mounted = true; - qDebug() << tr("USB flash drive %1 has been mounted on %2").arg(vDevice).arg(_usbMount); - emit didUSBDriveMount(); - } else { - usbError(vDevice); - } - return ok; -} - -bool FileHandler::usbUmount(const QString &vDevice) -{ - bool ok; - ok = umount(vDevice.toLatin1().constData()) == 0; - if (ok) { - _mounted = false; - emit didUSBDriveUmount(); - } else { - // the error is irrelevant, commented out for now - //usbError(vDevice); - } - return ok; -} - -void FileHandler::usbRemove() -{ - usbUmount(_usbMount); - umounted(false); - emit didUSBDriveRemove(); - qDebug() << tr("USB drive removed"); -} - -void FileHandler::onMainTimerTimeout() -{ - doUSBDriveMount(); -} - Index: sources/storage/filehandler.h =================================================================== diff -u -r5963f00ffd2c557d3ae06a5deea05032a3a3bd68 -rfeb3423b373dc2a2c4267ef9fcb4d924d738423d --- sources/storage/filehandler.h (.../filehandler.h) (revision 5963f00ffd2c557d3ae06a5deea05032a3a3bd68) +++ sources/storage/filehandler.h (.../filehandler.h) (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -29,54 +29,30 @@ { Q_OBJECT - const char *_usbMount = "/media/usb/"; - const char *_usbfsys = "vfat"; - bool _mounted = false; - bool _umounted = false; - const char *_usbDrive = ""; - QProcess _processCopyFolder; - // Singleton - SINGLETON_DECL(FileHandler) +// Singleton +SINGLETON_DECL(FileHandler) public: bool init(); void quit(); - bool umounted( ) const; - void umounted(bool vUmounted); - private: void initConnections(); - bool usbSeek(QString &vDevice); - bool write(const QString &vFileName, const QString &vContent, bool vAppend); bool read (const QString &vFileName, QString &vContent); signals: - void didUSBDriveMount (); - void didUSBDriveUmount(); - void didUSBDriveRemove(); - void didWrite(const QString &vFileName); void didRead (const QString &vFileName, const QString &vContent); -public slots: - void doUSBDriveMount (); - - bool doWrite(const QString &vFileName, const QString &vContent, bool vAppend = true); - bool doRead (const QString &vFileName); - - bool doExportFolder(const QString &vFolder); - +public slots: + bool onWrite (const QString &vFileName, const QString &vContent, bool vAppend = true); private slots: - bool usbMount (const QString &vDevice); - bool usbUmount(const QString &vDevice); - void usbRemove(); - void usbError (const QString &vDevice); + bool onRead (const QString &vFileName); - void onMainTimerTimeout(); + bool onExportLog(); }; } Index: sources/storage/logger.cpp =================================================================== diff -u -r5963f00ffd2c557d3ae06a5deea05032a3a3bd68 -rfeb3423b373dc2a2c4267ef9fcb4d924d738423d --- sources/storage/logger.cpp (.../logger.cpp) (revision 5963f00ffd2c557d3ae06a5deea05032a3a3bd68) +++ sources/storage/logger.cpp (.../logger.cpp) (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -18,8 +18,11 @@ #include #include #include +#include +#include // Project +#include "storageglobals.h" #include "filehandler.h" using namespace Storage; @@ -33,6 +36,7 @@ bool Logger::init() { checkLogPath(); + qRegisterMetaType("LogType"); initConnections(); return true; } @@ -54,20 +58,20 @@ _dir.setPath(qApp->applicationDirPath()); qDebug() << "WARNING :" << tr("Application Dir Path used for events logging (%1)").arg(_dir.path()); } else { - _dir.setPath(_logBasePathName); + _dir.setPath(Log_Base_Path_Name); } } bool Logger::setLogPath() { bool ok = true; - ok = ok && setLogPath(eLogDatum); - ok = ok && setLogPath(eLogEvent); - ok = ok && setLogPath(eLogError); + ok = ok && setLogPath(LogType::eLogDatum); + ok = ok && setLogPath(LogType::eLogEvent); + ok = ok && setLogPath(LogType::eLogError); return ok; } -bool Logger::setLogPath(Logger::LogType_Enum vLogType) +bool Logger::setLogPath(LogType vLogType) { _logPathNames[vLogType] = _dir.path() + "/" + _logBasePathNames[vLogType]; if ( ! _dir.exists(_logBasePathNames[vLogType]) ) { @@ -82,7 +86,9 @@ return true; } -bool Logger::log(const QString &vContent, LogType_Enum vLogType) { +bool Logger::log(const QString &vContent, LogType vLogType) { + //qDebug() << QThread::currentThread()->objectName(); + QString date = QDate::currentDate().toString(_dateFormat); QString mContent; @@ -97,19 +103,20 @@ mContent += _logPrefix[vLogType]; mContent += _prefixSeparator; mContent += QTime::currentTime().toString(_timeFormat); - mContent += _timeSeparator + vContent + "\r\n"; - QString fileName = date + _dateSeparator + _logFileName; - _FileHandler->doWrite(_logPathNames[vLogType] + fileName, mContent); - qDebug() << mContent; + mContent += _timeSeparator + vContent; + QString fileName = date + _dateSeparator + Log_File_Name; + _FileHandler->onWrite(_logPathNames[vLogType] + fileName, mContent + "\r\n"); + qDebug().noquote() << mContent; + return true; } -void Logger::doLog(const QString &vContent, LogType_Enum vLogType) +void Logger::doLog(const QString &vContent, LogType vLogType) { - emit didLog(log(vContent, vLogType)); -} + // // QMetaObject::invokeMethod(this, "log", Qt::AutoConnection, Q_ARG(QString, vContent) , Q_ARG(LogType, vLogType)); -void Logger::doExportLog() -{ - _FileHandler->doExportFolder(_logBasePathNameExport); + // /* QFuture future = */QtConcurrent::run(this,&Logger::log, vContent, vLogType); + // // qDebug() << future.result(); + + log(vContent, vLogType); } Index: sources/storage/logger.h =================================================================== diff -u -r5963f00ffd2c557d3ae06a5deea05032a3a3bd68 -rfeb3423b373dc2a2c4267ef9fcb4d924d738423d --- sources/storage/logger.h (.../logger.h) (revision 5963f00ffd2c557d3ae06a5deea05032a3a3bd68) +++ sources/storage/logger.h (.../logger.h) (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -20,11 +20,12 @@ // Project #include "main.h" + // Define -#define _Logger Storage::Logger::I() -#define LOG_DATUM(vCONTENT) _Logger->doLog(vCONTENT, Storage::Logger::eLogDatum) -#define LOG_EVENT(vCONTENT) _Logger->doLog(vCONTENT, Storage::Logger::eLogEvent) -#define LOG_ERROR(vCONTENT) _Logger->doLog(vCONTENT, Storage::Logger::eLogError) +#define _Logger Storage::Logger::I() +#define LOG_DATUM(vCONTENT) Storage::Logger::I()->doLog(vCONTENT, Storage::Logger::LogType::eLogDatum) +#define LOG_EVENT(vCONTENT) Storage::Logger::I()->doLog(vCONTENT, Storage::Logger::LogType::eLogEvent) +#define LOG_ERROR(vCONTENT) Storage::Logger::I()->doLog(vCONTENT, Storage::Logger::LogType::eLogError) namespace Storage { @@ -33,42 +34,37 @@ Q_OBJECT public: - enum LogType_Enum { + enum LogType { eLogDatum, eLogEvent, eLogError, }; private: QDir _dir; - QHash _logPathNames; - QHash _logBasePathNames { + QHash _logPathNames; + QHash _logBasePathNames { { eLogDatum, "log/event/" }, // "log/datum/" { eLogEvent, "log/event/" }, { eLogError, "log/error/" }, }; - QHash _logPrefix { + QHash _logPrefix { { eLogDatum, "Datum" }, { eLogEvent, "Event" }, { eLogError, "Error" }, }; - const char *_logBasePathName = "/media/sd-card/"; - const char *_logBasePathNameExport = "/media/sd-card/log/"; - - const char *_logFileName = "denali.log"; - const char *_dateFormat = "yyyy_MM_dd"; const char *_timeFormat = "HH:mm:ss"; - const char *_prefixSeparator = ": "; - const char *_dateSeparator = "_"; - const char *_timeSeparator = " , "; + const char *_prefixSeparator = ": " ; + const char *_dateSeparator = "_" ; + const char *_timeSeparator = " , "; - // Singleton - SINGLETON_DECL(Logger) +// Singleton +SINGLETON_DECL(Logger) public: bool init(); @@ -80,16 +76,16 @@ void checkLogPath (); void setLogBasePath(bool vUseApplicationDirPath = false); bool setLogPath (); - bool setLogPath (LogType_Enum vLogType); + bool setLogPath (LogType vLogType); - bool log(const QString &vContent, LogType_Enum vLogType); +private slots: + bool log(const QString &vContent, LogType vLogType); signals: void didLog(bool ok); public slots: - void doLog(const QString &vContent, LogType_Enum vLogType); - void doExportLog(); + void doLog(const QString &vContent, LogType vLogType); }; } Index: sources/storage/storageglobals.cpp =================================================================== diff -u --- sources/storage/storageglobals.cpp (revision 0) +++ sources/storage/storageglobals.cpp (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -0,0 +1,24 @@ +/*! + * + * 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 + * date 1/2/2020 + * author Behrouz NematiPour + * + */ + +namespace Storage { + // USB + const char *USB_Mount_Point = "/media/usb/"; + const char *USB_File_System = "vfat"; + + // Log + const char *Log_Base_Path_Name = "/media/sd-card/"; + const char *Log_Base_Path_Name_Location = "/media/sd-card/log/"; + const char *Log_File_Name = "denali.log"; +} Index: sources/storage/storageglobals.h =================================================================== diff -u --- sources/storage/storageglobals.h (revision 0) +++ sources/storage/storageglobals.h (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -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.h + * date 1/2/2020 + * author Behrouz NematiPour + * + */ +#pragma once + +namespace Storage +{ + // USB + extern const char *USB_Mount_Point; + extern const char *USB_File_System; + + // Log + extern const char *Log_Base_Path_Name ; + extern const char *Log_Base_Path_Name_Location; + extern const char *Log_File_Name ; +} Index: sources/storage/usbwatcher.cpp =================================================================== diff -u --- sources/storage/usbwatcher.cpp (revision 0) +++ sources/storage/usbwatcher.cpp (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -0,0 +1,161 @@ +/*! + * + * 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 usbwatcher.cpp + * date 12/31/2019 + * author Behrouz NematiPour + * + */ +#include "usbwatcher.h" + +// Linux +#include +#include + +// Qt +#include + +// Project +#include "storageglobals.h" +#include "logger.h" +#include "applicationcontroller.h" + +// namespace +using namespace Storage; + +// Singleton +SINGLETON_INIT(USBWatcher) + +USBWatcher::USBWatcher(QObject *parent) : QObject(parent) +{ + startTimer(_checkInterval); +} + +bool USBWatcher::init() +{ + initConnections(); + return true; +} + +void USBWatcher::quit() +{ + +} + +void USBWatcher::initConnections() +{ + connect(_ApplicationController, SIGNAL(didUSBDriveUmount()), this, SLOT(onUSBDriveUmount())); +} + +bool USBWatcher::isMounted() const +{ + return _mounted; +} + +bool USBWatcher::isUmounted() const +{ + return _umounted; +} + +bool USBWatcher::usbSeek(QString &vDevice) { + QString device = ""; + for (char a = 'a'; a <= 'z'; a++) { + device = QString("/dev/sd%1%2").arg(a).arg('1'); + if (QFileInfo::exists(device)) { + vDevice = device; + return true; // application is deciding on the first existing drive + } + } + vDevice = device; + return false; +} + +void USBWatcher::timerEvent(QTimerEvent *) +{ + usbcheck(); +} + +void USBWatcher::usbcheck() +{ + QString device = ""; + if (usbSeek(device)) { + if (! _umounted ) { + usbMount(device); + } else { + usbUmount(USB_Mount_Point); + } + } else { + if ( ! _removed ) { + usbRemove(); + } + } +} + +void USBWatcher::usbError(const QString &vDevice) +{ + QString error; + static QString lastError; + switch (errno) { + case EBUSY: + error = tr("%1 - Device or resource busy (%2)").arg(errno).arg(vDevice); + _mounted = true; + break; + default: + error = tr("%1 - %2 (%3 , %4)").arg(errno).arg(strerror(errno)).arg(vDevice).arg(USB_Mount_Point); + break; + } + if (error != lastError) { + LOG_ERROR(error); + lastError = error; + } +} + +void USBWatcher::onUSBDriveUmount() +{ + _umounted = true; +} + +bool USBWatcher::usbMount(const QString &vDevice) +{ + bool ok; + _usbDrive = vDevice.toLatin1().constData(); + ok = mount(_usbDrive, USB_Mount_Point, USB_File_System, 0, "") == 0; + if (ok) { + _mounted = true; + _removed = false; + LOG_EVENT(tr("USB flash drive %1 has been mounted on %2").arg(vDevice).arg(USB_Mount_Point)); + emit didUSBDriveMount(); + } else { + usbError(vDevice); + } + return ok; +} + +bool USBWatcher::usbUmount(const QString &vDevice) +{ + bool ok; + ok = umount(vDevice.toLatin1().constData()) == 0; + if (ok) { + _mounted = false; + LOG_EVENT(tr("USB drive unmounted")); + emit didUSBDriveUmount(); + } else { + // the error is irrelevant, commented out for now + usbError(vDevice); + } + return ok; +} + +void USBWatcher::usbRemove() +{ + usbUmount(USB_Mount_Point); + _umounted = false; + _removed = true; + LOG_EVENT(tr("USB drive removed")); + emit didUSBDriveRemove(); +} Index: sources/storage/usbwatcher.h =================================================================== diff -u --- sources/storage/usbwatcher.h (revision 0) +++ sources/storage/usbwatcher.h (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -0,0 +1,71 @@ +/*! + * + * 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 usbwatcher.h + * date 12/31/2019 + * author Behrouz NematiPour + * + */ +#pragma once + +// Qt +#include + +// Project +#include "main.h" + +// Define +#define _USBWatcher USBWatcher::I() + +namespace Storage { + +class USBWatcher : public QObject +{ + Q_OBJECT + + bool _mounted = false; + bool _umounted = false; + bool _removed = false; + const char *_usbDrive = ""; + const int _checkInterval = 1000; // in ms + +// Singleton +SINGLETON_DECL(USBWatcher) + +public: + bool init(); + void quit(); + + bool isMounted () const; + bool isUmounted() const; + +protected: + void timerEvent(QTimerEvent *) override; + +private: + void initConnections(); + + bool usbSeek(QString &vDevice); + +signals: + void didUSBDriveMount (); + void didUSBDriveUmount(); + void didUSBDriveRemove(); + +private slots: + void usbcheck (); + + bool usbMount (const QString &vDevice); + bool usbUmount(const QString &vDevice); + void usbRemove(); + void usbError (const QString &vDevice); + + void onUSBDriveUmount(); +}; + +} Index: sources/utility/format.cpp =================================================================== diff -u -r561055268da68e24fe91a1148b76bf1785dae14d -rfeb3423b373dc2a2c4267ef9fcb4d924d738423d --- sources/utility/format.cpp (.../format.cpp) (revision 561055268da68e24fe91a1148b76bf1785dae14d) +++ sources/utility/format.cpp (.../format.cpp) (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -27,11 +27,17 @@ } } -QByteArray Format::toHexString(const QByteArray &vData, char separator) +QByteArray Format::toHexByteArray(const QByteArray &vData, char separator) { return vData.toHex(separator).toUpper(); } +QString Format::toHexString(const QByteArray &vData, char separator) +{ + QString string = toHexByteArray(vData, separator); + return string; +} + QByteArray Format::fromVariant(const QVariant &vData) { QByteArray mData; Index: sources/utility/format.h =================================================================== diff -u -r561055268da68e24fe91a1148b76bf1785dae14d -rfeb3423b373dc2a2c4267ef9fcb4d924d738423d --- sources/utility/format.h (.../format.h) (revision 561055268da68e24fe91a1148b76bf1785dae14d) +++ sources/utility/format.h (.../format.h) (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -23,8 +23,9 @@ { Format(); public: - static QString toHexString(quint16 vValue, bool vWith0x = true, quint8 vLen = 4); - static QByteArray toHexString(const QByteArray &vData, char separator = '.'); - static QByteArray fromVariant(const QVariant &vData); + static QString toHexString ( quint16 vValue, bool vWith0x = true, quint8 vLen = 4); + static QByteArray toHexByteArray(const QByteArray &vData , char separator = '.'); + static QString toHexString (const QByteArray &vData , char separator = '.'); + static QByteArray fromVariant (const QVariant &vData ); }; Index: sources/utility/types.cpp =================================================================== diff -u -r188d7611230946fc5fde4e3e837a09202dd93eea -rfeb3423b373dc2a2c4267ef9fcb4d924d738423d --- sources/utility/types.cpp (.../types.cpp) (revision 188d7611230946fc5fde4e3e837a09202dd93eea) +++ sources/utility/types.cpp (.../types.cpp) (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -14,17 +14,21 @@ #include "types.h" // Qt -#include // Project -namespace types { - -bool floatCompare(float f1, float f2) { +bool Types::floatCompare(float f1, float f2) { static constexpr auto epsilon = 1.0e-05f; if (qAbs(f1 - f2) <= epsilon) return true; return qAbs(f1 - f2) <= epsilon * qMax(qAbs(f1), qAbs(f2)); } +bool Types::getBits(const QByteArray &vData, int &vIndex, QBitArray &vFlags, int vLen) { + vFlags.clear(); + QByteArray data = vData.mid(vIndex, vLen); + if (data.length() * 8 < vLen ) + return false; + vFlags = QBitArray::fromBits(data, vLen); + return true; } Index: sources/utility/types.h =================================================================== diff -u -r188d7611230946fc5fde4e3e837a09202dd93eea -rfeb3423b373dc2a2c4267ef9fcb4d924d738423d --- sources/utility/types.h (.../types.h) (revision 188d7611230946fc5fde4e3e837a09202dd93eea) +++ sources/utility/types.h (.../types.h) (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -14,11 +14,27 @@ #pragma once // Qt -#include - +#include +#include +#include // Project +#include "format.h" -namespace types { +class Types { +public: + + class Flags : public QBitArray { + public: + QString toString() { + QString tmp; + for (int i = 0; i < count(); i++) { + if (i % 4 == 0 && i != 0) + tmp += ' '; + tmp += at(i) ? '1' : '0'; + } + return tmp; + } + }; /*! * \brief The F32 union * \details This is the union which will be used to extract the bytes of a float type value @@ -30,14 +46,35 @@ }; /*! + * \brief The U08 union + * \details This is the union which will be used to extract the byte of an unsigned char type value + * 1 byte + */ +union U08 { + quint8 value = 0; + quint8 bytes[sizeof(quint8)]; +}; + +/*! + * \brief The U16 union + * \details This is the union which will be used to extract the bytes of an unsigned char type value + * 2 bytes + */ +union U16 { + quint16 value = 0; + quint8 bytes[sizeof(quint16)]; +}; + +/*! * \brief The U32 union * \details This is the union which will be used to extract the bytes of an unsigned int type value * 4 bytes */ union U32 { quint32 value = 0; - quint8 bytes[sizeof(quint32)]; + quint8 bytes[sizeof(quint32)]; }; + /*! * \brief The S32 union * \details This is the union which will be used to extract the bytes of an signed int type value @@ -48,6 +85,30 @@ quint8 bytes[sizeof(qint32)]; }; -extern bool floatCompare(float f1, float f2); +static bool floatCompare(float f1, float f2); +template < typename T > +static bool getValue(const QByteArray &vData, int &vIndex, T &vValue); +static bool getBits (const QByteArray &vData, int &vIndex, QBitArray &vFlags, int vLen); + +}; + +template < typename T > +bool Types::getValue(const QByteArray &vData, int &vIndex, T &vValue) { + int end = vIndex + sizeof(T); + if (vData.length() < end) { + qDebug() << QString("Not enough data from position %1 to the length of %2 to get data of type '%3' in buffer %4") + .arg(vIndex) + .arg(sizeof(T)) + .arg(typeid(T).name()) + .arg(Format::toHexString(vData)) + ; + } + int i = 0; + while (vIndex < end) { + vValue.bytes[i] = vData[vIndex]; + i++; + vIndex++; + } + return true; } Index: unittests/tst_canbus.cpp =================================================================== diff -u -r188d7611230946fc5fde4e3e837a09202dd93eea -rfeb3423b373dc2a2c4267ef9fcb4d924d738423d --- unittests/tst_canbus.cpp (.../tst_canbus.cpp) (revision 188d7611230946fc5fde4e3e837a09202dd93eea) +++ unittests/tst_canbus.cpp (.../tst_canbus.cpp) (revision feb3423b373dc2a2c4267ef9fcb4d924d738423d) @@ -76,7 +76,7 @@ if (! strcmp(vData[i].typeName(), "float")) { float f1 = vData[i].toFloat(); float f2 = _data[i].toFloat(); - QVERIFY(types::floatCompare(f1, f2)); + QVERIFY(Types::floatCompare(f1, f2)); } else { QVERIFY(vData[i] == _data[i]); }