2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 var T = xwalk.utils.type;
18 var Converter = xwalk.utils.converter;
19 var AV = xwalk.utils.validator;
20 var Privilege = xwalk.utils.privilege;
21 var privUtils_ = xwalk.utils;
22 var native = new xwalk.utils.NativeManager(extension);
24 var AbortError = new WebAPIException('AbortError', 'An unknown error occurred');
26 // class BluetoothClassDeviceMajor /////////////////////////////////////////
27 var BluetoothClassDeviceMajor = function() {
28 Object.defineProperties(this, {
29 MISC: { value: 0x00, writable: false, enumerable: true },
30 COMPUTER: { value: 0x01, writable: false, enumerable: true },
31 PHONE: { value: 0x02, writable: false, enumerable: true },
32 NETWORK: { value: 0x03, writable: false, enumerable: true },
33 AUDIO_VIDEO: { value: 0x04, writable: false, enumerable: true },
34 PERIPHERAL: { value: 0x05, writable: false, enumerable: true },
35 IMAGING: { value: 0x06, writable: false, enumerable: true },
36 WEARABLE: { value: 0x07, writable: false, enumerable: true },
37 TOY: { value: 0x08, writable: false, enumerable: true },
38 HEALTH: { value: 0x09, writable: false, enumerable: true },
39 UNCATEGORIZED: { value: 0x1f, writable: false, enumerable: true }
43 // class BluetoothClassDeviceMinor /////////////////////////////////////////
44 var BluetoothClassDeviceMinor = function() {
45 Object.defineProperties(this, {
46 COMPUTER_UNCATEGORIZED: { value: 0x00, writable: false, enumerable: true },
47 COMPUTER_DESKTOP: { value: 0x01, writable: false, enumerable: true },
48 COMPUTER_SERVER: { value: 0x02, writable: false, enumerable: true },
49 COMPUTER_LAPTOP: { value: 0x03, writable: false, enumerable: true },
50 COMPUTER_HANDHELD_PC_OR_PDA: { value: 0x04, writable: false, enumerable: true },
51 COMPUTER_PALM_PC_OR_PDA: { value: 0x05, writable: false, enumerable: true },
52 COMPUTER_WEARABLE: { value: 0x06, writable: false, enumerable: true },
54 PHONE_UNCATEGORIZED: { value: 0x00, writable: false, enumerable: true },
55 PHONE_CELLULAR: { value: 0x01, writable: false, enumerable: true },
56 PHONE_CORDLESS: { value: 0x02, writable: false, enumerable: true },
57 PHONE_SMARTPHONE: { value: 0x03, writable: false, enumerable: true },
58 PHONE_MODEM_OR_GATEWAY: { value: 0x04, writable: false, enumerable: true },
59 PHONE_ISDN: { value: 0x05, writable: false, enumerable: true },
61 AV_UNRECOGNIZED: { value: 0x00, writable: false, enumerable: true },
62 AV_WEARABLE_HEADSET: { value: 0x01, writable: false, enumerable: true },
63 AV_HANDSFREE: { value: 0x02, writable: false, enumerable: true },
64 AV_MICROPHONE: { value: 0x04, writable: false, enumerable: true },
65 AV_LOUDSPEAKER: { value: 0x05, writable: false, enumerable: true },
66 AV_HEADPHONES: { value: 0x06, writable: false, enumerable: true },
67 AV_PORTABLE_AUDIO: { value: 0x07, writable: false, enumerable: true },
68 AV_CAR_AUDIO: { value: 0x08, writable: false, enumerable: true },
69 AV_SETTOP_BOX: { value: 0x09, writable: false, enumerable: true },
70 AV_HIFI: { value: 0x0a, writable: false, enumerable: true },
71 AV_VCR: { value: 0x0b, writable: false, enumerable: true },
72 AV_VIDEO_CAMERA: { value: 0x0c, writable: false, enumerable: true },
73 AV_CAMCORDER: { value: 0x0d, writable: false, enumerable: true },
74 AV_MONITOR: { value: 0x0e, writable: false, enumerable: true },
75 AV_DISPLAY_AND_LOUDSPEAKER: { value: 0x0f, writable: false, enumerable: true },
76 AV_VIDEO_CONFERENCING: { value: 0x10, writable: false, enumerable: true },
77 AV_GAMING_TOY: { value: 0x12, writable: false, enumerable: true },
79 PERIPHERAL_UNCATEGORIZED: { value: 0x00, writable: false, enumerable: true },
80 PERIPHERAL_KEYBOARD: { value: 0x10, writable: false, enumerable: true },
81 PERIPHERAL_POINTING_DEVICE: { value: 0x20, writable: false, enumerable: true },
82 PERIPHERAL_KEYBOARD_AND_POINTING_DEVICE: {
87 PERIPHERAL_JOYSTICK: { value: 0x01, writable: false, enumerable: true },
88 PERIPHERAL_GAMEPAD: { value: 0x02, writable: false, enumerable: true },
89 PERIPHERAL_REMOTE_CONTROL: { value: 0x03, writable: false, enumerable: true },
90 PERIPHERAL_SENSING_DEVICE: { value: 0x04, writable: false, enumerable: true },
91 PERIPHERAL_DEGITIZER_TABLET: { value: 0x05, writable: false, enumerable: true },
92 PERIPHERAL_CARD_READER: { value: 0x06, writable: false, enumerable: true },
93 PERIPHERAL_DIGITAL_PEN: { value: 0x07, writable: false, enumerable: true },
94 PERIPHERAL_HANDHELD_SCANNER: { value: 0x08, writable: false, enumerable: true },
95 PERIPHERAL_HANDHELD_INPUT_DEVICE: {
101 IMAGING_UNCATEGORIZED: { value: 0x00, writable: false, enumerable: true },
102 IMAGING_DISPLAY: { value: 0x04, writable: false, enumerable: true },
103 IMAGING_CAMERA: { value: 0x08, writable: false, enumerable: true },
104 IMAGING_SCANNER: { value: 0x10, writable: false, enumerable: true },
105 IMAGING_PRINTER: { value: 0x20, writable: false, enumerable: true },
107 WEARABLE_WRITST_WATCH: { value: 0x01, writable: false, enumerable: true },
108 WEARABLE_PAGER: { value: 0x02, writable: false, enumerable: true },
109 WEARABLE_JACKET: { value: 0x03, writable: false, enumerable: true },
110 WEARABLE_HELMET: { value: 0x04, writable: false, enumerable: true },
111 WEARABLE_GLASSES: { value: 0x05, writable: false, enumerable: true },
113 TOY_ROBOT: { value: 0x01, writable: false, enumerable: true },
114 TOY_VEHICLE: { value: 0x02, writable: false, enumerable: true },
115 TOY_DOLL: { value: 0x03, writable: false, enumerable: true },
116 TOY_CONTROLLER: { value: 0x04, writable: false, enumerable: true },
117 TOY_GAME: { value: 0x05, writable: false, enumerable: true },
119 HEALTH_UNDEFINED: { value: 0x00, writable: false, enumerable: true },
120 HEALTH_BLOOD_PRESSURE_MONITOR: { value: 0x01, writable: false, enumerable: true },
121 HEALTH_THERMOMETER: { value: 0x02, writable: false, enumerable: true },
122 HEALTH_WEIGHING_SCALE: { value: 0x03, writable: false, enumerable: true },
123 HEALTH_GLUCOSE_METER: { value: 0x04, writable: false, enumerable: true },
124 HEALTH_PULSE_OXIMETER: { value: 0x05, writable: false, enumerable: true },
125 HEALTH_PULSE_RATE_MONITOR: { value: 0x06, writable: false, enumerable: true },
126 HEALTH_DATA_DISPLAY: { value: 0x07, writable: false, enumerable: true },
127 HEALTH_STEP_COUNTER: { value: 0x08, writable: false, enumerable: true },
128 HEALTH_BODY_COMPOSITION_ANALYZER: {
133 HEALTH_PEAK_FLOW_MONITOR: { value: 0x0a, writable: false, enumerable: true },
134 HEALTH_MEDICATION_MONITOR: { value: 0x0b, writable: false, enumerable: true },
135 HEALTH_KNEE_PROSTHESIS: { value: 0x0c, writable: false, enumerable: true },
136 HEALTH_ANKLE_PROSTHESIS: { value: 0x0d, writable: false, enumerable: true }
140 // class BluetoothClassDeviceService ///////////////////////////////////////
141 var BluetoothClassDeviceService = function() {
142 Object.defineProperties(this, {
143 LIMITED_DISCOVERABILITY: { value: 0x0001, writable: false, enumerable: true },
144 POSITIONING: { value: 0x0008, writable: false, enumerable: true },
145 NETWORKING: { value: 0x0010, writable: false, enumerable: true },
146 RENDERING: { value: 0x0020, writable: false, enumerable: true },
147 CAPTURING: { value: 0x0040, writable: false, enumerable: true },
148 OBJECT_TRANSFER: { value: 0x0080, writable: false, enumerable: true },
149 AUDIO: { value: 0x0100, writable: false, enumerable: true },
150 TELEPHONY: { value: 0x0200, writable: false, enumerable: true },
151 INFORMATION: { value: 0x0400, writable: false, enumerable: true }
155 //class tizen.BluetoothLEServiceData ///////////////////////////
156 tizen.BluetoothLEServiceData = function(d) {
157 AV.isConstructorCall(this, tizen.BluetoothLEServiceData);
161 Object.defineProperties(this, {
168 uuid_ = Converter.toString(v);
178 data_ = BluetoothManager_toDOMString(v);
180 data_ = Converter.toString(v);
186 if (arguments.length >= 2) {
187 // public constructor
188 this.uuid = arguments[0];
189 this.data = arguments[1];
190 } else if (d && T.isObject(d)) {
191 // internal constructor
200 //class BluetoothLEAdvertiseData ///////////////////////////
201 tizen.BluetoothLEAdvertiseData = function(dict) {
202 AV.isConstructorCall(this, tizen.BluetoothLEAdvertiseData);
203 var includeName_ = false;
205 var solicitationuuids_ = null;
206 var appearance_ = null;
207 var includeTxPowerLevel_ = false;
208 var serviceData_ = null;
209 var servicesData_ = null;
210 var manufacturerData_ = null;
212 Object.defineProperties(this, {
219 includeName_ = Converter.toBoolean(v, true);
230 } else if (T.isArray(v)) {
231 for (var i = 0; i < v.length; ++i) {
232 if (!T.isString(v[i])) {
233 v[i] = Converter.toString(v[i]);
243 return solicitationuuids_;
247 solicitationuuids_ = v;
248 } else if (T.isArray(v)) {
249 for (var i = 0; i < v.length; ++i) {
250 if (!T.isString(v[i])) {
251 v[i] = Converter.toString(v[i]);
254 solicitationuuids_ = v;
264 appearance_ = Converter.toUnsignedLong(v, true);
267 includeTxPowerLevel: {
270 return includeTxPowerLevel_;
273 includeTxPowerLevel_ = Converter.toBoolean(v, true);
282 if (T.isNull(v) || v instanceof tizen.BluetoothLEServiceData) {
290 return servicesData_;
295 } else if (T.isArray(v)) {
297 for (var i = 0; i < v.length; ++i) {
298 if (v[i] instanceof tizen.BluetoothLEServiceData) {
302 servicesData_ = tmpArray;
309 return manufacturerData_;
312 if (T.isNull(v) || v instanceof tizen.BluetoothLEManufacturerData) {
313 manufacturerData_ = v;
319 if (T.isObject(dict)) {
323 if (T.isNull(dict.includeName) || T.isBoolean(dict.includeName)) {
324 o.includeName = dict.includeName;
325 } else if (!T.isUndefined(dict.includeName)) {
330 if (T.isNull(dict.uuids)) {
331 o.uuids = dict.uuids;
332 } else if (T.isArray(dict.uuids)) {
333 for (var i = 0; i < dict.uuids.length; ++i) {
334 if (!T.isString(dict.uuids[i])) {
338 o.uuids = dict.uuids;
339 } else if (!T.isUndefined(dict.uuids)) {
344 if (T.isNull(dict.solicitationuuids)) {
345 o.solicitationuuids = dict.solicitationuuids;
346 } else if (T.isArray(dict.solicitationuuids)) {
347 for (var i = 0; i < dict.solicitationuuids.length; ++i) {
348 if (!T.isString(dict.solicitationuuids[i])) {
352 o.solicitationuuids = dict.solicitationuuids;
353 } else if (!T.isUndefined(dict.solicitationuuids)) {
358 if (T.isNull(dict.appearance) || T.isNumber(dict.appearance)) {
359 o.appearance = dict.appearance;
360 } else if (!T.isUndefined(dict.appearance)) {
364 // includeTxPowerLevel
365 if (T.isNull(dict.includeTxPowerLevel) || T.isBoolean(dict.includeTxPowerLevel)) {
366 o.includeTxPowerLevel = dict.includeTxPowerLevel;
367 } else if (!T.isUndefined(dict.includeTxPowerLevel)) {
373 T.isNull(dict.serviceData) ||
374 dict.serviceData instanceof tizen.BluetoothLEServiceData
376 o.serviceData = dict.serviceData;
377 } else if (!T.isUndefined(dict.serviceData)) {
382 if (T.isNull(dict.servicesData) || T.isArray(dict.servicesData)) {
383 // additional validation is done in setter of BluetoothLEAdvertiseData.servicesData
384 o.servicesData = dict.servicesData;
389 T.isNull(dict.manufacturerData) ||
390 dict.manufacturerData instanceof tizen.BluetoothLEManufacturerData
392 o.manufacturerData = dict.manufacturerData;
393 } else if (!T.isUndefined(dict.manufacturerData)) {
397 for (var prop in o) {
398 if (o.hasOwnProperty(prop) && this.hasOwnProperty(prop)) {
399 this[prop] = o[prop];
405 //class tizen.BluetoothLEManufacturerData ///////////////////////////
406 tizen.BluetoothLEManufacturerData = function(d) {
407 AV.isConstructorCall(this, tizen.BluetoothLEManufacturerData);
411 Object.defineProperties(this, {
418 id_ = Converter.toString(v);
428 data_ = BluetoothManager_toDOMString(v);
430 data_ = Converter.toString(v);
436 if (arguments.length >= 2) {
437 // public constructor
438 this.id = arguments[0];
439 this.data = arguments[1];
440 } else if (d && T.isObject(d)) {
441 // internal constructor
450 // class BluetoothClass ///////////////////////////
451 var BluetoothClass = function(data) {
454 services = data.services;
457 Object.defineProperties(this, {
458 major: { value: data.major, writable: false, enumerable: true },
459 minor: { value: data.minor, writable: false, enumerable: true },
464 return services.slice();
470 var BluetoothClass_hasService = function() {
471 privUtils_.log('Entered BluetoothClass.hasService()');
472 privUtils_.checkPrivilegeAccess4Ver(
475 Privilege.BLUETOOTH_GAP
478 var args = AV.validateArgs(arguments, [
481 type: AV.Types.UNSIGNED_LONG
485 var size = this.services.length;
486 for (var i = 0; i < size; i++) {
487 if (this.services[i] === args.service) {
494 BluetoothClass.prototype.hasService = function() {
495 return BluetoothClass_hasService.apply(this, arguments);
498 // class BluetoothSocket ///////////////////////////
499 var _BLUETOOTH_SOCKET_STATE_CLOSED = 'CLOSED';
501 function BluetoothSocketListeners() {
503 this.socketCallback = function(data) {
505 var socket = that.sockets[event.id];
508 if ('onclose' === event.event) {
510 that.removeListener(event.id);
512 Object.defineProperty(socket, 'state', {
513 value: _BLUETOOTH_SOCKET_STATE_CLOSED
517 var callback = socket[event.event];
518 if (T.isFunction(callback)) {
522 privUtils_.log('Received event for an unknown socket: ' + event.id);
527 BluetoothSocketListeners.prototype.sockets = {};
529 BluetoothSocketListeners.prototype.addListener = function(socket) {
530 if (T.isEmptyObject(this.sockets)) {
531 native.addListener('BLUETOOTH_SOCKET_STATE_CHANGED', this.socketCallback);
534 this.sockets[socket._id] = socket;
537 BluetoothSocketListeners.prototype.removeListener = function(id) {
538 delete this.sockets[id];
540 if (T.isEmptyObject(this.sockets)) {
541 native.removeListener('BLUETOOTH_SOCKET_STATE_CHANGED', this.socketCallback);
545 var _bluetoothSocketListeners = new BluetoothSocketListeners();
547 var BluetoothSocket = function(data) {
548 Object.defineProperties(this, {
549 uuid: { value: data.uuid, writable: false, enumerable: true },
557 value: new BluetoothDevice(data.peer),
561 onmessage: { value: null, writable: true, enumerable: true },
562 onclose: { value: null, writable: true, enumerable: true },
563 _id: { value: data.id, writable: false, enumerable: false }
566 _bluetoothSocketListeners.addListener(this);
569 BluetoothSocket.prototype.writeData = function(data) {
570 privUtils_.log('Entered BluetoothSocket.writeData()');
572 var byteData = BluetoothManager_toByteArray(data);
579 var result = native.callSync('BluetoothSocketWriteData', callArgs);
581 if (native.isFailure(result)) {
582 throw native.getErrorObject(result);
584 return native.getResultObject(result);
588 BluetoothSocket.prototype.readData = function() {
589 privUtils_.log('Entered BluetoothSocket.readData()');
595 var result = native.callSync('BluetoothSocketReadData', callArgs);
597 if (native.isFailure(result)) {
598 throw native.getErrorObject(result);
600 return native.getResultObject(result);
604 BluetoothSocket.prototype.close = function() {
605 privUtils_.log('Entered BluetoothSocket.close()');
607 if (_BLUETOOTH_SOCKET_STATE_CLOSED !== this.state) {
612 var result = native.callSync('BluetoothSocketClose', callArgs);
614 if (native.isFailure(result)) {
615 throw native.getErrorObject(result);
619 Object.defineProperty(this, 'state', { value: _BLUETOOTH_SOCKET_STATE_CLOSED });
623 //class BluetoothLEDevice ///////////////////////////
624 var BluetoothLEDevice = function(data) {
630 solicitationuuids = null,
632 manufacturerData = null,
636 address = data.address;
637 name = data.name || null;
638 txpowerlevel = data.txpowerlevel || null;
639 appearance = data.appearance || null;
640 uuids = data.uuids || null;
641 solicitationuuids = data.solicitationuuids || null;
642 if (data.serviceData) {
644 data.serviceData.forEach(function(d) {
645 serviceData.push(new tizen.BluetoothLEServiceData(d));
648 if (data.manufacturerData) {
649 manufacturerData = new tizen.BluetoothLEManufacturerData(
650 data.manufacturerData
658 Object.defineProperties(this, {
659 address: { value: address, writable: false, enumerable: true },
660 name: { value: name, writable: false, enumerable: true },
661 txpowerlevel: { value: txpowerlevel, writable: false, enumerable: true },
662 appearance: { value: appearance, writable: false, enumerable: true },
667 var service_uuids = uuids ? uuids.slice() : null;
668 return service_uuids;
675 return solicitationuuids ? solicitationuuids.slice() : null;
682 return serviceData ? serviceData.slice() : null;
686 value: manufacturerData,
690 rssi: { value: rssi, writable: false, enumerable: true }
694 BluetoothLEDevice.prototype.connect = function() {
695 privUtils_.log('Entered BluetoothLEDevice.connect()');
696 var args = AV.validateArgs(arguments, [
698 name: 'successCallback',
699 type: AV.Types.FUNCTION,
704 name: 'errorCallback',
705 type: AV.Types.FUNCTION,
711 var callback = function(result) {
712 if (native.isFailure(result)) {
713 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
715 native.callIfPossible(args.successCallback);
718 // Errors are handled by error callback
719 var result = native.call(
720 'BluetoothLEDeviceConnect',
721 { address: this.address },
724 if (native.isFailure(result)) {
725 throw native.getErrorObject(result);
729 BluetoothLEDevice.prototype.disconnect = function() {
730 privUtils_.log('Entered BluetoothLEDevice.disconnect()');
731 var args = AV.validateArgs(arguments, [
733 name: 'successCallback',
734 type: AV.Types.FUNCTION,
739 name: 'errorCallback',
740 type: AV.Types.FUNCTION,
745 var callback = function(result) {
746 if (native.isFailure(result)) {
747 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
749 native.callIfPossible(args.successCallback);
753 var result = native.call(
754 'BluetoothLEDeviceDisconnect',
755 { address: this.address },
758 if (native.isFailure(result)) {
759 throw native.getErrorObject(result);
763 BluetoothLEDevice.prototype.getService = function() {
764 privUtils_.log('Entered BluetoothLEDevice.getService()');
765 var args = AV.validateArgs(arguments, [
768 type: AV.Types.STRING
774 address: this.address
777 var result = native.callSync('BluetoothLEDeviceGetService', callArgs);
778 if (native.isFailure(result)) {
779 throw native.getErrorObject(result);
781 return new BluetoothGATTService(native.getResultObject(result));
785 BluetoothLEDevice.prototype.getServiceAllUuids = function() {
786 privUtils_.log('Entered BluetoothLEDevice.getServiceAllUuids()');
789 address: this.address
792 var result = native.callSync('BluetoothLEDeviceGetServiceAllUuids', callArgs);
793 if (native.isFailure(result)) {
794 throw native.getErrorObject(result);
796 var uuids = native.getResultObject(result);
801 BluetoothLEDevice.prototype.isConnected = function() {
802 privUtils_.log('Entered BluetoothLEDevice.isConnected()');
805 address: this.address
808 var result = native.callSync('BluetoothLEDeviceIsConnected', callArgs);
809 if (native.isFailure(result)) {
810 throw native.getErrorObject(result);
812 return native.getResultObject(result);
815 BluetoothLEDevice.prototype.addConnectStateChangeListener = function() {
816 privUtils_.log('Entered BluetoothLEDevice.addConnectStateChangeListener()');
817 var args = AV.validateArgs(arguments, [
820 type: AV.Types.LISTENER,
821 values: ['onconnected', 'ondisconnected']
827 var func = function(event) {
828 if (event.address === that.address && args.listener[event.action]) {
829 args.listener[event.action](that);
833 var watchId = _bleConnectChangeListener.addListener(func);
838 BluetoothLEDevice.prototype.removeConnectStateChangeListener = function() {
839 privUtils_.log('Entered BluetoothLEDevice.removeConnectStateChangeListener()');
841 var args = AV.validateArgs(arguments, [
848 _bleConnectChangeListener.removeListener(args.watchID);
851 BluetoothLEDevice.prototype.getAttMtu = function() {
852 privUtils_.log('Entered BluetoothLEDevice.getAttMtu()');
855 address: this.address
858 var result = native.callSync('BluetoothLEDeviceGetAttMtu', callArgs);
859 if (native.isFailure(result)) {
860 throw native.getErrorObject(result);
862 return native.getResultObject(result);
865 BluetoothLEDevice.prototype.requestAttMtuChange = function() {
866 privUtils_.log('Entered BluetoothLEDevice.requestAttMtuChange()');
868 var args = AV.validateArgs(arguments, [
876 address: this.address,
880 var result = native.callSync('BluetoothLEDeviceRequestAttMtuChange', callArgs);
881 if (native.isFailure(result)) {
882 throw native.getErrorObject(result);
884 return native.getResultObject(result);
887 BluetoothLEDevice.prototype.addAttMtuChangeListener = function() {
888 privUtils_.log('Entered BluetoothLEDevice.addAttMtuChangeListener()');
889 var args = AV.validateArgs(arguments, [
892 type: AV.Types.FUNCTION
896 var callArgs = { address: this.address };
898 var callback = function(result) {
899 privUtils_.log('Entered BluetoothLEDevice.addAttMtuChangeListener() callback');
900 args.callback(result.attMtuValue);
903 var watchId = _bleAttMtuChangeListener.addListener(callback, callArgs);
908 BluetoothLEDevice.prototype.removeAttMtuChangeListener = function() {
909 privUtils_.log('Entered BluetoothLEDevice.removeAttMtuChangeListener()');
911 var args = AV.validateArgs(arguments, [
918 var callArgs = { address: this.address };
920 _bleAttMtuChangeListener.removeListener(args.watchID, callArgs);
923 // class BluetoothDevice ///////////////////////////
924 var BluetoothDevice = function(data) {
926 function _getter(field) {
929 callArgs.address = self.address;
930 callArgs.field = field;
932 var result = native.callSync('BluetoothDeviceGetBoolValue', callArgs);
934 if (native.isFailure(result)) {
937 return native.getResultObject(result);
941 function isBondedGetter() {
942 return _getter('isBonded');
945 function isTrustedGetter() {
946 return _getter('isTrusted');
949 function isConnectedGetter() {
950 return _getter('isConnected');
958 Object.defineProperties(this, {
959 name: { value: data.name, writable: false, enumerable: true },
960 address: { value: data.address, writable: false, enumerable: true },
962 value: new BluetoothClass(data.deviceClass),
979 get: isConnectedGetter
985 return uuids.slice();
991 BluetoothDevice.prototype.connectToServiceByUUID = function() {
992 privUtils_.log('Entered BluetoothDevice.connectToServiceByUUID()');
994 var args = AV.validateArgs(arguments, [
997 type: AV.Types.STRING
1000 name: 'successCallback',
1001 type: AV.Types.FUNCTION
1004 name: 'errorCallback',
1005 type: AV.Types.FUNCTION,
1012 address: this.address,
1015 var callback = function(result) {
1016 if (native.isFailure(result)) {
1017 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
1019 args.successCallback(new BluetoothSocket(native.getResultObject(result)));
1023 var result = native.call('BluetoothDeviceConnectToServiceByUUID', callArgs, callback);
1024 if (native.isFailure(result)) {
1025 throw native.getErrorObject(result);
1029 // class BluetoothServiceHandler ///////////////////////////
1030 function BluetoothServiceListeners() {
1032 this.serviceCallback = function(data) {
1034 var service = that.services[e.uuid];
1035 var result = new BluetoothSocket(e);
1038 privUtils_.log(service);
1039 service.onconnect(result);
1044 BluetoothServiceListeners.prototype.services = {};
1046 BluetoothServiceListeners.prototype.addListener = function(service) {
1047 if (T.isEmptyObject(this.services)) {
1048 native.addListener('BLUETOOTH_SERVICE_ONCONNECT', this.serviceCallback);
1051 this.services[service.uuid] = service;
1054 BluetoothServiceListeners.prototype.removeListener = function(uuid) {
1055 delete this.services[uuid];
1057 if (T.isEmptyObject(this.services)) {
1058 native.removeListener('BLUETOOTH_SERVICE_ONCONNECT', this.serviceCallback);
1062 var _bluetoothServiceListeners = new BluetoothServiceListeners();
1064 var BluetoothServiceHandler = function(data) {
1065 function isConnectedGetter() {
1070 var result = native.callSync('BluetoothAdapterIsServiceConnected', {
1074 if (native.isFailure(result)) {
1077 return native.getResultObject(result);
1081 Object.defineProperties(this, {
1082 uuid: { value: data.uuid, writable: false, enumerable: true },
1083 name: { value: data.name, writable: false, enumerable: true },
1087 get: isConnectedGetter
1089 onconnect: { value: null, writable: true, enumerable: true }
1092 _bluetoothServiceListeners.addListener(this);
1095 BluetoothServiceHandler.prototype.unregister = function() {
1096 privUtils_.log('Entered BluetoothServiceHandler.unregister()');
1097 var args = AV.validateArgs(arguments, [
1099 name: 'successCallback',
1100 type: AV.Types.FUNCTION,
1105 name: 'errorCallback',
1106 type: AV.Types.FUNCTION,
1116 var callback = function(result) {
1117 if (native.isFailure(result)) {
1118 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
1120 native.callIfPossible(args.successCallback);
1124 var result = native.call('BluetoothServiceHandlerUnregister', callArgs, callback);
1125 if (native.isFailure(result)) {
1126 throw native.getErrorObject(result);
1129 _bluetoothServiceListeners.removeListener(this.uuid);
1132 // class BluetoothHealthApplication ///////////////////////////
1133 function BluetoothHealthApplicationListeners() {
1135 this.appCallback = function(data) {
1137 var app = that.apps[event.id];
1140 var callback = app[event.event];
1141 if (T.isFunction(callback)) {
1143 switch (event.event) {
1145 param = new BluetoothHealthChannel(native.getResultObject(event));
1149 privUtils_.log('Unknown event: ' + event.event);
1155 privUtils_.log('Received event for an unknown application: ' + event.id);
1160 BluetoothHealthApplicationListeners.prototype.apps = {};
1162 BluetoothHealthApplicationListeners.prototype.addListener = function(app) {
1163 if (T.isEmptyObject(this.apps)) {
1164 native.addListener('BLUETOOTH_HEALTH_APPLICATION_CHANGED', this.appCallback);
1167 this.apps[app._id] = app;
1170 BluetoothHealthApplicationListeners.prototype.removeListener = function(id) {
1171 delete this.apps[id];
1173 if (T.isEmptyObject(this.apps)) {
1174 native.removeListener('BLUETOOTH_HEALTH_APPLICATION_CHANGED', this.appCallback);
1178 var _bluetoothHealthApplicationListeners = new BluetoothHealthApplicationListeners();
1180 var BluetoothHealthApplication = function(data) {
1181 Object.defineProperties(this, {
1182 dataType: { value: data.dataType, writable: false, enumerable: true },
1183 name: { value: data.name, writable: false, enumerable: true },
1184 onconnect: { value: null, writable: true, enumerable: true },
1185 _id: { value: data._id, writable: false, enumerable: false }
1188 _bluetoothHealthApplicationListeners.addListener(this);
1191 BluetoothHealthApplication.prototype.unregister = function() {
1192 privUtils_.log('Entered BluetoothHealthApplication.unregister()');
1193 privUtils_.printDeprecationWarningFor('BluetoothHealthApplication');
1194 var args = AV.validateArgs(arguments, [
1196 name: 'successCallback',
1197 type: AV.Types.FUNCTION,
1202 name: 'errorCallback',
1203 type: AV.Types.FUNCTION,
1209 var callArgs = { id: this._id };
1211 var callback = function(result) {
1212 if (native.isFailure(result)) {
1213 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
1215 native.callIfPossible(args.successCallback);
1219 var result = native.call('BluetoothHealthApplicationUnregister', callArgs, callback);
1220 if (native.isFailure(result)) {
1221 throw native.getErrorObject(result);
1224 _bluetoothHealthApplicationListeners.removeListener(this._id);
1227 // class BluetoothProfileHandler ///////////////////////////
1228 var _BluetoothProfileType = {
1232 var BluetoothProfileHandler = function(data) {
1234 var profileType = data.profileType;
1235 function profileTypeGetter() {
1236 privUtils_.printDeprecationWarningFor('profileType');
1239 Object.defineProperties(this, {
1240 profileType: { enumerable: true, set: function() {}, get: profileTypeGetter }
1245 // class BluetoothHealthProfileHandler ///////////////////////////
1246 var BluetoothHealthProfileHandler = function(data) {
1247 BluetoothProfileHandler.call(this, data);
1250 BluetoothHealthProfileHandler.prototype = new BluetoothProfileHandler();
1252 BluetoothHealthProfileHandler.prototype.constructor = BluetoothProfileHandler;
1254 BluetoothHealthProfileHandler.prototype.registerSinkApplication = function() {
1255 privUtils_.log('Entered BluetoothHealthProfileHandler.registerSinkApplication()');
1256 privUtils_.printDeprecationWarningFor('BluetoothHealthProfileHandler');
1258 var args = AV.validateArgs(arguments, [
1261 type: AV.Types.LONG // there's no short type
1265 type: AV.Types.STRING
1268 name: 'successCallback',
1269 type: AV.Types.FUNCTION
1272 name: 'errorCallback',
1273 type: AV.Types.FUNCTION,
1280 dataType: args.dataType,
1284 var callback = function(result) {
1285 if (native.isFailure(result)) {
1286 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
1288 args.successCallback(
1289 new BluetoothHealthApplication(native.getResultObject(result))
1294 var result = native.call(
1295 'BluetoothHealthProfileHandlerRegisterSinkApp',
1299 if (native.isFailure(result)) {
1300 throw native.getErrorObject(result);
1304 BluetoothHealthProfileHandler.prototype.connectToSource = function() {
1305 privUtils_.log('Entered BluetoothHealthProfileHandler.connectToSource()');
1306 privUtils_.printDeprecationWarningFor('BluetoothHealthProfileHandler');
1308 var args = AV.validateArgs(arguments, [
1311 type: AV.Types.PLATFORM_OBJECT,
1312 values: BluetoothDevice
1315 name: 'application',
1316 type: AV.Types.PLATFORM_OBJECT,
1317 values: BluetoothHealthApplication
1320 name: 'successCallback',
1321 type: AV.Types.FUNCTION
1324 name: 'errorCallback',
1325 type: AV.Types.FUNCTION,
1332 address: args.peer.address,
1333 appId: args.application._id
1336 var callback = function(result) {
1337 if (native.isFailure(result)) {
1338 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
1340 var channel = native.getResultObject(result);
1341 channel.peer = args.peer;
1342 channel.appId = args.application._id;
1343 args.successCallback(new BluetoothHealthChannel(channel));
1347 var result = native.call(
1348 'BluetoothHealthProfileHandlerConnectToSource',
1352 if (native.isFailure(result)) {
1353 throw native.getErrorObject(result);
1357 // class BluetoothHealthChannel ///////////////////////////
1358 var BluetoothHealthChannel = function(data) {
1359 Object.defineProperties(this, {
1360 peer: { value: data.peer, writable: false, enumerable: true },
1361 channelType: { value: data.channelType, writable: false, enumerable: true },
1363 value: _bluetoothHealthApplicationListeners.apps[data.appId],
1368 value: data.isConnected,
1373 _id: { value: data._id, writable: false, enumerable: false }
1377 BluetoothHealthChannel.prototype.close = function() {
1378 privUtils_.log('Entered BluetoothHealthChannel.close()');
1379 privUtils_.printDeprecationWarningFor('BluetoothHealthChannel');
1381 if (this.isConnected) {
1384 address: this.peer.address
1387 var result = native.callSync('BluetoothHealthChannelClose', callArgs);
1389 if (native.isFailure(result)) {
1390 throw native.getErrorObject(result);
1393 Object.defineProperty(this, 'isConnected', { value: false });
1397 BluetoothHealthChannel.prototype.sendData = function() {
1398 privUtils_.log('Entered BluetoothHealthChannel.sendData()');
1399 privUtils_.printDeprecationWarningFor('BluetoothHealthChannel');
1401 var args = AV.validateArgs(arguments, [
1404 type: AV.Types.ARRAY,
1405 values: AV.Types.BYTE
1414 var result = native.callSync('BluetoothHealthChannelSendData', callArgs);
1416 if (native.isFailure(result)) {
1417 throw native.getErrorObject(result);
1419 return native.getResultObject(result);
1423 var _healthListeners = {};
1425 function _BluetoothHealthChannelChangeCallback(event) {
1427 var callback = _healthListeners[e.id];
1439 privUtils_.log('Unknown mode: ' + e.event);
1443 if (callback[e.event]) {
1444 callback[e.event](d);
1448 var BluetoothHealthChannel_setListener = function() {
1449 privUtils_.log('Entered BluetoothHealthChannel.setListener()');
1450 privUtils_.printDeprecationWarningFor('BluetoothHealthChannel');
1451 privUtils_.checkPrivilegeAccess4Ver(
1453 Privilege.BLUETOOTH,
1454 Privilege.BLUETOOTH_HEALTH
1456 var args = AV.validateArgs(arguments, [
1458 name: 'changeCallback',
1459 type: AV.Types.LISTENER,
1460 values: ['onmessage', 'onclose']
1464 if (T.isEmptyObject(_healthListeners)) {
1466 'BluetoothHealthChannelChangeCallback',
1467 _BluetoothHealthChannelChangeCallback
1470 _healthListeners[this._id] = args.changeCallback;
1473 BluetoothHealthChannel.prototype.setListener = function() {
1474 BluetoothHealthChannel_setListener.apply(this, arguments);
1477 var BluetoothHealthChannel_unsetListener = function() {
1478 privUtils_.log('Entered BluetoothHealthChannel.unsetListener ()');
1479 privUtils_.printDeprecationWarningFor('BluetoothHealthChannel');
1480 if (T.isEmptyObject(_healthListeners)) {
1481 privUtils_.checkPrivilegeAccess4Ver(
1483 Privilege.BLUETOOTH,
1484 Privilege.BLUETOOTH_HEALTH
1488 delete _healthListeners[this._id];
1490 if (T.isEmptyObject(_healthListeners)) {
1491 native.removeListener(
1492 'BluetoothHealthChannelChangeCallback',
1493 _BluetoothHealthChannelChangeCallback
1498 BluetoothHealthChannel.prototype.unsetListener = function() {
1499 privUtils_.printDeprecationWarningFor('BluetoothHealthChannel');
1500 BluetoothHealthChannel_unsetListener.apply(this, arguments);
1504 * Creates a manager for specified listener event.
1506 * @param {string} name - name of the listener this manager handles
1507 * @param {function} callback - function to be invoked when event specified by the name
1509 * This function should return false if the callback
1510 * doesn't want to handle the event anymore, true otherwise.
1511 * This function should have following signature:
1512 * bool callback(event, successCallback, errorCallback);
1514 * @return {object} object which allows to add or remove callbacks for specified listener
1516 function _singleListenerBuilder(name, callback) {
1517 var listenerName = name;
1518 var successCallback;
1520 var callbackFunction = callback;
1521 var listenerRegistered = false;
1523 function innerCallback(event) {
1524 if (!callbackFunction(event, successCallback, errorCallback)) {
1529 function addListener(s, e) {
1530 successCallback = s;
1533 if (!listenerRegistered) {
1534 native.addListener(listenerName, innerCallback);
1535 listenerRegistered = true;
1539 function removeListener() {
1540 if (listenerRegistered) {
1541 native.removeListener(listenerName, innerCallback);
1542 listenerRegistered = false;
1545 successCallback = undefined;
1546 errorCallback = undefined;
1550 addListener: addListener,
1551 removeListener: removeListener
1555 var _bleScanListener = _singleListenerBuilder('BluetoothLEScanCallback', function(
1563 switch (event.action) {
1565 d = new BluetoothLEDevice(event.data);
1569 if (errorCallback) {
1570 errorCallback(native.getErrorObject(event));
1575 privUtils_.log('Unknown mode: ' + event.action);
1578 if (successCallback) {
1585 var _bleAdvertiseListener = _singleListenerBuilder(
1586 'BluetoothLEAdvertiseCallback',
1587 function(event, successCallback, errorCallback) {
1591 switch (event.action) {
1593 if (successCallback) {
1594 successCallback(native.getResultObject(event));
1595 if (native.getResultObject(event) == 'STOPPED') {
1596 _bleAdvertiseListener.removeListener();
1602 if (errorCallback) {
1603 errorCallback(native.getErrorObject(event));
1608 privUtils_.log('Unknown mode: ' + event.action);
1614 //class BluetoothLEAdapter ///////////////////////////
1615 var BluetoothLEAdapter = function() {};
1617 BluetoothLEAdapter.prototype.startScan = function() {
1618 privUtils_.log('Entered BluetoothLEAdapter.startScan()');
1619 var args = AV.validateArgs(arguments, [
1621 name: 'successCallback',
1622 type: AV.Types.FUNCTION
1625 name: 'errorCallback',
1626 type: AV.Types.FUNCTION,
1632 var result = native.callSync('BluetoothLEAdapterStartScan', {});
1633 if (native.isFailure(result)) {
1634 throw native.getErrorObject(result);
1637 _bleScanListener.addListener(args.successCallback, args.errorCallback);
1640 BluetoothLEAdapter.prototype.stopScan = function() {
1641 privUtils_.log('Entered BluetoothLEAdapter.stopScan()');
1643 _bleScanListener.removeListener();
1645 var result = native.callSync('BluetoothLEAdapterStopScan', {});
1646 if (native.isFailure(result)) {
1647 throw native.getErrorObject(result);
1651 BluetoothLEAdapter.prototype.isScanning = function() {
1652 privUtils_.log('Entered BluetoothLEAdapter.isScanning()');
1654 var result = native.callSync('BluetoothLEAdapterIsScanning', {});
1655 if (native.isFailure(result)) {
1656 throw native.getErrorObject(result);
1658 return native.getResultObject(result);
1661 var _BluetoothAdvertisePacketType = {
1662 ADVERTISE: 'ADVERTISE',
1663 SCAN_RESPONSE: 'SCAN_RESPONSE'
1666 var _BluetoothAdvertisingMode = {
1667 BALANCED: 'BALANCED',
1668 LOW_LATENCY: 'LOW_LATENCY',
1669 LOW_ENERGY: 'LOW_ENERGY'
1672 BluetoothLEAdapter.prototype.startAdvertise = function() {
1673 privUtils_.log('Entered BluetoothLEAdapter.startAdvertise()');
1674 var args = AV.validateArgs(arguments, [
1676 name: 'advertiseData',
1677 type: AV.Types.PLATFORM_OBJECT,
1678 values: tizen.BluetoothLEAdvertiseData
1682 type: AV.Types.ENUM,
1683 values: T.getValues(_BluetoothAdvertisePacketType)
1686 name: 'successCallback',
1687 type: AV.Types.FUNCTION
1690 name: 'errorCallback',
1691 type: AV.Types.FUNCTION,
1697 type: AV.Types.ENUM,
1698 values: T.getValues(_BluetoothAdvertisingMode),
1703 name: 'connectable',
1704 type: AV.Types.BOOLEAN,
1711 advertiseData: args.advertiseData,
1712 packetType: args.packetType,
1713 mode: T.isNullOrUndefined(args.mode)
1714 ? _BluetoothAdvertisingMode.BALANCED
1716 connectable: T.isNullOrUndefined(args.connectable) ? true : args.connectable
1719 var result = native.callSync('BluetoothLEAdapterStartAdvertise', callArgs);
1721 if (native.isFailure(result)) {
1722 throw native.getErrorObject(result);
1725 _bleAdvertiseListener.addListener(args.successCallback, args.errorCallback);
1728 BluetoothLEAdapter.prototype.stopAdvertise = function() {
1729 privUtils_.log('Entered BluetoothLEAdapter.stopAdvertise()');
1731 var result = native.callSync('BluetoothLEAdapterStopAdvertise', {});
1733 if (native.isFailure(result)) {
1734 throw native.getErrorObject(result);
1738 BluetoothLEAdapter.prototype.addConnectStateChangeListener = function() {
1739 privUtils_.log('Entered BluetoothLEAdapter.addClientConnectStateChaneListener()');
1740 var args = AV.validateArgs(arguments, [
1743 type: AV.Types.LISTENER,
1744 values: ['onconnected', 'ondisconnected']
1748 var func = function(event) {
1749 if (args.listener[event.action]) {
1750 args.listener[event.action](new BluetoothLEDevice(event.address));
1754 return _bleConnectChangeListener.addListener(func);
1757 BluetoothLEAdapter.prototype.removeConnectStateChangeListener = function() {
1758 privUtils_.log('Entered BluetoothLEAdapter.removeConnectStateChangeListener()');
1760 var args = AV.validateArgs(arguments, [
1767 _bleConnectChangeListener.removeListener(args.watchID);
1770 //class BluetoothGATTService ///////////////////////////
1771 var BluetoothGATTService = function(data, address) {
1772 var handle_ = data.handle;
1773 var uuid_ = data.uuid;
1774 var serviceUuid_ = data.serviceUuid;
1775 //address_ is needed to control if device is still connected
1776 var address_ = address || data.address;
1778 function servicesGetter() {
1780 var result = native.callSync('BluetoothGATTClientServiceGetServices', {
1784 if (native.isSuccess(result)) {
1785 var resultObject = native.getResultObject(result);
1786 resultObject.forEach(function(s) {
1787 services.push(new BluetoothGATTService(s, address_));
1792 function characteristicsGetter() {
1793 var characteristics = [];
1794 var result = native.callSync('BluetoothGATTClientServiceGetCharacteristics', {
1799 if (native.isSuccess(result)) {
1800 var resultObject = native.getResultObject(result);
1801 resultObject.forEach(function(c) {
1802 if (!T.isNullOrUndefined(c)) {
1803 characteristics.push(new BluetoothGATTCharacteristic(c, address_));
1807 return characteristics;
1811 * If this function is called as a constructor of BluetoothGATTServerService's
1812 * base class, some properties have to be left configurable, to enable redefinition.
1813 * Otherwise, if this function is called to create BluetoothGATTService,
1814 * they are left non-configurable.
1816 * If BluetoothGATTService will be a base for any other class in the future,
1817 * the line below may have to be updated to take into account the new class.
1819 var isConfigurable = this instanceof BluetoothGATTServerService;
1821 Object.defineProperties(this, {
1822 uuid: { value: uuid_, writable: false, enumerable: true },
1823 serviceUuid: { value: serviceUuid_, writable: false, enumerable: true },
1826 configurable: isConfigurable,
1832 configurable: isConfigurable,
1834 get: characteristicsGetter
1839 var CurrentGATTServerEntityId = 0;
1840 function NextGattServerEntityID() {
1841 return ++CurrentGATTServerEntityId;
1844 function IsUuidValid(uuid) {
1846 BluetoothManager_UUIDIsValid16Bit(uuid) ||
1847 BluetoothManager_UUIDIsValid32Bit(uuid) ||
1848 BluetoothManager_UUIDIsValid128Bit(uuid)
1852 var ValidateBluetoothGATTServerServiceInit = function(initData) {
1853 initData = AV.validateArgs(
1855 initData['serviceUuid'],
1856 initData['isPrimary'] || true,
1857 initData['includedServices'] || [],
1858 initData['characteristics'] || []
1862 name: 'serviceUuid',
1863 type: AV.Types.STRING,
1864 validator: IsUuidValid
1868 type: AV.Types.BOOLEAN
1871 name: 'includedServices',
1872 type: AV.Types.ARRAY
1875 name: 'characteristics',
1876 type: AV.Types.ARRAY
1881 // "uuid" field is used to construct BluetoothGATTService, but it's not a part
1882 // of BluetoothGATTServerServiceInit dictionary.
1883 // In case of BluetoothGATTServerServices, its value is always the same as
1885 initData.uuid = initData.serviceUuid;
1889 //class BluetoothGATTServerService ///////////////////////////
1890 var BluetoothGATTServerService = function(data) {
1891 data = ValidateBluetoothGATTServerServiceInit(data);
1893 BluetoothGATTService.call(this, data, null);
1895 var services_ = data.includedServices.map(function(serviceData) {
1896 return new BluetoothGATTServerService(serviceData, null);
1898 var characteristics_ = data.characteristics.map(function(characteristicData) {
1899 return new BluetoothGATTServerCharacteristic(characteristicData, null);
1902 Object.defineProperties(this, {
1903 isPrimary: { value: data.isPrimary, writable: false, enumerable: true },
1907 return services_.slice();
1914 return characteristics_.slice();
1918 // This property is "private" and meant not to be used by users
1920 // It has to be enumerable, to be serialized with JSON.stringify()
1922 value: NextGattServerEntityID()
1927 BluetoothGATTServerService.prototype = Object.create(BluetoothGATTService.prototype);
1929 Object.defineProperty(BluetoothGATTServerService.prototype, 'constructor', {
1930 value: BluetoothGATTServerService,
1935 function _getIncludedServicesAndItsComponentsIdsRecursively(service) {
1938 for (var serviceIndex = 0; serviceIndex < service.services.length; ++serviceIndex) {
1939 ids.push(service.services[serviceIndex]._id);
1941 _getIncludedServicesAndItsComponentsIdsRecursively(
1942 service.services[serviceIndex]
1948 var characteristicIndex = 0;
1949 characteristicIndex < service.characteristics.length;
1950 ++characteristicIndex
1952 ids.push(service.characteristics[characteristicIndex]._id);
1955 var descriptorIndex = 0;
1957 service.characteristics[characteristicIndex].descriptors.length;
1961 service.characteristics[characteristicIndex].descriptors[descriptorIndex]
1970 var BluetoothGATTServer_valid_unregisterService_errors = [
1971 'InvalidStateError',
1974 var BluetoothGATTServer_valid_unregisterService_exceptions = [
1975 'TypeMismatchError',
1979 BluetoothGATTServerService.prototype.unregister = function() {
1980 var args = AV.validateArgs(arguments, [
1982 name: 'successCallback',
1983 type: AV.Types.FUNCTION,
1988 name: 'errorCallback',
1989 type: AV.Types.FUNCTION,
1995 var serviceIndex = _BluetoothGATTServerServices.findIndex(
1997 return service._id === this._id;
2001 if (serviceIndex === -1) {
2002 throw new WebAPIException(
2004 'The service is not registered in the local GATT server or is included in another service'
2008 function removeFromJSArrayAndCallSuccessCb() {
2009 _BluetoothGATTServerServices.splice(serviceIndex, 1);
2010 native.callIfPossible(args.successCallback);
2013 if (!_BluetoothGATTServerServicesRegisteredInNativeLayer[this._id]) {
2014 removeFromJSArrayAndCallSuccessCb();
2018 var callback = function(result) {
2019 if (native.isFailure(result)) {
2020 native.callIfPossible(
2022 native.getErrorObjectAndValidate(
2024 BluetoothGATTServer_valid_unregisterService_errors,
2029 delete _BluetoothGATTServerServicesRegisteredInNativeLayer[this._id];
2030 removeFromJSArrayAndCallSuccessCb();
2036 idsToRemoveFromNativeLayer: _getIncludedServicesAndItsComponentsIdsRecursively(
2040 var result = native.call('BluetoothGATTServerUnregisterService', callArgs, callback);
2042 if (native.isFailure(result)) {
2043 throw native.getErrorObjectAndValidate(
2045 BluetoothGATTServer_valid_unregisterService_errors,
2051 function _setReadWriteValueRequestCallbacksIfPresent(
2053 readValueRequestCallback,
2054 readValueSendResponseSuccessCallback,
2055 readValueSendResponseErrorCallback,
2056 writeValueRequestCallback,
2057 writeValueSendResponseSuccessCallback,
2058 writeValueSendResponseErrorCallback,
2063 object instanceof BluetoothGATTServerCharacteristic ||
2064 object instanceof BluetoothGATTServerDescriptor
2066 if (readValueRequestCallback) {
2067 object.setReadValueRequestCallback(
2068 readValueRequestCallback,
2071 readValueSendResponseSuccessCallback,
2072 readValueSendResponseErrorCallback
2075 if (writeValueRequestCallback) {
2076 object.setWriteValueRequestCallback(
2077 writeValueRequestCallback,
2080 writeValueSendResponseSuccessCallback,
2081 writeValueSendResponseErrorCallback
2087 function _countCallbackToRegisterInService(service) {
2089 for (var serviceIndex = 0; serviceIndex < service.services.length; ++serviceIndex) {
2090 count = count + _countCallbackToRegisterInService(service.services[serviceIndex]);
2094 var characteristicIndex = 0;
2095 characteristicIndex < service.characteristics.length;
2096 ++characteristicIndex
2098 var characteristic = service.characteristics[characteristicIndex];
2099 if (characteristic['_readValueRequestCallback']) {
2102 if (characteristic['_writeValueRequestCallback']) {
2106 var descriptorIndex = 0;
2107 descriptorIndex < characteristic.descriptors.length;
2110 var descriptor = characteristic.descriptors[descriptorIndex];
2111 if (descriptor['_readValueRequestCallback']) {
2114 if (descriptor['_writeValueRequestCallback']) {
2122 function _registerReadWriteValueRequestCallbacksInGATTServiceRecursively(
2126 for (var serviceIndex = 0; serviceIndex < service.services.length; ++serviceIndex) {
2127 _registerReadWriteValueRequestCallbacksInGATTServiceRecursively(
2128 service.services[serviceIndex],
2134 var characteristicIndex = 0;
2135 characteristicIndex < service.characteristics.length;
2136 ++characteristicIndex
2138 var characteristic = service.characteristics[characteristicIndex];
2139 // Callbacks for characteristics
2140 _setReadWriteValueRequestCallbacksIfPresent(
2142 characteristic['_readValueRequestCallback'],
2143 characteristic['_readValueSendResponseSuccessCallback'],
2144 characteristic['_readValueSendResponseErrorCallback'],
2145 characteristic['_writeValueRequestCallback'],
2146 characteristic['_writeValueSendResponseSuccessCallback'],
2147 characteristic['_writeValueSendResponseErrorCallback'],
2148 callbacksAggregator.successCallback,
2149 callbacksAggregator.errorCallback
2152 var descriptorIndex = 0;
2153 descriptorIndex < characteristic.descriptors.length;
2156 // Callbacks for descriptors
2157 var descriptor = characteristic.descriptors[descriptorIndex];
2158 _setReadWriteValueRequestCallbacksIfPresent(
2160 descriptor['_readValueRequestCallback'],
2161 descriptor['_readValueSendResponseSuccessCallback'],
2162 descriptor['_readValueSendResponseErrorCallback'],
2163 descriptor['_writeValueRequestCallback'],
2164 descriptor['_writeValueSendResponseSuccessCallback'],
2165 descriptor['_writeValueSendResponseErrorCallback'],
2166 callbacksAggregator.successCallback,
2167 callbacksAggregator.errorCallback
2173 function _registerReadWriteValueRequestCallbacksInGATTService(
2178 var count = _countCallbackToRegisterInService(service);
2185 var callbacksAggregator = new ResultCallbacksAggregator(
2187 function onAllSucceeded() {
2190 function onFailure(error) {
2191 errorCallback(error);
2195 _registerReadWriteValueRequestCallbacksInGATTServiceRecursively(
2201 var numberArrayToByteArray = function(array) {
2204 array.forEach(function(b) {
2205 d.push(Converter.toOctet(b));
2210 //class BluetoothGATTCharacteristic ///////////////////////////
2211 var BluetoothGATTCharacteristic = function(data, address) {
2212 if (!T.isObject(data)) {
2215 var address_ = address;
2216 var handle_ = data.handle;
2217 var descriptors_ = data.descriptors.map(function(descriptor_data) {
2218 return new BluetoothGATTDescriptor(descriptor_data, address_);
2220 var isBroadcast_ = data.isBroadcast;
2221 var hasExtendedProperties_ = data.hasExtendedProperties;
2222 var isNotify_ = data.isNotify;
2223 var isIndication_ = data.isIndication;
2224 var isReadable_ = data.isReadable;
2225 var isSignedWrite_ = data.isSignedWrite;
2226 var isWritable_ = data.isWritable;
2227 var isWriteNoResponse_ = data.isWriteNoResponse;
2228 var uuid_ = data.uuid;
2231 * If this function is called as a constructor of BluetoothGATTServerCharacteristic's
2232 * base class, some properties have to be left configurable, to enable redefinition.
2233 * Otherwise, if this function is called to create BluetoothGATTCharacteristic,
2234 * they are left non-configurable.
2236 * If BluetoothGATTCharacteristic will be a base for any other class in the future,
2237 * the line below may have to be updated to take into account the new class.
2239 var isConfigurable = this instanceof BluetoothGATTServerCharacteristic;
2241 Object.defineProperties(this, {
2244 configurable: isConfigurable,
2246 return descriptors_.slice();
2253 return isBroadcast_;
2257 hasExtendedProperties: {
2260 return hasExtendedProperties_;
2274 return isIndication_;
2288 return isSignedWrite_;
2299 isWriteNoResponse: {
2302 return isWriteNoResponse_;
2315 this.readValue = function() {
2316 privUtils_.log('Entered BluetoothGATTCharacteristic.readValue()');
2317 var args = AV.validateArgs(arguments, [
2319 name: 'successCallback',
2320 type: AV.Types.FUNCTION
2323 name: 'errorCallback',
2324 type: AV.Types.FUNCTION,
2330 var callback = function(result) {
2331 if (native.isFailure(result)) {
2332 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
2334 var d = numberArrayToByteArray(native.getResultObject(result));
2335 args.successCallback(d);
2339 var callArgs = { handle: handle_, address: address_ };
2341 var result = native.call(
2342 'BluetoothGATTClientServiceReadValue',
2347 if (native.isFailure(result)) {
2348 throw native.getErrorObject(result);
2352 this.writeValue = function(value, successCallback, errorCallback) {
2353 privUtils_.log('Entered BluetoothGATTCharacteristic.writeValue()');
2354 var args = AV.validateArgs(Array.prototype.slice.call(arguments, 1), [
2356 name: 'successCallback',
2357 type: AV.Types.FUNCTION,
2362 name: 'errorCallback',
2363 type: AV.Types.FUNCTION,
2369 var callback = function(result) {
2370 if (native.isFailure(result)) {
2371 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
2373 native.callIfPossible(args.successCallback);
2379 value: BluetoothManager_toByteArray(value),
2383 var result = native.call(
2384 'BluetoothGATTClientServiceWriteValue',
2389 if (native.isFailure(result)) {
2390 throw native.getErrorObject(result);
2394 var addValueChangeListener = function() {
2395 privUtils_.log('Entered BluetoothGATTCharacteristic.addValueChangeListener()');
2396 privUtils_.checkPrivilegeAccess4Ver(
2398 Privilege.BLUETOOTH,
2399 Privilege.BLUETOOTH_ADMIN
2401 var args = AV.validateArgs(arguments, [
2404 type: AV.Types.FUNCTION
2408 var callArgs = { handle: handle_, address: address_ };
2410 var callback = function(event) {
2411 if (event.handle === handle_) {
2412 args.callback(numberArrayToByteArray(native.getResultObject(event)));
2416 return _bluetoothGATTCharacteristicListener.addListener(callback, callArgs);
2419 this.addValueChangeListener = function() {
2420 return addValueChangeListener.apply(this, arguments);
2423 this.removeValueChangeListener = function() {
2424 privUtils_.log('Entered BluetoothGATTCharacteristic.removeValueChangeListener()');
2426 var args = AV.validateArgs(arguments, [
2433 var callArgs = { handle: handle_, address: address_ };
2435 return _bluetoothGATTCharacteristicListener.removeListener(
2442 var ValidateBluetoothGATTServerCharacteristicInit = function(initData) {
2443 return AV.validateArgs(
2446 initData['descriptors'] || [],
2447 initData['isBroadcast'] || false,
2448 initData['hasExtendedProperties'] || false,
2449 initData['isNotify'] || false,
2450 initData['isIndication'] || false,
2451 initData['isReadable'] || false,
2452 initData['isSignedWrite'] || false,
2453 initData['isWritable'] || false,
2454 initData['isWriteNoResponse'] || false,
2455 initData['readPermission'] || false,
2456 initData['writePermission'] || false,
2457 initData['encryptedReadPermission'] || false,
2458 initData['encryptedWritePermission'] || false,
2459 initData['encryptedSignedReadPermission'] || false,
2460 initData['encryptedSignedWritePermission'] || false,
2461 initData['readValueRequestCallback'] || null,
2462 initData['readValueSendResponseSuccessCallback'] || null,
2463 initData['readValueSendResponseErrorCallback'] || null,
2464 initData['writeValueRequestCallback'] || null,
2465 initData['writeValueSendResponseSuccessCallback'] || null,
2466 initData['writeValueSendResponseErrorCallback'] || null
2471 type: AV.Types.STRING,
2472 validator: IsUuidValid
2475 name: 'descriptors',
2476 type: AV.Types.ARRAY
2479 name: 'isBroadcast',
2480 type: AV.Types.BOOLEAN
2483 name: 'hasExtendedProperties',
2484 type: AV.Types.BOOLEAN
2488 type: AV.Types.BOOLEAN
2491 name: 'isIndication',
2492 type: AV.Types.BOOLEAN
2496 type: AV.Types.BOOLEAN
2499 name: 'isSignedWrite',
2500 type: AV.Types.BOOLEAN
2504 type: AV.Types.BOOLEAN
2507 name: 'isWriteNoResponse',
2508 type: AV.Types.BOOLEAN
2511 name: 'readPermission',
2512 type: AV.Types.BOOLEAN
2515 name: 'writePermission',
2516 type: AV.Types.BOOLEAN
2519 name: 'encryptedReadPermission',
2520 type: AV.Types.BOOLEAN
2523 name: 'encryptedWritePermission',
2524 type: AV.Types.BOOLEAN
2527 name: 'encryptedSignedReadPermission',
2528 type: AV.Types.BOOLEAN
2531 name: 'encryptedSignedWritePermission',
2532 type: AV.Types.BOOLEAN
2535 name: 'readValueRequestCallback',
2536 type: AV.Types.FUNCTION,
2540 name: 'readValueSendResponseSuccessCallback',
2541 type: AV.Types.FUNCTION,
2545 name: 'readValueSendResponseErrorCallback',
2546 type: AV.Types.FUNCTION,
2550 name: 'writeValueRequestCallback',
2551 type: AV.Types.FUNCTION,
2555 name: 'writeValueSendResponseErrorCallback',
2556 type: AV.Types.FUNCTION,
2560 name: 'writeValueSendResponseSuccessCallback',
2561 type: AV.Types.FUNCTION,
2568 //class BluetoothGATTServerCharacteristic ///////////////////////////
2569 var BluetoothGATTServerCharacteristic = function(data) {
2570 data = ValidateBluetoothGATTServerCharacteristicInit(data);
2572 BluetoothGATTCharacteristic.call(this, data, null);
2574 var descriptors_ = data.descriptors.map(function(descriptor_data) {
2575 return new BluetoothGATTServerDescriptor(descriptor_data, null);
2578 Object.defineProperties(this, {
2582 return descriptors_.slice();
2589 return data.readPermission;
2596 return data.writePermission;
2600 encryptedReadPermission: {
2603 return data.encryptedReadPermission;
2607 encryptedWritePermission: {
2610 return data.encryptedWritePermission;
2614 encryptedSignedReadPermission: {
2617 return data.encryptedSignedReadPermission;
2621 encryptedSignedWritePermission: {
2624 return data.encryptedSignedWritePermission;
2628 // This properties are "private" and meant not to be used by users
2629 _readValueRequestCallback: {
2632 return data.readValueRequestCallback;
2636 _readValueSendResponseSuccessCallback: {
2639 return data.readValueSendResponseSuccessCallback;
2643 _readValueSendResponseErrorCallback: {
2646 return data.readValueSendResponseErrorCallback;
2650 _writeValueRequestCallback: {
2653 return data.writeValueRequestCallback;
2657 _writeValueSendResponseSuccessCallback: {
2660 return data.writeValueSendResponseSuccessCallback;
2664 _writeValueSendResponseErrorCallback: {
2667 return data.writeValueSendResponseErrorCallback;
2672 // It has to be enumerable, to be serialized with JSON.stringify()
2674 value: NextGattServerEntityID()
2678 this.readValue = function() {
2679 throw new WebAPIException(
2680 'NotSupportedError',
2681 'This method cannot be called on BluetoothGATTServerCharacteristic'
2685 this.writeValue = function() {
2686 throw new WebAPIException(
2687 'NotSupportedError',
2688 'This method cannot be called on BluetoothGATTServerCharacteristic'
2692 this.addValueChangeListener = function() {
2693 throw new WebAPIException(
2694 'NotSupportedError',
2695 'This method cannot be called on BluetoothGATTServerCharacteristic'
2699 this.removeValueChangeListener = function() {
2700 /* Intended no operation */
2703 this.notifyAboutValueChange = function(
2709 var args = AV.validateArgs(Array.prototype.slice.call(arguments, 1), [
2711 name: 'clientAddress',
2712 type: AV.Types.STRING,
2717 name: 'notificationCB',
2718 type: AV.Types.LISTENER,
2720 'onnotificationsuccess',
2721 'onnotificationfail',
2722 'onnotificationfinish'
2729 type: AV.Types.FUNCTION,
2736 value: BluetoothManager_toByteArray(value),
2737 client: args.clientAddress || null,
2739 notifyId: _BluetoothGATTServerCharacteristicNotifyId++
2742 var callback = function(result) {
2743 if (native.isFailure(result)) {
2744 native.callIfPossible(args.errorCB, native.getErrorObject(result));
2748 var result = native.call(
2749 'BluetoothGATTServerCharacteristicNotifyAboutValueChange',
2754 if (native.isFailure(result)) {
2755 throw native.getErrorObject(result);
2759 'BluetoothGATTServerCharacteristicNotifyCallback_' + callArgs.notifyId,
2760 _BluetoothGATTServerCharacteristicNotifyCallback
2763 _BluetoothGATTServerCharacteristicNotifyListeners[callArgs.notifyId] =
2764 args.notificationCB;
2768 BluetoothGATTServerCharacteristic.prototype = Object.create(
2769 BluetoothGATTCharacteristic.prototype
2772 Object.defineProperty(BluetoothGATTServerCharacteristic.prototype, 'constructor', {
2773 value: BluetoothGATTServerCharacteristic,
2778 tizen.GATTRequestReply = function(statusCode, data) {
2779 AV.isConstructorCall(this, tizen.GATTRequestReply);
2781 var statusCode_ = Converter.toLong(statusCode);
2782 var data_ = T.isNullOrUndefined(data) ? null : BluetoothManager_toByteArray(data);
2784 Object.defineProperties(this, {
2791 statusCode_ = Converter.toLong(v);
2800 data_ = T.isNullOrUndefined(v) ? null : numberArrayToByteArray(v);
2806 function _createReadValueRequestCallback(
2808 sendResponseSuccessCallback,
2809 sendResponseErrorCallback
2811 return _singleListenerBuilder(
2812 'ReadValueRequestCallback_' + _id,
2814 * _singleListenerBuilder requires 2 callbacks, the second of which
2815 * is an error callback.
2816 * Read value request events coming from the native layer
2818 * Hence, we don't use the second callback here.
2820 function(event, readValueRequestCallback, unusedErrorCallback) {
2821 var clientAddress = event.clientAddress;
2822 var offset = event.offset;
2824 if (readValueRequestCallback) {
2825 var requestReply = readValueRequestCallback(clientAddress, offset);
2828 requestId: event.requestId,
2829 requestType: event.requestType,
2831 statusCode: requestReply.statusCode,
2832 data: requestReply.data
2834 var callback = function(result) {
2835 if (native.isFailure(result)) {
2836 native.callIfPossible(
2837 sendResponseErrorCallback,
2838 native.getErrorObject(result)
2841 native.callIfPossible(sendResponseSuccessCallback);
2844 var result = native.call(
2845 'BluetoothGATTServerSendResponse',
2855 function _createWriteValueRequestCallback(
2857 sendResponseSuccessCallback,
2858 sendResponseErrorCallback
2860 return _singleListenerBuilder(
2861 'WriteValueRequestCallback_' + _id,
2863 * _singleListenerBuilder requires 2 callbacks, the second of which
2864 * is an error callback.
2865 * Write value request events coming from the native layer
2867 * Hence, we don't use the second callback here.
2869 function(event, writeValueRequestCallback, unusedErrorCallback) {
2870 var clientAddress = event.clientAddress;
2871 var value = event.value;
2872 var offset = event.offset;
2873 var replyRequired = event.replyRequired;
2875 if (writeValueRequestCallback) {
2876 var requestReply = writeValueRequestCallback(
2878 BluetoothManager_toByteArray(value),
2884 requestId: event.requestId,
2885 requestType: event.requestType,
2886 value: null, // Responses to write requests don't contain value
2888 statusCode: requestReply.statusCode,
2889 data: requestReply.data
2891 var callback = function(result) {
2892 if (native.isFailure(result)) {
2893 native.callIfPossible(
2894 sendResponseErrorCallback,
2895 native.getErrorObject(result)
2898 native.callIfPossible(sendResponseSuccessCallback);
2901 var result = native.call(
2902 'BluetoothGATTServerSendResponse',
2912 var _BluetoothGATTServerReadWriteValueRequestCallbacks = {};
2914 var _setReadValueRequestCallbackCommon = function() {
2915 var args = AV.validateArgs(arguments, [
2917 name: 'readValueRequestCallback',
2918 type: AV.Types.FUNCTION
2921 name: 'successCallback',
2922 type: AV.Types.FUNCTION,
2927 name: 'errorCallback',
2928 type: AV.Types.FUNCTION,
2933 name: 'sendResponseSuccessCallback',
2934 type: AV.Types.FUNCTION,
2939 name: 'sendResponseErrorCallback',
2940 type: AV.Types.FUNCTION,
2946 var entityId = this._id;
2948 var callback = function(result) {
2949 if (native.isFailure(result)) {
2950 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
2952 var readValueRequestCallback = _createReadValueRequestCallback(
2954 args.sendResponseSuccessCallback,
2955 args.sendResponseErrorCallback
2957 readValueRequestCallback.addListener(
2958 args.readValueRequestCallback,
2959 function unusedErrorCallback() {
2960 /* Intentionally no operation */
2963 _BluetoothGATTServerReadWriteValueRequestCallbacks[
2964 'ReadValueCallback' + entityId
2965 ] = readValueRequestCallback;
2966 native.callIfPossible(args.successCallback, native.getErrorObject(result));
2970 var callArgs = { _id: this._id };
2971 var result = native.call(
2972 'BluetoothGATTServerSetReadValueRequestCallback',
2977 if (native.isFailure(result)) {
2978 throw native.getErrorObject(result);
2982 var _setWriteValueRequestCallbackCommon = function() {
2983 var args = AV.validateArgs(arguments, [
2985 name: 'writeValueRequestCallback',
2986 type: AV.Types.FUNCTION
2989 name: 'successCallback',
2990 type: AV.Types.FUNCTION,
2995 name: 'errorCallback',
2996 type: AV.Types.FUNCTION,
3001 name: 'sendResponseSuccessCallback',
3002 type: AV.Types.FUNCTION,
3007 name: 'sendResponseErrorCallback',
3008 type: AV.Types.FUNCTION,
3014 var entityId = this._id;
3016 var callback = function(result) {
3017 if (native.isFailure(result)) {
3018 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
3020 var writeValueRequestCallback = _createWriteValueRequestCallback(
3022 args.sendResponseSuccessCallback,
3023 args.sendResponseErrorCallback
3025 writeValueRequestCallback.addListener(
3026 args.writeValueRequestCallback,
3027 function unusedErrorCallback() {
3028 /* Intentionally no operation */
3031 _BluetoothGATTServerReadWriteValueRequestCallbacks[
3032 'WriteValueCallback' + entityId
3033 ] = writeValueRequestCallback;
3034 native.callIfPossible(args.successCallback, native.getErrorObject(result));
3038 var callArgs = { _id: this._id };
3039 var result = native.call(
3040 'BluetoothGATTServerSetWriteValueRequestCallback',
3045 if (native.isFailure(result)) {
3046 throw native.getErrorObject(result);
3050 BluetoothGATTServerCharacteristic.prototype.setReadValueRequestCallback = _setReadValueRequestCallbackCommon;
3051 BluetoothGATTServerCharacteristic.prototype.setWriteValueRequestCallback = _setWriteValueRequestCallbackCommon;
3053 var _BluetoothGATTServerCharacteristicNotifyId = 0;
3054 var _BluetoothGATTServerCharacteristicNotifyListeners = {};
3055 var _BluetoothGATTServerCharacteristicNotifyCallback = function(event) {
3056 privUtils_.log('Got notification about characteristic\'s value change');
3058 T.isNullOrUndefined(
3059 _BluetoothGATTServerCharacteristicNotifyListeners[event.notifyId]
3062 privUtils_.log('Notification callback is not set, skipping');
3066 var callback = _BluetoothGATTServerCharacteristicNotifyListeners[event.notifyId];
3068 if (event.type === 'onnotificationsuccess') {
3069 native.callIfPossible(callback.onnotificationsuccess, event.clientAddress);
3073 if (event.type === 'onnotificationfail') {
3074 native.callIfPossible(
3075 callback.onnotificationfail,
3076 event.clientAddress,
3077 native.getErrorObject(event)
3082 if (event.type === 'onnotificationfinish') {
3083 native.callIfPossible(callback.onnotificationfinish, event.clientAddress);
3086 native.removeListener(
3087 'BluetoothGATTServerCharacteristicNotifyCallback_' + event.notifyId
3092 * Creates a manager for specified listener event. Manager handles multiple
3093 * registered listeners
3095 * @param {string} name - name of the listener this manager handles
3096 * @param {function} callback - function to be invoked when event specified by the name
3098 * This function should have following signature:
3099 * void callback(listener, event);
3100 * @param {string} addListenerId - optional parameter. If specified, this native
3101 * method will be called synchronously when
3102 * listener is added.
3103 * @param {string} removeListenerId - optional parameter. If specified, this native
3104 * method will be called synchronously when
3105 * listener is removed.
3106 * @param {bool} repeatNativeCall - optional parameter. If specified, the addListenerId
3107 * and removeListenerId methods will be called
3108 * synchronously each time listener is added/removed.
3109 * Otherwise they are going to be called just once: when
3110 * first listener is added and last listener is removed.
3112 * @return {object} object which allows to add or remove callbacks for specified listener
3114 function _multipleListenerBuilder(
3121 var listenerName = name;
3122 var addId = addListenerId;
3123 var removeId = removeListenerId;
3124 var callbackFunction = callback;
3127 var jsListenerRegistered = false;
3128 var nativeListenerRegistered = false;
3129 var repeatNativeListenerCall = repeatNativeCall;
3131 function innerCallback(event) {
3132 for (var watchId in listeners) {
3133 if (listeners.hasOwnProperty(watchId)) {
3134 callbackFunction(listeners[watchId], event);
3139 function addListener(callback, args) {
3142 if (addId && (!nativeListenerRegistered || repeatNativeListenerCall)) {
3143 var result = native.callSync(addId, args || {});
3144 if (native.isFailure(result)) {
3145 throw native.getErrorObject(result);
3147 nativeListenerRegistered = true;
3150 if (!jsListenerRegistered) {
3151 native.addListener(listenerName, innerCallback);
3152 jsListenerRegistered = true;
3155 listeners[id] = callback;
3159 function removeListener(watchId, args) {
3160 if (listeners.hasOwnProperty(watchId)) {
3161 delete listeners[watchId];
3166 ((nativeListenerRegistered && T.isEmptyObject(listeners)) ||
3167 repeatNativeListenerCall)
3169 var result = native.callSync(removeId, args || {});
3170 if (native.isFailure(result)) {
3171 throw native.getErrorObject(result);
3173 nativeListenerRegistered = false;
3176 if (jsListenerRegistered && T.isEmptyObject(listeners)) {
3177 native.removeListener(listenerName, innerCallback);
3178 jsListenerRegistered = false;
3183 addListener: addListener,
3184 removeListener: removeListener
3188 var _bluetoothGATTCharacteristicListener = _multipleListenerBuilder(
3189 'BluetoothGATTCharacteristicValueChangeListener',
3190 function(listener, event) {
3193 'BluetoothGATTClientServiceAddValueChangeListener',
3194 'BluetoothGATTClientServiceRemoveValueChangeListener',
3199 * This object is used by:
3200 * - BluetoothLEDevice.addConnectStateChangeListener()
3201 * - BluetoothLEAdapter.addConnectStateChangeListener()
3203 var _bleConnectChangeListener = _multipleListenerBuilder(
3204 'BluetoothLEConnectChangeCallback',
3205 function(listener, event) {
3208 'BluetoothLEDeviceAddConnectStateChangeListener',
3209 'BluetoothLEDeviceRemoveConnectStateChangeListener'
3212 var _bleAttMtuChangeListener = _multipleListenerBuilder(
3213 'BluetoothLEAttMtuChangeCallback',
3214 function(listener, event) {
3217 'BluetoothLEDeviceAddAttMtuChangeListener',
3218 'BluetoothLEDeviceRemoveAttMtuChangeListener'
3221 //class BluetoothGATTDescriptor ///////////////////////////
3222 var BluetoothGATTDescriptor = function(data, address) {
3223 var handle_ = data.handle;
3224 //address_ is needed to control if device is still connected
3225 var address_ = address;
3226 var uuid_ = data.uuid;
3228 this.readValue = function() {
3229 privUtils_.log('Entered BluetoothGATTDescriptor.readValue()');
3230 var args = AV.validateArgs(arguments, [
3232 name: 'successCallback',
3233 type: AV.Types.FUNCTION
3236 name: 'errorCallback',
3237 type: AV.Types.FUNCTION,
3243 var callback = function(result) {
3244 if (native.isFailure(result)) {
3245 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
3247 var d = numberArrayToByteArray(native.getResultObject(result));
3248 args.successCallback(d);
3252 var callArgs = { handle: handle_, address: address_ };
3254 var result = native.call(
3255 'BluetoothGATTClientServiceReadValue',
3260 if (native.isFailure(result)) {
3261 throw native.getErrorObject(result);
3265 this.writeValue = function(value, successCallback, errorCallback) {
3266 privUtils_.log('Entered BluetoothGATTDescriptor.writeValue()');
3267 var args = AV.validateArgs(Array.prototype.slice.call(arguments, 1), [
3269 name: 'successCallback',
3270 type: AV.Types.FUNCTION,
3275 name: 'errorCallback',
3276 type: AV.Types.FUNCTION,
3282 var callback = function(result) {
3283 if (native.isFailure(result)) {
3284 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
3286 native.callIfPossible(args.successCallback);
3292 value: BluetoothManager_toByteArray(value),
3296 var result = native.call(
3297 'BluetoothGATTClientServiceWriteValue',
3302 if (native.isFailure(result)) {
3303 throw native.getErrorObject(result);
3307 Object.defineProperties(this, {
3318 var ValidateBluetoothGATTServerDescriptorInit = function(initData) {
3319 return AV.validateArgs(
3322 initData['readPermission'] || false,
3323 initData['writePermission'] || false,
3324 initData['encryptedReadPermission'] || false,
3325 initData['encryptedWritePermission'] || false,
3326 initData['encryptedSignedReadPermission'] || false,
3327 initData['encryptedSignedWritePermission'] || false,
3328 initData['readValueRequestCallback'] || null,
3329 initData['readValueSendResponseSuccessCallback'] || null,
3330 initData['readValueSendResponseErrorCallback'] || null,
3331 initData['writeValueRequestCallback'] || null,
3332 initData['writeValueSendResponseSuccessCallback'] || null,
3333 initData['writeValueSendResponseErrorCallback'] || null
3338 type: AV.Types.STRING,
3339 validator: IsUuidValid
3342 name: 'readPermission',
3343 type: AV.Types.BOOLEAN
3346 name: 'writePermission',
3347 type: AV.Types.BOOLEAN
3350 name: 'encryptedReadPermission',
3351 type: AV.Types.BOOLEAN
3354 name: 'encryptedWritePermission',
3355 type: AV.Types.BOOLEAN
3358 name: 'encryptedSignedReadPermission',
3359 type: AV.Types.BOOLEAN
3362 name: 'encryptedSignedWritePermission',
3363 type: AV.Types.BOOLEAN
3366 name: 'readValueRequestCallback',
3367 type: AV.Types.FUNCTION,
3371 name: 'readValueSendResponseSuccessCallback',
3372 type: AV.Types.FUNCTION,
3376 name: 'readValueSendResponseErrorCallback',
3377 type: AV.Types.FUNCTION,
3381 name: 'writeValueRequestCallback',
3382 type: AV.Types.FUNCTION,
3386 name: 'writeValueSendResponseErrorCallback',
3387 type: AV.Types.FUNCTION,
3391 name: 'writeValueSendResponseSuccessCallback',
3392 type: AV.Types.FUNCTION,
3399 var BluetoothGATTServerDescriptor = function(data, address) {
3400 data = ValidateBluetoothGATTServerDescriptorInit(data);
3402 BluetoothGATTDescriptor.call(this, data, null);
3404 Object.defineProperties(this, {
3408 return data.readPermission;
3415 return data.writePermission;
3419 encryptedReadPermission: {
3422 return data.encryptedReadPermission;
3426 encryptedWritePermission: {
3429 return data.encryptedWritePermission;
3433 encryptedSignedReadPermission: {
3436 return data.encryptedSignedReadPermission;
3440 encryptedSignedWritePermission: {
3443 return data.encryptedSignedWritePermission;
3447 // This properties are "private" and meant not to be used by users
3448 _readValueRequestCallback: {
3451 return data.readValueRequestCallback;
3455 _readValueSendResponseSuccessCallback: {
3458 return data.readValueSendResponseSuccessCallback;
3462 _readValueSendResponseErrorCallback: {
3465 return data.readValueSendResponseErrorCallback;
3469 _writeValueRequestCallback: {
3472 return data.writeValueRequestCallback;
3476 _writeValueSendResponseSuccessCallback: {
3479 return data.writeValueSendResponseSuccessCallback;
3483 _writeValueSendResponseErrorCallback: {
3486 return data.writeValueSendResponseErrorCallback;
3491 // It has to be enumerable, to be serialized with JSON.stringify()
3493 value: NextGattServerEntityID()
3497 this.readValue = function() {
3498 throw new WebAPIException(
3499 'NotSupportedError',
3500 'This method cannot be called on BluetoothGATTServerDescriptor'
3504 this.writeValue = function() {
3505 throw new WebAPIException(
3506 'NotSupportedError',
3507 'This method cannot be called on BluetoothGATTServerDescriptor'
3512 BluetoothGATTServerDescriptor.prototype = Object.create(
3513 BluetoothGATTDescriptor.prototype
3516 Object.defineProperty(BluetoothGATTServerDescriptor.prototype, 'constructor', {
3517 value: BluetoothGATTServerDescriptor,
3522 BluetoothGATTServerDescriptor.prototype.setReadValueRequestCallback = _setReadValueRequestCallbackCommon;
3523 BluetoothGATTServerDescriptor.prototype.setWriteValueRequestCallback = _setWriteValueRequestCallbackCommon;
3525 // class BluetoothAdapter ///////////////////////////
3526 var BluetoothAdapter = function() {
3527 function nameGetter() {
3528 var result = native.callSync('BluetoothAdapterGetName', {});
3530 if (native.isFailure(result)) {
3533 return native.getResultObject(result);
3537 function addressGetter() {
3538 var result = native.callSync('BluetoothAdapterGetAddress', {});
3540 if (native.isFailure(result)) {
3543 return native.getResultObject(result);
3547 function poweredGetter() {
3548 var result = native.callSync('BluetoothAdapterGetPowered', {});
3550 if (native.isFailure(result)) {
3553 return native.getResultObject(result);
3557 function visibleGetter() {
3558 var result = native.callSync('BluetoothAdapterGetVisible', {});
3560 if (native.isFailure(result)) {
3563 return native.getResultObject(result);
3567 Object.defineProperties(this, {
3591 BluetoothAdapter.prototype.setName = function() {
3592 privUtils_.log('Entered BluetoothAdapter.setName()');
3593 var args = AV.validateArgs(arguments, [
3596 type: AV.Types.STRING
3599 name: 'successCallback',
3600 type: AV.Types.FUNCTION,
3605 name: 'errorCallback',
3606 type: AV.Types.FUNCTION,
3616 var callback = function(result) {
3617 if (native.isFailure(result)) {
3618 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
3620 native.callIfPossible(args.successCallback);
3624 var result = native.call('BluetoothAdapterSetName', callArgs, callback);
3625 if (native.isFailure(result)) {
3626 throw native.getErrorObject(result);
3630 BluetoothAdapter.prototype.setPowered = function() {
3631 privUtils_.log('Entered BluetoothAdapter.setPowered()');
3632 privUtils_.printDeprecationWarningFor('setPowered()');
3634 'Let the user turn on/off Bluetooth through the Settings application instead.'
3637 var args = AV.validateArgs(arguments, [
3640 type: AV.Types.BOOLEAN
3643 name: 'successCallback',
3644 type: AV.Types.FUNCTION,
3649 name: 'errorCallback',
3650 type: AV.Types.FUNCTION,
3657 powered: args.powered
3660 var callback = function(result) {
3661 if (native.isFailure(result)) {
3662 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
3664 native.callIfPossible(args.successCallback);
3668 var result = native.call('BluetoothAdapterSetPowered', callArgs, callback);
3669 if (native.isFailure(result)) {
3670 throw native.getErrorObject(result);
3674 // This method is deprecated since Tizen 2.3.
3675 BluetoothAdapter.prototype.setVisible = function() {
3676 privUtils_.log('Entered BluetoothAdapter.setVisible()');
3677 privUtils_.printDeprecationWarningFor('setVisible()');
3679 'Let the user change the Bluetooth visibility through the Settings ' +
3680 'application instead.'
3683 var args = AV.validateArgs(arguments, [
3686 type: AV.Types.BOOLEAN
3689 name: 'successCallback',
3690 type: AV.Types.FUNCTION,
3695 name: 'errorCallback',
3696 type: AV.Types.FUNCTION,
3702 type: AV.Types.UNSIGNED_LONG,
3709 visible: args.visible
3712 if (args.visible === true) {
3713 if (T.isNullOrUndefined(args.timeout)) {
3714 callArgs.timeout = 0;
3716 callArgs.timeout = args.timeout > 65535 ? 180 : args.timeout;
3720 var callback = function(result) {
3721 if (native.isFailure(result)) {
3722 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
3724 native.callIfPossible(args.successCallback);
3728 var result = native.call('BluetoothAdapterSetVisible', callArgs, callback);
3729 if (native.isFailure(result)) {
3730 throw native.getErrorObject(result);
3736 function _BluetoothAdapterChangeCallback(event) {
3737 privUtils_.log('_BluetoothAdapterChangeCallback');
3743 case 'onstatechanged':
3747 case 'onnamechanged':
3751 case 'onvisibilitychanged':
3756 privUtils_.log('Unknown mode: ' + e.action);
3760 if (_listener[e.action]) {
3761 _listener[e.action](d);
3765 BluetoothAdapter.prototype.setChangeListener = function() {
3766 privUtils_.log('Entered BluetoothAdapter.setChangeListener()');
3767 var args = AV.validateArgs(arguments, [
3769 name: 'changeCallback',
3770 type: AV.Types.LISTENER,
3771 values: ['onstatechanged', 'onnamechanged', 'onvisibilitychanged']
3775 if (T.isNullOrUndefined(_listener)) {
3777 'BluetoothAdapterChangeCallback',
3778 _BluetoothAdapterChangeCallback
3780 native.callSync('BluetoothAdapterSetChangeListener', {});
3782 _listener = args.changeCallback;
3785 BluetoothAdapter.prototype.unsetChangeListener = function() {
3786 privUtils_.log('Entered BluetoothAdapter.unsetChangeListener()');
3787 if (!T.isNullOrUndefined(_listener)) {
3788 native.removeListener(
3789 'BluetoothAdapterChangeCallback',
3790 _BluetoothAdapterChangeCallback
3792 native.callSync('BluetoothAdapterUnsetChangeListener', {});
3793 _listener = undefined;
3797 var _discoverDevicesSuccessCallback;
3798 var _discoverDevicesErrorCallback;
3800 function _BluetoothDiscoverDevicesSuccessCallback(event) {
3808 case 'ondevicefound':
3809 d = new BluetoothDevice(e.data);
3812 case 'ondevicedisappeared':
3817 var result = e.data;
3819 result.forEach(function(data) {
3820 d.push(new BluetoothDevice(data));
3823 //remove listeners after discovering
3824 native.removeListener(
3825 'BluetoothDiscoverDevicesSuccessCallback',
3826 _BluetoothDiscoverDevicesSuccessCallback
3828 native.removeListener(
3829 'BluetoothDiscoverDevicesErrorCallback',
3830 _BluetoothDiscoverDevicesErrorCallback
3835 privUtils_.log('Unknown mode: ' + e.action);
3839 if (_discoverDevicesSuccessCallback[e.action]) {
3840 _discoverDevicesSuccessCallback[e.action](d);
3844 function _BluetoothDiscoverDevicesErrorCallback(event) {
3846 setTimeout(function() {
3847 native.callIfPossible(_discoverDevicesErrorCallback, native.getErrorObject(e));
3851 BluetoothAdapter.prototype.discoverDevices = function() {
3852 privUtils_.log('Entered BluetoothAdapter.discoverDevices()');
3853 var args = AV.validateArgs(arguments, [
3855 name: 'successCallback',
3856 type: AV.Types.LISTENER,
3857 values: ['onstarted', 'ondevicefound', 'ondevicedisappeared', 'onfinished']
3860 name: 'errorCallback',
3861 type: AV.Types.FUNCTION,
3867 _discoverDevicesSuccessCallback = args.successCallback;
3868 _discoverDevicesErrorCallback = args.errorCallback;
3870 'BluetoothDiscoverDevicesSuccessCallback',
3871 _BluetoothDiscoverDevicesSuccessCallback
3874 'BluetoothDiscoverDevicesErrorCallback',
3875 _BluetoothDiscoverDevicesErrorCallback
3878 var result = native.callSync('BluetoothAdapterDiscoverDevices', {});
3880 if (native.isFailure(result)) {
3881 native.removeListener(
3882 'BluetoothDiscoverDevicesSuccessCallback',
3883 _BluetoothDiscoverDevicesSuccessCallback
3885 native.removeListener(
3886 'BluetoothDiscoverDevicesErrorCallback',
3887 _BluetoothDiscoverDevicesErrorCallback
3889 throw native.getErrorObject(result);
3893 BluetoothAdapter.prototype.stopDiscovery = function() {
3894 privUtils_.log('Entered BluetoothAdapter.stopDiscovery()');
3895 var args = AV.validateArgs(arguments, [
3897 name: 'successCallback',
3898 type: AV.Types.FUNCTION,
3903 name: 'errorCallback',
3904 type: AV.Types.FUNCTION,
3910 var callback = function(result) {
3911 if (native.isFailure(result)) {
3912 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
3914 native.callIfPossible(args.successCallback);
3918 var result = native.call('BluetoothAdapterStopDiscovery', {}, callback);
3919 if (native.isFailure(result)) {
3920 throw native.getErrorObject(result);
3924 BluetoothAdapter.prototype.getKnownDevices = function() {
3925 privUtils_.log('Entered BluetoothAdapter.getKnownDevices()');
3926 var args = AV.validateArgs(arguments, [
3928 name: 'successCallback',
3929 type: AV.Types.FUNCTION
3932 name: 'errorCallback',
3933 type: AV.Types.FUNCTION,
3939 var callback = function(result) {
3940 if (native.isFailure(result)) {
3941 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
3943 var r = native.getResultObject(result).devices;
3945 r.forEach(function(data) {
3946 devices.push(new BluetoothDevice(data));
3948 args.successCallback(devices);
3952 var result = native.call('BluetoothAdapterGetKnownDevices', {}, callback);
3953 if (native.isFailure(result)) {
3954 throw native.getErrorObject(result);
3958 BluetoothAdapter.prototype.getDevice = function() {
3959 privUtils_.log('Entered BluetoothAdapter.getDevice()');
3960 var args = AV.validateArgs(arguments, [
3963 type: AV.Types.STRING
3966 name: 'successCallback',
3967 type: AV.Types.FUNCTION
3970 name: 'errorCallback',
3971 type: AV.Types.FUNCTION,
3977 var callback = function(result) {
3978 if (native.isFailure(result)) {
3979 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
3981 args.successCallback(new BluetoothDevice(native.getResultObject(result)));
3985 var result = native.call(
3986 'BluetoothAdapterGetDevice',
3987 { address: args.address },
3990 if (native.isFailure(result)) {
3991 throw native.getErrorObject(result);
3995 BluetoothAdapter.prototype.createBonding = function() {
3996 privUtils_.log('Entered BluetoothAdapter.createBonding()');
3997 var args = AV.validateArgs(arguments, [
4000 type: AV.Types.STRING
4003 name: 'successCallback',
4004 type: AV.Types.FUNCTION,
4009 name: 'errorCallback',
4010 type: AV.Types.FUNCTION,
4017 address: args.address
4020 var callback = function(result) {
4021 if (native.isFailure(result)) {
4022 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
4024 args.successCallback(new BluetoothDevice(native.getResultObject(result)));
4028 var result = native.call('BluetoothAdapterCreateBonding', callArgs, callback);
4029 if (native.isFailure(result)) {
4030 throw native.getErrorObject(result);
4034 BluetoothAdapter.prototype.destroyBonding = function() {
4035 privUtils_.log('Entered BluetoothAdapter.destroyBonding()');
4036 var args = AV.validateArgs(arguments, [
4039 type: AV.Types.STRING
4042 name: 'successCallback',
4043 type: AV.Types.FUNCTION,
4048 name: 'errorCallback',
4049 type: AV.Types.FUNCTION,
4056 address: args.address
4059 var callback = function(result) {
4060 if (native.isFailure(result)) {
4061 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
4063 native.callIfPossible(args.successCallback);
4067 var result = native.call('BluetoothAdapterDestroyBonding', callArgs, callback);
4068 if (native.isFailure(result)) {
4069 throw native.getErrorObject(result);
4073 BluetoothAdapter.prototype.registerRFCOMMServiceByUUID = function() {
4074 privUtils_.log('Entered BluetoothAdapter.registerRFCOMMServiceByUUID()');
4075 var args = AV.validateArgs(arguments, [
4078 type: AV.Types.STRING
4082 type: AV.Types.STRING
4085 name: 'successCallback',
4086 type: AV.Types.FUNCTION
4089 name: 'errorCallback',
4090 type: AV.Types.FUNCTION,
4101 var callback = function(result) {
4102 if (native.isFailure(result)) {
4103 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
4105 // if registration was finished with success create BluetoothServiceHandler
4106 // with parameters passed to this function (uuid and name).
4107 args.successCallback(new BluetoothServiceHandler(callArgs));
4111 var result = native.call(
4112 'BluetoothAdapterRegisterRFCOMMServiceByUUID',
4116 if (native.isFailure(result)) {
4117 throw native.getErrorObject(result);
4121 BluetoothAdapter.prototype.getBluetoothProfileHandler = function() {
4122 privUtils_.log('Entered BluetoothAdapter.getBluetoothProfileHandler()');
4123 privUtils_.printDeprecationWarningFor('getBluetoothProfileHandler');
4124 var args = AV.validateArgs(arguments, [
4126 name: 'profileType',
4127 type: AV.Types.ENUM,
4128 values: T.getValues(_BluetoothProfileType)
4132 var callArgs = { profileType: args.profileType };
4134 var result = native.callSync('BluetoothAdapterGetBluetoothProfileHandler', callArgs);
4136 if (native.isFailure(result)) {
4137 throw native.getErrorObject(result);
4139 switch (args.profileType) {
4140 case _BluetoothProfileType.HEALTH:
4141 return new BluetoothHealthProfileHandler(callArgs);
4144 throw new WebAPIException(
4145 'NotSupportedError',
4146 'Profile ' + args.profileType + ' is not supported.'
4152 // class BluetoothGATTServer ////////////////////////
4153 var _BluetoothGATTServerServices = [];
4154 var _isBluetoothGATTServerRunning = false;
4156 function _BluetoothGattServerIsRunningChangeListener(result) {
4157 _isBluetoothGATTServerRunning = result.state;
4160 function _BluetoothGattServerBluetoothAdapterStateChangeListener(result) {
4161 if (_isBluetoothGATTServerRunning && false === result.state) {
4162 _BluetoothGATTServerServicesRegisteredInNativeLayer = {};
4167 * This set is used in BluetoothGATTServer::start() to check which services
4168 * from BluetoothGATTServer::services have already been registered in native
4169 * layer and which have to be registered.
4171 var _BluetoothGATTServerServicesRegisteredInNativeLayer = {};
4173 var BluetoothGATTServer = function() {
4174 Object.defineProperties(this, {
4178 return _BluetoothGATTServerServices;
4185 return _isBluetoothGATTServerRunning;
4191 // Register listener for managing GATTServer start / stop
4193 'BluetoothGattServerIsRunningChangeListener',
4194 _BluetoothGattServerIsRunningChangeListener
4197 // Register listener for managing BluetoothAdapter power off
4199 'BluetoothGattServerBluetoothAdapterStateChangeListener',
4200 _BluetoothGattServerBluetoothAdapterStateChangeListener
4204 var BluetoothGATTServer_valid_registerService_errors = [
4205 'InvalidStateError',
4206 'NotSupportedError',
4207 'InvalidValuesError',
4210 var BluetoothGATTServer_valid_registerService_exceptions = [
4211 'InvalidStateError',
4212 'TypeMismatchError',
4216 BluetoothGATTServer.prototype.registerService = function() {
4217 var args = AV.validateArgs(arguments, [
4220 type: AV.Types.DICTIONARY
4223 name: 'successCallback',
4224 type: AV.Types.FUNCTION,
4229 name: 'errorCallback',
4230 type: AV.Types.FUNCTION,
4236 var service = new BluetoothGATTServerService(args.service);
4238 // Callback when registering characteristics and descriptors callbacks is successful
4239 var successCallback = function() {
4240 _BluetoothGATTServerServicesRegisteredInNativeLayer[service._id] = true;
4241 _BluetoothGATTServerServices.push(service);
4242 native.callIfPossible(args.successCallback);
4245 // Callback when registering characteristics and descriptors callbacks fails,
4246 // unregister service
4247 var errorCallback = function() {
4248 var unregisterServiceCallback = function() {
4249 native.callIfPossible(args.errorCallback, AbortError);
4254 idsToRemoveFromNativeLayer: _getIncludedServicesAndItsComponentsIdsRecursively(
4260 'BluetoothGATTServerUnregisterService',
4262 unregisterServiceCallback
4266 var callback = function(result) {
4267 if (native.isFailure(result)) {
4268 native.callIfPossible(
4270 native.getErrorObjectAndValidate(
4272 BluetoothGATTServer_valid_registerService_errors,
4277 _registerReadWriteValueRequestCallbacksInGATTService(
4285 var result = native.call('BluetoothGATTServerRegisterService', service, callback);
4286 if (native.isFailure(result)) {
4287 throw native.getErrorObjectAndValidate(
4289 BluetoothGATTServer_valid_registerService_exceptions,
4295 var BluetoothGATTServer_valid_unregisterAllServices_errors = [
4296 'InvalidStateError',
4300 var BluetoothGATTServer_valid_unregisterAllServices_exceptions = [
4301 'TypeMismatchError',
4305 BluetoothGATTServer.prototype.unregisterAllServices = function() {
4306 privUtils_.log('Entered BluetoothGATTServer.unregisterAllServices()');
4307 var args = AV.validateArgs(arguments, [
4309 name: 'successCallback',
4310 type: AV.Types.FUNCTION,
4315 name: 'errorCallback',
4316 type: AV.Types.FUNCTION,
4322 var servicesToUnregister = [];
4323 for (var i = 0; i < _BluetoothGATTServerServices.length; ++i) {
4324 if (!T.isNullOrUndefined(_BluetoothGATTServerServices[i]._id)) {
4325 servicesToUnregister.push(_BluetoothGATTServerServices[i]);
4329 if (servicesToUnregister.length) {
4331 'Number of services to unregister: ' + servicesToUnregister.length
4333 var unregisterServiceCallbacksAggregator = new ResultCallbacksAggregator(
4334 servicesToUnregister.length,
4335 function onAllSucceeded() {
4336 _BluetoothGATTServerServices = [];
4337 _BluetoothGATTServerServicesRegisteredInNativeLayer = [];
4338 native.callIfPossible(args.successCallback);
4340 function onFailure(error) {
4341 native.callIfPossible(
4343 native.getErrorObjectAndValidate(
4345 BluetoothGATTServer_valid_unregisterAllServices_errors,
4352 for (var i = 0; i < servicesToUnregister.length; ++i) {
4353 var serviceIndex = _BluetoothGATTServerServices.findIndex(function(service) {
4354 return service._id === servicesToUnregister[i]._id;
4357 var serviceId = servicesToUnregister[i]._id;
4359 var unregisterServiceCallback = function(result) {
4360 if (native.isFailure(result)) {
4361 unregisterServiceCallbacksAggregator.errorCallback(
4362 native.getErrorObjectAndValidate(
4364 BluetoothGATTServer_valid_unregisterAllServices_errors,
4369 delete _BluetoothGATTServerServicesRegisteredInNativeLayer[serviceId];
4370 _BluetoothGATTServerServices.splice(serviceIndex, 1);
4371 unregisterServiceCallbacksAggregator.successCallback();
4376 _id: servicesToUnregister[i]._id,
4377 idsToRemoveFromNativeLayer: _getIncludedServicesAndItsComponentsIdsRecursively(
4378 servicesToUnregister[i]
4382 var result = native.call(
4383 'BluetoothGATTServerUnregisterService',
4385 unregisterServiceCallback
4388 if (native.isFailure(result)) {
4389 throw native.getErrorObjectAndValidate(
4391 BluetoothGATTServer_valid_unregisterAllServices_exceptions,
4398 'Nothing registered in native layer, calling BluetoothGATTServer.stop()'
4401 var callback = function(result) {
4402 if (native.isFailure(result)) {
4403 native.callIfPossible(
4405 native.getErrorObjectAndValidate(
4407 BluetoothGATTServer_valid_unregisterAllServices_errors,
4412 _BluetoothGATTServerServices = [];
4413 _BluetoothGATTServerServicesRegisteredInNativeLayer = {};
4414 native.callIfPossible(args.successCallback);
4418 var result = native.call('BluetoothGATTServerStop', {}, callback);
4419 if (native.isFailure(result)) {
4420 throw native.getErrorObjectAndValidate(
4422 BluetoothGATTServer_valid_unregisterAllServices_exceptions,
4430 * Objects of this class are used to wait for multiple callbacks results.
4432 * Its successCallback and errorCallback members should be passed as
4433 * the success and error callbacks, respectively, to the functions we wait for.
4434 * When the functions we wait for are called callbacksNum times, either
4435 * onAllSucceeded or onFailure is called, depending on whether only
4436 * successCallback was called or not.
4438 * For the usage example, take a look at BluetoothGATTServer.prototype.start,
4439 * where it's used to wait for registration of multiple services.
4441 var ResultCallbacksAggregator = function(callbacksNum, onAllSucceeded, onFailure) {
4442 var _callbacksNum = callbacksNum;
4443 var _allSucceeded = true;
4446 this.successCallback = function() {
4449 if (!_callbacksNum) {
4450 if (_allSucceeded) {
4458 this.errorCallback = function(error) {
4460 _allSucceeded = false;
4463 if (!_callbacksNum) {
4469 function _getServicesUnregisteredInNativeLayer() {
4470 var servicesUnregisteredInNativeLayer = [];
4471 for (var i = 0; i < _BluetoothGATTServerServices.length; ++i) {
4473 !_BluetoothGATTServerServicesRegisteredInNativeLayer[
4474 _BluetoothGATTServerServices[i]._id
4477 servicesUnregisteredInNativeLayer.push(_BluetoothGATTServerServices[i]);
4480 return servicesUnregisteredInNativeLayer;
4483 function _getIdsToReregisterReadWriteCallbacks(servicesUnregisteredInNativeLayer) {
4484 var idsToRegisterWriteValueCallbacks = [];
4485 var idsToRegisterReadValueCallbacks = [];
4487 for (var i = 0; i < servicesUnregisteredInNativeLayer.length; ++i) {
4488 var serviceComponentIds = _getIncludedServicesAndItsComponentsIdsRecursively(
4489 servicesUnregisteredInNativeLayer[i]
4492 for (var j = 0; j < serviceComponentIds.length; ++j) {
4493 var _id = serviceComponentIds[j];
4494 var callbackName = 'ReadValueCallback' + _id;
4497 * Only some of the serviceComponentIds are characteristics and descriptors
4498 * and within them, only some have read/write callbacks registered.
4499 * We have to check if the callbacks were registered for each id.
4501 if (callbackName in _BluetoothGATTServerReadWriteValueRequestCallbacks) {
4502 idsToRegisterReadValueCallbacks.push(_id);
4505 callbackName = 'WriteValueCallback' + _id;
4506 if (callbackName in _BluetoothGATTServerReadWriteValueRequestCallbacks) {
4507 idsToRegisterWriteValueCallbacks.push(_id);
4512 return [idsToRegisterReadValueCallbacks, idsToRegisterWriteValueCallbacks];
4515 var BluetoothGATTServer_valid_start_errors = [
4516 'InvalidStateError',
4517 'NotSupportedError',
4520 var BluetoothGATTServer_valid_start_exceptions = [
4521 'InvalidStateError',
4522 'TypeMismatchError',
4526 function _reregisterCallback(_id, nativeFunction, successCallback, errorCallback) {
4528 * This function should only be used to reregister read/write value request
4529 * callbacks in native layer for characteristics/descriptors, that have
4530 * had such callbacks registered before the last server's stop().
4531 * As JS listeners corresponding to these callbacks already exist in JS,
4532 * only C++ callbacks have to be reregistered.
4534 var callback = function(result) {
4535 if (native.isFailure(result)) {
4536 errorCallback(native.getErrorObject(result));
4542 var result = native.call(nativeFunction, { _id: _id }, callback);
4544 if (native.isFailure(result)) {
4545 throw native.getErrorObjectAndValidate(
4547 BluetoothGATTServer_valid_start_exceptions,
4553 BluetoothGATTServer.prototype.start = function() {
4554 privUtils_.log('Entered BluetoothGATTServer.start()');
4555 var args = AV.validateArgs(arguments, [
4557 name: 'successCallback',
4558 type: AV.Types.FUNCTION,
4563 name: 'errorCallback',
4564 type: AV.Types.FUNCTION,
4570 var servicesUnregisteredInNativeLayer = _getServicesUnregisteredInNativeLayer();
4572 * Characteristics and descriptors that were registered in the server before the last stop() call
4573 * could have had read/write value request callbacks registered.
4574 * These callbacks have to be reregistered (only) in native layer.
4575 * These arrays contain _ids of characteristics and descriptors, that will have their callbacks
4578 var idsToReregisterReadWriteValueCallbacks = _getIdsToReregisterReadWriteCallbacks(
4579 servicesUnregisteredInNativeLayer
4581 var idsToReregisterReadValueCallbacks = idsToReregisterReadWriteValueCallbacks[0];
4582 var idsToReregisterWriteValueCallbacks = idsToReregisterReadWriteValueCallbacks[1];
4584 var startServerCallback = function(result) {
4585 if (native.isFailure(result)) {
4586 native.callIfPossible(
4588 native.getErrorObjectAndValidate(
4590 BluetoothGATTServer_valid_start_errors,
4595 native.callIfPossible(args.successCallback);
4599 if (servicesUnregisteredInNativeLayer.length) {
4600 var numberOfCallbacksToWaitFor =
4601 servicesUnregisteredInNativeLayer.length +
4602 idsToReregisterReadValueCallbacks.length +
4603 idsToReregisterWriteValueCallbacks.length;
4604 var registerServiceCallbacksAggregator = new ResultCallbacksAggregator(
4605 numberOfCallbacksToWaitFor,
4606 function onAllSucceeded() {
4607 var result = native.call(
4608 'BluetoothGATTServerStart',
4613 if (native.isFailure(result)) {
4614 throw native.getErrorObjectAndValidate(
4616 BluetoothGATTServer_valid_start_exceptions,
4621 function onFailure(error) {
4622 native.callIfPossible(
4624 native.getErrorObjectAndValidate(
4626 BluetoothGATTServer_valid_start_errors,
4633 var registerServicesCallback = function(result) {
4634 if (native.isFailure(result)) {
4635 registerServiceCallbacksAggregator.errorCallback(result);
4637 registerServiceCallbacksAggregator.successCallback();
4641 for (var i = 0; i < servicesUnregisteredInNativeLayer.length; ++i) {
4642 var result = native.call(
4643 'BluetoothGATTServerRegisterService',
4644 servicesUnregisteredInNativeLayer[i],
4645 registerServicesCallback
4647 if (native.isFailure(result)) {
4648 throw native.getErrorObjectAndValidate(
4650 BluetoothGATTServer_valid_registerService_exceptions,
4656 for (var i = 0; i < idsToReregisterReadValueCallbacks.length; ++i) {
4657 _reregisterCallback(
4658 idsToReregisterReadValueCallbacks[i],
4659 'BluetoothGATTServerSetReadValueRequestCallback',
4660 registerServiceCallbacksAggregator.successCallback,
4661 registerServiceCallbacksAggregator.errorCallback
4665 for (var i = 0; i < idsToReregisterWriteValueCallbacks.length; ++i) {
4666 _reregisterCallback(
4667 idsToReregisterWriteValueCallbacks[i],
4668 'BluetoothGATTServerSetWriteValueRequestCallback',
4669 registerServiceCallbacksAggregator.successCallback,
4670 registerServiceCallbacksAggregator.errorCallback
4674 var result = native.call('BluetoothGATTServerStart', {}, startServerCallback);
4676 if (native.isFailure(result)) {
4677 throw native.getErrorObjectAndValidate(
4679 BluetoothGATTServer_valid_start_exceptions,
4686 var BluetoothGATTServer_valid_stop_errors = [
4687 'InvalidStateError',
4688 'NotSupportedError',
4691 var BluetoothGATTServer_valid_stop_exceptions = [
4692 'InvalidStateError',
4693 'TypeMismatchError',
4697 BluetoothGATTServer.prototype.stop = function() {
4698 privUtils_.log('Entered BluetoothGATTServer.stop()');
4699 var args = AV.validateArgs(arguments, [
4701 name: 'successCallback',
4702 type: AV.Types.FUNCTION,
4707 name: 'errorCallback',
4708 type: AV.Types.FUNCTION,
4714 var callback = function(result) {
4715 if (native.isFailure(result)) {
4716 native.callIfPossible(
4718 native.getErrorObjectAndValidate(
4720 BluetoothGATTServer_valid_stop_errors,
4725 _BluetoothGATTServerServicesRegisteredInNativeLayer = {};
4726 native.callIfPossible(args.successCallback);
4730 var result = native.call('BluetoothGATTServerStop', {}, callback);
4731 if (native.isFailure(result)) {
4732 throw native.getErrorObjectAndValidate(
4734 BluetoothGATTServer_valid_stop_exceptions,
4740 var BluetoothGATTServer_valid_getConnectionMtu_errors = [
4741 'InvalidStateError',
4742 'NotSupportedError',
4745 var BluetoothGATTServer_valid_getConnectionMtu_exceptions = [
4746 'TypeMismatchError',
4750 BluetoothGATTServer.prototype.getConnectionMtu = function() {
4751 privUtils_.log('Entered BluetoothGATTServer.getConnectionMtu()');
4752 var args = AV.validateArgs(arguments, [
4754 name: 'clientAddress',
4755 type: AV.Types.STRING
4758 name: 'successCallback',
4759 type: AV.Types.FUNCTION
4762 name: 'errorCallback',
4763 type: AV.Types.FUNCTION,
4768 var callback = function(result) {
4769 if (native.isFailure(result)) {
4770 native.callIfPossible(
4772 native.getErrorObjectAndValidate(
4774 BluetoothGATTServer_valid_getConnectionMtu_errors,
4779 args.successCallback(native.getResultObject(result));
4783 var result = native.call(
4784 'BluetoothGATTServerGetConnectionMtu',
4785 { clientAddress: args.clientAddress },
4788 if (native.isFailure(result)) {
4789 throw native.getErrorObjectAndValidate(
4791 BluetoothGATTServer_valid_getConnectionMtu_exceptions,
4797 var GATTServer = new BluetoothGATTServer();
4799 // class BluetoothManager ///////////////////////////
4800 var BluetoothManager = function() {
4801 Object.defineProperties(this, {
4803 value: new BluetoothClassDeviceMajor(),
4808 value: new BluetoothClassDeviceMinor(),
4813 value: new BluetoothClassDeviceService(),
4818 value: '00000000-0000-1000-8000-00805F9B34FB',
4825 var BluetoothManager_getDefaultAdapter = function() {
4826 privUtils_.checkPrivilegeAccess4Ver(
4828 Privilege.BLUETOOTH,
4829 Privilege.BLUETOOTH_GAP
4832 return new BluetoothAdapter();
4835 BluetoothManager.prototype.getDefaultAdapter = function() {
4836 privUtils_.log('Entered BluetoothManager.getDefaultAdapter()');
4837 return BluetoothManager_getDefaultAdapter();
4840 var BluetoothManager_getLEAdapter = function() {
4841 privUtils_.checkPrivilegeAccess4Ver(
4843 Privilege.BLUETOOTH,
4844 Privilege.BLUETOOTH_ADMIN
4847 return new BluetoothLEAdapter();
4850 BluetoothManager.prototype.getLEAdapter = function() {
4851 privUtils_.log('Entered BluetoothManager.getLEAdapter()');
4852 return BluetoothManager_getLEAdapter();
4855 var BluetoothManager_checkAndNormalizeHexString = function(hexString) {
4856 hexString = hexString.toLowerCase();
4857 if (hexString.startsWith('0x')) {
4858 hexString = hexString.substring(2);
4860 if (!/^[0-9a-f]+$/.test(hexString)) {
4861 throw new WebAPIException(
4862 WebAPIException.TYPE_MISMATCH_ERR,
4863 'Given string is not hexadecimal value'
4866 if ('0' === hexString) {
4869 if (1 === hexString.length % 2) {
4870 // to save consistency with BluetoothLEManufacturerData, last character is omitted
4871 hexString = hexString.replace(/.$/, '');
4876 var BluetoothManager_HexStringToUint8Array = function(hexString) {
4877 hexString = BluetoothManager_checkAndNormalizeHexString(hexString);
4878 if (0 === hexString.length) {
4879 return new Uint8Array([]);
4881 var data = hexString.match(/[0-9a-f]{2}/g).map(function(byte) {
4882 return parseInt(byte, 16);
4884 return new Uint8Array(data);
4887 var BluetoothManager_byteArrayToHexString = function(bytes) {
4888 if (0 == bytes.length) {
4894 .call(bytes, function(byte) {
4895 return ('0' + (byte & 0xff).toString(16)).slice(-2);
4901 var BluetoothManager_toByteArray = function(data) {
4902 if (data && String === data.constructor) {
4903 return numberArrayToByteArray(BluetoothManager_HexStringToUint8Array(data));
4906 data = numberArrayToByteArray(data);
4908 throw new WebAPIException(
4909 WebAPIException.TYPE_MISMATCH_ERR,
4910 'argument is not a valid Bytes type'
4917 BluetoothManager.prototype.toByteArray = function(data) {
4918 privUtils_.log('Entered BluetoothManager.toByteArray()');
4919 return BluetoothManager_toByteArray(data);
4922 var BluetoothManager_toDOMString = function(data) {
4923 if (data && String === data.constructor) {
4924 data = BluetoothManager_checkAndNormalizeHexString(data);
4925 if (0 !== data.length) {
4931 data = numberArrayToByteArray(data);
4933 throw new WebAPIException(
4934 WebAPIException.TYPE_MISMATCH_ERR,
4935 'argument is not a valid Bytes type'
4938 return BluetoothManager_byteArrayToHexString(data);
4941 BluetoothManager.prototype.toDOMString = function(data) {
4942 privUtils_.log('Entered BluetoothManager.toDOMString()');
4943 return BluetoothManager_toDOMString(data);
4946 var BluetoothManager_toUint8Array = function(data) {
4947 if (data && String === data.constructor) {
4948 return BluetoothManager_HexStringToUint8Array(data);
4951 data = new Uint8Array(numberArrayToByteArray(data));
4953 throw new WebAPIException(
4954 WebAPIException.TYPE_MISMATCH_ERR,
4955 'argument is not a valid Bytes type'
4962 BluetoothManager.prototype.toUint8Array = function(data) {
4963 privUtils_.log('Entered BluetoothManager.toUint8Array()');
4964 return BluetoothManager_toUint8Array(data);
4967 var BluetoothManager_UUIDIsValid128Bit = function(uuid) {
4968 var re128BitFormat = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
4969 if (re128BitFormat.test(uuid)) {
4975 var BluetoothManager_UUIDIsValid32Bit = function(uuid) {
4976 var re32BitFormat = /^[0-9a-f]{8}$/;
4977 if (re32BitFormat.test(uuid)) {
4983 var BluetoothManager_UUIDIsValid16Bit = function(uuid) {
4984 var re16BitFormat = /^[0-9a-f]{4}$/;
4985 if (re16BitFormat.test(uuid)) {
4991 var BluetoothManager_UUIDIsConvertibleTo16Bit = function(uuid) {
4992 var re128BitFormat = /^0000[0-9a-f]{4}-0000-1000-8000-00805f9b34fb$/;
4993 if (re128BitFormat.test(uuid)) {
4996 var re32BitFormat = /^0000[0-9a-f]{4}$/;
4997 if (re32BitFormat.test(uuid)) {
5003 var BluetoothManager_UUIDIsConvertibleTo32Bit = function(uuid) {
5004 var re = /^[0-9a-f]{8}-0000-1000-8000-00805f9b34fb$/;
5005 if (re.test(uuid)) {
5011 var BluetoothManager_UUIDTo128bit = function(uuid) {
5012 uuid = Converter.toString(uuid).toLowerCase();
5013 if (BluetoothManager_UUIDIsValid128Bit(uuid)) {
5016 var baseUuidLast96Bits = '-0000-1000-8000-00805f9b34fb';
5017 if (BluetoothManager_UUIDIsValid16Bit(uuid)) {
5018 return '0000' + uuid + baseUuidLast96Bits;
5020 if (BluetoothManager_UUIDIsValid32Bit(uuid)) {
5021 return uuid + baseUuidLast96Bits;
5023 throw new WebAPIException(
5024 WebAPIException.INVALID_VALUES_ERR,
5025 'Given parameter is not a supported uuid format: ' + uuid
5029 var BluetoothManager_UUIDToShortestPossible = function(uuid) {
5030 uuid = uuid.toLowerCase();
5031 if (BluetoothManager_UUIDIsValid16Bit(uuid)) {
5034 if (BluetoothManager_UUIDIsValid32Bit(uuid)) {
5035 if (BluetoothManager_UUIDIsConvertibleTo16Bit(uuid)) {
5036 return uuid.substring(4, 8);
5039 if (!BluetoothManager_UUIDIsValid128Bit(uuid)) {
5040 throw new WebAPIException(
5041 WebAPIException.INVALID_VALUES_ERR,
5042 'Given parameter is not a supported uuid format: ' + uuid
5045 if (BluetoothManager_UUIDIsConvertibleTo16Bit(uuid)) {
5046 return uuid.substring(4, 8);
5048 if (BluetoothManager_UUIDIsConvertibleTo32Bit(uuid)) {
5049 return uuid.substring(0, 8);
5054 var BluetoothManager_UUIDsEqual = function(uuid1, uuid2) {
5055 uuid1 = Converter.toString(uuid1).toLowerCase();
5056 uuid1 = BluetoothManager_UUIDTo128bit(uuid1);
5057 uuid2 = Converter.toString(uuid2).toLowerCase();
5058 uuid2 = BluetoothManager_UUIDTo128bit(uuid2);
5059 return uuid1 === uuid2;
5062 BluetoothManager.prototype.uuidTo128bit = function(uuid) {
5063 privUtils_.log('Entered BluetoothManager.uuidTo128bit()');
5064 var args = AV.validateArgs(arguments, [
5067 type: AV.Types.STRING
5070 return BluetoothManager_UUIDTo128bit(args.uuid);
5073 BluetoothManager.prototype.uuidToShortestPossible = function(uuid) {
5074 privUtils_.log('Entered BluetoothManager.uuidToShortestPossible()');
5075 var args = AV.validateArgs(arguments, [
5078 type: AV.Types.STRING
5081 return BluetoothManager_UUIDToShortestPossible(args.uuid);
5084 BluetoothManager.prototype.uuidsEqual = function(uuid1, uuid2) {
5085 privUtils_.log('Entered BluetoothManager.uuidsEqual()');
5086 var args = AV.validateArgs(arguments, [
5089 type: AV.Types.STRING
5093 type: AV.Types.STRING
5096 return BluetoothManager_UUIDsEqual(args.uuid1, args.uuid2);
5098 BluetoothManager.prototype.getGATTServer = function() {
5099 privUtils_.log('Entered BluetoothManager.getGATTServer()');
5100 return BluetoothManager_getGATTServer();
5103 var BluetoothManager_getGATTServer = function() {
5107 // exports //////////////////////////////////////////
5108 exports = new BluetoothManager();