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

Qt 5.14.2 BLE not working as expected on Android

Scheduled Pinned Locked Moved Unsolved General and Desktop
blebluetoothqtbluetooth
1 Posts 1 Posters 403 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