Jidea
Jidea
  • 发布:2024-04-05 10:14
  • 更新:2024-09-10 08:55
  • 阅读:399

【报Bug】uni.getBLEDeviceServices获取的services为空

分类:uni-app

产品分类: uniapp/App

PC开发环境操作系统: Mac

PC开发环境操作系统版本号: 12.7.4 (21H1123)

HBuilderX类型: 正式

HBuilderX版本号: 4.08

手机系统: Android

手机系统版本号: Android 13

手机厂商: 小米

手机机型: redmi k40

页面类型: vue

vue版本: vue2

打包方式: 离线

项目创建方式: HBuilderX

示例代码:

<template>
<view class="content">
<scroll-view scroll-y class="box">
<view class="item" :style="(index+1)!=ble_list.length?'border-bottom:1px solid #aaa':'border-bottom:0'"
v-for="(item,index) in ble_list">
<view class="item_2">
<view class="ble">

                </view>  
            </view>  
            <view class="item_2">  
                <view>  
                    <text>Id: {{ item.deviceId }}</text>  
                </view>  
                <view>  
                    <text>Name: {{ item.name?item.name:item.localName }}</text>  
                </view>  
            </view>  
            <view class="item_2">  
                <h2>{{index+1}}</h2>  
            </view>  
            <view class="item_2">  
                <!-- <button  
                    @tap="deviceId==item.deviceId?closeBLEConnect():createBLEConnection(item.deviceId)">{{(deviceId===item.deviceId && deviceId)?'断开':'连接'}}</button> -->  

                <text class="text_on" v-if="deviceId!=item.deviceId"  
                    @tap="createBLEConnection(item.deviceId)">连接</text>  
                <text class="text_off" v-if="deviceId==item.deviceId"  
                    @tap="closeBLEConnect(item.deviceId)">断开</text>  
            </view>  
            <br>  
        </view>  
    </scroll-view><button type="warn" @click="openBluetoothAdapter">重新搜索附近蓝牙设备</button>  
    <view class="send_view">  
        <input type="text" placeholder="请输入要发送至蓝牙设备的内容" v-model="to_ble_text"><button type="primary"  
            @tap="writeBLECharacteristicValue(to_ble_text)">发送</button>  
    </view>  

    <view class="msg_x">  
        蓝牙传来的内容:  
        <view class="msg_txt" :style="(index+1)!=ble_list.length?'border-bottom:1px solid #aaa':'border-bottom:0'"  
            v-for="(item,index) in on_ble_text">  
            <h3>{{index+1}}</h3>  
            <p>时间:{{item.time}}</p>  
            <p>内容:<strong>{{item.text}}</strong></p>  
        </view>  
    </view>  
    ​  
</view>  

</template>

