[BluetoothLE] Added checking, if device is still connected
authorPiotr Kosko <p.kosko@samsung.com>
Mon, 11 May 2015 08:56:40 +0000 (10:56 +0200)
committerPawel Andruszkiewicz <p.andruszkie@samsung.com>
Mon, 11 May 2015 13:15:13 +0000 (22:15 +0900)
[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 <p.kosko@samsung.com>
src/bluetooth/bluetooth_api.js
src/bluetooth/bluetooth_gatt_service.cc
src/bluetooth/bluetooth_gatt_service.h

index 716393f0049ff3e4e75757bb88e5ef105afcdb67..4bf1a2fd83c1428a6d5a9f44178d7860324a186a 100644 (file)
@@ -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);
 
index 6fbf020f01221469c0685a1b960af5c6d135ef60..96a5168f5e9a3d78969120f43b3f7109db505b31 100644 (file)
@@ -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<long>(args.get("handle").get<double>());
-  std::string uuid = args.get("uuid").get<std::string>();
+  const std::string& uuid = args.get("uuid").get<std::string>();
+  const std::string& address = args.get("address").get<std::string>();
 
   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<long>(args.get("handle").get<double>());
-  std::string uuid = args.get("uuid").get<std::string>();
+  const std::string& uuid = args.get("uuid").get<std::string>();
+  const std::string& address = args.get("address").get<std::string>();
 
   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<std::string>();
+  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<long>(args.get("handle").get<double>());
 
-  //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<std::string>();
+  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<picojson::array>();
 
@@ -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<long>(args.get("handle").get<double>());
 
-  //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;
index 1af6388053b135f21834ce2170507c98243fa289..c072af57cff1e4a44049684beed9a0630885cfb3 100644 (file)
@@ -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<std::string, bt_gatt_client_h> gatt_clients_;