Index: sources/cloudsync/CloudSyncController.cpp =================================================================== diff -u -r2f0f23635ac0225d2012e3db9d1043ce19c6d715 -ra7c8f14c6d5420ea15cdbd8fc6e3c46bae1052cb --- sources/cloudsync/CloudSyncController.cpp (.../CloudSyncController.cpp) (revision 2f0f23635ac0225d2012e3db9d1043ce19c6d715) +++ sources/cloudsync/CloudSyncController.cpp (.../CloudSyncController.cpp) (revision a7c8f14c6d5420ea15cdbd8fc6e3c46bae1052cb) @@ -106,6 +106,8 @@ connect(&_DeviceController , SIGNAL(didCryptSetupMount(bool)), this , SLOT( onCryptSetupMount(bool))); + connect(&_DeviceController , SIGNAL(didPendingLog (const QString &, const QString &)), + this , SLOT( onPendingLog (const QString &, const QString &))); connect(&_DeviceController , SIGNAL(didWatchFileChange (const QString &)), this , SLOT( onWatchFileChange (const QString &))); @@ -415,6 +417,8 @@ case eError_CredentialEmpty : text = tr( "CS The credentials folder is empty." ) ; break; case eError_TxCodeNoParam : text = tr( "CS No Treatment Code provided." ) ; break; case eError_TxCodeEmpty : text = tr( "CS The provided Treatment Code is empty." ) ; break; + case eError_LogNameNoParam : text = tr( "CS No Log Name provided." ) ; break; + case eError_LogNameEmpty : text = tr( "CS The provided Log Name is empty." ) ; break; case eError_NotRegistered : text = tr( "CS Not Sent, Device not registered." ) ; break; } @@ -472,6 +476,8 @@ case eError_CredentialEmpty : info = QString( "[%1:%2]" ).arg( vErrorID ).arg( item(0) ) ; break; case eError_TxCodeNoParam : info = QString( "[%1:%2]" ).arg( vErrorID ).arg( item(0) ) ; break; case eError_TxCodeEmpty : info = QString( "[%1:%2]" ).arg( vErrorID ).arg( item(0) ) ; break; + case eError_LogNameNoParam : info = QString( "[%1:%2]" ).arg( vErrorID ).arg( item(0) ) ; break; + case eError_LogNameEmpty : info = QString( "[%1:%2]" ).arg( vErrorID ).arg( item(0) ) ; break; case eError_NotRegistered : info = QString( "[%1:%2]" ).arg( vErrorID ).arg( item(0) ) ; break; } return info; @@ -759,7 +765,51 @@ sendPendingTxr(vFileName); } +// ------------------------------------------------------------------------ TODO: Improve : fucntion description +void CloudSyncController::onPendingLog(const QString &vFileName, const QString vChecksum) +{ + sendPendingLog(vFileName, vChecksum); +} + +// ------------------------------------------------------------------------ TODO: Improve : fucntion description +void CloudSyncController::sendPendingLog(const QString &vFileName, const QString vChecksum) +{ + bool ok = true; Q_UNUSED(ok) + QVariantList args ; + Errors_Enum error = eError_Unknown; + qint32 messageID = UI2CS(static_cast( eMessageID_SendLogUpload )); + // DEBUG ok = false; // using the ok bool which is true as the debug flag to bypass the registration on debug testing. + if ( ok && ! isRegistered() ) { error = eError_NotRegistered ; args = { vFileName }; ok = false; goto lErr; } + sendUIBuff(makeUIBuff( messageID , { vFileName, vChecksum } )); + + return; +lErr: + toLog(error, args); +} + /*! + * \brief CloudSyncController::rcvdPendingLog + * \details reads the received Log Name from CloudSync app and notifies with a signal. + * \param vMessage : message containing the uploaded Log name. + * \return true on successful extracting the Log Name. + */ +bool CloudSyncController::rcvdPendingLog(const Message &vMessage) +{ + bool ok = true; + QString mLogName; + // although it has been checked in the interpreter, we won't risk the crash and check the list empty. + if ( vMessage.params.isEmpty() ) { toLog(eError_LogNameNoParam , {}); ok = false; goto lOut; } + mLogName = vMessage.params[0].trimmed(); + if ( mLogName.isEmpty() ) { toLog(eError_LogNameEmpty , {}); ok = false; goto lOut; } + //DEBUG + qDebug() << " ---------- " << mLogName; + emit didLogUpload( mLogName ); + + lOut: + return ok; +} + +/*! * \brief CloudSyncController::sendMessage * \details Makes and Sends the appropriate message for the vAction. * Some messages are sent out upon request form the last received on the history and will not be asked from FW. @@ -778,6 +828,7 @@ case eMessageID_DeviceState : ok = sendDeviceState ( ); break; case eMessageID_TxCodeDisplay : ok = sendTxCodeDisplay ( vMessage ); break; + case eMessageID_SendLogUpload : ok = rcvdPendingLog ( vMessage ); break; case eMessageID_TxReport : /* No Req/Rsp, it is event based */ break; // This message doesn't have the response since there is no request. UI will send when the data ready by HD. @@ -997,9 +1048,13 @@ */ bool CloudSyncController::isRegistered() { +#ifdef BUILD_FOR_DESKTOP + return true; +#else QString source = QString(Storage::CloudSync_Base_Path_Name) + Storage::CloudSync_Credentials_Folder_Name; QFileInfoList fileInfos = QDir(source).entryInfoList(QDir::NoDotAndDotDot|QDir::Files); return !fileInfos.isEmpty(); +#endif } /*! Index: sources/cloudsync/CloudSyncController.h =================================================================== diff -u -r2f0f23635ac0225d2012e3db9d1043ce19c6d715 -ra7c8f14c6d5420ea15cdbd8fc6e3c46bae1052cb --- sources/cloudsync/CloudSyncController.h (.../CloudSyncController.h) (revision 2f0f23635ac0225d2012e3db9d1043ce19c6d715) +++ sources/cloudsync/CloudSyncController.h (.../CloudSyncController.h) (revision a7c8f14c6d5420ea15cdbd8fc6e3c46bae1052cb) @@ -130,6 +130,9 @@ eError_OutFileEmpty = 971, // Out file has changed from CS2UI but the content is empty. eError_NotRegistered = 972, // avoid sending any message other than the device registration, when device is not registered. + + eError_LogNameNoParam = 973, // the received Log Name not provided + eError_LogNameEmpty = 974, // the received Log Name is empty }; typedef QHash MessageList; @@ -219,15 +222,17 @@ private slots: void onWatchFileChange (const QString &vFile); void onActionReceive (GuiActionType vAction, const QVariantList &vData); - void onPendingTxr (const QString &vFileName ); + void onPendingTxr (const QString &vFileName ); + void onPendingLog (const QString &vFileName, const QString vChecksum ); void onInitComplete (); void onPOSTCloudSync (bool vPass ); void onCryptSetupMount (bool vPass ); void onFactoryReset (bool vPass ); signals: void didInitComplete (); - void didTxCodeReceive (const QString &vTxCode); + void didTxCodeReceive (const QString &vTxCode ); + void didLogUpload (const QString &vFileName ); void didRegisterStart (bool vOK ); void didRegisterDone (bool vOK ); void didCloudSyncStatus (bool vReady ); @@ -308,4 +313,8 @@ void sendPendingTxr ( const QString &vFileName ); // eMessageID_TxReport bool sendTxCodeDisplay ( const Message &vMessage ); // eMessageID_TxCodeDisplay + // pending Treatment log + void sendPendingLog (const QString &vFileName , const QString vChecksum); // eMessageID_SendLogUpload + bool rcvdPendingLog (const Message &vMessage ); // eMessageID_SendLogUpload + }; Index: sources/device/DeviceController.cpp =================================================================== diff -u -rf724589acaa51725f5e5f8a746404d01804efbcf -ra7c8f14c6d5420ea15cdbd8fc6e3c46bae1052cb --- sources/device/DeviceController.cpp (.../DeviceController.cpp) (revision f724589acaa51725f5e5f8a746404d01804efbcf) +++ sources/device/DeviceController.cpp (.../DeviceController.cpp) (revision a7c8f14c6d5420ea15cdbd8fc6e3c46bae1052cb) @@ -27,6 +27,7 @@ #include "Threads.h" #include "StorageGlobals.h" #include "Logger.h" +#include "CloudSyncController.h" #include "ApplicationController.h" #include "FileHandler.h" #include "DeviceModels.h" @@ -119,6 +120,11 @@ connect(&_ApplicationController , SIGNAL(didPOSTCloudSyncData (const QString &)), this , SLOT( onPOSTCloudSyncData (const QString &))); + connect(&_Logger , SIGNAL(didLogBackup (const QString &)), + this , SLOT( onLogBackup (const QString &))); + connect(&_CloudSyncController , SIGNAL(didLogUpload (const QString &)), + this , SLOT( onLogUpload (const QString &))); + DEVICE_DEV_INIT_CONNECTIONS_LIST connect(this, SIGNAL(didEventThreadChange()), @@ -243,6 +249,7 @@ // logs and need a separate disk space usage check settingsPartitionSpaceCheck(); #endif + findPendingLogs(); } /*! @@ -963,6 +970,44 @@ emit didPOSTCloudSyncData (vNetAddress); } +void DeviceController::onLogBackup(const QString &vFileName) +{ + QFileInfo fileInfo(vFileName); + QString filePath(fileInfo.absolutePath()); + QString fileBase(fileInfo.baseName()); + // ------------------------------------------------------------------------ TODO: Improve : get pending type extention + QString fileSufx(fileInfo.completeSuffix().prepend("u.")); + QString fileDest(QString("%1/%2.%3").arg(filePath, fileBase, fileSufx)); + // DEBUG + // qDebug() << ""; + // qDebug() << vFileName; + // qDebug() << fileDest; + QFile::rename(vFileName, fileDest); +} + +void DeviceController::onLogUpload(const QString &vFileName) +{ + QFileInfo fileInfo(vFileName); + QString filePath(Storage::Log_Folder_Base); + QString fileBase(fileInfo.baseName()); + // ------------------------------------------------------------------------ TODO: Improve : get pending type extention + QString fileSufx(fileInfo.completeSuffix().remove("u.")); + // ------------------------------------------------------------------------ TODO: Improve : get type + if( fileSufx == "log" ) { + filePath += Storage::Log_Folder_Application; + } + // ------------------------------------------------------------------------ TODO: Improve : get type + if( fileSufx == "err" ) { + filePath += Storage::Log_Folder_Service; + } + QString fileDest(QString("%1.%2").arg(fileBase, fileSufx)); + // DEBUG + // qDebug() << ""; + // qDebug() << vFileName; + // qDebug() << fileDest; + QFile::rename(filePath + vFileName, filePath + fileDest); +} + /*! * \brief DeviceController::checkConfugurationMountReady * \details Cheks if the system is ready to mount the encrypted partition. @@ -997,6 +1042,54 @@ // and take care of the security flag in the Storage class. } +/*! + * \brief DeviceController::findPendingLogs + * \details this function counts downs for the _pendingInterval + * when the _pendingCounter reaches 0 will search for the files + * and if there is any will get the recent file in the list + */ +void DeviceController::findPendingLogs() +{ + static QString pendingLog = ""; + if( _pendingCounter ) { + _pendingCounter -- ; + return; + } + else { + _pendingCounter = _pendingInterval; // every minute + } + + QFileInfoList pendingFiles; + QString logLoc = Log_Folder_Base; + // ------------------------------------------------------------------------ TODO: Improve : get pending type extention + QString logExt = "*.u.*"; + + for( auto logFolder : { Log_Folder_Application, Log_Folder_Service/*, Log_Folder_CloudSync*/ } ) { + pendingFiles = Storage::FileHandler::find( logLoc + logFolder, { logExt } ); + // look into the list. + // if there are pending files, + // send a request only for the top on the list + /// Note I thought it makes sense to send the oldest on the application and service logs + /// but there some conversation about the situation if something happens on the device, + /// and it would be a critical situation to get the recent/top log and won't wait for the old ones to upload. + // * When gets uploaded, moves from pending then next one comes to top + // the process repeats until there is no file in pending + if ( pendingFiles.count() ) { + // the most recent/first Tx file, to first ask for the current treatment which has just saved as pending on screen + _pendingLog = pendingFiles.first().absoluteFilePath(); + QString message = pendingLog; + LOG_DEBUG(message); + emit didPendingLog( _pendingLog, FileHandler::sha256sum( _pendingLog ) ); + // when a pending file found in the first log folder stop + // until there is none in first one (log) + // then continue to the next log folder (service) ... + goto lOut; + } + } +lOut: + return; +} + ///////////////////////////////////////////// DeviceFactoryReset void DeviceController::onAttributeRequest(const DeviceFactoryResetRequestData &vData) { Index: sources/device/DeviceController.h =================================================================== diff -u -r2ef03b2ce51b4dc507f66e9671953a8e0824bde9 -ra7c8f14c6d5420ea15cdbd8fc6e3c46bae1052cb --- sources/device/DeviceController.h (.../DeviceController.h) (revision 2ef03b2ce51b4dc507f66e9671953a8e0824bde9) +++ sources/device/DeviceController.h (.../DeviceController.h) (revision a7c8f14c6d5420ea15cdbd8fc6e3c46bae1052cb) @@ -104,7 +104,10 @@ bool _mounted = false; bool _umounted = false; bool _removed = false; - const int _interval = 1000; // in ms + const int _interval = 1000; // in ms = 1s + const int _pendingInterval = 60 ; // 1m + int _pendingCounter = 0 ; // + QString _pendingLog = ""; const qint8 _minRequiredAvailableSpacePercent = 10; @@ -157,6 +160,9 @@ void onPOSTBluetoothData (const QString &vMacAddress); void onPOSTCloudSyncData (const QString &vNetAddress); + void onLogBackup (const QString &vFileName ); + void onLogUpload (const QString &vFileName ); + protected: void timerEvent(QTimerEvent *) override; @@ -178,6 +184,8 @@ void checkConfugurationMountReady(); + void findPendingLogs(); + signals: /*! * \brief didScreenshot @@ -290,6 +298,13 @@ */ void didFactoryReset ( bool vPass ); + /*! + * \brief didPendingLog + * \details will be emitted when a log file is pending to be uploaded. + * \param vFileName - the pending log file name + */ + void didPendingLog (const QString &vFileName, const QString vChecksum ); + private: // ----- USB void usbCheck (); Index: sources/storage/Logger.cpp =================================================================== diff -u -r5e9b0ee29f7f9702dc8aa13044b5a38358269211 -ra7c8f14c6d5420ea15cdbd8fc6e3c46bae1052cb --- sources/storage/Logger.cpp (.../Logger.cpp) (revision 5e9b0ee29f7f9702dc8aa13044b5a38358269211) +++ sources/storage/Logger.cpp (.../Logger.cpp) (revision a7c8f14c6d5420ea15cdbd8fc6e3c46bae1052cb) @@ -343,12 +343,38 @@ + _fileSeparator + _logFileNameHDSN + _fileSeparator + _logFileNameMode ; - switch (vLogType) { - case LogType::eLogAppED: - case LogType::eLogDebug: // case LogType::eLogTrtmt: // this type of log will never happen here. Only put here to make sure it is intentional. - fileName += _logFileNameExt[vLogType]; + switch (vLogType) { + case LogType::eLogAppED: { + // ------------------------------------------------------------------------ TODO: Improve : fucntion declaration + fileName += _logFileNameExt[vLogType]; + static QString oFileName; + if( oFileName != fileName ) { + if( oFileName.trimmed().isEmpty() ) { + oFileName = fileName; + } + else { + emit didLogBackup( _logPathNames[vLogType] + oFileName ); + oFileName = fileName; + } + } + } break; + case LogType::eLogDebug: { + // ------------------------------------------------------------------------ TODO: Improve : fucntion declaration + fileName += _logFileNameExt[vLogType]; + static QString oFileName; + if( oFileName != fileName ) { + if( oFileName.trimmed().isEmpty() ) { + oFileName = fileName; + } + else { + emit didLogBackup( _logPathNames[vLogType] + oFileName ); + oFileName = fileName; + } + } + } + break; default: fileName += _logFileNameExt[eLogDebug]; Index: sources/storage/Logger.h =================================================================== diff -u -rabd0e958420f25e5b8dd8ce6e21131f8561b99e0 -ra7c8f14c6d5420ea15cdbd8fc6e3c46bae1052cb --- sources/storage/Logger.h (.../Logger.h) (revision abd0e958420f25e5b8dd8ce6e21131f8561b99e0) +++ sources/storage/Logger.h (.../Logger.h) (revision a7c8f14c6d5420ea15cdbd8fc6e3c46bae1052cb) @@ -185,6 +185,7 @@ signals: void didLogPathSet(Logger::LogType vLogType, const QString &vLogPath); void didLogIOFail(); + void didLogBackup ( const QString vFileName ); public slots: bool init(); Index: sources/storage/TreatmentLog.cpp =================================================================== diff -u -r2f0f23635ac0225d2012e3db9d1043ce19c6d715 -ra7c8f14c6d5420ea15cdbd8fc6e3c46bae1052cb --- sources/storage/TreatmentLog.cpp (.../TreatmentLog.cpp) (revision 2f0f23635ac0225d2012e3db9d1043ce19c6d715) +++ sources/storage/TreatmentLog.cpp (.../TreatmentLog.cpp) (revision a7c8f14c6d5420ea15cdbd8fc6e3c46bae1052cb) @@ -616,9 +616,8 @@ /*! * \brief TreatmentLog::testPendingTxReports - * \details this function count downs for the _pendingInterval + * \details this function counts downs for the _pendingInterval * when the _pendingCounter reaches 0 will search for the files - * in the _TreatmentLog.logPathPending() * and if there is any will get the recent file in the list * and asks for the TxCode by emitting the didPendingTxr signal */