我需要一段非常简单的代码,将蓝牙设备(自制)连接为虚拟COM(串行端口配置文件),将一些数据写入其中,然后读取回复。写入的数据打开设备上的LED(这样可以很容易地查看设备是否实际接收到的数据)
我使用Qt 5.3.1与QSerialPort
一起使用,在Windows7上使用Visual Studio 2010编译。它适用于我的笔记本电脑,我只需要指定端口名称COMi
。一旦我的设备配对,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.cpp:
#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)
答案 0 :(得分:0)
你是否确定你有一个连接,所有的握手都是在你调用waitForReadyRead时完成的?
USB /蓝牙通常需要比串行更多的等待。
答案 1 :(得分:0)
在网上再次搜索后,我发现这个Qtbug报告了同样的问题: https://bugreports.qt-project.org/browse/QTBUG-40172
我升级到Qt 5.3.2,代码很简单!!!
感谢Surt的帮助,不知道如果没有while ( socket->state() != QBluetoothSocket::ConnectedState )
循环就行了。但可以肯定的是,它无法与Qt 5.3.1一起使用!