summaryrefslogtreecommitdiffstats
path: root/src/bluetooth
diff options
context:
space:
mode:
authorNedim Hadzic <nhadzic@blackberry.com>2014-03-20 12:08:08 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-03-25 11:46:14 +0100
commitec4aa0bcb592e9668b0767906157a1a51915d76c (patch)
treea3670134427ed8191a247d44031dcdb7135ba212 /src/bluetooth
parent5c9d111edbdf73a4875bcf9ea02a3057659f7730 (diff)
Added and improved error handling in controller class
Error enums added and implemented together with examples. Change-Id: I912c396080ee9a6b87f41104eb7e41f8c62abf8b Reviewed-by: Alex Blasche <alexander.blasche@digia.com>
Diffstat (limited to 'src/bluetooth')
-rw-r--r--src/bluetooth/qlowenergycontroller.cpp29
-rw-r--r--src/bluetooth/qlowenergycontroller.h13
-rw-r--r--src/bluetooth/qlowenergycontroller_bluez.cpp19
-rw-r--r--src/bluetooth/qlowenergycontroller_p.cpp3
-rw-r--r--src/bluetooth/qlowenergycontroller_p.h1
-rw-r--r--src/bluetooth/qlowenergycontroller_qnx.cpp72
6 files changed, 99 insertions, 38 deletions
diff --git a/src/bluetooth/qlowenergycontroller.cpp b/src/bluetooth/qlowenergycontroller.cpp
index 3ff8e131..d993e205 100644
--- a/src/bluetooth/qlowenergycontroller.cpp
+++ b/src/bluetooth/qlowenergycontroller.cpp
@@ -65,7 +65,20 @@ QT_BEGIN_NAMESPACE
service on the same LE device.
- \sa QLowEnergyServiceInfo, QLowEnergyCharacteristicInfo
+ \sa QLowEnergyServiceInfo, QLowEnergyCharacteristicInfo, QLowEnergyDescriptorInfo
+*/
+
+/*!
+ \enum QLowEnergyController::Error
+
+ Indicates all possible error conditions found during Bluetooth Low Energy communication.
+
+ \value NoError No error has occurred.
+ \value UnknownError An unknown error has occurred.
+ \value InputOutputError BLE device is not responding.
+ \value OperationError The error occurred while communicating with the BLE device
+ (connecting, disconnecting, receiving updates,etc).
+ \value PermissionError Characteristic does not have required permissions.
*/
/*!
@@ -78,7 +91,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn void QLowEnergyController::error(const QLowEnergyServiceInfo &)
+ \fn void QLowEnergyController::error(const QLowEnergyServiceInfo &, QLowEnergyController::Error)
This signal is emitted when the service error occurs.
@@ -86,7 +99,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn void QLowEnergyController::error(const QLowEnergyCharacteristicInfo &)
+ \fn void QLowEnergyController::error(const QLowEnergyCharacteristicInfo &, QLowEnergyController::Error)
This signal is emitted when the characteristic error occurs.
@@ -235,4 +248,14 @@ bool QLowEnergyController::writeDescriptor(const QLowEnergyDescriptorInfo &descr
return d_ptr->write(descriptor);
}
+/*!
+ This method returns the last error that was emitted.
+
+ \sa errorString(), error()
+ */
+QLowEnergyController::Error QLowEnergyController::error() const
+{
+ return d_ptr->error;
+}
+
QT_END_NAMESPACE
diff --git a/src/bluetooth/qlowenergycontroller.h b/src/bluetooth/qlowenergycontroller.h
index e993d8d7..53e29343 100644
--- a/src/bluetooth/qlowenergycontroller.h
+++ b/src/bluetooth/qlowenergycontroller.h
@@ -57,6 +57,13 @@ class Q_BLUETOOTH_EXPORT QLowEnergyController: public QObject
{
Q_OBJECT
public:
+ enum Error {
+ NoError,
+ UnknownError,
+ OperationError,
+ InputOutputError,
+ PermissionError
+ };
QLowEnergyController(QObject *parent = 0);
QLowEnergyController(const QBluetoothAddress &localAdapter, QObject *parent = 0);
~QLowEnergyController();
@@ -75,15 +82,15 @@ public:
QString errorString() const;
void setRandomAddress();
+ Error error() const;
Q_SIGNALS:
void connected(const QLowEnergyServiceInfo &);
+ void error(const QLowEnergyServiceInfo &, QLowEnergyController::Error);
+ void error(const QLowEnergyCharacteristicInfo &, QLowEnergyController::Error);
void disconnected(const QLowEnergyServiceInfo &);
-
void valueChanged(const QLowEnergyCharacteristicInfo &);
- void error(const QLowEnergyServiceInfo &);
- void error(const QLowEnergyCharacteristicInfo &);
private:
Q_DECLARE_PRIVATE(QLowEnergyController)
QLowEnergyControllerPrivate *d_ptr;
diff --git a/src/bluetooth/qlowenergycontroller_bluez.cpp b/src/bluetooth/qlowenergycontroller_bluez.cpp
index fcf94bda..8fc7bf23 100644
--- a/src/bluetooth/qlowenergycontroller_bluez.cpp
+++ b/src/bluetooth/qlowenergycontroller_bluez.cpp
@@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ)
QLowEnergyControllerPrivate::QLowEnergyControllerPrivate():
- m_randomAddress(false), m_step(0), m_commandStarted(false)
+ error(QLowEnergyController::NoError), m_randomAddress(false), m_step(0), m_commandStarted(false)
{
}
@@ -132,14 +132,17 @@ void QLowEnergyControllerPrivate::_q_replyReceived(const QString &reply)
connectToTerminal();
if (reply.contains(QStringLiteral("Connection refused (111)"))) {
errorString = QStringLiteral("Connection refused (111)");
+ error = QLowEnergyController::InputOutputError;
disconnectAllServices();
}
else if (reply.contains(QStringLiteral("Device busy"))) {
- errorString = QStringLiteral("Connection refused (111)");
+ errorString = QStringLiteral("Device busy");
+ error = QLowEnergyController::InputOutputError;
disconnectAllServices();
}
else if (reply.contains(QStringLiteral("disconnected"))) {
errorString = QStringLiteral("Trying to execute command on disconnected service");
+ error = QLowEnergyController::OperationError;
disconnectAllServices();
}
else {
@@ -328,8 +331,8 @@ void QLowEnergyControllerPrivate::disconnectAllServices()
m_leServices.at(i).d_ptr->connected = false;
emit q_ptr->disconnected(m_leServices.at(i));
}
- if (errorString != QString())
- emit q_ptr->error(m_leServices.at(i));
+ if (error != QLowEnergyController::NoError)
+ emit q_ptr->error(m_leServices.at(i), error);
m_step = 0;
}
m_leServices.clear();
@@ -404,9 +407,9 @@ bool QLowEnergyControllerPrivate::enableNotification(const QLowEnergyCharacteris
}
}
}
-
+ error = QLowEnergyController::UnknownError;
errorString = QStringLiteral("Characteristic or notification descriptor not found.");
- emit q_ptr->error(characteristic);
+ emit q_ptr->error(characteristic, error);
return false;
}
@@ -438,13 +441,15 @@ bool QLowEnergyControllerPrivate::write(const QLowEnergyCharacteristicInfo &char
writeValue(characteristic.handle(), characteristic.value());
return true;
} else {
+ error = QLowEnergyController::PermissionError;
errorString = QStringLiteral("This characteristic does not support write operations.");
}
} else {
+ error = QLowEnergyController::OperationError;
errorString = QStringLiteral("The device is not connected or characteristic is not valid");
}
- emit q_ptr->error(characteristic);
+ emit q_ptr->error(characteristic, error);
return false;
}
diff --git a/src/bluetooth/qlowenergycontroller_p.cpp b/src/bluetooth/qlowenergycontroller_p.cpp
index de634133..07d58fdd 100644
--- a/src/bluetooth/qlowenergycontroller_p.cpp
+++ b/src/bluetooth/qlowenergycontroller_p.cpp
@@ -44,7 +44,8 @@
QT_BEGIN_NAMESPACE
-QLowEnergyControllerPrivate::QLowEnergyControllerPrivate()
+QLowEnergyControllerPrivate::QLowEnergyControllerPrivate():
+ error(QLowEnergyController::NoError)
{
}
diff --git a/src/bluetooth/qlowenergycontroller_p.h b/src/bluetooth/qlowenergycontroller_p.h
index 971cd7dd..45cefdc8 100644
--- a/src/bluetooth/qlowenergycontroller_p.h
+++ b/src/bluetooth/qlowenergycontroller_p.h
@@ -62,6 +62,7 @@ public:
QList<QLowEnergyServiceInfo> m_leServices;
QString errorString;
+ QLowEnergyController::Error error;
#ifdef QT_QNX_BLUETOOTH
static void serviceConnected(const char*, const char*, int, int, short unsigned int, short unsigned int, short unsigned int, void*);
diff --git a/src/bluetooth/qlowenergycontroller_qnx.cpp b/src/bluetooth/qlowenergycontroller_qnx.cpp
index bf1a57d7..ac8bb551 100644
--- a/src/bluetooth/qlowenergycontroller_qnx.cpp
+++ b/src/bluetooth/qlowenergycontroller_qnx.cpp
@@ -129,8 +129,9 @@ void QLowEnergyControllerPrivate::serviceConnected(const char *bdaddr, const cha
if (err != 0) {
qCDebug(QT_BT_QNX) << "An error occurred in service connected callback: " << qt_error_string(err);
+ p->error = QLowEnergyController::OperationError;
p->errorString = qt_error_string(err);
- p->q_ptr->error(p->m_leServices.at(index));
+ Q_EMIT p->q_ptr->error(p->m_leServices.at(index), p->error);
}
if (index != -1) {
p->m_leServices.at(index).d_ptr->characteristicList.clear();
@@ -139,8 +140,9 @@ void QLowEnergyControllerPrivate::serviceConnected(const char *bdaddr, const cha
if (!data) {
qCDebug(QT_BT_QNX) << "[SERVICE: Connected] GATT characteristics: Not enough memory";
bt_gatt_disconnect_instance(instance);
+ p->error = QLowEnergyController::OperationError;
p->errorString = QStringLiteral("GATT characteristics: Not enough memory");
- p->q_ptr->error(p->m_leServices.at(index));
+ Q_EMIT p->q_ptr->error(p->m_leServices.at(index), p->error);
return;
}
@@ -154,8 +156,9 @@ void QLowEnergyControllerPrivate::serviceConnected(const char *bdaddr, const cha
if (!allCharacteristicList) {
qCDebug(QT_BT_QNX) <<" GATT characteristics: Not enough memory";
bt_gatt_disconnect_instance(instance);
+ p->error = QLowEnergyController::OperationError;
p->errorString = QStringLiteral("GATT characteristics: Not enough memory");
- p->q_ptr->error(p->m_leServices.at(index));
+ Q_EMIT p->q_ptr->error(p->m_leServices.at(index), p->error);
return;
}
@@ -200,8 +203,9 @@ void QLowEnergyControllerPrivate::serviceConnected(const char *bdaddr, const cha
int rc = bt_gatt_reg_notifications(instance, &(p->serviceNotification));
if (!rc) {
qCDebug(QT_BT_QNX) << "[SERVICE: Connected] bt_gatt_reg_notifications failed." << errno << qt_error_string(errno);
+ p->error = QLowEnergyController::OperationError;
p->errorString = qt_error_string(errno);
- p->q_ptr->error(p->m_leServices.at(index));
+ Q_EMIT p->q_ptr->error(p->m_leServices.at(index), p->error);
} else {
qCDebug(QT_BT_QNX) << "[SERVICE: Connected] bt_gatt_reg_notifications was presumably OK";
}
@@ -222,7 +226,7 @@ void QLowEnergyControllerPrivate::serviceConnected(const char *bdaddr, const cha
p->m_leServices.at(index).d_ptr->connected = true;
qCDebug(QT_BT_QNX) << p;
- emit p->q_ptr->connected(p->m_leServices.at(index));
+ Q_EMIT p->q_ptr->connected(p->m_leServices.at(index));
qCDebug(QT_BT_QNX) << "---------------------------------------------------------------------------------";
} else {
qCDebug(QT_BT_QNX) << "Unregistered service connected";
@@ -263,7 +267,7 @@ void QLowEnergyControllerPrivate::serviceNotification(int instance, short unsign
p->m_leServices.at(i).d_ptr->characteristicList.at(j).d_ptr->notification = true;
p->m_leServices.at(i).d_ptr->characteristicList.at(j).d_ptr->value = receivedValue;
- p->q_ptr->valueChanged(p->m_leServices.at(i).d_ptr->characteristicList.at(j));
+ Q_EMIT p->q_ptr->valueChanged(p->m_leServices.at(i).d_ptr->characteristicList.at(j));
current = true;
}
}
@@ -305,7 +309,7 @@ void QLowEnergyControllerPrivate::serviceDisconnected(const char *bdaddr, const
leUuid = QBluetoothUuid(lowEnergyUuid.toUShort(0,0));
}
QLowEnergyServiceInfo leService(leUuid);
- emit p->q_ptr->connected(leService);
+ Q_EMIT p->q_ptr->connected(leService);
qCDebug(QT_BT_QNX) << "---------------------------------------------------";
qCDebug(QT_BT_QNX) << "[SERVICE: Disconnect] (service, instance, reason):" << service << instance << reason;
@@ -315,7 +319,8 @@ void QLowEnergyControllerPrivate::serviceDisconnected(const char *bdaddr, const
delete classPointer;
}
-QLowEnergyControllerPrivate::QLowEnergyControllerPrivate()
+QLowEnergyControllerPrivate::QLowEnergyControllerPrivate():
+ error(QLowEnergyController::NoError)
{
qRegisterMetaType<QLowEnergyServiceInfo>("QLowEnergyServiceInfo");
qRegisterMetaType<QLowEnergyCharacteristicInfo>("QLowEnergyCharacteristicInfo");
@@ -328,9 +333,11 @@ QLowEnergyControllerPrivate::~QLowEnergyControllerPrivate()
void QLowEnergyControllerPrivate::connectService(const QLowEnergyServiceInfo &service)
{
+ Q_Q(QLowEnergyController);
if (!service.isValid()) {
+ error = QLowEnergyController::UnknownError;
errorString = QStringLiteral("Service not valid.");
- emit q_ptr->error(service);
+ Q_EMIT q->error(service, error);
return;
}
@@ -338,8 +345,9 @@ void QLowEnergyControllerPrivate::connectService(const QLowEnergyServiceInfo &se
for (int i = 0; i < m_leServices.size(); i++) {
if (m_leServices.at(i).serviceUuid() == service.serviceUuid()) {
if (m_leServices.at(i).isConnected()) {
+ error = QLowEnergyController::OperationError;
errorString = QStringLiteral("Service already connected");
- emit q_ptr->error(m_leServices.at(i));
+ Q_EMIT q->error(m_leServices.at(i), error);
}
else {
m_leServices.replace(i, service);
@@ -357,16 +365,18 @@ void QLowEnergyControllerPrivate::connectService(const QLowEnergyServiceInfo &se
process = process->instance();
if (!process->isConnected()) {
qCDebug(QT_BT_QNX) << "[INIT] Init problem." << errno << qt_error_string(errno);
+ error = QLowEnergyController::InputOutputError;
errorString = QStringLiteral("Initialization of device falied. ") + qt_error_string(errno);
- emit q_ptr->error(service);
+ Q_EMIT q->error(service, error);
return;
}
errno = 0;
if (bt_gatt_init(&gatt_callbacks) < 0) {
qCDebug(QT_BT_QNX) << "[INIT] GAT Init problem." << errno << qt_error_string(errno);
+ error = QLowEnergyController::UnknownError;
errorString = QStringLiteral("Callbacks initialization failed. ") + qt_error_string(errno);
- emit q_ptr->error(service);
+ Q_EMIT q->error(service, error);
return;
}
if (bt_le_init(0) != EOK) {
@@ -390,14 +400,16 @@ void QLowEnergyControllerPrivate::connectService(const QLowEnergyServiceInfo &se
if (bt_gatt_connect_service(service.device().address().toString().toLocal8Bit().constData(), serviceUuid.toLocal8Bit().constData(), 0, &conParm, classPointer) < 0) {
qCDebug(QT_BT_QNX) << "[SERVICE] Connection to service failed." << errno << qt_error_string(errno);
+ error = QLowEnergyController::OperationError;
errorString = QStringLiteral("[SERVICE] Connection to service failed.") + qt_error_string(errno);
- emit q_ptr->error(service);
+ Q_EMIT q->error(service, error);
}
qCDebug(QT_BT_QNX) << "errno after connect: " << errno;
}
void QLowEnergyControllerPrivate::disconnectService(const QLowEnergyServiceInfo &leService)
{
+ Q_Q(QLowEnergyController);
if (leService.isValid()){
QString serviceUuid = leService.serviceUuid().toString().remove(QLatin1Char('{')).remove(QLatin1Char('}'));
if (leService.serviceName() == QStringLiteral("Unknown Service"))
@@ -407,8 +419,9 @@ void QLowEnergyControllerPrivate::disconnectService(const QLowEnergyServiceInfo
if (leService.isConnected()) {
if (bt_gatt_disconnect_service(leService.device().address().toString().toLocal8Bit().constData(), serviceUuid.toLocal8Bit().constData()) < 0) {
qCDebug(QT_BT_QNX) << "[SERVICE] Disconnect service request failed. " << errno << qt_error_string(errno);
+ error = QLowEnergyController::OperationError;
errorString = QStringLiteral("[SERVICE] Disconnect service request failed. ") + qt_error_string(errno);
- emit q_ptr->error(leService);
+ Q_EMIT q->error(leService, error);
} else {
for (int i = 0; i < m_leServices.size(); i++) {
if (leService.serviceUuid() == m_leServices.at(i).serviceUuid()) {
@@ -417,12 +430,13 @@ void QLowEnergyControllerPrivate::disconnectService(const QLowEnergyServiceInfo
}
}
leService.d_ptr->connected = false;
- emit q_ptr->disconnected(leService);
+ Q_EMIT q->disconnected(leService);
qCDebug(QT_BT_QNX) << "[SERVICE] Disconnected from service OK.";
}
} else {
+ error = QLowEnergyController::UnknownError;
errorString = QStringLiteral("Service is not connected");
- q_ptr->error(leService);
+ Q_EMIT q->error(leService, error);
}
} else {
disconnectAllServices();
@@ -431,6 +445,7 @@ void QLowEnergyControllerPrivate::disconnectService(const QLowEnergyServiceInfo
void QLowEnergyControllerPrivate::disconnectAllServices()
{
+ Q_Q(QLowEnergyController);
for (int i = 0; i < m_leServices.size(); i++) {
QString serviceUuid = m_leServices.at(i).serviceUuid().toString().remove(QLatin1Char('{')).remove(QLatin1Char('}'));
if (m_leServices.at(i).serviceName() == QStringLiteral("Unknown Service"))
@@ -442,11 +457,12 @@ void QLowEnergyControllerPrivate::disconnectAllServices()
qCDebug(QT_BT_QNX) << m_leServices.at(i).device().address().toString().toLocal8Bit().constData() << serviceUuid.toLocal8Bit().constData();
if (bt_gatt_disconnect_service( m_leServices.at(i).device().address().toString().toLocal8Bit().constData(), serviceUuid.toLocal8Bit().constData()) < 0) {
qCDebug(QT_BT_QNX) << "[SERVICE] Disconnect service request failed. " << errno << qt_error_string(errno);
+ error = QLowEnergyController::OperationError;
errorString = QStringLiteral("[SERVICE] Disconnect service request failed. ") + qt_error_string(errno);
- emit q_ptr->error( m_leServices.at(i));
+ Q_EMIT q->error( m_leServices.at(i), error);
} else {
m_leServices.at(i).d_ptr->connected = false;
- emit q_ptr->disconnected(m_leServices.at(i));
+ Q_EMIT q->disconnected(m_leServices.at(i));
qCDebug(QT_BT_QNX) << "[SERVICE] Disconnected from service OK.";
}
}
@@ -456,24 +472,28 @@ void QLowEnergyControllerPrivate::disconnectAllServices()
bool QLowEnergyControllerPrivate::enableNotification(const QLowEnergyCharacteristicInfo &characteristic)
{
+ Q_Q(QLowEnergyController);
if (characteristic.d_ptr->instance == -1) {
qCDebug(QT_BT_QNX) << " GATT service not connected ";
+ error = QLowEnergyController::UnknownError;
errorString = QStringLiteral("Service is not connected");
- emit q_ptr->error(characteristic);
+ Q_EMIT q->error(characteristic, error);
return false;
}
if (!(characteristic.d_ptr->permission & QLowEnergyCharacteristicInfo::Notify)) {
qCDebug(QT_BT_QNX) << "Notification changes not allowed";
+ error = QLowEnergyController::PermissionError;
errorString = QStringLiteral("This characteristic does not support notifications.");
- emit q_ptr->error(characteristic);
+ Q_EMIT q->error(characteristic, error);
return false;
}
int rc = bt_gatt_enable_notify(characteristic.d_ptr->instance, &characteristic.d_ptr->characteristic, 1);
if (!rc) {
qCDebug(QT_BT_QNX) << "bt_gatt_enable_notify errno=" << errno << qt_error_string(errno);
+ error = QLowEnergyController::OperationError;
errorString = qt_error_string(errno);
- emit q_ptr->error(characteristic);
+ Q_EMIT q->error(characteristic, error);
return false;
} else {
qCDebug(QT_BT_QNX) << "bt_gatt_enable_notify was presumably OK";
@@ -492,9 +512,11 @@ void QLowEnergyControllerPrivate::disableNotification(const QLowEnergyCharacteri
bool QLowEnergyControllerPrivate::write(const QLowEnergyCharacteristicInfo &characteristic)
{
+ Q_Q(QLowEnergyController);
if (!characteristic.isValid()) {
+ error = QLowEnergyController::UnknownError;
errorString = QStringLiteral("Characteristic not valid.");
- emit q_ptr->error(characteristic);
+ Q_EMIT q->error(characteristic, error);
return false;
}
@@ -503,12 +525,14 @@ bool QLowEnergyControllerPrivate::write(const QLowEnergyCharacteristicInfo &char
if (errorString == QString()) {
return true;
} else {
- emit q_ptr->error(characteristic);
+ error = QLowEnergyController::OperationError;
+ Q_EMIT q->error(characteristic, error);
return false;
}
} else {
+ error = QLowEnergyController::PermissionError;
errorString = QStringLiteral("Characteristic does not allow write operations. The wanted value was not written to the device.");
- emit q_ptr->error(characteristic);
+ Q_EMIT q->error(characteristic, error);
return false;
}