<script>
let thia;
export default {
data() {
return {
ble_list: [], //设备列表
deviceId: '',
to_ble_text: '',
on_ble_text: [],
}
},
mounted() {
thia = this;
},
methods: {
seachDevice() {
if (!this.discovering) {
this.openBluetoothAdapter();
if (this.Connecting) {
this.closeBLEConnect(this.deviceId);
}
} else {
this.Toast("正在扫描中,请等待");
}

        },  
        //检查蓝牙打开,初始化蓝牙  
        openBluetoothAdapter() {  
            uni.openBluetoothAdapter({  
                success: (res) => {  
                    //初始化成功,搜索设备  
                    setTimeout(() => {  
                        this.deviceList = []; //每次扫描清空设备列表,不然会导致重复  
                        this.startBluetoothDeviceDiscovery();  
                    }, 100);  
                    //定时关闭搜索设备  
                    setTimeout(() => {  
                        this.stopBluetoothDevicesDiscovery();  
                    }, 5 * 1000);  
                },  
                fail: err => {  
                    uni.showToast({  
                        title: '请确认手机蓝牙是否打开'  
                    })  
                }  
            })  
        },  
        //这里是开启蓝牙搜寻    
        startBluetoothDeviceDiscovery() {  
            uni.startBluetoothDevicesDiscovery({  
                success: (resd) => {  
                    console.log("打开成功", resd);  
                },  
                fail: err => {  
                    console.error("startBluetoothDevicesDiscoveryErr", err);  
                    this.Toast("请检查蓝牙状态")  
                }  
            })  
        },  
        //关闭蓝牙搜索  
        stopBluetoothDevicesDiscovery() {  
            uni.stopBluetoothDevicesDiscovery({  
                success: res => {  
                    uni.hideLoading()  
                }  
            })  
        },  

        //监听连接状态  
        onBLEConnectionStateChange() {  
            uni.onBLEConnectionStateChange(res => {  
                console.log(`设备 ${res.deviceId},connected: ${res.connected}`)  
                if (!res.connected) {  
                    thia.deviceId = '';  
                    thia.$forceUpdate();  
                }  
                this.Connecting = res.connected;  
                this.deviceId = res.deviceId;  
            })  
        },  
        /*连接低功耗蓝牙设备  
          @params deviceId  蓝牙设备id  
          0 ok  正常  
          10000 not init    未初始化蓝牙适配器  
          10001 not available   当前蓝牙适配器不可用  
          10002 no device   没有找到指定设备  
          10003 connection fail 连接失败  
          10004 no service  没有找到指定服务  
          10005 no characteristic   没有找到指定特征值  
          10006 no connection   当前连接已断开  
          10007 property not support    当前特征值不支持此操作  
          10008 system error    其余所有系统上报的异常  
          10009 system not support  Android 系统特有,系统版本低于 4.3 不支持 BLE  
        */  
        createBLEConnection(deviceId) {  
            console.log(deviceId)  
            if (this.discovering) {  
                this.stopBluetoothDevicesDiscovery()  
            }  
            if (this.Connecting) {  
                this.Toast("设备已连接");  
                return  
            }  
            uni.showLoading({  
                title: "连接设备中..."  
            })  

            uni.createBLEConnection({  
                deviceId,  
                success: res => {  
                    uni.hideLoading();  
                    thia.Toast('设备连接成功')  

                    setTimeout(() => {  
                        thia.deviceId = deviceId;  
                    }, 10)  

                    //获取蓝牙服务  
                    setTimeout(() => {  

                        thia.getBLEDeviceServices(deviceId);  
                        // thia.writeBLECharacteristicValue("5555555555555555")  
                    }, 15000)  

                },  
                fail: err => {  
                    uni.hideLoading();  
                    this.Toast('设备连接失败,请检查重试')  
                    if (err.errCode == -1) {  
                        this.closeBLEConnect(deviceId)  
                    }  
                }  
            })  
        },  
        /*获取蓝牙设备所有服务(service)。  
          连接蓝牙后调用  
         @parmas deviceId  蓝牙设备id  
        */  
        getBLEDeviceServices(deviceId) {  
            console.log('执行到getBLEDeviceServices:deviceId='+deviceId)  
            const _this = this;  
            setTimeout(() => {  
                uni.getBLEDeviceServices({  
                    deviceId,  
                    success(res) {  
                        //获取特征值  
                        let services = res.services;  
                        console.log(res);  
                        _this.serviceUUID = services[2].uuid;  
                        console.log('serviceUUID:' + _this.serviceUUID)  
                        this.getBLEDeviceCharacteristics(deviceId, _this.serviceUUID).then(res => {  
                            console.log(res);  

                            _this.notifyUUid = res.characteristics[0].uuid  
                            console.log('notifyUUid:' + _this.notifyUUid)  

                            _this.writeUUid = res.characteristics[1].uuid  
                            console.log('writeUUid:' + _this.writeUUid)  
                            uni.notifyBLECharacteristicValueChange({  
                                deviceId: deviceId,  
                                serviceId: _this.serviceUUID,  
                                characteristicId: _this.notifyUUid,  
                                state: true,  
                                success: (res) => {  
                                    console.log("广播开启成功")  
                                    _this.onBLECharacteristicValueChange();  
                                },  
                                fail: (err) => {  
                                    console.error(err)  
                                }  
                            })  
                            // setTimeout(() => {  
                            //  _this.writeBLECharacteristicValue([0x5A, 0x03,  
                            //      0xFF  
                            //  ])  
                            // }, 2000)  
                        })  

                    },  
                    fail: err => {  
                        console.warn("设备服务Error" + err)  
                    }  
                })  
            }, 10000)  

        },  
        /*向蓝牙设备中写入数据  
            @parmas  deviceId 蓝牙设备 id  
            @parmas  serviceId  蓝牙特征值对应服务的 uuid  
            @parmas  characteristicId 蓝牙特征值的 uuid  
            @parmas  value  ArrayBuffer 蓝牙设备特征值对应的二进制值  
        */  
        writeBLECharacteristicValue(value) {  
            if (this.deviceId) {  
                if (value) {  
                    uni.writeBLECharacteristicValue({  
                        deviceId: this.deviceId,  
                        serviceId: this.serviceUUID,  
                        characteristicId: this.writeUUid,  
                        value: thia.stringToArrayBuffer(value),  
                        success: res => {  
                            console.log("写入成功", res)  
                        },  
                        fail: err => {  
                            console.error("写入失败", err)  
                        }  
                    })  
                } else {  
                    this.Toast('请输入要发送的内容')  
                }  
            } else {  
                this.Toast('您还未连接上任何蓝牙')  
            }  

        },  
        // 监测低功耗蓝牙设备变化  
        onBLECharacteristicValueChange() {  
            uni.onBLECharacteristicValueChange(res => {  
                console.log(`监听低功耗蓝牙设备的特征值变化事件 ${res.characteristicId} has changed, now is ${res.value}`)  
                let text = String.fromCharCode.apply(null, new Uint8Array(res.value));  
                thia.on_ble_text.push({  
                    'time': thia.formatDate(new Date().getTime()),  
                    'text': text  
                });  
                console.log(text)  

            })  
        },  

        stringToArrayBuffer(str) { //字符串转arrarbuffer  
            var bytes = new Array();  
            var len, c;  
            len = str.length;  
            for (var i = 0; i < len; i++) {  
                c = str.charCodeAt(i);  
                if (c >= 0x010000 && c <= 0x10FFFF) {  
                    bytes.push(((c >> 18) & 0x07) | 0xF0);  
                    bytes.push(((c >> 12) & 0x3F) | 0x80);  
                    bytes.push(((c >> 6) & 0x3F) | 0x80);  
                    bytes.push((c & 0x3F) | 0x80);  
                } else if (c >= 0x000800 && c <= 0x00FFFF) {  
                    bytes.push(((c >> 12) & 0x0F) | 0xE0);  
                    bytes.push(((c >> 6) & 0x3F) | 0x80);  
                    bytes.push((c & 0x3F) | 0x80);  
                } else if (c >= 0x000080 && c <= 0x0007FF) {  
                    bytes.push(((c >> 6) & 0x1F) | 0xC0);  
                    bytes.push((c & 0x3F) | 0x80);  
                } else {  
                    bytes.push(c & 0xFF);  
                }  
            }  
            var array = new Int8Array(bytes.length);  
            for (var i in bytes) {  
                array[i] = bytes[i];  
            }  
            return array.buffer;  
        },  
        // arrayBufferToString(arr) {//arrarbuffer转字符串--小程序专用  
        //  if (typeof arr === 'string') {  
        //      return arr;  
        //  }  
        //  var dataview = new DataView(arr.data);  
        //  var ints = new Uint8Array(arr.data.byteLength);  
        //  for (var i = 0; i < ints.length; i++) {  
        //      ints[i] = dataview.getUint8(i);  
        //  }  
        //  arr = ints;  
        //  var str = '',  
        //      _arr = arr;  
        //  for (var i = 0; i < _arr.length; i++) {  
        //      var one = _arr[i].toString(2),  
        //          v = one.match(/^1+?(?=0)/);  
        //      if (v && one.length == 8) {  
        //          var bytesLength = v[0].length;  
        //          var store = _arr[i].toString(2).slice(7 - bytesLength);  
        //          for (var st = 1; st < bytesLength; st++) {  
        //              store += _arr[st + i].toString(2).slice(2);  
        //          }  
        //          str += String.fromCharCode(parseInt(store, 2));  
        //          i += bytesLength - 1;  
        //      } else {  
        //          str += String.fromCharCode(_arr[i]);  
        //      }  
        //  }  
        //  return str;  
        // },  

        /*获取蓝牙设备某个服务中所有特征值(characteristic)。  
          @parmas deviceId 设备id  
          @parmas serviceId 蓝牙服务uuid ,需要使用getBLEDeviceServices 获取  
        */  
        getBLEDeviceCharacteristics(deviceId, serviceId) {  
            const _this = this;  
            return new Promise((resolve, reject) => {  
                uni.getBLEDeviceCharacteristics({  
                    deviceId,  
                    serviceId,  
                    success: res => {  
                        resolve(res);  
                    },  
                    fail: err => {  
                        console.log("获取特征值失败", err)  
                        reject(err);  
                    }  
                })  
            })  
        },  
        /*断开蓝牙设备连接  
          @params deviceId  
        */  
        closeBLEConnect(deviceId = thia.deviceId) {  
            uni.closeBLEConnection({  
                deviceId,  
                success: res => {  
                    setTimeout(() => {  
                        thia.deviceId = '';  
                    }, 10)  
                    thia.$forceUpdate()  
                    thia.Toast('断开成功')  
                    console.log("断开成功", res);  
                },  
                fail: err => {  
                    console.error("断开错误", err);  
                }  
            });  
        },  
        /*获取蓝牙设备信号强度 @parmas deviceId 设备id */  
        getBLEDeviceRssi(deviceId) {  
            uni.getBLEDeviceRSSI({  
                deviceId,  
                success: res => {  
                    console.log("获取蓝牙设备强度成功", res);  
                },  
                fail: err => {  
                    console.error("获取蓝牙强度失败,", err);  
                }  
            })  
        },  
        /*读取蓝牙设备特征值的二进制数据  
          @parmas deviceId  蓝牙设备Id  
          @params serviceId  蓝牙特征值 对应服务的uuid  
          @params characteristicId 蓝牙特征值的 uuid  
        */  
        readBLEDeviceData(deviceId, serviceId, characteristicId) {  
            uni.readBLECharacteristicValue({  
                deviceId,  
                serviceId,  
                characteristicId,  
                success: res => {  
                    console.log("读取设备值成功", res);  
                },  
                fail: err => {  
                    console.error("读取设备值err", err)  
                }  
            })  
        },  

        Toast(title) {  
            uni.showToast({  
                title,  
                position: 'bottom',  
                icon: 'none'  
            })  
        },  
        formatDate(time) { //格式化日期  
            var date = new Date(time);  

            var year = date.getFullYear(),  
                month = date.getMonth() + 1, //月份是从0开始的  
                day = date.getDate(),  
                hour = date.getHours(),  
                min = date.getMinutes(),  
                sec = date.getSeconds();  
            var newTime = year + '-' +  
                month + '-' +  
                day + ' ' +  
                hour + ':' +  
                min + ':' +  
                sec;  
            return newTime;  
        }  

    },  
    onLoad() {  
        console.log(111111111111111111111)  

        //监听扫描到的蓝牙设备  
        uni.onBluetoothDeviceFound(resd => {  
            const devices = resd.devices;  
            console.log(JSON.stringify(devices[0]))  
            thia.ble_list.push(devices[0]);  
        })  
        this.onBLEConnectionStateChange();  
        this.seachDevice()  
        // this.onBLECharacteristicValueChange()  
    },  
    onUnload() {  
        if (this.discovering) {  
            this.stopBluetoothDevicesDiscovery();  
        }  
        if (this.Connecting) {  
            this.closeBLEConnect(this.deviceId);  
        }  
    },  

}  

