/*! * * 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 DeviceController.h * \author (last) Behrouz NematiPour * \date (last) 29-May-2021 * \author (original) Behrouz NematiPour * \date (original) 17-Jul-2020 * */ #pragma once // Qt #include #include #include // Project #include "main.h" // Doxygen : do not remove #include "Threads.h" #include "DeviceGlobals.h" #include "DeviceModels.h" #include "DeviceError.h" // Define #define _DeviceController Device::DeviceController::I() // forward declarations class tst_initializations; namespace Device { /*! * \brief The TimedProcess class * \details This is a timed process class which has a timeout * and will kill the process if it can't be finished within the given timeout * in milliseconds. */ class TimedProcess : public QObject { Q_OBJECT explicit TimedProcess(QObject *parent = nullptr) : QObject(parent) { } int _id = 0; int _timeout = 0; QProcess *_process = nullptr; QString _command = ""; private slots: void onFinish(int) { killTimer(_id); _process->kill(); _process = nullptr; deleteLater(); } public: TimedProcess(QProcess *vProcess, const QString &vCommand, int vTimeout) : QObject(), _timeout(vTimeout), _process(vProcess), _command(vCommand) { connect(_process, SIGNAL( finished(int)), this , SLOT(onFinish (int))); } void start() { _id = startTimer(_timeout); _process->start(_command); } protected: void timerEvent(QTimerEvent *) { onFinish(-1); } }; /*! * \brief The DeviceController class * \details This class is the device controller meaning all the device interactions and settings like Volume(Device), Brightness, WiFi, Date, Time, etc * has to be done through this controller and it's dedicated thread and by using the QProcess(es) which is a call to the administrative shell scripts. * It also is watching for the USB and SD-Card drives in Linux file system. * It has the interval of 1000 ms and will look if any device between /dev/sda1 to /dev/sdz1 exists then will mount it in /media/usb, * and does check if the SD-Card has been mounted under /media/sdcard, * but for SD-Card does not try to mount it and it has to be mounted prior to UI Application start * and that's because from UI Application perspective it is not a removable/hot-plug device (although physically it is). * This class works in its own thread and will send notification by emitting signals about the USB device status * which are Mounted, Unmounted, Removed * and SD-Card space conditions changes. * \note : - 'Removed' is when no USB device present. * - Only brightness is using this class currently */ class DeviceController : public QObject { Q_OBJECT // Singleton SINGLETON(DeviceController) // friends friend class ::tst_initializations; bool _mounted = false; bool _umounted = false; bool _removed = false; const char *_usbDrive = ""; const int _interval = 1000; // in ms const qint8 _minRequiredAvailableSpacePercent = 10; QThread *_thread = nullptr; bool _init = false; bool _pauseSpaceCheck = false; QFileSystemWatcher _fileSystemWatcher; //TODO: all of these should use the TimesProcess (instead of QProcess) // to be able to kill the process automatically after the set time out. DEVICE_DEV_DEFINITION_LIST public slots: bool init(); bool init(QThread &vThread); void doScreenshot(const QImage &vImage, const QString &vFileName); private slots: void quit(); void onRemoveLogs(bool vInProgress); void onScreenshot(const QImage &vImage, const QString &vFileName); protected: void timerEvent(QTimerEvent *) override; private: void initConnections(); void initThread(QThread &vThread); void quitThread(); bool usbSeek(QString &vDevice); bool driveSpaceCheck(const QString &vPath, qint64 &vTotalBytes, qint64 &vAvailableBytes, bool *vIsReadOnly = nullptr); template bool checkError(DeviceError::Scripts_Error_Enum vError, TModel &vModel,QString vExtraLogInfo = ""); DeviceError::Scripts_Error_Enum checkScript(QString &vScript, const QString &vShellScript); bool addWatch(const QString &vFilePath); signals: /*! * \brief didScreenshot * \details The screenshot signal to run the onScreenshot slot in device controller thread. * \param vImage - The image source object * \param vFileName - The filename to same the image to */ void didScreenshot(const QImage &vImage, const QString &vFilenNme); /*! * \brief didUSBDriveMount * \details notifies UI when USB device is available and has been mounted. */ void didUSBDriveMount (); /*! * \brief didUSBDriveUmount * \details notifies USB watcher on UI(user) request for USB umount. */ void didUSBDriveUmount(); /*! * \brief didUSBDriveRemove * \details notifies UI when USB device has been removed(not exists). */ void didUSBDriveRemove(); /*! * \brief didSDCardFreeSpaceChange * \param vReady - Device is mounted and ready * \note if device ejected manually system assumes it's still ready. * \param vTotal - Returns the total volume size in bytes. * Returns -1 if QStorageInfo object is not valid * \param vAvailable - Returns the size (in bytes) available for the current user. * It returns the total size available if the user is the root user or a system administrator. * This size can be less than or equal to the free size returned by bytesFree() function. * Returns -1 if QStorageInfo object is not valid. * \param vPercent - The percentage of available space. * \note Will emitted if only one of the publishing parameter changes. */ void didSDCardSpaceChange(bool vReady, qint64 vTotal, qint64 vAvailable, quint8 vPercent); /*! * \brief didSDCardStateChange * \details If SDCard state changes like removed or is not present this signal will emit. */ void didSDCardStateChange(bool vIsReady, bool vIsReadOnly); /*! * \brief didSDCardSpaceTooLow * \details this signal will emit ones the available space left on the SD-Card * is less than minimum required percentage defined in _minRequiredAvailableSpacePercent. * \param vAvailablePercent */ void didSDCardSpaceTooLow(quint8 vAvailablePercent); void didActionReceive( const DeviceBrightnessResponseData &vBrightness ); void didWatchFileChange(const QString &vFile); private slots: // ----- USB void usbCheck(); bool usbMount (const QString &vDevice); bool usbUmount(const QString &vDevice); void usbRemove(); void usbError (const QString &vDevice); void onUSBDriveUmount(); void onWatchFileChanged(const QString &vFile); // ----- SDCard void sdcardSpaceCheck(); SAFE_CALL_EX(doAddWatch, const QString &) }; }