diff --git a/autoapp/UI/ConnectDialog.cpp b/autoapp/UI/ConnectDialog.cpp index 479db07..210097e 100644 --- a/autoapp/UI/ConnectDialog.cpp +++ b/autoapp/UI/ConnectDialog.cpp @@ -4,116 +4,125 @@ namespace autoapp { -namespace ui -{ - -ConnectDialog::ConnectDialog(boost::asio::io_service& ioService, aasdk::tcp::ITCPWrapper& tcpWrapper, openauto::configuration::IRecentAddressesList& recentAddressesList, QWidget *parent) - : QDialog(parent) - , ioService_(ioService) - , tcpWrapper_(tcpWrapper) - , recentAddressesList_(recentAddressesList) - , ui_(new Ui::ConnectDialog) -{ - qRegisterMetaType("aasdk::tcp::ITCPEndpoint::SocketPointer"); - qRegisterMetaType("std::string"); - - ui_->setupUi(this); - connect(ui_->pushButtonCancel, &QPushButton::clicked, this, &ConnectDialog::close); - connect(ui_->pushButtonConnect, &QPushButton::clicked, this, &ConnectDialog::onConnectButtonClicked); - connect(ui_->listViewRecent, &QListView::clicked, this, &ConnectDialog::onRecentAddressClicked); - connect(this, &ConnectDialog::connectionSucceed, this, &ConnectDialog::onConnectionSucceed); - connect(this, &ConnectDialog::connectionFailed, this, &ConnectDialog::onConnectionFailed); - - ui_->listViewRecent->setModel(&recentAddressesModel_); - this->loadRecentList(); -} - -ConnectDialog::~ConnectDialog() -{ - delete ui_; -} - -void ConnectDialog::onConnectButtonClicked() -{ - this->setControlsEnabledStatus(false); - - const auto& ipAddress = ui_->lineEditIPAddress->text().toStdString(); - auto socket = std::make_shared(ioService_); - - try + namespace ui { - tcpWrapper_.asyncConnect(*socket, ipAddress, 5277, std::bind(&ConnectDialog::connectHandler, this, std::placeholders::_1, ipAddress, socket)); - } - catch(const boost::system::system_error& se) - { - emit connectionFailed(QString(se.what())); + + ConnectDialog::ConnectDialog(boost::asio::io_service &ioService, aasdk::tcp::ITCPWrapper &tcpWrapper, openauto::configuration::IRecentAddressesList &recentAddressesList, QWidget *parent) + : QDialog(parent), ioService_(ioService), tcpWrapper_(tcpWrapper), recentAddressesList_(recentAddressesList), ui_(new Ui::ConnectDialog) + { + qRegisterMetaType("aasdk::tcp::ITCPEndpoint::SocketPointer"); + qRegisterMetaType("std::string"); + + ui_->setupUi(this); + connect(ui_->pushButtonCancel, &QPushButton::clicked, this, &ConnectDialog::close); + connect(ui_->pushButtonConnect, &QPushButton::clicked, this, &ConnectDialog::onConnectButtonClicked); + connect(ui_->listViewRecent, &QListView::clicked, this, &ConnectDialog::onRecentAddressClicked); + connect(this, &ConnectDialog::connectionSucceed, this, &ConnectDialog::onConnectionSucceed); + connect(this, &ConnectDialog::connectionFailed, this, &ConnectDialog::onConnectionFailed); + + ui_->listViewRecent->setModel(&recentAddressesModel_); + this->loadRecentList(); + } + + ConnectDialog::~ConnectDialog() + { + delete ui_; + } + + void ConnectDialog::onConnectButtonClicked() + { + this->setControlsEnabledStatus(false); + + const auto &ipAddress = ui_->lineEditIPAddress->text().toStdString(); + auto socket = std::make_shared(ioService_); + + try + { + tcpWrapper_.asyncConnect(*socket, ipAddress, 5277, std::bind(&ConnectDialog::connectHandler, this, std::placeholders::_1, ipAddress, socket)); + } + catch (const boost::system::system_error &se) + { + emit connectionFailed(QString(se.what())); + } + } + + void ConnectDialog::connectHandler(const boost::system::error_code &ec, const std::string &ipAddress, aasdk::tcp::ITCPEndpoint::SocketPointer socket) + { + if (!ec) + { + emit connectionSucceed(std::move(socket), ipAddress); + this->close(); + } + else + { + emit connectionFailed(QString::fromStdString(ec.message())); + } + } + + void ConnectDialog::onConnectionSucceed(aasdk::tcp::ITCPEndpoint::SocketPointer, const std::string &ipAddress) + { + this->insertIpAddress(ipAddress); + this->setControlsEnabledStatus(true); + } + + void ConnectDialog::onConnectionFailed(const QString &message) + { + this->setControlsEnabledStatus(true); + + QMessageBox errorMessage(QMessageBox::Critical, "Connect error", message, QMessageBox::Ok); + errorMessage.setWindowFlags(Qt::WindowStaysOnTopHint); + errorMessage.exec(); + } + + void ConnectDialog::onRecentAddressClicked(const QModelIndex &index) + { + const auto &recentAddressesList = recentAddressesList_.getList(); + + if (static_cast(index.row()) <= recentAddressesList.size()) + { + ui_->lineEditIPAddress->setText(QString::fromStdString(recentAddressesList.at(index.row()))); + } + } + + void ConnectDialog::setControlsEnabledStatus(bool status) + { + ui_->pushButtonConnect->setVisible(status); + ui_->pushButtonCancel->setEnabled(status); + ui_->lineEditIPAddress->setEnabled(status); + ui_->listViewRecent->setEnabled(status); + } + + void ConnectDialog::loadRecentList() + { + QStringList stringList; + const auto &configList = recentAddressesList_.getList(); + + for (const auto &element : configList) + { + stringList.append(QString::fromStdString(element)); + } + + recentAddressesModel_.setStringList(stringList); + } + + void ConnectDialog::insertIpAddress(const std::string &ipAddress) + { + recentAddressesList_.insertAddress(ipAddress); + this->loadRecentList(); + } + + void ConnectDialog::connectToAddress(const QString &ip) + { + const auto &ipAddress = ip.toStdString(); + auto socket = std::make_shared(ioService_); + try + { + tcpWrapper_.asyncConnect(*socket, ipAddress, 5277, std::bind(&ConnectDialog::connectHandler, this, std::placeholders::_1, ipAddress, socket)); + } + catch (const boost::system::system_error &se) + { + emit connectionFailed(QString(se.what())); + } + } } } - -void ConnectDialog::connectHandler(const boost::system::error_code& ec, const std::string& ipAddress, aasdk::tcp::ITCPEndpoint::SocketPointer socket) -{ - if(!ec) - { - emit connectionSucceed(std::move(socket), ipAddress); - this->close(); - } - else - { - emit connectionFailed(QString::fromStdString(ec.message())); - } -} - -void ConnectDialog::onConnectionSucceed(aasdk::tcp::ITCPEndpoint::SocketPointer, const std::string& ipAddress) -{ - this->insertIpAddress(ipAddress); - this->setControlsEnabledStatus(true); -} - -void ConnectDialog::onConnectionFailed(const QString& message) -{ - this->setControlsEnabledStatus(true); - - QMessageBox errorMessage(QMessageBox::Critical, "Connect error", message, QMessageBox::Ok); - errorMessage.setWindowFlags(Qt::WindowStaysOnTopHint); - errorMessage.exec(); -} - -void ConnectDialog::onRecentAddressClicked(const QModelIndex& index) -{ - const auto& recentAddressesList = recentAddressesList_.getList(); - - if(static_cast(index.row()) <= recentAddressesList.size()) - { - ui_->lineEditIPAddress->setText(QString::fromStdString(recentAddressesList.at(index.row()))); - } -} - -void ConnectDialog::setControlsEnabledStatus(bool status) -{ - ui_->pushButtonConnect->setVisible(status); - ui_->pushButtonCancel->setEnabled(status); - ui_->lineEditIPAddress->setEnabled(status); - ui_->listViewRecent->setEnabled(status); -} - -void ConnectDialog::loadRecentList() -{ - QStringList stringList; - const auto& configList = recentAddressesList_.getList(); - - for(const auto& element : configList) - { - stringList.append(QString::fromStdString(element)); - } - - recentAddressesModel_.setStringList(stringList); -} - -void ConnectDialog::insertIpAddress(const std::string& ipAddress) -{ - recentAddressesList_.insertAddress(ipAddress); - this->loadRecentList(); -} - -} -} diff --git a/autoapp/UI/MainWindow.cpp b/autoapp/UI/MainWindow.cpp index 3eda26a..45b05de 100644 --- a/autoapp/UI/MainWindow.cpp +++ b/autoapp/UI/MainWindow.cpp @@ -17,12 +17,8 @@ */ #include -#include #include -#include -#include #include -#include #include "autoapp/UI/MainWindow.hpp" #include "ui_mainwindow.h" @@ -32,77 +28,25 @@ namespace autoapp namespace ui { MainWindow::MainWindow(QWidget *parent) - : QMainWindow(parent), ui_(new Ui::MainWindow), webSocket(new QWebSocket), - reconnectTimer(new QTimer(this)), - shuttingDown(false) + : QMainWindow(parent), ui_(new Ui::MainWindow) { ui_->setupUi(this); connect(ui_->pushButtonSettings, &QPushButton::clicked, this, &MainWindow::openSettings); connect(ui_->pushButtonExit, &QPushButton::clicked, this, &MainWindow::exit); connect(ui_->pushButtonToggleCursor, &QPushButton::clicked, this, &MainWindow::toggleCursor); connect(ui_->pushButtonWirelessConnection, &QPushButton::clicked, this, &MainWindow::openConnectDialog); - - // RADIO WEBSOCKET STUFF - reconnectTimer->setSingleShot(true); - reconnectTimer->setInterval(3000); - - connect(reconnectTimer, &QTimer::timeout, this, &MainWindow::connectWebSocket); - - connect(webSocket, &QWebSocket::connected, this, [this]() - { - qDebug() << "WebSocket connected"; - webSocket->sendTextMessage(QStringLiteral("Hello from MainWindow WebSocket!")); }); - - connect(webSocket, &QWebSocket::textMessageReceived, this, [this](const QString &message) - { - qDebug() << "Message received:" << message; - handleIncomingMessage(message); }); - - connect(webSocket, &QWebSocket::disconnected, this, [this]() - { - qDebug() << "WebSocket disconnected"; - if (!shuttingDown) { - qDebug() << "Attempting to reconnect in 3 seconds..."; - reconnectTimer->start(); - } }); - - connect(webSocket, QOverload::of(&QWebSocket::error), - this, [this](QAbstractSocket::SocketError) - { qDebug() << "WebSocket error:" << webSocket->errorString(); }); - - connectWebSocket(); } MainWindow::~MainWindow() { - shuttingDown = true; - webSocket->abort(); - webSocket->deleteLater(); delete ui_; } } } -void autoapp::ui::MainWindow::connectWebSocket() +void autoapp::ui::MainWindow::handleIncomingMessage(const QJsonObject &rootObj) { - QUrl url(QStringLiteral("ws://127.0.0.1:5000")); // Change to your real server - qDebug() << "Connecting to WebSocket:" << url; - webSocket->open(url); -} - -void autoapp::ui::MainWindow::handleIncomingMessage(const QString &message) -{ - qDebug() << "[Handler] Processing message:" << message; - - QJsonParseError error; - QJsonDocument doc = QJsonDocument::fromJson(message.toUtf8(), &error); - if (error.error != QJsonParseError::NoError) { - qDebug() << "JSON parse error:" << error.errorString(); - return; - } - - QJsonObject rootObj = doc.object(); if (rootObj.contains("bluetooth")) { ui_->stackedWidget->setCurrentIndex(0); QJsonObject btObj = rootObj["bluetooth"].toObject(); @@ -121,5 +65,8 @@ void autoapp::ui::MainWindow::handleIncomingMessage(const QString &message) ui_->radioScreen->setText(radioObj["screen"].toString()); ui_->radioPreset->setText(radioObj["preset"].toString()); ui_->radioSecondLine->setText(radioObj["second"].toString()); + } else if (rootObj.contains("connect_wireless_aa")) { + QJsonObject aaObj = rootObj["connect_wireless_aa"].toObject(); + //connectWirelessAndroidAuto(aaObj["address"].toString()); } -} +} \ No newline at end of file diff --git a/autoapp/autoapp.cpp b/autoapp/autoapp.cpp index 3cae84e..949ad42 100644 --- a/autoapp/autoapp.cpp +++ b/autoapp/autoapp.cpp @@ -18,6 +18,11 @@ #include #include +#include +#include +#include +#include +#include #include "aasdk/USB/USBHub.hpp" #include "aasdk/USB/ConnectedAccessoriesEnumerator.hpp" #include "aasdk/USB/AccessoryModeQueryChain.hpp" @@ -38,12 +43,13 @@ using namespace openauto; using ThreadPool = std::vector; -void startUSBWorkers(boost::asio::io_service& ioService, libusb_context* usbContext, ThreadPool& threadPool) +void startUSBWorkers(boost::asio::io_service &ioService, libusb_context *usbContext, ThreadPool &threadPool) { - auto usbWorker = [&ioService, usbContext]() { + auto usbWorker = [&ioService, usbContext]() + { timeval libusbEventTimeout{180, 0}; - while(!ioService.stopped()) + while (!ioService.stopped()) { libusb_handle_events_timeout_completed(usbContext, &libusbEventTimeout, nullptr); } @@ -55,9 +61,10 @@ void startUSBWorkers(boost::asio::io_service& ioService, libusb_context* usbCont threadPool.emplace_back(usbWorker); } -void startIOServiceWorkers(boost::asio::io_service& ioService, ThreadPool& threadPool) +void startIOServiceWorkers(boost::asio::io_service &ioService, ThreadPool &threadPool) { - auto ioServiceWorker = [&ioService]() { + auto ioServiceWorker = [&ioService]() + { ioService.run(); }; @@ -67,10 +74,10 @@ void startIOServiceWorkers(boost::asio::io_service& ioService, ThreadPool& threa threadPool.emplace_back(ioServiceWorker); } -int main(int argc, char* argv[]) +int main(int argc, char *argv[]) { - libusb_context* usbContext; - if(libusb_init(&usbContext) != 0) + libusb_context *usbContext; + if (libusb_init(&usbContext) != 0) { OPENAUTO_LOG(error) << "[OpenAuto] libusb init failed."; return 1; @@ -97,15 +104,16 @@ int main(int argc, char* argv[]) autoapp::ui::ConnectDialog connectDialog(ioService, tcpWrapper, recentAddressesList); connectDialog.setWindowFlags(Qt::WindowStaysOnTopHint); - QObject::connect(&mainWindow, &autoapp::ui::MainWindow::exit, []() { std::exit(0); }); + QObject::connect(&mainWindow, &autoapp::ui::MainWindow::exit, []() + { std::exit(0); }); QObject::connect(&mainWindow, &autoapp::ui::MainWindow::openSettings, &settingsWindow, &autoapp::ui::SettingsWindow::showFullScreen); QObject::connect(&mainWindow, &autoapp::ui::MainWindow::openConnectDialog, &connectDialog, &autoapp::ui::ConnectDialog::exec); qApplication.setOverrideCursor(Qt::BlankCursor); - QObject::connect(&mainWindow, &autoapp::ui::MainWindow::toggleCursor, [&qApplication]() { + QObject::connect(&mainWindow, &autoapp::ui::MainWindow::toggleCursor, [&qApplication]() + { const auto cursor = qApplication.overrideCursor()->shape() == Qt::BlankCursor ? Qt::ArrowCursor : Qt::BlankCursor; - qApplication.setOverrideCursor(cursor); - }); + qApplication.setOverrideCursor(cursor); }); mainWindow.showFullScreen(); @@ -119,12 +127,62 @@ int main(int argc, char* argv[]) auto connectedAccessoriesEnumerator(std::make_shared(usbWrapper, ioService, queryChainFactory)); auto app = std::make_shared(ioService, usbWrapper, tcpWrapper, androidAutoEntityFactory, std::move(usbHub), std::move(connectedAccessoriesEnumerator)); - QObject::connect(&connectDialog, &autoapp::ui::ConnectDialog::connectionSucceed, [&app](auto socket) { - app->start(std::move(socket)); - }); + QObject::connect(&connectDialog, &autoapp::ui::ConnectDialog::connectionSucceed, [&app](auto socket) + { app->start(std::move(socket)); }); app->waitForDevice(true); + QWebSocket webSocket; + QTimer reconnectTimer; + const QUrl websocketUrl(QStringLiteral("ws://127.0.0.1:5959/ws")); + + auto tryConnect = [&webSocket, &websocketUrl]() + { + if (webSocket.state() != QAbstractSocket::ConnectedState && + webSocket.state() != QAbstractSocket::ConnectingState) + { + qDebug() << "[WebSocket] Attempting to connect to" << websocketUrl.toString(); + webSocket.open(websocketUrl); + } + }; + + // Connect events + QObject::connect(&webSocket, &QWebSocket::connected, [&]() + { + qDebug() << "[WebSocket] Connected."; + webSocket.sendTextMessage("Hello from OpenAuto WebSocket client!"); + reconnectTimer.stop(); }); + + QObject::connect(&webSocket, &QWebSocket::disconnected, [&]() + { + qDebug() << "[WebSocket] Disconnected. Will retry..."; + reconnectTimer.start(3000); }); + + QObject::connect(&webSocket, &QWebSocket::textMessageReceived, [&mainWindow, &connectDialog](const QString &message) + { + QJsonParseError error; + QJsonDocument doc = QJsonDocument::fromJson(message.toUtf8(), &error); + if (error.error != QJsonParseError::NoError) { + qDebug() << "JSON parse error:" << error.errorString(); + return; + } + QJsonObject rootObj = doc.object(); + if (rootObj.contains("wireless_aa_ip")) { + QString ipAddr = rootObj["wireless_aa_ip"].toString(); + connectDialog.connectToAddress(ipAddr); + } + else if (rootObj.contains("button")) { + + } + else{ + mainWindow.handleIncomingMessage(rootObj); + } }); + + reconnectTimer.setInterval(3000); + reconnectTimer.setSingleShot(true); + QObject::connect(&reconnectTimer, &QTimer::timeout, tryConnect); + tryConnect(); + auto result = qApplication.exec(); std::for_each(threadPool.begin(), threadPool.end(), std::bind(&std::thread::join, std::placeholders::_1)); diff --git a/include/autoapp/UI/ConnectDialog.hpp b/include/autoapp/UI/ConnectDialog.hpp index f9fcb9f..1307f36 100644 --- a/include/autoapp/UI/ConnectDialog.hpp +++ b/include/autoapp/UI/ConnectDialog.hpp @@ -22,6 +22,7 @@ class ConnectDialog : public QDialog public: explicit ConnectDialog(boost::asio::io_service& ioService, aasdk::tcp::ITCPWrapper& tcpWrapper, openauto::configuration::IRecentAddressesList& recentAddressesList, QWidget *parent = nullptr); ~ConnectDialog() override; + void connectToAddress(const QString& ip); signals: void connectToDevice(const QString& ipAddress); diff --git a/include/autoapp/UI/MainWindow.hpp b/include/autoapp/UI/MainWindow.hpp index 0f508e0..8b7c263 100644 --- a/include/autoapp/UI/MainWindow.hpp +++ b/include/autoapp/UI/MainWindow.hpp @@ -20,7 +20,6 @@ #include #include -#include namespace Ui { @@ -38,6 +37,7 @@ namespace autoapp public: explicit MainWindow(QWidget *parent = nullptr); ~MainWindow() override; + void handleIncomingMessage(const QJsonObject &rootObj); signals: void exit(); @@ -46,15 +46,9 @@ namespace autoapp void openConnectDialog(); private slots: - void connectWebSocket(); - void handleIncomingMessage(const QString &message); private: Ui::MainWindow *ui_; - QWebSocket *webSocket; - QTimer *reconnectTimer; - bool shuttingDown; }; - } } diff --git a/openauto/Configuration/Configuration.cpp b/openauto/Configuration/Configuration.cpp index 900ec58..acaabcc 100644 --- a/openauto/Configuration/Configuration.cpp +++ b/openauto/Configuration/Configuration.cpp @@ -97,7 +97,7 @@ void Configuration::load() videoMargins_ = QRect(0, 0, iniConfig.get(cVideoMarginWidth, 0), iniConfig.get(cVideoMarginHeight, 0)); whitescreenWorkaround_ = iniConfig.get(cVideoWhitescreenWorkaround, true); - enableTouchscreen_ = iniConfig.get(cInputEnableTouchscreenKey, true); + enableTouchscreen_ = iniConfig.get(cInputEnableTouchscreenKey, false); this->readButtonCodes(iniConfig); bluetoothAdapterType_ = static_cast(iniConfig.get(cBluetoothAdapterTypeKey, @@ -134,7 +134,7 @@ void Configuration::reset() omxLayerIndex_ = 1; videoMargins_ = QRect(0, 0, 0, 0); whitescreenWorkaround_ = true; - enableTouchscreen_ = true; + enableTouchscreen_ = false; buttonCodes_.clear(); bluetoothAdapterType_ = BluetoothAdapterType::NONE; bluetoothRemoteAdapterAddress_ = "";