};
//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;
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;
};
//class BluetoothGATTCharacteristic ////////////////////////////////////////////////////
-var BluetoothGATTCharacteristic = function(data) {
+var BluetoothGATTCharacteristic = function(data, address) {
var handle_ = data.handle;
var descriptors_ = [];
var isBroadcast_ = false;
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;
}
};
- var callArgs = {handle : handle_};
+ var callArgs = {handle : handle_, address : address_};
var result = native.call('BluetoothGATT_readValue', callArgs, callback);
}
};
- 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);
};
//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()');
}
};
- var callArgs = {handle : handle_};
+ var callArgs = {handle : handle_, address : address_};
var result = native.call('BluetoothGATT_readValue', callArgs, callback);
}
};
- 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);
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";
}
}
+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) {
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);
}
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);
}
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;
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);
}
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) {
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;
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;
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>();
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;
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_;