[BluetoothLE] Implementation of Bluetooth LE Device
authorLukasz Bardeli <l.bardeli@samsung.com>
Wed, 6 May 2015 10:02:54 +0000 (12:02 +0200)
committerPawel Andruszkiewicz <p.andruszkie@samsung.com>
Fri, 8 May 2015 12:30:43 +0000 (21:30 +0900)
ToJson method

[Verification] Code compiles without errors.

Change-Id: I1a29d6284e35debefe405dc6fcdf1e704c152bc4
Signed-off-by: Lukasz Bardeli <l.bardeli@samsung.com>
src/bluetooth/bluetooth.gyp
src/bluetooth/bluetooth_api.js
src/bluetooth/bluetooth_instance.cc
src/bluetooth/bluetooth_instance.h
src/bluetooth/bluetooth_le_adapter.cc
src/bluetooth/bluetooth_le_device.cc [new file with mode: 0644]
src/bluetooth/bluetooth_le_device.h [new file with mode: 0644]

index 9bf3975aff75cc50d18385eeab2c7bf3190703d7..d277032e2a9d0c8b0e0d19ceb392b58168a07148 100644 (file)
@@ -35,6 +35,8 @@
         'bluetooth_socket.h',
         'bluetooth_util.cc',
         'bluetooth_util.h',
