Мне нужен очень простой фрагмент кода, который соединяет устройство Bluetooth (домашний) как виртуальный COM (профиль последовательного порта), записывает на него некоторые данные и затем считывает ответ. Написанные данные включаются на светодиод на устройстве (что позволяет легко увидеть, действительно ли данные были получены устройством)Как перенести код из QSerialPort в QBluetoothSocket
У меня есть работа с QSerialPort
, используя Qt 5.3.1, скомпилированный с Visual Studio 2010 на Windows 7. Он работает на моем ноутбуке, мне просто нужно указать имя порта COMi
. Когда мое устройство сопряжено, диалоговое окно свойств Bluetooth в Windows сообщает мне, какой виртуальный порт следует использовать для подключения устройства.
Я хочу портировать этот Qt-код на Android. По-видимому, система Android не позволит мне открыть COM-порт напрямую, как QSerialPort
(/dev/tty*
доступ запрещен). Поэтому мне нужно портировать код, чтобы использовать QBluetoothSocket, а не QSerialPort.
К сожалению, я не могу получить эту QBluetoothSocket на основе кода для работы ...
Вот QSerialPort
код рабочий:
#include <QApplication>
#include <QThread>
#include <QMessageBox>
#include <QtSerialPort/QSerialPort>
#include <sstream>
#include <vector>
static std::vector<char> sReceived;
class readThread : public QThread
{
public:
readThread(QSerialPort* port) : m_port(port), m_bContinue(true)
{
}
void run()
{
while (m_bContinue)
{
m_port->waitForReadyRead(100);
QByteArray received = m_port->readAll();
for (size_t i = 0; i != received.size(); ++i)
{
sReceived.push_back(received.at(i));
}
}
}
volatile bool m_bContinue;
private:
QSerialPort* m_port;
};
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
int res = 1;
if (argc != 2)
{
QMessageBox::critical(NULL, "Invalid argument", "Specify COM port name as first and unic parameter");
}
else
{
QString portName = argv[1];
QSerialPort port(portName);
if (port.open(QSerialPort::ReadWrite))
{
if (port.setBaudRate(QSerialPort::Baud115200) &&
port.setFlowControl(QSerialPort::HardwareControl) &&
port.setStopBits(QSerialPort::OneStop) &&
port.setParity(QSerialPort::NoParity) &&
port.setDataBits(QSerialPort::Data8))
{
readThread thrd(&port);
thrd.start();
static const size_t requestMessageSize = 10;
char request[requestMessageSize] = { 0x01, 0x00, 0x07, 0x01, 0x01, 0x00, 0x00, 0xBE, 0x0B, 0x00 };
if (port.write(request, requestMessageSize) == requestMessageSize)
{
port.waitForBytesWritten(1000);
QThread::sleep(5);
if (!sReceived.empty())
{
std::stringstream str;
str << "Received:" << std::hex;
for (size_t i = 0; i != sReceived.size(); ++i)
{
str << " 0x" << static_cast<int>(sReceived[i]);
}
str << std::endl;
str << "Could open port, send and receive data" << std::endl;
QMessageBox::information(NULL, "OK", str.str().c_str());
res = 0;
}
else
{
QMessageBox::critical(NULL, "Error", "Could open port, send data, but did not received any reply");
}
}
else
{
QMessageBox::critical(NULL, "Error", "Unable to send request to port");
}
thrd.m_bContinue = false;
thrd.wait();
}
else
{
QMessageBox::critical(NULL, "Error", "Unable to configure port");
}
port.close();
}
else
{
QMessageBox::critical(NULL, "Unable to connect", QString("Could not open connection with %1").arg(portName));
}
}
return res;
}
А вот код на основе QBluetooth не работает:
bthandler.h:
#pragma once
#include <QObject>
#include <QtBluetooth/QBluetoothDeviceDiscoveryAgent>
#include <QtBluetooth/QBluetoothSocket>
class BTHandler : public QObject
{
Q_OBJECT
public:
BTHandler(QBluetoothDeviceDiscoveryAgent& agent);
public slots:
void deviceDiscovered(const QBluetoothDeviceInfo&);
void detectError(QBluetoothDeviceDiscoveryAgent::Error);
void detectError(QBluetoothSocket::SocketError);
QBluetoothDeviceInfo* getDevice() { return (m_foundDeviceFlag) ? &m_foundDevice : NULL; }
QBluetoothSocket* createSocket();
private:
volatile bool m_foundDeviceFlag;
QBluetoothDeviceInfo m_foundDevice;
};
bthandler.c С.:
#include "bthandler.h"
#include <sstream>
#include <QtBluetooth/QBluetoothDeviceInfo>
#include <QtBluetooth/QBluetoothSocket>
#include <QtBluetooth/QBluetoothUuid>
#include <QMessageBox>
#include <QThread>
BTHandler::BTHandler(QBluetoothDeviceDiscoveryAgent& agent) :
m_foundDeviceFlag(false)
{
// Create a discovery agent and connect to its signals
connect(&agent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)),
this, SLOT(deviceDiscovered(QBluetoothDeviceInfo)));
connect(&agent, SIGNAL(error(QBluetoothDeviceDiscoveryAgent::Error)),
this, SLOT(detectError(QBluetoothDeviceDiscoveryAgent::Error)));
}
void BTHandler::deviceDiscovered(const QBluetoothDeviceInfo& device)
{
QBluetoothDeviceInfo::DataCompleteness complete = QBluetoothDeviceInfo::DataComplete;
QBluetoothDeviceInfo::DataCompleteness incomplete = QBluetoothDeviceInfo::DataIncomplete;
QList<QBluetoothUuid> services1 = device.serviceUuids();
QList<QBluetoothUuid> services2 = device.serviceUuids(&complete);
QList<QBluetoothUuid> services3 = device.serviceUuids(&incomplete);
QMessageBox::information(NULL, "Found device", device.name());
if (device.name() == "BLUESWEAT11")
{
QMessageBox::information(NULL, "Info", "Found correct device");
m_foundDevice = QBluetoothDeviceInfo(device);
m_foundDeviceFlag = true;
}
}
void BTHandler::detectError(QBluetoothDeviceDiscoveryAgent::Error error)
{
std::stringstream str;
str << "An error occured during bluetooth lookup: " << (int) error;
QMessageBox::critical(NULL, "Error", str.str().c_str());
}
void BTHandler::detectError(QBluetoothSocket::SocketError error)
{
std::stringstream str;
str << "An error occured during socket use: " << (int) error;
QMessageBox::critical(NULL, "Error", str.str().c_str());
}
QBluetoothSocket* BTHandler::createSocket()
{
QBluetoothSocket* socket = NULL;
if (m_foundDeviceFlag)
{
QBluetoothUuid uuid(QBluetoothUuid::Rfcomm);
socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol);
connect(socket, SIGNAL(error(QBluetoothSocket::SocketError)),
this, SLOT(detectError(QBluetoothSocket::SocketError)));
socket->connectToService(m_foundDevice.address(), uuid);
if (!socket->isOpen())
{
QMessageBox::critical(NULL, "Error", "Unabel to open socket");
delete socket;
}
while (socket->state() != QBluetoothSocket::ConnectedState)
{
QThread::sleep(1);
}
}
return socket;
}
main.cpp:
#include "bthandler.h"
#include <vector>
#include <sstream>
#include <QMessageBox>
#include <QApplication>
#include <QtBluetooth/QBluetoothDeviceDiscoveryAgent>
#include <QtBluetooth/QBluetoothDeviceInfo>
#include <QtBluetooth/QBluetoothSocket>
#include <QtBluetooth/QBluetoothUuid>
#include <QThread>
static std::vector<char> sReceived;
class readThread : public QThread
{
public:
readThread(QBluetoothSocket* port) : m_port(port), m_bContinue(true)
{
}
void run()
{
while (m_bContinue)
{
m_port->waitForReadyRead(100);
QByteArray received = m_port->readAll();
for (size_t i = 0; i != received.size(); ++i)
{
sReceived.push_back(received.at(i));
}
}
}
volatile bool m_bContinue;
private:
QBluetoothSocket* m_port;
};
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
QBluetoothDeviceDiscoveryAgent discoveryAgent;
BTHandler handler(discoveryAgent);
discoveryAgent.start();
while (handler.getDevice() == NULL)
{
QThread::sleep(1);
app.processEvents();
}
discoveryAgent.stop();
int res = 1;
QBluetoothSocket* socket = handler.createSocket();
if (socket)
{
readThread thrd(socket);
thrd.start();
static const size_t requestMessageSize = 10;
char request[requestMessageSize] = { 0x01, 0x00, 0x07, 0x01, 0x01, 0x00, 0x00, 0xBE, 0x0B, 0x00 };
if (socket->write(request, requestMessageSize) == requestMessageSize)
{
socket->waitForBytesWritten(1000);
QThread::sleep(5);
if (!sReceived.empty())
{
std::stringstream str;
str << "Received:" << std::hex;
for (size_t i = 0; i != sReceived.size(); ++i)
{
str << " 0x" << static_cast<int>(sReceived[i]);
}
str << std::endl;
str << "Could open port, send and receive data" << std::endl;
QMessageBox::information(NULL, "OK", str.str().c_str());
res = 0;
}
else
{
QMessageBox::critical(NULL, "Error", "Could open port, send data, but did not received any reply");
}
}
else
{
QMessageBox::critical(NULL, "Error", "Unable to send request to port");
}
thrd.m_bContinue = false;
thrd.wait();
socket->close();
delete socket;
}
else
{
QMessageBox::critical(NULL, "Unable to connect", "Could not open bluetooth connection with device");
}
return res;
}
В этой версии кода, во время ожидания установки соединения (while (socket->state() != QBluetoothSocket::ConnectedState)
), QtCreator журнал сообщает следующее сообщение об ошибке:
W/BluetoothAdapter(5866): getBluetoothService() called with no BluetoothManagerCallback
D/BluetoothSocket(5866): connect(), SocketState: INIT, mPfd: {ParcelFileDescriptor: FileDescriptor[65]}
W/System.err(5866): java.io.IOException: read failed, socket might closed or timeout, read ret: -1
W/System.err(5866): at android.bluetooth.BluetoothSocket.readAll(BluetoothSocket.java:505)
W/System.err(5866): at android.bluetooth.BluetoothSocket.readInt(BluetoothSocket.java:516)
W/System.err(5866): at android.bluetooth.BluetoothSocket.connect(BluetoothSocket.java:320)
W/System.err(5866): at dalvik.system.NativeStart.run(Native Method)
Вы абсолютно уверены, что получили соединение, и все рукопожатие выполняется к тому времени, когда вы вызываете 'waitForReadyRead'? – Surt
Хорошая точка. Я действительно тестировал 'socket-> isOpen()', но этого, по-видимому, недостаточно. Я обновил сообщение, теперь я жду, когда состояние сокета будет 'QBluetoothSocket :: ConnectedState', а журнал QtCReator теперь сообщает об ошибке ввода-вывода. – jpo38
Вы говорите, что успешно подключили и обменяли данные через Bluetooth SPP-режим с Windows-машины? Если это так, это странно, так как документация Qt - http://doc.qt.io/qt-5/qtbluetooth-index.html - явно указывает поддерживаемые операционные системы, Windows не входит в их число.Кроме того, в документации Qt нет ничего, связанного с QSerialPort, поскольку он может подключать и обмениваться данными с устройством Bluetooth. Таким образом, возникает вопрос: насколько конкретно настроено ваше домашнее устройство? Будет ли QSerialPort работать с любым Bluetooth-устройством SPP? Благодаря! – kellogs