Bluetooth Socket For Android
-
Hello everyone,
I'm currently developing an embedded system with a Raspberry Pi 3 B+ (GCC C program with Bluez) & Android App (Qt C++/QML) connected via Bluetooth. I have got bi-directional communication working with RFCOMM and Serial Port Profile. However, the user currently has to click a connect button, wait for the connection to accept on the Pi, then click a separate send button to actually write to the socket; I'm trying to automate this.
However, if I simply call my sendBluetooth() function at the end of my connectBluetooth() function, apparently the device is not open. I have also tried putting the entire sendBluetooth() function inside my connectBluetooth() function, but I get the same error. If I click on the connect button (which just runs the connectBluetooth() function), then the send button (which just runs the sendBluetooth() function), it works, so I'm not sure what exactly is going on here!
Any help would be appreciated! I'm not sure if it's something in the header file, or something I'm doing fundamentally wrong. I have also tried putting a loop in the sendBluetooth() function, to keep sending the message in case it doesn't connect in time, but still fails.
Qt 5.13.2 on Windows 10 compiling for Android Note 7P (Android 9) with C++/QML.
// backend.cpp #include "backend.h" #include <QDebug> #include <QString> #include <QThread> #include <QProcess> #include <QtCore> #include <QtBluetooth> #include <unistd.h> #include <stdio.h> BackEnd::BackEnd(QObject *parent) : QObject(parent) { qDebug("INITINITINITINITINITINITINITINITINITINITINITINITINITINITINITINITINITINITINITINITINITINITINITINITINITINITINITINITINITINIT"); setLastName("Hi"); setConnectionStatus("Waiting or User Selection..."); } QString BackEnd::connectionStatus() { return m_connectionStatus; } QString BackEnd::lastName() { return m_lastName; } void BackEnd::setConnectionStatus(const QString &connectionStatus) { if (connectionStatus == m_connectionStatus) return; m_connectionStatus = connectionStatus; emit connectionStatusChanged(); qDebug("emit connectionStatusChanged()"); } void BackEnd::setLastName(const QString &lastName) { if (lastName == m_lastName) return; m_lastName = lastName; emit lastNameChanged(); qDebug("emit lastNameChanged()"); } void BackEnd::selectBluetooth() // Removed from QML, button goes straight to connectBluetooth() now { qDebug("SELECT BLUETOOTH ()"); setConnectionStatus("Initializing Connection..."); connectBluetooth(); } void BackEnd::selectWifi() { qDebug("SELECT WIFI ()"); } void BackEnd::connectBluetooth() { qDebug("connectBluetooth() has been run!"); qDebug("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Connecting to Bluetooth"); int numberOfAttempts = 0; if (numberOfAttempts >= 5) { qDebug("Bluetooth connect failed 5 times, show error message and stop loop!"); setConnectionStatus("Bluetooth connect failed 5 times. Please close and retry the app!"); socket->close(); return; } else if (numberOfAttempts > 0) qDebug("Bluetooth connect failed, attempting again...!"); setConnectionStatus("Could not connect to Bluetooth, trying again..."); connect(agent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)), this, SLOT(deviceDiscovered(QBluetoothDeviceInfo))); qDebug("Starting Bluetooth Agent..."); numberOfAttempts++; agent->start(); //Start Bluetooth Agent setConnectionStatus("Bluetooth Agent Started..."); qDebug("Agent Started, Creating"); socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol); setConnectionStatus("Connecting to Service..."); qDebug("Connecting to Service..."); static const QString serviceUuid(QStringLiteral("00001101-0000-1000-8000-00805F9B34FB")); // Normal Service UUID socket->connectToService(QBluetoothAddress("B8:27:EB:60:8F:84"), QBluetoothUuid(serviceUuid), QIODevice::ReadWrite); qDebug("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@CONNECT Bluetooth Function Finished."); //socket->waitForReadyRead(10000); qDebug("Running sendBluetooth()....."); sendBluetooth(); } void BackEnd::sendBluetooth() { qDebug("sendBluetooth() has been run!"); qDebug("HEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHEREHERE"); sleep(2); /*while ( socket->state() != QBluetoothSocket::ConnectedState ) { qDebug() << "sendBluetooth(): Bluetooth not in connected state!"; sleep(1); } qDebug("socket->state() == Connected.");*/ char astring[] = "1,1,1,1"; char *ptrToString = astring; //work int writeStatus = 0; writeStatus = socket->write(ptrToString, 128); qDebug("writeStatus: %d",writeStatus); qDebug("COMPLETECOMPLETECOMPLETECOMPLETECOMPLETECOMPLETECOMPLETECOMPLETECOMPLETECOMPLETECOMPLETECOMPLETECOMPLETECOMPLETECOMPLETECOMPLETE"); }
// backend.h #ifndef BACKEND_H #define BACKEND_H #include <QObject> #include <QString> #include <QBluetoothSocket> #include <QBluetoothDeviceDiscoveryAgent> #include <QDebug> class BackEnd : public QObject { Q_OBJECT Q_PROPERTY(QString connectionStatus READ connectionStatus WRITE setConnectionStatus NOTIFY connectionStatusChanged) Q_PROPERTY(QString lastName READ lastName WRITE setLastName NOTIFY lastNameChanged) public: explicit BackEnd(QObject *parent = nullptr); QString connectionStatus(); QString lastName(); void setConnectionStatus(const QString &connectionStatus); void setLastName(const QString &lastName); QBluetoothDeviceDiscoveryAgent *agent = new QBluetoothDeviceDiscoveryAgent; QBluetoothSocket *socket; signals: void connectionStatusChanged(); void lastNameChanged(); void connectClicked(); void sendClicked(); void selectBluetooth(); void selectWifi(); private: QString string; QString m_connectionStatus; QString m_lastName; public slots: void connectBluetooth(); void sendBluetooth(); void deviceDiscovered(QBluetoothDeviceInfo); }; #endif // BACKEND_H
// main.cpp #include <QGuiApplication> #include <QQmlApplicationEngine> #include <QQmlContext> #include <QQuickView> #include "backend.h" int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); qmlRegisterType<BackEnd>("io.qt.examples.backend", 1, 0, "BackEnd"); // QML > C++ QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) return -1; return app.exec(); }
// main.qml import QtQuick 2.9 import QtGraphicalEffects 1.12 import QtQuick.Window 2.2 //import QtQuick.Controls 2.0 //import QtQuick.Controls 2.13 import QtQuick.Controls 2.12 import io.qt.examples.backend 1.0 import QtQuick.Layouts 1.11 ApplicationWindow { id: root color: "#000000" visible: true property int home: 0 property int loadingBluetooth: 1 property int loadingWifi: 2 property int connectedBluetooth: 3 function pageToShow (page) { switch (page) { case home: buttonBluetooth.opacity = 1; buttonWifi.opacity = 1; rectangleLoading.opacity = 0; rectangleConnected.opacity = 0; break; case loadingBluetooth: buttonBluetooth.opacity = 0; buttonWifi.opacity = 0; rectangleLoading.opacity = 1; break; case loadingWifi: buttonBluetooth.opacity = 0; buttonWifi.opacity = 0; break; case connectedBluetooth: rectangleLoading.opacity = 0; rectangleConnected.opacity = 1; break; } } BackEnd { id: backend } Button { id: buttonBluetooth x: 13 y: 55 width: 147 height: 132 text: qsTr("Bluetooth") onClicked:{ backend.connectBluetooth() //backend.keepAlive() pageToShow(loadingBluetooth) } } Button { id: buttonWifi x: 242 y: 55 width: 147 height: 132 text: qsTr("Wifi") onClicked: { backend.selectWifi() pageToShow(loadingWifi) } } Button { id: buttonReset x: 239 y: 207 width: 150 height: 40 text: qsTr("Reset") onClicked: { print("Reset button pressed.") pageToShow(home) } } Rectangle { id: rectangleLoading x: 30 y: 168 width: 112 height: 79 color: "#c8c8c8" opacity: 0 z: 1 BusyIndicator { id: busyIndicator x: 26 y: 19 z:2 } Label { id: label x: 24 y: 3 text: qsTr("Connecting...") } } Rectangle { id: rectangleConnected x: 30 y: 266 width: 112 height: 79 color: "#c8c8c8" Label { id: label1 x: 24 y: 3 text: qsTr("Connected!") } z: 1 opacity: 0 } TextField { id: textField x: 13 y: 207 text: qsTr("Text Field") } // this function is our QML slot function setTextField(text){ console.log("setTextField: " + text) textField1.text = text } Text { id: username width: 292 height: 30 color: "#fffff3" text: backend.connectionStatus opacity: 1 anchors.verticalCenterOffset: -109 anchors.horizontalCenterOffset: -41 anchors.centerIn: parent onTextChanged: backend.connectionStatus = text } Text { id: lastname x: -4 y: 4 width: 120 height: 30 color: "#ffff00" text: backend.lastName opacity: 1 anchors.verticalCenterOffset: -60 anchors.horizontalCenterOffset: -127 anchors.centerIn: parent onTextChanged: backend.lastName = text } Label { id: label2 x: 13 y: 25 width: 107 height: 18 color: "#ebfa3c" text: qsTr("Drink Selected") } Button { id: sendDebug x: 239 y: 266 width: 150 height: 40 text: qsTr("Send Debug") onClicked: { backend.sendBluetooth() } } } // Application Window