+        'bluetooth_le_device.cc',
+        'bluetooth_le_device.h',
       ],
       'includes': [
         '../common/pkg-config.gypi',
index d0d78f704f22cbc0c230af9d2f9d7cb03e9e86ba..3afd0e1e63042ecabce4436fdc8b776cd4e0cf93 100644 (file)
@@ -135,21 +135,13 @@ var BluetoothClassDeviceService = function() {
 //class BluetoothLEServiceData ////////////////////////////////////////////////////
 var BluetoothLEServiceData = function(data) {
     Object.defineProperties(this, {
-        serviceuuids : {value: "dummyValue", writable: true, enumerable: true},
-        data : {value: "dummyValue", writable: true, enumerable: true}
+        serviceuuids : {value: data.serviceData, writable: true, enumerable: true},
+        data : {value: data.data, writable: true, enumerable: true}
     });
 };
 
 //class BluetoothLEAdvertiseData ////////////////////////////////////////////////////
 var BluetoothLEAdvertiseData = function(data) {
-    Object.defineProperties(this, {
-        id : {value: "dummyValue", writable: true, enumerable: true},
-        data : {value: "dummyValue", writable: true, enumerable: true}
-    });
-};
-
-//class BluetoothLEManufacturerData ////////////////////////////////////////////////////
-var BluetoothLEManufacturerData = function(data) {
     Object.defineProperties(this, {
         name : {value: false, writable: true, enumerable: true},
         serviceuuids : {value: ["dummyUuids"], writable: true, enumerable: true},
@@ -161,6 +153,14 @@ var BluetoothLEManufacturerData = function(data) {
     });
 };
 
+//class BluetoothLEManufacturerData ////////////////////////////////////////////////////
+var BluetoothLEManufacturerData = function(data) {
+    Object.defineProperties(this, {
+        id : {value: data.id, writable: true, enumerable: true},
+        data : {value: data.data, writable: true, enumerable: true}
+    });
+};
+
 // class BluetoothClass ////////////////////////////////////////////////////
 var BluetoothClass = function(data) {
     var services = [];
@@ -324,15 +324,47 @@ BluetoothSocket.prototype.close = function() {
 
 //class BluetoothLEDevice ////////////////////////////////////////////////////
 var BluetoothLEDevice = function(data) {
+
+    var address = "", name = "", txpowerLevel = null, appearance = null, uuids = [],
+        solicitationuuids = [], serviceData = [], manufacturerData = null;
+
+    if (data) {
+        address = data.address;
+        name = data.name;
+        txpowerLevel = data.txpowerLevel;
+        apperance = data.appearance;
+        uuids = data.uuids;
+        solicitationuuids = data.solicitationuuids;
+        data.serviceData.forEach(function(d) {
+            serviceData.push(new BluetoothLEServiceData(d));
+        });
+        manufacturerData = new BluetoothLEManufacturerData(data.manufacturerData);
+    }
+
     Object.defineProperties(this, {
-        address : {value: "dummyValue", writable: false, enumerable: true},
-        name : {value: "dummyValue", writable: false, enumerable: true},
-        txpowerLevel : {value: 123456, writable: false, enumerable: true},
-        appearance : {value: 123456, writable: false, enumerable: true},
-        uuids : {value: ["dummyValues"], writable: false, enumerable: true},
-        solicitationuuids : {value: ["dummyValues"], writable: false, enumerable: true},
-        serviceData : {value: ["dummyValues"], writable: false, enumerable: true},
-        manufacturerData : {value: "dummyManufacturer", writable: false, enumerable: true}
+        address : {value: address, writable: false, enumerable: true},
+        name : {value: name, writable: false, enumerable: true},
+        txpowerLevel : {value: txpowerLevel, writable: false, enumerable: true},
+        appearance : {value: appearance, writable: false, enumerable: true},
+        uuids : {
+            enumerable: true,
+            set : function(){},
+            get : function(){ return uuids.slice(); }
+        },
+        solicitationuuids : {
+            enumerable: true,
+            set : function(){},
+            get : function(){ return solicitationuuids.slice(); }
+        },
+        serviceData : {
+            enumerable: true,
+            set : function(){},
+            get : function(){ return serviceData.slice(); }
+        },
+        manufacturerData : {
+            value: manufacturerData,
+            writable: false,
+            enumerable: true}
     });
 };
 
index a655d3820b041f8fc1998bb8eadd23ed2b9d883a..9781c67bc322b50ac1e3c8c288e983dfce8c7d66 100644 (file)
@@ -21,7 +21,8 @@ BluetoothInstance::BluetoothInstance() :
     bluetooth_health_application_(bluetooth_health_profile_handler_),
     bluetooth_service_handler_(bluetooth_adapter_),
     bluetooth_socket_(bluetooth_adapter_),
-    bluetooth_le_adapter_(*this)
+    bluetooth_le_adapter_(*this),
+    bluetooth_le_device_(*this)
 {
   LoggerD("Entered");
   using std::placeholders::_1;
@@ -106,6 +107,25 @@ BluetoothInstance::BluetoothInstance() :
   REGISTER_SYNC("BluetoothLEAdapter_stopScan",
       std::bind(&BluetoothLEAdapter::StopScan, &bluetooth_le_adapter_, _1, _2));
 
+  // BluetoothLEDevice
+  REGISTER_ASYNC(
+      "BluetoothLEDevice_connect",
+      std::bind(&BluetoothLEDevice::Connect, &bluetooth_le_device_, _1, _2));
+  REGISTER_ASYNC(
+      "BluetoothLEDevice_disconnect",
+      std::bind(&BluetoothLEDevice::Disconnect, &bluetooth_le_device_, _1, _2));
+  REGISTER_SYNC(
+      "BluetoothLEDevice_getService",
+      std::bind(&BluetoothLEDevice::GetService, &bluetooth_le_device_, _1, _2));
+  REGISTER_SYNC(
+      "BluetoothLEDevice_addConnectStateChangeListener",
+      std::bind(&BluetoothLEDevice::AddConnectStateChangeListener,
+                &bluetooth_le_device_, _1, _2));
+  REGISTER_SYNC(
+      "BluetoothLEDevice_removeConnectStateChangeListener",
+      std::bind(&BluetoothLEDevice::RemoveConnectStateChangeListener,
+                &bluetooth_le_device_, _1, _2));
+
   #undef REGISTER_ASYNC
   #undef REGISTER_SYNC
 }
index fddb3f63dcc327bc28d03ee96f4209de65814b13..cd9f743e1ddd7879207991424cf76651d04b98a6 100644 (file)
@@ -13,6 +13,7 @@
 #include "bluetooth/bluetooth_health_channel.h"
 #include "bluetooth/bluetooth_health_profile_handler.h"
 #include "bluetooth/bluetooth_le_adapter.h"
+#include "bluetooth/bluetooth_le_device.h"
 #include "bluetooth/bluetooth_service_handler.h"
 #include "bluetooth/bluetooth_socket.h"
 #include "bluetooth/bluetooth_util.h"
@@ -42,6 +43,7 @@ class BluetoothInstance: public common::ParsedInstance {
   BluetoothServiceHandler bluetooth_service_handler_;
   BluetoothSocket bluetooth_socket_;
   BluetoothLEAdapter bluetooth_le_adapter_;
+  BluetoothLEDevice bluetooth_le_device_;
 };
 
 } // namespace bluetooth
index 426e64c1adf0b3d935f5cdd5ab792f7dc93270d3..718e402824bd40cda89fe7b77003fc1e5a4c6996 100644 (file)
@@ -19,6 +19,7 @@
 #include "common/logger.h"
 
 #include "bluetooth/bluetooth_instance.h"
+#include "bluetooth/bluetooth_le_device.h"
 #include "bluetooth/bluetooth_util.h"
 
 namespace extension {
@@ -26,17 +27,6 @@ namespace bluetooth {
 
 namespace {
 
-// TODO: remove this code when BluetoothLEDevice is available
-class BluetoothLEDevice {
- public:
-  static common::PlatformResult ToJson(
-       bt_adapter_le_device_scan_result_info_s* info,
-       picojson::object* le_device) {
-    return common::PlatformResult(common::ErrorCode::NO_ERROR);
-  }
-};
-// TODO end
-
 // utility functions
 
 bool ToBool(bt_adapter_le_state_e state) {
diff --git a/src/bluetooth/bluetooth_le_device.cc b/src/bluetooth/bluetooth_le_device.cc
new file mode 100644 (file)
index 0000000..625ee40
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#include "bluetooth/bluetooth_le_device.h"
+#include <glib.h>
+
+#include "bluetooth/bluetooth_util.h"
+
+#include "common/logger.h"
+
+using common::PlatformResult;
+
+namespace extension {
+namespace bluetooth {
+
+namespace {
+//le_device
+const std::string kDeviceName = "name";
+const std::string kDeviceAddress = "address";
+const std::string kTxPowerLevel = "txpowerLevel";
+const std::string kAppearance = "appearance";
+const std::string kDeviceUuids = "uuids";
+const std::string kSolicitationUuids = "solicitationuuids";
+const std::string kServiceData = "serviceData";
+const std::string kServiceUuids = "serviceuuids";
+const std::string kManufacturerData = "manufacturerData";
+const std::string kId = "id";
+const std::string kData = "data";
+
+}
+
+BluetoothLEDevice::BluetoothLEDevice(BluetoothInstance& instance)
+    : instance_(instance) {
+}
+
+BluetoothLEDevice::~BluetoothLEDevice() {
+}
+
+static void UUIDsToJson(char **service_uuid, int service_count,
+                        const std::string &field, picojson::object* le_device) {
+  LoggerD("Entered");
+
+  picojson::array& array = le_device->insert(
+      std::make_pair(field, picojson::value(picojson::array()))).first->second
+      .get<picojson::array>();
+
+  for (int i = 0; i < service_count; i++) {
+    array.push_back(picojson::value(service_uuid[i]));
+  }
+}
+
+static void ServiceDataToJson(bt_adapter_le_service_data_s *service_data_list,
+                              int service_data_list_count,
+                              picojson::object* le_device) {
+  LoggerD("Entered");
+
+  picojson::array& array = le_device->insert(
+      std::make_pair(kServiceData, picojson::value(picojson::array()))).first
+      ->second.get<picojson::array>();
+
+  for (int i = 0; i < service_data_list_count; i++) {
+    picojson::value response = picojson::value(picojson::object());
+    picojson::object& response_obj = response.get<picojson::object>();
+    response_obj[kServiceUuids] = picojson::value(
+        std::string(service_data_list[i].service_uuid));
+    response_obj[kData] = picojson::value(
+        std::string(service_data_list[i].service_data,
+                    service_data_list[i].service_data_len));
+
+    array.push_back(response);
+  }
+}
+
+static void ManufacturerToJson(int manufacturer_id, char *manufacturer_data,
+                               int manufacturer_count,
+                               picojson::object* le_device) {
+  LoggerD("Entered");
+
+  picojson::value response = picojson::value(picojson::object());
+  picojson::object& response_obj = response.get<picojson::object>();
+  response_obj[kId] = picojson::value(std::to_string(manufacturer_id));
+  response_obj[kData] = picojson::value(
+      std::string(manufacturer_data, manufacturer_count));
+}
+
+PlatformResult BluetoothLEDevice::ToJson(
+    bt_adapter_le_device_scan_result_info_s* info,
+    picojson::object* le_device) {
+  LoggerD("Entered");
+
+  le_device->insert(
+      std::make_pair(kDeviceAddress,
+                     picojson::value(std::string(info->remote_address))));
+
+  char *device_name = nullptr;
+
+  int ret = BT_ERROR_NONE;
+
+  std::vector<bt_adapter_le_packet_type_e> types = {BT_ADAPTER_LE_PACKET_SCAN_RESPONSE,
+    BT_ADAPTER_LE_PACKET_ADVERTISING};
+  bool found = false;
+
+  for (size_t i = 0; i < types.size() && !found; ++i) {
+    ret = bt_adapter_le_get_scan_result_device_name(info, types[i],
+                                                    &device_name);
+    if (BT_ERROR_NONE == ret) {
+      found = true;
+    } else {
+      LoggerE("Failed to get device name (%d). Packet type: %d", ret, types[i]);
+    }
+  }
+
+  if (!found) {
+    return util::GetBluetoothError(ret, "Failed to get device name.");
+  }
+
+  le_device->insert(
+      std::make_pair(kDeviceName, picojson::value(std::string(device_name))));
+
+  g_free(device_name);
+
+  int power_level = 0;
+  found = false;
+  for (size_t i = 0; i < types.size() && !found; ++i) {
+    ret = bt_adapter_le_get_scan_result_tx_power_level(info, types[i],
+                                                       &power_level);
+    if (BT_ERROR_NONE == ret) {
+      found = true;
+    } else {
+      LoggerE("Failed to get txpower (%d). Packet type: %d", ret, types[i]);
+    }
+  }
+
+  if (!found) {
+    return util::GetBluetoothError(ret, "Failed to get txpower.");
+  }
+
+  le_device->insert(
+      std::make_pair(kTxPowerLevel,
+                     picojson::value(static_cast<double>(power_level))));
+
+  int appearance = 0;
+  found = false;
+  for (size_t i = 0; i < types.size() && !found; ++i) {
+    ret = bt_adapter_le_get_scan_result_appearance(info, types[i], &appearance);
+    if (BT_ERROR_NONE == ret) {
+      found = true;
+    } else {
+      LoggerE("Failed to get appearance (%d). Packet type: %d", ret, types[i]);
+    }
+  }
+
+  if (!found) {
+    return util::GetBluetoothError(ret, "Failed to get appearance.");
+  }
+
+  le_device->insert(
+      std::make_pair(kAppearance,
+                     picojson::value(static_cast<double>(appearance))));
+
+  char **uuids = nullptr;
+  int count = 0;
+  found = false;
+  for (size_t i = 0; i < types.size() && !found; ++i) {
+    ret = bt_adapter_le_get_scan_result_service_uuids(info, types[i], &uuids,
+                                                      &count);
+    if (BT_ERROR_NONE == ret) {
+      found = true;
+    } else {
+      LoggerE("Failed to get uuids (%d). Packet type: %d", ret, types[i]);
+    }
+  }
+
+  if (!found) {
+    return util::GetBluetoothError(ret, "Failed to get uuids.");
+  }
+
+  UUIDsToJson(uuids, count, kDeviceUuids, le_device);
+  for (int i = 0; i < count; ++i) {
+    g_free(uuids[i]);
+  }
+  g_free(uuids);
+
+  char** service_solicitation_uuids = nullptr;
+  int service_solicitation_uuids_count = 0;
+  found = false;
+
+  for (size_t i = 0; i < types.size() && !found; ++i) {
+    ret = bt_adapter_le_get_scan_result_service_solicitation_uuids(
+        info, types[i], &service_solicitation_uuids,
+        &service_solicitation_uuids_count);
+    if (BT_ERROR_NONE == ret) {
+      found = true;
+    } else {
+      LoggerE("Failed to get solicitation UUID (%d). Packet type: %d", ret, types[i]);
+    }
+  }
+
+  if (!found) {
+    return util::GetBluetoothError(ret, "Failed to get solicitation UUID.");
+  }
+
+  UUIDsToJson(service_solicitation_uuids, service_solicitation_uuids_count,
+              kSolicitationUuids, le_device);
+  for (int i = 0; i < service_solicitation_uuids_count; ++i) {
+    g_free(service_solicitation_uuids[i]);
+  }
+  g_free(service_solicitation_uuids);
+
+  bt_adapter_le_service_data_s *serviceDataList = nullptr;
+  int service_data_list_count = 0;
+  found = false;
+
+  for (size_t i = 0; i < types.size() && !found; ++i) {
+    ret = bt_adapter_le_get_scan_result_service_data_list(
+        info, types[i], &serviceDataList, &service_data_list_count);
+    if (BT_ERROR_NONE == ret) {
+      found = true;
+    } else {
+      LoggerE("Failed to get device service data (%d). Packet type: %d", ret, types[i]);
+    }
+  }
+
+  if (!found) {
+    return util::GetBluetoothError(ret, "Failed to get device service data.");
+  }
+
+  ServiceDataToJson(serviceDataList, service_data_list_count, le_device);
+
+  ret = bt_adapter_le_free_service_data_list(serviceDataList,
+                                             service_data_list_count);
+  if (BT_ERROR_NONE != ret) {
+    LoggerW("Failed to free service data list: %d", ret);
+  }
+
+  int manufacturer_id = 0;
+  char* manufacturer_data = nullptr;
+  int manufacturer_data_count = 0;
+  found = false;
+
+  for (size_t i = 0; i < types.size() && !found; ++i) {
+    ret = bt_adapter_le_get_scan_result_manufacturer_data(
+        info, types[i], &manufacturer_id, &manufacturer_data,
+        &manufacturer_data_count);
+    if (BT_ERROR_NONE == ret) {
+      found = true;
+    } else {
+      LoggerE("Failed to get device manufacturer (%d). Packet type: %d", ret, types[i]);
+    }
+  }
+
+  if (!found) {
+    return util::GetBluetoothError(ret, "Failed to get device manufacturer.");
+  }
+
+  ManufacturerToJson(manufacturer_id, manufacturer_data,
+                     manufacturer_data_count, le_device);
+  g_free(manufacturer_data);
+  return common::PlatformResult(common::ErrorCode::NO_ERROR);
+}
+
+void BluetoothLEDevice::Connect(const picojson::value& data,
+                                picojson::object& out) {
+  LoggerD("Entered");
+}
+
+void BluetoothLEDevice::Disconnect(const picojson::value& data,
+                                   picojson::object& out) {
+  LoggerD("Entered");
+}
+
+void BluetoothLEDevice::GetService(const picojson::value& data,
+                                   picojson::object& out) {
+  LoggerD("Entered");
+}
+
+void BluetoothLEDevice::AddConnectStateChangeListener(
+    const picojson::value& data, picojson::object& out) {
+  LoggerD("Entered");
+}
+
+void BluetoothLEDevice::RemoveConnectStateChangeListener(
+    const picojson::value& data, picojson::object& out) {
+  LoggerD("Entered");
+}
+
+}  // namespace bluetooth
+}  // namespace extension
diff --git a/src/bluetooth/bluetooth_le_device.h b/src/bluetooth/bluetooth_le_device.h
new file mode 100644 (file)
index 0000000..a38836a
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#ifndef BLUETOOTH_BLUETOOTH_LE_DEVICE_H_
+#define BLUETOOTH_BLUETOOTH_LE_DEVICE_H_
+
+#include <bluetooth.h>
+
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+namespace extension {
+namespace bluetooth {
+
+class BluetoothInstance;
+
+class BluetoothLEDevice {
+ public:
+  explicit BluetoothLEDevice(BluetoothInstance& instance);
+  ~BluetoothLEDevice();
+
+  void Connect(const picojson::value& data, picojson::object& out);
+  void Disconnect(const picojson::value& data, picojson::object& out);
+
+  void GetService(const picojson::value& data, picojson::object& out);
+
+  void AddConnectStateChangeListener(const picojson::value& data,
+                                     picojson::object& out);
+  void RemoveConnectStateChangeListener(const picojson::value& data,
+                                        picojson::object& out);
+
+  static common::PlatformResult ToJson(
+      bt_adapter_le_device_scan_result_info_s* info,
+      picojson::object* le_device);
+
+ private:
+  BluetoothInstance& instance_;
+};
+
+}  // namespace bluetooth
+}  // namespace extension
+
+#endif // BLUETOOTH_BLUETOOTH_LE_DEVICE_H_