// class BluetoothGATTServer ////////////////////////
var _BluetoothGATTServerServices = [];
+/*
+ * This set is used in BluetoothGATTServer::start() to check which services
+ * from BluetoothGATTServer::services have already been registered in native
+ * layer and which have to be registered.
+ */
+var _BluetoothGATTServerServicesRegisteredInNativeLayer = {};
+
var BluetoothGATTServer = function() {
Object.defineProperties(this, {
services: {
}
};
+/*
+ * Objects of this class are used to wait for multiple callbacks results.
+ *
+ * Its successCallback and errorCallback members should be passed as
+ * the success and error callbacks, respectively, to the functions we wait for.
+ * When the functions we wait for are called callbacksNum times, either
+ * onAllSucceeded or onFailure is called, depending on whether only
+ * successCallback was called or not.
+ *
+ * For the usage example, take a look at BluetoothGATTServer.prototype.start,
+ * where it's used to wait for registration of multiple services.
+ */
+var ResultCallbacksAggregator = function(callbacksNum, onAllSucceeded, onFailure) {
+ var _callbacksNum = callbacksNum;
+ var _allSucceeded = true;
+ var _error;
+
+ this.successCallback = function (){
+ _callbacksNum--;
+
+ if (!_callbacksNum) {
+ if (_allSucceeded) {
+ onAllSucceeded();
+ } else {
+ onFailure(_error);
+ }
+ }
+ };
+
+ this.errorCallback = function(error) {
+ _callbacksNum--;
+ _allSucceeded = false;
+ _error = error;
+
+ if (!_callbacksNum) {
+ onFailure(_error);
+ }
+ };
+};
+
var BluetoothGATTServer_valid_start_errors = ['InvalidStateError', 'NotSupportedError', 'AbortError'];
var BluetoothGATTServer_valid_start_exceptions = ['InvalidStateError', 'TypeMismatchError', 'SecurityError'];
}
]);
- var callback = function(result) {
+ var servicesUnregisteredInNativeLayer = [];
+ for (var i = 0; i < this.services.length; ++i) {
+ if(this.services[i]) {
+ if (!_BluetoothGATTServerServicesRegisteredInNativeLayer[this.services[i]._id]) {
+ servicesUnregisteredInNativeLayer.push(this.services[i]);
+ }
+ }
+ }
+
+ var startServerCallback = function(result) {
if (native.isFailure(result)) {
native.callIfPossible(args.errorCallback,
native.getErrorObjectAndValidate(result,
}
};
- var result = native.call('BluetoothGATTServerStart', {}, callback);
- if (native.isFailure(result)) {
- throw native.getErrorObjectAndValidate(result, BluetoothGATTServer_valid_start_exceptions, AbortError);
+ if (servicesUnregisteredInNativeLayer.length) {
+ var registerServiceCallbacksAggregator = new ResultCallbacksAggregator(servicesUnregisteredInNativeLayer.length,
+ function onAllSucceeded() {
+
+ var result = native.call('BluetoothGATTServerStart', {}, startServerCallback);
+
+ if (native.isFailure(result)) {
+ throw native.getErrorObjectAndValidate(result, BluetoothGATTServer_valid_start_exceptions, AbortError);
+ }
+ },
+ function onFailure(error) {
+ native.callIfPossible(args.errorCallback,
+ native.getErrorObjectAndValidate(error,
+ BluetoothGATTServer_valid_start_errors, AbortError));
+ });
+
+ var registerServicesCallback = function(result) {
+ if (native.isFailure(result)) {
+ registerServiceCallbacksAggregator.errorCallback(
+ native.getErrorObjectAndValidate(result,
+ BluetoothGATTServer_valid_start_errors, AbortError));
+ } else {
+ registerServiceCallbacksAggregator.successCallback();
+ }
+ };
+
+ for (var i = 0; i < servicesUnregisteredInNativeLayer.length; ++i) {
+ var result = native.call('BluetoothGATTServerRegisterService', servicesUnregisteredInNativeLayer[i], registerServicesCallback);
+ if (native.isFailure(result)) {
+ throw native.getErrorObjectAndValidate(
+ result,
+ BluetoothGATTServer_valid_registerService_exceptions,
+ AbortError
+ );
+ }
+ }
+ } else {
+ var result = native.call('BluetoothGATTServerStart', {}, startServerCallback);
+
+ if (native.isFailure(result)) {
+ throw native.getErrorObjectAndValidate(result, BluetoothGATTServer_valid_start_exceptions, AbortError);
+ }
}
}
native.getErrorObjectAndValidate(result,
BluetoothGATTServer_valid_stop_errors, AbortError));
} else {
+ _BluetoothGATTServerServicesRegisteredInNativeLayer = {};
native.callIfPossible(args.successCallback);
}
};