UNPKG

nativescript-akylas-bluetooth

Version:

Connect to and interact with Bluetooth LE peripherals

587 lines 23.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var common_1 = require("../common"); var CBCentralManagerDelegateImpl_1 = require("./CBCentralManagerDelegateImpl"); function toArrayBuffer(value) { if (value === null) { return null; } return interop.bufferFromData(value); } exports.toArrayBuffer = toArrayBuffer; function CBUUIDToString(uuid) { return uuid.toString().toLowerCase(); } exports.CBUUIDToString = CBUUIDToString; var Bluetooth = (function (_super) { __extends(Bluetooth, _super); function Bluetooth(restoreIdentifier) { var _this = _super.call(this) || this; _this._centralDelegate = CBCentralManagerDelegateImpl_1.CBCentralManagerDelegateImpl.new().initWithCallback(new WeakRef(_this), function (obj) { common_1.CLog(common_1.CLogTypes.info, "---- centralDelegate ---- obj: " + obj); }); _this._discoverPeripherals = {}; _this._connectedPeripherals = {}; _this._connectCallbacks = {}; _this._advData = {}; _this._disconnectCallbacks = {}; _this._onDiscovered = null; _this.findPeripheral = function (UUID) { var result = _this._connectedPeripherals[UUID] || _this._discoverPeripherals[UUID]; if (!result) { var periphs = _this._centralManager.retrievePeripheralsWithIdentifiers([NSUUID.alloc().initWithUUIDString(UUID)]); if (periphs.count > 0) { result = periphs.objectAtIndex(0); } } return result; }; _this.adddDiscoverPeripheral = function (peripheral) { var UUID = peripheral.identifier.UUIDString; if (!_this._discoverPeripherals[UUID]) { _this._discoverPeripherals[UUID] = peripheral; } }; _this.findDiscoverPeripheral = function (UUID) { var result = _this._discoverPeripherals[UUID]; if (!result) { var periphs = _this._centralManager.retrievePeripheralsWithIdentifiers([NSUUID.alloc().initWithUUIDString(UUID)]); if (periphs.count > 0) { result = periphs.objectAtIndex(0); } } return result; }; var options = null; if (restoreIdentifier) { options = new NSDictionary([restoreIdentifier], [CBCentralManagerOptionRestoreIdentifierKey]); } _this._centralManager = CBCentralManager.alloc().initWithDelegateQueueOptions(_this._centralDelegate, null, options); common_1.CLog(common_1.CLogTypes.info, '*** iOS Bluetooth Constructor *** ${restoreIdentifier}'); common_1.CLog(common_1.CLogTypes.info, "this._centralManager: " + _this._centralManager); return _this; } Object.defineProperty(Bluetooth.prototype, "enabled", { get: function () { var state = this._centralManager.state; if (state === 5) { return true; } else { return false; } }, enumerable: true, configurable: true }); Bluetooth.prototype._getState = function (state) { if (state === 1) { return 'connecting'; } else if (state === 2) { return 'connected'; } else if (state === 0) { return 'disconnected'; } else { common_1.CLog(common_1.CLogTypes.warning, '_getState ---- Unexpected state, returning "disconnected" for state of', state); return 'disconnected'; } }; Bluetooth.prototype.onPeripheralDisconnected = function (peripheral) { var UUID = peripheral.identifier.UUIDString; delete this._connectedPeripherals[UUID]; }; Bluetooth.prototype.onPeripheralConnected = function (peripheral) { var UUID = peripheral.identifier.UUIDString; this._connectedPeripherals[UUID] = peripheral; }; Bluetooth.prototype.isBluetoothEnabled = function () { var _this = this; return new Promise(function (resolve, reject) { try { var isEnabled = _this._isEnabled(); resolve(isEnabled); } catch (ex) { common_1.CLog(common_1.CLogTypes.error, 'isBluetoothEnabled ----', ex); reject(ex); } }); }; Bluetooth.prototype.startScanning = function (arg) { var _this = this; return new Promise(function (resolve, reject) { try { if (!_this._isEnabled()) { common_1.CLog(common_1.CLogTypes.info, 'startScanning ---- Bluetooth is not enabled.'); reject('Bluetooth is not enabled.'); return; } _this._discoverPeripherals = {}; _this._onDiscovered = arg.onDiscovered; var services_1 = null; if (arg.filters) { services_1 = []; arg.filters.forEach(function (f) { if (f.serviceUUID) { services_1.push(CBUUID.UUIDWithString(f.serviceUUID)); } }); } common_1.CLog(common_1.CLogTypes.info, 'startScanning ---- services:', services_1); _this._centralManager.scanForPeripheralsWithServicesOptions(services_1, null); if (_this.scanningReferTimer) { clearTimeout(_this.scanningReferTimer.timer); _this.scanningReferTimer.resolve(); } _this.scanningReferTimer = {}; if (arg.seconds) { _this.scanningReferTimer.timer = setTimeout(function () { _this._centralManager.stopScan(); resolve(); }, arg.seconds * 1000); _this.scanningReferTimer.resolve = resolve; } else { resolve(); } } catch (ex) { common_1.CLog(common_1.CLogTypes.error, 'startScanning ---- error:', ex); reject(ex); } }); }; Bluetooth.prototype.enable = function () { var _this = this; return new Promise(function (resolve, reject) { common_1.CLog(common_1.CLogTypes.info, 'enable ---- Not possible on iOS'); resolve(_this._isEnabled()); }); }; Bluetooth.prototype.isGPSEnabled = function () { return Promise.resolve(true); }; Bluetooth.prototype.enableGPS = function () { return Promise.resolve(); }; Bluetooth.prototype.openBluetoothSettings = function (url) { console.log('openBluetoothSettings', this._isEnabled()); if (!this._isEnabled()) { return Promise.resolve().then(function () { var settingsUrl = NSURL.URLWithString(url || 'App-prefs:root=General&path=BLUETOOTH'); console.log('openBluetoothSettings url ', settingsUrl.absoluteString, UIApplication.sharedApplication.canOpenURL(settingsUrl)); if (UIApplication.sharedApplication.canOpenURL(settingsUrl)) { UIApplication.sharedApplication.openURLOptionsCompletionHandler(settingsUrl, null, function (success) { if (success) { return Promise.reject(undefined); } else { return Promise.reject('cant_open_settings'); } }); } }); } return Promise.resolve(); }; Bluetooth.prototype.stopScanning = function (arg) { var _this = this; return new Promise(function (resolve, reject) { try { if (!_this._isEnabled()) { reject('Bluetooth is not enabled.'); return; } _this._centralManager.stopScan(); if (_this.scanningReferTimer) { _this.scanningReferTimer.resolve && _this.scanningReferTimer.resolve(); clearTimeout(_this.scanningReferTimer.timer); _this.scanningReferTimer = null; } resolve(); } catch (ex) { common_1.CLog(common_1.CLogTypes.error, 'stopScanning ---- error:', ex); reject(ex); } }); }; Bluetooth.prototype.connect = function (args) { var _this = this; return new Promise(function (resolve, reject) { try { if (!_this._isEnabled()) { reject('Bluetooth is not enabled.'); return; } if (!args.UUID) { reject('No UUID was passed'); return; } common_1.CLog(common_1.CLogTypes.info, 'connect ----', args.UUID); var peripheral = _this.findDiscoverPeripheral(args.UUID); common_1.CLog(common_1.CLogTypes.info, 'connect ---- peripheral found', peripheral); if (!peripheral) { reject("Could not find peripheral with UUID: " + args.UUID); } else { common_1.CLog(common_1.CLogTypes.info, 'connect ---- Connecting to peripheral with UUID:', args.UUID); _this._connectCallbacks[args.UUID] = args.onConnected; _this._disconnectCallbacks[args.UUID] = args.onDisconnected; _this._centralManager.connectPeripheralOptions(peripheral, null); resolve(); } } catch (ex) { common_1.CLog(common_1.CLogTypes.error, 'connect ---- error:', ex); reject(ex); } }); }; Bluetooth.prototype.disconnect = function (arg) { var _this = this; return new Promise(function (resolve, reject) { try { if (!_this._isEnabled()) { reject('Bluetooth is not enabled'); return; } if (!arg.UUID) { reject('No UUID was passed'); return; } var peripheral = _this.findPeripheral(arg.UUID); if (!peripheral) { reject('Could not find peripheral with UUID ' + arg.UUID); } else { common_1.CLog(common_1.CLogTypes.info, 'disconnect ---- Disconnecting peripheral with UUID', arg.UUID); if (peripheral.state !== 0) { _this._centralManager.cancelPeripheralConnection(peripheral); } resolve(); } } catch (ex) { common_1.CLog(common_1.CLogTypes.error, 'disconnect ---- error:', ex); reject(ex); } }); }; Bluetooth.prototype.isConnected = function (arg) { var _this = this; return new Promise(function (resolve, reject) { try { if (!_this._isEnabled()) { reject('Bluetooth is not enabled'); return; } if (!arg.UUID) { reject('No UUID was passed'); return; } var peripheral = _this.findPeripheral(arg.UUID); if (peripheral === null) { reject('Could not find peripheral with UUID ' + arg.UUID); } else { common_1.CLog(common_1.CLogTypes.info, 'isConnected ---- checking connection with peripheral UUID:', arg.UUID); resolve(peripheral.state === 2); } } catch (ex) { common_1.CLog(common_1.CLogTypes.error, 'isConnected ---- error:', ex); reject(ex); } }); }; Bluetooth.prototype.read = function (arg) { var _this = this; return new Promise(function (resolve, reject) { try { var wrapper = _this._getWrapper(arg, 2, reject); if (!wrapper) { return; } wrapper.peripheral.delegate._onReadPromise = resolve; wrapper.peripheral.readValueForCharacteristic(wrapper.characteristic); } catch (ex) { common_1.CLog(common_1.CLogTypes.error, 'read ---- error:', ex); reject(ex); } }); }; Bluetooth.prototype.write = function (arg) { var _this = this; return new Promise(function (resolve, reject) { try { if (!arg.value) { reject("You need to provide some data to write in the 'value' property."); return; } var wrapper = _this._getWrapper(arg, 8, reject); if (!wrapper) { return; } var valueEncoded = _this.valueToNSData(arg.value, arg.encoding); if (common_1.BluetoothUtil.debug) { common_1.CLog(common_1.CLogTypes.info, 'write:', arg.value); } if (valueEncoded === null) { reject('Invalid value: ' + arg.value); return; } wrapper.peripheral.delegate._onWritePromise = resolve; wrapper.peripheral.writeValueForCharacteristicType(valueEncoded, wrapper.characteristic, 0); if (common_1.BluetoothUtil.debug) { common_1.CLog(common_1.CLogTypes.info, 'write:', arg.value, JSON.stringify(_this.valueToString(valueEncoded))); } } catch (ex) { common_1.CLog(common_1.CLogTypes.error, 'write ---- error:', ex); reject(ex); } }); }; Bluetooth.prototype.writeWithoutResponse = function (arg) { var _this = this; return new Promise(function (resolve, reject) { try { if (!arg.value) { reject("You need to provide some data to write in the 'value' property"); return; } var wrapper = _this._getWrapper(arg, 4, reject); if (!wrapper) { return; } var valueEncoded = _this.valueToNSData(arg.value, arg.encoding); if (valueEncoded === null) { reject('Invalid value: ' + arg.value); return; } wrapper.peripheral.writeValueForCharacteristicType(valueEncoded, wrapper.characteristic, 1); if (common_1.BluetoothUtil.debug) { common_1.CLog(common_1.CLogTypes.info, 'writeWithoutResponse:', arg.value, JSON.stringify(_this.valueToString(valueEncoded))); } resolve(); } catch (ex) { common_1.CLog(common_1.CLogTypes.error, 'writeWithoutResponse ---- error:', ex); reject(ex); } }); }; Bluetooth.prototype.startNotifying = function (args) { var _this = this; return new Promise(function (resolve, reject) { try { var wrapper = _this._getWrapper(args, 16, reject); common_1.CLog(common_1.CLogTypes.info, 'startNotifying ---- wrapper:', wrapper); if (!wrapper) { return; } var cb = args.onNotify || function (result) { common_1.CLog(common_1.CLogTypes.info, 'startNotifying ---- No "onNotify" callback function specified for "startNotifying()"'); }; wrapper.peripheral.delegate._onNotifyCallback = cb; wrapper.peripheral.setNotifyValueForCharacteristic(true, wrapper.characteristic); resolve(); } catch (ex) { common_1.CLog(common_1.CLogTypes.error, 'startNotifying ---- error:', ex); reject(ex); } }); }; Bluetooth.prototype.stopNotifying = function (args) { var _this = this; return new Promise(function (resolve, reject) { try { var wrapper = _this._getWrapper(args, 16, reject); common_1.CLog(common_1.CLogTypes.info, 'stopNotifying ---- wrapper:', wrapper); if (wrapper === null) { return; } var peripheral = _this.findPeripheral(args.peripheralUUID); peripheral.setNotifyValueForCharacteristic(false, wrapper.characteristic); resolve(); } catch (ex) { common_1.CLog(common_1.CLogTypes.error, 'stopNotifying ---- error:', ex); reject(ex); } }); }; Bluetooth.prototype._isEnabled = function () { var state = this._centralManager.state; return state === 5; }; Bluetooth.prototype._stringToUuid = function (uuidStr) { if (uuidStr.length === 4) { uuidStr = "0000" + uuidStr + "-0000-1000-8000-00805f9b34fb"; } return CFUUIDCreateFromString(null, uuidStr); }; Bluetooth.prototype._findService = function (UUID, peripheral) { for (var i = 0; i < peripheral.services.count; i++) { var service = peripheral.services.objectAtIndex(i); if (UUID.isEqual(service.UUID)) { return service; } } return null; }; Bluetooth.prototype._findCharacteristic = function (UUID, service, property) { for (var i = 0; i < service.characteristics.count; i++) { var characteristic = service.characteristics.objectAtIndex(i); if (UUID.isEqual(characteristic.UUID)) { if (property && characteristic.properties) { if (property === property) { return characteristic; } } else { return characteristic; } } } return null; }; Bluetooth.prototype._getWrapper = function (arg, property, reject) { if (!this._isEnabled()) { reject('Bluetooth is not enabled'); return null; } if (!arg.peripheralUUID) { reject('No peripheralUUID was passed'); return null; } if (!arg.serviceUUID) { reject('No serviceUUID was passed'); return null; } if (!arg.characteristicUUID) { reject('No characteristicUUID was passed'); return null; } var peripheral = this.findPeripheral(arg.peripheralUUID); if (!peripheral) { reject('Could not find peripheral with UUID ' + arg.peripheralUUID); return null; } if (peripheral.state !== 2) { reject('The peripheral is disconnected'); return null; } var serviceUUID = CBUUID.UUIDWithString(arg.serviceUUID); var service = this._findService(serviceUUID, peripheral); if (!service) { reject("Could not find service with UUID " + arg.serviceUUID + " on peripheral with UUID " + arg.peripheralUUID); return null; } var characteristicUUID = CBUUID.UUIDWithString(arg.characteristicUUID); var characteristic = this._findCharacteristic(characteristicUUID, service, property); if (property === 16 && !characteristic) { characteristic = this._findCharacteristic(characteristicUUID, service, 32); } if (!characteristic) { characteristic = this._findCharacteristic(characteristicUUID, service, null); } if (!characteristic) { reject("Could not find characteristic with UUID " + arg.characteristicUUID + " on service with UUID " + arg.serviceUUID + " on peripheral with UUID " + arg.peripheralUUID); return null; } return { peripheral: peripheral, service: service, characteristic: characteristic }; }; Bluetooth.prototype._encodeValue = function (value) { if (typeof value !== 'string') { return value.buffer; } var parts = value.split(','); if (parts[0].indexOf('x') === -1) { return null; } var result; if (parts[0].length === 4) { result = new Uint8Array(parts.length); } else { result = new Uint16Array(parts.length); } for (var i = 0; i < parts.length; i++) { result[i] = parts[i]; } return result.buffer; }; Bluetooth.prototype.nativeEncoding = function (encoding) { switch (encoding) { case 'utf-8': return NSUTF8StringEncoding; case 'latin2': case 'iso-8859-2': return NSISOLatin2StringEncoding; case 'shift-jis': return NSShiftJISStringEncoding; case 'iso-2022-jp': return NSISO2022JPStringEncoding; case 'euc-jp': return NSJapaneseEUCStringEncoding; case 'windows-1250': return NSWindowsCP1250StringEncoding; case 'windows-1251': return NSWindowsCP1251StringEncoding; case 'windows-1252': return NSWindowsCP1252StringEncoding; case 'windows-1253': return NSWindowsCP1253StringEncoding; case 'windows-1254': return NSWindowsCP1254StringEncoding; case 'utf-16be': return NSUTF16BigEndianStringEncoding; case 'utf-16le': return NSUTF16LittleEndianStringEncoding; default: case 'iso-8859-1': case 'latin1': return NSISOLatin1StringEncoding; } }; Bluetooth.prototype.valueToNSData = function (value, encoding) { if (encoding === void 0) { encoding = 'iso-8859-1'; } if (typeof value === 'string') { return NSString.stringWithString(value).dataUsingEncoding(this.nativeEncoding(encoding)); } else if (Array.isArray(value)) { var intRef = new interop.Reference(interop.types.int8, interop.alloc(value.length)); for (var i = 0; i < value.length; i++) { intRef[i] = value[i]; } return NSData.dataWithBytesLength(intRef, value.length); } else { return null; } }; Bluetooth.prototype.valueToString = function (value) { if (value instanceof NSData) { var data = new Uint8Array(interop.bufferFromData(value)); var result_1 = []; data.forEach(function (v, i) { return (result_1[i] = v); }); return result_1; } return value; }; return Bluetooth; }(common_1.BluetoothCommon)); exports.Bluetooth = Bluetooth; //# sourceMappingURL=ios_main.js.map