@nativescript-community/ble
连接并交互蓝牙低功耗外围设备。
npm i --save @nativescript-community/ble

@nativescript-community/ble

Downloads per month NPM Version

连接并交互蓝牙低功耗外围设备。


目录

安装

从项目的根目录运行以下命令

ns plugin add @nativescript-community/ble

API

想快速入门?查看演示应用!否则,根据需要混合使用这些函数

先决条件

发现

连接

交互

调试

isBluetoothEnabled

报告蓝牙是否启用。

// require the plugin
import { Bluetooth } from '@nativescript-community/ble';
var bluetooth = new Bluetooth();

bluetooth.isBluetoothEnabled().then(
function(enabled) {
console.log("Enabled? " + enabled);
}
);

权限 (Android)

在 Android 6 及以上版本和小于 12 的版本中,您需要在 API 级别 23+ 的目标上请求权限,以便能够与蓝牙外围设备交互(当应用处于后台时)。您需要 BLUETOOTHACCESS_FINE_LOCATION。您应该在这里阅读文档https://android-docs.cn/develop/connectivity/bluetooth/bt-permissions

在 Android 12 及以上版本中,您需要新的权限。您应该在这里阅读文档https://android-docs.cn/develop/connectivity/bluetooth/bt-permissions 注意,对于 BLUETOOTHBLUETOOTH_ADMIN,您不需要运行时权限;将这些添加到 AndroidManifest.xml 即可。

请注意,当以下情况时,hasLocationPermission 将返回 true:

  • 您在 iOS 上运行此代码,或
  • 您的目标是 API 级别低于 23,或
  • 您正在使用运行 Android 6 以下版本的设备,或
  • 您已授予权限。
bluetooth.hasLocationPermission().then(
function(granted) {
// if this is 'false' you probably want to call 'requestLocationPermission' now
console.log("Has Location Permission? " + granted);
}
);

requestLocationPermission

从插件版本 1.2.0 开始,startScanning 函数将内部处理此功能,因此不再强制在您的代码中添加权限检查。

// if no permission was granted previously this will open a user consent screen
bluetooth.requestLocationPermission().then(
function(granted) {
console.log("Location permission requested, user granted? " + granted);
}
);

enable (仅限 Android)

在 iOS 上将拒绝承诺

// This turns bluetooth on, will return false if the user denied the request.
bluetooth.enable().then(
function(enabled) {
// use Bluetooth features if enabled is true
}
);

startScanning

一些可选参数需要一些解释

seconds

扫描外围设备会快速耗尽电量,因此您最好不要扫描超过必要的范围。如果外围设备在范围内且未参与其他连接,通常在不到一秒钟的时间内就会出现。如果您不传入秒数,则需要手动调用 stopScanning

avoidDuplicates

如果不想在 "onDiscovered" 回调中报告具有相同 serviceUUID 的重复设备,请将此设置为 true。如果为 true,则只会报告首次发现的具有相同 serviceUUID 的外围设备。

skipPermissionCheck

如果不想让插件检查(并请求)所需的蓝牙权限,请将此设置为 true。这对于在非 UI 线程(例如 Worker)上运行此函数特别有用。仅适用于 Android。

filters

扫描所有可用的蓝牙外围设备并报告它们提供的所有服务是不高效的。此外,在 Android 中,如果我们不使用过滤器,则必须具有位置权限并启用 GPS。

如果您只想找到心率外设,例如,可以传入服务UUID '180d',如下所示:filters: [{serviceUUID:'180d'}]。如果您添加了2个或更多(以逗号分隔)服务,则只有支持所有这些服务的设备才会匹配。

请注意,UUID始终是字符串;不要传入整数。

onDiscovered

在扫描过程中,插件将立即报告唯一发现的设备。

此函数将接收一个表示外围设备的对象,该对象包含以下属性(和类型)

  • UUID:字符串
  • name:字符串
  • RSSI:数字(相对信号强度,可用于距离测量)
  • services?:(可选 - 在连接到外围设备后设置)
  • manufacturerId?:数字(可选)
  • advertismentData?:{ localName?:字符串 manufacturerData?:ArrayBuffer;serviceUUIDs?:字符串[];txPowerLevel?:数字,flags?:数字 }(可选)
bluetooth.startScanning({
filters: [{serviceUUID:'180d'}],
seconds: 4,
onDiscovered: function (peripheral) {
console.log("Periperhal found with UUID: " + peripheral.UUID);
}
}).then(function() {
console.log("scanning complete");
}, function (err) {
console.log("error while scanning: " + err);
});

stopScanning

在任何时候进行扫描期间,无论您是否传入秒数,都可以通过调用此函数停止扫描。

例如,当您在startScanningonDiscovered回调中找到的设备与您的标准匹配时,您可以停止扫描。

bluetooth.stopScanning().then(function() {
console.log("scanning stopped");
});

connect

传入您想要连接的外设的UUID,一旦建立连接,onConnected回调函数将被调用。此回调将接收与之前相同的设备对象,但现在它还包含一个services属性。返回的设备对象示例可能如下所示

  peripheral: {
UUID: '3424-542-4534-53454',
name: 'Polar P7 Heartrate Monitor',
RSSI: '-57',
services: [{
UUID: '180d',
name: 'Heartrate service',
characteristics: [{
UUID: '34534-54353-234324-343',
name: 'Heartrate characteristic',
properties: {
read: true,
write: false,
writeWithoutResponse: false,
notify: true
}
}]
}]
}

以下是connect函数的作用,以及一个简单的onConnected实现,它将整个设备对象打印到控制台

