Socket
Socket
Sign inDemoInstall

cordova-plugin-ble-central

Package Overview
Dependencies
0
Maintainers
2
Versions
58
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.4.4 to 1.5.0

cordova-plugin-ble-central.iml

5

CHANGES.txt

@@ -0,1 +1,6 @@

= 1.5.0 =
Android: Add support for target SDK version 31 (Android 12) #923 #879 #875 Thanks LDLCLid3
Add L2CAP support (minimum iOS 11 & Android 10 required) for connection-oriented Bluetooth streams #812
Add ble.withPromises.startNotification variant to indicate when notifications are successfully subscribed #903 #95
= 1.4.4 =

@@ -2,0 +7,0 @@ Browser: Add support via navigator.Bluetooth #907 #231 Thanks joeferner

168

hooks/after_prepare.js
#!/usr/bin/env node
'use strict';
var fs = require('fs');
const fs = require('fs');
const path = require('path');
var ACCESS_BACKGROUND_LOCATION_PERMISSION =
'<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />';
module.exports = function (context) {
const { projectRoot, plugin } = context.opts;
const { ConfigParser } = context.requireCordovaModule('cordova-common');
module.exports = function (context) {
const accessBackgroundLocationVariable = getAccessBackgroundLocationVariable();
const manifestPath = getAndroidManifestFilePath(context);
const androidManifest = fs.readFileSync(manifestPath).toString();
if (accessBackgroundLocationVariable === 'true') {
if (!accessBackgroundLocationExists(androidManifest)) {
addAccessBackgroundLocationToManifest(manifestPath, androidManifest);
console.log(context.opts.plugin.id + ': ACCESS_BACKGROUND_LOCATION permission added to ' + manifestPath);
} else {
console.log(
context.opts.plugin.id + ': ACCESS_BACKGROUND_LOCATION permission already exists in ' + manifestPath
);
}
} else {
if (accessBackgroundLocationExists(androidManifest)) {
removeAccessBackgroundLocationToManifest(manifestPath, androidManifest);
console.log(
context.opts.plugin.id + ': ACCESS_BACKGROUND_LOCATION permission removed from ' + manifestPath
);
} else {
console.log(
context.opts.plugin.id + ': ACCESS_BACKGROUND_LOCATION permission does not exists in ' + manifestPath
);
}
const platformPath = path.resolve(projectRoot, 'platforms/android');
const config = new ConfigParser(path.resolve(platformPath, 'app/src/main/res/xml/config.xml'));
const accessBackgroundLocation = config.getPreference('accessBackgroundLocation', 'android');
const targetSdkVersion = getTargetSdkVersion(platformPath);
if (!targetSdkVersion) {
console.log(plugin.id + ': WARNING - unable to find Android SDK version');
}
};
var getAccessBackgroundLocationVariable = function () {
if (process.argv.join('|').indexOf('ACCESS_BACKGROUND_LOCATION=') > -1) {
return process.argv.join('|').match(/ACCESS_BACKGROUND_LOCATION=(.*?)(\||$)/)[1];
} else {
return getPreferenceValue('ACCESS_BACKGROUND_LOCATION');
const manifestPath = path.resolve(platformPath, 'app/src/main/AndroidManifest.xml');
if (!fs.existsSync(manifestPath)) {
throw "Can't find AndroidManifest.xml in platforms/Android";
}
};
var getPreferenceValue = function (name) {
const config = fs.readFileSync('config.xml').toString();
var preferenceValue = getPreferenceValueFromConfig(config, name);
if (!preferenceValue) {
const packageJson = fs.readFileSync('package.json').toString();
preferenceValue = getPreferenceValueFromPackageJson(packageJson, name);
let manifestChanged = false;
let androidManifest = fs.readFileSync(manifestPath).toString();
if (accessBackgroundLocation != 'true') {
androidManifest = stripPermission(androidManifest, 'ACCESS_BACKGROUND_LOCATION');
manifestChanged = true;
}
return preferenceValue;
};
var getPreferenceValueFromConfig = function (config, name) {
const value = config.match(new RegExp('name="' + name + '" value="(.*?)"', 'i'));
if (value && value[1]) {
return value[1];
} else {
return null;
if (targetSdkVersion <= 30) {
// Strip out Android 12+ changes
androidManifest = stripPermission(androidManifest, 'BLUETOOTH_SCAN');
androidManifest = stripPermission(androidManifest, 'BLUETOOTH_CONNECT');
androidManifest = stripMaxSdkVersion(androidManifest, '30');
manifestChanged = true;
}
};
var getPreferenceValueFromPackageJson = function (packageJson, name) {
const value = packageJson.match(new RegExp('"' + name + '":\\s"(.*?)"', 'i'));
if (value && value[1]) {
return value[1];
} else {
return null;
if (targetSdkVersion <= 28) {
// Strip out Android 10+ changes
androidManifest = stripPermission(androidManifest, 'ACCESS_FINE_LOCATION');
androidManifest = stripPermission(androidManifest, 'ACCESS_BACKGROUND_LOCATION');
androidManifest = stripMaxSdkVersion(androidManifest, '28');
manifestChanged = true;
}
};
var getAndroidManifestFilePath = function (context) {
const manifestPath = {
cordovaAndroid6: context.opts.projectRoot + '/platforms/android/AndroidManifest.xml',
cordovaAndroid7: context.opts.projectRoot + '/platforms/android/app/src/main/AndroidManifest.xml',
};
if (fs.existsSync(manifestPath.cordovaAndroid7)) {
return manifestPath.cordovaAndroid7;
} else if (fs.existsSync(manifestPath.cordovaAndroid6)) {
return manifestPath.cordovaAndroid6;
} else {
throw "Can't find AndroidManifest.xml in platforms/Android";
if (manifestChanged) {
fs.writeFileSync(manifestPath, androidManifest);
}
checkForDuplicatePermissions(plugin, androidManifest);
};
var accessBackgroundLocationExists = function (manifest) {
const value = manifest.search(ACCESS_BACKGROUND_LOCATION_PERMISSION);
if (value === -1) {
return false;
} else {
return true;
function checkForDuplicatePermissions(plugin, androidManifest) {
const permissionsRegex = /<uses-permission.*?android:name="(?<permission>android\.permission\..*?)".*?\/>/gm;
const permissions = {};
let capture;
while ((capture = permissionsRegex.exec(androidManifest)) !== null) {
const permission = capture.groups && capture.groups.permission;
if (permission && permissions[permission]) {
console.log(plugin.id + ': !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!');
console.log(plugin.id + ': WARNING - duplicate android permissions found: ' + permission);
console.log(plugin.id + ': See https://github.com/don/cordova-plugin-ble-central/issues/925');
console.log(plugin.id + ': !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!');
break;
}
permissions[permission] = true;
}
};
}
var addAccessBackgroundLocationToManifest = function (manifestPath, androidManifest) {
const index = androidManifest.search('</manifest>');
const accessBackgroundLocationPermissionLine = ' ' + ACCESS_BACKGROUND_LOCATION_PERMISSION + '\n';
const updatedManifest =
androidManifest.substring(0, index) + accessBackgroundLocationPermissionLine + androidManifest.substring(index);
fs.writeFileSync(manifestPath, updatedManifest);
};
function getTargetSdkVersion(platformPath) {
let sdkVersion;
const gradleConfigJson = path.resolve(platformPath, 'cdv-gradle-config.json');
const gradleConfigProperties = path.resolve(platformPath, 'gradle.properties');
var removeAccessBackgroundLocationToManifest = function (manifestPath, androidManifest) {
const accessBackgroundLocationPermissionLine = ' ' + ACCESS_BACKGROUND_LOCATION_PERMISSION + '\n';
const updatedManifest = androidManifest.replace(accessBackgroundLocationPermissionLine, '');
fs.writeFileSync(manifestPath, updatedManifest);
};
if (fs.existsSync(gradleConfigJson)) {
const gradleConfig = JSON.parse(fs.readFileSync(gradleConfigJson).toString());
sdkVersion = gradleConfig.SDK_VERSION;
} else if (fs.existsSync(gradleConfigProperties)) {
const gradleConfig = fs.readFileSync(gradleConfigProperties).toString();
sdkVersion = gradleConfig
.split('\n')
.map((l) => l.split('='))
.filter(([key]) => key == 'cdvTargetSdkVersion')
.map(([_, value]) => value);
}
return Number(sdkVersion || 0);
}
function stripPermission(androidManifest, permission) {
const replacer = new RegExp(
'\\n\\s*?<uses-permission.*? android:name="android\\.permission\\.' + permission + '".*?\\/>\\n',
'gm'
);
return androidManifest.replace(replacer, '\n');
}
function stripMaxSdkVersion(androidManifest, level) {
const replacer = new RegExp('\\s*android:maxSdkVersion="' + level + '"\\s*', 'g');
return androidManifest.replace(replacer, ' ');
}
{
"name": "cordova-plugin-ble-central",
"version": "1.4.4",
"version": "1.5.0",
"description": "Bluetooth Low Energy (BLE) Central Plugin",

@@ -10,2 +10,3 @@ "cordova": {

"android",
"browser",
"wp8"

@@ -12,0 +13,0 @@ ]

# Bluetooth Low Energy (BLE) Central Plugin for Apache Cordova
[![npm version](https://img.shields.io/npm/v/cordova-plugin-ble-central.svg?style=flat)](https://www.npmjs.com/package/cordova-plugin-ble-central)
This plugin enables communication between a phone and Bluetooth Low Energy (BLE) peripherals.

@@ -27,3 +29,3 @@

- iOS
- Android (4.3 or greater)
- Android (likely supports 6+, but 8.1 or greater recommended)
- Browser (where navigator.bluetooth is supported)

@@ -37,19 +39,8 @@

### PhoneGap
It's recommended to always use the latest cordova and cordova platform packages in order to enusre correct function. This plugin generally best supports the following platforms and version ranges:
$ phonegap plugin add cordova-plugin-ble-central
| cordova | cordova-ios | cordova-android | cordova-browser |
| ------- | ----------- | --------------- | --------------- |
| 9+ | 6.2.0+ | 9.1.0+ | not tested |
### PhoneGap Build
Edit config.xml to install the plugin for [PhoneGap Build](http://build.phonegap.com).
<gap:plugin name="cordova-plugin-ble-central" source="npm" />
<preference name="phonegap-version" value="cli-6.1.0" />
### PhoneGap Developer App
This plugin is included in iOS and Android versions of the [PhoneGap Developer App](http://app.phonegap.com/).
Note that this plugin's id changed from `com.megster.cordova.ble` to `cordova-plugin-ble-central` as part of the migration from the [Cordova plugin repo](http://plugins.cordova.io/) to [npm](https://www.npmjs.com/).
### iOS

@@ -75,6 +66,8 @@

If your app targets Android 10 (API level 29) or higher, you have also the option of requesting the ACCESS_BACKGROUND_LOCATION permission. If your app has a feature that requires it, set `ACCESS_BACKGROUND_LOCATION ` to true when installing.
If your app targets Android 10 (API level 29) or higher, you may need the ACCESS_BACKGROUND_LOCATION permission on Android 10 & Android 11 in order for scanning to function when your app is not visible. To enable this permission and feature, set `ACCESS_BACKGROUND_LOCATION ` to true when installing:
--variable ACCESS_BACKGROUND_LOCATION=true
For the best understanding about which permissions are needed for which combinations of target SDK version & OS version, see [Android Bluetooth permissions](https://developer.android.com/guide/topics/connectivity/bluetooth/permissions)
# API

@@ -114,2 +107,6 @@

- [ble.bondedDevices](#bondeddevices)
- [ble.l2cap.open](#l2capopen)
- [ble.l2cap.close](#l2capclose)
- [ble.l2cap.receiveData](#l2capreceivedata)
- [ble.l2cap.write](#l2capwrite)

@@ -962,2 +959,110 @@ ## scan

## l2cap.open
Open an L2CAP channel with a connected peripheral. The PSM is assigned by the peripheral, or possibly defined by the Bluetooth standard.
ble.l2cap.open(device_id, psm, connectCallback, disconnectCallback);
Using await with promises
await ble.withPromises.l2cap.open(device_id, psm, disconnectCallback);
Android supports additional arguments in the psm flag to select whether the L2CAP channel is insecure or secure (iOS does this automatically):
ble.l2cap.open(device_id, { psm: psm, secureChannel: true }, connectCallback, disconnectCallback);
// or with promises
await ble.withPromises.l2cap.open(device_id, { psm: psm, secureChannel: true }, disconnectCallback);
### Description
An L2CAP channel is a duplex byte stream interface (similar to a network socket) that can be used for much more efficient binary data transfer. This is used in some streaming applications, such as the Bluetooth Object Transfer Service.
The PSM (protocol/service multiplexer) is specified by the peripheral when it opens the channel. Some channels have predefined identifiers controlled by [Bluetooth organisation](https://www.bluetooth.com/specifications/assigned-numbers/logical-link-control/). Apple has also outlined a [generic design](https://developer.apple.com/documentation/corebluetooth/cbuuidl2cappsmcharacteristicstring) for PSM exchange. To advertise an L2CAP channel on a specific service, a characteristic with the UUID "ABDD3056-28FA-441D-A470-55A75A52553A" is added to that service, and updated by the peripheral when the L2CAP channel is opened.
### Parameters
- **device_id**: UUID or MAC address of the peripheral
- **psm** or **options**: Protocol/service multiplexer, specified by the peripheral when the channel was opened. Can be an object which includes a `psm` key, with an optional `secureChannel` boolean setting to control whether the channel is encrypted or not (Android-only)
- **connectCallback**: Connect callback function, invoked when an L2CAP connection is successfully opened
- **disconnectCallback**: Disconnect callback function, invoked when the L2CAP stream closes or an error occurs.
### Supported Platforms
- iOS
- Android (>= 10)
## l2cap.close
Close an L2CAP channel.
ble.l2cap.close(device_id, psm, success, failure);
Using await with promises
await ble.withPromises.l2cap.close(device_id, psm);
### Description
Closes an open L2CAP channel with the selected device. All pending reads and writes are aborted.
### Parameters
- **device_id**: UUID or MAC address of the peripheral
- **psm**: Protocol/service multiplexer, specified by the peripheral when the channel was opened
- **success**: Success callback function that is invoked when the stream is closed successfully. [optional]
- **failure**: Error callback function, invoked when error occurs. [optional]
### Supported Platforms
- iOS
- Android (>= 10)
## l2cap.receiveData
Receive data from an L2CAP channel.
ble.l2cap.receiveData(device_id, psm, dataCallback);
### Description
Sets the function to be called whenever bytes are received on the L2CAP channel. This function will be used as long as the L2CAP connection remains open.
### Parameters
- **device_id**: UUID or MAC address of the peripheral
- **psm**: Protocol/service multiplexer, specified by the peripheral when the channel was opened
- **dataCallback**: Data processing function that is invoked when bytes are received from the peripheral
### Supported Platforms
- iOS
- Android (>= 10)
## l2cap.write
Write data to an L2CAP channel.
ble.l2cap.write(device_id, psm, data, success, failure);
Using await with promises
await ble.withPromises.l2cap.write(device_id, psm, data);
### Description
Writes all data to an open L2CAP channel. If the data exceeds the available space in the transmit buffer, the data will be automatically sent in chunks as space becomes available. The success callback is called only once after all the supplied bytes have been written to the transmit stream.
### Parameters
- **device_id**: UUID or MAC address of the peripheral
- **psm**: Protocol/service multiplexer, specified by the peripheral when the channel was opened
- **data**: Data to write to the stream
- **success**: Success callback function that is invoked after all bytes have been written to the stream [optional]
- **failure**: Error callback function, invoked when error occurs [optional]
### Supported Platforms
- iOS
- Android (>= 10)
# Peripheral Data

@@ -964,0 +1069,0 @@

function notSupported() {
function notSupported(failure) {
console.log('BLE is not supported on the browser');
if (failure) failure(new Error("not supported"));
}

@@ -177,4 +178,3 @@

isEnabled: function(success, failure) {
notSupported();
if (failure) failure(new Error("not supported"));
notSupported(failure);
},

@@ -194,17 +194,13 @@ isConnected: function(deviceId, success, failure) {

showBluetoothSettings: function(success, failure) {
notSupported();
if (failure) failure(new Error("not supported"));
notSupported(failure);
},
enable: function(success, failure) {
notSupported();
if (failure) failure(new Error("not supported"));
notSupported(failure);
},
startStateNotifications: function(success, failure) {
notSupported();
if (failure) failure(new Error("not supported"));
notSupported(failure);
},
stopStateNotifications: function(success, failure) {
notSupported();
if (failure) failure(new Error("not supported"));
notSupported(failure);
}
};

@@ -34,2 +34,38 @@ declare namespace BLECentralPlugin {

interface L2CAPOptions {
psm: number;
secureChannel?: boolean;
}
interface L2CAP {
close(device_id: string, psm: number, success?: () => any, failure?: (error: string | BLEError) => any);
open(
device_id: string,
psmOrOptions: number | L2CAPOptions,
connectCallback?: () => any,
disconnectCallback?: (error: string | BLEError) => any
);
receiveData(device_id: string, psm: number, data: (data: ArrayBuffer) => any);
write(
device_id: string,
psm: number,
data: ArrayBuffer,
success?: () => {},
failure?: (error: string | BLEError) => any
);
}
interface L2CAPPromises {
open(
device_id: string,
psmOrOptions: number | L2CAPOptions,
disconnectCallback?: (error: string | BLEError) => any
): Promise<void>;
close(device_id: string, psm: number): Promise<void>;
write(device_id: string, psm: number, data: ArrayBuffer): Promise<void>;
}
interface RestoredState {

@@ -67,16 +103,7 @@ peripherals?: PeripheralDataExtended[];

): void;
/* Register to be notified when the value of a characteristic changes. */
startNotification(
device_id: string,
service_uuid: string,
characteristic_uuid: string,
success: (rawData: ArrayBuffer) => any,
failure?: (error: string | BLEError) => any
): void;
startStateNotifications(success: (state: string) => any, failure?: (error: string) => any): void;
}
export interface BLECentralPluginPromises extends BLECentralPluginCommon {
l2cap: L2CAPPromises;
stopScan(): Promise<void>;

@@ -92,2 +119,11 @@ disconnect(device_id: string): Promise<void>;

): Promise<void>;
/* Register to be notified when the value of a characteristic changes. */
startNotification(
device_id: string,
service_uuid: string,
characteristic_uuid: string,
success: (rawData: ArrayBuffer) => any,
failure?: (error: string | BLEError) => any
): Promise<void>;
stopNotification(device_id: string, service_uuid: string, characteristic_uuid: string): Promise<void>;

@@ -103,4 +139,16 @@

showBluetoothSettings(): Promise<void>;
/** Registers a change listener for Bluetooth adapter state changes */
startStateNotifications(success: (state: string) => any, failure?: (error: string) => any): Promise<void>;
stopStateNotifications(): Promise<void>;
/* Registers a change listener for location-related services.
[iOS] startLocationStateNotifications is not supported on iOS. */
startLocationStateNotifications(
change: (isLocationEnabled: boolean) => any,
failure?: (error: string) => any
): Promise<void>;
stopLocationStateNotifications(): Promise<void>;
readRSSI(device_id: string): Promise<number>;

@@ -111,2 +159,4 @@ restoredBluetoothState(): Promise<RestoredState | undefined>;

export interface BLECentralPluginStatic extends BLECentralPluginCommon {
l2cap: L2CAP;
/* sets the pin when device requires it.

@@ -116,4 +166,3 @@ [iOS] setPin is not supported on iOS. */

stopScan(): void;
stopScan(success: () => any, failure?: () => any): void;
stopScan(success?: () => any, failure?: () => any): void;

@@ -160,2 +209,24 @@ /* Automatically connect to a device when it is in range of the phone

/* Start notifications on the given characteristic
- options
emitOnRegistered Default is false. Emit "registered" to success callback
when peripheral confirms notifications are active
*/
startNotification(
device_id: string,
service_uuid: string,
characteristic_uuid: string,
success: (rawData: ArrayBuffer | 'registered') => any,
failure: (error: string | BLEError) => any,
options: { emitOnRegistered: boolean }
): void;
startNotification(
device_id: string,
service_uuid: string,
characteristic_uuid: string,
success: (rawData: ArrayBuffer) => any,
failure?: (error: string | BLEError) => any
): void;
stopNotification(

@@ -202,2 +273,5 @@ device_id: string,

/** Registers a change listener for Bluetooth adapter state changes */
startStateNotifications(success: (state: string) => any, failure?: (error: string) => any): void;
stopStateNotifications(success?: () => any, failure?: () => any): void;

@@ -204,0 +278,0 @@

@@ -216,4 +216,13 @@ // (c) 2014-2016 Don Coleman

// success callback is called on notification
startNotification: function (device_id, service_uuid, characteristic_uuid, success, failure) {
cordova.exec(success, failure, 'BLE', 'startNotification', [device_id, service_uuid, characteristic_uuid]);
startNotification: function (device_id, service_uuid, characteristic_uuid, success, failure, options) {
const emitOnRegistered = options && options.emitOnRegistered == true;
function onEvent(data) {
if (data === 'registered') {
// For backwards compatibility, don't emit the registered event unless explicitly instructed
if (emitOnRegistered) success(data);
} else {
success(data);
}
}
cordova.exec(onEvent, failure, 'BLE', 'startNotification', [device_id, service_uuid, characteristic_uuid]);
},

@@ -248,7 +257,7 @@

startLocationStateNotifications: function (success, failure) {
cordova.exec(success, failure, "BLE", "startLocationStateNotifications", []);
cordova.exec(success, failure, 'BLE', 'startLocationStateNotifications', []);
},
stopLocationStateNotifications: function (success, failure) {
cordova.exec(success, failure, "BLE", "stopLocationStateNotifications", []);
cordova.exec(success, failure, 'BLE', 'stopLocationStateNotifications', []);
},

@@ -274,4 +283,2 @@

connect: module.exports.connect,
startNotification: module.exports.startNotification,
startStateNotifications: module.exports.startStateNotifications,

@@ -320,2 +327,22 @@ stopScan: function () {

startNotification: function (device_id, service_uuid, characteristic_uuid, success, failure) {
return new Promise(function (resolve, reject) {
module.exports.startNotification(
device_id,
service_uuid,
characteristic_uuid,
(data) => {
resolve();
// Filter out registered callback
if (data !== 'registered') success(data);
},
(err) => {
reject(err);
failure(err);
},
{ emitOnRegistered: true }
);
});
},
stopNotification: function (device_id, service_uuid, characteristic_uuid) {

@@ -351,2 +378,17 @@ return new Promise(function (resolve, reject) {

startStateNotifications: function (success, failure) {
return new Promise(function (resolve, reject) {
module.exports.startStateNotifications(
function (state) {
resolve();
success(state);
},
function (err) {
reject(err);
failure(err);
}
);
});
},
stopStateNotifications: function () {

@@ -358,6 +400,21 @@ return new Promise(function (resolve, reject) {

startLocationStateNotifications: function (change, failure) {
return new Promise(function (resolve, reject) {
module.exports.startLocationStateNotifications(
function (state) {
resolve();
change(state);
},
function (err) {
reject(err);
failure(err);
}
);
});
},
stopLocationStateNotifications: function () {
return new Promise(function(resolve, reject) {
module.exports.stopLocationStateNotifications(resolve, reject);
});
return new Promise(function (resolve, reject) {
module.exports.stopLocationStateNotifications(resolve, reject);
});
},

@@ -377,1 +434,48 @@

};
module.exports.l2cap = {
close(device_id, psm, success, failure) {
cordova.exec(success, failure, 'BLE', 'closeL2Cap', [device_id, psm]);
},
open(device_id, psmOrOptions, connectCallback, disconnectCallback) {
var psm = psmOrOptions;
var settings = {};
if (psmOrOptions != undefined && "psm" in psmOrOptions) {
psm = psmOrOptions.psm;
settings = psmOrOptions;
}
cordova.exec(connectCallback, disconnectCallback, 'BLE', 'openL2Cap', [device_id, psm, settings]);
},
receiveData(device_id, psm, receive) {
cordova.exec(receive, function(){}, 'BLE', 'receiveDataL2Cap', [device_id, psm]);
},
write(device_id, psm, data, success, failure) {
cordova.exec(success, failure, 'BLE', 'writeL2Cap', [device_id, psm, data]);
},
};
module.exports.withPromises.l2cap = {
close(device_id, psm) {
return new Promise(function(resolve, reject) {
module.exports.l2cap.close(device_id, psm, resolve, reject);
});
},
open(device_id, psmOrOptions, disconnectCallback) {
return new Promise(function(resolve, reject) {
module.exports.l2cap.open(device_id, psmOrOptions, resolve, function(e) {
disconnectCallback(e);
reject(e);
});
});
},
write(device_id, psm, data) {
return new Promise(function(resolve, reject) {
module.exports.l2cap.write(device_id, psm, data, resolve, reject);
});
},
};

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc