nativescript-akylas-bluetooth
Version:
Connect to and interact with Bluetooth LE peripherals
587 lines • 23.8 kB
JavaScript
"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