bluetooth.connect({
UUID: '04343-23445-45243-423434',
onConnected: function (peripheral) {
console.log("Periperhal connected with UUID: " + peripheral.UUID);

// the peripheral object now has a list of available services:
peripheral.services.forEach(function(service) {
console.log("service found: " + JSON.stringify(service));
});
},
onDisconnected: function (peripheral) {
console.log("Periperhal disconnected with UUID: " + peripheral.UUID);
}
});

请注意,还有onDisconnected函数:在此事件之后尝试与外围设备交互可能会使您的应用程序崩溃。

disconnect

一旦完成与外围设备的交互,请作为好公民断开连接。这将允许其他应用程序建立连接。

bluetooth.disconnect({
UUID: '34234-5453-4453-54545'
}).then(function() {
console.log("disconnected successfully");
}, function (err) {
// in this case you're probably best off treating this as a disconnected peripheral though
console.log("disconnection error: " + err);
});

read

如果外围设备有一个服务,其中properties.readtrue,则可以调用read函数以检索特性的当前状态(值)。

该承诺将接收一个如下的对象

{
value: <ArrayBuffer>, // an ArrayBuffer which you can use to decode (see example below)
ios: <72>, // the platform-specific binary value of the characteristic: NSData (iOS), byte[] (Android)
android: <72>, // the platform-specific binary value of the characteristic: NSData (iOS), byte[] (Android)
characteristicUUID: '434234-234234-234234-434'
}

有了这些知识,让我们调用read函数

bluetooth.read({
peripheralUUID: '34234-5453-4453-54545',
serviceUUID: '180d',
characteristicUUID: '3434-45234-34324-2343'
}).then(function(result) {
// fi. a heartrate monitor value (Uint8) can be retrieved like this:
var data = new Uint8Array(result.value);
console.log("Your heartrate is: " + data[1] + " bpm");
}, function (err) {
console.log("read error: " + err);
});

write

如果外围设备有一个服务,其中特性properties.writetrue,则可以调用write函数来更新特性的当前状态(值)。

值可以是字符串或任何数组类型值。如果您传递字符串,则应传递编码。

bluetooth.write({
peripheralUUID: '34134-5453-4453-54545',
serviceUUID: '180e',
characteristicUUID: '3424-45234-34324-2343',
value: [1]
}).then(function(result) {
console.log("value written");
}, function (err) {
console.log("write error: " + err);
});

writeWithoutResponse

write相同的API,只是在承诺调用时,值尚未写入;它只是请求写入,并且在写入完成时不会收到响应。

startNotifying

如果外围设备有一个服务,其中特性properties.notifytrue,则可以调用startNotifying函数以检索特性的值更改。

用法与read非常相似,但结果不会发送到承诺,而是发送到您传入的onNotify回调函数。这是因为可以接收多个通知,而承诺只能解决一次。发送到onNotify的对象的值与您在read的承诺中获得的值相同。

bluetooth.startNotifying({
peripheralUUID: '34234-5453-4453-54545',
serviceUUID: '180d',
characteristicUUID: '3434-45234-34324-2343',
onNotify: function (result) {
// see the read example for how to decode ArrayBuffers
console.log("read: " + JSON.stringify(result));
}
}).then(function() {
console.log("subscribed for notifications");
});

stopNotifying

足够了。当您不再对外围设备发送的值感兴趣时,这样做

bluetooth.stopNotifying({
peripheralUUID: '34234-5453-4453-54545',
serviceUUID: '180d',
characteristicUUID: '3434-45234-34324-2343'
}).then(function() {
console.log("unsubscribed for notifications");
}, function (err) {
console.log("unsubscribe error: " + err);
});

示例

  • 基础
    • 一个基础示例显示即使是在模态中,覆盖N个手势也是有效的

演示和开发

仓库设置

该仓库使用子模块。如果您没有使用 --recursive进行克隆,则需要调用

git submodule update --init

用于安装和链接依赖项的包管理器必须是pnpmyarn。不兼容npm

开发和测试:如果您使用 yarn,则运行 yarn;如果您使用 pnpm,则运行 pnpm i

交互式菜单

要启动交互式菜单,运行 npm start(或 yarn startpnpm start)。这将列出所有常用脚本。

构建

npm run build.all

警告:似乎 yarn build.all 不会总是工作(在 node_modules/.bin 中找不到二进制文件),这就是为什么文档明确使用 npm run

演示

npm run demo.[ng|react|svelte|vue].[ios|android]

npm run demo.svelte.ios # Example

演示设置在某种程度上有些特殊,如果您想修改或添加演示,您不需要直接在 demo-[ng|react|svelte|vue] 中工作。相反,您应在 demo-snippets/[ng|react|svelte|vue] 中工作。您可以从每个样式的 install.ts 开始,了解如何注册新的演示。

贡献

更新仓库

您可以非常容易地更新仓库文件。

首先更新子模块。

npm run update

然后提交更改,然后更新公共文件。

npm run sync

然后您可以运行 yarn|pnpm,如果有任何更改,请提交更改的文件。

更新 README

npm run readme

更新文档

npm run doc

发布

发布完全由 lerna 处理(您可以通过添加 -- --bump major 强制进行主要版本发布)只需运行即可。

npm run publish

修改子模块

仓库使用 https:// 来处理子模块,这意味着您无法直接将内容推送到子模块。一个简单的解决方案是修改 ~/.gitconfig 并添加以下内容:

[url "ssh://[email protected]/"]
pushInsteadOf = https://github.com/

问题

如果您有任何问题/问题/评论,请随时创建一个问题或在 NativeScript 社区 Discord 中开始对话。