diff --git a/include/f1x/openauto/autoapp/Projection/LocalBluetoothDevice.hpp b/include/f1x/openauto/autoapp/Projection/LocalBluetoothDevice.hpp index 73ec688..f261228 100644 --- a/include/f1x/openauto/autoapp/Projection/LocalBluetoothDevice.hpp +++ b/include/f1x/openauto/autoapp/Projection/LocalBluetoothDevice.hpp @@ -38,17 +38,8 @@ public: std::string getAdapterAddress() const override; bool isAvailable() const override; -signals: - void startPairing(const QString& address, PairingPromise::Pointer promise); - private slots: - void createBluetoothLocalDevice(); - void onStartPairing(const QString& address, PairingPromise::Pointer promise); - void onPairingDisplayConfirmation(const QBluetoothAddress &address, QString pin); - void onPairingDisplayPinCode(const QBluetoothAddress &address, QString pin); - void onPairingFinished(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing); - void onError(QBluetoothLocalDevice::Error error); - void onHostModeStateChanged(QBluetoothLocalDevice::HostMode state); + void createBluetoothLocalDevice(const QString &adapterAddress); private: mutable std::mutex mutex_; diff --git a/include/f1x/openauto/autoapp/UI/SettingsWindow.hpp b/include/f1x/openauto/autoapp/UI/SettingsWindow.hpp index bedaad4..6aa3d20 100644 --- a/include/f1x/openauto/autoapp/UI/SettingsWindow.hpp +++ b/include/f1x/openauto/autoapp/UI/SettingsWindow.hpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #ifdef MAC_OS #else @@ -98,7 +99,16 @@ private: void saveButtonCheckBoxes(); void saveButtonCheckBox(const QCheckBox* checkBox, configuration::IConfiguration::ButtonCodes& buttonCodes, aap_protobuf::service::media::sink::message::KeyCode buttonCode); void setButtonCheckBoxes(bool value); - +#ifdef Q_OS_LINUX + void populateBluetoothComboBoxLinux(QComboBox *comboBoxBluetooth); +#endif +#ifdef Q_OS_WIN + void populateBluetoothComboBoxWindows(QComboBox *comboBoxBluetooth); +#endif +#ifdef Q_OS_MAC + void populateBluetoothComboBoxMac(QComboBox *comboBoxBluetooth); +#endif + void populateBluetoothComboBox(QComboBox *comboBoxBluetooth); Ui::SettingsWindow* ui_; configuration::IConfiguration::Pointer configuration_; diff --git a/include/f1x/openauto/btservice/AndroidBluetoothServer.hpp b/include/f1x/openauto/btservice/AndroidBluetoothServer.hpp index 24b4f7f..72c9815 100644 --- a/include/f1x/openauto/btservice/AndroidBluetoothServer.hpp +++ b/include/f1x/openauto/btservice/AndroidBluetoothServer.hpp @@ -33,47 +33,46 @@ #include #include -namespace f1x { - namespace openauto { - namespace btservice { - class AndroidBluetoothServer : public QObject, public IAndroidBluetoothServer { - Q_OBJECT +namespace f1x::openauto::btservice { - public: - AndroidBluetoothServer(autoapp::configuration::IConfiguration::Pointer configuration); + class AndroidBluetoothServer : public QObject, public IAndroidBluetoothServer { + Q_OBJECT - uint16_t start(const QBluetoothAddress &address) override; + public: + AndroidBluetoothServer(autoapp::configuration::IConfiguration::Pointer configuration); - private slots: + uint16_t start(const QBluetoothAddress &address) override; - void onClientConnected(); + private slots: - private: - std::unique_ptr rfcommServer_; - QBluetoothSocket *socket = nullptr; - autoapp::configuration::IConfiguration::Pointer configuration_; + void onClientConnected(); - void readSocket(); + private: + std::unique_ptr rfcommServer_; + QBluetoothSocket *socket = nullptr; + autoapp::configuration::IConfiguration::Pointer configuration_; - QByteArray buffer; + void readSocket(); - void handleWifiInfoRequest(QByteArray &buffer, uint16_t length); + QByteArray buffer; - void handleWifiVersionResponse(QByteArray &buffer, uint16_t length); + void handleWifiInfoRequest(QByteArray &buffer, uint16_t length); - void handleWifiConnectionStatus(QByteArray &buffer, uint16_t length); + void handleWifiVersionResponse(QByteArray &buffer, uint16_t length); - void handleWifiStartResponse(QByteArray &buffer, uint16_t length); + void handleWifiConnectionStatus(QByteArray &buffer, uint16_t length); - void sendMessage(const google::protobuf::Message &message, uint16_t type); + void handleWifiStartResponse(QByteArray &buffer, uint16_t length); + + void sendMessage(const google::protobuf::Message &message, uint16_t type); - const ::std::string getIP4_(const QString intf); + const ::std::string getIP4_(const QString intf); - void DecodeProtoMessage(const std::string &proto_data); - }; + void DecodeProtoMessage(const std::string &proto_data); + }; - } - } } + + diff --git a/include/f1x/openauto/btservice/AndroidBluetoothService.hpp b/include/f1x/openauto/btservice/AndroidBluetoothService.hpp index ebbb860..64e0abb 100644 --- a/include/f1x/openauto/btservice/AndroidBluetoothService.hpp +++ b/include/f1x/openauto/btservice/AndroidBluetoothService.hpp @@ -21,11 +21,7 @@ #include #include -namespace f1x -{ -namespace openauto -{ -namespace btservice +namespace f1x::openauto::btservice { class AndroidBluetoothService: public IAndroidBluetoothService @@ -41,5 +37,5 @@ private: }; } -} -} + + diff --git a/include/f1x/openauto/btservice/BluetoothHandler.hpp b/include/f1x/openauto/btservice/BluetoothHandler.hpp new file mode 100644 index 0000000..236b461 --- /dev/null +++ b/include/f1x/openauto/btservice/BluetoothHandler.hpp @@ -0,0 +1,38 @@ +// +// Created by Simon Dean on 26/11/2024. +// + +#ifndef OPENAUTO_BLUETOOTHHANDLER_HPP +#define OPENAUTO_BLUETOOTHHANDLER_HPP + +#include +#include +#include + + +namespace f1x::openauto::btservice { + + class BluetoothHandler : public QObject, public IBluetoothHandler { + Q_OBJECT + public: + BluetoothHandler(autoapp::configuration::IConfiguration::Pointer configuration); + + private slots: + void onPairingDisplayPinCode(const QBluetoothAddress &address, QString pin); + + void onPairingDisplayConfirmation(const QBluetoothAddress &address, QString pin); + + void onPairingFinished(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing); + + void onError(QBluetoothLocalDevice::Error error); + + void onHostModeStateChanged(QBluetoothLocalDevice::HostMode state); + + private: + std::unique_ptr localDevice_; + autoapp::configuration::IConfiguration::Pointer configuration_; + }; +} + + +#endif //OPENAUTO_BLUETOOTHHANDLER_HPP diff --git a/include/f1x/openauto/btservice/IAndroidBluetoothServer.hpp b/include/f1x/openauto/btservice/IAndroidBluetoothServer.hpp index c798567..d626bea 100644 --- a/include/f1x/openauto/btservice/IAndroidBluetoothServer.hpp +++ b/include/f1x/openauto/btservice/IAndroidBluetoothServer.hpp @@ -20,11 +20,9 @@ #include -namespace f1x -{ -namespace openauto -{ -namespace btservice + + +namespace f1x::openauto::btservice { class IAndroidBluetoothServer @@ -36,5 +34,5 @@ public: }; } -} -} + + diff --git a/include/f1x/openauto/btservice/IAndroidBluetoothService.hpp b/include/f1x/openauto/btservice/IAndroidBluetoothService.hpp index 71352c9..0868d83 100644 --- a/include/f1x/openauto/btservice/IAndroidBluetoothService.hpp +++ b/include/f1x/openauto/btservice/IAndroidBluetoothService.hpp @@ -20,11 +20,7 @@ #include -namespace f1x -{ -namespace openauto -{ -namespace btservice +namespace f1x::openauto::btservice { class IAndroidBluetoothService @@ -37,5 +33,5 @@ public: }; } -} -} + + diff --git a/include/f1x/openauto/btservice/IBluetoothHandler.hpp b/include/f1x/openauto/btservice/IBluetoothHandler.hpp new file mode 100644 index 0000000..d3430c7 --- /dev/null +++ b/include/f1x/openauto/btservice/IBluetoothHandler.hpp @@ -0,0 +1,24 @@ +// +// Created by Simon Dean on 26/11/2024. +// + +#ifndef OPENAUTO_IBLUETOOTHHANDLER_HPP +#define OPENAUTO_IBLUETOOTHHANDLER_HPP + +#include +#include + +namespace f1x::openauto::btservice { + + class IBluetoothHandler + { + public: + virtual ~IBluetoothHandler() = default; + + }; + +} + + + +#endif //OPENAUTO_IBLUETOOTHHANDLER_HPP diff --git a/src/autoapp/Projection/DummyBluetoothDevice.cpp b/src/autoapp/Projection/DummyBluetoothDevice.cpp index 4147683..10a54c3 100644 --- a/src/autoapp/Projection/DummyBluetoothDevice.cpp +++ b/src/autoapp/Projection/DummyBluetoothDevice.cpp @@ -34,12 +34,7 @@ bool DummyBluetoothDevice::isPaired(const std::string&) const return false; } -void DummyBluetoothDevice::pair(const std::string&, PairingPromise::Pointer promise) -{ - promise->reject(); -} - -std::string DummyBluetoothDevice::getLocalAddress() const +std::string DummyBluetoothDevice::getAdapterAddress() const { return ""; } diff --git a/src/autoapp/Projection/LocalBluetoothDevice.cpp b/src/autoapp/Projection/LocalBluetoothDevice.cpp index 5d3be0b..aebc8bd 100644 --- a/src/autoapp/Projection/LocalBluetoothDevice.cpp +++ b/src/autoapp/Projection/LocalBluetoothDevice.cpp @@ -19,159 +19,53 @@ #include #include #include -#include #include namespace f1x::openauto::autoapp::projection { -LocalBluetoothDevice::LocalBluetoothDevice() -{ + LocalBluetoothDevice::LocalBluetoothDevice(const QString &adapterAddress, QObject *parent) : QObject(parent) { qRegisterMetaType("PairingPromise::Pointer"); this->moveToThread(QApplication::instance()->thread()); - connect(this, &LocalBluetoothDevice::startPairing, this, &LocalBluetoothDevice::onStartPairing, Qt::QueuedConnection); - QMetaObject::invokeMethod(this, "createBluetoothLocalDevice", Qt::BlockingQueuedConnection); -} -void LocalBluetoothDevice::createBluetoothLocalDevice() -{ + QMetaObject::invokeMethod(this, "createBluetoothLocalDevice", Qt::BlockingQueuedConnection, + Q_ARG(QString, adapterAddress)); + + } + + void LocalBluetoothDevice::createBluetoothLocalDevice(const QString &adapterAddress) { OPENAUTO_LOG(info) << "[LocalBluetoothDevice] create."; - localDevice_ = std::make_unique(QBluetoothAddress()); - connect(localDevice_.get(), &QBluetoothLocalDevice::pairingDisplayConfirmation, this, &LocalBluetoothDevice::onPairingDisplayConfirmation); - connect(localDevice_.get(), &QBluetoothLocalDevice::pairingDisplayPinCode, this, &LocalBluetoothDevice::onPairingDisplayPinCode); - connect(localDevice_.get(), &QBluetoothLocalDevice::pairingFinished, this, &LocalBluetoothDevice::onPairingFinished); - connect(localDevice_.get(), &QBluetoothLocalDevice::error, this, &LocalBluetoothDevice::onError); - connect(localDevice_.get(), &QBluetoothLocalDevice::hostModeStateChanged, this, &LocalBluetoothDevice::onHostModeStateChanged); + QBluetoothAddress address(adapterAddress); + localDevice_ = std::make_unique(address); - localDevice_->powerOn(); - localDevice_->setHostMode(QBluetoothLocalDevice::HostDiscoverable); + // Pairing signals are being handled by btservice -} + } -void LocalBluetoothDevice::stop() -{ + void LocalBluetoothDevice::stop() { std::lock_guard lock(mutex_); - if(pairingPromise_ != nullptr) - { - pairingPromise_->reject(); - pairingPromise_.reset(); - pairingAddress_ = QBluetoothAddress(); - } -} + } -bool LocalBluetoothDevice::isPaired(const std::string& address) const -{ + bool LocalBluetoothDevice::isPaired(const std::string &address) const { std::lock_guard lock(mutex_); - return localDevice_->pairingStatus(QBluetoothAddress(QString::fromStdString(address))) != QBluetoothLocalDevice::Unpaired; -} - -void LocalBluetoothDevice::pair(const std::string& address, PairingPromise::Pointer promise) -{ - emit startPairing(QString::fromStdString(address), std::move(promise)); -} + return localDevice_->pairingStatus(QBluetoothAddress(QString::fromStdString(address))) != + QBluetoothLocalDevice::Unpaired; + } std::string LocalBluetoothDevice::getAdapterAddress() const { std::lock_guard lock(mutex_); return localDevice_->isValid() ? localDevice_->address().toString().toStdString() : ""; -} + } -bool LocalBluetoothDevice::isAvailable() const -{ + bool LocalBluetoothDevice::isAvailable() const { std::lock_guard lock(mutex_); return localDevice_->isValid(); + } } -void LocalBluetoothDevice::onStartPairing(const QString& address, PairingPromise::Pointer promise) -{ - OPENAUTO_LOG(debug) << "[LocalBluetoothDevice] onStartPairing, address: " << address.toStdString(); - std::lock_guard lock(mutex_); - - if(!localDevice_->isValid()) - { - promise->reject(); - } - else - { - if(pairingPromise_ != nullptr) - { - pairingPromise_->reject(); - } - - pairingAddress_ = QBluetoothAddress(address); - pairingPromise_ = std::move(promise); - localDevice_->requestPairing(pairingAddress_, QBluetoothLocalDevice::AuthorizedPaired); - } -} - -void LocalBluetoothDevice::onPairingDisplayConfirmation(const QBluetoothAddress &address, QString pin) -{ - OPENAUTO_LOG(info) << "[LocalBluetoothDevice] onPairingDisplayConfirmation, address: " << address.toString().toStdString() - << ", pin: " << pin.toStdString(); - - std::lock_guard lock(mutex_); - localDevice_->pairingConfirmation(address == pairingAddress_); -} - -void LocalBluetoothDevice::onPairingDisplayPinCode(const QBluetoothAddress &address, QString pin) -{ - OPENAUTO_LOG(info) << "[LocalBluetoothDevice] onPairingDisplayPinCode, address: " << address.toString().toStdString() - << ", pin: " << pin.toStdString(); - - std::lock_guard lock(mutex_); - localDevice_->pairingConfirmation(address == pairingAddress_); -} - -void LocalBluetoothDevice::onPairingFinished(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing) -{ - OPENAUTO_LOG(info) << "[LocalBluetoothDevice] onPairingDisplayPinCode, address: " << address.toString().toStdString() - << ", pin: " << pairing; - - std::lock_guard lock(mutex_); - - if(address == pairingAddress_) - { - if(pairing != QBluetoothLocalDevice::Unpaired) - { - pairingPromise_->resolve(); - } - else - { - pairingPromise_->reject(); - } - - pairingPromise_.reset(); - pairingAddress_ = QBluetoothAddress(); - } -} - -void LocalBluetoothDevice::onError(QBluetoothLocalDevice::Error error) -{ - OPENAUTO_LOG(warning) << "[LocalBluetoothDevice] onError, error: " << error; - - std::lock_guard lock(mutex_); - - if(pairingPromise_ != nullptr) - { - pairingPromise_->reject(); - pairingPromise_.reset(); - pairingAddress_ = QBluetoothAddress(); - } -} - -void LocalBluetoothDevice::onHostModeStateChanged(QBluetoothLocalDevice::HostMode state) -{ - std::lock_guard lock(mutex_); - - if(state == QBluetoothLocalDevice::HostPoweredOff && pairingPromise_ != nullptr) - { - pairingPromise_->reject(); - pairingPromise_.reset(); - pairingAddress_ = QBluetoothAddress(); - } -} diff --git a/src/autoapp/Service/ServiceFactory.cpp b/src/autoapp/Service/ServiceFactory.cpp index 693be0d..f4638e8 100644 --- a/src/autoapp/Service/ServiceFactory.cpp +++ b/src/autoapp/Service/ServiceFactory.cpp @@ -38,7 +38,6 @@ #include #include #include - #include #include #include @@ -46,7 +45,6 @@ #include #include #include -#include #include namespace f1x::openauto::autoapp::service { diff --git a/src/autoapp/UI/MainWindow.cpp b/src/autoapp/UI/MainWindow.cpp index 7a3166c..f9ab78d 100644 --- a/src/autoapp/UI/MainWindow.cpp +++ b/src/autoapp/UI/MainWindow.cpp @@ -2163,7 +2163,7 @@ void f1x::openauto::autoapp::ui::MainWindow::tmpChanged() ui_->devlabel_right->show(); } } - } + // } if (std::ifstream("/tmp/btdevice") || std::ifstream("/tmp/media_playing") || std::ifstream("/tmp/dev_mode_enabled") || std::ifstream("/tmp/android_device")) { if (ui_->labelLock->isVisible() == false) { diff --git a/src/btservice/AndroidBluetoothServer.cpp b/src/btservice/AndroidBluetoothServer.cpp index 26c45f9..8a66cb6 100644 --- a/src/btservice/AndroidBluetoothServer.cpp +++ b/src/btservice/AndroidBluetoothServer.cpp @@ -16,6 +16,7 @@ * along with openauto. If not, see . */ + #include #include #include @@ -23,7 +24,15 @@ #include #include #include +#include +#include +#include +#include +using namespace google::protobuf; +using namespace google::protobuf::io; + +// 39171FDJG002WHhandleWifiVersionRequest namespace f1x::openauto::btservice { @@ -34,14 +43,18 @@ namespace f1x::openauto::btservice { &AndroidBluetoothServer::onClientConnected); } + /// Start Server listening on Address uint16_t AndroidBluetoothServer::start(const QBluetoothAddress &address) { + OPENAUTO_LOG(debug) << "[AndroidBluetoothServer] start()"; if (rfcommServer_->listen(address)) { return rfcommServer_->serverPort(); } return 0; } + /// Call-Back for when Client Connected void AndroidBluetoothServer::onClientConnected() { + OPENAUTO_LOG(debug) << "[AndroidBluetoothServer] onClientConnected()"; if (socket != nullptr) { socket->deleteLater(); } @@ -49,31 +62,31 @@ namespace f1x::openauto::btservice { socket = rfcommServer_->nextPendingConnection(); if (socket != nullptr) { - OPENAUTO_LOG(info) << "[AndroidBluetoothServer] rfcomm client connected, peer name: " + OPENAUTO_LOG(debug) << "[AndroidBluetoothServer] rfcomm client connected, peer name: " << socket->peerName().toStdString(); connect(socket, &QBluetoothSocket::readyRead, this, &AndroidBluetoothServer::readSocket); - aap_protobuf::service::wifiprojection::message::WifiCredentialsRequest request; - // TODO: How do we ping back the Wireless Port and IP? - //aap_protobuf::service::::WifiInfoRequest request; - request.set_ip_address(getIP4_("wlan0")); - getIP4_() - //request.set_port(5000); + aap_protobuf::aaw::WifiVersionRequest versionRequest; + aap_protobuf::aaw::WifiStartRequest startRequest; + startRequest.set_ip_address(getIP4_("wlan0")); + startRequest.set_port(5000); - sendMessage(request, 1); + sendMessage(versionRequest, aap_protobuf::aaw::MessageId::WIFI_VERSION_REQUEST); + sendMessage(startRequest, aap_protobuf::aaw::MessageId::WIFI_START_REQUEST); } else { OPENAUTO_LOG(error) << "[AndroidBluetoothServer] received null socket during client connection."; } } + /// Read data from Bluetooth Socket void AndroidBluetoothServer::readSocket() { buffer += socket->readAll(); - OPENAUTO_LOG(info) << "Received message"; + OPENAUTO_LOG(debug) << "[AndroidBluetoothServer::readSocket] Reading from socket."; if (buffer.length() < 4) { - OPENAUTO_LOG(debug) << "Not enough data, waiting for more"; + OPENAUTO_LOG(debug) << "[AndroidBluetoothServer::readSocket] Not enough data, waiting for more."; return; } @@ -82,66 +95,112 @@ namespace f1x::openauto::btservice { stream >> length; if (buffer.length() < length + 4) { - OPENAUTO_LOG(info) << "Not enough data, waiting for more: " << buffer.length(); + OPENAUTO_LOG(debug) << "[AndroidBluetoothServer::readSocket] Not enough data, waiting for more: " << buffer.length(); return; } - aap_protobuf::service::wifiprojection::WifiProjectionMessageId messageId; - //uint16_t messageId; - stream >> messageId; + quint16 rawMessageId; + stream >> rawMessageId; - //OPENAUTO_LOG(info) << "[AndroidBluetoothServer] " << length << " " << messageId; - OPENAUTO_LOG(debug) << messageId; + aap_protobuf::aaw::MessageId messageId; + messageId = static_cast(rawMessageId); + + OPENAUTO_LOG(debug) << "[AndroidBluetoothServer::readSocket] Message length: " << length << " MessageId: " << messageId; + + switch (messageId) { + + case aap_protobuf::aaw::MessageId::WIFI_INFO_REQUEST: // WifiInfoRequest - Respond with a WifiInfoResponse + handleWifiInfoRequest(buffer, length); + break; + case aap_protobuf::aaw::MessageId::WIFI_VERSION_RESPONSE: // WifiVersionRequest - Send a Version Request + handleWifiVersionResponse(buffer, length);// do something + break; + case aap_protobuf::aaw::MessageId::WIFI_CONNECTION_STATUS: // WifiStartResponse - Receive a confirmation + handleWifiConnectionStatus(buffer, length); + break; + case aap_protobuf::aaw::MessageId::WIFI_START_RESPONSE: // WifiStartResponse - Receive a confirmation + handleWifiStartResponse(buffer, length); + break; + case aap_protobuf::aaw::MessageId::WIFI_START_REQUEST: // These are not received from the MD. + case aap_protobuf::aaw::MessageId::WIFI_INFO_RESPONSE: // These are not received from the MD. + case aap_protobuf::aaw::MessageId::WIFI_VERSION_REQUEST: // These are not received from the MD. + default: + QByteArray messageData = buffer.mid(stream.device()->pos(), length - 2); + + // Convert QByteArray to std::string + std::string protoData = messageData.toStdString(); + + // Pass it to your function + this->DecodeProtoMessage(protoData); std::stringstream ss; ss << std::hex << std::setfill('0'); for (auto &&val: buffer) { ss << std::setw(2) << static_cast(val); } - OPENAUTO_LOG(info) << "Unknown message: " << messageId; - OPENAUTO_LOG(info) << ss.str(); + OPENAUTO_LOG(debug) << "[AndroidBluetoothServer::readSocket] Unknown message: " << messageId; + OPENAUTO_LOG(debug) << "[AndroidBluetoothServer::readSocket] Data " << ss.str(); + + break; + } buffer = buffer.mid(length + 4); } + /// Handles request for WifiInfoRequest by sending a WifiInfoResponse + /// \param buffer + /// \param length void AndroidBluetoothServer::handleWifiInfoRequest(QByteArray &buffer, uint16_t length) { - aap_protobuf::service::wifiprojection::message::WifiCredentialsRequest msg; - msg.ParseFromArray(buffer.data() + 4, length); - OPENAUTO_LOG(info) << "WifiInfoRequest: " << msg.DebugString(); + OPENAUTO_LOG(info) << "[AndroidBluetoothServer::handleWifiInfoRequest] Handling wifi info request"; - aap_protobuf::service::wifiprojection::message::WifiCredentialsResponse response; + aap_protobuf::aaw::WifiInfoResponse response; - //response.set_ip_address(getIP4_("wlan0")); - //response.set_port(5000); - //response.set_status(aap_protobuf::service::control::WifiInfoResponse_Status_STATUS_SUCCESS); - - sendMessage(response, 7); - } - - void AndroidBluetoothServer::handleWifiSecurityRequest(QByteArray &buffer, uint16_t length) { - OPENAUTO_LOG(info) << "[AndroidBluetoothServer] WifiSecurityRequest:"; - aap_protobuf::service::wifiprojection::message::WifiCredentialsResponse response; - - response.set_car_wifi_security_mode( - aap_protobuf::service::wifiprojection::message::WifiSecurityMode::WPA2_PERSONAL); - response.set_car_wifi_ssid(configuration_->getParamFromFile("/etc/hostapd/hostapd.conf", "ssid").toStdString()); - response.set_car_wifi_password( + response.set_ssid(configuration_->getParamFromFile("/etc/hostapd/hostapd.conf", "ssid").toStdString()); + response.set_password( configuration_->getParamFromFile("/etc/hostapd/hostapd.conf", "wpa_passphrase").toStdString()); + response.set_bssid(QNetworkInterface::interfaceFromName("wlan0").hardwareAddress().toStdString()); + response.set_security_mode( + aap_protobuf::service::wifiprojection::message::WifiSecurityMode::WPA2_PERSONAL); response.set_access_point_type(aap_protobuf::service::wifiprojection::message::AccessPointType::STATIC); - response.add_supported_wifi_channels(1); - - - //response.set_ssid(configuration_->getParamFromFile("/etc/hostapd/hostapd.conf","ssid").toStdString()); - //response.set_bssid(QNetworkInterface::interfaceFromName("wlan0").hardwareAddress().toStdString()); - //response.set_key(configuration_->getParamFromFile("/etc/hostapd/hostapd.conf","wpa_passphrase").toStdString()); - //response.set_security_mode(aap_protobuf::messages::WifiSecurityReponse_SecurityMode_WPA2_PERSONAL); - //response.set_access_point_type(aap_protobuf::messages::WifiSecurityReponse_AccessPointType_STATIC); sendMessage(response, 3); } + /// Listens for a WifiVersionResponse from the MD - usually just a notification + /// \param buffer + /// \param length + void AndroidBluetoothServer::handleWifiVersionResponse(QByteArray &buffer, uint16_t length) { + OPENAUTO_LOG(info) << "[AndroidBluetoothServer::handleWifiVersionResponse] Handling wifi version response"; + + aap_protobuf::aaw::WifiVersionResponse response; + response.ParseFromArray(buffer.data() + 4, length); + OPENAUTO_LOG(debug) << "[AndroidBluetoothServer::handleWifiVersionResponse] Unknown Param 1: " << response.unknown_value_a() << " Unknown Param 2: " << response.unknown_value_b(); + } + + /// Listens for WifiStartResponse from MD - usually just a notification with a status + /// \param buffer + /// \param length + void AndroidBluetoothServer::handleWifiStartResponse(QByteArray &buffer, uint16_t length) { + OPENAUTO_LOG(info) << "[AndroidBluetoothServer::handleWifiStartResponse] Handling wifi start response"; + + aap_protobuf::aaw::WifiStartResponse response; + response.ParseFromArray(buffer.data() + 4, length); + OPENAUTO_LOG(debug) << "[AndroidBluetoothServer::handleWifiStartResponse] " << response.ip_address() << " port " << response.port() << " status " << Status_Name(response.status()); + } + + /// Handles request for WifiStartRequest by sending a WifiStartResponse + /// \param buffer + /// \param length + void AndroidBluetoothServer::handleWifiConnectionStatus(QByteArray &buffer, uint16_t length) { + aap_protobuf::aaw::WifiConnectionStatus status; + status.ParseFromArray(buffer.data() + 4, length); + OPENAUTO_LOG(info) << "[AndroidBluetoothServer::handleWifiConnectionStatus] Handle wifi connection status, received: " << Status_Name(status.status()); + } + void AndroidBluetoothServer::sendMessage(const google::protobuf::Message &message, uint16_t type) { - int byteSize = message.ByteSize(); + OPENAUTO_LOG(info) << "[AndroidBluetoothServer::sendMessage] Sending message to connected device"; + + int byteSize = message.ByteSizeLong(); QByteArray out(byteSize + 4, 0); QDataStream ds(&out, QIODevice::ReadWrite); ds << (uint16_t) byteSize; @@ -153,24 +212,17 @@ namespace f1x::openauto::btservice { for (auto &&val: out) { ss << std::setw(2) << static_cast(val); } - //OPENAUTO_LOG(info) << "Writing message: " << ss.str(); + OPENAUTO_LOG(debug) << message.GetTypeName() << " - " + message.DebugString(); auto written = socket->write(out); if (written > -1) { - OPENAUTO_LOG(info) << "Bytes written: " << written; + OPENAUTO_LOG(debug) << "[AndroidBluetoothServer::sendMessage] Bytes written: " << written; } else { - OPENAUTO_LOG(info) << "Could not write data"; + OPENAUTO_LOG(debug) << "[AndroidBluetoothServer::sendMessage] Could not write data"; } } - void AndroidBluetoothServer::handleWifiInfoRequestResponse(QByteArray &buffer, uint16_t length) { - OPENAUTO_LOG(info) << "[AndroidBluetoothServer] WifiInfoRequestResponse"; - aap_protobuf::service::wifiprojection::message::WifiCredentialsResponse msg; - msg.ParseFromArray(buffer.data() + 4, length); - OPENAUTO_LOG(info) << "WifiInfoResponse: " << msg.DebugString(); - } - const ::std::string AndroidBluetoothServer::getIP4_(const QString intf) { for (const QNetworkAddressEntry &address: QNetworkInterface::interfaceFromName(intf).addressEntries()) { if (address.ip().protocol() == QAbstractSocket::IPv4Protocol) @@ -178,5 +230,47 @@ namespace f1x::openauto::btservice { } return ""; } + + /// Decode Proto Messages to their constituent components + /// \param proto_data + void AndroidBluetoothServer::DecodeProtoMessage(const std::string& proto_data) { + UnknownFieldSet set; + + // Create streams + ArrayInputStream raw_input(proto_data.data(), proto_data.size()); + CodedInputStream input(&raw_input); + + // Decode the message + if (!set.MergeFromCodedStream(&input)) { + std::cerr << "Failed to decode the message." << std::endl; + return; + } + + // Iterate over the fields + for (int i = 0; i < set.field_count(); ++i) { + const UnknownField& field = set.field(i); + switch (field.type()) { + case UnknownField::TYPE_VARINT: + std::cout << "Field number " << field.number() << " is a varint: " << field.varint() << std::endl; + break; + case UnknownField::TYPE_FIXED32: + std::cout << "Field number " << field.number() << " is a fixed32: " << field.fixed32() << std::endl; + break; + case UnknownField::TYPE_FIXED64: + std::cout << "Field number " << field.number() << " is a fixed64: " << field.fixed64() << std::endl; + break; + case UnknownField::TYPE_LENGTH_DELIMITED: + std::cout << "Field number " << field.number() << " is length-delimited: "; + for (char ch : field.length_delimited()) { + std::cout << std::hex << (int)(unsigned char)ch; + } + std::cout << std::dec << std::endl; + break; + case UnknownField::TYPE_GROUP: // Deprecated in modern Protobuf + std::cout << "Field number " << field.number() << " is a group." << std::endl; + break; + } + } + } } diff --git a/src/btservice/BluetoothHandler.cpp b/src/btservice/BluetoothHandler.cpp new file mode 100644 index 0000000..40daafa --- /dev/null +++ b/src/btservice/BluetoothHandler.cpp @@ -0,0 +1,85 @@ +// +// Created by Simon Dean on 26/11/2024. +// + +#include +#include +#include +#include + +namespace f1x::openauto::btservice { + BluetoothHandler::BluetoothHandler(autoapp::configuration::IConfiguration::Pointer configuration) + : configuration_(std::move(configuration)) { + + OPENAUTO_LOG(info) << "[BluetoothHandler::BluetoothHandler] Starting Up..."; + + QString adapterAddress = QString::fromStdString(configuration_->getBluetoothAdapterAddress()); + QBluetoothAddress address(adapterAddress); + localDevice_ = std::make_unique(QBluetoothAddress()); + + if (!localDevice_->isValid()) { + OPENAUTO_LOG(error) << "[BluetoothHandler] Bluetooth adapter is not valid."; + } else { + OPENAUTO_LOG(info) << "[BluetoothHandler] Bluetooth adapter is valid."; + } + + QObject::connect(localDevice_.get(), &QBluetoothLocalDevice::pairingDisplayPinCode, this, &BluetoothHandler::onPairingDisplayPinCode); + QObject::connect(localDevice_.get(), &QBluetoothLocalDevice::pairingDisplayConfirmation, this, &BluetoothHandler::onPairingDisplayConfirmation); + QObject::connect(localDevice_.get(), &QBluetoothLocalDevice::pairingFinished, this, &BluetoothHandler::onPairingFinished); + QObject::connect(localDevice_.get(), &QBluetoothLocalDevice::hostModeStateChanged, this, &BluetoothHandler::onHostModeStateChanged); + QObject::connect(localDevice_.get(), &QBluetoothLocalDevice::error, this, &BluetoothHandler::onError); + + // Turn Bluetooth on + localDevice_->powerOn(); + + // Make it visible to others + localDevice_->setHostMode(QBluetoothLocalDevice::HostDiscoverable); + + btservice::AndroidBluetoothServer androidBluetoothServer(configuration_); + uint16_t portNumber = androidBluetoothServer.start(address); + + if (portNumber == 0) { + OPENAUTO_LOG(error) << "[BluetoothHandler::BluetoothHandler] Server start failed."; + throw std::runtime_error("Unable to start bluetooth server"); + } + + OPENAUTO_LOG(info) << "[BluetoothHandler::BluetoothHandler] Listening for connections, address: " << address.toString().toStdString() + << ", port: " << portNumber; + + btservice::AndroidBluetoothService androidBluetoothService(portNumber); + if (!androidBluetoothService.registerService(address)) { + OPENAUTO_LOG(error) << "[BluetoothHandler::BluetoothHandler] Service registration failed."; + throw std::runtime_error("Unable to register btservice"); + } else { + OPENAUTO_LOG(info) << "[BluetoothHandler::BluetoothHandler] Service registered, port: " << portNumber; + } + + androidBluetoothService.unregisterService(); + } + + void BluetoothHandler::onPairingDisplayPinCode(const QBluetoothAddress &address, QString pin) { + OPENAUTO_LOG(debug) << "[BluetoothHandler::onPairingDisplayPinCode] Pairing display PIN code: " << pin.toStdString(); + } + + void BluetoothHandler::onPairingDisplayConfirmation(const QBluetoothAddress &address, QString pin) { + OPENAUTO_LOG(debug) << "[BluetoothHandler::onPairingDisplayConfirmation] Pairing display confirmation: " << pin.toStdString(); + + // Here you can implement logic to show this PIN to the user or automatically accept if you trust all devices + localDevice_->pairingConfirmation(true); // Confirm pairing (for security, you might want to verify the PIN) + } + + void BluetoothHandler::onPairingFinished(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing) { + OPENAUTO_LOG(info) << "[BluetoothHandler::onPairingFinished] pairingFinished, address: " << address.toString().toStdString() + << ", pairing: " << pairing; + } + + void BluetoothHandler::onError(QBluetoothLocalDevice::Error error) { + OPENAUTO_LOG(warning) << "[BluetoothHandler::onError] Bluetooth error: " << error; + // ... your logic to handle the error ... + } + + void BluetoothHandler::onHostModeStateChanged(QBluetoothLocalDevice::HostMode state) { + OPENAUTO_LOG(info) << "[BluetoothHandler::onHostModeStateChanged] Host mode state changed: " << state; + // ... your logic to handle the state change ... + } +} \ No newline at end of file diff --git a/src/btservice/btservice.cpp b/src/btservice/btservice.cpp index 3b8b8ee..287eede 100644 --- a/src/btservice/btservice.cpp +++ b/src/btservice/btservice.cpp @@ -20,8 +20,7 @@ #include #include #include -#include -#include +#include namespace btservice = f1x::openauto::btservice; @@ -29,39 +28,16 @@ int main(int argc, char *argv[]) { QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth*=true")); QCoreApplication qApplication(argc, argv); - QBluetoothLocalDevice localDevice; - const QBluetoothAddress address = localDevice.address(); - auto configuration = std::make_shared(); - // Turn Bluetooth on - localDevice.powerOn(); - // Make it visible to others - localDevice.setHostMode(QBluetoothLocalDevice::HostDiscoverable); - - btservice::AndroidBluetoothServer androidBluetoothServer(configuration); - uint16_t portNumber = androidBluetoothServer.start(address); - - if (portNumber == 0) { - OPENAUTO_LOG(error) << "[btservice] Server start failed."; - return 2; + try { + btservice::BluetoothHandler bluetoothHandler(configuration); + QCoreApplication::exec(); + } catch (std::runtime_error& e) { + std::cerr << "Exception caught: " << e.what() << std::endl; } - OPENAUTO_LOG(info) << "[btservice] Listening for connections, address: " << address.toString().toStdString() - << ", port: " << portNumber; - - btservice::AndroidBluetoothService androidBluetoothService(portNumber); - if (!androidBluetoothService.registerService(address)) { - OPENAUTO_LOG(error) << "[btservice] Service registration failed."; - return 1; - } else { - OPENAUTO_LOG(info) << "[btservice] Service registered, port: " << portNumber; - } - - QCoreApplication::exec(); - OPENAUTO_LOG(info) << "stop"; - androidBluetoothService.unregisterService(); return 0; }