summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPetre Eftime <[email protected]>2016-05-25 12:43:12 +0300
committerPetre Eftime <[email protected]>2016-06-30 12:54:55 +0300
commit04f2c650964f5a9fa55dc9a6b87cdd69f0a2b2a9 (patch)
tree5ebf389cbad78cb7fba8d2c5fa6a7fa396c3a98a /src
parent34bd85eec952b8031dedd58882a9bcfeef57d848 (diff)
Add support for notifications
GATT Characteristics support push notifications as per BLE spec Other objects support most relevant "virtual" notifications (DBus properties changed) Signed-off-by: Petre Eftime <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/BluetoothAdapter.cpp108
-rw-r--r--src/BluetoothDevice.cpp126
-rw-r--r--src/BluetoothEvent.cpp9
-rw-r--r--src/BluetoothGattCharacteristic.cpp55
-rw-r--r--src/BluetoothGattDescriptor.cpp49
-rw-r--r--src/BluetoothManager.cpp2
-rw-r--r--src/tinyb_utils.cpp21
7 files changed, 361 insertions, 9 deletions
diff --git a/src/BluetoothAdapter.cpp b/src/BluetoothAdapter.cpp
index 49f69cb6..74f2c38d 100644
--- a/src/BluetoothAdapter.cpp
+++ b/src/BluetoothAdapter.cpp
@@ -24,6 +24,7 @@
#include "generated-code.h"
#include "tinyb_utils.hpp"
+#include "BluetoothNotificationHandler.hpp"
#include "BluetoothAdapter.hpp"
#include "BluetoothDevice.hpp"
#include "BluetoothManager.hpp"
@@ -31,6 +32,55 @@
using namespace tinyb;
+void BluetoothNotificationHandler::on_properties_changed_adapter(GDBusProxy *proxy, GVariant *changed_properties, GStrv invalidated_properties, gpointer userdata) {
+
+ auto c = static_cast<BluetoothAdapter*>(userdata);
+
+ if (!c->lock())
+ return;
+
+ if(g_variant_n_children(changed_properties) > 0) {
+ GVariantIter *iter = NULL;
+
+ GVariant *value;
+ const gchar *key;
+ g_variant_get(changed_properties, "a{sv}", &iter);
+ while (iter != nullptr && g_variant_iter_loop(iter, "{&sv}", &key, &value)) {
+ auto powered_callback = c->powered_callback;
+ if (powered_callback != nullptr && g_ascii_strncasecmp(key, "powered", 8) == 0) {
+ bool new_value;
+ g_variant_get(value, "b", &new_value);
+ powered_callback(new_value);
+ continue;
+ }
+ auto discoverable_callback = c->discoverable_callback;
+ if (discoverable_callback != nullptr && g_ascii_strncasecmp(key, "discoverable", 13) == 0) {
+ bool new_value;
+ g_variant_get(value, "b", &new_value);
+ discoverable_callback(new_value);
+ continue;
+ }
+ auto pairable_callback = c->pairable_callback;
+ if (pairable_callback != nullptr && g_ascii_strncasecmp(key, "pairable", 9) == 0) {
+ bool new_value;
+ g_variant_get(value, "b", &new_value);
+ pairable_callback(new_value);
+ continue;
+ }
+ auto discovering_callback = c->discovering_callback;
+ if (discovering_callback != nullptr && g_ascii_strncasecmp(key, "discovering", 12) == 0) {
+ bool new_value;
+ g_variant_get(value, "b", &new_value);
+ discovering_callback(new_value);
+ continue;
+ }
+ }
+ g_variant_iter_free (iter);
+ }
+
+ c->unlock();
+}
+
std::string BluetoothAdapter::get_class_name() const
{
return std::string("BluetoothAdapter");
@@ -55,6 +105,10 @@ BluetoothAdapter::BluetoothAdapter(Adapter1 *object)
{
this->object = object;
g_object_ref(object);
+
+ g_signal_connect(G_DBUS_PROXY(object), "g-properties-changed",
+ G_CALLBACK(BluetoothNotificationHandler::on_properties_changed_adapter), this);
+ valid = true;
}
BluetoothAdapter::BluetoothAdapter(const BluetoothAdapter &object)
@@ -69,6 +123,10 @@ BluetoothAdapter *BluetoothAdapter::clone() const
BluetoothAdapter::~BluetoothAdapter()
{
+ valid = false;
+ g_signal_handlers_disconnect_by_data(object, this);
+ lk.lock();
+
g_object_unref(object);
}
@@ -151,8 +209,6 @@ bool BluetoothAdapter::remove_device (
return result;
}
-
-
/* D-Bus property accessors: */
std::string BluetoothAdapter::get_address ()
{
@@ -184,6 +240,18 @@ bool BluetoothAdapter::get_powered ()
return adapter1_get_powered (object);
}
+void BluetoothAdapter::enable_powered_notifications(
+ std::function<void(BluetoothAdapter &adapter, bool powered, void *userdata)> callback,
+ void *userdata) {
+ powered_callback = std::bind(callback, std::ref(*this), std::placeholders::_1, userdata);
+}
+void BluetoothAdapter::enable_powered_notifications(std::function<void(bool powered)> callback) {
+ powered_callback = callback;
+}
+void BluetoothAdapter::disable_powered_notifications() {
+ powered_callback = nullptr;
+}
+
void BluetoothAdapter::set_powered (bool value)
{
if (get_powered() != value)
@@ -200,6 +268,18 @@ void BluetoothAdapter::set_discoverable (bool value)
adapter1_set_discoverable (object, value);
}
+void BluetoothAdapter::enable_discoverable_notifications(
+ std::function<void(BluetoothAdapter &adapter, bool discoverable, void *userdata)> callback,
+ void *userdata) {
+ discoverable_callback = std::bind(callback, std::ref(*this), std::placeholders::_1, userdata);
+}
+void BluetoothAdapter::enable_discoverable_notifications(std::function<void(bool discoverable)> callback) {
+ discoverable_callback = callback;
+}
+void BluetoothAdapter::disable_discoverable_notifications() {
+ discoverable_callback = nullptr;
+}
+
unsigned int BluetoothAdapter::get_discoverable_timeout ()
{
return adapter1_get_discoverable_timeout (object);
@@ -215,6 +295,18 @@ bool BluetoothAdapter::get_pairable ()
return adapter1_get_pairable (object);
}
+void BluetoothAdapter::enable_pairable_notifications(
+ std::function<void(BluetoothAdapter &adapter, bool pairable, void *userdata)> callback,
+ void *userdata) {
+ pairable_callback = std::bind(callback, std::ref(*this), std::placeholders::_1, userdata);
+}
+void BluetoothAdapter::enable_pairable_notifications(std::function<void(bool pairable)> callback) {
+ pairable_callback = callback;
+}
+void BluetoothAdapter::disable_pairable_notifications() {
+ pairable_callback = nullptr;
+}
+
void BluetoothAdapter::set_pairable (bool value)
{
adapter1_set_pairable (object, value);
@@ -235,6 +327,18 @@ bool BluetoothAdapter::get_discovering ()
return adapter1_get_discovering (object);
}
+void BluetoothAdapter::enable_discovering_notifications(
+ std::function<void(BluetoothAdapter &adapter, bool discovering, void *userdata)> callback,
+ void *userdata) {
+ discovering_callback = std::bind(callback, std::ref(*this), std::placeholders::_1, userdata);
+}
+void BluetoothAdapter::enable_discovering_notifications(std::function<void(bool discovering)> callback) {
+ discovering_callback = callback;
+}
+void BluetoothAdapter::disable_discovering_notifications() {
+ discovering_callback = nullptr;
+}
+
std::vector<std::string> BluetoothAdapter::get_uuids ()
{
const char * const *uuids_c = adapter1_get_uuids (object);
diff --git a/src/BluetoothDevice.cpp b/src/BluetoothDevice.cpp
index 1b76a849..943efc67 100644
--- a/src/BluetoothDevice.cpp
+++ b/src/BluetoothDevice.cpp
@@ -24,6 +24,7 @@
#include "generated-code.h"
#include "tinyb_utils.hpp"
+#include "BluetoothNotificationHandler.hpp"
#include "BluetoothDevice.hpp"
#include "BluetoothGattService.hpp"
#include "BluetoothManager.hpp"
@@ -31,6 +32,62 @@
using namespace tinyb;
+void BluetoothNotificationHandler::on_properties_changed_device(GDBusProxy *proxy, GVariant *changed_properties, GStrv invalidated_properties, gpointer userdata) {
+
+ auto c = static_cast<BluetoothDevice*>(userdata);
+
+ if (!c->lock())
+ return;
+
+ if(g_variant_n_children(changed_properties) > 0) {
+ GVariantIter *iter = NULL;
+
+ GVariant *value;
+ const gchar *key;
+ g_variant_get(changed_properties, "a{sv}", &iter);
+ while (iter != nullptr && g_variant_iter_loop(iter, "{&sv}", &key, &value)) {
+ auto rssi_callback = c->rssi_callback;
+ if (rssi_callback != nullptr && g_ascii_strncasecmp(key, "rssi", 5) == 0) {
+ int16_t new_value;
+ g_variant_get(value, "n", &new_value);
+ rssi_callback(new_value);
+ continue;
+ }
+ auto blocked_callback = c->blocked_callback;
+ if (blocked_callback != nullptr && g_ascii_strncasecmp(key, "blocked", 8) == 0) {
+ bool new_value;
+ g_variant_get(value, "b", &new_value);
+ blocked_callback(new_value);
+ continue;
+ }
+ auto trusted_callback = c->trusted_callback;
+ if (trusted_callback != nullptr && g_ascii_strncasecmp(key, "trusted", 8) == 0) {
+ bool new_value;
+ g_variant_get(value, "b", &new_value);
+ trusted_callback(new_value);
+ continue;
+ }
+ auto paired_callback = c->paired_callback;
+ if (paired_callback != nullptr && g_ascii_strncasecmp(key, "paired", 7) == 0) {
+ bool new_value;
+ g_variant_get(value, "b", &new_value);
+ paired_callback(new_value);
+ continue;
+ }
+ auto connected_callback = c->connected_callback;
+ if (connected_callback != nullptr && g_ascii_strncasecmp(key, "connected", 10) == 0) {
+ bool new_value;
+ g_variant_get(value, "b", &new_value);
+ connected_callback(new_value);
+ continue;
+ }
+ }
+ g_variant_iter_free (iter);
+ }
+
+ c->unlock();
+}
+
std::string BluetoothDevice::get_class_name() const
{
return std::string("BluetoothDevice");
@@ -55,6 +112,10 @@ BluetoothDevice::BluetoothDevice(Device1 *object)
{
this->object = object;
g_object_ref(object);
+
+ g_signal_connect(G_DBUS_PROXY(object), "g-properties-changed",
+ G_CALLBACK(BluetoothNotificationHandler::on_properties_changed_device), this);
+ valid = true;
}
BluetoothDevice::BluetoothDevice(const BluetoothDevice &object)
@@ -64,6 +125,10 @@ BluetoothDevice::BluetoothDevice(const BluetoothDevice &object)
BluetoothDevice::~BluetoothDevice()
{
+ valid = false;
+ g_signal_handlers_disconnect_by_data(object, this);
+ lk.lock();
+
g_object_unref(object);
}
@@ -240,6 +305,15 @@ bool BluetoothDevice::get_paired ()
return device1_get_paired (object);
}
+void BluetoothDevice::enable_paired_notifications(
+ std::function<void(BluetoothDevice &, bool, void *)> callback,
+ void *userdata) {
+ paired_callback = std::bind(callback, std::ref(*this), std::placeholders::_1, userdata);
+}
+void BluetoothDevice::disable_paired_notifications() {
+ paired_callback = nullptr;
+}
+
bool BluetoothDevice::get_trusted ()
{
return device1_get_trusted (object);
@@ -250,6 +324,19 @@ void BluetoothDevice::set_trusted (bool value)
device1_set_trusted (object, value);
}
+void BluetoothDevice::enable_trusted_notifications(
+ std::function<void(BluetoothDevice &, bool, void *)> callback,
+ void *userdata) {
+ trusted_callback = std::bind(callback, std::ref(*this), std::placeholders::_1, userdata);
+}
+void BluetoothDevice::enable_trusted_notifications(
+ std::function<void(bool)> callback) {
+ trusted_callback = callback;
+}
+void BluetoothDevice::disable_trusted_notifications() {
+ trusted_callback = nullptr;
+}
+
bool BluetoothDevice::get_blocked ()
{
return device1_get_blocked (object);
@@ -260,6 +347,19 @@ void BluetoothDevice::set_blocked (bool value)
device1_set_blocked (object, value);
}
+void BluetoothDevice::enable_blocked_notifications(
+ std::function<void(BluetoothDevice &, bool, void *)> callback,
+ void *userdata) {
+ blocked_callback = std::bind(callback, std::ref(*this), std::placeholders::_1, userdata);
+}
+void BluetoothDevice::enable_blocked_notifications(
+ std::function<void(bool)> callback) {
+ blocked_callback = callback;
+}
+void BluetoothDevice::disable_blocked_notifications() {
+ blocked_callback = nullptr;
+}
+
bool BluetoothDevice::get_legacy_pairing ()
{
return device1_get_legacy_pairing (object);
@@ -270,11 +370,37 @@ int16_t BluetoothDevice::get_rssi ()
return device1_get_rssi (object);
}
+void BluetoothDevice::enable_rssi_notifications(
+ std::function<void(BluetoothDevice &, int16_t, void *)> callback,
+ void *userdata) {
+ rssi_callback = std::bind(callback, std::ref(*this), std::placeholders::_1, userdata);
+}
+void BluetoothDevice::enable_rssi_notifications(
+ std::function<void(int16_t)> callback) {
+ rssi_callback = callback;
+}
+void BluetoothDevice::disable_rssi_notifications() {
+ rssi_callback = nullptr;
+}
+
bool BluetoothDevice::get_connected ()
{
return device1_get_connected (object);
}
+void BluetoothDevice::enable_connected_notifications(
+ std::function<void(BluetoothDevice &, bool, void *)> callback,
+ void *userdata) {
+ connected_callback = std::bind(callback, std::ref(*this), std::placeholders::_1, userdata);
+}
+void BluetoothDevice::enable_connected_notifications(
+ std::function<void(bool)> callback) {
+ connected_callback = callback;
+}
+void BluetoothDevice::disable_connected_notifications() {
+ connected_callback = nullptr;
+}
+
std::vector<std::string> BluetoothDevice::get_uuids ()
{
diff --git a/src/BluetoothEvent.cpp b/src/BluetoothEvent.cpp
index 1b68f629..ee797343 100644
--- a/src/BluetoothEvent.cpp
+++ b/src/BluetoothEvent.cpp
@@ -36,12 +36,15 @@ BluetoothEvent::BluetoothEvent(BluetoothType type, std::string *name,
this->parent = nullptr;
this->execute_once = execute_once;
- this->cb = cb;
- if (cb == generic_callback)
+ if (cb == nullptr) {
this->data = static_cast<void *>(&cv);
- else
+ this->cb = generic_callback;
+ }
+ else {
+ this->cb = cb;
this->data = data;
+ }
}
bool BluetoothEvent::execute_callback(BluetoothObject &object)
diff --git a/src/BluetoothGattCharacteristic.cpp b/src/BluetoothGattCharacteristic.cpp
index b8784883..d947ad72 100644
--- a/src/BluetoothGattCharacteristic.cpp
+++ b/src/BluetoothGattCharacteristic.cpp
@@ -24,6 +24,7 @@
#include "generated-code.h"
#include "tinyb_utils.hpp"
+#include "BluetoothNotificationHandler.hpp"
#include "BluetoothGattCharacteristic.hpp"
#include "BluetoothGattService.hpp"
#include "BluetoothGattDescriptor.hpp"
@@ -31,6 +32,27 @@
using namespace tinyb;
+void BluetoothNotificationHandler::on_properties_changed_characteristic(GDBusProxy *proxy, GVariant *changed_properties, GStrv invalidated_properties, gpointer userdata) {
+
+ auto c = static_cast<BluetoothGattCharacteristic*>(userdata);
+
+ if(g_variant_n_children(changed_properties) > 0) {
+ GVariantIter *iter = NULL;
+
+ GVariant *value;
+ const gchar *key;
+ g_variant_get(changed_properties, "a{sv}", &iter);
+ while (iter != nullptr && g_variant_iter_loop(iter, "{&sv}", &key, &value)) {
+ auto value_callback = c->value_changed_callback;
+ if (value_callback != nullptr && g_ascii_strncasecmp(key, "value", 5) == 0) {
+ std::vector<unsigned char> new_value = from_iter_to_vector(value);
+ value_callback(new_value);
+ }
+ }
+ g_variant_iter_free (iter);
+ }
+}
+
std::string BluetoothGattCharacteristic::get_class_name() const
{
return std::string("BluetoothGattCharacteristic");
@@ -55,15 +77,20 @@ BluetoothGattCharacteristic::BluetoothGattCharacteristic(GattCharacteristic1 *ob
{
this->object = object;
g_object_ref(object);
+
+ g_signal_connect(G_DBUS_PROXY(object), "g-properties-changed",
+ G_CALLBACK(BluetoothNotificationHandler::on_properties_changed_characteristic), this);
}
BluetoothGattCharacteristic::BluetoothGattCharacteristic(const BluetoothGattCharacteristic &object)
{
BluetoothGattCharacteristic(object.object);
+
}
BluetoothGattCharacteristic::~BluetoothGattCharacteristic()
{
+ g_signal_handlers_disconnect_by_data(object, this);
g_object_unref(object);
}
@@ -135,6 +162,31 @@ bool BluetoothGattCharacteristic::write_value (
return result;
}
+bool BluetoothGattCharacteristic::enable_value_notifications(
+ std::function<void(BluetoothGattCharacteristic &, std::vector<unsigned char> &,void *)> callback,
+ void *userdata)
+{
+ value_changed_callback = std::bind(callback, std::ref(*this), std::placeholders::_1, userdata);
+ start_notify();
+ return true;
+}
+
+bool BluetoothGattCharacteristic::enable_value_notifications(
+ std::function<void(std::vector<unsigned char> &)> callback)
+{
+ value_changed_callback = callback;
+ start_notify();
+ return true;
+}
+
+bool BluetoothGattCharacteristic::disable_value_notifications()
+{
+ stop_notify();
+ value_changed_callback = nullptr;
+ return true;
+}
+
+
bool BluetoothGattCharacteristic::start_notify ()
{
GError *error = NULL;
@@ -144,6 +196,7 @@ bool BluetoothGattCharacteristic::start_notify ()
NULL,
&error
);
+
handle_error(error);
return result;
}
@@ -161,8 +214,6 @@ bool BluetoothGattCharacteristic::stop_notify ()
return result;
}
-
-
/* D-Bus property accessors: */
std::string BluetoothGattCharacteristic::get_uuid ()
{
diff --git a/src/BluetoothGattDescriptor.cpp b/src/BluetoothGattDescriptor.cpp
index b0c5fd64..bd210347 100644
--- a/src/BluetoothGattDescriptor.cpp
+++ b/src/BluetoothGattDescriptor.cpp
@@ -24,12 +24,34 @@
#include "generated-code.h"
#include "tinyb_utils.hpp"
+#include "BluetoothNotificationHandler.hpp"
#include "BluetoothGattDescriptor.hpp"
#include "BluetoothGattCharacteristic.hpp"
#include "BluetoothException.hpp"
using namespace tinyb;
+void BluetoothNotificationHandler::on_properties_changed_descriptor(GDBusProxy *proxy, GVariant *changed_properties, GStrv invalidated_properties, gpointer userdata) {
+
+ auto c = static_cast<BluetoothGattDescriptor*>(userdata);
+
+ if(g_variant_n_children(changed_properties) > 0) {
+ GVariantIter *iter = NULL;
+
+ GVariant *value;
+ const gchar *key;
+ g_variant_get(changed_properties, "a{sv}", &iter);
+ while (iter != nullptr && g_variant_iter_loop(iter, "{&sv}", &key, &value)) {
+ auto value_callback = c->value_changed_callback;
+ if (value_callback != nullptr && g_ascii_strncasecmp(key, "value", 5) == 0) {
+ std::vector<unsigned char> new_value = from_iter_to_vector(value);
+ value_callback(new_value);
+ }
+ }
+ g_variant_iter_free (iter);
+ }
+}
+
std::string BluetoothGattDescriptor::get_class_name() const
{
return std::string("BluetoothGattDescriptor");
@@ -54,6 +76,10 @@ BluetoothGattDescriptor::BluetoothGattDescriptor(GattDescriptor1 *object)
{
this->object = object;
g_object_ref(object);
+
+ g_signal_connect(G_DBUS_PROXY(object), "g-properties-changed",
+ G_CALLBACK(BluetoothNotificationHandler::on_properties_changed_descriptor), this);
+ valid = true;
}
BluetoothGattDescriptor::BluetoothGattDescriptor(const BluetoothGattDescriptor &object)
@@ -63,6 +89,10 @@ BluetoothGattDescriptor::BluetoothGattDescriptor(const BluetoothGattDescriptor &
BluetoothGattDescriptor::~BluetoothGattDescriptor()
{
+ valid = false;
+ g_signal_handlers_disconnect_by_data(object, this);
+ lk.lock();
+
g_object_unref(object);
}
@@ -136,7 +166,26 @@ bool BluetoothGattDescriptor::write_value (
return result;
}
+bool BluetoothGattDescriptor::enable_value_notifications(
+ std::function<void(BluetoothGattDescriptor &, std::vector<unsigned char> &,void *)> callback,
+ void *userdata)
+{
+ value_changed_callback = std::bind(callback, std::ref(*this), std::placeholders::_1, userdata);
+ return true;
+}
+bool BluetoothGattDescriptor::enable_value_notifications(
+ std::function<void(std::vector<unsigned char> &)> callback)
+{
+ value_changed_callback = callback;
+ return true;
+}
+
+bool BluetoothGattDescriptor::disable_value_notifications()
+{
+ value_changed_callback = nullptr;
+ return true;
+}
/* D-Bus property accessors: */
std::string BluetoothGattDescriptor::get_uuid ()
diff --git a/src/BluetoothManager.cpp b/src/BluetoothManager.cpp
index a7459f4a..9363617e 100644
--- a/src/BluetoothManager.cpp
+++ b/src/BluetoothManager.cpp
@@ -33,9 +33,7 @@
#include "BluetoothException.hpp"
#include "version.h"
-#include <pthread.h>
#include <cassert>
-#include <iostream>
using namespace tinyb;
diff --git a/src/tinyb_utils.cpp b/src/tinyb_utils.cpp
index 449ef1ed..97a17898 100644
--- a/src/tinyb_utils.cpp
+++ b/src/tinyb_utils.cpp
@@ -52,6 +52,27 @@ GBytes *tinyb::from_vector_to_gbytes(const std::vector<unsigned char>& vector)
return result;
}
+std::vector<unsigned char> tinyb::from_iter_to_vector(GVariant *iter)
+{
+ GVariantIter *value_iter;
+ guchar value_byte;
+
+ g_variant_get (iter,
+ "ay",
+ &value_iter);
+
+ if (value_iter == nullptr)
+ throw std::invalid_argument("GVariant should be a container of an array of bytes");
+
+ std::vector<unsigned char> value;
+ while (g_variant_iter_loop(value_iter, "y", &value_byte)) {
+ value.push_back(value_byte);
+ }
+
+ g_variant_iter_free(value_iter);
+ return value;
+}
+
void tinyb::handle_error(GError *error)
{
if (error != nullptr) {