/*! * * 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 CloudSyncController.cpp * \author (last) Behrouz NematiPour * \author (original) Behrouz NematiPour * \date (last) 13-Oct-2021 * \date (original) 13-Oct-2021 * */ #include "CloudSyncController.h" // Qt #include // Project #include "MainTimer.h" #include "MessageDispatcher.h" #include "GuiController.h" #include "DeviceController.h" #include "FileHandler.h" //#include "GuiGlobals.h" /*! * \brief CloudSyncController::CloudSyncController * \details Constructor * \param parent - QObject parent owner object. * Qt handles the children destruction by their parent objects life-cycle. */ CloudSyncController::CloudSyncController(QObject *parent) : QObject(parent) { checkDate(); sendOutBuff("Ready"); startTimer(_interval); } /*! * \brief CloudSyncController initializer */ bool CloudSyncController::init() { if ( _init ) return false; _init = true; initConnections(); LOG_DEBUG(tr("%1 Initialized").arg(metaObject()->className())); return true; } /*! * \brief CloudSyncController::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 CloudSyncController::init(QThread &vThread) { if ( ! init() ) return false; initThread(vThread); return true; } /*! * \brief CloudSyncController::quit * \details quits the class * Calls quitThread */ void CloudSyncController::quit() { // coco begin validated: CloudSync termination is not correctly done in coco!!! // it has been tested and works perfectly fine in normal run. quitThread(); // validated } // coco end /*! * \brief CloudSyncController::initConnections * \details Initializes the required signal/slot connection between this class and other objects * to be able to communicate. */ void CloudSyncController::initConnections() { connect(&_DeviceController , SIGNAL(didWatchFileChange (const QString &)), this , SLOT( onWatchFileChange (const QString &))); connect(&_MessageDispatcher , SIGNAL(didActionReceive (GuiActionType,const QVariantList &)), this , SLOT( onActionReceive (GuiActionType,const QVariantList &))); } /*! * \brief CloudSyncController::initThread * \details Moves this object into the thread vThread. * And checks that this method is called from main thread. * Also connects quitThread to CloudSync aboutToQuit. * \param vThread - the thread */ void CloudSyncController::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 CloudSyncController::quitThread * \details Moves this object to main thread to be handled by QCloudSync * And to be destroyed there. */ void CloudSyncController::quitThread() { // coco begin validated: CloudSync 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 CloudSyncController::timerEvent * \details The timer event handler which currently is triggered on each second to check for the date change, * Which caused the watched file change and needs to updated the watched list. * The check-in (watch dog) also needs to be here. */ void CloudSyncController::timerEvent(QTimerEvent *) { // TODO: touch the inp file to as a check-in for CloudSync to know we are up // a simple touch or a check-in message? checkDate(); } /*! * \brief CloudSyncController::onWatchFileChange * \details This slot will be called when the Device Controller identifies any changes in the watched files. * \param vFile - watched file * \note The DeviceController will emit the signal on any watched file update, it's up to the CloudSyncController to filter the result. */ void CloudSyncController::onWatchFileChange(const QString &vFile) { if ( vFile != _date_out_File ) return; // ignore unwanted file updates. QString content; Storage::FileHandler::read(vFile, content); interpreter(content); } /*! * \brief CloudSyncController::addWatch * \details */ void CloudSyncController::addWatch() { // QString outBuff; bool ok = Storage::FileHandler::makeFolder(_location); if ( ok ) { _date_out_File = _location + // The location _dateFormatted + _dateSeparator + _out_File; // The file name // watching for the cloud sync output file buffer. _DeviceController.doAddWatch(_date_out_File); } else { LOG_DEBUG(tr("the CloudSync log folder cannot be created.")); } } /*! * \brief CloudSyncController::interpreter * \details the function to be called after reading the CloudSync out file to interpret the content of the file. * \param vContent - the content to be interpreted. * \return true if the content has a meaning for the interpreter, false otherwise. */ bool CloudSyncController::interpreter(const QString &vContent) { LOG_DEBUG(QString("~~~CloudSync Message received [%1]").arg(vContent)); // TODO: messages have to have a sequence. // if the seq is duplicate it will be ignored. // seq, id, payload return true; } /*! * \brief CloudSyncController::checkDate * \details Checks the date and updated the watched file in case the date changed. */ void CloudSyncController::checkDate() { _datetime = QDateTime::currentDateTime(); _timeFormatted = _datetime.toString(_timeFormat); QString dateFormatted = _datetime.toString(_dateFormat); if (_dateFormatted != dateFormatted) { _dateFormatted = dateFormatted; // TODO: do we need to remove current watch? addWatch(); } } bool CloudSyncController::sendOutBuff(const QString &vData) { QString inpBuff; _date_inp_File = _location + // The location _dateFormatted + _dateSeparator + _inp_File; // The file name inpBuff = _timeFormatted; inpBuff += _separator + QString::number(_seq++); inpBuff += _separator + vData; inpBuff += '\n'; // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // writing the message into the buffer. if ( ! Storage::FileHandler::write(_date_inp_File, inpBuff) ) { LOG_DEBUG(tr("Error writing to the CloudSync Input file.")); return false; } return true; } /*! * \brief CloudSyncController::onActionReceive * \details The slot which will be called when a CANBus message is received, and will be sent to CloudSync if related. * \param vAction - The message action * \param vData - The message data */ void CloudSyncController::onActionReceive(GuiActionType vAction, const QVariantList &vData) { QString inpBuff; switch (vAction) { case GuiActionType::ID_HDOperationModeData: case GuiActionType::ID_PreTreatmentStates : case GuiActionType::ID_TreatmentStates : case GuiActionType::ID_PostTreatmentStates: case GuiActionType::ID_DisinfectStates : // TODO: This section is the translation/mapping section // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv // preparing the message inpBuff = Format::toHexString/*QString::number*//*enumString*/(vAction); for (auto var : vData) { inpBuff += _separator + var.toString(); } if ( ! sendOutBuff(inpBuff) ) break; default: break; } }