Solved Issue: Bluetooth data transfer
-
I am able to establish a Bluetooth connection and receive data over it in a simple (single class) program. But in my case, I have multiple classes and UI. I have put Bluetooth connection code in a class where app enters first. Later when I switch to other screens then I am unable to see data coming over Bluetooth connection (for data sharing I have connected classes using Signal/Slot). I need to continuously read data coming over Bluetooth connection every 10ms.
Please help me out. -
@ahsan737 You can use QTimer to read data every 10ms and share that data with other classes in your application via signals/slots.
-
Hi,
To add to @jsulm, this is the kind of case where you should have one instance of a dedicated controller class that does all the Bluetooth handling and that you either pass to other objects that needs it like the model/view concept or that you have in one central place and that you connect to all interested objects.
-
@jsulm I am using QTimer to read Bluetooth socket every 10ms and emitting a signal to share that data with other class. but it is working abnormal, sometimes it can receive data in other class and sometimes no data at all. how to solve this abnormal behavior?
-
@ahsan737 You have to debug your app or post your code, else we can only guess...
-
@jsulm the code is as following:
----Bluetooth Class----
#include "bluetooth_server.h" #include<QtBluetooth> #include<QBluetoothSocket> #include <QTimer> bluetooth_server::bluetooth_server(QObject *parent) : QObject(parent) { localDevice.powerOn(); //bluetooth turn on agent = new QBluetoothDeviceDiscoveryAgent; connect(agent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)), this, SLOT(deviceDiscovered(QBluetoothDeviceInfo))); agent->start(); socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol); readSocket(); timer = new QTimer(this); connect(timer, SIGNAL(timeout()),this, SLOT(readSocket())); timer->start(10); // connect(socket, &QBluetoothSocket::readyRead, this, &bluetooth_server::readSocket); connect(socket, &QBluetoothSocket::connected, this, QOverload<>::of(&bluetooth_server::socketStatuscheck)); connect(socket, &QBluetoothSocket::disconnected, this, &bluetooth_server::socketStatuscheck); } //------------------- void bluetooth_server::deviceDiscovered(const QBluetoothDeviceInfo &device) { Q_UNUSED(device); static const QString serviceUuid(QStringLiteral("00001101-0000-1000-8000-00805F9B34FB")); socket->connectToService(QBluetoothAddress("20:19:03:29:27:62"), QBluetoothUuid(serviceUuid), QIODevice::ReadWrite); } //----------------------------------------------- void bluetooth_server::readSocket() { while (socket->canReadLine()) { QByteArray line = socket->readLine().trimmed(); emit messageReceived(socket->peerName(), QString ::fromUtf8(line.constData(), line.length())); QStringList lista, listc, listd; QString listb= QString::fromUtf8(line.constData(), line.length()); lista= listb.split(","); listc=lista.at(2).split("@"); listd=listc.at(1).split("~"); //---------------------- a=lista.at(1).toInt(); b=listc.at(0).toInt(); c=listd.at(0).toInt(); aa=lista.at(1); bb=listc.at(0); cc=listd.at(0); //---------------------- } emit data(aa,bb); } //------------------------------------------------------------------------------------------------------------------- void bluetooth_server::socketStatuscheck() { int socketState = socket->state(); if (socketState==QAbstractSocket::ConnectedState) { readSocket(); string="Connected..."; emit connected(string); } else if(socketState==QAbstractSocket::UnconnectedState) { localDevice.powerOn(); agent->stop(); agent->start(); string="Disconnected..."; emit connected(string); } }
----Data Display Class----
#include "static_measurement.h" #include "ui_static_measurement.h" #include "dynamic_instruct_1.h" #include "settings.h" #include "bluetooth_server.h" #include <main_menu.h> #include "mainwindow.h" #include <time.h> #include <QTimer> static_measurement::static_measurement(QWidget *parent) : QDialog(parent), ui(new Ui::static_measurement) { ui->setupUi(this); setWindowState(Qt::WindowMaximized); Screen_Size scr; server = new bluetooth_server(this); connect(server, &bluetooth_server::data, this, &static_measurement::data); //---------------------Bar Graph Plot--------------------------- //Initialize random variable generator srand (time(NULL)); //-------------------------------------------------------------- ui->custom_plot->resize(270,450); bars1 = new QCPBars(ui->custom_plot->xAxis, ui->custom_plot->yAxis); //bars1->setWidth(9/(double)x3.size()); bars1->setPen(Qt::NoPen); bars1->setBrush(QColor(10, 140, 70, 200)); bars1->setName("LEFT"); bars2 = new QCPBars(ui->custom_plot->xAxis, ui->custom_plot->yAxis); bars2->setPen(Qt::NoPen); bars2->setBrush(QColor(255, 0, 0, 200)); bars2->setName("RIGHT"); ui->custom_plot->yAxis->setRange(0, 12); ui->custom_plot->xAxis->setRange(0, 3); ticks <<1<<2; ticks2 <<2; QVector<QString> labels; labels << "LEFT" << "RIGHT"; QSharedPointer<QCPAxisTickerText> textTicker(new QCPAxisTickerText); textTicker->addTicks(ticks, labels); ui->custom_plot->xAxis->setTicker(textTicker); //---------------------------------------------------------------------------------------------- // setup a timer that repeatedly calls MainWindow::realtimeDataSlot: dataTimer=new QTimer(this); connect(dataTimer, SIGNAL(timeout()), this, SLOT(data(int sensor_a, int sensor_b))); connect(dataTimer, SIGNAL(timeout()), this, SLOT(realtimeDataSlot())); dataTimer->start(100); // Interval 0 means to refresh as fast as possible //---------------------------------------------------------------------------------------------- } static_measurement::~static_measurement() { delete ui; } void static_measurement::realtimeDataSlot() { s = QString::number(x); t = QString::number(y); QVector<double> Qv_x, Qv_y; Qv_x.append(x); Qv_y.append(y); //-------------------------------------------------------------------------------------------------- // Add data: bars1->setData(ticks,Qv_x); bars2->setData(ticks2,Qv_y); //-------------------------------------------------------------------------------------------------- ui->custom_plot->legend->setVisible(true); bars1->setName("LEFT:"+s); bars2->setName("RIGHT:"+t); ui->custom_plot->replot(); } void static_measurement::data(QString sensor_a, QString sensor_b) { x=sensor_a.toDouble(); y=sensor_b.toDouble(); }
-
@ahsan737 said in Issue: Bluetooth data transfer:
void bluetooth_server::readSocket()
{while (socket->canReadLine())
{Well, it can be that there is not always something to read.
Do this:void bluetooth_server::readSocket() { qDebug() << "readSocket()" << socket->canReadLine(); while (socket->canReadLine()) {
And see what this qDebug() line outputs.
-
@jsulm actually app need to continuously read the sensor readings being sent via Bluetooth (HC-05). For testing purpose, I am sending a comma-separated string (a,b,c) via Bluetooth and trying to read in the app. I cannot see Qtdebug response as I am testing the app on phone (connected with PC) Qt Application output shows these errors upon running the code.
W System.err: java.io.IOException: read failed, socket might closed or timeout, read ret: -1 W System.err: at android.bluetooth.BluetoothSocket.readAll(BluetoothSocket.java:686) W System.err: at android.bluetooth.BluetoothSocket.readInt(BluetoothSocket.java:698) W System.err: at android.bluetooth.BluetoothSocket.connect(BluetoothSocket.java:375) W libComplete_GUI_1.so: qt.bluetooth.android: Socket connect via workaround failed.
-
@ahsan737 Looks like you're not connected.
If you have to read continuously, then you should not use QTimer, but connect a slot to https://doc.qt.io/qt-5/qiodevice.html#readyRead of your socket and read there. -
@jsulm got it, thank you. btw signal/slots were not transmitting data to the required class for real-time bar graph plot, So I've opted for global variables and it worked for me.