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);
|
||
}
|
||
}
|
||
}
|
||
}
|