</script>

<style lang="scss">
.content {
padding: 20rpx;
box-sizing: border-box;

}  

button {  
    border-radius: 20rpx;  
}  

.box {  
    height: 400rpx;  
    box-sizing: border-box;  
    margin: 0 auto 20rpx;  
    border: 2px solid #007aff;  
    padding: 30rpx;  
    border-radius: 30rpx;  
}  

.item {  
    display: flex;  
    box-sizing: border-box;  
    padding: 10rpx;  

    justify-content: space-between;  
    align-items: center;  

    .item_2 {  
        .text_on {  
            display: block;  
            text-align: center;  
            line-height: 80rpx;  
            width: 80rpx;  
            height: 80rpx;  
            border-radius: 50%;  
            box-shadow: inset 0 0 0px 2px #007aff;  
        }  

        .text_off {  
            display: block;  
            text-align: center;  
            line-height: 80rpx;  
            width: 80rpx;  
            height: 80rpx;  
            border-radius: 50%;  
            box-shadow: inset 0 0 0px 2px red;  
        }  

        // display: flex;  
        // align-items: center;  
        button {  
            margin: auto;  
        }  
    }  
}  

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;  
}  

.send_view {  
    display: flex;  
    justify-content: space-between;  
    align-items: center;  
    margin: 20rpx auto;  
    height: 100rpx;  
    border-radius: 20rpx;  
    border: 2px solid #007aff;  
    overflow: hidden;  
    padding: 0;  
    box-shadow: inset 0 0 0px 1px #007aff;  

    input {  
        width: calc(100% - 130rpx);  
        height: 100rpx;  
        font-size: 1.1em;  
        text-align: center;  
    }  

    button {  
        width: 130rpx;  
        height: 100rpx;  
        margin: 0;  
    }  
}  

