namespace {
const std::string kUuid = "uuid";
const std::string kServiceUuid = "serviceUuid";
-const std::string kHandle = "handle";
+const std::string kHandleId = "handleId";
const std::string kAddress = "address";
+const std::string kValue = "value";
const std::string kDescriptors = "descriptors";
const std::string kBroadcast = "isBroadcast";
const std::string kOnValueChanged = "BluetoothGATTCharacteristicValueChangeListener";
+const std::string kGATTService = "GATT service";
+const std::string kGATTCharacteristic = "GATT characteristic";
+const std::string kGATTDescriptor = "GATT descriptor";
+const std::string kGATTObject = "GATT object";
+
bool IsProperty(int propertyBits, bt_gatt_property_e property) {
return (propertyBits & property) != 0;
}
}
+int BluetoothGATTClientService::GATTClient::next_id_ = 0;
+
BluetoothGATTClientService::BluetoothGATTClientService(BluetoothInstance& instance)
: instance_(instance) {
ScopeLogger();
BluetoothGATTClientService::~BluetoothGATTClientService() {
ScopeLogger();
- for (auto it : gatt_characteristic_) {
+ for (const auto& handle_and_id : listened_gatt_handle_to_id) {
// unregister callback, ignore errors
- bt_gatt_client_unset_characteristic_value_changed_cb(it);
+ bt_gatt_client_unset_characteristic_value_changed_cb(handle_and_id.first);
}
- for (auto it : gatt_clients_) {
- LoggerD("destroying client for address: %s", it.first.c_str());
- bt_gatt_client_destroy(it.second);
+ for (const auto& address_and_gatt_client_handle : gatt_clients_) {
+ LoggerD("destroying client for address: %s", address_and_gatt_client_handle.first.c_str());
+ bt_gatt_client_destroy(address_and_gatt_client_handle.second.handle);
}
}
return gatt_clients_.end() != it;
}
-bt_gatt_client_h BluetoothGATTClientService::GetGattClient(const std::string& address) {
- ScopeLogger();
+BluetoothGATTClientService::GATTClientsMap::iterator BluetoothGATTClientService::CreateGATTClient(
+ const std::string& address) {
+ ScopeLogger("address: %s", address.c_str());
bt_gatt_client_h client = nullptr;
- const auto it = gatt_clients_.find(address);
+ const auto client_it = gatt_clients_.find(address);
- if (gatt_clients_.end() == it) {
+ if (client_it == gatt_clients_.end()) {
+ LoggerD("Client not found");
int ret = bt_gatt_client_create(address.c_str(), &client);
if (BT_ERROR_NONE != ret) {
LoggerE("Failed to create GATT client, error: %d", ret);
} else {
- gatt_clients_.insert(std::make_pair(address, client));
+ return gatt_clients_.insert(std::make_pair(address, GATTClient{client})).first;
}
} else {
- LoggerD("Client already created");
- client = it->second;
+ LoggerD("Returning existing client");
}
- return client;
+ return client_it;
+}
+
+PlatformResult BluetoothGATTClientService::GATTHandleFromJSON(const picojson::value& json,
+ const std::string& gatt_object_type,
+ bt_gatt_h* result) {
+ ScopeLogger();
+
+ const auto& address = json.get(kAddress).get<std::string>();
+ auto gatt_handle_id = static_cast<int>(json.get(kHandleId).get<double>());
+ LoggerD("Getting bt_gatt_h for address: %s, handle_id: %d", address.c_str(), gatt_handle_id);
+ auto& gatt_client = gatt_clients_.at(address);
+ auto gatt_handle_it = gatt_client.id_to_handle.find(gatt_handle_id);
+ if (gatt_client.id_to_handle.end() == gatt_handle_it) {
+ return LogAndCreateResult(
+ ErrorCode::INVALID_STATE_ERR, "This " + gatt_object_type + " has been invalidated",
+ ("No handle with %d gatt_handle_id found for address %s", gatt_handle_id, address.c_str()));
+ }
+
+ *result = gatt_handle_it->second;
+ return PlatformResult{ErrorCode::NO_ERROR};
+}
+
+bt_gatt_client_h BluetoothGATTClientService::GetGattClientHandle(const std::string& address) {
+ ScopeLogger("address: %s", address.c_str());
+
+ auto client_it = CreateGATTClient(address);
+ return (gatt_clients_.end() == client_it) ? nullptr : client_it->second.handle;
}
// this method should be used to inform this object that some device was disconnected
void BluetoothGATTClientService::TryDestroyClient(const std::string& address) {
- ScopeLogger();
- 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);
+ ScopeLogger("address: %s", address.c_str());
+
+ auto client_it = gatt_clients_.find(address);
+ if (gatt_clients_.end() != client_it) {
+ auto ret = bt_gatt_client_destroy(client_it->second.handle);
+ LoggerD("bt_gatt_client_destroy(): %d (%s)", ret, get_error_message(ret));
+
+ for (const auto& id_and_handle : client_it->second.id_to_handle) {
+ listened_gatt_handle_to_id.erase(id_and_handle.second);
+ }
+
+ gatt_clients_.erase(client_it);
} else {
LoggerD("Client for address: %s does not exist, no need for deletion", address.c_str());
}
}
-PlatformResult BluetoothGATTClientService::GetSpecifiedGATTClient(const std::string& address,
- const UUID& uuid,
- picojson::object* result) {
- ScopeLogger();
+PlatformResult BluetoothGATTClientService::GetSpecifiedGATTService(const std::string& address,
+ const UUID& uuid,
+ picojson::object* result) {
+ ScopeLogger("address: %s, UUID: %s", address.c_str(), uuid.uuid_in_source_format.c_str());
- bt_gatt_client_h client = GetGattClient(address);
-
- if (nullptr == client) {
+ auto client_it = CreateGATTClient(address);
+ if (gatt_clients_.end() == client_it) {
return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Failed to create the GATT client's handle");
}
bt_gatt_h service = nullptr;
- int ret = bt_gatt_client_get_service(client, uuid.uuid_128_bit.c_str(), &service);
+ int ret =
+ bt_gatt_client_get_service(client_it->second.handle, uuid.uuid_128_bit.c_str(), &service);
if (BT_ERROR_NONE != ret) {
LoggerE("bt_gatt_client_get_service() error: %d", ret);
switch (ret) {
}
}
+ auto gatt_handle_id = client_it->second.AddGATTHandle(service);
+
/*
* BACKWARD COMPATIBILITY
*
*/
result->insert(std::make_pair(kUuid, picojson::value(uuid.uuid_in_source_format)));
result->insert(std::make_pair(kServiceUuid, picojson::value(uuid.uuid_in_source_format)));
- // 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(kHandleId, picojson::value(static_cast<double>(gatt_handle_id))));
+ // address is necessary to later check if device is still connected and retrieve handle
result->insert(std::make_pair(kAddress, picojson::value(address)));
return PlatformResult(ErrorCode::NO_ERROR);
}
void BluetoothGATTClientService::GetServices(const picojson::value& args, picojson::object& out) {
ScopeLogger();
- bt_gatt_h handle = (bt_gatt_h) static_cast<long>(args.get("handle").get<double>());
- const std::string& address = args.get("address").get<std::string>();
+ const std::string& address = args.get(kAddress).get<std::string>();
+
+ if (!IsStillConnected(address)) {
+ LogAndReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR, "Device is not connected"), &out,
+ ("Device with address %s is no longer connected", address.c_str()));
+ return;
+ }
+
+ bt_gatt_h gatt_handle = nullptr;
+ auto result = GATTHandleFromJSON(args, kGATTService, &gatt_handle);
+ if (!result) {
+ ReportError(result, &out);
+ return;
+ }
picojson::array array;
- PlatformResult ret = GetServicesHelper(handle, address, &array);
+ PlatformResult ret = GetServicesHelper(gatt_handle, address, &array);
if (ret.IsError()) {
LogAndReportError(ret, &out, ("Error while getting services"));
} else {
PlatformResult BluetoothGATTClientService::GetServicesHelper(bt_gatt_h handle,
const std::string& address,
picojson::array* array) {
- ScopeLogger();
+ /*
+ * This function expects valid input, i.e. "handle" pointing to an existing
+ * object, "address" to a connected client and a "array" pointing to an
+ * existing picojson::array.
+ */
+ ScopeLogger("address: %s", address.c_str());
- if (!IsStillConnected(address)) {
- return LogAndCreateResult(ErrorCode::INVALID_STATE_ERR, "Device is not connected",
- ("Device with address %s is no longer connected", address.c_str()));
- }
+ auto& gatt_client = gatt_clients_.at(address);
+ std::vector<int> gatt_handle_ids_to_remove_in_case_of_error;
+ struct UserData {
+ picojson::array* array;
+ GATTClient* gatt_client;
+ std::vector<int>* gatt_handle_ids_to_remove_in_case_of_error;
+ } user_data = {array, &gatt_client, &gatt_handle_ids_to_remove_in_case_of_error};
int ret = bt_gatt_service_foreach_included_services(
handle,
result_obj.insert(std::make_pair(kServiceUuid, picojson::value{}));
}
- // handle is passed to upper layer because there is no need of deletion
- result_obj.insert(std::make_pair(kHandle, picojson::value{(double)(long)gatt_handle}));
- static_cast<picojson::array*>(data)->push_back(result);
+ UserData* user_data = static_cast<UserData*>(data);
+ auto gatt_handle_id = user_data->gatt_client->AddGATTHandle(gatt_handle);
+ result_obj.insert(std::make_pair(kHandleId, static_cast<double>(gatt_handle_id)));
+ user_data->gatt_handle_ids_to_remove_in_case_of_error->push_back(gatt_handle_id);
+
+ user_data->array->push_back(result);
return true;
},
- array);
+ static_cast<void*>(&user_data));
+
if (BT_ERROR_NONE != ret) {
LoggerE("Failed bt_gatt_service_foreach_included_services() (%d)", ret);
- return util::GetBluetoothError(ret, "Failed to set a service's GATT callback");
+
+ for (auto gatt_handle_id : gatt_handle_ids_to_remove_in_case_of_error) {
+ gatt_client.id_to_handle.erase(gatt_handle_id);
+ }
+
+ return util::GetBluetoothError(ret, "Failed to get included GATT services");
}
return PlatformResult(ErrorCode::NO_ERROR);
picojson::object& out) {
ScopeLogger();
- bt_gatt_h handle = (bt_gatt_h) static_cast<long>(args.get("handle").get<double>());
+ const std::string& address = args.get(kAddress).get<std::string>();
- const std::string& address = args.get("address").get<std::string>();
+ if (!IsStillConnected(address)) {
+ LogAndReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR, "Device is not connected"), &out,
+ ("Device with address %s is no longer connected", address.c_str()));
+ return;
+ }
+
+ bt_gatt_h gatt_handle = nullptr;
+ auto result = GATTHandleFromJSON(args, kGATTService, &gatt_handle);
+ if (!result) {
+ ReportError(result, &out);
+ return;
+ }
picojson::array array;
- PlatformResult ret = GetCharacteristicsHelper(handle, address, &array);
+ PlatformResult ret = GetCharacteristicsHelper(gatt_handle, address, &array);
if (ret.IsError()) {
LogAndReportError(ret, &out, ("Error while getting characteristics"));
} else {
PlatformResult BluetoothGATTClientService::GetCharacteristicsHelper(bt_gatt_h handle,
const std::string& address,
picojson::array* array) {
- ScopeLogger();
+ /*
+ * This function expects valid input, i.e. "handle" pointing to an existing
+ * object, "address" to a connected client and a "array" pointing to an
+ * existing picojson::array.
+ */
- if (!IsStillConnected(address)) {
- return LogAndCreateResult(ErrorCode::INVALID_STATE_ERR, "Device is not connected",
- ("Device with address %s is no longer connected", address.c_str()));
- }
+ ScopeLogger("address: %s", address.c_str());
+ PlatformResult platform_result = PlatformResult(ErrorCode::NO_ERROR);
+ std::vector<int> gatt_handle_ids_to_remove_in_case_of_error;
+
+ auto& gatt_client = gatt_clients_.at(address);
struct Data {
+ GATTClient* gatt_client;
+ std::vector<int>* gatt_handle_ids_to_remove_in_case_of_error;
picojson::array* array;
PlatformResult* platform_res;
- };
-
- PlatformResult platform_result = PlatformResult(ErrorCode::NO_ERROR);
- Data user_data = {array, &platform_result};
+ } user_data = {&gatt_client, &gatt_handle_ids_to_remove_in_case_of_error, array,
+ &platform_result};
int ret = bt_gatt_service_foreach_characteristics(
handle,
Data* user_data = static_cast<Data*>(data);
picojson::array* array = user_data->array;
PlatformResult* platform_result = user_data->platform_res;
+ GATTClient* gatt_client = user_data->gatt_client;
+ std::vector<int>* gatt_handle_ids_to_remove_in_case_of_error =
+ user_data->gatt_handle_ids_to_remove_in_case_of_error;
picojson::value result = picojson::value(picojson::object());
picojson::object& result_obj = result.get<picojson::object>();
- // handle is passed to upper layer because there is no need of deletion
- result_obj.insert(std::make_pair(kHandle, picojson::value((double)(long)gatt_handle)));
+ auto gatt_handle_id = gatt_client->AddGATTHandle(gatt_handle);
+ result_obj.insert(
+ std::make_pair(kHandleId, picojson::value(static_cast<double>(gatt_handle_id))));
+ gatt_handle_ids_to_remove_in_case_of_error->push_back(gatt_handle_id);
// descriptors
picojson::array& desc_array =
- result_obj.insert(std::make_pair("descriptors", picojson::value(picojson::array())))
+ result_obj.insert(std::make_pair(kDescriptors, picojson::value(picojson::array())))
.first->second.get<picojson::array>();
+ struct DescriptorsData {
+ GATTClient* gatt_client;
+ std::vector<int>* gatt_handle_ids_to_remove_in_case_of_error;
+ picojson::array* desc_array;
+ } descriptors_user_data = {gatt_client, gatt_handle_ids_to_remove_in_case_of_error,
+ &desc_array};
+
int ret = bt_gatt_characteristic_foreach_descriptors(
gatt_handle,
[](int total, int index, bt_gatt_h desc_handle, void* data) {
"Entered into asynchronous function, bt_gatt_characteristic_foreach_descriptors;"
" index: %d",
index);
- picojson::array& desc_array = *(static_cast<picojson::array*>(data));
-
+ DescriptorsData* descriptors_data = static_cast<DescriptorsData*>(data);
+ picojson::array* desc_array = descriptors_data->desc_array;
+ GATTClient* gatt_client = descriptors_data->gatt_client;
+ std::vector<int>* gatt_handle_ids_to_remove_in_case_of_error =
+ descriptors_data->gatt_handle_ids_to_remove_in_case_of_error;
picojson::value desc = picojson::value(picojson::object());
picojson::object& desc_obj = desc.get<picojson::object>();
- // handle is passed to upper layer because there is no need of deletion
- desc_obj.insert(std::make_pair(kHandle, picojson::value((double)(long)desc_handle)));
+ auto gatt_handle_id = gatt_client->AddGATTHandle(desc_handle);
+ desc_obj.insert(
+ std::make_pair(kHandleId, picojson::value(static_cast<double>(gatt_handle_id))));
+ gatt_handle_ids_to_remove_in_case_of_error->push_back(gatt_handle_id);
auto uuid = UUID::createFromGatt(desc_handle);
if (uuid) {
desc_obj.insert(std::make_pair(kUuid, picojson::value{}));
}
- desc_array.push_back(desc);
+ desc_array->push_back(desc);
return true;
},
- static_cast<void*>(&desc_array));
+ static_cast<void*>(&descriptors_user_data));
if (BT_ERROR_NONE != ret) {
*platform_result = util::GetBluetoothError(ret, "Failed to get descriptors");
LoggerE("Failed bt_gatt_characteristic_foreach_descriptors() (%d)", ret);
return platform_result;
}
if (BT_ERROR_NONE != ret) {
- LoggerE("Failed (%d)", ret);
+ LoggerE("bt_gatt_service_foreach_characteristics failed: %d (%s)", ret, get_error_message(ret));
+
+ for (auto& gatt_handle_id : gatt_handle_ids_to_remove_in_case_of_error) {
+ gatt_client.id_to_handle.erase(gatt_handle_id);
+ }
+
return util::GetBluetoothError(ret, "Failed while getting characteristic");
}
CHECK_BACKWARD_COMPABILITY_PRIVILEGE_ACCESS(Privilege::kBluetooth, Privilege::kBluetoothAdmin,
&out);
- const std::string& address = args.get("address").get<std::string>();
+ const std::string& address = args.get(kAddress).get<std::string>();
if (!IsStillConnected(address)) {
LogAndReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR, "Device is not connected"), &out,
("Device with address %s is no longer connected", address.c_str()));
};
Data* user_data = new Data{callback_handle, this};
- bt_gatt_h handle = (bt_gatt_h) static_cast<long>(args.get("handle").get<double>());
+
+ bt_gatt_h gatt_handle = nullptr;
+ auto result = GATTHandleFromJSON(args, kGATTObject, &gatt_handle);
+ if (!result) {
+ ReportError(result, &out);
+ return;
+ }
auto read_value = [](int result, bt_gatt_h handle, void* user_data) -> void {
ScopeLogger("Entered into asynchronous function, read_value");
},
response);
};
- int ret = bt_gatt_client_read_value(handle, read_value, (void*)user_data);
+ int ret = bt_gatt_client_read_value(gatt_handle, read_value, (void*)user_data);
if (BT_ERROR_NONE != ret) {
delete user_data;
user_data = nullptr;
CHECK_BACKWARD_COMPABILITY_PRIVILEGE_ACCESS(Privilege::kBluetooth, Privilege::kBluetoothAdmin,
&out);
- const std::string& address = args.get("address").get<std::string>();
+ const std::string& address = args.get(kAddress).get<std::string>();
if (!IsStillConnected(address)) {
LogAndReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR, "Device is not connected"), &out,
("Device with address %s is no longer connected", address.c_str()));
}
const double callback_handle = util::GetAsyncCallbackHandle(args);
- const picojson::array& value_array = args.get("value").get<picojson::array>();
+ const picojson::array& value_array = args.get(kValue).get<picojson::array>();
int value_size = value_array.size();
std::unique_ptr<char[]> value_data(new char[value_size]);
value_data[i] = (int)value_array[i].get<double>();
}
+ bt_gatt_h gatt_handle = nullptr;
+ auto result = GATTHandleFromJSON(args, kGATTObject, &gatt_handle);
+ if (!result) {
+ ReportError(result, &out);
+ return;
+ }
+
struct Data {
double callback_handle;
BluetoothGATTClientService* service;
};
- bt_gatt_h handle = (bt_gatt_h) static_cast<long>(args.get("handle").get<double>());
-
auto write_value = [](int result, bt_gatt_h handle, void* user_data) -> void {
ScopeLogger("Entered into asynchronous function, write_value");
Data* data = static_cast<Data*>(user_data);
response);
};
- int ret = bt_gatt_set_value(handle, value_data.get(), value_size);
-
+ int ret = bt_gatt_set_value(gatt_handle, value_data.get(), value_size);
if (BT_ERROR_NONE != ret) {
std::shared_ptr<picojson::value> response =
std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
response);
} else {
Data* user_data = new Data{callback_handle, this};
- ret = bt_gatt_client_write_value(handle, write_value, user_data);
+ ret = bt_gatt_client_write_value(gatt_handle, write_value, user_data);
if (BT_ERROR_NONE != ret) {
delete user_data;
LoggerE("Couldn't register callback for write value %d (%s)", ret, get_error_message(ret));
void BluetoothGATTClientService::AddValueChangeListener(const picojson::value& args,
picojson::object& out) {
ScopeLogger();
- const auto& address = args.get("address").get<std::string>();
+
+ const auto& address = args.get(kAddress).get<std::string>();
if (!IsStillConnected(address)) {
LogAndReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR, "Device is not connected"), &out,
("Device with address %s is no longer connected", address.c_str()));
return;
}
- bt_gatt_h handle = (bt_gatt_h) static_cast<long>(args.get(kHandle).get<double>());
+ bt_gatt_h gatt_handle = nullptr;
+ auto result = GATTHandleFromJSON(args, kGATTObject, &gatt_handle);
+ if (!result) {
+ ReportError(result, &out);
+ return;
+ }
- int ret = bt_gatt_client_set_characteristic_value_changed_cb(handle, OnCharacteristicValueChanged,
- this);
+ auto gatt_handle_id = static_cast<int>(args.get(kHandleId).get<double>());
+ LoggerD("Adding change listener for address: %s, gatt_handle_id: %d", address.c_str(),
+ gatt_handle_id);
+
+ int ret = bt_gatt_client_set_characteristic_value_changed_cb(gatt_handle,
+ OnCharacteristicValueChanged, this);
if (BT_ERROR_NONE != ret) {
LogAndReportError(util::GetBluetoothError(ret, "Failed to register listener"), &out,
("bt_gatt_client_set_characteristic_value_changed_cb() failed with: %d (%s)",
ret, get_error_message(ret)));
} else {
- gatt_characteristic_.push_back(handle);
+ listened_gatt_handle_to_id.insert(std::make_pair(gatt_handle, gatt_handle_id));
ReportSuccess(out);
}
}
void BluetoothGATTClientService::RemoveValueChangeListener(const picojson::value& args,
picojson::object& out) {
ScopeLogger();
- const auto& address = args.get("address").get<std::string>();
+
+ const auto& address = args.get(kAddress).get<std::string>();
if (!IsStillConnected(address)) {
LoggerW("Device with address %s is no longer connected", address.c_str());
} else {
- bt_gatt_h handle = (bt_gatt_h) static_cast<long>(args.get(kHandle).get<double>());
+ bt_gatt_h gatt_handle = nullptr;
+ auto result = GATTHandleFromJSON(args, kGATTObject, &gatt_handle);
+ if (!result) {
+ ReportError(result, &out);
+ return;
+ }
- int ret = bt_gatt_client_unset_characteristic_value_changed_cb(handle);
+ auto gatt_handle_id = static_cast<int>(args.get(kHandleId).get<double>());
+ LoggerD("Removing change listener of address: %s, gatt_handle_id: %d", address.c_str(),
+ gatt_handle_id);
+ int ret = bt_gatt_client_unset_characteristic_value_changed_cb(gatt_handle);
if (BT_ERROR_NONE != ret) {
LoggerW("bt_gatt_client_unset_characteristic_value_changed_cb() failed with: %d (%s)", ret,
get_error_message(ret));
} else {
- gatt_characteristic_.erase(
- std::remove(gatt_characteristic_.begin(), gatt_characteristic_.end(), handle),
- gatt_characteristic_.end());
+ listened_gatt_handle_to_id.erase(gatt_handle);
}
}
ReportSuccess(out);
common::PlatformResult BluetoothGATTClientService::GetServiceAllUuids(const std::string& address,
picojson::array* array) {
- ScopeLogger();
-
- bt_gatt_client_h client = GetGattClient(address);
+ ScopeLogger("address: %s", address.c_str());
- if (nullptr == client) {
+ auto client_it = CreateGATTClient(address);
+ if (gatt_clients_.end() == client_it) {
return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unable to create client");
}
return true;
};
- int ret = bt_gatt_client_foreach_services(client, foreach_callback, array);
+ int ret = bt_gatt_client_foreach_services(client_it->second.handle, foreach_callback, array);
if (BT_ERROR_NONE == ret) {
return PlatformResult(ErrorCode::NO_ERROR);
picojson::value result = picojson::value(picojson::object());
picojson::object& result_obj = result.get<picojson::object>();
- result_obj.insert(std::make_pair(kHandle, picojson::value((double)(long)characteristic)));
+ auto listened_gatt_handle_id_it = service->listened_gatt_handle_to_id.find(characteristic);
+ if (service->listened_gatt_handle_to_id.end() == listened_gatt_handle_id_it) {
+ LoggerE("The characteristic has been invalidated.");
+ return;
+ }
+ result_obj.insert(std::make_pair(
+ kHandleId, picojson::value(static_cast<double>(listened_gatt_handle_id_it->second))));
picojson::value byte_array = picojson::value(picojson::array());
picojson::array& byte_array_obj = byte_array.get<picojson::array>();