本文简介

点赞 + 关注 + 珍藏 = 学会了


这是一次实在的 蓝牙收发数据 的全过程解说。


本文应用 uni-app + Vue3 的形式进行开发,以手机app的形式运行(微信小程序同样可行)。

uni-app 提供了 蓝牙低功耗蓝牙api ,和微信小程序提供的 api 是一样的,所以本文的解说也实用于微信小程序


本文只实现 蓝牙收发数据 性能,至于款式,我懒得调~

蓝牙相干性能我会逐渐解说。如果你根底好,又急的话,能够间接跳到 『残缺代码』的章节查看,那里没废话。


花了几块钱巨款买回来的蓝牙学习套装~



环境阐明

  • 开发工具:HBuilder X 3.4.7.20220422
  • uni-app + Vue3
  • 以安卓App的形式运行(iOS和小程序同理)



思路

蓝牙收发数据的逻辑和咱们罕用的 AJAX 进行的网络申请是有一丢丢不同的。

其中较大的区别是:蓝牙接收数据不是那么的稳固,相比起网络申请,蓝牙更容易呈现丢包的状况。


在开发中,AJAX 发动的申请不论胜利还是失败,浏览器根本都会给你一个回答。但 uni-app 提供的 api 来看,蓝牙接收数据会显得更加“异步”



大抵思路

应用蓝牙进行数据传输的大略思路如下:

  1. 初始化:关上蓝牙模块
  2. 搜查:检测左近存在的设施
  3. 连贯:找到指标设施进行
  4. 监听:开启监听性能,接管其余设施传过来的数据
  5. 发送指令:不论发送数据还是读取数据,都能够了解为向外发送指令



实现

下面整顿出应用蓝牙传输数据的5大动作,但每个动作其实都是由 uni-app 提供的一个或者多个 api 组合而成。


初始化阶段

应用蓝牙之前,须要初始化蓝牙模块,这是最最最开始就要做的!

应用 uni.openBluetoothAdapter 这个 api 就能够初始化蓝牙模块。其余蓝牙相干 API 必须在 uni.openBluetoothAdapter 调用之后应用。否则 API 会返回谬误( errCode=10000 )。

错误代码能够查阅 《错误码文档》

代码示例

<template>    <view>        <button @click="initBlue">初始化蓝牙</button>    </view></template><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步:

  1. 开启搜查性能uni.startBluetoothDevicesDiscovery
  2. 监听搜查到新设施uni.onBluetoothDeviceFound


开发蓝牙相干性能时,操作逻辑更像是推送,所以“开启搜寻”和“监听新设施”是离开操作的。


uni.startBluetoothDevicesDiscovery 能够让设施开始搜寻左近蓝牙设施,但这个办法比拟消耗系统资源,倡议在连贯到设施之后就应用 uni.stopBluetoothDevicesDiscovery 进行持续搜寻。

uni.startBluetoothDevicesDiscovery 办法里能够传入一个对象,该对象接管几个参数,但初学的话咱们只关注 successfail。如果你的我的项目中硬件佬有提供 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) 里,最初讲这个列表的数据渲染到页面上。



连贯指标设施

连贯指标设施只须要1个 api 就能实现。但依据文档提醒,咱们连贯后还须要敞开 “搜寻左近设施” 的性能,这个很好了解,既然找到了,再持续找就是浪费资源。


流程如下:

  1. 获取设施ID:依据 uni.onBluetoothDeviceFound 回调,拿到设施ID
  2. 连贯设施:应用设施ID进行连贯 uni.createBLEConnection
  3. 进行搜寻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])}// 蓝牙设施的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><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"}


连贯胜利后,设施也亮起了绿灯。



监听

在连贯完设施后,就要先开启监听数据的性能。这样能力接管到发送读写指令后设施给你回调的信息。

要开启监听,首先须要晓得蓝牙设施提供了那些服务,而后通过服务获取特征值,特征值会通知你哪个可读,哪个可写。最初依据特征值进行音讯监听


步骤如下:

  1. 获取蓝牙设施服务uni.getBLEDeviceServices
  2. 获取特征值uni.getBLEDeviceCharacteristics
  3. 开启音讯监听uni.notifyBLECharacteristicValueChange
  4. 接管音讯监听传来的数据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

在上两步我拿到了 设施IDB4:10:7B:C4:83:14服务ID0000FFE0-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.writeBLECharacteristicValuesuccess ,证实你曾经把数据向外胜利发送了,但不代表设施肯定就收到了。

通常设施收到你发送过来的信息,会返回一条音讯给你,而这个回调音讯会在 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 只负责发送读取的申请,并且外面的 successfail 只是返回你本次发送申请的动作是否胜利,至于对面的蓝牙设施有没有收到这个指令你是不分明的。

最初须要通过 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])}// 蓝牙设施的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><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>


以上就是本文的残缺代码。



相干文档

uni-app 蓝牙文档

uni-app 低功耗蓝牙文档


微信小程序 蓝牙文档

微信小程序 低功耗蓝牙文档



DataView 应用办法

举荐浏览

uni-app App端半屏间断扫码


记住:点赞 + 关注 + 珍藏 = 学会了

点赞 + 关注 + 珍藏 = 学会了