3 #include <QRegularExpression>
5 #define UARTSERVICEUUID "6e400001-b5a3-f393-e0a9-e50e24dcca9e"
6 #define RXUUID "6e400002-b5a3-f393-e0a9-e50e24dcca9e"
7 #define TXUUID "6e400003-b5a3-f393-e0a9-e50e24dcca9e"
13 _timer = startTimer(std::chrono::milliseconds{10});
28 std::lock_guard guard(_cmdMutex);
29 _cmd += QString::fromStdString(cmd);
32 void BLEProthesisInterfaceQtWorker::cleanup()
43 _control->disconnectFromDevice();
57 if (_deviceDiscoveryAgent)
59 delete _deviceDiscoveryAgent;
60 _deviceDiscoveryAgent =
nullptr;
68 qDebug() <<
'[' << _mac <<
']' <<
" Stopping NOW!";
76 _deviceDiscoveryAgent =
new QBluetoothDeviceDiscoveryAgent;
77 connect(_deviceDiscoveryAgent, SIGNAL(deviceDiscovered(
const QBluetoothDeviceInfo&)),
78 this, SLOT(deviceDiscovered(
const QBluetoothDeviceInfo&)));
79 connect(_deviceDiscoveryAgent, SIGNAL(error(QBluetoothDeviceDiscoveryAgent::Error)),
80 this, SLOT(deviceDiscoverError(QBluetoothDeviceDiscoveryAgent::Error)));
81 connect(_deviceDiscoveryAgent, SIGNAL(finished()),
this, SLOT(deviceDiscoverFinished()));
82 connect(_deviceDiscoveryAgent, SIGNAL(canceled()),
this, SLOT(deviceDiscoverFinished()));
83 qDebug() <<
'[' << _mac <<
']' <<
" State DiscoveringDevices";
85 _deviceDiscoveryAgent->start();
89 if (!_deviceDiscovered)
91 qDebug() <<
'[' << _mac <<
']' <<
" Device discovering failed!";
95 qDebug() <<
'[' << _mac <<
']' <<
" State Disconnected";
110 _serviceDiscovered =
false;
111 _control =
new QLowEnergyController(_currentDevice);
112 _control ->setRemoteAddressType(QLowEnergyController::RandomAddress);
114 connect(_control, SIGNAL(serviceDiscovered(QBluetoothUuid)),
115 this, SLOT(serviceDiscovered(QBluetoothUuid)));
116 connect(_control, SIGNAL(discoveryFinished()),
117 this, SLOT(serviceScanDone()));
118 connect(_control, SIGNAL(error(QLowEnergyController::Error)),
119 this, SLOT(controllerError(QLowEnergyController::Error)));
120 connect(_control, SIGNAL(connected()),
121 this, SLOT(deviceConnected()));
122 connect(_control, SIGNAL(disconnected()),
123 this, SLOT(deviceDisconnected()));
124 _control->connectToDevice();
125 qDebug() <<
'[' << _mac <<
']' <<
" State Connecting";
130 _control->discoverServices();
131 qDebug() <<
'[' << _mac <<
']' <<
" State DiscoveringServices";
136 if (!_serviceDiscovered)
138 qDebug() <<
'[' << _mac <<
']' <<
" Service discovering failed!";
142 _service = _control->createServiceObject(QBluetoothUuid(QUuid(
UARTSERVICEUUID)));
144 connect(_service, SIGNAL(stateChanged(QLowEnergyService::ServiceState)),
145 this, SLOT(serviceStateChanged(QLowEnergyService::ServiceState)));
146 connect(_service, SIGNAL(characteristicChanged(QLowEnergyCharacteristic, QByteArray)),
147 this, SLOT(readData(QLowEnergyCharacteristic, QByteArray)));
148 connect(_service, SIGNAL(descriptorWritten(QLowEnergyDescriptor, QByteArray)),
149 this, SLOT(receiveDeviceDisconnec(QLowEnergyDescriptor, QByteArray)));
151 _service->discoverDetails();
153 qDebug() <<
'[' << _mac <<
']' <<
" State ConnectingService";
158 std::lock_guard g(_cmdMutex);
159 if (_service && _cmd.size() != 0)
161 const QLowEnergyCharacteristic RxChar = _service->characteristic(QBluetoothUuid(QUuid(
RXUUID)));
164 _service->writeCharacteristic(RxChar,
data, QLowEnergyService::WriteWithoutResponse);
165 if (_owner->_verboseSend)
167 qDebug() <<
'[' << _mac <<
']' <<
" send: " << _cmd;
174 void BLEProthesisInterfaceQtWorker::deviceDiscovered(
const QBluetoothDeviceInfo& device)
176 if (device.address().toString() == _mac)
178 qDebug() <<
'[' << _mac <<
']' <<
" Discovered target device " << device.address().toString();
179 _currentDevice = device;
180 _deviceDiscovered =
true;
181 qDebug() <<
'[' << _mac <<
']' <<
" State DiscoveringDevicesDone";
183 _deviceDiscoveryAgent->stop();
187 qDebug() <<
'[' << _mac <<
']' <<
" Discovered device " << device.address().toString();
191 void BLEProthesisInterfaceQtWorker::deviceDiscoverFinished()
193 qDebug() <<
'[' << _mac <<
']' <<
" Discovering of services done.";
197 void BLEProthesisInterfaceQtWorker::deviceDiscoverError(QBluetoothDeviceDiscoveryAgent::Error error)
199 if (error == QBluetoothDeviceDiscoveryAgent::PoweredOffError)
201 qDebug() <<
'[' << _mac <<
']' <<
"The Bluetooth adaptor is powered off, power it on before doing discovery.";
203 else if (error == QBluetoothDeviceDiscoveryAgent::InputOutputError)
205 qDebug() <<
'[' << _mac <<
']' <<
"Writing or reading from the device resulted in an error.";
209 qDebug() <<
'[' << _mac <<
']' <<
"An unknown error has occurred.";
214 void BLEProthesisInterfaceQtWorker::serviceDiscovered(
const QBluetoothUuid& gatt)
216 qDebug() <<
'[' << _mac <<
']' <<
" Discovered service " << gatt.toString();
219 qDebug() <<
'[' << _mac <<
']' <<
"Discovered UART service " << gatt.toString();
220 _serviceDiscovered =
true;
225 void BLEProthesisInterfaceQtWorker::serviceDiscoverFinished()
227 qDebug() <<
'[' << _mac <<
']' <<
" State DiscoveringServicesDone";
231 void BLEProthesisInterfaceQtWorker::controllerError(QLowEnergyController::Error error)
233 qDebug() <<
'[' << _mac <<
']' <<
" Cannot connect to remote device.";
234 qWarning() <<
'[' << _mac <<
']' <<
" Controller Error:" << error;
238 void BLEProthesisInterfaceQtWorker::receiveDeviceDisconnec(
const QLowEnergyDescriptor& d,
const QByteArray&
value)
240 if (d.isValid() && d == _notificationDescTx &&
value == QByteArray(
"0000"))
242 qDebug() <<
'[' << _mac <<
']' <<
"Device requests disconnect.";
244 _control->disconnectFromDevice();
253 void BLEProthesisInterfaceQtWorker::serviceStateChanged(QLowEnergyService::ServiceState
s)
256 qDebug() <<
'[' << _mac <<
']' <<
" serviceStateChanged -> " <<
s;
259 case QLowEnergyService::ServiceDiscovered:
263 const QLowEnergyCharacteristic TxChar = _service->characteristic(QBluetoothUuid(QUuid(
TXUUID)));
264 if (!TxChar.isValid())
266 qDebug() <<
'[' << _mac <<
']' <<
" Tx characteristic not found";
271 const QLowEnergyCharacteristic RxChar = _service->characteristic(QBluetoothUuid(QUuid(
RXUUID)));
272 if (!RxChar.isValid())
274 qDebug() <<
'[' << _mac <<
']' <<
" Rx characteristic not found";
281 _notificationDescTx = TxChar.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
282 if (_notificationDescTx.isValid())
285 _service->writeDescriptor(_notificationDescTx, QByteArray::fromHex(
"0100"));
286 qDebug() <<
'[' << _mac <<
']' <<
" State Running";
296 void BLEProthesisInterfaceQtWorker::deviceConnected()
298 qDebug() <<
'[' << _mac <<
']' <<
" State ConnectingDone";
302 void BLEProthesisInterfaceQtWorker::deviceDisconnected()
304 qDebug() <<
'[' << _mac <<
']' <<
" State Disconnected";
310 void BLEProthesisInterfaceQtWorker::consumeData<BLEProthesisInterface::SensorValueProtocol::tpos_tpwm_fpos_fpwm>()
312 if (!_valueAkk.contains(
'\n'))
314 if (_owner->_verboseReceive)
316 qDebug() <<
'[' << _mac <<
']' <<
" data does not contain \\n -> no new sensor values\n Buffer:\n" << _valueAkk;
320 auto listPacks = _valueAkk.split(
'\n');
322 if (_owner->_verboseReceive)
324 qDebug() <<
'[' << _mac <<
']' <<
" parsing " << listPacks.at(listPacks.size() - 2);
327 auto listVals = listPacks.at(listPacks.size() - 2).split(
' ');
328 _owner->_thumbPos = listVals.at(0).toLong();
329 _owner->_thumbPWM = listVals.at(1).toLong();
330 _owner->_fingerPos = listVals.at(2).toLong();
331 _owner->_fingerPWM = listVals.at(3).toLong();
333 _valueAkk = listPacks.back();
337 void BLEProthesisInterfaceQtWorker::consumeData<BLEProthesisInterface::SensorValueProtocol::mx_pos_pwm>()
339 if (!_valueAkk.contains(
'\n'))
341 if (_owner->_verboseReceive)
343 qDebug() <<
'[' << _mac <<
']' <<
" data does not contain \\n -> no new sensor values\n Buffer:\n" << _valueAkk;
347 auto listPacks = _valueAkk.split(
'\n');
349 static const QRegularExpression m2(R
"(^M2:[ \t]+Pos.:[ \t]+(-?[1-9][0-9]*|0)[ \t]+PWM:[ \t]+(-?[1-9][0-9]*|0)[ \t\n\r]+$)");
350 static const QRegularExpression m3(R
"(^M3:[ \t]+Pos.:[ \t]+(-?[1-9][0-9]*|0)[ \t]+PWM:[ \t]+(-?[1-9][0-9]*|0)[ \t\n\r]+$)");
352 for (
int i = 0; i < listPacks.size() - 1; ++i)
354 if (listPacks.at(i).size() == 0)
358 if (_owner->_verboseReceive)
360 qDebug() <<
'[' << _mac <<
']' <<
" parsing " << listPacks.at(i);
362 if (
const auto matchM2 = m2.match(listPacks.at(i)); matchM2.hasMatch())
364 _owner->_thumbPos = matchM2.captured(1).toLong();
365 _owner->_thumbPWM = matchM2.captured(2).toLong();
366 if (_owner->_verboseReceive)
368 qDebug() <<
'[' << _mac <<
']' <<
" updated M2";
371 else if (
const auto matchM3 = m3.match(listPacks.at(i)); matchM3.hasMatch())
373 _owner->_fingerPos = matchM3.captured(1).toLong();
374 _owner->_fingerPWM = matchM3.captured(2).toLong();
375 if (_owner->_verboseReceive)
377 qDebug() <<
'[' << _mac <<
']' <<
" updated M3";
382 qWarning() <<
"unknown format for data: " << listPacks.at(i).toLocal8Bit() <<
"\nSkipping";
385 _valueAkk = listPacks.back();
388 void BLEProthesisInterfaceQtWorker::readData(
const QLowEnergyCharacteristic&
c,
const QByteArray&
value)
391 if (
c.uuid() != QBluetoothUuid(QUuid(
TXUUID)))
395 if (_owner->_verboseReceive)
397 qDebug() <<
'[' << _mac <<
']' <<
" received : " <<
value;
400 _valueAkk.append(
value.data());
402 switch (_owner->_protocol)
405 consumeData<BLEProthesisInterface::SensorValueProtocol::tpos_tpwm_fpos_fpwm>();
408 consumeData<BLEProthesisInterface::SensorValueProtocol::mx_pos_pwm>();