2014-11-20 3 views
2

Мне нужен очень простой фрагмент кода, который соединяет устройство 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) 
+0

Вы абсолютно уверены, что получили соединение, и все рукопожатие выполняется к тому времени, когда вы вызываете 'waitForReadyRead'? – Surt

+0

Хорошая точка. Я действительно тестировал 'socket-> isOpen()', но этого, по-видимому, недостаточно. Я обновил сообщение, теперь я жду, когда состояние сокета будет 'QBluetoothSocket :: ConnectedState', а журнал QtCReator теперь сообщает об ошибке ввода-вывода. – jpo38

+0

Вы говорите, что успешно подключили и обменяли данные через Bluetooth SPP-режим с Windows-машины? Если это так, это странно, так как документация Qt - http://doc.qt.io/qt-5/qtbluetooth-index.html - явно указывает поддерживаемые операционные системы, Windows не входит в их число.Кроме того, в документации Qt нет ничего, связанного с QSerialPort, поскольку он может подключать и обмениваться данными с устройством Bluetooth. Таким образом, возникает вопрос: насколько конкретно настроено ваше домашнее устройство? Будет ли QSerialPort работать с любым Bluetooth-устройством SPP? Благодаря! – kellogs

ответ

0

После повторного поиска в Интернете, я нашел этот Qtbug, сообщая тот же вопрос: https://bugreports.qt-project.org/browse/QTBUG-40172

Я модернизированный в Qt 5.3.2, а код просто работал !!!

Спасибо за помощь, не знаю, если бы она работала без петли while (socket->state() != QBluetoothSocket::ConnectedState). Но точно, он не может работать с Qt 5.3.1!

0

Вы абсолютно уверены, что у вас есть соединение, и все рукопожатие выполняется к тому времени, когда вы вызываете waitForReadyRead?

USB/Bluetooth обычно требует немного больше ожидания, чем последовательный.

+0

Да, после вашего комментария выше, исходное сообщение было обновлено. См. Сообщение об ошибке, сообщаемое системой. Ожидание не является решением: теперь я жду, когда соединение будет готово, но я получаю системную ошибку. – jpo38

+0

Моя память об этом довольно туманна, поэтому я могу только посоветовать посмотреть [прочитать не удалось] (http://stackoverflow.com/questions/18657427/ioexception-read-failed-socket-might-closed-bluetooth-on -android-4-3? lq = 1) или [нет BluetoothManagerCallback] (http://stackoverflow.com/questions/17304479/android-getbluetoothservice-called-with-no-bluetoothmanagercallback). Если это не помогает, я возвращаюсь к googeling. – Surt

Смежные вопросы