From 287f4fee1b976b2d5982d06fdef35b703aca5cbd Mon Sep 17 00:00:00 2001 From: Lukasz Bardeli Date: Wed, 6 May 2015 12:02:54 +0200 Subject: [PATCH] [BluetoothLE] Implementation of Bluetooth LE Device ToJson method [Verification] Code compiles without errors. Change-Id: I1a29d6284e35debefe405dc6fcdf1e704c152bc4 Signed-off-by: Lukasz Bardeli --- src/bluetooth/bluetooth.gyp | 2 + src/bluetooth/bluetooth_api.js | 68 ++++-- src/bluetooth/bluetooth_instance.cc | 22 +- src/bluetooth/bluetooth_instance.h | 2 + src/bluetooth/bluetooth_le_adapter.cc | 12 +- src/bluetooth/bluetooth_le_device.cc | 301 ++++++++++++++++++++++++++ src/bluetooth/bluetooth_le_device.h | 56 +++++ 7 files changed, 433 insertions(+), 30 deletions(-) create mode 100644 src/bluetooth/bluetooth_le_device.cc create mode 100644 src/bluetooth/bluetooth_le_device.h diff --git a/src/bluetooth/bluetooth.gyp b/src/bluetooth/bluetooth.gyp index 9bf3975a..d277032e 100644 --- a/src/bluetooth/bluetooth.gyp +++ b/src/bluetooth/bluetooth.gyp @@ -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', diff --git a/src/bluetooth/bluetooth_api.js b/src/bluetooth/bluetooth_api.js index d0d78f70..3afd0e1e 100644 --- a/src/bluetooth/bluetooth_api.js +++ b/src/bluetooth/bluetooth_api.js @@ -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} }); }; diff --git a/src/bluetooth/bluetooth_instance.cc b/src/bluetooth/bluetooth_instance.cc index a655d382..9781c67b 100644 --- a/src/bluetooth/bluetooth_instance.cc +++ b/src/bluetooth/bluetooth_instance.cc @@ -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 } diff --git a/src/bluetooth/bluetooth_instance.h b/src/bluetooth/bluetooth_instance.h index fddb3f63..cd9f743e 100644 --- a/src/bluetooth/bluetooth_instance.h +++ b/src/bluetooth/bluetooth_instance.h @@ -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 diff --git a/src/bluetooth/bluetooth_le_adapter.cc b/src/bluetooth/bluetooth_le_adapter.cc index 426e64c1..718e4028 100644 --- a/src/bluetooth/bluetooth_le_adapter.cc +++ b/src/bluetooth/bluetooth_le_adapter.cc @@ -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 index 00000000..625ee401 --- /dev/null +++ b/src/bluetooth/bluetooth_le_device.cc @@ -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 + +#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(); + + 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(); + + for (int i = 0; i < service_data_list_count; i++) { + picojson::value response = picojson::value(picojson::object()); + picojson::object& response_obj = response.get(); + 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(); + 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 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(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(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 index 00000000..a38836a4 --- /dev/null +++ b/src/bluetooth/bluetooth_le_device.h @@ -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 + +#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_ -- 2.34.1