.ble {  
    width: 80rpx;  
    height: 80rpx;  
    background-image: url("data:image/svg+xml,%3Csvg class='icon' viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='128' height='128'%3E%3Cpath d='M762.88 976.512H258.56c-114.56 0-207.36-92.8-207.36-207.36V264.704c0-114.56 92.8-207.36 207.36-207.36h504.32c114.56 0 207.36 92.8 207.36 207.36v504.448c0 114.56-92.8 207.36-207.36 207.36z' fill='%230079F5'/%3E%3Cpath d='M671.488 385.024L512.896 228.736c-12.672-12.544-34.176-3.456-34.176 14.336v196.096l-100.096-93.952c-1.408-1.408-3.712-1.28-5.12.128L344.96 375.68c-1.408 1.408-1.28 3.712.128 5.12L478.72 506.24v18.816l-133.504 124.16c-1.408 1.408-1.536 3.712-.128 5.12l28.416 30.464c1.408 1.408 3.712 1.536 5.12.128l100.224-93.184v198.912c0 17.792 21.504 26.88 34.176 14.336L671.488 648.96c7.936-7.808 7.936-20.736 0-28.672l-90.368-88.96c-7.936-7.808-7.936-20.736 0-28.672l90.368-89.088c8.064-7.808 8.064-20.736 0-28.544zm-143.872-73.088l87.552 86.272-87.04 80.896-.512-.512V311.936zm0 243.328l1.664-1.536 86.656 81.28-88.192 86.912V555.264z' fill='%23FFF'/%3E%3C/svg%3E");  
    background-repeat: no-repeat;  
    background-size: contain;  
    background-position: center;  
}  

</style>

操作步骤:

连接之后就会出现

预期结果:

希望获取到services然后接收到蓝牙的数据

实际结果:

services为[],无法接收到蓝牙的数据

bug描述:

蓝牙连接后 uni.getBLEDeviceServices 获取的services始终为空,延迟了50秒都不行,使用官方的测试工具nrf connect工具没有问题,可以获取到6个services

2024-04-05 10:14 负责人:无 分享
已邀请:
yangzhuowen

yangzhuowen

遇到了同样的问题,用微信小程序的文档同样的方法就能获取到serviceid,uniapp就为空

4***@qq.com

4***@qq.com

这个问题关注两年了,还没解决

要回复问题请先登录注册