这里给大家分享我在网上总结出来的一些知识 ,希望对大家有所帮助
本文简介
这是一次真实的 蓝牙收发数据 的全过程讲解 。
本文使用 uni-app + Vue3 的方式进行开发 ,以手机app的方式运行(微信小程序同样可行) 。
uni-app 提供了 蓝牙 和 低功耗蓝牙 的 api ,和微信小程序提供的 api 是一样的 ,所以本文的讲解也适用于微信小程序 。
本文只实现 蓝牙收发数据 功能 ,至于样式 ,我懒得调~
蓝牙相关功能我会逐步讲解 。如果你基础好 ,又急的话 ,可以直接跳到 『完整代码』的章节查看 ,那里没废话 。
环境说明
开发工具:HBuilder X 3.4.7.20220422
uni-app + Vue3
以安卓App的方式运行(iOS和小程序同理)
思路
蓝牙收发数据的逻辑和我们常用的 AJAX 进行的网络请求是有一丢丢不同的 。
其中较大的区别是:蓝牙接收数据不是那么的稳定 ,相比起网络请求 ,蓝牙更容易出现丢包的情况 。
在开发中 ,AJAX 发起的请求不管成功还是失败,浏览器基本都会给你一个答复 。但 uni-app 提供的 api 来看 ,蓝牙接收数据会显得更加 “异步 ” 。
大致思路
使用蓝牙进行数据传输的大概思路如下:
初始化:打开蓝牙模块
搜寻:检测附近存在的设备
连接:找到目标设备进行
监听:开启监听功能 ,接收其他设备传过来的数据
发送指令:不管发送数据还是读取数据,都可以理解为向外发送指令
实现
上面整理出使用蓝牙传输数据的5大动作 ,但每个动作其实都是由 uni-app 提供的一个或者多个 api 组合而成 。
初始化阶段
使用蓝牙之前 ,需要初始化蓝牙模块 ,这是最最最开始就要做的!
使用 uni.openBluetoothAdapter 这个 api 就可以初始化蓝牙模块 。其他蓝牙相关 API 必须在 uni.openBluetoothAdapter 调用之后使用 。否则 API 会返回错误( errCode=10000 )。
代码示例
如果你手机开启了蓝牙 ,点击页面上的按钮后 ,控制台就会输出如下内容
初始化蓝牙成功
{"errMsg":"openBluetoothAdapter:ok"}
如果手机没开启蓝牙 ,就会返回如下内容
初始化蓝牙失败
{"errMsg":"openBluetoothAdapter:fail not available","code":10001}
根据文档提示 ,10001代表当前蓝牙适配器不可用 。
如果你的控制台能打印出 {"errMsg":"openBluetoothAdapter:ok"} 证明第一步已经成功了 。
接下来可以开始搜索附近蓝牙设备。
搜寻附近设备
这一步需要2个 api 配合完成 。所以可以分解成以下2步:
开启搜寻功能:uni.startBluetoothDevicesDiscovery
监听搜寻到新设备:uni.onBluetoothDeviceFound
开发蓝牙相关功能时 ,操作逻辑更像是推送 ,所以“开启搜索 ”和“监听新设备 ”是分开操作的 。
uni.startBluetoothDevicesDiscovery 可以让设备开始搜索附近蓝牙设备 ,但这个方法比较耗费系统资源 ,建议在连接到设备之后就使用 uni.stopBluetoothDevicesDiscovery 停止继续搜索 。
uni.startBluetoothDevicesDiscovery 方法里可以传入一个对象 ,该对象接收几个参数,但初学的话我们只关注 success 和 fail 。如果你的项目中硬件佬有提供 service 的 uuid 给你的话 ,你也可以在 services 里传入 。其他参数可以查看官方文档的介绍 。
在使用 uni.startBluetoothDevicesDiscovery (开始搜索)后 ,可以使用 uni.onBluetoothDeviceFound 进行监听,这个方法里面接收一个回调函数 。
代码示例
<template>
<view>
<scroll-view
scroll-y
class="box"
>
<view class="item" v-for="item in blueDeviceList">
<view>
<text>id: {{ item.deviceId }}</text>
</view>
<view>
<text>name: {{ item.name }}</text>
</view>
</view>
</scroll-view>
<button @click="initBlue">初始化蓝牙</button>
<button @click="discovery">搜索附近蓝牙设备</button>
</view>
</template>
<script setup> import { ref } from vue
// 搜索到的蓝牙设备列表
const blueDeviceList = ref([])
// 【1】初始化蓝牙
function initBlue() {
uni.openBluetoothAdapter({
success(res) {
console.log(初始化蓝牙成功)
console.log(res)
},
fail(err) {
console.log(初始化蓝牙失败)
console.error(err)
}
})
}
// 【2】开始搜寻附近设备
function discovery() {
uni.startBluetoothDevicesDiscovery({
success(res) {
console.log(开始搜索)
// 开启监听回调
uni.onBluetoothDeviceFound(found)
},
fail(err) {
console.log(搜索失败)
console.error(err)
}
})
}
// 【3】找到新设备就触发该方法
function found(res) {
console.log(res)
blueDeviceList.value.push(res.devices[0])
} </script>
<style> .box {
width: 100%;
height: 400rpx;
box-sizing: border-box;
margin-bottom: 20rpx;
border: 2px solid dodgerblue;
}
.item {
box-sizing: border-box;
padding: 10rpx;
border-bottom: 1px solid #ccc;
}
button {
margin-bottom: 20rpx;
} </style>
上面代码的逻辑是 ,如果开启“寻找附近设备 ”功能成功 ,接着就开启“监听寻找到新设备的事件 ” 。
搜索到的设备会返回以下数据:
{
"devices": [{
"deviceId": "B4:10:7B:C4:83:14",
"name": "蓝牙设备名",
"RSSI": -58,
"localName": "",
"advertisServiceUUIDs": ["0000FFF0-0000-1000-8000-00805F9B34FB"],
"advertisData": {}
}]
}
每监听到一个新的设备 ,我都会将其添加到 蓝牙设备列表(blueDeviceList) 里 ,最后讲这个列表的数据渲染到页面上 。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cePpaik0-1652253685142)(https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f3a21f372d3b40e996e3a0db9f4aa66b~tplv-k3u1fbpfcp-zoom-in-crop-mark:1956:0:0:0.image?)]
连接目标设备
连接目标设备只需要1个 api 就能完成 。但根据文档提示 ,我们连接后还需要关闭 “搜索附近设备 ” 的功能 ,这个很好理解 ,既然找到了 ,再继续找就是浪费资源 。
流程如下:
获取设备ID:根据 uni.onBluetoothDeviceFound 回调 ,拿到设备ID
连接设备:使用设备ID进行连接 uni.createBLEConnection
停止搜索:uni.stopBluetoothDevicesDiscovery
我给每条搜索到的蓝牙结果添加一个 click 事件 ,会向目标设备发送连接请求 。
我的设备名称是 leihou ,所以我点击了这条。
代码示例
<template>
<view>
<scroll-view
scroll-y
class="box"
>
<view class="item" v-for="item in blueDeviceList" @click="connect(item)">
<view>
<text>id: {{ item.deviceId }}</text>
</view>
<view>
<text>name: {{ item.name }}</text>
</view>
</view>
</scroll-view>
<button @click="initBlue">初始化蓝牙</button>
<button @click="discovery">搜索附近蓝牙设备</button>
</view>
</template>
<script setup> import { ref } from vue
// 搜索到的蓝牙设备列表
const blueDeviceList = ref([])
// 【1】初始化蓝牙
function initBlue() {
uni.openBluetoothAdapter({
success(res) {
console.log(初始化蓝牙成功)
console.log(res)
},
fail(err) {
console.log(初始化蓝牙失败)
console.error(err)
}
})
}
// 【2】开始搜寻附近设备
function discovery() {
uni.startBluetoothDevicesDiscovery({
success(res) {
console.log(开始搜索)
// 开启监听回调
uni.onBluetoothDeviceFound(found)
},
fail(err) {
console.log(搜索失败)
console.error(err)
}
})
}
// 【3】找到新设备就触发该方法
function found(res) {
console.log(res)
blueDeviceList.value.push(res.devices[0])
}
// 蓝牙设备的id
const deviceId = ref()
// 【4】连接设备
function connect(data) {
console.log(data)
deviceId.value = data.deviceId
uni.createBLEConnection({
deviceId: deviceId.value,
success(res) {
console.log(连接成功)
console.log(res)
// 停止搜索
stopDiscovery()
},
fail(err) {
console.log(连接失败)
console.error(err)
}
})
}
// 【5】停止搜索
function stopDiscovery() {
uni.stopBluetoothDevicesDiscovery({
success(res) {
console.log(停止成功)
console.log(res)
},
fail(err) {
console.log(停止失败)
console.error(err)
}
})
} </script>
<style> .box {
width: 100%;
height: 400rpx;
box-sizing: border-box;
margin-bottom: 20rpx;
border: 2px solid dodgerblue;
}
.item {
box-sizing: border-box;
padding: 10rpx;
border-bottom: 1px solid #ccc;
}
button {
margin-bottom: 20rpx;
} </style>
连接成功后在控制台会输出
连接成功
{"errMsg":"createBLEConnection:ok"}
在连接成功后就立刻调用uni.stopBluetoothDevicesDiscovery方法停止继续搜索附近其他设备 ,停止成功后会输出
停止成功
{"errMsg":"stopBluetoothDevicesDiscovery:ok"}
监听
在连接完设备后,就要先开启监听数据的功能 。这样才能接收到发送读写指令后设备给你回调的信息 。
要开启监听 ,首先需要知道蓝牙设备提供了那些服务 ,然后通过服务获取特征值,特征值会告诉你哪个可读 ,哪个可写。最后根据特征值进行消息监听 。
步骤如下:
获取蓝牙设备服务:uni.getBLEDeviceServices
获取特征值:uni.getBLEDeviceCharacteristics
开启消息监听:uni.notifyBLECharacteristicValueChange
接收消息监听传来的数据:uni.onBLECharacteristicValueChange
正常情况下 ,硬件佬会提前把蓝牙设备的指定服务还有特征值告诉你 。
比如我这个设备的蓝牙服务是:0000FFE0-0000-1000-8000-00805F9B34FB
特征值是:0000FFE1-0000-1000-8000-00805F9B34FB
第一步 ,获取蓝牙服务
<template>
<view>
<!-- 省略上一步的代码 -->
<button @click="getServices">获取蓝牙服务</button>
</view>
</template>
<script setup> import { ref } from vue
// 省略上一步的代码……
// 【6】获取服务
function getServices() {
uni.getBLEDeviceServices({
deviceId: deviceId.value, // 设备ID ,在上一步【4】里获取
success(res) {
console.log(res)
},
fail(err) {
console.error(err)
}
})
} </script>
此时点击按钮 ,将会获取到已连接设备的所有服务 。
我的设备有以下几个服务 。你在工作中拿到的服务uuid和我的是不一样的 ,数量也不一定相同 。
可以发现 ,我拿到的结果里有0000FFE0-0000-1000-8000-00805F9B34FB这条服务 。
{
"services": [{
"uuid": "00001800-0000-1000-8000-00805F9B34FB",
"isPrimary": true
}, {
"uuid": "00001801-0000-1000-8000-00805F9B34FB",
"isPrimary": true
}, {
"uuid": "0000180A-0000-1000-8000-00805F9B34FB",
"isPrimary": true
}, {
"uuid": "0000FFF0-0000-1000-8000-00805F9B34FB",
"isPrimary": true
}, {
"uuid": "0000FFE0-0000-1000-8000-00805F9B34FB",
"isPrimary": true
}],
"errMsg": "getBLEDeviceServices:ok"
}
第二步 ,获取指定服务的特征值
获取特征值 ,需要传设备ID和服务ID 。
在上两步我拿到了设备ID为B4:10:7B:C4:83:14 ,服务ID为0000FFE0-0000-1000-8000-00805F9B34FB 。
<template>
<view>
<!-- 省略前面几步代码 -->
<button @click="getCharacteristics">获取特征值</button>
</view>
</template>
<script setup> import { ref } from vue
// 省略前面几步代码
// 【7】获取特征值
function getCharacteristics() {
uni.getBLEDeviceCharacteristics({
deviceId: deviceId.value, // 设备ID ,在【4】里获取到
serviceId: 0000FFE0-0000-1000-8000-00805F9B34FB, // 服务UUID ,在【6】里能获取到
success(res) {
console.log(res)
},
fail(err) {
console.error(err)
}
})
} </script>
最后成功输出
{
"characteristics": [{
"uuid": "0000FFE1-0000-1000-8000-00805F9B34FB",
"properties": {
"read": true,
"write": true,
"notify": true,
"indicate": false
}
}],
"errMsg": "getBLEDeviceCharacteristics:ok"
}
characteristics 字段里保存了该服务的所有特征值,我的设备这个服务只有1个特征值 ,并且读 、写 、消息推送都为 true 。
你的设备可能不止一条特征值 ,需要监听那条特征值这需要你和硬件佬协商的(通常也是硬件佬直接和你说要监听哪条) 。
第三 、四步,开启消息监听 并 接收消息监听传来的数据
根据已经拿到的 设备ID 、服务ID 、特征值 ,就可以开启对应的监听功能 。
使用 uni.notifyBLECharacteristicValueChange 开启消息监听;
并在 uni.onBLECharacteristicValueChange 方法触发监听到的消息 。
<template>
<view>
<!-- 省略前面几步代码 -->
<button @click="notify">开启消息监听</button>
</view>
</template>
<script setup> import { ref } from vue
// 省略前面几步代码
// 【8】开启消息监听
function notify() {
uni.notifyBLECharacteristicValueChange({
deviceId: deviceId.value, // 设备ID ,在【4】里获取到
serviceId: 0000FFE0-0000-1000-8000-00805F9B34FB, // 服务UUID ,在【6】里能获取到
characteristicId: 0000FFE1-0000-1000-8000-00805F9B34FB, // 特征值 ,在【7】里能获取到
success(res) {
console.log(res)
// 接受消息的方法
listenValueChange()
},
fail(err) {
console.error(err)
}
})
}
// ArrayBuffer转16进度字符串示例
function ab2hex(buffer) {
const hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function (bit) {
return (00 + bit.toString(16)).slice(-2)
}
)
return hexArr.join()
}
// 将16进制的内容转成我们看得懂的字符串内容
function hexCharCodeToStr(hexCharCodeStr) {
var trimedStr = hexCharCodeStr.trim();
var rawStr = trimedStr.substr(0, 2).toLowerCase() === "0x" ? trimedStr.substr(2) : trimedStr;
var len = rawStr.length;
if (len % 2 !== 0) {
alert("存在非法字符!");
return "";
}
var curCharCode;
var resultStr = [];
for (var i = 0; i < len; i = i + 2) {
curCharCode = parseInt(rawStr.substr(i, 2), 16);
resultStr.push(String.fromCharCode(curCharCode));
}
return resultStr.join("");
}
// 【9】监听消息变化
function listenValueChange() {
uni.onBLECharacteristicValueChange(res => {
// 结果
console.log(res)
// 结果里有个value值 ,该值为 ArrayBuffer 类型 ,所以在控制台无法用肉眼观察到 ,必须将该值转换为16进制
let resHex = ab2hex(res.value)
console.log(resHex)
// 最后将16进制转换为ascii码 ,就能看到对应的结果
let result = hexCharCodeToStr(resHex)
console.log(result)
})
} </script>
listenValueChange方法是用来接收设备传过来的消息。
上面的例子中 ,res的结果是
{
"deviceId": "B4:10:7B:C4:83:14",
"serviceId": "0000FFE0-0000-1000-8000-00805F9B34FB",
"characteristicId": "0000FFE1-0000-1000-8000-00805F9B34FB",
"value": {}
}
设备传过来的内容就放在 value 字段里 ,但因为该字段的类型是 ArrayBuffer ,所以无法在控制台用肉眼直接观察 。于是就通过 ab2hex 方法将该值转成 16进制 ,最后再用 hexCharCodeToStr 方法将 16进制 转成 ASCII码 。
我从设备里发送一段字符串过来:leihou
App端收到的数据转成 16进制 后的结果:6c6569686f75
再从 16进制 转成 ASCII码 后的结果:leihou
发送指令
终于到最后一步了。
从 uni-app 和 微信小程序 提供的蓝牙api 来看,发送指令只要有2个方法:
uni.writeBLECharacteristicValue:向低功耗蓝牙设备特征值中写入二进制数据 。
uni.readBLECharacteristicValue:读取低功耗蓝牙设备的特征值的二进制数据值 。
这里需要理清一个概念 ,本节的内容为 “发送指令 ” ,也就是说,从你的app或小程序向其他蓝牙设备发送指令 ,而这个指令分2种情况 ,一种是你要发送一些数据给蓝牙设备 ,另一种情况是你叫蓝牙设备给你发点信息 。
uni.writeBLECharacteristicValue
这两种情况我们需要分开讨论 ,先讲讲 uni.writeBLECharacteristicValue 。
uni.writeBLECharacteristicValue 从文档可以看出 ,这个 api 是可以发送一些数据给蓝牙设备 ,但发送的值要转成 ArrayBuffer 。
代码示例
<template>
<view>
<!-- 省略前面几步代码 -->
<button @click="send">发送数据</button>
</view>
</template>
<script setup> import { ref } from vue
// 省略前面几步代码
// 【10】发送数据
function send() {
// 向蓝牙设备发送一个0x00的16进制数据
let msg = hello
const buffer = new ArrayBuffer(msg.length)
const dataView = new DataView(buffer)
// dataView.setUint8(0, 0)
for (var i = 0; i < msg.length; i++) {
dataView.setUint8(i, msg.charAt(i).charCodeAt())
}
uni.writeBLECharacteristicValue({
deviceId: deviceId.value, // 设备ID ,在【4】里获取到
serviceId: 0000FFE0-0000-1000-8000-00805F9B34FB, // 服务UUID ,在【6】里能获取到
characteristicId: 0000FFE1-0000-1000-8000-00805F9B34FB, // 特征值 ,在【7】里能获取到
value: buffer,
success(res) {
console.log(res)
},
fail(err) {
console.error(err)
}
})
} </script>
此时 ,如果 uni.writeBLECharacteristicValue 走 success ,证明你已经把数据向外成功发送了 ,但不代表设备一定就收到了 。
通常设备收到你发送过去的信息,会返回一条消息给你 ,而这个回调消息会在 uni.onBLECharacteristicValueChange 触发 ,也就是 第【9】步 那里 。但这是蓝牙设备那边控制的,你作为前端佬 ,人家“已读不回 ”你也拿人家没办法 。
uni.readBLECharacteristicValue
在 “监听 ” 部分 ,我们使用了 uni.getBLEDeviceCharacteristics 获取设备的特征值 ,我的设备提供的特征值支持 read ,所以可以使用 uni.readBLECharacteristicValue 向蓝牙设备发送一条 “读取 ” 指令 。然后在 uni.onBLECharacteristicValueChange 里可以接收设备发送过来的数据 。
代码示例
<template>
<view>
<!-- 省略前面几步代码 -->
<button @click="read">读取数据</button>
</view>
</template>
<script setup> import { ref } from vue
// 省略前面几步代码
// 【11】读取数据
function read() {
uni.readBLECharacteristicValue({
deviceId: deviceId.value,
serviceId: serviceId.value,
characteristicId: characteristicId.value,
success(res) {
console.log(读取指令发送成功)
console.log(res)
},
fail(err) {
console.log(读取指令发送失败)
console.error(err)
}
})
} </script>
使用 “读取 ” 的方式向设备发送指令 ,是不需要另外传值的 。
此时我的设备返回00
这个数据是硬件那边设置的 。
在日常工作中 ,uni.readBLECharacteristicValue 的作用主要是读取数据 ,但使用场景不算很多。
我在工作中遇到的场景是:蓝牙设备提供了几个接口 ,而且传过来的数据比较大 ,比如传图片给app这边 。我就会先用 uni.writeBLECharacteristicValue 告诉设备我现在需要取什么接口的数据 ,然后用 uni.readBLECharacteristicValue 发送读取数据的请求 ,如果数据量比较大 ,就要重复使用 uni.readBLECharacteristicValue 进行读取 。比如上面的例子,我读第一次的时候返回 00 ,读第二次就返回 01 ……
最后再提醒一下 ,uni.readBLECharacteristicValue 只负责发送读取的请求,并且里面的 success 和 fail 只是返回你本次发送请求的动作是否成功 ,至于对面的蓝牙设备有没有收到这个指令你是不清楚的。
最后需要通过 uni.getBLEDeviceCharacteristics 监听设备传过来的数据 。
完整代码
<template>
<view>
<scroll-view
scroll-y
class="box"
>
<view class="item" v-for="item in blueDeviceList" @click="connect(item)">
<view>
<text>id: {{ item.deviceId }}</text>
</view>
<view>
<text>name: {{ item.name }}</text>
</view>
</view>
</scroll-view>
<button @click="initBlue">1 初始化蓝牙</button>
<button @click="discovery">2 搜索附近蓝牙设备</button>
<button @click="getServices">3 获取蓝牙服务</button>
<button @click="getCharacteristics">4 获取特征值</button>
<button @click="notify">5 开启消息监听</button>
<button @click="send">6 发送数据</button>
<button @click="read">7 读取数据</button>
<view class="msg_x">
<view class="msg_txt">
监听到的内容:{{ message }}
</view>
<view class="msg_hex">
监听到的内容(十六进制):{{ messageHex }}
</view>
</view>
</view>
</template>
<script setup> import { ref } from vue
// 搜索到的蓝牙设备列表
const blueDeviceList = ref([])
// 【1】初始化蓝牙
function initBlue() {
uni.openBluetoothAdapter({
success(res) {
console.log(初始化蓝牙成功)
console.log(res)
},
fail(err) {
console.log(初始化蓝牙失败)
console.error(err)
}
})
}
// 【2】开始搜寻附近设备
function discovery() {
uni.startBluetoothDevicesDiscovery({
success(res) {
console.log(开始搜索)
// 开启监听回调
uni.onBluetoothDeviceFound(found)
},
fail(err) {
console.log(搜索失败)
console.error(err)
}
})
}
// 【3】找到新设备就触发该方法
function found(res) {
console.log(res)
blueDeviceList.value.push(res.devices[0])
}
// 蓝牙设备的id
const deviceId = ref()
// 【4】连接设备
function connect(data) {
console.log(data)
deviceId.value = data.deviceId // 将获取到的设备ID存起来
uni.createBLEConnection({
deviceId: deviceId.value,
success(res) {
console.log(连接成功)
console.log(res)
// 停止搜索
stopDiscovery()
uni.showToast({
title: 连接成功
})
},
fail(err) {
console.log(连接失败)
console.error(err)
uni.showToast({
title: 连接成功,
icon: error
})
}
})
}
// 【5】停止搜索
function stopDiscovery() {
uni.stopBluetoothDevicesDiscovery({
success(res) {
console.log(停止成功)
console.log(res)
},
fail(err) {
console.log(停止失败)
console.error(err)
}
})
}
// 【6】获取服务
function getServices() {
// 如果是自动链接的话 ,uni.getBLEDeviceServices方法建议使用setTimeout延迟1秒后再执行
uni.getBLEDeviceServices({
deviceId: deviceId.value,
success(res) {
console.log(res) // 可以在res里判断有没有硬件佬给你的服务
uni.showToast({
title: 获取服务成功
})
},
fail(err) {
console.error(err)
uni.showToast({
title: 获取服务失败,
icon: error
})
}
})
}
// 硬件提供的服务id ,开发中需要问硬件佬获取该id
const serviceId = ref(0000FFE0-0000-1000-8000-00805F9B34FB)
// 【7】获取特征值
function getCharacteristics() {
// 如果是自动链接的话 ,uni.getBLEDeviceCharacteristics方法建议使用setTimeout延迟1秒后再执行
uni.getBLEDeviceCharacteristics({
deviceId: deviceId.value,
serviceId: serviceId.value,
success(res) {
console.log(res) // 可以在此判断特征值是否支持读写等操作 ,特征值其实也需要提前向硬件佬索取的
uni.showToast({
title: 获取特征值成功
})
},
fail(err) {
console.error(err)
uni.showToast({
title: 获取特征值失败,
icon: error
})
}
})
}
const characteristicId = ref(0000FFE1-0000-1000-8000-00805F9B34FB)
// 【8】开启消息监听
function notify() {
uni.notifyBLECharacteristicValueChange({
deviceId: deviceId.value, // 设备id
serviceId: serviceId.value, // 监听指定的服务
characteristicId: characteristicId.value, // 监听对应的特征值
success(res) {
console.log(res)
listenValueChange()
uni.showToast({
title: 已开启监听
})
},
fail(err) {
console.error(err)
uni.showToast({
title: 监听失败,
icon: error
})
}
})
}
// ArrayBuffer转16进度字符串示例
function ab2hex(buffer) {
const hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function (bit) {
return (00 + bit.toString(16)).slice(-2)
}
)
return hexArr.join()
}
// 将16进制的内容转成我们看得懂的字符串内容
function hexCharCodeToStr(hexCharCodeStr) {
var trimedStr = hexCharCodeStr.trim();
var rawStr = trimedStr.substr(0, 2).toLowerCase() === "0x" ? trimedStr.substr(2) : trimedStr;
var len = rawStr.length;
if (len % 2 !== 0) {
alert("存在非法字符!");
return "";
}
var curCharCode;
var resultStr = [];
for (var i = 0; i < len; i = i + 2) {
curCharCode = parseInt(rawStr.substr(i, 2), 16);
resultStr.push(String.fromCharCode(curCharCode));
}
return resultStr.join("");
}
// 监听到的内容
const message = ref()
const messageHex = ref() // 十六进制
// 【9】监听消息变化
function listenValueChange() {
uni.onBLECharacteristicValueChange(res => {
console.log(res)
let resHex = ab2hex(res.value)
console.log(resHex)
messageHex.value = resHex
let result = hexCharCodeToStr(resHex)
console.log(String(result))
message.value = String(result)
})
}
// 【10】发送数据
function send() {
// 向蓝牙设备发送一个0x00的16进制数据
let msg = hello
const buffer = new ArrayBuffer(msg.length)
const dataView = new DataView(buffer)
// dataView.setUint8(0, 0)
for (var i = 0; i < msg.length; i++) {
dataView.setUint8(i, msg.charAt(i).charCodeAt())
}
uni.writeBLECharacteristicValue({
deviceId: deviceId.value,
serviceId: serviceId.value,
characteristicId: characteristicId.value,
value: buffer,
success(res) {
console.log(writeBLECharacteristicValue success, res.errMsg)
uni.showToast({
title: write指令发送成功
})
},
fail(err) {
console.error(err)
uni.showToast({
title: write指令发送失败,
icon: error
})
}
})
}
// 【11】读取数据
function read() {
uni.readBLECharacteristicValue({
deviceId: deviceId.value,
serviceId: serviceId.value,
characteristicId: characteristicId.value,
success(res) {
console.log(res)
uni.showToast({
title: read指令发送成功
})
},
fail(err) {
console.error(err)
uni.showToast({
title: read指令发送失败,
icon: error
})
}
})
} </script>
<style> .box {
width: 98%;
height: 400rpx;
box-sizing: border-box;
margin: 0 auto 20rpx;
border: 2px solid dodgerblue;
}
.item {
box-sizing: border-box;
padding: 10rpx;
border-bottom: 1px solid #ccc;
}
button {
margin-bottom: 20rpx;
}
.msg_x {
border: 2px solid seagreen;
width: 98%;
margin: 10rpx auto;
box-sizing: border-box;
padding: 20rpx;
}
.msg_x .msg_txt {
margin-bottom: 20rpx;
} </style>
本文转载于:
https://blog.csdn.net/pfourfire/article/details/124711068
如果对您有所帮助 ,欢迎您点个关注 ,我会定时更新技术文档 ,大家一起讨论学习 ,一起进步 。
声明:本站所有文章 ,如无特殊说明或标注 ,均为本站原创发布 。任何个人或组织 ,在未征得本站同意时,禁止复制 、盗用 、采集 、发布本站内容到任何网站 、书籍等各类媒体平台 。如若本站内容侵犯了原著者的合法权益 ,可联系我们进行处理 。