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_;