228 lines
7.9 KiB
C++
Raw Normal View History

2024-11-25 17:15:44 +08:00
#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);
}
}
}
}