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);
2179 var callbacksAggregator = new ResultCallbacksAggregator(
2181 function onAllSucceeded() {
2184 function onFailure(error) {
2185 errorCallback(error);
2189 _registerReadWriteValueRequestCallbacksInGATTServiceRecursively(
2195 var numberArrayToByteArray = function(array) {
2198 array.forEach(function(b) {
2199 d.push(Converter.toOctet(b));
2204 //class BluetoothGATTCharacteristic ///////////////////////////
2205 var BluetoothGATTCharacteristic = function(data, address) {
2206 if (!T.isObject(data)) {
2209 var address_ = address;
2210 var handle_ = data.handle;
2211 var descriptors_ = data.descriptors.map(function(descriptor_data) {
2212 return new BluetoothGATTDescriptor(descriptor_data, address_);
2214 var isBroadcast_ = data.isBroadcast;
2215 var hasExtendedProperties_ = data.hasExtendedProperties;
2216 var isNotify_ = data.isNotify;
2217 var isIndication_ = data.isIndication;
2218 var isReadable_ = data.isReadable;
2219 var isSignedWrite_ = data.isSignedWrite;
2220 var isWritable_ = data.isWritable;
2221 var isWriteNoResponse_ = data.isWriteNoResponse;
2222 var uuid_ = data.uuid;
2225 * If this function is called as a constructor of BluetoothGATTServerCharacteristic's
2226 * base class, some properties have to be left configurable, to enable redefinition.
2227 * Otherwise, if this function is called to create BluetoothGATTCharacteristic,
2228 * they are left non-configurable.
2230 * If BluetoothGATTCharacteristic will be a base for any other class in the future,
2231 * the line below may have to be updated to take into account the new class.
2233 var isConfigurable = this instanceof BluetoothGATTServerCharacteristic;
2235 Object.defineProperties(this, {
2238 configurable: isConfigurable,
2240 return descriptors_.slice();
2247 return isBroadcast_;
2251 hasExtendedProperties: {
2254 return hasExtendedProperties_;
2268 return isIndication_;
2282 return isSignedWrite_;
2293 isWriteNoResponse: {
2296 return isWriteNoResponse_;
2309 this.readValue = function() {
2310 privUtils_.log('Entered BluetoothGATTCharacteristic.readValue()');
2311 var args = AV.validateArgs(arguments, [
2313 name: 'successCallback',
2314 type: AV.Types.FUNCTION
2317 name: 'errorCallback',
2318 type: AV.Types.FUNCTION,
2324 var callback = function(result) {
2325 if (native.isFailure(result)) {
2326 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
2328 var d = numberArrayToByteArray(native.getResultObject(result));
2329 args.successCallback(d);
2333 var callArgs = { handle: handle_, address: address_ };
2335 var result = native.call(
2336 'BluetoothGATTClientServiceReadValue',
2341 if (native.isFailure(result)) {
2342 throw native.getErrorObject(result);
2346 this.writeValue = function(value, successCallback, errorCallback) {
2347 privUtils_.log('Entered BluetoothGATTCharacteristic.writeValue()');
2348 var args = AV.validateArgs(Array.prototype.slice.call(arguments, 1), [
2350 name: 'successCallback',
2351 type: AV.Types.FUNCTION,
2356 name: 'errorCallback',
2357 type: AV.Types.FUNCTION,
2363 var callback = function(result) {
2364 if (native.isFailure(result)) {
2365 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
2367 native.callIfPossible(args.successCallback);
2373 value: BluetoothManager_toByteArray(value),
2377 var result = native.call(
2378 'BluetoothGATTClientServiceWriteValue',
2383 if (native.isFailure(result)) {
2384 throw native.getErrorObject(result);
2388 var addValueChangeListener = function() {
2389 privUtils_.log('Entered BluetoothGATTCharacteristic.addValueChangeListener()');
2390 privUtils_.checkPrivilegeAccess4Ver(
2392 Privilege.BLUETOOTH,
2393 Privilege.BLUETOOTH_ADMIN
2395 var args = AV.validateArgs(arguments, [
2398 type: AV.Types.FUNCTION
2402 var callArgs = { handle: handle_, address: address_ };
2404 var callback = function(event) {
2405 if (event.handle === handle_) {
2406 args.callback(numberArrayToByteArray(native.getResultObject(event)));
2410 return _bluetoothGATTCharacteristicListener.addListener(callback, callArgs);
2413 this.addValueChangeListener = function() {
2414 return addValueChangeListener.apply(this, arguments);
2417 this.removeValueChangeListener = function() {
2418 privUtils_.log('Entered BluetoothGATTCharacteristic.removeValueChangeListener()');
2420 var args = AV.validateArgs(arguments, [
2427 var callArgs = { handle: handle_, address: address_ };
2429 return _bluetoothGATTCharacteristicListener.removeListener(
2436 var ValidateBluetoothGATTServerCharacteristicInit = function(initData) {
2437 return AV.validateArgs(
2440 initData['descriptors'] || [],
2441 initData['isBroadcast'] || false,
2442 initData['hasExtendedProperties'] || false,
2443 initData['isNotify'] || false,
2444 initData['isIndication'] || false,
2445 initData['isReadable'] || false,
2446 initData['isSignedWrite'] || false,
2447 initData['isWritable'] || false,
2448 initData['isWriteNoResponse'] || false,
2449 initData['readPermission'] || false,
2450 initData['writePermission'] || false,
2451 initData['encryptedReadPermission'] || false,
2452 initData['encryptedWritePermission'] || false,
2453 initData['encryptedSignedReadPermission'] || false,
2454 initData['encryptedSignedWritePermission'] || false,
2455 initData['readValueRequestCallback'] || null,
2456 initData['readValueSendResponseSuccessCallback'] || null,
2457 initData['readValueSendResponseErrorCallback'] || null,
2458 initData['writeValueRequestCallback'] || null,
2459 initData['writeValueSendResponseSuccessCallback'] || null,
2460 initData['writeValueSendResponseErrorCallback'] || null
2465 type: AV.Types.STRING,
2466 validator: IsUuidValid
2469 name: 'descriptors',
2470 type: AV.Types.ARRAY
2473 name: 'isBroadcast',
2474 type: AV.Types.BOOLEAN
2477 name: 'hasExtendedProperties',
2478 type: AV.Types.BOOLEAN
2482 type: AV.Types.BOOLEAN
2485 name: 'isIndication',
2486 type: AV.Types.BOOLEAN
2490 type: AV.Types.BOOLEAN
2493 name: 'isSignedWrite',
2494 type: AV.Types.BOOLEAN
2498 type: AV.Types.BOOLEAN
2501 name: 'isWriteNoResponse',
2502 type: AV.Types.BOOLEAN
2505 name: 'readPermission',
2506 type: AV.Types.BOOLEAN
2509 name: 'writePermission',
2510 type: AV.Types.BOOLEAN
2513 name: 'encryptedReadPermission',
2514 type: AV.Types.BOOLEAN
2517 name: 'encryptedWritePermission',
2518 type: AV.Types.BOOLEAN
2521 name: 'encryptedSignedReadPermission',
2522 type: AV.Types.BOOLEAN
2525 name: 'encryptedSignedWritePermission',
2526 type: AV.Types.BOOLEAN
2529 name: 'readValueRequestCallback',
2530 type: AV.Types.FUNCTION,
2534 name: 'readValueSendResponseSuccessCallback',
2535 type: AV.Types.FUNCTION,
2539 name: 'readValueSendResponseErrorCallback',
2540 type: AV.Types.FUNCTION,
2544 name: 'writeValueRequestCallback',
2545 type: AV.Types.FUNCTION,
2549 name: 'writeValueSendResponseErrorCallback',
2550 type: AV.Types.FUNCTION,
2554 name: 'writeValueSendResponseSuccessCallback',
2555 type: AV.Types.FUNCTION,
2562 //class BluetoothGATTServerCharacteristic ///////////////////////////
2563 var BluetoothGATTServerCharacteristic = function(data) {
2564 data = ValidateBluetoothGATTServerCharacteristicInit(data);
2566 BluetoothGATTCharacteristic.call(this, data, null);
2568 var descriptors_ = data.descriptors.map(function(descriptor_data) {
2569 return new BluetoothGATTServerDescriptor(descriptor_data, null);
2572 Object.defineProperties(this, {
2576 return descriptors_.slice();
2583 return data.readPermission;
2590 return data.writePermission;
2594 encryptedReadPermission: {
2597 return data.encryptedReadPermission;
2601 encryptedWritePermission: {
2604 return data.encryptedWritePermission;
2608 encryptedSignedReadPermission: {
2611 return data.encryptedSignedReadPermission;
2615 encryptedSignedWritePermission: {
2618 return data.encryptedSignedWritePermission;
2622 // This properties are "private" and meant not to be used by users
2623 _readValueRequestCallback: {
2626 return data.readValueRequestCallback;
2630 _readValueSendResponseSuccessCallback: {
2633 return data.readValueSendResponseSuccessCallback;
2637 _readValueSendResponseErrorCallback: {
2640 return data.readValueSendResponseErrorCallback;
2644 _writeValueRequestCallback: {
2647 return data.writeValueRequestCallback;
2651 _writeValueSendResponseSuccessCallback: {
2654 return data.writeValueSendResponseSuccessCallback;
2658 _writeValueSendResponseErrorCallback: {
2661 return data.writeValueSendResponseErrorCallback;
2666 // It has to be enumerable, to be serialized with JSON.stringify()
2668 value: NextGattServerEntityID()
2672 this.readValue = function() {
2673 throw new WebAPIException(
2674 'NotSupportedError',
2675 'This method cannot be called on BluetoothGATTServerCharacteristic'
2679 this.writeValue = function() {
2680 throw new WebAPIException(
2681 'NotSupportedError',
2682 'This method cannot be called on BluetoothGATTServerCharacteristic'
2686 this.addValueChangeListener = function() {
2687 throw new WebAPIException(
2688 'NotSupportedError',
2689 'This method cannot be called on BluetoothGATTServerCharacteristic'
2693 this.removeValueChangeListener = function() {
2694 /* Intended no operation */
2697 this.notifyAboutValueChange = function(
2703 var args = AV.validateArgs(Array.prototype.slice.call(arguments, 1), [
2705 name: 'clientAddress',
2706 type: AV.Types.STRING,
2711 name: 'notificationCB',
2712 type: AV.Types.LISTENER,
2714 'onnotificationsuccess',
2715 'onnotificationfail',
2716 'onnotificationfinish'
2723 type: AV.Types.FUNCTION,
2730 value: BluetoothManager_toByteArray(value),
2731 client: args.clientAddress || null,
2733 notifyId: _BluetoothGATTServerCharacteristicNotifyId++
2736 var callback = function(result) {
2737 if (native.isFailure(result)) {
2738 native.callIfPossible(args.errorCB, native.getErrorObject(result));
2742 var result = native.call(
2743 'BluetoothGATTServerCharacteristicNotifyAboutValueChange',
2748 if (native.isFailure(result)) {
2749 throw native.getErrorObject(result);
2753 'BluetoothGATTServerCharacteristicNotifyCallback_' + callArgs.notifyId,
2754 _BluetoothGATTServerCharacteristicNotifyCallback
2757 _BluetoothGATTServerCharacteristicNotifyListeners[callArgs.notifyId] =
2758 args.notificationCB;
2762 BluetoothGATTServerCharacteristic.prototype = Object.create(
2763 BluetoothGATTCharacteristic.prototype
2766 Object.defineProperty(BluetoothGATTServerCharacteristic.prototype, 'constructor', {
2767 value: BluetoothGATTServerCharacteristic,
2772 tizen.GATTRequestReply = function(statusCode, data) {
2773 AV.isConstructorCall(this, tizen.GATTRequestReply);
2775 var statusCode_ = Converter.toLong(statusCode);
2776 var data_ = T.isNullOrUndefined(data) ? null : BluetoothManager_toByteArray(data);
2778 Object.defineProperties(this, {
2785 statusCode_ = Converter.toLong(v);
2794 data_ = T.isNullOrUndefined(v) ? null : numberArrayToByteArray(v);
2800 function _createReadValueRequestCallback(
2802 sendResponseSuccessCallback,
2803 sendResponseErrorCallback
2805 return _singleListenerBuilder(
2806 'ReadValueRequestCallback_' + _id,
2808 * _singleListenerBuilder requires 2 callbacks, the second of which
2809 * is an error callback.
2810 * Read value request events coming from the native layer
2812 * Hence, we don't use the second callback here.
2814 function(event, readValueRequestCallback, unusedErrorCallback) {
2815 var clientAddress = event.clientAddress;
2816 var offset = event.offset;
2818 if (readValueRequestCallback) {
2819 var requestReply = readValueRequestCallback(clientAddress, offset);
2822 requestId: event.requestId,
2823 requestType: event.requestType,
2825 statusCode: requestReply.statusCode,
2826 data: requestReply.data
2828 var callback = function(result) {
2829 if (native.isFailure(result)) {
2830 native.callIfPossible(
2831 sendResponseErrorCallback,
2832 native.getErrorObject(result)
2835 native.callIfPossible(sendResponseSuccessCallback);
2838 var result = native.call(
2839 'BluetoothGATTServerSendResponse',
2849 function _createWriteValueRequestCallback(
2851 sendResponseSuccessCallback,
2852 sendResponseErrorCallback
2854 return _singleListenerBuilder(
2855 'WriteValueRequestCallback_' + _id,
2857 * _singleListenerBuilder requires 2 callbacks, the second of which
2858 * is an error callback.
2859 * Write value request events coming from the native layer
2861 * Hence, we don't use the second callback here.
2863 function(event, writeValueRequestCallback, unusedErrorCallback) {
2864 var clientAddress = event.clientAddress;
2865 var value = event.value;
2866 var offset = event.offset;
2867 var replyRequired = event.replyRequired;
2869 if (writeValueRequestCallback) {
2870 var requestReply = writeValueRequestCallback(
2872 BluetoothManager_toByteArray(value),
2878 requestId: event.requestId,
2879 requestType: event.requestType,
2880 value: null, // Responses to write requests don't contain value
2882 statusCode: requestReply.statusCode,
2883 data: requestReply.data
2885 var callback = function(result) {
2886 if (native.isFailure(result)) {
2887 native.callIfPossible(
2888 sendResponseErrorCallback,
2889 native.getErrorObject(result)
2892 native.callIfPossible(sendResponseSuccessCallback);
2895 var result = native.call(
2896 'BluetoothGATTServerSendResponse',
2906 var _BluetoothGATTServerReadWriteValueRequestCallbacks = {};
2908 var _setReadValueRequestCallbackCommon = function() {
2909 var args = AV.validateArgs(arguments, [
2911 name: 'readValueRequestCallback',
2912 type: AV.Types.FUNCTION
2915 name: 'successCallback',
2916 type: AV.Types.FUNCTION,
2921 name: 'errorCallback',
2922 type: AV.Types.FUNCTION,
2927 name: 'sendResponseSuccessCallback',
2928 type: AV.Types.FUNCTION,
2933 name: 'sendResponseErrorCallback',
2934 type: AV.Types.FUNCTION,
2940 var entityId = this._id;
2942 var callback = function(result) {
2943 if (native.isFailure(result)) {
2944 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
2946 var readValueRequestCallback = _createReadValueRequestCallback(
2948 args.sendResponseSuccessCallback,
2949 args.sendResponseErrorCallback
2951 readValueRequestCallback.addListener(
2952 args.readValueRequestCallback,
2953 function unusedErrorCallback() {
2954 /* Intentionally no operation */
2957 _BluetoothGATTServerReadWriteValueRequestCallbacks[
2958 'ReadValueCallback' + entityId
2959 ] = readValueRequestCallback;
2960 native.callIfPossible(args.successCallback, native.getErrorObject(result));
2964 var callArgs = { _id: this._id };
2965 var result = native.call(
2966 'BluetoothGATTServerSetReadValueRequestCallback',
2971 if (native.isFailure(result)) {
2972 throw native.getErrorObject(result);
2976 var _setWriteValueRequestCallbackCommon = function() {
2977 var args = AV.validateArgs(arguments, [
2979 name: 'writeValueRequestCallback',
2980 type: AV.Types.FUNCTION
2983 name: 'successCallback',
2984 type: AV.Types.FUNCTION,
2989 name: 'errorCallback',
2990 type: AV.Types.FUNCTION,
2995 name: 'sendResponseSuccessCallback',
2996 type: AV.Types.FUNCTION,
3001 name: 'sendResponseErrorCallback',
3002 type: AV.Types.FUNCTION,
3008 var entityId = this._id;
3010 var callback = function(result) {
3011 if (native.isFailure(result)) {
3012 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
3014 var writeValueRequestCallback = _createWriteValueRequestCallback(
3016 args.sendResponseSuccessCallback,
3017 args.sendResponseErrorCallback
3019 writeValueRequestCallback.addListener(
3020 args.writeValueRequestCallback,
3021 function unusedErrorCallback() {
3022 /* Intentionally no operation */
3025 _BluetoothGATTServerReadWriteValueRequestCallbacks[
3026 'WriteValueCallback' + entityId
3027 ] = writeValueRequestCallback;
3028 native.callIfPossible(args.successCallback, native.getErrorObject(result));
3032 var callArgs = { _id: this._id };
3033 var result = native.call(
3034 'BluetoothGATTServerSetWriteValueRequestCallback',
3039 if (native.isFailure(result)) {
3040 throw native.getErrorObject(result);
3044 BluetoothGATTServerCharacteristic.prototype.setReadValueRequestCallback = _setReadValueRequestCallbackCommon;
3045 BluetoothGATTServerCharacteristic.prototype.setWriteValueRequestCallback = _setWriteValueRequestCallbackCommon;
3047 var _BluetoothGATTServerCharacteristicNotifyId = 0;
3048 var _BluetoothGATTServerCharacteristicNotifyListeners = {};
3049 var _BluetoothGATTServerCharacteristicNotifyCallback = function(event) {
3050 privUtils_.log('Got notification about characteristic\'s value change');
3052 T.isNullOrUndefined(
3053 _BluetoothGATTServerCharacteristicNotifyListeners[event.notifyId]
3056 privUtils_.log('Notification callback is not set, skipping');
3060 var callback = _BluetoothGATTServerCharacteristicNotifyListeners[event.notifyId];
3062 if (event.type === 'onnotificationsuccess') {
3063 native.callIfPossible(callback.onnotificationsuccess, event.clientAddress);
3067 if (event.type === 'onnotificationfail') {
3068 native.callIfPossible(
3069 callback.onnotificationfail,
3070 event.clientAddress,
3071 native.getErrorObject(event)
3076 if (event.type === 'onnotificationfinish') {
3077 native.callIfPossible(callback.onnotificationfinish, event.clientAddress);
3080 native.removeListener(
3081 'BluetoothGATTServerCharacteristicNotifyCallback_' + event.notifyId
3086 * Creates a manager for specified listener event. Manager handles multiple
3087 * registered listeners
3089 * @param {string} name - name of the listener this manager handles
3090 * @param {function} callback - function to be invoked when event specified by the name
3092 * This function should have following signature:
3093 * void callback(listener, event);
3094 * @param {string} addListenerId - optional parameter. If specified, this native
3095 * method will be called synchronously when
3096 * listener is added.
3097 * @param {string} removeListenerId - optional parameter. If specified, this native
3098 * method will be called synchronously when
3099 * listener is removed.
3100 * @param {bool} repeatNativeCall - optional parameter. If specified, the addListenerId
3101 * and removeListenerId methods will be called
3102 * synchronously each time listener is added/removed.
3103 * Otherwise they are going to be called just once: when
3104 * first listener is added and last listener is removed.
3106 * @return {object} object which allows to add or remove callbacks for specified listener
3108 function _multipleListenerBuilder(
3115 var listenerName = name;
3116 var addId = addListenerId;
3117 var removeId = removeListenerId;
3118 var callbackFunction = callback;
3121 var jsListenerRegistered = false;
3122 var nativeListenerRegistered = false;
3123 var repeatNativeListenerCall = repeatNativeCall;
3125 function innerCallback(event) {
3126 for (var watchId in listeners) {
3127 if (listeners.hasOwnProperty(watchId)) {
3128 callbackFunction(listeners[watchId], event);
3133 function addListener(callback, args) {
3136 if (addId && (!nativeListenerRegistered || repeatNativeListenerCall)) {
3137 var result = native.callSync(addId, args || {});
3138 if (native.isFailure(result)) {
3139 throw native.getErrorObject(result);
3141 nativeListenerRegistered = true;
3144 if (!jsListenerRegistered) {
3145 native.addListener(listenerName, innerCallback);
3146 jsListenerRegistered = true;
3149 listeners[id] = callback;
3153 function removeListener(watchId, args) {
3154 if (listeners.hasOwnProperty(watchId)) {
3155 delete listeners[watchId];
3160 ((nativeListenerRegistered && T.isEmptyObject(listeners)) ||
3161 repeatNativeListenerCall)
3163 var result = native.callSync(removeId, args || {});
3164 if (native.isFailure(result)) {
3165 throw native.getErrorObject(result);
3167 nativeListenerRegistered = false;
3170 if (jsListenerRegistered && T.isEmptyObject(listeners)) {
3171 native.removeListener(listenerName, innerCallback);
3172 jsListenerRegistered = false;
3177 addListener: addListener,
3178 removeListener: removeListener
3182 var _bluetoothGATTCharacteristicListener = _multipleListenerBuilder(
3183 'BluetoothGATTCharacteristicValueChangeListener',
3184 function(listener, event) {
3187 'BluetoothGATTClientServiceAddValueChangeListener',
3188 'BluetoothGATTClientServiceRemoveValueChangeListener',
3193 * This object is used by:
3194 * - BluetoothLEDevice.addConnectStateChangeListener()
3195 * - BluetoothLEAdapter.addConnectStateChangeListener()
3197 var _bleConnectChangeListener = _multipleListenerBuilder(
3198 'BluetoothLEConnectChangeCallback',
3199 function(listener, event) {
3202 'BluetoothLEDeviceAddConnectStateChangeListener',
3203 'BluetoothLEDeviceRemoveConnectStateChangeListener'
3206 var _bleAttMtuChangeListener = _multipleListenerBuilder(
3207 'BluetoothLEAttMtuChangeCallback',
3208 function(listener, event) {
3211 'BluetoothLEDeviceAddAttMtuChangeListener',
3212 'BluetoothLEDeviceRemoveAttMtuChangeListener'
3215 //class BluetoothGATTDescriptor ///////////////////////////
3216 var BluetoothGATTDescriptor = function(data, address) {
3217 var handle_ = data.handle;
3218 //address_ is needed to control if device is still connected
3219 var address_ = address;
3220 var uuid_ = data.uuid;
3222 this.readValue = function() {
3223 privUtils_.log('Entered BluetoothGATTDescriptor.readValue()');
3224 var args = AV.validateArgs(arguments, [
3226 name: 'successCallback',
3227 type: AV.Types.FUNCTION
3230 name: 'errorCallback',
3231 type: AV.Types.FUNCTION,
3237 var callback = function(result) {
3238 if (native.isFailure(result)) {
3239 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
3241 var d = numberArrayToByteArray(native.getResultObject(result));
3242 args.successCallback(d);
3246 var callArgs = { handle: handle_, address: address_ };
3248 var result = native.call(
3249 'BluetoothGATTClientServiceReadValue',
3254 if (native.isFailure(result)) {
3255 throw native.getErrorObject(result);
3259 this.writeValue = function(value, successCallback, errorCallback) {
3260 privUtils_.log('Entered BluetoothGATTDescriptor.writeValue()');
3261 var args = AV.validateArgs(Array.prototype.slice.call(arguments, 1), [
3263 name: 'successCallback',
3264 type: AV.Types.FUNCTION,
3269 name: 'errorCallback',
3270 type: AV.Types.FUNCTION,
3276 var callback = function(result) {
3277 if (native.isFailure(result)) {
3278 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
3280 native.callIfPossible(args.successCallback);
3286 value: BluetoothManager_toByteArray(value),
3290 var result = native.call(
3291 'BluetoothGATTClientServiceWriteValue',
3296 if (native.isFailure(result)) {
3297 throw native.getErrorObject(result);
3301 Object.defineProperties(this, {
3312 var ValidateBluetoothGATTServerDescriptorInit = function(initData) {
3313 return AV.validateArgs(
3316 initData['readPermission'] || false,
3317 initData['writePermission'] || false,
3318 initData['encryptedReadPermission'] || false,
3319 initData['encryptedWritePermission'] || false,
3320 initData['encryptedSignedReadPermission'] || false,
3321 initData['encryptedSignedWritePermission'] || false,
3322 initData['readValueRequestCallback'] || null,
3323 initData['readValueSendResponseSuccessCallback'] || null,
3324 initData['readValueSendResponseErrorCallback'] || null,
3325 initData['writeValueRequestCallback'] || null,
3326 initData['writeValueSendResponseSuccessCallback'] || null,
3327 initData['writeValueSendResponseErrorCallback'] || null
3332 type: AV.Types.STRING,
3333 validator: IsUuidValid
3336 name: 'readPermission',
3337 type: AV.Types.BOOLEAN
3340 name: 'writePermission',
3341 type: AV.Types.BOOLEAN
3344 name: 'encryptedReadPermission',
3345 type: AV.Types.BOOLEAN
3348 name: 'encryptedWritePermission',
3349 type: AV.Types.BOOLEAN
3352 name: 'encryptedSignedReadPermission',
3353 type: AV.Types.BOOLEAN
3356 name: 'encryptedSignedWritePermission',
3357 type: AV.Types.BOOLEAN
3360 name: 'readValueRequestCallback',
3361 type: AV.Types.FUNCTION,
3365 name: 'readValueSendResponseSuccessCallback',
3366 type: AV.Types.FUNCTION,
3370 name: 'readValueSendResponseErrorCallback',
3371 type: AV.Types.FUNCTION,
3375 name: 'writeValueRequestCallback',
3376 type: AV.Types.FUNCTION,
3380 name: 'writeValueSendResponseErrorCallback',
3381 type: AV.Types.FUNCTION,
3385 name: 'writeValueSendResponseSuccessCallback',
3386 type: AV.Types.FUNCTION,
3393 var BluetoothGATTServerDescriptor = function(data, address) {
3394 data = ValidateBluetoothGATTServerDescriptorInit(data);
3396 BluetoothGATTDescriptor.call(this, data, null);
3398 Object.defineProperties(this, {
3402 return data.readPermission;
3409 return data.writePermission;
3413 encryptedReadPermission: {
3416 return data.encryptedReadPermission;
3420 encryptedWritePermission: {
3423 return data.encryptedWritePermission;
3427 encryptedSignedReadPermission: {
3430 return data.encryptedSignedReadPermission;
3434 encryptedSignedWritePermission: {
3437 return data.encryptedSignedWritePermission;
3441 // This properties are "private" and meant not to be used by users
3442 _readValueRequestCallback: {
3445 return data.readValueRequestCallback;
3449 _readValueSendResponseSuccessCallback: {
3452 return data.readValueSendResponseSuccessCallback;
3456 _readValueSendResponseErrorCallback: {
3459 return data.readValueSendResponseErrorCallback;
3463 _writeValueRequestCallback: {
3466 return data.writeValueRequestCallback;
3470 _writeValueSendResponseSuccessCallback: {
3473 return data.writeValueSendResponseSuccessCallback;
3477 _writeValueSendResponseErrorCallback: {
3480 return data.writeValueSendResponseErrorCallback;
3485 // It has to be enumerable, to be serialized with JSON.stringify()
3487 value: NextGattServerEntityID()
3491 this.readValue = function() {
3492 throw new WebAPIException(
3493 'NotSupportedError',
3494 'This method cannot be called on BluetoothGATTServerDescriptor'
3498 this.writeValue = function() {
3499 throw new WebAPIException(
3500 'NotSupportedError',
3501 'This method cannot be called on BluetoothGATTServerDescriptor'
3506 BluetoothGATTServerDescriptor.prototype = Object.create(
3507 BluetoothGATTDescriptor.prototype
3510 Object.defineProperty(BluetoothGATTServerDescriptor.prototype, 'constructor', {
3511 value: BluetoothGATTServerDescriptor,
3516 BluetoothGATTServerDescriptor.prototype.setReadValueRequestCallback = _setReadValueRequestCallbackCommon;
3517 BluetoothGATTServerDescriptor.prototype.setWriteValueRequestCallback = _setWriteValueRequestCallbackCommon;
3519 // class BluetoothAdapter ///////////////////////////
3520 var BluetoothAdapter = function() {
3521 function nameGetter() {
3522 var result = native.callSync('BluetoothAdapterGetName', {});
3524 if (native.isFailure(result)) {
3527 return native.getResultObject(result);
3531 function addressGetter() {
3532 var result = native.callSync('BluetoothAdapterGetAddress', {});
3534 if (native.isFailure(result)) {
3537 return native.getResultObject(result);
3541 function poweredGetter() {
3542 var result = native.callSync('BluetoothAdapterGetPowered', {});
3544 if (native.isFailure(result)) {
3547 return native.getResultObject(result);
3551 function visibleGetter() {
3552 var result = native.callSync('BluetoothAdapterGetVisible', {});
3554 if (native.isFailure(result)) {
3557 return native.getResultObject(result);
3561 Object.defineProperties(this, {
3585 BluetoothAdapter.prototype.setName = function() {
3586 privUtils_.log('Entered BluetoothAdapter.setName()');
3587 var args = AV.validateArgs(arguments, [
3590 type: AV.Types.STRING
3593 name: 'successCallback',
3594 type: AV.Types.FUNCTION,
3599 name: 'errorCallback',
3600 type: AV.Types.FUNCTION,
3610 var callback = function(result) {
3611 if (native.isFailure(result)) {
3612 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
3614 native.callIfPossible(args.successCallback);
3618 var result = native.call('BluetoothAdapterSetName', callArgs, callback);
3619 if (native.isFailure(result)) {
3620 throw native.getErrorObject(result);
3624 BluetoothAdapter.prototype.setPowered = function() {
3625 privUtils_.log('Entered BluetoothAdapter.setPowered()');
3626 privUtils_.printDeprecationWarningFor('setPowered()');
3628 'Let the user turn on/off Bluetooth through the Settings application instead.'
3631 var args = AV.validateArgs(arguments, [
3634 type: AV.Types.BOOLEAN
3637 name: 'successCallback',
3638 type: AV.Types.FUNCTION,
3643 name: 'errorCallback',
3644 type: AV.Types.FUNCTION,
3651 powered: args.powered
3654 var callback = function(result) {
3655 if (native.isFailure(result)) {
3656 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
3658 native.callIfPossible(args.successCallback);
3662 var result = native.call('BluetoothAdapterSetPowered', callArgs, callback);
3663 if (native.isFailure(result)) {
3664 throw native.getErrorObject(result);
3668 // This method is deprecated since Tizen 2.3.
3669 BluetoothAdapter.prototype.setVisible = function() {
3670 privUtils_.log('Entered BluetoothAdapter.setVisible()');
3671 privUtils_.printDeprecationWarningFor('setVisible()');
3673 'Let the user change the Bluetooth visibility through the Settings ' +
3674 'application instead.'
3677 var args = AV.validateArgs(arguments, [
3680 type: AV.Types.BOOLEAN
3683 name: 'successCallback',
3684 type: AV.Types.FUNCTION,
3689 name: 'errorCallback',
3690 type: AV.Types.FUNCTION,
3696 type: AV.Types.UNSIGNED_LONG,
3703 visible: args.visible
3706 if (args.visible === true) {
3707 if (T.isNullOrUndefined(args.timeout)) {
3708 callArgs.timeout = 0;
3710 callArgs.timeout = args.timeout > 65535 ? 180 : args.timeout;
3714 var callback = function(result) {
3715 if (native.isFailure(result)) {
3716 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
3718 native.callIfPossible(args.successCallback);
3722 var result = native.call('BluetoothAdapterSetVisible', callArgs, callback);
3723 if (native.isFailure(result)) {
3724 throw native.getErrorObject(result);
3730 function _BluetoothAdapterChangeCallback(event) {
3731 privUtils_.log('_BluetoothAdapterChangeCallback');
3737 case 'onstatechanged':
3741 case 'onnamechanged':
3745 case 'onvisibilitychanged':
3750 privUtils_.log('Unknown mode: ' + e.action);
3754 if (_listener[e.action]) {
3755 _listener[e.action](d);
3759 BluetoothAdapter.prototype.setChangeListener = function() {
3760 privUtils_.log('Entered BluetoothAdapter.setChangeListener()');
3761 var args = AV.validateArgs(arguments, [
3763 name: 'changeCallback',
3764 type: AV.Types.LISTENER,
3765 values: ['onstatechanged', 'onnamechanged', 'onvisibilitychanged']
3769 if (T.isNullOrUndefined(_listener)) {
3771 'BluetoothAdapterChangeCallback',
3772 _BluetoothAdapterChangeCallback
3774 native.callSync('BluetoothAdapterSetChangeListener', {});
3776 _listener = args.changeCallback;
3779 BluetoothAdapter.prototype.unsetChangeListener = function() {
3780 privUtils_.log('Entered BluetoothAdapter.unsetChangeListener()');
3781 if (!T.isNullOrUndefined(_listener)) {
3782 native.removeListener(
3783 'BluetoothAdapterChangeCallback',
3784 _BluetoothAdapterChangeCallback
3786 native.callSync('BluetoothAdapterUnsetChangeListener', {});
3787 _listener = undefined;
3791 var _discoverDevicesSuccessCallback;
3792 var _discoverDevicesErrorCallback;
3794 function _BluetoothDiscoverDevicesSuccessCallback(event) {
3802 case 'ondevicefound':
3803 d = new BluetoothDevice(e.data);
3806 case 'ondevicedisappeared':
3811 var result = e.data;
3813 result.forEach(function(data) {
3814 d.push(new BluetoothDevice(data));
3817 //remove listeners after discovering
3818 native.removeListener(
3819 'BluetoothDiscoverDevicesSuccessCallback',
3820 _BluetoothDiscoverDevicesSuccessCallback
3822 native.removeListener(
3823 'BluetoothDiscoverDevicesErrorCallback',
3824 _BluetoothDiscoverDevicesErrorCallback
3829 privUtils_.log('Unknown mode: ' + e.action);
3833 if (_discoverDevicesSuccessCallback[e.action]) {
3834 _discoverDevicesSuccessCallback[e.action](d);
3838 function _BluetoothDiscoverDevicesErrorCallback(event) {
3840 setTimeout(function() {
3841 native.callIfPossible(_discoverDevicesErrorCallback, native.getErrorObject(e));
3845 BluetoothAdapter.prototype.discoverDevices = function() {
3846 privUtils_.log('Entered BluetoothAdapter.discoverDevices()');
3847 var args = AV.validateArgs(arguments, [
3849 name: 'successCallback',
3850 type: AV.Types.LISTENER,
3851 values: ['onstarted', 'ondevicefound', 'ondevicedisappeared', 'onfinished']
3854 name: 'errorCallback',
3855 type: AV.Types.FUNCTION,
3861 _discoverDevicesSuccessCallback = args.successCallback;
3862 _discoverDevicesErrorCallback = args.errorCallback;
3864 'BluetoothDiscoverDevicesSuccessCallback',
3865 _BluetoothDiscoverDevicesSuccessCallback
3868 'BluetoothDiscoverDevicesErrorCallback',
3869 _BluetoothDiscoverDevicesErrorCallback
3872 var result = native.callSync('BluetoothAdapterDiscoverDevices', {});
3874 if (native.isFailure(result)) {
3875 native.removeListener(
3876 'BluetoothDiscoverDevicesSuccessCallback',
3877 _BluetoothDiscoverDevicesSuccessCallback
3879 native.removeListener(
3880 'BluetoothDiscoverDevicesErrorCallback',
3881 _BluetoothDiscoverDevicesErrorCallback
3883 throw native.getErrorObject(result);
3887 BluetoothAdapter.prototype.stopDiscovery = function() {
3888 privUtils_.log('Entered BluetoothAdapter.stopDiscovery()');
3889 var args = AV.validateArgs(arguments, [
3891 name: 'successCallback',
3892 type: AV.Types.FUNCTION,
3897 name: 'errorCallback',
3898 type: AV.Types.FUNCTION,
3904 var callback = function(result) {
3905 if (native.isFailure(result)) {
3906 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
3908 native.callIfPossible(args.successCallback);
3912 var result = native.call('BluetoothAdapterStopDiscovery', {}, callback);
3913 if (native.isFailure(result)) {
3914 throw native.getErrorObject(result);
3918 BluetoothAdapter.prototype.getKnownDevices = function() {
3919 privUtils_.log('Entered BluetoothAdapter.getKnownDevices()');
3920 var args = AV.validateArgs(arguments, [
3922 name: 'successCallback',
3923 type: AV.Types.FUNCTION
3926 name: 'errorCallback',
3927 type: AV.Types.FUNCTION,
3933 var callback = function(result) {
3934 if (native.isFailure(result)) {
3935 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
3937 var r = native.getResultObject(result).devices;
3939 r.forEach(function(data) {
3940 devices.push(new BluetoothDevice(data));
3942 args.successCallback(devices);
3946 var result = native.call('BluetoothAdapterGetKnownDevices', {}, callback);
3947 if (native.isFailure(result)) {
3948 throw native.getErrorObject(result);
3952 BluetoothAdapter.prototype.getDevice = function() {
3953 privUtils_.log('Entered BluetoothAdapter.getDevice()');
3954 var args = AV.validateArgs(arguments, [
3957 type: AV.Types.STRING
3960 name: 'successCallback',
3961 type: AV.Types.FUNCTION
3964 name: 'errorCallback',
3965 type: AV.Types.FUNCTION,
3971 var callback = function(result) {
3972 if (native.isFailure(result)) {
3973 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
3975 args.successCallback(new BluetoothDevice(native.getResultObject(result)));
3979 var result = native.call(
3980 'BluetoothAdapterGetDevice',
3981 { address: args.address },
3984 if (native.isFailure(result)) {
3985 throw native.getErrorObject(result);
3989 BluetoothAdapter.prototype.createBonding = function() {
3990 privUtils_.log('Entered BluetoothAdapter.createBonding()');
3991 var args = AV.validateArgs(arguments, [
3994 type: AV.Types.STRING
3997 name: 'successCallback',
3998 type: AV.Types.FUNCTION,
4003 name: 'errorCallback',
4004 type: AV.Types.FUNCTION,
4011 address: args.address
4014 var callback = function(result) {
4015 if (native.isFailure(result)) {
4016 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
4018 args.successCallback(new BluetoothDevice(native.getResultObject(result)));
4022 var result = native.call('BluetoothAdapterCreateBonding', callArgs, callback);
4023 if (native.isFailure(result)) {
4024 throw native.getErrorObject(result);
4028 BluetoothAdapter.prototype.destroyBonding = function() {
4029 privUtils_.log('Entered BluetoothAdapter.destroyBonding()');
4030 var args = AV.validateArgs(arguments, [
4033 type: AV.Types.STRING
4036 name: 'successCallback',
4037 type: AV.Types.FUNCTION,
4042 name: 'errorCallback',
4043 type: AV.Types.FUNCTION,
4050 address: args.address
4053 var callback = function(result) {
4054 if (native.isFailure(result)) {
4055 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
4057 native.callIfPossible(args.successCallback);
4061 var result = native.call('BluetoothAdapterDestroyBonding', callArgs, callback);
4062 if (native.isFailure(result)) {
4063 throw native.getErrorObject(result);
4067 BluetoothAdapter.prototype.registerRFCOMMServiceByUUID = function() {
4068 privUtils_.log('Entered BluetoothAdapter.registerRFCOMMServiceByUUID()');
4069 var args = AV.validateArgs(arguments, [
4072 type: AV.Types.STRING
4076 type: AV.Types.STRING
4079 name: 'successCallback',
4080 type: AV.Types.FUNCTION
4083 name: 'errorCallback',
4084 type: AV.Types.FUNCTION,
4095 var callback = function(result) {
4096 if (native.isFailure(result)) {
4097 native.callIfPossible(args.errorCallback, native.getErrorObject(result));
4099 // if registration was finished with success create BluetoothServiceHandler
4100 // with parameters passed to this function (uuid and name).
4101 args.successCallback(new BluetoothServiceHandler(callArgs));
4105 var result = native.call(
4106 'BluetoothAdapterRegisterRFCOMMServiceByUUID',
4110 if (native.isFailure(result)) {
4111 throw native.getErrorObject(result);
4115 BluetoothAdapter.prototype.getBluetoothProfileHandler = function() {
4116 privUtils_.log('Entered BluetoothAdapter.getBluetoothProfileHandler()');
4117 privUtils_.printDeprecationWarningFor('getBluetoothProfileHandler');
4118 var args = AV.validateArgs(arguments, [
4120 name: 'profileType',
4121 type: AV.Types.ENUM,
4122 values: T.getValues(_BluetoothProfileType)
4126 var callArgs = { profileType: args.profileType };
4128 var result = native.callSync('BluetoothAdapterGetBluetoothProfileHandler', callArgs);
4130 if (native.isFailure(result)) {
4131 throw native.getErrorObject(result);
4133 switch (args.profileType) {
4134 case _BluetoothProfileType.HEALTH:
4135 return new BluetoothHealthProfileHandler(callArgs);
4138 throw new WebAPIException(
4139 'NotSupportedError',
4140 'Profile ' + args.profileType + ' is not supported.'
4146 // class BluetoothGATTServer ////////////////////////
4147 var _BluetoothGATTServerServices = [];
4148 var _isBluetoothGATTServerRunning = false;
4150 function _BluetoothGattServerIsRunningChangeListener(result) {
4151 _isBluetoothGATTServerRunning = result.state;
4154 function _BluetoothGattServerBluetoothAdapterStateChangeListener(result) {
4155 if (_isBluetoothGATTServerRunning && false === result.state) {
4156 _BluetoothGATTServerServicesRegisteredInNativeLayer = {};
4161 * This set is used in BluetoothGATTServer::start() to check which services
4162 * from BluetoothGATTServer::services have already been registered in native
4163 * layer and which have to be registered.
4165 var _BluetoothGATTServerServicesRegisteredInNativeLayer = {};
4167 var BluetoothGATTServer = function() {
4168 Object.defineProperties(this, {
4172 return _BluetoothGATTServerServices;
4179 return _isBluetoothGATTServerRunning;
4185 // Register listener for managing GATTServer start / stop
4187 'BluetoothGattServerIsRunningChangeListener',
4188 _BluetoothGattServerIsRunningChangeListener
4191 // Register listener for managing BluetoothAdapter power off
4193 'BluetoothGattServerBluetoothAdapterStateChangeListener',
4194 _BluetoothGattServerBluetoothAdapterStateChangeListener
4198 var BluetoothGATTServer_valid_registerService_errors = [
4199 'InvalidStateError',
4200 'NotSupportedError',
4201 'InvalidValuesError',
4204 var BluetoothGATTServer_valid_registerService_exceptions = [
4205 'InvalidStateError',
4206 'TypeMismatchError',
4210 BluetoothGATTServer.prototype.registerService = function() {
4211 var args = AV.validateArgs(arguments, [
4214 type: AV.Types.DICTIONARY
4217 name: 'successCallback',
4218 type: AV.Types.FUNCTION,
4223 name: 'errorCallback',
4224 type: AV.Types.FUNCTION,
4230 var service = new BluetoothGATTServerService(args.service);
4232 // Callback when registering characteristics and descriptors callbacks is successful
4233 var successCallback = function() {
4234 _BluetoothGATTServerServicesRegisteredInNativeLayer[service._id] = true;
4235 _BluetoothGATTServerServices.push(service);
4236 native.callIfPossible(args.successCallback);
4239 // Callback when registering characteristics and descriptors callbacks fails,
4240 // unregister service
4241 var errorCallback = function() {
4242 var unregisterServiceCallback = function() {
4243 native.callIfPossible(args.errorCallback, AbortError);
4248 idsToRemoveFromNativeLayer: _getIncludedServicesAndItsComponentsIdsRecursively(
4254 'BluetoothGATTServerUnregisterService',
4256 unregisterServiceCallback
4260 var callback = function(result) {
4261 if (native.isFailure(result)) {
4262 native.callIfPossible(
4264 native.getErrorObjectAndValidate(
4266 BluetoothGATTServer_valid_registerService_errors,
4271 _registerReadWriteValueRequestCallbacksInGATTService(
4279 var result = native.call('BluetoothGATTServerRegisterService', service, callback);
4280 if (native.isFailure(result)) {
4281 throw native.getErrorObjectAndValidate(
4283 BluetoothGATTServer_valid_registerService_exceptions,
4289 var BluetoothGATTServer_valid_unregisterAllServices_errors = [
4290 'InvalidStateError',
4294 var BluetoothGATTServer_valid_unregisterAllServices_exceptions = [
4295 'TypeMismatchError',
4299 BluetoothGATTServer.prototype.unregisterAllServices = function() {
4300 privUtils_.log('Entered BluetoothGATTServer.unregisterAllServices()');
4301 var args = AV.validateArgs(arguments, [
4303 name: 'successCallback',
4304 type: AV.Types.FUNCTION,
4309 name: 'errorCallback',
4310 type: AV.Types.FUNCTION,
4316 var servicesToUnregister = [];
4317 for (var i = 0; i < _BluetoothGATTServerServices.length; ++i) {
4318 if (!T.isNullOrUndefined(_BluetoothGATTServerServices[i]._id)) {
4319 servicesToUnregister.push(_BluetoothGATTServerServices[i]);
4323 if (servicesToUnregister.length) {
4325 'Number of services to unregister: ' + servicesToUnregister.length
4327 var unregisterServiceCallbacksAggregator = new ResultCallbacksAggregator(
4328 servicesToUnregister.length,
4329 function onAllSucceeded() {
4330 _BluetoothGATTServerServices = [];
4331 _BluetoothGATTServerServicesRegisteredInNativeLayer = [];
4332 native.callIfPossible(args.successCallback);
4334 function onFailure(error) {
4335 native.callIfPossible(
4337 native.getErrorObjectAndValidate(
4339 BluetoothGATTServer_valid_unregisterAllServices_errors,
4346 for (var i = 0; i < servicesToUnregister.length; ++i) {
4347 var serviceIndex = _BluetoothGATTServerServices.findIndex(function(service) {
4348 return service._id === servicesToUnregister[i]._id;
4351 var serviceId = servicesToUnregister[i]._id;
4353 var unregisterServiceCallback = function(result) {
4354 if (native.isFailure(result)) {
4355 unregisterServiceCallbacksAggregator.errorCallback(
4356 native.getErrorObjectAndValidate(
4358 BluetoothGATTServer_valid_unregisterAllServices_errors,
4363 delete _BluetoothGATTServerServicesRegisteredInNativeLayer[serviceId];
4364 _BluetoothGATTServerServices.splice(serviceIndex, 1);
4365 unregisterServiceCallbacksAggregator.successCallback();
4370 _id: servicesToUnregister[i]._id,
4371 idsToRemoveFromNativeLayer: _getIncludedServicesAndItsComponentsIdsRecursively(
4372 servicesToUnregister[i]
4376 var result = native.call(
4377 'BluetoothGATTServerUnregisterService',
4379 unregisterServiceCallback
4382 if (native.isFailure(result)) {
4383 throw native.getErrorObjectAndValidate(
4385 BluetoothGATTServer_valid_unregisterAllServices_exceptions,
4392 'Nothing registered in native layer, calling BluetoothGATTServer.stop()'
4395 var callback = function(result) {
4396 if (native.isFailure(result)) {
4397 native.callIfPossible(
4399 native.getErrorObjectAndValidate(
4401 BluetoothGATTServer_valid_unregisterAllServices_errors,
4406 _BluetoothGATTServerServices = [];
4407 _BluetoothGATTServerServicesRegisteredInNativeLayer = {};
4408 native.callIfPossible(args.successCallback);
4412 var result = native.call('BluetoothGATTServerStop', {}, callback);
4413 if (native.isFailure(result)) {
4414 throw native.getErrorObjectAndValidate(
4416 BluetoothGATTServer_valid_unregisterAllServices_exceptions,
4424 * Objects of this class are used to wait for multiple callbacks results.
4426 * Its successCallback and errorCallback members should be passed as
4427 * the success and error callbacks, respectively, to the functions we wait for.
4428 * When the functions we wait for are called callbacksNum times, either
4429 * onAllSucceeded or onFailure is called, depending on whether only
4430 * successCallback was called or not.
4432 * For the usage example, take a look at BluetoothGATTServer.prototype.start,
4433 * where it's used to wait for registration of multiple services.
4435 var ResultCallbacksAggregator = function(callbacksNum, onAllSucceeded, onFailure) {
4436 var _callbacksNum = callbacksNum;
4437 var _allSucceeded = true;
4440 this.successCallback = function() {
4443 if (!_callbacksNum) {
4444 if (_allSucceeded) {
4452 this.errorCallback = function(error) {
4454 _allSucceeded = false;
4457 if (!_callbacksNum) {
4463 function _getServicesUnregisteredInNativeLayer() {
4464 var servicesUnregisteredInNativeLayer = [];
4465 for (var i = 0; i < _BluetoothGATTServerServices.length; ++i) {
4467 !_BluetoothGATTServerServicesRegisteredInNativeLayer[
4468 _BluetoothGATTServerServices[i]._id
4471 servicesUnregisteredInNativeLayer.push(_BluetoothGATTServerServices[i]);
4474 return servicesUnregisteredInNativeLayer;
4477 function _getIdsToReregisterReadWriteCallbacks(servicesUnregisteredInNativeLayer) {
4478 var idsToRegisterWriteValueCallbacks = [];
4479 var idsToRegisterReadValueCallbacks = [];
4481 for (var i = 0; i < servicesUnregisteredInNativeLayer.length; ++i) {
4482 var serviceComponentIds = _getIncludedServicesAndItsComponentsIdsRecursively(
4483 servicesUnregisteredInNativeLayer[i]
4486 for (var j = 0; j < serviceComponentIds.length; ++j) {
4487 var _id = serviceComponentIds[j];
4488 var callbackName = 'ReadValueCallback' + _id;
4491 * Only some of the serviceComponentIds are characteristics and descriptors
4492 * and within them, only some have read/write callbacks registered.
4493 * We have to check if the callbacks were registered for each id.
4495 if (callbackName in _BluetoothGATTServerReadWriteValueRequestCallbacks) {
4496 idsToRegisterReadValueCallbacks.push(_id);
4499 callbackName = 'WriteValueCallback' + _id;
4500 if (callbackName in _BluetoothGATTServerReadWriteValueRequestCallbacks) {
4501 idsToRegisterWriteValueCallbacks.push(_id);
4506 return [idsToRegisterReadValueCallbacks, idsToRegisterWriteValueCallbacks];
4509 var BluetoothGATTServer_valid_start_errors = [
4510 'InvalidStateError',
4511 'NotSupportedError',
4514 var BluetoothGATTServer_valid_start_exceptions = [
4515 'InvalidStateError',
4516 'TypeMismatchError',
4520 function _reregisterCallback(_id, nativeFunction, successCallback, errorCallback) {
4522 * This function should only be used to reregister read/write value request
4523 * callbacks in native layer for characteristics/descriptors, that have
4524 * had such callbacks registered before the last server's stop().
4525 * As JS listeners corresponding to these callbacks already exist in JS,
4526 * only C++ callbacks have to be reregistered.
4528 var callback = function(result) {
4529 if (native.isFailure(result)) {
4530 errorCallback(native.getErrorObject(result));
4536 var result = native.call(nativeFunction, { _id: _id }, callback);
4538 if (native.isFailure(result)) {
4539 throw native.getErrorObjectAndValidate(
4541 BluetoothGATTServer_valid_start_exceptions,
4547 BluetoothGATTServer.prototype.start = function() {
4548 privUtils_.log('Entered BluetoothGATTServer.start()');
4549 var args = AV.validateArgs(arguments, [
4551 name: 'successCallback',
4552 type: AV.Types.FUNCTION,
4557 name: 'errorCallback',
4558 type: AV.Types.FUNCTION,
4564 var servicesUnregisteredInNativeLayer = _getServicesUnregisteredInNativeLayer();
4566 * Characteristics and descriptors that were registered in the server before the last stop() call
4567 * could have had read/write value request callbacks registered.
4568 * These callbacks have to be reregistered (only) in native layer.
4569 * These arrays contain _ids of characteristics and descriptors, that will have their callbacks
4572 var idsToReregisterReadWriteValueCallbacks = _getIdsToReregisterReadWriteCallbacks(
4573 servicesUnregisteredInNativeLayer
4575 var idsToReregisterReadValueCallbacks = idsToReregisterReadWriteValueCallbacks[0];
4576 var idsToReregisterWriteValueCallbacks = idsToReregisterReadWriteValueCallbacks[1];
4578 var startServerCallback = function(result) {
4579 if (native.isFailure(result)) {
4580 native.callIfPossible(
4582 native.getErrorObjectAndValidate(
4584 BluetoothGATTServer_valid_start_errors,
4589 native.callIfPossible(args.successCallback);
4593 if (servicesUnregisteredInNativeLayer.length) {
4594 var numberOfCallbacksToWaitFor =
4595 servicesUnregisteredInNativeLayer.length +
4596 idsToReregisterReadValueCallbacks.length +
4597 idsToReregisterWriteValueCallbacks.length;
4598 var registerServiceCallbacksAggregator = new ResultCallbacksAggregator(
4599 numberOfCallbacksToWaitFor,
4600 function onAllSucceeded() {
4601 var result = native.call(
4602 'BluetoothGATTServerStart',
4607 if (native.isFailure(result)) {
4608 throw native.getErrorObjectAndValidate(
4610 BluetoothGATTServer_valid_start_exceptions,
4615 function onFailure(error) {
4616 native.callIfPossible(
4618 native.getErrorObjectAndValidate(
4620 BluetoothGATTServer_valid_start_errors,
4627 var registerServicesCallback = function(result) {
4628 if (native.isFailure(result)) {
4629 registerServiceCallbacksAggregator.errorCallback(result);
4631 registerServiceCallbacksAggregator.successCallback();
4635 for (var i = 0; i < servicesUnregisteredInNativeLayer.length; ++i) {
4636 var result = native.call(
4637 'BluetoothGATTServerRegisterService',
4638 servicesUnregisteredInNativeLayer[i],
4639 registerServicesCallback
4641 if (native.isFailure(result)) {
4642 throw native.getErrorObjectAndValidate(
4644 BluetoothGATTServer_valid_registerService_exceptions,
4650 for (var i = 0; i < idsToReregisterReadValueCallbacks.length; ++i) {
4651 _reregisterCallback(
4652 idsToReregisterReadValueCallbacks[i],
4653 'BluetoothGATTServerSetReadValueRequestCallback',
4654 registerServiceCallbacksAggregator.successCallback,
4655 registerServiceCallbacksAggregator.errorCallback
4659 for (var i = 0; i < idsToReregisterWriteValueCallbacks.length; ++i) {
4660 _reregisterCallback(
4661 idsToReregisterWriteValueCallbacks[i],
4662 'BluetoothGATTServerSetWriteValueRequestCallback',
4663 registerServiceCallbacksAggregator.successCallback,
4664 registerServiceCallbacksAggregator.errorCallback
4668 var result = native.call('BluetoothGATTServerStart', {}, startServerCallback);
4670 if (native.isFailure(result)) {
4671 throw native.getErrorObjectAndValidate(
4673 BluetoothGATTServer_valid_start_exceptions,
4680 var BluetoothGATTServer_valid_stop_errors = [
4681 'InvalidStateError',
4682 'NotSupportedError',
4685 var BluetoothGATTServer_valid_stop_exceptions = [
4686 'InvalidStateError',
4687 'TypeMismatchError',
4691 BluetoothGATTServer.prototype.stop = function() {
4692 privUtils_.log('Entered BluetoothGATTServer.stop()');
4693 var args = AV.validateArgs(arguments, [
4695 name: 'successCallback',
4696 type: AV.Types.FUNCTION,
4701 name: 'errorCallback',
4702 type: AV.Types.FUNCTION,
4708 var callback = function(result) {
4709 if (native.isFailure(result)) {
4710 native.callIfPossible(
4712 native.getErrorObjectAndValidate(
4714 BluetoothGATTServer_valid_stop_errors,
4719 _BluetoothGATTServerServicesRegisteredInNativeLayer = {};
4720 native.callIfPossible(args.successCallback);
4724 var result = native.call('BluetoothGATTServerStop', {}, callback);
4725 if (native.isFailure(result)) {
4726 throw native.getErrorObjectAndValidate(
4728 BluetoothGATTServer_valid_stop_exceptions,
4734 var BluetoothGATTServer_valid_getConnectionMtu_errors = [
4735 'InvalidStateError',
4736 'NotSupportedError',
4739 var BluetoothGATTServer_valid_getConnectionMtu_exceptions = [
4740 'TypeMismatchError',
4744 BluetoothGATTServer.prototype.getConnectionMtu = function() {
4745 privUtils_.log('Entered BluetoothGATTServer.getConnectionMtu()');
4746 var args = AV.validateArgs(arguments, [
4748 name: 'clientAddress',
4749 type: AV.Types.STRING
4752 name: 'successCallback',
4753 type: AV.Types.FUNCTION
4756 name: 'errorCallback',
4757 type: AV.Types.FUNCTION,
4762 var callback = function(result) {
4763 if (native.isFailure(result)) {
4764 native.callIfPossible(
4766 native.getErrorObjectAndValidate(
4768 BluetoothGATTServer_valid_getConnectionMtu_errors,
4773 args.successCallback(native.getResultObject(result));
4777 var result = native.call(
4778 'BluetoothGATTServerGetConnectionMtu',
4779 { clientAddress: args.clientAddress },
4782 if (native.isFailure(result)) {
4783 throw native.getErrorObjectAndValidate(
4785 BluetoothGATTServer_valid_getConnectionMtu_exceptions,
4791 var GATTServer = new BluetoothGATTServer();
4793 // class BluetoothManager ///////////////////////////
4794 var BluetoothManager = function() {
4795 Object.defineProperties(this, {
4797 value: new BluetoothClassDeviceMajor(),
4802 value: new BluetoothClassDeviceMinor(),
4807 value: new BluetoothClassDeviceService(),
4812 value: '00000000-0000-1000-8000-00805F9B34FB',
4819 var BluetoothManager_getDefaultAdapter = function() {
4820 privUtils_.checkPrivilegeAccess4Ver(
4822 Privilege.BLUETOOTH,
4823 Privilege.BLUETOOTH_GAP
4826 return new BluetoothAdapter();
4829 BluetoothManager.prototype.getDefaultAdapter = function() {
4830 privUtils_.log('Entered BluetoothManager.getDefaultAdapter()');
4831 return BluetoothManager_getDefaultAdapter();
4834 var BluetoothManager_getLEAdapter = function() {
4835 privUtils_.checkPrivilegeAccess4Ver(
4837 Privilege.BLUETOOTH,
4838 Privilege.BLUETOOTH_ADMIN
4841 return new BluetoothLEAdapter();
4844 BluetoothManager.prototype.getLEAdapter = function() {
4845 privUtils_.log('Entered BluetoothManager.getLEAdapter()');
4846 return BluetoothManager_getLEAdapter();
4849 var BluetoothManager_checkAndNormalizeHexString = function(hexString) {
4850 hexString = hexString.toLowerCase();
4851 if (hexString.startsWith('0x')) {
4852 hexString = hexString.substring(2);
4854 if (!/^[0-9a-f]+$/.test(hexString)) {
4855 throw new WebAPIException(
4856 WebAPIException.TYPE_MISMATCH_ERR,
4857 'Given string is not hexadecimal value'
4860 if ('0' === hexString) {
4863 if (1 === hexString.length % 2) {
4864 // to save consistency with BluetoothLEManufacturerData, last character is omitted
4865 hexString = hexString.replace(/.$/, '');
4870 var BluetoothManager_HexStringToUint8Array = function(hexString) {
4871 hexString = BluetoothManager_checkAndNormalizeHexString(hexString);
4872 if (0 === hexString.length) {
4873 return new Uint8Array([]);
4875 var data = hexString.match(/[0-9a-f]{2}/g).map(function(byte) {
4876 return parseInt(byte, 16);
4878 return new Uint8Array(data);
4881 var BluetoothManager_byteArrayToHexString = function(bytes) {
4882 if (0 == bytes.length) {
4888 .call(bytes, function(byte) {
4889 return ('0' + (byte & 0xff).toString(16)).slice(-2);
4895 var BluetoothManager_toByteArray = function(data) {
4896 if (data && String === data.constructor) {
4897 return numberArrayToByteArray(BluetoothManager_HexStringToUint8Array(data));
4900 data = numberArrayToByteArray(data);
4902 throw new WebAPIException(
4903 WebAPIException.TYPE_MISMATCH_ERR,
4904 'argument is not a valid Bytes type'
4911 BluetoothManager.prototype.toByteArray = function(data) {
4912 privUtils_.log('Entered BluetoothManager.toByteArray()');
4913 return BluetoothManager_toByteArray(data);
4916 var BluetoothManager_toDOMString = function(data) {
4917 if (data && String === data.constructor) {
4918 data = BluetoothManager_checkAndNormalizeHexString(data);
4919 if (0 !== data.length) {
4925 data = numberArrayToByteArray(data);
4927 throw new WebAPIException(
4928 WebAPIException.TYPE_MISMATCH_ERR,
4929 'argument is not a valid Bytes type'
4932 return BluetoothManager_byteArrayToHexString(data);
4935 BluetoothManager.prototype.toDOMString = function(data) {
4936 privUtils_.log('Entered BluetoothManager.toDOMString()');
4937 return BluetoothManager_toDOMString(data);
4940 var BluetoothManager_toUint8Array = function(data) {
4941 if (data && String === data.constructor) {
4942 return BluetoothManager_HexStringToUint8Array(data);
4945 data = new Uint8Array(numberArrayToByteArray(data));
4947 throw new WebAPIException(
4948 WebAPIException.TYPE_MISMATCH_ERR,
4949 'argument is not a valid Bytes type'
4956 BluetoothManager.prototype.toUint8Array = function(data) {
4957 privUtils_.log('Entered BluetoothManager.toUint8Array()');
4958 return BluetoothManager_toUint8Array(data);
4961 var BluetoothManager_UUIDIsValid128Bit = function(uuid) {
4962 var re128BitFormat = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
4963 if (re128BitFormat.test(uuid)) {
4969 var BluetoothManager_UUIDIsValid32Bit = function(uuid) {
4970 var re32BitFormat = /^[0-9a-f]{8}$/;
4971 if (re32BitFormat.test(uuid)) {
4977 var BluetoothManager_UUIDIsValid16Bit = function(uuid) {
4978 var re16BitFormat = /^[0-9a-f]{4}$/;
4979 if (re16BitFormat.test(uuid)) {
4985 var BluetoothManager_UUIDIsConvertibleTo16Bit = function(uuid) {
4986 var re128BitFormat = /^0000[0-9a-f]{4}-0000-1000-8000-00805f9b34fb$/;
4987 if (re128BitFormat.test(uuid)) {
4990 var re32BitFormat = /^0000[0-9a-f]{4}$/;
4991 if (re32BitFormat.test(uuid)) {
4997 var BluetoothManager_UUIDIsConvertibleTo32Bit = function(uuid) {
4998 var re = /^[0-9a-f]{8}-0000-1000-8000-00805f9b34fb$/;
4999 if (re.test(uuid)) {
5005 var BluetoothManager_UUIDTo128bit = function(uuid) {
5006 uuid = Converter.toString(uuid).toLowerCase();
5007 if (BluetoothManager_UUIDIsValid128Bit(uuid)) {
5010 var baseUuidLast96Bits = '-0000-1000-8000-00805f9b34fb';
5011 if (BluetoothManager_UUIDIsValid16Bit(uuid)) {
5012 return '0000' + uuid + baseUuidLast96Bits;
5014 if (BluetoothManager_UUIDIsValid32Bit(uuid)) {
5015 return uuid + baseUuidLast96Bits;
5017 throw new WebAPIException(
5018 WebAPIException.INVALID_VALUES_ERR,
5019 'Given parameter is not a supported uuid format: ' + uuid
5023 var BluetoothManager_UUIDToShortestPossible = function(uuid) {
5024 uuid = uuid.toLowerCase();
5025 if (BluetoothManager_UUIDIsValid16Bit(uuid)) {
5028 if (BluetoothManager_UUIDIsValid32Bit(uuid)) {
5029 if (BluetoothManager_UUIDIsConvertibleTo16Bit(uuid)) {
5030 return uuid.substring(4, 8);
5033 if (!BluetoothManager_UUIDIsValid128Bit(uuid)) {
5034 throw new WebAPIException(
5035 WebAPIException.INVALID_VALUES_ERR,
5036 'Given parameter is not a supported uuid format: ' + uuid
5039 if (BluetoothManager_UUIDIsConvertibleTo16Bit(uuid)) {
5040 return uuid.substring(4, 8);
5042 if (BluetoothManager_UUIDIsConvertibleTo32Bit(uuid)) {
5043 return uuid.substring(0, 8);
5048 var BluetoothManager_UUIDsEqual = function(uuid1, uuid2) {
5049 uuid1 = Converter.toString(uuid1).toLowerCase();
5050 uuid1 = BluetoothManager_UUIDTo128bit(uuid1);
5051 uuid2 = Converter.toString(uuid2).toLowerCase();
5052 uuid2 = BluetoothManager_UUIDTo128bit(uuid2);
5053 return uuid1 === uuid2;
5056 BluetoothManager.prototype.uuidTo128bit = function(uuid) {
5057 privUtils_.log('Entered BluetoothManager.uuidTo128bit()');
5058 var args = AV.validateArgs(arguments, [
5061 type: AV.Types.STRING
5064 return BluetoothManager_UUIDTo128bit(args.uuid);
5067 BluetoothManager.prototype.uuidToShortestPossible = function(uuid) {
5068 privUtils_.log('Entered BluetoothManager.uuidToShortestPossible()');
5069 var args = AV.validateArgs(arguments, [
5072 type: AV.Types.STRING
5075 return BluetoothManager_UUIDToShortestPossible(args.uuid);
5078 BluetoothManager.prototype.uuidsEqual = function(uuid1, uuid2) {
5079 privUtils_.log('Entered BluetoothManager.uuidsEqual()');
5080 var args = AV.validateArgs(arguments, [
5083 type: AV.Types.STRING
5087 type: AV.Types.STRING
5090 return BluetoothManager_UUIDsEqual(args.uuid1, args.uuid2);
5092 BluetoothManager.prototype.getGATTServer = function() {
5093 privUtils_.log('Entered BluetoothManager.getGATTServer()');
5094 return BluetoothManager_getGATTServer();
5097 var BluetoothManager_getGATTServer = function() {
5101 // exports //////////////////////////////////////////
5102 exports = new BluetoothManager();