最新要闻
- 天天看热讯:想要模仿LPL,DRX赛后发漫画,却被Gen官方拉黑了?
- 焦点速读:Win11下月喜迎更新大礼包:10GB补丁 重启次数更少
- 【环球播资讯】员工发现老板娘偷看同事微信:火速离职
- 天天精选!车标成伤人凶器 日产召回超40万辆汽车
- 索尼降噪耳机新秀!WH-CH720N意外偷跑:升级蓝牙5.2
- 大国重器 首台国产HA级重型燃机下线:未来将100%零排放
- 每日看点!独立包装:大牌N95口罩25片9.9元到手
- 环球观速讯丨贾跃亭名下已无财产可执行:无车辆、不动产
- 【环球报资讯】苹果逐渐向OLED过渡!替换掉mini LED
- 世界消息!羊毛没了 Steam阿根廷区《卧龙》价格暴涨一倍
- 焦点讯息:一看就能装!奇瑞iCar原厂趣改套件上市:3389元起
- 【焦点热闻】舍利子制作方法居然也有发明专利 网友:得道高僧等级速升外挂
- 世界即时:跑腿师傅诉苦:男子订一束花送五个女生均被拒 还被扣款差评
- 微软将用UUP方式推送.NET更新:“可选更新”终于可控
- 钉钉iOS版喜迎更新:支持定时消息 再不怕打扰别人休息了
- 天天热讯:《星际争霸2》新晋中国世界冠军李培楠:别给暴雪送钱 不要买!
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
焦点观察:记录--『uni-app、小程序』蓝牙连接、读写数据全过程
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助
本文简介
这是一次真实的 蓝牙收发数据 的全过程讲解。
(资料图片仅供参考)
本文使用 uni-app + Vue3 的方式进行开发,以手机app的方式运行(微信小程序同样可行)。
uni-app 提供了 蓝牙 和 低功耗蓝牙 的 api ,和微信小程序提供的 api 是一样的,所以本文的讲解也适用于微信小程序。
本文只实现 蓝牙收发数据 功能,至于样式,我懒得调~
蓝牙相关功能我会逐步讲解。如果你基础好,又急的话,可以直接跳到 『完整代码』的章节查看,那里没废话。
环境说明
开发工具:HBuilder X 3.4.7.20220422uni-app + Vue3以安卓App的方式运行(iOS和小程序同理)
思路
蓝牙收发数据的逻辑和我们常用的 AJAX 进行的网络请求是有一丢丢不同的。
其中较大的区别是:蓝牙接收数据不是那么的稳定,相比起网络请求,蓝牙更容易出现丢包的情况。
在开发中,AJAX 发起的请求不管成功还是失败,浏览器基本都会给你一个答复。但 uni-app 提供的 api 来看,蓝牙接收数据会显得更加 “异步” 。
大致思路
使用蓝牙进行数据传输的大概思路如下:
初始化:打开蓝牙模块搜寻:检测附近存在的设备连接:找到目标设备进行监听:开启监听功能,接收其他设备传过来的数据发送指令:不管发送数据还是读取数据,都可以理解为向外发送指令
实现
上面整理出使用蓝牙传输数据的5大动作,但每个动作其实都是由 uni-app 提供的一个或者多个 api 组合而成。
初始化阶段
使用蓝牙之前,需要初始化蓝牙模块,这是最最最开始就要做的!
使用 uni.openBluetoothAdapter 这个 api 就可以初始化蓝牙模块。其他蓝牙相关 API 必须在 uni.openBluetoothAdapter 调用之后使用。否则 API 会返回错误( errCode=10000 )。
代码示例
<script setup> // 【1】初始化蓝牙function initBlue() { uni.openBluetoothAdapter({ success(res) { console.log("初始化蓝牙成功") console.log(res) }, fail(err) { console.log("初始化蓝牙失败") console.error(err) } })} </script>
如果你手机开启了蓝牙,点击页面上的按钮后,控制台就会输出如下内容
初始化蓝牙成功{"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 进行监听,这个方法里面接收一个回调函数。
代码示例
<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> id: {{ item.deviceId }} name: {{ item.name }}
上面代码的逻辑是,如果开启“寻找附近设备”功能成功,接着就开启“监听寻找到新设备的事件”。
搜索到的设备会返回以下数据:
{ "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 ,所以我点击了这条。
代码示例
<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])}// 蓝牙设备的idconst 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> id: {{ item.deviceId }} name: {{ item.name }}
连接成功后在控制台会输出
连接成功{"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
第一步,获取蓝牙服务
<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
。
<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 方法触发监听到的消息。
<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 。
代码示例
<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 里可以接收设备发送过来的数据。
代码示例
<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 监听设备传过来的数据。
完整代码
<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])}// 蓝牙设备的idconst 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,开发中需要问硬件佬获取该idconst 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> id: {{ item.deviceId }} name: {{ item.name }} 监听到的内容:{{ message }} 监听到的内容(十六进制):{{ messageHex }}
本文转载于:
https://blog.csdn.net/pfourfire/article/details/124711068
如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。
-
【全球报资讯】(数据库系统概论|王珊)第三章关系数据库标准语言SQL-第六、七节:视图
pdf下载:密码7281专栏目录首页:【专栏必读】(考研复试)数据库系统概论第五版(王珊)专栏学习笔记目...
来源: 焦点观察:记录--『uni-app、小程序』蓝牙连接、读写数据全过程
全球速看:PostgreSQL重要参数解析及优化
天天新动态:openeuler加载dpdk驱动模块
【全球报资讯】(数据库系统概论|王珊)第三章关系数据库标准语言SQL-第六、七节:视图
环球热头条丨【算法训练营day44】完全背包基础 LeetCode518. 零钱兑换II LeetCode377. 组合总和IV
天天看热讯:想要模仿LPL,DRX赛后发漫画,却被Gen官方拉黑了?
焦点速读:Win11下月喜迎更新大礼包:10GB补丁 重启次数更少
【环球播资讯】员工发现老板娘偷看同事微信:火速离职
天天精选!车标成伤人凶器 日产召回超40万辆汽车
索尼降噪耳机新秀!WH-CH720N意外偷跑:升级蓝牙5.2
大国重器 首台国产HA级重型燃机下线:未来将100%零排放
焦点!字体查看小工具 -- (采用wpf开发)
【算法训练营day43】LeetCode1049. 最后一块石头的重量II LeetCode494. 目标和 LeetCode474. 一和零
每日看点!独立包装:大牌N95口罩25片9.9元到手
环球观速讯丨贾跃亭名下已无财产可执行:无车辆、不动产
【环球报资讯】苹果逐渐向OLED过渡!替换掉mini LED
世界消息!羊毛没了 Steam阿根廷区《卧龙》价格暴涨一倍
焦点讯息:一看就能装!奇瑞iCar原厂趣改套件上市:3389元起
你应该知道的微信小程序游戏技术❗️❗️
【算法题--异或操作】找出数组中唯一没有重复的那个元素
极兔一面:Dockerfile如何优化?注意:千万不要只说减少层数
环球时讯:怎样的目标管理能真正实现目标?做到这3点就对了
开心档之Java 流(Stream)、文件(File)和IO
【焦点热闻】舍利子制作方法居然也有发明专利 网友:得道高僧等级速升外挂
世界即时:跑腿师傅诉苦:男子订一束花送五个女生均被拒 还被扣款差评
微软将用UUP方式推送.NET更新:“可选更新”终于可控
钉钉iOS版喜迎更新:支持定时消息 再不怕打扰别人休息了
天天热讯:《星际争霸2》新晋中国世界冠军李培楠:别给暴雪送钱 不要买!
天天最新:CSS 盒模型和 box-sizing 属性
环球讯息:全志h616,Ubuntu,python3.9环境搭建
【全球新要闻】【关系型数据库】事务特性及事务隔离级别
软件自动化测试高频面试题
环球百事通!游戏帧数暴增84% 英特尔锐炫显卡新老驱动对比
当前动态:山东多人无视劝阻赶海 1人溺水遇难:必须小心这4点
世界即时看!价值7万的爱马仕包运输途中被烧毁!顺丰:如果是我们的问题 会进行处理
天天速看:男子给女友转账140万分手想要回:女方最终被判返还40万
每日热门:媒体曝苹果扩大在印产量障碍重重:这品控看完避雷
新资讯:时隔多年,这次我终于把动态代理的源码翻了个地儿朝天
环球速读:AI照骗恐怖如斯!美女刷屏真假难辨 网友:警惕AI网恋诈骗
【全球时快讯】万元级最香!ROG四款满血笔记本齐上阵:魔霸新锐2023首发9999元手慢无
SQL工具性能实测:居然比Navicat还快,数百万行数据导出仅51秒
当前要闻:从上至下遍历二叉树---队列的性质
全球焦点!00后男生长期把可乐当水喝:牙全坏
《巫师3》次时代版热修复上线:解决4.01版性能问题
MINI纯电Countryman谍照
世界简讯:贾跃亭再被执行2.4亿:总额超42亿!自称FF91四月交付
车主称凯迪拉克新车刹车失灵高速上撞车 网友:这次支持4S
焦点要闻:xxl-job~为宿主机添加定时备份数据库的程序
扬汤止沸是什么意思?扬汤止沸是做功还是热传递?
生活中测量质量的工具有哪些?生活中测量质量的工具研究背景
每日观点:199元!小米30W无线车充开售:电动夹臂 iPhone也能用
天天快资讯:荣耀Magic5系列样张首曝光 AI无人抓拍或刷新拍照速度革命 2月27日全球发布!
全球头条:首发7999起 机械师曙光16 Pro开启预售:可选13代i9+RTX 4070
通讯!13倍浓缩:日本隅田川胶囊咖啡1.2元/杯大差价抄底
你最信任哪家快递公司?数千网友近一半投票给了它
露蜂房和蜂房有什么区别?露蜂房的功效和作用是什么?
漫画长歌行的结局是什么?漫画长歌行什么时候恢复更新?
汉武帝叫什么名字?汉武帝之后的皇位顺序
屏幕分辨率调不了是什么原因?屏幕分辨率调不了怎么解决?
荣事达手机怎么刷机?荣事达手机所有型号
海尔洗衣机e4怎么解决?海尔洗衣机故障代码大全
上海和首尔哪个更发达?上海和首尔咖啡馆数量
骁龙616处理器怎么样?骁龙616处理器相当于麒麟多少?
环球要闻:矩阵中的路径
当前速读:CF1753EF
环球微资讯!机器学习-决策树
三分钟使用chatGPT
全球观天下!关于Linux从内核启动选项中开启对ipv6的支持
京东券在哪里领?京东券怎么使用?
压力给到合资燃油车!比亚迪秦PLUS DM-i冠军版上市5天订单破2.5万
每日热闻!真我GT Neo5成为史上最畅销的安卓1TB手机:首销被抢购一空
热点!非机械键盘不买?你可能不了解薄膜键盘
天天报道:一箱油跑1100km 五菱凯捷混动铂金版将上市:演员周迅成首位车主
控制空调、收音机 无缝显示油量!全新一代苹果Carplay年底推出
全球百事通!面试官:Lambda 表达式中的 forEach 如何提前终止?这次被问倒了!
天天讯息:从青铜到王者,揭秘 Serverless 自动化函数最佳配置
Linux常用命令
微资讯!转移国内工厂 彻底摆脱中国制造?印度坑惨苹果 iPhone良品率不到50%
环球快播:一次性带走29包 奥利奥缤纷零食大礼包狂促:券后29.9元
世界滚动:比小米猛!曝Redmi K60将推出1TB版本:彻底解决微信存储焦虑
重庆阿姨参加免费活动微信被封 腾讯客服:发布刷单欺诈消息 已解封
天天精选!索尼出品!《圣斗士星矢》真人电影最新预告发布 4月28日上映
每日聚焦:UiPath 初探
canvas画板(鼠标和触摸)
天天速看:史上最大客机订单!印度航空采购波音、空客近500架客机
全球消息!199元 小米米家智能电子血压计众筹:支持联网远程监测
观天下!你怎么看?国内多地学校尝试推作业熔断机制:超过9点无条件停做
“中国复眼”二期开工!事关我国近地小行星撞击防御
环球热资讯!天选之子!女子来西安旅游买30元彩票中了1800万 网友调侃又骗我买彩票
【当前热闻】读Java实战(第二版)笔记10_函数式编程的技巧
历史一刻!欧洲宣布禁止燃油车 时间确定:中国新能源汽车笑了
天天资讯:2 - 【RocketMQ 系列】CentOS 7.6 安装部署RocketMQ
【全球快播报】前端安全--CSRF攻防
期末复习——操作系统概述 chapter(0+1)
全球热文:期末复习——进程与线程
精选!暴雪服务器消失后 《星际争霸2》多了个中国世界冠军
ChatGPT火爆 韩国厂商天降喜事:HBM内存价格涨了5倍
热门看点:情人节晚上 我的被窝里只有童年回忆杀
离开太阳系!旅行者号要给外星人讲讲人类的爱情
创建.a静态库, framework静态库