Index: sources/device/DeviceView.cpp =================================================================== diff -u -r2ef03b2ce51b4dc507f66e9671953a8e0824bde9 -r472c10e72a8d278f13d2343f9c81c1def14490ff --- sources/device/DeviceView.cpp (.../DeviceView.cpp) (revision 2ef03b2ce51b4dc507f66e9671953a8e0824bde9) +++ sources/device/DeviceView.cpp (.../DeviceView.cpp) (revision 472c10e72a8d278f13d2343f9c81c1def14490ff) @@ -22,44 +22,50 @@ #include "DeviceController.h" #include "GuiGlobals.h" #include "encryption.h" +#include "MWifiNetwork.h" -VIEW_DEF_CLASS(VDevice) +VIEW_DEF_CLASS_EX(VDevice, QAbstractListModel) void VDevice::initConnections() { DEVICE_VIEW_INIT_CONNECTIONS_LIST - connect(&_DeviceController , SIGNAL(didPOSTOSVersionData(QString)), this , SLOT( onPOSTOSVersionData(QString))); } -// developer implementation section +// ================================================================================================== +// ================================================= developer implementation section +// ================================================================================================== + +// ================================================= OS Version +void VDevice::onPOSTOSVersionData(const QString &vOSVersion) +{ + osVersion(vOSVersion); +} + +// ================================================= Brightness void VDevice::doInitBrightness() { // DEBUG : qDebug() << "HERE Request" << vValue; DeviceBrightnessRequestData data; - data.mRead = true; emit didAttributeRequest(data); } void VDevice::brightnessRequest(const quint8 &vValue) { // DEBUG : qDebug() << "HERE Request" << vValue; DeviceBrightnessRequestData data; - data.mBrightnessPercent = vValue; + data.mBrightness = vValue; emit didAttributeRequest(data); } void VDevice::onAttributeResponse(const DeviceBrightnessResponseData &vData) { - // DEBUG : qDebug() << "HERE Response" << vData.mBrightnessPercent; - if ( vData.mAccepted ) { - brightness(vData.mBrightnessPercent); - status(""); + // DEBUG : qDebug() << "HERE Response" << vData.mBrightness << brightness(); + if ( vData.mCompleted ) { + // for the brightness we will set what ever comes from the script either succeed or failed. + brightness(vData.mBrightness); + emit brightnessChanged(vData.mBrightness); } - else { - // this has to be called to let Gui to set to old value that device controller provided. - emit brightnessChanged(vData.mBrightnessPercent); - status(vData.mMessage); - } + status (vData.mMessage ); accepted(vData.mAccepted); reason (vData.mReason ); @@ -89,7 +95,6 @@ } void VDevice::onAttributeResponse(const DeviceCryptSetupResponseData &vData) { - // DEBUG : qDebug() << "HERE Response" << vData.mBrightnessPercent; // this has to be called to let Gui to set to old value that device controller provided. // this response is not updating the cryptsetup attribute. // cryptsetup attribute will containe the command to be sent to the cryptsetup script @@ -174,7 +179,6 @@ } void VDevice::onAttributeResponse(const DeviceRootSSHAccessResponseData &vData) { - // DEBUG : qDebug() << "HERE Response" << vData.mBrightnessPercent; if ( vData.mAccepted ) { rootSSHAccess(vData.mRootSSHAccess); status(""); @@ -258,7 +262,214 @@ response(true); } -void VDevice::onPOSTOSVersionData(const QString &vOSVersion) +// ================================================= WifiList +void VDevice::doInitWifiList() { + wifiListRequest({}); +} + +void VDevice::wifiListRequest(const QStringList &) { + status( "" ); + wifiList({}); + dataClear(); + wifiListEnabled(false); + DeviceWifiListRequestData data ; + emit didAttributeRequest( data ); +} + +void VDevice::onAttributeResponse(const DeviceWifiListResponseData &vData) { + // DEBUG : qDebug() << " 2 ---------- " << __FUNCTION__ << vData.mMessage << result << vData.mCompleted; + if ( vData.mCompleted ) { + if ( vData.mAccepted ) { + wifiListEnabled(true); + parseWifiListResult(vData.mWifiList); + } + else { + wifiList({}); + } + } + + accepted(vData.mAccepted); + reason (vData.mReason ); + + status (vData.mMessage ); + + // has to be the last one + response(true); +} + +/*! + * \brief Network::parseWifiListResult + * \details Extract desired information from the WiFi scan output. Sorts by signal stength + * \param vResult - (QString) output collected from QProcess execution + * \return List of the Found SSIDs in a model. + */ +void View::VDevice::parseWifiListResult(const QString &vResult) { - osVersion(vOSVersion); + enum SSIDInfo_Enum { + eSSID , + eBSSID , + eFREQ , + eRATE , + eSIGNAL , + eSECURITY , + eWPA_FLAGS , + eRSN_FLAGS , + eIN_USE , + }; + enum ValueUnit_Enum { + eValue , + eUnit , + eCount , + }; + + struct SSIDInfo { + QString mSSID ; + QString mBSSID ; + quint16 mFREQ_Max ; + quint16 mRATE_Max ; + quint16 mSIGNAL_Max ; + QString mSECURITY ; + QString mFLAGS ; // eWPA_FLAGS, eRSN_FLAGS are exclusive + bool mInUse = false ; + bool mSupported = true ; + QString toString() { + QStringList fields = QStringList() + << mSSID + << mBSSID + << QString::number(mFREQ_Max ) + << QString::number(mRATE_Max ) + << QString::number(mSIGNAL_Max ) + << mSECURITY + << mFLAGS + << (mSupported ? "T" : "") + << (mInUse ? "T" : ""); + return fields.join(','); + } + }; + + QString mResult = vResult; + QHash ssidInfoList; + + // the Freq, Rate units + QString mSSID; +const QString mFREQ_Unit = " MHz"; +const QString mRATE_Unit = " Mbit/s"; + // Removing the units once from the result to accelerate parsing. (will be added when done) + mResult.remove(mFREQ_Unit); + mResult.remove(mRATE_Unit); + + QStringList lines = mResult.split('\n'); + for ( int row = 0; row < lines.count(); row++ ) { + QString mWPA_FLAGS; + QString mRSN_FLAGS; + + QStringList fields = lines[row].split(','); + qDebug() << fields.join("-"); + // this will never fail since even an empty string in split at least has index 0=eSSID; + mSSID = fields[eSSID].trimmed(); + if ( mSSID.isEmpty() ) continue; //hidden networks, or an incorrect entry + + if ( ssidInfoList.contains( mSSID ) ) { + for ( int index = 0; index < fields.count(); index++ ) { // the list has to be sorted and the script is written that way. + QString field = fields[index].trimmed(); + quint32 value = 0; + switch (index) { + // NOTE: NOT USED FOR NOW + // Not sure if get the max independently for each row is a correct way. + // since if we connect to one then we are bound to the specification of that Ap, so we cannot have a max freq from one and max rate from another one. + case eFREQ : value = QString("%1").arg(field).toInt(); if ( ssidInfoList[mSSID].mFREQ_Max < value ) { ssidInfoList[mSSID].mFREQ_Max = value; } break; + case eRATE : value = QString("%1").arg(field).toInt(); if ( ssidInfoList[mSSID].mRATE_Max < value ) { ssidInfoList[mSSID].mRATE_Max = value; } break; + case eSIGNAL : value = QString("%1").arg(field).toInt(); if ( ssidInfoList[mSSID].mSIGNAL_Max < value ) { ssidInfoList[mSSID].mSIGNAL_Max = value; } break; + case eIN_USE : value = field.contains("*"); ssidInfoList[mSSID].mInUse = value; break; + default: break; + } + } + } + else { + SSIDInfo ssidInfo; + for ( int index = 0; index < fields.count(); index++ ) { // the list has to be sorted and the script is written that way. + QString field = fields[index].trimmed(); + switch (index) { // DO NOT USE default in this switch + case eSSID : mSSID = field; break; + case eBSSID :/* ssidInfo.mBSSID = field; */ break; // every row is different and not used now. + case eFREQ : ssidInfo.mFREQ_Max = QString("%1").arg(field).toInt(); break; + case eRATE : ssidInfo.mRATE_Max = QString("%1").arg(field).toInt(); break; + case eSIGNAL : ssidInfo.mSIGNAL_Max = QString("%1").arg(field).toInt(); break; + case eIN_USE : ssidInfo.mInUse = field.contains("*"); break; + case eSECURITY : ssidInfo.mSECURITY = field; + if ( field.isEmpty() ) { + ssidInfo.mSupported = false; + } else { + ssidInfo.mSupported = field.remove(QRegExp("(WPA[23])")).trimmed().isEmpty(); + } + break; + + case eWPA_FLAGS : + if ( field.contains("tkip") ) { mWPA_FLAGS += " TKIP" ; ssidInfo.mSupported = false; } + if ( field.contains("ccmp") ) { mWPA_FLAGS += " AES" ; } + if ( ! mWPA_FLAGS.isEmpty() ) { ssidInfo.mFLAGS = mWPA_FLAGS.trimmed(); } + break; + + case eRSN_FLAGS : + if ( field.contains("tkip") ) { mRSN_FLAGS += " TKIP" ; ssidInfo.mSupported = false; } + if ( field.contains("ccmp") ) { mRSN_FLAGS += " AES" ; } + if ( field.contains("sae" ) ) { mRSN_FLAGS += " SAE" ; } + if ( ! mRSN_FLAGS.isEmpty() ) { ssidInfo.mFLAGS = mRSN_FLAGS.trimmed(); } + break; + } + } + ssidInfo .mSSID = mSSID; + ssidInfoList[mSSID] = ssidInfo; + } + } + + _dataList.clear(); + for (const auto &ssid: qAsConst(ssidInfoList)) { + DataModel data; + data.mWifiMacAddress = ssid.mBSSID; + data.mWifiSSID = ssid.mSSID; + data.mWifiSecurityTypes = ssid.mSECURITY; + data.mWifiSignalLevel = ssid.mSIGNAL_Max; + data.mWifiSupported = ssid.mSupported; + data.mWifiConnected = ssid.mInUse ; + + dataAppend( data, ssid.mInUse, ssid.mSupported); + } } + +void View::VDevice::dataAppend(const DataModel &vData, bool vFirst, bool vSecond) { + beginInsertRows(QModelIndex(), rowCount(), rowCount()); + if ( vFirst && _dataList.count() >= 0 ) { _dataList.insert(0, vData); goto lOut; } + if ( vSecond && _dataList.count() >= 1 ) { _dataList.insert(1, vData); goto lOut; } + + _dataList.append( vData); +lOut: + endInsertRows(); +} + +void View::VDevice::dataClear() { + beginRemoveRows(QModelIndex(), 0, rowCount()); + _dataList.clear(); + endRemoveRows(); +} + +QVariant View::VDevice::data(const QModelIndex &vIndex, int vRole) const { + if (! vIndex.isValid() || vIndex.row() >= _dataList.count()) + return QVariant(); + + DataModel dataList = _dataList[vIndex.row()]; + + switch (vRole) { + // ----- WiFi + case eRole_WifiMacAddress : return dataList.mWifiMacAddress ; + case eRole_WifiSsid : return dataList.mWifiSSID ; + case eRole_WifiSecurityTypes : return dataList.mWifiSecurityTypes ; + case eRole_WifiSignalLevel : return dataList.mWifiSignalLevel ; + case eRole_WifiSupported : return dataList.mWifiSupported ; + case eRole_WifiConnected : return dataList.mWifiConnected ; + // ----- Bluetooth + case eRole_BLE_UNUSED : return ""; ; + } + + return QString("Wifi %1").arg(vIndex.row()); +}