Index: main.cpp =================================================================== diff -u -re5a802bc26647388cfea4f1d46ae22570ec2dba3 -rf35b360054e1e2fa81bf107427fe2d50d78e9e8a --- main.cpp (.../main.cpp) (revision e5a802bc26647388cfea4f1d46ae22570ec2dba3) +++ main.cpp (.../main.cpp) (revision f35b360054e1e2fa81bf107427fe2d50d78e9e8a) @@ -339,7 +339,7 @@ _BLEScanner.doInit(); //! - Initializing Wifi Interface - _WifiInterface.doInit(); + _WifiInterface.init(Threads::_Wifi_Thread); //! - Initializing Application Controller _ApplicationController.init(Threads::_Application_Thread); Index: sources/Threads.h =================================================================== diff -u -r64d87d540594252e8039ab2595016d98f1e3cc28 -rf35b360054e1e2fa81bf107427fe2d50d78e9e8a --- sources/Threads.h (.../Threads.h) (revision 64d87d540594252e8039ab2595016d98f1e3cc28) +++ sources/Threads.h (.../Threads.h) (revision f35b360054e1e2fa81bf107427fe2d50d78e9e8a) @@ -32,6 +32,7 @@ extern QThread _CanMessage_Thread ; extern QThread _DriveWatcher_Thread ; extern QThread _Logger_Thread ; + extern QThread _Wifi_Thread ; extern QThread _Application_Thread ; void registerTypes(); Index: sources/gui/GuiGlobals.cpp =================================================================== diff -u -re5a802bc26647388cfea4f1d46ae22570ec2dba3 -rf35b360054e1e2fa81bf107427fe2d50d78e9e8a --- sources/gui/GuiGlobals.cpp (.../GuiGlobals.cpp) (revision e5a802bc26647388cfea4f1d46ae22570ec2dba3) +++ sources/gui/GuiGlobals.cpp (.../GuiGlobals.cpp) (revision f35b360054e1e2fa81bf107427fe2d50d78e9e8a) @@ -93,6 +93,7 @@ qRegisterMetaType ("GuiAlarmPriority"); qRegisterMetaType ("GuiRequestReasons"); + qRegisterMetaType ("Network"); // Note that this Models are not used in the QML // but Qt needs them to be registered to be able to use them in between threads queue Index: sources/gui/qml/pages/SettingsHome.qml =================================================================== diff -u -re5a802bc26647388cfea4f1d46ae22570ec2dba3 -rf35b360054e1e2fa81bf107427fe2d50d78e9e8a --- sources/gui/qml/pages/SettingsHome.qml (.../SettingsHome.qml) (revision e5a802bc26647388cfea4f1d46ae22570ec2dba3) +++ sources/gui/qml/pages/SettingsHome.qml (.../SettingsHome.qml) (revision f35b360054e1e2fa81bf107427fe2d50d78e9e8a) @@ -122,7 +122,10 @@ } SettingsItem { id: _item_wifi title : qsTr("Wifi") - onClicked: push(_wifi); + onClicked: { + push(_wifi); + vNetworkModel.doScan() + } } } Index: sources/gui/qml/pages/SettingsWifi.qml =================================================================== diff -u -rc77365fa76422bc2150e58d483c446325b50f4b8 -rf35b360054e1e2fa81bf107427fe2d50d78e9e8a --- sources/gui/qml/pages/SettingsWifi.qml (.../SettingsWifi.qml) (revision c77365fa76422bc2150e58d483c446325b50f4b8) +++ sources/gui/qml/pages/SettingsWifi.qml (.../SettingsWifi.qml) (revision f35b360054e1e2fa81bf107427fe2d50d78e9e8a) @@ -32,13 +32,6 @@ signal clickedBack() - onVisibleChanged: { - if (visible) { - vNetworkModel.doRequestIPSettings() - vNetworkModel.doScan() - } - } - BackButton { id : _backButton onClicked: { _root.clickedBack() @@ -170,18 +163,6 @@ } } - Text { id: _noNetworks - text: qsTr("No Networks in Range") - color: Colors.textMain - font.pixelSize: Fonts.fontPixelTextRectExtra - visible: !vNetworkModel.scanInProgress && vNetworkModel.rowCount() === 0 - anchors { - top: parent.top - right: parent.right - rightMargin: 25 - } - } - ListView { id: _networkList model: vNetworkModel anchors { Index: sources/view/VNetworkModel.cpp =================================================================== diff -u -rc77365fa76422bc2150e58d483c446325b50f4b8 -rf35b360054e1e2fa81bf107427fe2d50d78e9e8a --- sources/view/VNetworkModel.cpp (.../VNetworkModel.cpp) (revision c77365fa76422bc2150e58d483c446325b50f4b8) +++ sources/view/VNetworkModel.cpp (.../VNetworkModel.cpp) (revision f35b360054e1e2fa81bf107427fe2d50d78e9e8a) @@ -1,5 +1,6 @@ // Qt +#include // Project #include "VNetworkModel.h" @@ -16,19 +17,19 @@ { // incoming connect(&_WifiInterface, SIGNAL(didAddNetwork(const Network)), - this, SLOT(doAddNetwork(const Network)), Qt::QueuedConnection); + this, SLOT(doAddNetwork(const Network))); connect(&_WifiInterface, SIGNAL(didScanStatusChanged(const bool)), - this, SLOT(onScanStatusChanged(const bool)), Qt::QueuedConnection); + this, SLOT(onScanStatusChanged(const bool))); connect(&_WifiInterface, SIGNAL(didConnectToNetwork(const Network)), - this, SLOT(onConnectedToNetwork(const Network)), Qt::QueuedConnection); + this, SLOT(onConnectedToNetwork(const Network))); connect(&_WifiInterface, SIGNAL(didDisconnectNetwork(Network)), - this, SLOT(onDisconnectedNetwork(const Network)), Qt::QueuedConnection); + this, SLOT(onDisconnectedNetwork(const Network))); connect(&_WifiInterface, SIGNAL(didError(const QString)), - this, SLOT(onError(const QString)), Qt::QueuedConnection); + this, SLOT(onError(const QString))); // outgoing connect(this, SIGNAL(didScan()), @@ -65,7 +66,8 @@ * \param parent - (QModelIndex) the parent QModelIndex * \return (int) - the number of networks */ -int VNetworkModel::rowCount(const QModelIndex & parent) const { +int VNetworkModel::rowCount(const QModelIndex & parent) const +{ Q_UNUSED(parent); return _networks.count(); } @@ -77,8 +79,8 @@ * \param role - (int) the property index to return. See NetworkDataRole * \return (QVariant) - the value for the specified network property */ -QVariant VNetworkModel::data(const QModelIndex & index, int role) const { - +QVariant VNetworkModel::data(const QModelIndex & index, int role) const +{ if (index.row() < 0 || index.row() >= _networks.count()) return QVariant(); @@ -121,6 +123,7 @@ * Handles when a user clicks the Scan button */ void VNetworkModel::doScan() { + qDebug() << __FUNCTION__ << QThread::currentThread()->objectName(); status(tr("Scanning...")); emit didScan(); } Index: sources/view/VNetworkModel.h =================================================================== diff -u -rc77365fa76422bc2150e58d483c446325b50f4b8 -rf35b360054e1e2fa81bf107427fe2d50d78e9e8a --- sources/view/VNetworkModel.h (.../VNetworkModel.h) (revision c77365fa76422bc2150e58d483c446325b50f4b8) +++ sources/view/VNetworkModel.h (.../VNetworkModel.h) (revision f35b360054e1e2fa81bf107427fe2d50d78e9e8a) @@ -26,12 +26,12 @@ { Q_OBJECT - PROPERTY(bool , scanInProgress, false) - PROPERTY(QString, status , "") - PROPERTY(QString, ipAddress , "") - PROPERTY(QString, gateway , "") - PROPERTY(QString, subnetMask , "") - PROPERTY(QString, dns , "") + PROPERTY(bool, scanInProgress , false) + PROPERTY(QString, status , "") + PROPERTY(QString, ipAddress , "") + PROPERTY(QString, gateway , "") + PROPERTY(QString, subnetMask , "") + PROPERTY(QString, dns , "") public: // Note: VIEW_DEC_CLASS(VNetworkModel) requires QObject as the parent, so it's necessary to define it here Index: sources/wifi/WifiInterface.cpp =================================================================== diff -u -rc77365fa76422bc2150e58d483c446325b50f4b8 -rf35b360054e1e2fa81bf107427fe2d50d78e9e8a --- sources/wifi/WifiInterface.cpp (.../WifiInterface.cpp) (revision c77365fa76422bc2150e58d483c446325b50f4b8) +++ sources/wifi/WifiInterface.cpp (.../WifiInterface.cpp) (revision f35b360054e1e2fa81bf107427fe2d50d78e9e8a) @@ -12,33 +12,101 @@ using namespace Storage; -WifiInterface::WifiInterface(QObject *parent) : QObject(parent) -{ -} +WifiInterface::WifiInterface(QObject *parent) : QObject(parent) {} void WifiInterface::onInitConnections() { connect(this, SIGNAL(didError(const QString)), this, SLOT(onLogFailure(const QString))); + + connect(&_processScan, SIGNAL(finished(int, QProcess::ExitStatus)), + this, SLOT(onScanFinished(int,QProcess::ExitStatus))); + +// connect(&_scanWatcher, SIGNAL(finished()), +// this , SLOT(onFinishedScan())); + + connect(this, SIGNAL(didScan()), + this, SLOT(onScan())); + } /*! * \brief WifiInterface::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 WifiInterface::init(QThread &vThread) +{ + if (!init()) return false; + initThread(vThread); + return true; +} + + +/*! + * \brief ApplicationController::initThread + * \details Moves this object into the thread vThread. + * And checks that this method is called from main thread. + * Also connects quitThread to application aboutToQuit. + * \param vThread - the thread + */ +void WifiInterface::initThread(QThread &vThread) +{ + // runs in main thread + Q_ASSERT_X(QThread::currentThread() == qApp->thread() , __func__, "The Class initialization must be done in Main Thread" ); + _thread = &vThread; + _thread->setObjectName(QString("%1_Thread").arg(metaObject()->className())); + connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(quit())); + _thread->start(); + moveToThread(_thread); +} + +/*! + * \brief MessageAcknowModel::quit + * \details quits the class + * Calls quitThread + */ +void WifiInterface::quit() +{ + // coco begin validated: Application termination is not correctly done in coco!!! + // it has been tested and works perfectly fine in normal run. + quitThread(); // validated +} + +/*! + * \brief MessageAcknowModel::quitThread + * \details Moves this object to main thread to be handled by QApplicaiton + * And to be destroyed there. + */ +void WifiInterface::quitThread() +{ + // coco begin validated: Application termination is not correctly done in coco!!! + // it has been tested and works perfectly fine in normal run. + + if (!_thread) return; + + // runs in thread + moveToThread(qApp->thread()); // validated +} +// coco end + + +/*! + * \brief WifiInterface::init * \details Initializes the class by setting the connections * \return true on first initialization, false if it has already been initialized */ -bool WifiInterface::doInit() +bool WifiInterface::init() { if (_init) return false; - _init = true; - onInitConnections(); - LOG_EVENT("UI," + tr("%1 Initialized").arg(metaObject()->className())); - return true; } @@ -60,7 +128,7 @@ */ void WifiInterface::onQuitThread() { - if (!_thread ) + if (!_thread) return; moveToThread(qApp->thread()); @@ -81,29 +149,43 @@ * Scans for Wifi Access Points */ void WifiInterface::doScan() +{ + qDebug() << __FUNCTION__ << QThread::currentThread()->objectName(); + emit didScan(); +} + +void WifiInterface::onScan() { - QtConcurrent::run([=]() { - if (_scanRunning) - { - LOG_DEBUG("Wifi network scan is already running."); - return; - } - LOG_DEBUG("Scanning for Wifi Access Points..."); - QProcess process; - process.setWorkingDirectory(Wifi_Scripts_Dir); - _scanRunning = true; - emit didScanStatusChanged(_scanRunning); - process.start(Wifi_Scan_For_Networks); - process.waitForFinished(_scanTimeout); - QString out = process.readAllStandardOutput(); - QString err = process.readAllStandardError(); - LOG_DEBUG(out); - LOG_DEBUG(err); - _scanRunning = false; - emit didScanStatusChanged(_scanRunning); - onParseWifiScan(out); - }); + qDebug() << __FUNCTION__ << QThread::currentThread()->objectName(); + if (_scanRunning) + { + LOG_DEBUG("Wifi network scan is already running."); + return; + } + LOG_DEBUG("Scanning for Wifi Access Points..."); + _processScan.setWorkingDirectory(Wifi_Scripts_Dir); + _scanRunning = true; + emit didScanStatusChanged(_scanRunning); + _processScan.start(Wifi_Scan_For_Networks); +} +/*! + * \brief WifiInterface::onScanFinished + * Called when the scan process has finished + * \param vExitCode - (int) the exit code + * \param vExitStatus - (QProcess::ExitStatus) the exit status + */ +void WifiInterface::onScanFinished(int vExitCode, QProcess::ExitStatus vExitStatus) +{ + Q_UNUSED(vExitCode) + Q_UNUSED(vExitStatus) +// QString out = _processScan.readAllStandardOutput(); +// QString err = _processScan.readAllStandardError(); +// LOG_DEBUG(out); +// LOG_DEBUG(err); +// _scanRunning = false; +// emit didScanStatusChanged(_scanRunning); +// onParseWifiScan(out); } /*! @@ -168,31 +250,29 @@ */ void WifiInterface::doJoinNetwork(const Network &vNetwork, const QString &vPassword) { - QtConcurrent::run([=]() { - LOG_DEBUG(QString("Joining Network %1").arg(vNetwork.ssid())); - if (!generateWPASupplicant(vNetwork, vPassword)) - { - emit didError("Could not configure network."); - return; - } + LOG_DEBUG(QString("Joining Network %1").arg(vNetwork.ssid())); + if (!generateWPASupplicant(vNetwork, vPassword)) + { + emit didError("Could not configure network."); + return; + } - if (!startWPASupplicant()) - { - emit didError("Could not configure network."); - return; - } + if (!startWPASupplicant()) + { + emit didError("Could not configure network."); + return; + } - // TODO: Add option to setup with static IP settings instead - if (!requestAutoAssignedIP()) - { - emit didError(QString("Could not connect to %1").arg(vNetwork.ssid())); - return; - } + // TODO: Add option to setup with static IP settings instead + if (!requestAutoAssignedIP()) + { + emit didError(QString("Could not connect to %1").arg(vNetwork.ssid())); + return; + } - Network network = vNetwork; - network.ipSettings(getIPSettings()); - emit didConnectToNetwork(network); - }); + Network network = vNetwork; + network.ipSettings(getIPSettings()); + emit didConnectToNetwork(network); } /*! Index: sources/wifi/WifiInterface.h =================================================================== diff -u -rc77365fa76422bc2150e58d483c446325b50f4b8 -rf35b360054e1e2fa81bf107427fe2d50d78e9e8a --- sources/wifi/WifiInterface.h (.../WifiInterface.h) (revision c77365fa76422bc2150e58d483c446325b50f4b8) +++ sources/wifi/WifiInterface.h (.../WifiInterface.h) (revision f35b360054e1e2fa81bf107427fe2d50d78e9e8a) @@ -3,6 +3,7 @@ // Qt #include #include +#include // Project #include "main.h" @@ -29,6 +30,8 @@ int _defaultTimeout = 5000; int _dhcpTimeout = 10000; int _scanTimeout = 30000; + int _processCounter = 0; + QProcess _processScan; const QString _iface = "wlan0"; const QString _wpaSupplicantConfPath = "/etc/wpa_supplicant.conf"; @@ -38,6 +41,8 @@ SINGLETON(WifiInterface) private: +// QFutureWatcher _scanWatcher; + bool generateWPASupplicant(const Network &vNetwork, const QString &vPassword); bool startWPASupplicant(); bool requestAutoAssignedIP(int vTries = 4); @@ -53,24 +58,36 @@ void onInitConnections(); void onQuitThread(); void timerEvent(QTimerEvent* event); + void initThread(QThread &vThread); + void quitThread(); public slots: - bool doInit(); + bool init(QThread &vThread); + bool init(); void doScan(); void doJoinNetwork(const Network &vNetwork, const QString &vPassword); void doDisconnectNetwork(const Network &vNetwork); void doRequestIPSettings(); +private slots: + void quit(); + signals: void didAddNetwork(const Network); + void didDisconnectNetwork(const Network); + void didGetIPSettings(const Network::IPSettings); + void didRequestScan(); + void didScan(); + + // emitted from separate threads void didScanStatusChanged(const bool); void didConnectToNetwork(const Network); - void didDisconnectNetwork(const Network); void didError(const QString); - void didGetIPSettings(const Network::IPSettings); private slots: void onQuit(); void onParseWifiScan(const QString &vOutput); void onLogFailure(const QString &vMessage); + void onScanFinished(int vExitCode, QProcess::ExitStatus vExitStatus); + void onScan(); };