/*! * * Copyright (c) 2021-2024 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 DeviceView.cpp * \author (last) Behrouz NematiPour * \date (last) 11-Sep-2023 * \author (original) Behrouz NematiPour * \date (original) 03-Jun-2021 * */ #include "DeviceView.h" // Qt // Project #include "ApplicationController.h" #include "GuiController.h" #include "DeviceController.h" #include "GuiGlobals.h" #include "encryption.h" #include "MWifiNetwork.h" VIEW_DEF_CLASS(VDevice) void VDevice::initConnections() { DEVICE_VIEW_INIT_CONNECTIONS_LIST connect(&_DeviceController , SIGNAL(didPOSTOSVersionData(QString)), this , SLOT( onPOSTOSVersionData(QString))); } // ================================================================================================== // ================================================= 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; emit didAttributeRequest(data); } void VDevice::onAttributeResponse(const DeviceBrightnessResponseData &vData) { // DEBUG : qDebug() << "HERE Response" << vData.mBrightnessPercent; if ( vData.mAccepted ) { brightness(vData.mBrightnessPercent); status(""); } 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); } accepted(vData.mAccepted); reason (vData.mReason ); // has to be the last one response(true); } // ================================================= Crypt Setup void VDevice::doInitCryptSetup() { // Nothing for now. } void VDevice::cryptSetupRequest(const QString &vCommand) { // DEBUG : qDebug() << "HERE Request" << vValue; cryptSetupEnabled(false); DeviceCryptSetupRequestData data; data.mCommand = vCommand; bool ok = false; data.mPassword = encryption::configurationsPassword( ok ); if ( ! ok ) { // not enough infromation to create a secure passowrd status(tr("Not enough secure information provided")); } else { emit didAttributeRequest(data); } } void VDevice::onAttributeResponse(const DeviceCryptSetupResponseData &vData) { // 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 // and the retrurned message can be the model message in vData.mMessage status(vData.mMessage); accepted(vData.mAccepted); reason (vData.mReason ); // Only set to enable if request failed with a reason reported, disable otherwise //DEBUG qDebug()<< "accepted " << vData.mAccepted << " reason "<< vData.mReason; cryptSetupEnabled (!vData.mAccepted && vData.mReason != 0); // has to be the last one response(true); } // ================================================= Bluetooth Paired Reset void VDevice::doInitBluetoothPairedReset() { // DEBUG : qDebug() << "HERE Init"; DeviceBluetoothPairedResetRequestData data; emit didAttributeRequest(data); } void VDevice::bluetoothPairedResetRequest(const quint8 &) { // DEBUG : qDebug() << "HERE Request"; // Nothing to be done here. This property will not be assigned. } void VDevice::onAttributeResponse(const DeviceBluetoothPairedResetResponseData &vData) { // DEBUG : qDebug() << "HERE Response" << vData.mAccepted << vData.mReason << vData.mMessage; // this has to be called to let Gui to set to old value that device controller provided. status(vData.mMessage); accepted(vData.mAccepted); reason (vData.mReason ); // has to be the last one emit bluetoothPairedResetChanged(vData.mReason); response(true); } // ================================================= Bluetooth Paired Query void VDevice::doInitBluetoothPairedQuery() { // DEBUG : qDebug() << "HERE Init"; DeviceBluetoothPairedQueryRequestData data; emit didAttributeRequest(data); } void VDevice::bluetoothPairedQueryRequest(const QStringList &) { // DEBUG : qDebug() << "HERE Request"; // Nothing to be done here. This property will not be assigned. } void VDevice::onAttributeResponse(const DeviceBluetoothPairedQueryResponseData &vData) { // DEBUG : qDebug() << "HERE Response" << vData.mAccepted << vData.mReason << vData.mMessage; // this has to be called to let Gui to set to old value that device controller provided. status(vData.mMessage); accepted(vData.mAccepted); reason (vData.mReason ); // has to be the last one emit bluetoothPairedQueryChanged(vData.mInfo); response(true); } // ================================================= RootSSHAccess void VDevice::doInitRootSSHAccess() { // DEBUG : qDebug() << "HERE Request" << vValue; DeviceRootSSHAccessRequestData data; data.mIsGet = true; emit didAttributeRequest(data); } void VDevice::rootSSHAccessRequest(const Qt::CheckState &vValue) { // DEBUG : qDebug() << "HERE Request" << vValue; DeviceRootSSHAccessRequestData data; data.mIsGet = false; data.mRootSSHAccess = vValue; emit didAttributeRequest(data); } void VDevice::onAttributeResponse(const DeviceRootSSHAccessResponseData &vData) { if ( vData.mAccepted ) { rootSSHAccess(vData.mRootSSHAccess); status(""); } else { // this has to be called to let Gui to set to old value that device controller provided. emit rootSSHAccessChanged(vData.mRootSSHAccess); status(vData.mMessage); } accepted(vData.mAccepted); reason (vData.mReason ); // has to be the last one response(true); } // ================================================= Factory Reset void VDevice::doInitFactoryReset() { // Nothing for now. } void VDevice::factoryResetRequest(const QString &vCommand) { Q_UNUSED(vCommand) // DEBUG : qDebug() << "HERE Request" << vCommand; factoryResetEnabled(false); DeviceFactoryResetRequestData data; emit didAttributeRequest(data); } void VDevice::onAttributeResponse(const DeviceFactoryResetResponseData &vData) { // QDEBUG : qDebug() << "HERE Response " << Q_FUNC_INFO << " accepted: " << vData.mAccepted; // this has to be called to let Gui to set to old value that device controller provided. status(vData.mMessage); accepted(vData.mAccepted); reason (vData.mReason ); factoryResetEnabled(isCompleteResponse(vData)); // has to be the last one response(true); } // ================================================= Decommission void VDevice::doInitDecommission() { // Nothing for now. } void VDevice::decommissionRequest(const QString &vCommand) { Q_UNUSED(vCommand) // DEBUG : qDebug() << "HERE Request" << vCommand; decommissionEnabled(true); DeviceDecommissionRequestData data; bool ok = false; data.mPassword = encryption::configurationsPassword( ok ); if ( ! ok ) { // not enough infromation to create a secure passowrd status(tr("Not enough secure information provided")); } else { emit didAttributeRequest(data); } emit didAttributeRequest(data); } void VDevice::onAttributeResponse(const DeviceDecommissionResponseData &vData) { //QDEBUG : qDebug() << "HERE Response " << Q_FUNC_INFO << " accepted: "<< vData.mAccepted << vData.mReason; // this has to be called to let Gui to set to old value that device controller provided. status(vData.mMessage); accepted(vData.mAccepted); reason (vData.mReason ); decommissionEnabled(isCompleteResponse(vData)); // has to be the last one response(true); } // ================================================= WifiList void VDevice::doInitWifiList() { wifiListRequest({}); } void VDevice::wifiListRequest(const QStringList &) { wifiListEnabled(false); DeviceWifiListRequestData data; emit didAttributeRequest(data); } void VDevice::onAttributeResponse(const DeviceWifiListResponseData &vData) { /// When calling a script, the last echo which is before the exit, is not where the script is completed. /// therefore we need to store the last one to use it when the script is sending the data and then exits, /// which is when we have the mComp;eted as true. static QString result; // DEBUG : qDebug() << __FUNCTION__ << vData.mMessage << result << vData.mCompleted; if ( vData.mCompleted ) { if ( vData.mAccepted ) { wifiList({ "SSID1" , "SSID2" }); status(""); wifiListEnabled(true); // TODO parseWifiListResult(result); status(vData.mMessage); } else { // this has to be called to let Gui to set to old value that device controller provided. // when not accepted could be a message only to update the screen. emit wifiListChanged({}); status(vData.mMessage); } } accepted(vData.mAccepted); reason (vData.mReason ); result = vData.mWifiList; // 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. */ QVariantList VDevice::parseWifiListResult(const QString &vResult) { 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 ; QString mFREQ_Max ; QString mRATE_Max ; quint16 mSIGNAL_Max ; QString mSECURITY ; QString mFLAGS ; // eWPA_FLAGS, eRSN_FLAGS are exclusive bool mIN_USE = false ; bool mSupported = true ; QString toString() { QStringList fields = QStringList() << mSSID << mBSSID << mFREQ_Max << mRATE_Max << QString::number(mSIGNAL_Max) << mSECURITY << mFLAGS << (mSupported ? "T" : "") << (mIN_USE ? "T" : ""); return fields.join(','); } }; QString mResult = vResult; SSIDInfo data; QHash mSSIDInfoList; // the Freq, Rate units QString mSSID; const QString mFREQ_Unit = " MHz"; const QString mRATE_Unit = " Mbit/s"; quint32 mFREQ_Value = 0; quint32 mRATE_Value = 0; // 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++ ) { QStringList fields = lines[row].split(','); if ( fields[eSSID].trimmed().isEmpty() ) continue; // hidden networks, or an incorrect entry QString mWPA_FLAGS; QString mRSN_FLAGS; 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(); if ( row ) { // if is not first row if ( mSSID == fields[eSSID] ) { // if is the same SSID just update necessary fields quint32 value = 0; switch (index) { case eFREQ : value = QString("%1").arg(field).toInt(); if ( mFREQ_Value < value ) { mFREQ_Value = value; } break; case eRATE : value = QString("%1").arg(field).toInt(); if ( mRATE_Value < value ) { mRATE_Value = value; } break; case eSIGNAL : value = QString("%1").arg(field).toInt(); if ( data.mSIGNAL_Max < value ) { data.mSIGNAL_Max = value; } break; case eIN_USE : data.mIN_USE = field.contains("*"); break; default: break; } } else { // else add the previous one and continue to the next. if ( ! mSSID.trimmed().isEmpty() ) { data.mSSID = mSSID; data.mFREQ_Max += QString::number(mFREQ_Value) + mFREQ_Unit; data.mRATE_Max += QString::number(mRATE_Value) + mRATE_Unit; mSSIDInfoList[mSSID] = data; qDebug() << data.toString(); } // clean up / reset data.mFREQ_Max = ""; data.mRATE_Max = ""; data.mFLAGS = ""; } } switch (index) { // DO NOT USE default in this switch case eSSID : mSSID = field; break; case eBSSID :/* data.mBSSID = field; */ break; // not directly used for now case eFREQ : mFREQ_Value = QString("%1").arg(field).toInt(); break; case eRATE : mRATE_Value = QString("%1").arg(field).toInt(); break; case eSIGNAL : data.mSIGNAL_Max = QString("%1").arg(field).toInt(); break; case eIN_USE : data.mIN_USE = field.contains("*"); break; case eSECURITY : data.mSECURITY = field; if ( field.isEmpty() ) { data.mSupported = false; } else { data.mSupported = field.remove(QRegExp("(WPA[23])")).trimmed().isEmpty(); } break; case eWPA_FLAGS : if ( field.contains("tkip") ) { mWPA_FLAGS += " TKIP" ; data.mSupported = false; } if ( field.contains("ccmp") ) { mWPA_FLAGS += " AES" ; } if ( ! mWPA_FLAGS.isEmpty() ) { data.mFLAGS = mWPA_FLAGS.trimmed(); } break; case eRSN_FLAGS : if ( field.contains("tkip") ) { mRSN_FLAGS += " TKIP" ; data.mSupported = false; } if ( field.contains("ccmp") ) { mRSN_FLAGS += " AES" ; } if ( field.contains("sae" ) ) { mRSN_FLAGS += " SAE" ; } if ( ! mRSN_FLAGS.isEmpty() ) { data.mFLAGS = mRSN_FLAGS.trimmed(); } break; } } } return {}; }