Qt: RFCOMM BluetoothSocket Connection Problems after switching Pages in QML

1k views Asked by At

I'm developing an cross plattform Application in Qt Creator, which has the exercise to control a device via Classic Bluetooth. I have a communication protocol. FIRST: I can connect to device and write Data to it with BluetoothSocket. If I put the startMotor() function into the socketConnected SLOT after beepBuzzor() command then it works fine and I get state() connected.

My problem is if I switch the page in my Application on Android and click on the "start motor" button, I get the state() unconnected, but I am still connected to the device because the LED on the device shows connected. My app does not crash. I think the problem is in the line with socket->connectToService(...), but I'm unsure what to change. The beepBuzzor command works fine, startMotor command too. But if I call the function after successfully connectToService() it does not work because the state is unconnected.

    BluetoothManager::BluetoothManager(QObject *parent) : QObject(parent)
    {
        socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol);
    }

    void BluetoothManager::startDiscovery()
    {

        // Check if Bluetooth is available on this device
        if (localDevice.isValid()) {

            qDebug() << "Bluetooth is available on this device";

            //Turn BT on
            localDevice.powerOn();

            // Make it visible to others
            localDevice.setHostMode(QBluetoothLocalDevice::HostDiscoverable);

            //Read local device name & address
            qDebug() << "Local Device:" << localDevice.name() << "(" << "Address:" << localDevice.address() << ")";

            // Create a discovery agent and connect to its signals

            discoveryAgent = new QBluetoothDeviceDiscoveryAgent(this);

            connect(discoveryAgent, SIGNAL(finished()), this, SLOT(deviceDiscoverFinished()));

            // Start a discovery
            // Trick: da es kein DiscoveryTimer für Classic gibt, suchen wir nach LE devices, da BT121 BLE unterstützt.
            // Die Verbindung erfolgt jedoch über RFCOMM sobald man sich mit dem Gerät verbindet.
            discoveryAgent->setLowEnergyDiscoveryTimeout(5000);
            discoveryAgent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);


            qDebug() << "Device discover started";
        }
        else
        {
            qDebug() << "Bluetooth is not available on this device";
        }

    }
    //SLOT for the finish of device Discovery
    void BluetoothManager::deviceDiscoverFinished()
    {
        qDebug() << "Device discover finished";

        listOfDevices = discoveryAgent->discoveredDevices();

        qDebug() << "Found new devices:";

        for (int i = 0; i < listOfDevices.size(); i++)
        {
            //Q_OS_IOS / MAC do not need here cuz the run is on android device, delete later
            //We do not find galileo device on MacBook
            #if defined (Q_OS_IOS) || defined (Q_OS_MAC)
            // On MacOS and iOS we get no access to device address,
            // only unique UUIDs generated by Core Bluetooth.

            qDebug() << "getting address from deviceUuid()" << listOfDevices.at(i).name().trimmed()
            << " ( " << listOfDevices.at(i).deviceUuid().toString().trimmed() << " ) ";
            setDevice(listOfDevices.at(i).name().trimmed() + " (" + listOfDevices.at(i).deviceUuid().toString().trimmed() + ")");


            #else

            qDebug() << listOfDevices.at(i).name().trimmed()
                     << " ("
                     << listOfDevices.at(i).address().toString().trimmed()
                     << ")";
            setDevice(listOfDevices.at(i).name().trimmed() + " (" + listOfDevices.at(i).address().toString().trimmed() + ")");

            #endif
        }


    }

    /**
    *   In GUI (QML) user select a device with index i.
    *   Create a new socket, using Rfcomm protocol to communicate 
    */

    void BluetoothManager::deviceSelected(int i)
    {
        selectedDevice = listOfDevices.at(i);

        #if defined (Q_OS_IOS) || defined (Q_OS_MAC)
        qDebug() << "User select a device: " << selectedDevice.name() << " ("
                 << selectedDevice.deviceUuid().toString().trimmed() << ")";
    #else

        qDebug() << "User select a device: " << selectedDevice.name() << " ("
                 << selectedDevice.address().toString().trimmed() << ")";
    #endif



        if (localDevice.pairingStatus(selectedDevice.address())== QBluetoothLocalDevice::Paired)
            {
                qDebug() << "Pairing is allready done";
            }
            else
            {
                qDebug() << "Not paired. Please do pairing first for communication with device!";
            }

        selecDevAdress = selectedDevice.address();
        connectToSvc();
        //Connect SIGNALS with SLOTS
        connect(socket, SIGNAL(error(QBluetoothSocket::SocketError)), this, SLOT(socketError(QBluetoothSocket::SocketError)));
        connect(socket, SIGNAL(connected()), this, SLOT(socketConnected()));
        connect(socket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));
        connect(socket, SIGNAL(readyRead()), this, SLOT(socketRead()));
        connect(socket, SIGNAL(stateChanged(QBluetoothSocket::SocketState)), this, SLOT(socketStateChanged()));
    }

    void BluetoothManager::connectToSvc()
    {
        qDebug() << "Create socket";

        //socket->connectToService(selecDevAdress, QBluetoothUuid(QString("00001101-0000-1000-8000-00805F9B34FB")), QIODevice::ReadWrite);
        //static const QString serviceUuid(QStringLiteral("00001101-0000-1000-8000-00805F9B34FB"));
        socket->connectToService(selectedDevice.address(), QBluetoothUuid(QString("00001101-0000-1000-8000-00805F9B34FB")), QIODevice::ReadWrite);

        //Also works with this line instead of the two above (with declaration of serviceUuid)
        //socket->connectToService(QBluetoothAddress(selectedDevice.address()),QBluetoothUuid(QBluetoothUuid::SerialPort));
        socket->open(QIODevice::ReadWrite);

        socket->openMode();

    }

    //SLOT wenn Socket verbunden ist

    void BluetoothManager::socketConnected()
    {

        //qDebug() << ("Connected to: "+socket->peerAddress().toString() +":"+socket->peerPort());
        qDebug() << ("Connected to: "+socket->peerAddress().toString());
        qDebug() << "Socket connected";
        qDebug() << "Local: "
                 << socket->localName()
                 << socket->localAddress().toString()
                 << socket->localPort();
        qDebug() << "Peer: "
                 << socket->peerName()
                 << socket->peerAddress().toString()
                 << socket->peerPort();

        //Do "beep" sound commando after succesfull connection to Galileo device
        beepBuzzor();

    }

    /**
    *   Socket disconnected.
    *   Delete socket, free the memory.
    */

    //SLOT für Verbindungsabbruch von Socket
    void BluetoothManager::socketDisconnected()
    {
        qDebug() << "Socket disconnected";
        socket->deleteLater();
    }


    void BluetoothManager::socketError(QBluetoothSocket::SocketError error)
    {
        qDebug() << "Socket error: " << error;
    }

    void BluetoothManager::socketStateChanged()
    {
        int socketState = socket->state();

        if(socketState == QAbstractSocket::UnconnectedState)
        {
            qDebug() << "unconnected";
        }
        else if(socketState == QAbstractSocket::HostLookupState)
        {
            qDebug() << "host lookup";
        }
        else if(socketState == QAbstractSocket::ConnectingState )
        {
            qDebug() << "connecting";
        }
        else if(socketState == QAbstractSocket::ConnectedState)
        {
            qDebug() << "connected";
        }
        else if(socketState == QAbstractSocket::BoundState)
        {
            qDebug() << "bound";
        }
        else if(socketState == QAbstractSocket::ClosingState)
        {
            qDebug() << "closing";
        }
        else if(socketState == QAbstractSocket::ListeningState)
        {
            qDebug() << "listening";
        }
    }

    //   SLOT when data ready on bluetooth socket
    void BluetoothManager::socketRead()
    {
        qDebug() << "socketRead()";
        QByteArray recievedData = socket->readAll();

        emit dataRecieved(recievedData);
    }

    /**
    *   Get a string with device info
    */

    const QString &BluetoothManager::device() const
    {
        return deviceInfo;
    }


    void BluetoothManager::setDevice(const QString &newDevice)
    {
        if (newDevice != deviceInfo) {

            deviceInfo = newDevice;
            emit deviceChanged();
        }
    }

    void BluetoothManager::beepBuzzor()
    {
        QByteArray beep;
        beep.append(QByteArray::fromRawData("\x04\x00\x09\xD0\x07\x32\x00", 7));
        command(beep);
    }

    void BluetoothManager::startMotor()
    {
        qDebug() << "startMotor slot";
        if(socket->state() == QBluetoothSocket::UnconnectedState){
            qDebug() << "Socket Unconnected";
        }
        else{
            qDebug() << "Socket Unonnected";
        }
        socketStateChanged();
        //command(start);
    }

void BluetoothManager::command(QByteArray &cmdBuf)
{
    socket->write(cmdBuf);
}
0

There are 0 answers