From: Piotr Kosko
Date: Mon, 11 May 2015 08:56:40 +0000 (+0200)
Subject: [BluetoothLE] Added checking, if device is still connected
X-Git-Tag: submit/tizen_tv/20150603.064601~1^2~37
X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b438fd3a5484b2458e4306191b08f417d95acc49;p=platform%2Fcore%2Fapi%2Fwebapi-plugins.git
[BluetoothLE] Added checking, if device is still connected
[Feature] Code for checking if device from which BluetoothGATTService object was gathered
is still connected.
[Verification] Code compiles without errors.
Change-Id: Ie94c771116b0129f208374ce8a9042c5a071b040
Signed-off-by: Piotr Kosko
---
diff --git a/src/bluetooth/bluetooth_api.js b/src/bluetooth/bluetooth_api.js
index 716393f0..4bf1a2fd 100644
--- a/src/bluetooth/bluetooth_api.js
+++ b/src/bluetooth/bluetooth_api.js
@@ -1465,17 +1465,19 @@ BluetoothLEAdapter.prototype.stopAdvertise = function() {
};
//class BluetoothGATTService ////////////////////////////////////////////////////
-var BluetoothGATTService = function(data) {
+var BluetoothGATTService = function(data, address) {
var handle_ = data.handle;
var uuid_ = data.uuid;
+ //address_ is needed to control if device is still connected
+ var address_ = address || data.address;
function servicesGetter() {
var services = [];
var result = native.callSync('BluetoothGATTService_getServices',
- {handle: handle_, uuid: uuid_});
+ {handle: handle_, uuid: uuid_, address : address_});
if (native.isSuccess(result)) {
var resultObject = native.getResultObject(result);
resultObject.forEach(function(s) {
- services.push(new BluetoothGATTService(s));
+ services.push(new BluetoothGATTService(s, address_));
});
}
return services;
@@ -1483,11 +1485,11 @@ var BluetoothGATTService = function(data) {
function characteristicsGetter() {
var characteristics = [];
var result = native.callSync('BluetoothGATTService_getCharacteristics',
- {handle: handle_, uuid: uuid_});
+ {handle: handle_, uuid: uuid_, address : address_});
if (native.isSuccess(result)) {
var resultObject = native.getResultObject(result);
resultObject.forEach(function(c) {
- characteristics.push(new BluetoothGATTCharacteristic(c));
+ characteristics.push(new BluetoothGATTCharacteristic(c, address_));
});
}
return characteristics;
@@ -1500,7 +1502,7 @@ var BluetoothGATTService = function(data) {
};
//class BluetoothGATTCharacteristic ////////////////////////////////////////////////////
-var BluetoothGATTCharacteristic = function(data) {
+var BluetoothGATTCharacteristic = function(data, address) {
var handle_ = data.handle;
var descriptors_ = [];
var isBroadcast_ = false;
@@ -1511,10 +1513,12 @@ var BluetoothGATTCharacteristic = function(data) {
var isSignedWrite_ = false;
var isWritable_ = false;
var isWriteNoResponse_ = false;
+ //address_ is needed to control if device is still connected
+ var address_ = address;
if (T.isObject(data)) {
data.descriptors.forEach(function(dd) {
- descriptors_.push(new BluetoothGATTDescriptor(dd));
+ descriptors_.push(new BluetoothGATTDescriptor(dd, address_));
});
isBroadcast_ = data.isBroadcast;
hasExtendedProperties_ = data.hasExtendedProperties;
@@ -1634,7 +1638,7 @@ var BluetoothGATTCharacteristic = function(data) {
}
};
- var callArgs = {handle : handle_};
+ var callArgs = {handle : handle_, address : address_};
var result = native.call('BluetoothGATT_readValue', callArgs, callback);
@@ -1672,7 +1676,7 @@ var BluetoothGATTCharacteristic = function(data) {
}
};
- var callArgs = { handle : handle_, value: toByteArray(args.value) };
+ var callArgs = { handle : handle_, value: toByteArray(args.value), address : address_ };
var result = native.call('BluetoothGATT_writeValue', callArgs, callback);
@@ -1800,8 +1804,10 @@ BluetoothGATTCharacteristic.prototype.removeValueChangeListener = function() {
};
//class BluetoothGATTDescriptor ////////////////////////////////////////////////////
-var BluetoothGATTDescriptor = function() {
+var BluetoothGATTDescriptor = function(address) {
var handle_ = data.handle;
+ //address_ is needed to control if device is still connected
+ var address_ == address;
BluetoothGATTDescriptor.prototype.readValue = function() {
console.log('Entered BluetoothGATTDescriptor.readValue()');
@@ -1827,7 +1833,7 @@ var BluetoothGATTDescriptor = function() {
}
};
- var callArgs = {handle : handle_};
+ var callArgs = {handle : handle_, address : address_};
var result = native.call('BluetoothGATT_readValue', callArgs, callback);
@@ -1865,7 +1871,7 @@ var BluetoothGATTDescriptor = function() {
}
};
- var callArgs = { handle : handle_, value: toByteArray(args.value) };
+ var callArgs = { handle : handle_, value: toByteArray(args.value), address : address_ };
var result = native.call('BluetoothGATT_writeValue', callArgs, callback);
diff --git a/src/bluetooth/bluetooth_gatt_service.cc b/src/bluetooth/bluetooth_gatt_service.cc
index 6fbf020f..96a5168f 100644
--- a/src/bluetooth/bluetooth_gatt_service.cc
+++ b/src/bluetooth/bluetooth_gatt_service.cc
@@ -37,6 +37,7 @@ using namespace common::tools;
namespace {
const std::string kUuid = "uuid";
const std::string kHandle = "handle";
+const std::string kAddress = "address";
const std::string kDescriptors = "descriptors";
const std::string kBroadcast = "isBroadcast";
@@ -69,6 +70,24 @@ BluetoothGATTService::~BluetoothGATTService() {
}
}
+bool BluetoothGATTService::IsStillConnected(const std::string& address) {
+ auto it = gatt_clients_.find(address);
+ return gatt_clients_.end() != it;
+}
+
+// this method should be used to inform this object that some device was disconnected
+void BluetoothGATTService::TryDestroyClient(const std::string &address) {
+ auto it = gatt_clients_.find(address);
+ if (gatt_clients_.end() != it) {
+ LoggerD("destroying client for address: %s", it->first.c_str());
+ bt_gatt_client_destroy(it->second);
+ gatt_clients_.erase(it);
+ } else {
+ LoggerD("Client for address: %s does not exist, no need for deletion",
+ address.c_str());
+ }
+}
+
PlatformResult BluetoothGATTService::GetSpecifiedGATTService(const std::string &address,
const std::string &uuid,
picojson::object* result) {
@@ -104,6 +123,8 @@ PlatformResult BluetoothGATTService::GetSpecifiedGATTService(const std::string &
result->insert(std::make_pair(kUuid, picojson::value(uuid)));
//handle is passed to upper layer because there is no need to delete it
result->insert(std::make_pair(kHandle, picojson::value((double)(long)service)));
+ //address is necessary to later check if device is still connected
+ result->insert(std::make_pair(kAddress, picojson::value(address)));
return PlatformResult(ErrorCode::NO_ERROR);
}
@@ -112,10 +133,11 @@ void BluetoothGATTService::GetServices(const picojson::value& args,
LoggerD("Entered");
bt_gatt_h handle = (bt_gatt_h) static_cast(args.get("handle").get());
- std::string uuid = args.get("uuid").get();
+ const std::string& uuid = args.get("uuid").get();
+ const std::string& address = args.get("address").get();
picojson::array array;
- PlatformResult ret = GetServicesHelper(handle, uuid, &array);
+ PlatformResult ret = GetServicesHelper(handle, address, uuid, &array);
if (ret.IsError()) {
LoggerE("Error while getting services");
ReportError(ret, &out);
@@ -125,10 +147,17 @@ void BluetoothGATTService::GetServices(const picojson::value& args,
}
PlatformResult BluetoothGATTService::GetServicesHelper(bt_gatt_h handle,
+ const std::string& address,
const std::string& uuid,
picojson::array* array) {
LoggerD("Entered");
+ if (!IsStillConnected(address)) {
+ LoggerE("Device with address %s is no longer connected", address.c_str());
+ return PlatformResult(ErrorCode::INVALID_STATE_ERR,
+ "Device is not connected");
+ }
+
struct Data {
const std::string& uuid;
picojson::array* array;
@@ -164,10 +193,11 @@ void BluetoothGATTService::GetCharacteristics(const picojson::value& args,
LoggerD("Entered");
bt_gatt_h handle = (bt_gatt_h) static_cast(args.get("handle").get());
- std::string uuid = args.get("uuid").get();
+ const std::string& uuid = args.get("uuid").get();
+ const std::string& address = args.get("address").get();
picojson::array array;
- PlatformResult ret = GetCharacteristicsHelper(handle, uuid, &array);
+ PlatformResult ret = GetCharacteristicsHelper(handle, address, uuid, &array);
if (ret.IsError()) {
LoggerE("Error while getting characteristics");
ReportError(ret, &out);
@@ -177,10 +207,17 @@ void BluetoothGATTService::GetCharacteristics(const picojson::value& args,
}
PlatformResult BluetoothGATTService::GetCharacteristicsHelper(bt_gatt_h handle,
+ const std::string& address,
const std::string& uuid,
picojson::array* array) {
LoggerD("Entered");
+ if (!IsStillConnected(address)) {
+ LoggerE("Device with address %s is no longer connected", address.c_str());
+ return PlatformResult(ErrorCode::INVALID_STATE_ERR,
+ "Device is not connected");
+ }
+
int ret = bt_gatt_service_foreach_characteristics(
handle,
[](int total, int index, bt_gatt_h gatt_handle, void *data) {
@@ -255,6 +292,15 @@ PlatformResult BluetoothGATTService::GetCharacteristicsHelper(bt_gatt_h handle,
void BluetoothGATTService::ReadValue(const picojson::value& args,
picojson::object& out) {
LoggerD("Entered");
+
+ const std::string& address = args.get("address").get();
+ if (!IsStillConnected(address)) {
+ LoggerE("Device with address %s is no longer connected", address.c_str());
+ ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+ "Device is not connected"), &out);
+ return;
+ }
+
const double callback_handle = util::GetAsyncCallbackHandle(args);
struct Data {
double callback_handle;
@@ -264,8 +310,6 @@ void BluetoothGATTService::ReadValue(const picojson::value& args,
Data* user_data = new Data{callback_handle, this};
bt_gatt_h handle = (bt_gatt_h) static_cast(args.get("handle").get());
- //TODO check if client device is still connected and throw InvalidStateError
-
auto read_value = [](int result, bt_gatt_h handle, void *user_data) -> void {
Data* data = (Data*) user_data;
double callback_handle = data->callback_handle;
@@ -320,6 +364,15 @@ void BluetoothGATTService::ReadValue(const picojson::value& args,
void BluetoothGATTService::WriteValue(const picojson::value& args,
picojson::object& out) {
LoggerD("Entered");
+
+ const std::string& address = args.get("address").get();
+ if (!IsStillConnected(address)) {
+ LoggerE("Device with address %s is no longer connected", address.c_str());
+ ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+ "Device is not connected"), &out);
+ return;
+ }
+
const double callback_handle = util::GetAsyncCallbackHandle(args);
const picojson::array& value_array = args.get("value").get();
@@ -337,8 +390,6 @@ void BluetoothGATTService::WriteValue(const picojson::value& args,
Data* user_data = new Data{callback_handle, this};
bt_gatt_h handle = (bt_gatt_h) static_cast(args.get("handle").get());
- //TODO check if client device is still connected and throw InvalidStateError
-
auto write_value = [](int result, bt_gatt_h handle, void *user_data) -> void {
Data* data = (Data*) user_data;
double callback_handle = data->callback_handle;
diff --git a/src/bluetooth/bluetooth_gatt_service.h b/src/bluetooth/bluetooth_gatt_service.h
index 1af63880..c072af57 100644
--- a/src/bluetooth/bluetooth_gatt_service.h
+++ b/src/bluetooth/bluetooth_gatt_service.h
@@ -38,16 +38,21 @@ class BluetoothGATTService {
const std::string &uuid,
picojson::object* result);
+ void TryDestroyClient(const std::string &address);
void GetServices(const picojson::value& data, picojson::object& out);
void GetCharacteristics(const picojson::value& data, picojson::object& out);
void ReadValue(const picojson::value& args, picojson::object& out);
void WriteValue(const picojson::value& args, picojson::object& out);
private:
- static common::PlatformResult GetServicesHelper(bt_gatt_h handle, const std::string& uuid,
- picojson::array* array);
- static common::PlatformResult GetCharacteristicsHelper(bt_gatt_h handle, const std::string& uuid,
- picojson::array* array);
+ bool IsStillConnected(const std::string& address);
+ common::PlatformResult GetServicesHelper(bt_gatt_h handle, const std::string& address,
+ const std::string& uuid,
+ picojson::array* array);
+ common::PlatformResult GetCharacteristicsHelper(bt_gatt_h handle,
+ const std::string& address,
+ const std::string& uuid,
+ picojson::array* array);
std::map gatt_clients_;