Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Qt 5.14.2 BLE not working as expected on Android
Forum Updated to NodeBB v4.3 + New Features

Qt 5.14.2 BLE not working as expected on Android

Scheduled Pinned Locked Moved Unsolved General and Desktop
blebluetoothqtbluetooth
1 Posts 1 Posters 414 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • F Offline
    F Offline
    Fausto01
    wrote on last edited by Fausto01
    #1

    I made a simple app that write a command to a device and expect the device reply with another command. On windows everything works fine, but on Android I'm not able to send the data. This is my code:

    #include "communicator.hpp"
    #include <QDataStream>
    #include <QBluetoothLocalDevice>
    
    #define SERVICE_UUID "{49535343-fe7d-4ae5-8fa9-9fafd205e455}"
    #define SERVICE_CHARACTERISTIC_TX_UUID "{49535343-1e4d-4bd9-ba61-23c647249616}"
    #define READ_DATA_REQUEST_CMD 0xA5
    #define READ_DATA_RESPONSE_CMD 0xA6
    
    Communicator::Communicator()
    {
      QObject::connect(&m_receptionTimer, &QTimer::timeout, this, &Communicator::onReceptionTimerTimeout);
      m_receptionTimer.setInterval(2000);
    }
    
    void Communicator::connectToDevice(const QString& macAddress)
    {
      m_controller.reset(QLowEnergyController::createCentral(QBluetoothAddress(macAddress), QBluetoothLocalDevice().address()));
    
      QObject::connect(m_controller.data(), &QLowEnergyController::connected, this, &Communicator::onDeviceConnected);
      QObject::connect(m_controller.data(), &QLowEnergyController::discoveryFinished, this, &Communicator::onDiscoveryFinished);
      QObject::connect(m_controller.data(), QOverload<QLowEnergyController::Error>::of(&QLowEnergyController::error), this, &Communicator::onDiscoveryError);
      QObject::connect(m_controller.data(), &QLowEnergyController::serviceDiscovered, this, &Communicator::onServiceDiscovered);
    
      m_controller->connectToDevice();
    }
    
    void Communicator::onDeviceConnected()
    {
      qDebug() << "Device connected";
    
      m_serviceDiscovered = false;
      m_controller->discoverServices();
    }
    
    void Communicator::onDiscoveryFinished()
    {
      if(!m_serviceDiscovered)
      {
        emit connectionFailed();
        return;
      }
    
      m_service.reset(m_controller->createServiceObject(QBluetoothUuid(QString(SERVICE_UUID)), this));
      if(m_service.isNull())
      {
        emit connectionFailed();
        return;
      }
    
      QObject::connect(m_service.data(), &QLowEnergyService::stateChanged, this, &Communicator::onServiceStateChanged);
      QObject::connect(m_service.data(), QOverload<QLowEnergyService::ServiceError>::of(&QLowEnergyService::error), this, &Communicator::onServiceError);
      QObject::connect(m_service.data(), &QLowEnergyService::characteristicChanged, this, &Communicator::onCharacteristicChanged);
    
      //************************
      //**********TEST**********
      //************************
    
      QObject::connect(m_service.data(), &QLowEnergyService::stateChanged, this, [](QLowEnergyService::ServiceState state)
      {
        qDebug() << "SERVICE STATE CHANGED -> STATE:" << state;
      });
    
      QObject::connect(m_service.data(), &QLowEnergyService::characteristicWritten, this, [](const QLowEnergyCharacteristic &info, const QByteArray &value)
      {
        qDebug() << "CHARACTERISTIC WRITTEN -> UUID:" << info.uuid().toString() << "VALUE:" << value;
      });
    
      QObject::connect(m_service.data(), &QLowEnergyService::characteristicChanged, this, [](const QLowEnergyCharacteristic &info, const QByteArray &value)
      {
        qDebug() << "CHARACTERISTIC CHANGED -> UUID:" << info.uuid().toString() << "VALUE:" << value;
      });
    
      QObject::connect(m_service.data(), &QLowEnergyService::characteristicRead, this, [](const QLowEnergyCharacteristic &info, const QByteArray &value)
      {
        qDebug() << "CHARACTERISTIC READ -> UUID:" << info.uuid().toString() << "VALUE:" << value;
      });
    
      QObject::connect(m_service.data(), &QLowEnergyService::descriptorRead, this, [](const QLowEnergyDescriptor &info, const QByteArray &value)
      {
        qDebug() << "DESCRIPTOR READ -> UUID:" << info.uuid().toString() << "VALUE:" << value;
      });
    
      QObject::connect(m_service.data(), &QLowEnergyService::descriptorWritten, this, [](const QLowEnergyDescriptor &info, const QByteArray &value)
      {
        qDebug() << "DESCRIPTOR WRITTEN -> UUID:" << info.uuid().toString() << "VALUE:" << value;
      });
    
      //************************
      //**********TEST**********
      //************************
    
      if(m_service->state() == QLowEnergyService::DiscoveryRequired)
        m_service->discoverDetails();
      else
      {
        searchCharacteristics();
        requestData();
      }
    }
    
    void Communicator::onDiscoveryError(QLowEnergyController::Error error)
    {
      qDebug() << "Discovery error" << error;
      emit connectionFailed();
    }
    
    void Communicator::onServiceDiscovered(const QBluetoothUuid& service)
    {
      if(service.toString() == SERVICE_UUID)
        m_serviceDiscovered = true;
    }
    
    void Communicator::onServiceStateChanged(QLowEnergyService::ServiceState state)
    {
      switch(state)
      {
        case QLowEnergyService::InvalidService:
        case QLowEnergyService::DiscoveryRequired:
        case QLowEnergyService::DiscoveringServices:
        case QLowEnergyService::LocalService:
          break;
    
        case QLowEnergyService::ServiceDiscovered:
          searchCharacteristics();
          requestData();
          break;
      }
    }
    
    void Communicator::onServiceError(QLowEnergyService::ServiceError error)
    {
      qDebug() << "Service error" << error;
      emit connectionFailed();
    }
    
    void Communicator::onCharacteristicChanged(const QLowEnergyCharacteristic& info, const QByteArray& value)
    {
      if(info.uuid() != m_writeCharacteristic.uuid())
        return;
    
      m_receptionBuffer.append(value);
      parseResponse(m_receptionBuffer);
    }
    
    void Communicator::onReceptionTimerTimeout()
    {
      qDebug() << "Reception timeout";
      requestData();
      emit errorOccurred();
    }
    
    void Communicator::searchCharacteristics()
    {
      const auto& characteristics = m_service->characteristics();
      for(const QLowEnergyCharacteristic& characteristic : characteristics)
      {
        if(!characteristic.isValid())
          continue;
    
        if(characteristic.uuid().toString() != SERVICE_CHARACTERISTIC_TX_UUID)
          continue;
    
        if(characteristic.properties() & QLowEnergyCharacteristic::WriteNoResponse || characteristic.properties() & QLowEnergyCharacteristic::Write)
        {
          m_writeCharacteristic = characteristic;
          if(characteristic.properties() & QLowEnergyCharacteristic::WriteNoResponse)
            m_writeMode = QLowEnergyService::WriteWithoutResponse;
          else
            m_writeMode = QLowEnergyService::WriteWithResponse;
    
          QLowEnergyDescriptor notificationDescriptor = characteristic.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
          if(notificationDescriptor.isValid())
            m_service->writeDescriptor(notificationDescriptor, QByteArray::fromHex("0100"));
        }
      }
    }
    
    bool Communicator::write(const QByteArray& data)
    {
      if(m_service.isNull())
        return false;
    
      if(!m_writeCharacteristic.isValid())
        return false;
    
      m_service->writeCharacteristic(m_writeCharacteristic, data, m_writeMode);
      return true;
    }
    
    void Communicator::requestData()
    {
      m_receptionBuffer.clear();
      m_receptionTimer.start();
      write(QByteArray(1, READ_DATA_REQUEST_CMD));
    }
    
    void Communicator::parseResponse(const QByteArray& data)
    {
      const quint8 headerLength = 3;
      if(data.length() < headerLength)
        return;
    
      quint8 cmd;
      quint16 length;
    
      QDataStream stream(data);
      stream >> cmd;
    

    This is the log of my application on Android:
    06-07-22 16:48:55.353 |W| ACCESS_COARSE|FINE_LOCATION permission available
    06-07-22 16:48:57.986 |D| Device connected
    06-07-22 16:48:58.018 |D| SERVICE STATE CHANGED -> STATE: QLowEnergyService::DiscoveringServices
    06-07-22 16:49:03.284 |D| Discovery error QLowEnergyController::ConnectionError
    06-07-22 16:49:03.287 |D| SERVICE STATE CHANGED -> STATE: QLowEnergyService::InvalidService
    06-07-22 16:49:03.287 |D| Device disconnected

    Am I doing something wrong?

    1 Reply Last reply
    0

    • Login

    • Login or register to search.
    • First post
      Last post
    0
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Get Qt Extensions
    • Unsolved