228 lines
7.9 KiB
C++
228 lines
7.9 KiB
C++
|
#include "ble.h"
|
|||
|
|
|||
|
BLE::BLE(QObject *parent) : QObject(parent)
|
|||
|
{
|
|||
|
init();
|
|||
|
}
|
|||
|
|
|||
|
BLE::~BLE()
|
|||
|
{
|
|||
|
delete m_LowController;
|
|||
|
delete m_DiscoveryAgent;
|
|||
|
servicesList.clear();
|
|||
|
characterList.clear();
|
|||
|
bleDevicesList.clear();
|
|||
|
}
|
|||
|
|
|||
|
void BLE::init()
|
|||
|
{
|
|||
|
m_DiscoveryAgent = new QBluetoothDeviceDiscoveryAgent();
|
|||
|
m_DiscoveryAgent->setLowEnergyDiscoveryTimeout(5000);
|
|||
|
connect(m_DiscoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered,[=](const QBluetoothDeviceInfo &info){
|
|||
|
if (info.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration){
|
|||
|
qDebug()<<info.name()<<info.address().toString();
|
|||
|
bleDevicesList.append(info);
|
|||
|
}
|
|||
|
});
|
|||
|
connect(m_DiscoveryAgent, QOverload<QBluetoothDeviceDiscoveryAgent::Error>::of(&QBluetoothDeviceDiscoveryAgent::error),[=](QBluetoothDeviceDiscoveryAgent::Error error){
|
|||
|
if (error == QBluetoothDeviceDiscoveryAgent::PoweredOffError){
|
|||
|
qDebug("The Bluetooth is powered off.");
|
|||
|
}
|
|||
|
else if (error == QBluetoothDeviceDiscoveryAgent::InputOutputError) {
|
|||
|
qDebug("Writing or reading from the device resulted in an error.");
|
|||
|
}
|
|||
|
});
|
|||
|
connect(m_DiscoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, [=]{
|
|||
|
if (bleDevicesList.isEmpty())
|
|||
|
qDebug("No Low Energy devices found...");
|
|||
|
else
|
|||
|
qDebug("Scan finished!");
|
|||
|
emit signal_scanFinished();
|
|||
|
isScanning = false;
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
//开始扫描设备
|
|||
|
void BLE::startScanDevices()
|
|||
|
{
|
|||
|
//清空设备列表
|
|||
|
bleDevicesList.clear();
|
|||
|
//开始扫描
|
|||
|
m_DiscoveryAgent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
|
|||
|
if(m_DiscoveryAgent->isActive()){
|
|||
|
qDebug("Scanning.\n");
|
|||
|
isScanning = true;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//连接设备
|
|||
|
void BLE::connectDevice(QString address)
|
|||
|
{
|
|||
|
for(auto dev : bleDevicesList){
|
|||
|
if(dev.address().toString() == address){
|
|||
|
nowDevice = dev;
|
|||
|
}
|
|||
|
}
|
|||
|
if(!nowDevice.isValid()){
|
|||
|
qDebug("Not a valid device");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
servicesList.clear();
|
|||
|
characterList.clear();
|
|||
|
|
|||
|
if (m_LowController && previousAddress != nowDevice.address().toString()) {
|
|||
|
m_LowController->disconnectFromDevice();
|
|||
|
delete m_LowController;
|
|||
|
m_LowController = nullptr;
|
|||
|
}
|
|||
|
|
|||
|
if (!m_LowController) {
|
|||
|
m_LowController = QLowEnergyController::createCentral(nowDevice);
|
|||
|
connect(m_LowController, &QLowEnergyController::connected,[=](){
|
|||
|
qDebug("Device connect success.");
|
|||
|
m_LowController->discoverServices();
|
|||
|
});
|
|||
|
connect(m_LowController, QOverload<QLowEnergyController::Error>::of(&QLowEnergyController::error),[=](QLowEnergyController::Error){
|
|||
|
qDebug()<<"Error : "+m_LowController->errorString();
|
|||
|
});
|
|||
|
connect(m_LowController, &QLowEnergyController::disconnected,[=]{
|
|||
|
qDebug("Device disconnected.");
|
|||
|
});
|
|||
|
connect(m_LowController, &QLowEnergyController::serviceDiscovered,[=]{
|
|||
|
//
|
|||
|
});
|
|||
|
connect(m_LowController, &QLowEnergyController::discoveryFinished,[=]{
|
|||
|
qDebug("Services scan finished.");
|
|||
|
|
|||
|
servicesUUIDList = m_LowController->services();
|
|||
|
for(auto s : servicesUUIDList){
|
|||
|
qDebug()<<s.toString();
|
|||
|
}
|
|||
|
emit signal_findservicesFinished();
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
m_LowController->connectToDevice();
|
|||
|
previousAddress = nowDevice.address().toString();
|
|||
|
}
|
|||
|
|
|||
|
void BLE::connectService(QString uuid)
|
|||
|
{
|
|||
|
QLowEnergyService *service = nullptr;
|
|||
|
|
|||
|
for(int i=0;i<servicesUUIDList.length();i++)
|
|||
|
{
|
|||
|
if(servicesUUIDList.at(i).toString() == uuid){
|
|||
|
service = m_LowController->createServiceObject(servicesUUIDList.at(i));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!service)
|
|||
|
return;
|
|||
|
characterList.clear();
|
|||
|
|
|||
|
|
|||
|
if (service->state() == QLowEnergyService::DiscoveryRequired) {
|
|||
|
connect(service, &QLowEnergyService::stateChanged,this, &BLE::serviceDetailsDiscovered);
|
|||
|
service->discoverDetails();
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void BLE::serviceDetailsDiscovered(QLowEnergyService::ServiceState newState)
|
|||
|
{
|
|||
|
qDebug()<<"State : "<<newState;
|
|||
|
|
|||
|
if (newState != QLowEnergyService::ServiceDiscovered) {
|
|||
|
if (newState != QLowEnergyService::DiscoveringServices) {
|
|||
|
|
|||
|
}
|
|||
|
return;
|
|||
|
}
|
|||
|
auto service = qobject_cast<QLowEnergyService *>(sender());
|
|||
|
if (!service){
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
//BLE设备特征值改变
|
|||
|
connect(service, &QLowEnergyService::characteristicChanged,[=](const QLowEnergyCharacteristic &c, const QByteArray &value){
|
|||
|
QString Charuuid = c.uuid().toString();
|
|||
|
QString Value = value.toHex();
|
|||
|
qDebug()<<"BLE设备-"+Charuuid+"特性值发生变化:"+ Value;
|
|||
|
});
|
|||
|
//当特征读取请求成功返回其值时,发出此信号。
|
|||
|
connect(service,&QLowEnergyService::characteristicRead,[=](const QLowEnergyCharacteristic &c, const QByteArray &value){
|
|||
|
QString Charname = c.uuid().toString();
|
|||
|
QString Value = value.toHex();
|
|||
|
qDebug()<<"BLE设备-"+Charname+"特性值读取到的值:"+ Value;
|
|||
|
});
|
|||
|
//当特性值成功更改为newValue时,会发出此信号。
|
|||
|
connect(service,&QLowEnergyService::characteristicWritten,[=](const QLowEnergyCharacteristic &c, const QByteArray &value){
|
|||
|
QString Charname = c.uuid().toString();
|
|||
|
QString Value = value.toHex();
|
|||
|
qDebug()<<"BLE设备-"+Charname+"特性值成功写入值:"+ Value;
|
|||
|
});
|
|||
|
//描述符修改
|
|||
|
connect(service,&QLowEnergyService::descriptorWritten,[=](const QLowEnergyDescriptor &descriptor, const QByteArray &newValue){
|
|||
|
QString Charname = QString("%1").arg(descriptor.name());
|
|||
|
qDebug()<<"BLE设备-"+Charname+"描述符成功写入值:"+ QString(newValue);
|
|||
|
});
|
|||
|
//各种错误信息
|
|||
|
connect(service, static_cast<void(QLowEnergyService::*)(QLowEnergyService::ServiceError)>(&QLowEnergyService::error),
|
|||
|
[=](QLowEnergyService::ServiceError newErrorr)
|
|||
|
{
|
|||
|
if(QLowEnergyService::NoError == newErrorr){
|
|||
|
qDebug()<<"没有发生错误。\n";
|
|||
|
}
|
|||
|
if(QLowEnergyService::OperationError==newErrorr){
|
|||
|
qDebug()<<"错误: 当服务没有准备好时尝试进行操作!\n";
|
|||
|
}
|
|||
|
if(QLowEnergyService::CharacteristicReadError==newErrorr){
|
|||
|
qDebug()<<"尝试读取特征值失败!\n";
|
|||
|
}
|
|||
|
if(QLowEnergyService::CharacteristicWriteError==newErrorr){
|
|||
|
qDebug()<<"尝试为特性写入新值失败!\n";
|
|||
|
}
|
|||
|
if(QLowEnergyService::DescriptorReadError==newErrorr){
|
|||
|
qDebug()<<"尝试读取描述符值失败!\n";
|
|||
|
}
|
|||
|
if(QLowEnergyService::DescriptorWriteError==newErrorr){
|
|||
|
qDebug()<<"尝试向描述符写入新值失败!\n";
|
|||
|
}
|
|||
|
if(QLowEnergyService::UnknownError==newErrorr){
|
|||
|
qDebug()<<"与服务交互时发生未知错误!\n";
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
characterList = service->characteristics();
|
|||
|
emit signal_findcharsFinished();
|
|||
|
|
|||
|
for(auto s : characterList){
|
|||
|
qDebug()<<s.uuid();
|
|||
|
}
|
|||
|
|
|||
|
for (const QLowEnergyCharacteristic &ch : characterList) {
|
|||
|
if(ch.isValid()){
|
|||
|
if(ch.properties() & QLowEnergyCharacteristic::Notify){
|
|||
|
QLowEnergyDescriptor notice = ch.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
|
|||
|
if(notice.isValid()){
|
|||
|
service->writeDescriptor(notice,QByteArray::fromHex("0100"));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if(ch.properties() & QLowEnergyCharacteristic::WriteNoResponse || ch.properties() & QLowEnergyCharacteristic::Write){
|
|||
|
QByteArray arr;
|
|||
|
arr.resize(20);
|
|||
|
for(int i=0;i<20;i++){
|
|||
|
arr[i] = static_cast<char>(i);
|
|||
|
}
|
|||
|
service->writeCharacteristic(ch,arr);
|
|||
|
}
|
|||
|
if(ch.properties() & QLowEnergyCharacteristic::Read){
|
|||
|
service->readCharacteristic(ch);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|