1***@qq.com
1***@qq.com
  • 发布:2025-07-15 11:20
  • 更新:2025-07-15 11:22
  • 阅读:23

【报Bug】uni.closeBLEConnection进入success后,实际并未与蓝牙设备断开连接

分类:uni-app

产品分类: uniapp/App

PC开发环境操作系统: Windows

PC开发环境操作系统版本号: Win11

HBuilderX类型: 正式

HBuilderX版本号: 4.75

手机系统: Android

手机系统版本号: Android 9.0

手机厂商: 华为

手机机型: BND-AL00

页面类型: vue

vue版本: vue2

打包方式: 云端

项目创建方式: HBuilderX

App下载地址或H5⽹址: https://www.pgyer.com/jqzm

示例代码:

<template>
<view class="container">
<!-- 蓝牙设备列表页 -->
<view v-if="currentPage === 'deviceList'">
<view class="title">蓝牙设备列表</view>

        <view class="status-bar">  
            <text>蓝牙状态: {{ bluetoothStatus }}</text>  
            <button class="btn" :disabled="isLoading" @click="toggleBluetooth">  
                {{ isBluetoothOpen ? '关闭蓝牙' : '开启蓝牙' }}  
            </button>  
        </view>  

        <view class="search-area">  
            <button class="btn search-btn" :disabled="!isBluetoothOpen || isSearching" @click="startSearch">  
                {{ isSearching ? '正在搜索...' : '搜索设备' }}  
            </button>  
            <text class="tips">{{ searchTips }}</text>  
        </view>  

        <view class="devices-list" v-if="deviceList.length > 0">  
            <view class="device-item" v-for="(device, index) in deviceList" :key="index"  
                :class="{'active': device.name === targetDeviceName}"  
                @click="connectDevice(device.deviceId, device.name)">  
                <text class="device-name">{{ device.name || '未知设备' }}</text>  
                <text class="device-rssi">{{ device.RSSI }}dBm</text>  
                <text class="device-status" v-if="device.name === targetDeviceName">已连接</text>  
            </view>  
        </view>  
    </view>  

    <!-- 主控制页面 -->  
    <view v-if="currentPage === 'controlPanel'">  
        <view class="title">蓝牙设备控制器</view>  

        <view class="status-bar">  
            <text>已连接: {{ targetDeviceName }}</text>  
            <button class="btn" @click="disconnectDevice(null)">断开连接</button>  
        </view>  
        <view class="receivLog">  
            <view>数据更新时间:{{receiveData.date}}</view>  
            <view>静电探测档位:{{receiveData.staticLevel}}</view>  
            <view>剩余照明时间:{{receiveData.lightingTime}}</view>  
            <view>照明档位:{{receiveData.lightingLevel}}</view>  
            <view>电池电量:{{receiveData.batteryLevel}}</view>  
        </view>  

        <view v-show="currentTab === 'splash' || currentTab === 'text'">  
            <text>发送间隔:</text>  
            <input type="number" v-model="inteval" class="txt" />  
        </view>  

        <view class="function-tabs">  
            <button class="tab-btn" :class="{'active': currentTab === 'mode'}"  
                @click="currentTab = 'mode'">检测模式</button>  
            <button class="tab-btn" :class="{'active': currentTab === 'brightness'}"  
                @click="currentTab = 'brightness'">照明模式</button>  
            <button class="tab-btn" :class="{'active': currentTab === 'splash'}"  
                @click="currentTab = 'splash'">开机画面</button>  
            <button class="tab-btn" :class="{'active': currentTab === 'text'}"  
                @click="currentTab = 'text'">文字设置</button>  
        </view>  

        <!-- 模式设置选项卡 -->  
        <view v-if="currentTab === 'mode'">  
            <view class="modes-area">  
                <view class="mode-title">选择静电探测档位</view>  
                <view class="modes-grid">  
                    <view class="mode-item" :class="{'selected': currentMode === 'high'}" @click="setMode('high')">  
                        <text class="mode-icon">?</text>  
                        <text class="mode-name">高档模式</text>  
                    </view>  
                    <view class="mode-item" :class="{'selected': currentMode === 'low'}" @click="setMode('low')">  
                        <text class="mode-icon">?</text>  
                        <text class="mode-name">中档模式</text>  
                    </view>  
                    <view class="mode-item" :class="{'selected': currentMode === 'flash'}"  
                        @click="setMode('flash')">  
                        <text class="mode-icon">?</text>  
                        <text class="mode-name">低档模式</text>  
                    </view>  
                </view>  
            </view>  
        </view>  

        <!-- 亮度调节选项卡 -->  
        <view v-if="currentTab === 'brightness'">  
            <view class="brightness-area">  
                <view class="brightness-title">照明模式</view>  
                <button class="tab-btn" :class="{'active': brightnessStatu}"  
                    @click="setBrightness(true)">开启</button>  
                <button class="tab-btn" :class="{'active': !brightnessStatu}"  
                    @click="setBrightness(false)">关闭</button>  
            </view>  
        </view>  

        <!-- 开机画面选项卡 -->  
        <view v-if="currentTab === 'splash'">  
            <view class="splash-controls">  
                <button class="btn" @click="importImage">导入图片</button>  

                <button class="btn" :disabled="!hasImage || isSending" @click="sendSplashImage">确认发送</button>  
            </view>  

            <view class="splash-preview">  
                <view class="splash-frame">  
                    <image v-if="tempImagePath" :src="tempImagePath" mode="aspectFill" :style="imageStyle"  
                        @touchstart="onTouchStart" @touchmove="onTouchMove" @touchend="onTouchEnd"></image>  
                    <view v-else class="empty-frame">点击"导入图片"选择开机画面</view>  
                </view>  
                <view class="frame-info">  
                    <text>框选区域: 160×80像素</text>  
                    <text v-if="hasImage">缩放: {{ scale.toFixed(2) }}x</text>  
                </view>  
            </view>  

            <view class="sending-progress" v-if="isSending">  
                <view class="progress-bar">  
                    <view class="progress-fill" :style="{ width: progress + '%' }"></view>  
                </view>  
                <text>正在发送: {{ progress }}% ({{ currentPacket }}/{{ totalPackets }})</text>  
            </view>  
        </view>  

        <!-- 文字设置选项卡 -->  
        <view v-if="currentTab === 'text'">  
            <view class="text-inputs">  
                <view class="text-line" v-for="(line, index) in textLines" :key="index">  
                    <text>第{{ index + 1 }}行:</text>  
                    <input v-model="textLines[index]" placeholder="请输入文字" maxlength="30"  
                        @confirm="onTextChanged(index)" />  
                </view>  
            </view>  

            <button class="btn send-text-btn" :disabled="isSendingText" @click="sendText">发送文字</button>  

            <view class="sending-progress" v-if="isSendingText">  
                <view class="progress-bar">  
                    <view class="progress-fill" :style="{ width: textProgress + '%' }"></view>  
                </view>  
                <text>正在发送: {{ textProgress }}% ({{ currentTextPacket }}/{{ totalTextPackets }})</text>  
            </view>  
        </view>  
    </view>  

    <!-- 隐藏的canvas用于图片处理 -->  
    <canvas canvas-id="splashCanvas" style="width: 160px; height: 80px; z-index: 9999;position: fixed; "  
        :style="{top:canvasTop,left:canvasLeft}" </canvas>  
</view>  

</template>

<script>
import gbk from '@/utils/gbk.js';
export default {
data() {
return {
canvasTop: '-1000px',
canvasLeft: '-1000px',
inteval: 50,
isLoading: false,
isBluetoothOpen: false,
isSearching: false,
isConnected: false,
isSending: false,
isSendingText: false,
bluetoothStatus: '未初始化',
searchTips: '',
deviceList: [],
connectedDeviceId: '',
serviceId: '0xFFE1',
writeCharacteristicId: '0xFFE1',
notifyCharacteristicId: '0xFFE2',
currentMode: '',
logList: [],
packetCount: 1,
currentPage: 'deviceList',
targetDeviceName: 'JQZM-EF4651',
currentTab: 'mode',
brightness: 50,
brightnessTimer: null,
tempImagePath: '',
hasImage: false,
scale: 1,
translateX: 0,
translateY: 0,
lastX: 0,
lastY: 0,
isDragging: false,
progress: 0,
currentPacket: 0,
totalPackets: 100,
imageWidth: 0,
imageHeight: 0,
textLines: ['你好中国', '你好中国', '你好中国', '你好中国'],
textProgress: 0,
currentTextPacket: 0,
totalTextPackets: 4,
brightnessStatu: false,
receiveData:
{
"date":"",
"staticLevel": "",
"lightingLevel": "",
"lightingTime": "",
"batteryLevel": ""
},
subscits:[]

        }  
    },  
    computed: {  
        imageStyle() {  
            return `transform: scale(${this.scale}) translate(${this.translateX}px, ${this.translateY}px); transform-origin: 0 0;`;  
        }  
    },  
    onLoad() {  

        // debugger;  
        //  // const iconv = require('iconv-lite');  
        // // 假设我们有一个UTF-8编码的字符串  
        // let utf8String = '你好,世界!';  

        // // 使用iconv-lite将字符串从UTF-8编码转换为GBK编码  
        // let gbkBuffer = iconv.encode(utf8String, 'GBK');  

        // console.log('转换后的GBK编码Buffer对象:', gbkBuffer)  

        this.initBluetoothAdapter();  
    },  

    methods: {  
        //灯光打开与关闭  
        setBrightness(flag) {  
            if (this.brightnessStatu == flag) {  
                return;  

            }  
            this.brightnessStatu = flag;  

            setTimeout(() => {  
                const buffer = new ArrayBuffer(6);  
                const dataView = new DataView(buffer);  

                dataView.setUint8(0, 0x55); // 帧头  
                dataView.setUint8(1, 0x00); // 帧类型  
                dataView.setUint8(2, 0x01); // 包序号  
                dataView.setUint8(3, 0x00); // 数据长度  
                dataView.setUint8(4, 0x01); // 数据长度  
                dataView.setUint8(5, flag ? 0x6e : 0x6f); // 数据  

                // 发送数据  
                this.sendData(buffer);  

            }, 0);  
        },  
        // 蓝牙初始化  
        initBluetoothAdapter() {  
            console.log('开始初始化蓝牙适配器');  
            uni.openBluetoothAdapter({  
                success: (res) => {  
                    this.isBluetoothOpen = true;  
                    this.bluetoothStatus = '已开启';  
                    console.log('蓝牙适配器初始化成功');  
                    this.getBluetoothAdapterState();  

                    // 自动开始搜索设备  
                    this.startSearch();  
                },  
                fail: (err) => {  
                    this.bluetoothStatus = '初始化失败';  
                    console.log(`蓝牙适配器初始化失败: ${err.errMsg}`);  
                    if (err.errCode === 10001) {  
                        uni.onBluetoothAdapterStateChange((res) => {  
                            if (res.available) {  
                                this.isBluetoothOpen = true;  
                                this.bluetoothStatus = '已开启';  
                                console.log('蓝牙适配器已开启');  
                                this.startSearch();  
                            }  
                        });  
                    }  
                }  
            });  
        },  

        // 获取蓝牙适配器状态  
        getBluetoothAdapterState() {  
            uni.getBluetoothAdapterState({  
                success: (res) => {  
                    this.isBluetoothOpen = res.available;  
                    this.bluetoothStatus = res.available ? '已开启' : '已关闭';  
                    if (!res.available) {  
                        console.log('蓝牙适配器未开启');  
                    }  
                }  
            });  
        },  

        // 开关蓝牙  
        toggleBluetooth() {  
            if (this.isBluetoothOpen) {  
                this.closeBluetoothAdapter();                     
            } else {  
                this.initBluetoothAdapter();  
            }  
        },  

        // 关闭蓝牙适配器  
        closeBluetoothAdapter() {  

            this.stopSearch();  
            this.disconnectDevice(()=>{  
                uni.closeBluetoothAdapter({  
                    success: () => {  
                        console.log("蓝牙已关闭");  
                        this.isBluetoothOpen = false;  
                        this.isSearching = false;  
                        this.isConnected = false;  
                        this.bluetoothStatus = '已关闭';  
                        this.deviceList = [];  
                        this.connectedDeviceId = '';  
                        this.currentMode = '';  
                        this.currentPage = 'deviceList';  
                    }  
                })  
            });  

        },  

        // 开始搜索蓝牙设备  
        startSearch() {  
            if (this.isSearching) return;  

            this.isSearching = true;  
            this.deviceList = [];  
            this.searchTips = '搜索中...';  
            console.log('开始搜索蓝牙设备');  

            uni.startBluetoothDevicesDiscovery({  
                services: ["0xFFE0"],  
                allowDuplicatesKey: false,  
                success: (res) => {  
                    console.log('开始搜索蓝牙设备成功');  
                    this.onDeviceFound();  

                },  
                fail: (err) => {  
                    this.isSearching = false;  
                    this.searchTips = '搜索失败';  
                    console.log(`搜索蓝牙设备失败: ${err.errMsg}`);  
                }  
            });  
        },  

        // 停止搜索蓝牙设备  
        stopSearch() {  
            this.isSearching = false;  
            this.searchTips = this.deviceList.length > 0 ? '搜索完成' : '未发现蓝牙设备';  

            uni.stopBluetoothDevicesDiscovery({  
                success: () => {  
                    console.log('停止搜索蓝牙设备');  
                }  
            });  
        },  

        // 监听发现新设备  
        onDeviceFound() {  
            uni.onBluetoothDeviceFound((res) => {  
                const device = res.devices[0];  
                if (!device.name && !device.localName) return;  
                // if ((device.name || device.localName) === this.targetDeviceName) {  
                // 检查是否已存在该设备  
                const index = this.deviceList.findIndex(item => item.deviceId === device.deviceId);  
                if (index === -1) {  
                    this.deviceList.push({  
                        deviceId: device.deviceId,  
                        name: device.name || device.localName,  
                        RSSI: device.RSSI  
                    });  
                } else {  
                    // 更新信号强度  
                    this.deviceList[index].RSSI = device.RSSI;  

                }  
                // }  

                // 如果找到目标设备,自动连接  
                if ((device.name || device.localName) === this.targetDeviceName) {  
                    console.log(`发现目标设备: ${JSON.stringify(device)}`);  
                    this.connectDevice(device.deviceId, this.targetDeviceName);  
                }  
            });  
        },  

        // 连接蓝牙设备  
        connectDevice(deviceId, deviceName) {  
            if (this.isConnected && this.connectedDeviceId === deviceId) return;  

            this.isLoading = true;  
            console.log(`开始连接设备: ${deviceName}`);  
            var these = this;  
            uni.createBLEConnection({  
                deviceId: deviceId,  
                timeout: 10000,  
                success: (res) => {  
                    this.isConnected = true;  
                    this.connectedDeviceId = deviceId;  
                    this.targetDeviceName = deviceName;  
                    console.log(`连接设备 ${deviceName} 成功`);  
                    this.enableNotification(deviceId);  
                    // 连接成功后切换到控制面板  
                    this.currentPage = 'controlPanel';  

                    setTimeout(function() {  
                        uni.setBLEMTU({  
                            deviceId: deviceId,  
                            mtu: 512,  
                            success: (info) => {  
                                console.log("设置mtu成功")  
                            },  
                            fail: (ex) => {  
                                console.log("设置mtu失败" + JSON.stringify(ex));  
                            }  
                        })  

                        these.getDeviceServices(deviceId);  
                    }, 2000)  

                    this.stopSearch();  
                },  
                fail: (err) => {  
                    console.log(`连接设备失败: ${JSON.stringify(err)}`);  
                    uni.showToast({  
                        title: '连接失败',  
                        icon: 'none'  
                    });  
                },  
                complete: () => {  
                    this.isLoading = false;  
                }  
            });  
        },  

        // 断开蓝牙连接  
        disconnectDevice(callback) {  
            var these = this;  
            var promises=[];  
            for (var i = 0; i < these.subscits.length; i++) {  
                promises.push(new Promise((succ,err)=>{  
                    uni.notifyBLECharacteristicValueChange({deviceId:these.connectedDeviceId,  
                    serviceId:these.subscits[i].serviceId,  
                    characteristicId:these.subscits[i].notifyId,  
                    state:false,  
                    success: () => {  
                        console.log("取消订阅成功");  
                        succ();  
                    },  
                    fail: () => {  
                        err();  
                    }});  
                }));  
            }  
            these.subscits=[];  
            Promise.all(promises).then(()=>{  
                if(!this.connectedDeviceId){  
                    this.isConnected = false;  
                    this.connectedDeviceId = '';  
                    this.currentMode = '';  
                    this.currentPage = 'deviceList';  
                    if(callback)  
                    {  
                        callback();  
                    }  
                    return;  
                }  
                setTimeout(()=>{  
                    uni.closeBLEConnection({  
                    deviceId: this.connectedDeviceId,  
                    success: (res) => {  

                        console.log('蓝牙连接已断开'+JSON.stringify(res));  

                    },fail:(ex)=>{  
                        let arr = [{  
                                code: 0,  
                                remark: '正常'  
                            },  
                            {  
                                code: 10000,  
                                remark: '未初始化蓝牙适配器'  
                            },  
                            {  
                                code: 10001,  
                                remark: '当前蓝牙适配器不可用'  
                            },  
                            {  
                                code: 10002,  
                                remark: '没有找到指定设备'  
                            },  
                            {  
                                code: 10003,  
                                remark: '连接失败'  
                            },  
                            {  
                                code: 10004,  
                                remark: '没有找到指定服务'  
                            },  
                            {  
                                code: 10005,  
                                remark: '没有找到指定特征值'  
                            },  
                            {  
                                code: 10006,  
                                remark: '当前连接已断开'  
                            },  
                            {  
                                code: 10007,  
                                remark: '当前特征值不支持此操作'  
                            },  
                            {  
                                code: 10008,  
                                remark: '其余所有系统上报的异常'  
                            },  
                            {  
                                code: 10009,  
                                remark: 'Android 系统特有,系统版本低于 4.3 不支持 BLE'  
                            },  
                            {  
                                code: 10010,  
                                remark: '已连接'  
                            },  
                            {  
                                code: 10011,  
                                remark: '配对设备需要配对码'  
                            },  
                            {  
                                code: 10012,  
                                remark: '连接超时'  
                            },  
                            {  
                                code: 10013,  
                                remark: '连接 deviceId 为空或者是格式不正确'  
                            }  
                        ];  
                        let f=arr.find(function(v){  
                            return v.code==ex.code;  
                        })  

                        console.log("无法断开蓝牙连接:"+ f.remark);  

                        uni.showToast({  
                            title: "无法断开蓝牙连接:"+ f.remark,  
                            icon: 'fail'  
                        });  

                    },  
                    complete: () => {  
                        this.isConnected = false;  
                        this.connectedDeviceId = '';  
                        this.currentMode = '';  
                        this.currentPage = 'deviceList';  
                        if(callback)  
                        {  
                            callback();  
                        }  
                    }  
                });  

                },200)  

            }).catch().finally();  

        },  

        // 获取设备服务  
        getDeviceServices(deviceId) {  
            console.log("deviceId=" + deviceId);  
            var these = this;  
            uni.getBLEDeviceServices({  
                deviceId: deviceId,  
                success: (res) => {  

                    console.log("发现服务" + JSON.stringify(res.services))  
                    if (res.services.length == 0) {  
                        setTimeout(function() {  
                            these.getDeviceServices(deviceId);  
                        }, 1000);  
                        return;  
                    }  
                    // 查找目标服务  
                    const targetService = res.services.find(service => service.uuid.indexOf('FFE0') > -1);  

                    if (targetService) {  
                        console.log(`找到目标服务: ${targetService.uuid}`);  
                        this.serviceId = targetService.uuid;  
                        this.getDeviceCharacteristics(deviceId, targetService.uuid);  
                    }  

                },  
                fail: (err) => {  
                    console.log(`获取设备服务失败: ${err.errMsg}`);  
                }  
            });  
        },  

        // 获取设备特征值  
        getDeviceCharacteristics(deviceId, serviceId) {  
            uni.getBLEDeviceCharacteristics({  
                deviceId: deviceId,  
                serviceId: serviceId,  
                success: (res) => {  
                    console.log(`获取设备特征值成功,共发现 ${res.characteristics.length} 个特征值`);  
                    console.log(`获取设备特征值成功${JSON.stringify(res.characteristics)}`);  
                    // 查找可写特征值  
                    const writeChar = res.characteristics.find(char =>  
                        char.uuid.indexOf("FFE1") >= 1  
                    );  

                    // 查找通知特征值  
                    const notifyChar = res.characteristics.find(char => {  
                            return char.properties.notify;  
                        }  

                    );  

                    if (writeChar) {  
                        console.log(`找到可写特征值: ${writeChar.uuid}`);  
                        this.writeCharacteristicId = writeChar.uuid;  
                    } else {  
                        console.log(`未找到可写特征值: ${this.writeCharacteristicId}`);  
                    }  

                    if (notifyChar) {  
                        console.log(`找到通知特征值: ${notifyChar.uuid}`);  
                        this.notifyCharacteristicId = notifyChar.uuid;  
                        console.log("serviceId=" + serviceId);  
                        console.log("characteristicId=" + notifyChar.uuid);  
                        this.subscits.push({deviceId:deviceId,serviceId,serviceId,notifyId:notifyChar.uuid});  
                        setTimeout(() => {  
                            uni.notifyBLECharacteristicValueChange({  
                                deviceId: deviceId,  
                                serviceId: serviceId,  
                                characteristicId: notifyChar.uuid,  
                                state: true,  
                                success: (info) => {  
                                    console.log('启用通知成功' + JSON.stringify(info));  
                                    uni.showToast({  
                                        title:"订阅消息成功",  
                                        icon:'success'  
                                    });  
                                    // 监听特征值变化   
                                    setTimeout(() => {  
                                        uni.onBLECharacteristicValueChange((  
                                            receive) => {  

                                            var bytesToHexString =  
                                                function(bytes) {  
                                                    return bytes.map(  
                                                        byte =>  
                                                        byte  
                                                        .toString(  
                                                            16)  
                                                        .padStart(  
                                                            2, '0')  
                                                        ).join(' ');  
                                                }  

                                            var parseData = (  
                                                bytes)=> {  
                                                 if (bytes.length < 6) {  
                                                    console.warn('数据包长度不足,至少需要6个字节');  
                                                    return;  
                                                  }  

                                                  try {  
                                                    // 跳过帧头(第一个字节),从第二个字节开始解析  
                                                    const staticLevelByte = bytes[1];  
                                                    let staticLevelText = '未知';  
                                                    switch (staticLevelByte) {  
                                                      case 0x65:  
                                                        staticLevelText = '高档';  
                                                        break;  
                                                      case 0x66:  
                                                        staticLevelText = '中档';  
                                                        break;  
                                                      case 0x67:  
                                                        staticLevelText = '低档';  
                                                        break;  
                                                      case 0x68:  
                                                        staticLevelText = '关闭';  
                                                        break;  
                                                    }  

                                                    // 解析照明档位  
                                                    const lightingLevelByte = bytes[2];  
                                                    const lightingLevelText = lightingLevelByte === 0x6e ? '开启' : '关闭';  

                                                    // 解析剩余照明时间(第三和第四字节,小端序)  
                                                    const lightingTime = (bytes[4] << 8) | bytes[3];  

                                                    // 解析剩余电量  
                                                    const batteryLevelByte = bytes[5];  
                                                    // 电量百分比范围检查  
                                                    const batteryLevel = Math.max(0, Math.min(100, batteryLevelByte));  

                                                    console.log('解析结果:', {  
                                                      staticLevel: staticLevelText,  
                                                      lightingLevel: lightingLevelText,  
                                                      lightingTime: `${lightingTime} 分钟`,  
                                                      batteryLevel: `${batteryLevel}%`  
                                                    });  
                                                    let date=new Date();  
                                                    this.receiveData.date=date.getHours()+":"+date.getMinutes()+":"+date.getSeconds();  
                                                this.receiveData.staticLevel=staticLevelText;  
                                                this.receiveData.lightingLevel=lightingLevelText;  
                                                this.receiveData.lightingTime=lightingTime+'分钟';  
                                                this.receiveData.batteryLevel=batteryLevel+'%';  

                                                  } catch (error) {  
                                                    console.error('数据解析错误:', error);  
                                                  }  
                                            }  

                                            const dataView =  
                                                new DataView(receive  
                                                    .value);  

                                            // 转换为字节数组  
                                            const bytes = [];  
                                            for (let i = 0; i <  
                                                dataView  
                                                .byteLength; i++) {  
                                                bytes.push(dataView  
                                                    .getUint8(i));  
                                            }  

                                            // 保存原始数据用于调试  
                                            this.receivedData = bytes;  
                                            console.log('接收到原始数据:',  
                                                bytesToHexString(  
                                                    bytes));  

                                                parseData(bytes);  

                                        });  
                                    }, 100)  

                                },  
                                fail: (err) => {  
                                    console.error('启用通知失败', err);  
                                }  
                            });  
                        }, 500);  

                    } else {  
                        console.log(`未找到通知特征值: ${this.notifyCharacteristicId}`);  
                    }  

                },  
                fail: (err) => {  
                    console.log(`获取设备特征值失败: ${err.errMsg}`);  
                }  
            });  
        },  

        // 启用通知  
        enableNotification(deviceId) {  
            // uni.notifyBLECharacteristicValueChange({  
            //  deviceId: deviceId,  
            //  serviceId: this.serviceId,  
            //  characteristicId: this.notifyCharacteristicId,  
            //  state: true,  
            //  success: () => {  
            //      console.log('启用通知成功');  

            //      // 监听通知  
            //      uni.onBLECharacteristicValueChange((res) => {  
            //          this.handleNotification(res.value);  
            //      });  
            //  },  
            //  fail: (err) => {  
            //      console.log(`启用通知失败: ${err.errMsg}`);  
            //  }  
            // });  
        },  

        // 处理通知数据  
        handleNotification(buffer) {  
            console.log("收到设备通知数据")  
            // 解析从设备接收的数据  
            const dataView = new DataView(buffer);  
            let result = '';  

            for (let i = 0; i < dataView.byteLength; i++) {  
                result += String.fromCharCode(dataView.getUint8(i));  
            }  

            console.log(`收到设备数据: ${result}`);  
        },  

        // 设置静电检测模式  
        setMode(mode) {  
            if (!this.isConnected) {  
                uni.showToast({  
                    title: '未连接设备',  
                    icon: 'none'  
                });  
                return;  
            }  

            if (this.currentMode === mode) return;  

            this.currentMode = mode;  
            let dataValue = 0;  

            switch (mode) {  
                case 'high':  
                    dataValue = 0x65; // 高档模式  
                    console.log('开始切换到高档模式');  
                    break;  
                case 'low':  
                    dataValue = 0x66; // 中档模式  
                    console.log('开始切换到中档模式');  
                    break;  
                case 'flash':  
                    dataValue = 0x67; // 低档模式  
                    console.log('开始切换到低档模式');  
                    break;  
            }  

            // 构建数据包  
            const buffer = new ArrayBuffer(6);  
            const dataView = new DataView(buffer);  

            dataView.setUint8(0, 0x55); // 帧头  
            dataView.setUint8(1, 0x00); // 帧类型  
            dataView.setUint8(2, 0x01); // 包序号  
            dataView.setUint8(3, 0x00); // 数据长度  
            dataView.setUint8(4, 0x01); // 数据长度  
            dataView.setUint8(5, dataValue); // 数据  

            // 发送数据  
            this.sendData(buffer);  
        },  

        // 亮度调节  
        onBrightnessChanging(e) {  
            this.brightness = e.detail.value;  

            // 清除之前的定时器  
            if (this.brightnessTimer) {  
                clearTimeout(this.brightnessTimer);  
            }  

            // 设置新的定时器,控制发送频率  
            this.brightnessTimer = setTimeout(() => {  
                this.sendBrightness();  
            }, 100);  
        },  

        onBrightnessChanged(e) {  
            this.brightness = e.detail.value;  
            //this.sendBrightness();  
        },  

        sendBrightness() {  
            if (!this.isConnected) return;  

            // 构建数据包  
            const buffer = new ArrayBuffer(6);  
            const dataView = new DataView(buffer);  
            let data = '0x' + parseInt(this.brightness).toString(16);  
            console.log("亮度:" + this.brightness + ',16进制:' + data);  
            dataView.setUint8(0, 0x55); // 帧头  
            dataView.setUint8(1, 0x01); // 帧类型:亮度调节  
            dataView.setUint8(2, 0x01); // 包序号  
            dataView.setUint8(3, 0x00); // 数据长度  
            dataView.setUint8(4, 0x01); // 数据长度  
            dataView.setUint8(5, data); // 数据  

            // 发送数据  
            this.sendData(buffer);  
        },  

        // 导入图片  
        importImage() {  
            uni.chooseImage({  
                count: 1,  
                sourceType: ['album'],  
                success: (res) => {  
                    this.tempImagePath = res.tempFilePaths[0];  
                    this.hasImage = true;  
                    this.scale = 1;  
                    this.translateX = 0;  
                    this.translateY = 0;  

                    // 获取图片尺寸  
                    uni.getImageInfo({  
                        src: this.tempImagePath,  
                        success: (info) => {  
                            this.imageWidth = info.width;  
                            this.imageHeight = info.height;  
                            this.autoFitImage();  
                            console.log('图片导入成功,请调整图片位置和大小');  
                        },  
                        fail: (err) => {  
                            console.log(`获取图片信息失败: ${err.errMsg}`);  
                        }  
                    });  
                },  
                fail: (err) => {  
                    console.log(`选择图片失败: ${err.errMsg}`);  
                }  
            });  
        },  

        // 自动适配图片到容器  
        autoFitImage() {  
            const frameWidth = 320; // 预览框宽度,根据实际UI调整  
            const frameHeight = 640; // 预览框高度,根据实际UI调整  

            const widthRatio = frameWidth / this.imageWidth;  
            const heightRatio = frameHeight / this.imageHeight;  

            // 取较小的缩放比例,确保图片能完全显示在容器内  
            this.scale = Math.min(widthRatio, heightRatio);  

            // 居中显示  
            this.translateX = (frameWidth - this.imageWidth * this.scale) / 2;  
            this.translateY = (frameHeight - this.imageHeight * this.scale) / 2;  
        },  

        // 触摸事件处理  
        onTouchStart(e) {  
            if (e.touches.length === 1) {  
                this.isDragging = true;  
                this.lastX = e.touches[0].clientX;  
                this.lastY = e.touches[0].clientY;  
            }  
        },  

        onTouchMove(e) {  
            if (this.isDragging && e.touches.length === 1) {  
                const currentX = e.touches[0].clientX;  
                const currentY = e.touches[0].clientY;  

                // 计算位移  
                const deltaX = currentX - this.lastX;  
                const deltaY = currentY - this.lastY;  

                // 更新位置  
                this.translateX += deltaX;  
                this.translateY += deltaY;  

                // 限制移动范围  
                this.limitImagePosition();  

                // 更新最后位置  
                this.lastX = currentX;  
                this.lastY = currentY;  
            }  
        },  

        onTouchEnd() {  
            this.isDragging = false;  
        },  

        // 限制图片移动范围  
        limitImagePosition() {  
            const frameWidth = 320; // 预览框宽度,根据实际UI调整  
            const frameHeight = 640; // 预览框高度,根据实际UI调整  

            const maxX = 0;  
            const minX = frameWidth - this.imageWidth * this.scale;  
            const maxY = 0;  
            const minY = frameHeight - this.imageHeight * this.scale;  

            this.translateX = Math.max(minX, Math.min(maxX, this.translateX));  
            this.translateY = Math.max(minY, Math.min(maxY, this.translateY));  
        },  

        // 发送开机画面  
        sendSplashImage() {  
            if (!this.hasImage) {  
                uni.showToast({  
                    title: '请先导入图片',  
                    icon: 'none'  
                });  
                return;  
            }  

            uni.showLoading({  
                title: '处理图片中...',  
                mask: true  
            });  

            // 将图片转换为RGB565格式并发送  
            this.convertAndSendImage().then(() => {  
                uni.hideLoading();  
                console.log('开机画面发送完成');  
                uni.showToast({  
                    title: '开机画面发送完成',  
                    icon: 'success'  
                });  
            }).catch((error) => {  
                uni.hideLoading();  
                console.log(`图片发送失败: ${error}`);  
                uni.showToast({  
                    title: '图片发送失败',  
                    icon: 'none'  
                });  
            });  
        },  

        // 转换图片并发送  
        convertAndSendImage() {  
            return new Promise((resolve, reject) => {  
                console.log("111111");  
                // 创建canvas用于处理图片  
                const ctx = uni.createCanvasContext('splashCanvas', this);  
                console.log("2222222");  
                // 绘制图片到canvas  
                ctx.drawImage(this.tempImagePath, 0, 0, 160, 80);  
                console.log("33333333");  
                try {  
                    ctx.draw(false, () => {  
                        console.log("4444444");  
                        // 获取canvas像素数据  
                        this.canvasTop = '0px';  
                        this.canvasLeft = '0px';  
                        setTimeout(() => {  
                            uni.canvasGetImageData({  
                                canvasId: 'splashCanvas',  
                                x: 0,  
                                y: 0,  
                                width: 160,  
                                height: 80,  
                                success: (res) => {  
                                    // 处理像素数据并发送  
                                    console.log("res.data.length=" + res.data  
                                        .length);  
                                    this.processAndSendImageData(res.data).then(  
                                        resolve).catch(reject);  
                                },  
                                fail: (err) => {  
                                    reject(`获取canvas数据失败: ${err.errMsg}`);  
                                }  
                            });  
                        }, 300); // 等待canvas绘制完成  
                    });  
                } catch (ex) {  
                    console.log("出现异常" + JSON.stringify(ex))  
                }  

            });  
        },  

        // 处理像素数据并发送  
        processAndSendImageData(pixels) {  
            return new Promise((resolve, reject) => {  
                // 创建RGB565格式的像素数据  
                const rgb565Data = this.convertToRGB565(pixels);  

                // 分包发送  
                this.sendImagePackets(rgb565Data).then(resolve).catch(reject);  
            });  
        },  

        // 将RGBA转换为RGB565  
        convertToRGB565(pixels) {  

            var rgbaToRgb565 = function(r, g, b, a = 255) {  
                // 忽略透明度(如果需要考虑透明度,请根据需求处理)  

                // 将8位颜色值压缩到RGB565对应的位数  
                const r5 = Math.round((r / 255) * 31); // 5位:0-31  
                const g6 = Math.round((g / 255) * 63); // 6位:0-63  
                const b5 = Math.round((b / 255) * 31); // 5位:0-31  

                // 合并为16位整数  
                return (r5 << 11) | (g6 << 5) | b5;  
            }  

            const result = new Uint16Array(160 * 80);  
            let index = 0;  
            console.log("pixels.length=" + pixels.length);  
            for (let i = 0; i < pixels.length; i += 4) {  
                const r = pixels[i];  
                const g = pixels[i + 1];  
                const b = pixels[i + 2];  

                // 转换为RGB565 (R:5bit, G:6bit, B:5bit)  
                const rgb565 = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);  
                //let rgb565=rgbaToRgb565(r,g,b);  
                result[index++] = rgb565;  
            }  

            return result;  
        },  

        // 分包发送图片数据  
        sendImagePackets(imageData) {  
            return new Promise((resolve, reject) => {  
                this.isSending = true;  
                this.progress = 0;  
                this.currentPacket = 0;  

                // 总数据包数  
                const totalPackets = 52;  
                let currentPacket = 1;  

                // 发送单个数据包  
                const sendNextPacket = () => {  
                    if (currentPacket > totalPackets) {  
                        this.isSending = false;  
                        resolve();  
                        return;  
                    }  

                    // 计算当前包的数据  
                    let packetSize = 250;  
                    if (currentPacket <= 51) {  
                        packetSize = 250; // 前51个包每个500字节  
                    } else {  
                        packetSize = 50; // 最后一个包100字节  
                    }  

                    // 创建数据包  
                    const startIndex = (currentPacket - 1) * packetSize;  
                    const endIndex = Math.min(startIndex + packetSize, imageData.length);  
                    if (startIndex > endIndex) {  
                        return;  
                    }  
                    const packetData = imageData.slice(startIndex,  
                        endIndex); // imageData.subarray(startIndex, endIndex);  
                    console.log("imageData.length=" + imageData.length + ",startIndex=" + startIndex +  
                        ",endIndex=" + endIndex + ",数据包长度" + (endIndex - startIndex) +  
                        ',packetData.length=' + packetData.length);  
                    // 构建数据包  
                    const bufferSize = 5 + packetData.length * 2; // 头部5字节 + 数据部分  
                    const buffer = new ArrayBuffer(bufferSize);  
                    const dataView = new DataView(buffer);  

                    // 填充头部  
                    dataView.setUint8(0, 0x55); // 帧头  
                    dataView.setUint8(1, 0x02); // 帧类型:开机画面  
                    dataView.setUint8(2, '0x' + currentPacket.toString(16).padStart(2, '0')); // 包序号  
                    // dataView.setUint8(3, 0x01);  
                    // dataView.setUint8(4, 0xFF);  
                    if (packetData.length == 250) {  
                        dataView.setUint8(3, 0x01);  
                        dataView.setUint8(4, 0xF4);  
                    } else {  
                        dataView.setUint8(3, 0x00);  
                        dataView.setUint8(4, 0x64);  
                    }  

                    // 填充数据(每个RGB565值占2字节)  
                    for (let i = 0; i < packetData.length; i++) {  
                        dataView.setUint16(5 + i * 2, packetData[i], false); // 大端字节序  
                    }  
                    console.log(  
                        `发送数据包${currentPacket}/${totalPackets},${dataView.getUint8(0)} ${dataView.getUint8(1)} ${dataView.getUint8(2)}`  
                    )  
                    //发送数据包  
                    this.sendData(buffer).then(() => {  
                        // 更新进度  
                        this.currentPacket = currentPacket;  
                        this.progress = Math.round((currentPacket / totalPackets) * 52);  
                        // console.log(`发送开机画面数据包 ${currentPacket}/${totalPackets}`);  

                        // 发送下一个包(添加延迟避免蓝牙缓冲区溢出)  
                        currentPacket++;  
                        let inteval = parseInt(this.inteval ? this.inteval : 100);  
                        // if ((currentPacket - 1) % 16 == 1) {  
                        //  inteval += 150;  
                        //  console.log("当前是第" + (currentPacket - 1) + "完成,额外多停留150ms,inteval=" +  
                        //      inteval);  
                        // } else {  
                        //  console.log("interval=" + inteval)  
                        // }  
                        setTimeout(sendNextPacket, inteval);  
                    }).catch(err => {  
                        this.isSending = false;  
                        reject(err);  
                    });  
                };  

                //牵着你的手  
                var HoldYouHand = () => {  
                    var str = "picture transmit start"; //握手的协议字符串  

                    // 1. 创建 ArrayBuffer 和 DataView  
                    const buffer = new ArrayBuffer(str.length);  
                    const dataView = new DataView(buffer);  

                    // 2. 将字符串转换为 ASCII 码并写入 DataView  
                    for (let i = 0; i < str.length; i++) {  
                        dataView.setUint8(i, str.charCodeAt(i));  
                    }  

                    this.sendData(buffer).then(() => {  
                        // 开始发送第一个包  
                        console.log("握手成功了,等待200ms");  
                        setTimeout(sendNextPacket, 200);  

                    }).catch(err => {  
                        console.log("握手没有成功");  
                        reject(err);  
                    });  
                }  

                HoldYouHand();  

            });  
        },  

        // 文字输入变化  
        onTextChanged(index) {  
            console.log(`第${index + 1}行文字已更新`);  
        },  

        // 发送文字  
        sendText() {  
            if (!this.isConnected) {  
                uni.showToast({  
                    title: '未连接设备',  
                    icon: 'none'  
                });  
                return;  
            }  

            this.isSendingText = true;  
            this.textProgress = 0;  
            this.currentTextPacket = 0;  

            // 总数据包数  
            const totalPackets = this.textLines.length;  
            let currentPacket = 1;  

            // 发送单个数据包  
            const sendNextPacket = () => {  
                if (currentPacket > totalPackets) {  
                    this.isSendingText = false;  
                    console.log('文字发送完成');  
                    uni.showToast({  
                        title: '发送成功',  
                        icon: 'success'  
                    });  
                    return;  
                }  

                // 获取当前行文字  
                const text = this.textLines[currentPacket - 1] || '';  

                // 将文字转换为GBK编码  
                this.convertToGBK(text).then(gbkData => {  
                    console.log(JSON.stringify(gbkData));  
                    // 构建数据包  
                    const bufferSize = 5 + text.length * 2; // 头部4字节 + 数据部分  
                    const buffer = new ArrayBuffer(bufferSize);  
                    const dataView = new DataView(buffer);  

                    // 填充头部  
                    dataView.setUint8(0, 0x55); // 帧头  
                    dataView.setUint8(1, 0x03); // 帧类型:文字  
                    dataView.setUint8(2, currentPacket.toString(16)); // 包序号  

                    console.log(text.length.toString(16));  
                    dataView.setUint16(3, (text.length * 2).toString(16)); // 数据长度  
                    console.log("gbkData.length=" + gbkData.length);  
                    let str = new Array();  
                    // 填充数据  
                    for (let i = 1; i <= text.length * 2; i++) {  
                        const highNibble = gbkData[i * 2 - 2]; // 高4位  
                        const lowNibble = gbkData[i * 2 - 1]; // 低4位(如果是奇数长度,补0)  
                        console.log("i=" + i + "," + highNibble + lowNibble)  
                        // 组合高低位并转换为字节值  
                        const byteValue = parseInt(highNibble + lowNibble, 16);  
                        dataView.setUint8(5 + i - 1, byteValue);  
                    }  
                    console.log(str.join(" "));  

                    console.log("dataView.length=" + dataView.byteLength)  
                    // 发送数据包  
                    this.sendData(buffer).then(() => {  
                        // 更新进度  
                        this.currentTextPacket = currentPacket;  
                        this.textProgress = Math.round((currentPacket / totalPackets) * 100);  
                        console.log(`发送文字数据包 ${currentPacket}/${totalPackets}: ${text}`);  

                        // 发送下一个包  
                        currentPacket++;  
                        setTimeout(sendNextPacket, this.inteval ? this.inteval : 100);  
                    }).catch(err => {  
                        this.isSendingText = false;  
                        uni.showToast({  
                            title: '文字发送失败',  
                            icon: 'none'  
                        });  
                    });  
                }).catch(err => {  
                    this.isSendingText = false;  
                    console.log(`文字编码失败: ${err}`);  
                    uni.showToast({  
                        title: '编码失败',  
                        icon: 'none'  
                    });  
                });  
            };  

            // 开始发送第一个包  

            //牵着你的手  
            var HoldYouHand = () => {  
                var str = "word transmit start"; //握手的协议字符串  

                // 1. 创建 ArrayBuffer 和 DataView  
                const buffer = new ArrayBuffer(str.length);  
                const dataView = new DataView(buffer);  

                // 2. 将字符串转换为 ASCII 码并写入 DataView  
                for (let i = 0; i < str.length; i++) {  
                    dataView.setUint8(i, str.charCodeAt(i));  
                }  

                this.sendData(buffer).then(() => {  
                    // 开始发送第一个包  
                    console.log("握手成功了,等待200ms");  
                    setTimeout(sendNextPacket, 200);  

                }).catch(err => {  
                    console.log("握手没有成功");  
                    uni.showToast({  
                        title: '握手没有成功',  
                        icon: 'none'  
                    });  
                });  
            }  

            HoldYouHand();  

        },  

        // 将文字转换为GBK编码(使用第三方库或API)  
        convertToGBK(text) {  
            return new Promise((resolve, reject) => {  
                // 注意:uniapp环境中可能需要使用特定的GBK编码库  
                // 这里使用模拟实现,实际项目中应使用适当的编码库  
                try {  

                    // 模拟GBK编码转换  

                    let arr = gbk.encode(text)  
                    let utf8Data = gbk.arr2hex(arr);  
                    // 注意:这只是示例,实际GBK编码需要使用专门的库  
                    resolve(utf8Data); // 实际项目中替换为GBK编码实现  
                } catch (error) {  
                    console.log("错误:" + JSON.stringify(error));  
                    reject(error);  
                }  
            });  
        },  

        // 发送数据通用方法  
        sendData(buffer) {  
            console.log("deviceId=" + this.connectedDeviceId);  
            console.log("serviceId=" + this.serviceId);  
            console.log("characteristicId=" + this.writeCharacteristicId);  
            return new Promise((resolve, reject) => {  
                uni.writeBLECharacteristicValue({  
                    deviceId: this.connectedDeviceId,  
                    serviceId: this.serviceId,  
                    characteristicId: this.writeCharacteristicId,  
                    value: buffer,  
                    success: () => {  
                        console.log("发送数据成功");  
                        resolve();  
                    },  
                    fail: (err) => {  
                        console.log("发送数据失败");  
                        reject(`发送数据失败: ${err.errMsg}`);  
                    }  
                });  
            });  
        },  

        // 添加日志  
        addLog(message) {  
            const time = new Date().toLocaleTimeString();  
            this.logList.unshift({  
                time,  
                message  
            });  
            console.log(message);  
            // 限制日志数量  
            if (this.logList.length > 20) {  
                this.logList.pop();  
            }  
        }  
    },  
    onUnload() {  
        this.closeBluetoothAdapter();  

    }  
}  

</script>

<style>
.receivLog {
padding: 20rpx;
width: 100%;
height: auto;
box-sizing: border-box;
border:2rpx solid #e5e5e5;
border-radius: 20rpx;
font-size: 28rpx;
color: #2e2e2e;
}

.container {  
    padding: 20rpx;  
    background-color: #f8f8f8;  
    min-height: 100vh;  
}  

.title {  
    font-size: 36rpx;  
    font-weight: bold;  
    text-align: center;  
    padding: 20rpx 0;  
    color: #333;  
}  

.status-bar {  
    display: flex;  
    align-items: center;  
    justify-content: space-between;  
    padding: 15rpx 0;  
    border-bottom: 1rpx solid #eee;  
}  

.function-tabs {  
    display: flex;  
    margin: 20rpx 0;  
}  

.tab-btn {  
    flex: 1;  
    padding: 15rpx 0;  
    text-align: center;  
    font-size: 28rpx;  
    border-bottom: 2rpx solid #eee;  
}  

.tab-btn.active {  
    color: #409eff;  
    border-bottom: 2rpx solid #409eff;  
}  

/* 设备列表样式 */  
.search-area {  
    padding: 20rpx 0;  
}  

.search-btn {  
    background-color: #409eff;  
    color: white;  
}  

.tips {  
    color: #999;  
    font-size: 24rpx;  
    margin-top: 10rpx;  
}  

.devices-list {  
    margin-top: 20rpx;  
}  

.device-item {  
    display: flex;  
    align-items: center;  
    justify-content: space-between;  
    padding: 20rpx;  
    background-color: white;  
    border-radius: 10rpx;  
    margin-bottom: 15rpx;  
    box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);  
}  

.device-item.active {  
    background-color: #e8f3ff;  
    border-left: 6rpx solid #409eff;  
}  

.device-name {  
    font-size: 28rpx;  
    max-width: 500rpx;  
    white-space: nowrap;  
    overflow: hidden;  
    text-overflow: ellipsis;  
}  

.device-rssi {  
    color: #999;  
    font-size: 24rpx;  
}  

.device-status {  
    color: #409eff;  
    font-size: 24rpx;  
}  

/* 模式设置样式 */  
.modes-area {  
    margin-top: 30rpx;  
}  

.mode-title {  
    font-size: 28rpx;  
    font-weight: bold;  
    margin-bottom: 20rpx;  
    color: #333;  
}  

.modes-grid {  
    display: flex;  
    flex-wrap: wrap;  
    justify-content: space-between;  
}  

.mode-item {  
    width: 30%;  
    padding: 20rpx 0;  
    background-color: white;  
    border-radius: 10rpx;  
    display: flex;  
    flex-direction: column;  
    align-items: center;  
    box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);  
}  

.mode-item.selected {  
    background-color: #e8f3ff;  
    border: 2rpx solid #409eff;  
}  

.mode-icon {  
    font-size: 40rpx;  
    margin-bottom: 10rpx;  
}  

.mode-name {  
    font-size: 26rpx;  
}  

/* 亮度调节样式 */  
.brightness-area {  
    margin-top: 30rpx;  
    padding: 20rpx;  
    background-color: white;  
    border-radius: 10rpx;  
    box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);  
}  

.brightness-title {  
    font-size: 28rpx;  
    font-weight: bold;  
    margin-bottom: 20rpx;  
    color: #333;  
}  

.brightness-value {  
    font-size: 36rpx;  
    text-align: center;  
    margin-bottom: 30rpx;  
    color: #409eff;  
}  

.brightness-slider {  
    width: 100%;  
}  

/* 开机画面样式 */  
.splash-controls {  
    display: flex;  
    justify-content: center;  
    gap: 20rpx;  
    margin: 20rpx 0;  
}  

.splash-preview {  
    display: flex;  
    flex-direction: column;  
    align-items: center;  
}  

.splash-frame {  
    height: 320rpx;  
    width: 640rpx;  
    border: 2rpx solid #409eff;  
    border-radius: 8rpx;  
    overflow: hidden;  
    position: relative;  
    background-color: #f0f0f0;  
}  

.empty-frame {  
    width: 100%;  
    height: 100%;  
    display: flex;  
    align-items: center;  
    justify-content: center;  
    color: #999;  
    font-size: 24rpx;  
}  

.frame-info {  
    margin-top: 15rpx;  
    color: #666;  
    font-size: 24rpx;  
}  

.sending-progress {  
    margin-top: 30rpx;  
    width: 100%;  
}  

.progress-bar {  
    height: 12rpx;  
    background-color: #e0e0e0;  
    border-radius: 6rpx;  
    overflow: hidden;  
}  

.progress-fill {  
    height: 100%;  
    background-color: #409eff;  
    transition: width 0.3s;  
}  

/* 文字设置样式 */  
.text-inputs {  
    margin-top: 30rpx;  
    background-color: white;  
    border-radius: 10rpx;  
    box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);  
    padding: 20rpx;  
}  

.text-line {  
    display: flex;  
    align-items: center;  
    margin-bottom: 20rpx;  
}  

.text-line text {  
    width: 80rpx;  
    font-size: 26rpx;  
}  

.text-line input {  
    flex: 1;  
    height: 60rpx;  
    padding: 0 15rpx;  
    border: 1rpx solid #eee;  
    border-radius: 8rpx;  
    font-size: 26rpx;  
}  

.send-text-btn {  
    margin-top: 20rpx;  
    background-color: #409eff;  
    color: white;  
}  

/* 日志区域样式 */  
.log-area {  
    margin-top: 30rpx;  
}  

.log-title {  
    font-size: 28rpx;  
    font-weight: bold;  
    margin-bottom: 15rpx;  
    color: #333;  
}  

.log-content {  
    height: 200rpx;  
    background-color: white;  
    border-radius: 10rpx;  
    padding: 15rpx;  
    font-size: 24rpx;  
    color: #666;  
}  

.log-item {  
    margin-bottom: 8rpx;  
}  

.btn {  
    padding: 10rpx 20rpx;  
    border-radius: 8rpx;  
    font-size: 26rpx;  
    text-align: center;  
}  

.btn[disabled] {  
    opacity: 0.5;  
}  

.txt {  
    border: 1px solid #000000;  
}  

</style>

操作步骤:

先打开蓝牙搜索设备,与目标设备建立连接,再与设备断开连接。

预期结果:

无论何种情况,只要uni.closeBLEConnection进入success,都要跟设备断开连接,否则就进入fail回调。

实际结果:

大多数情况下都与设备断开了连接,偶尔没有断开

bug描述:

1.我们开发团队有一块蓝牙的开发电子板,当有蓝牙设备跟它连接后,会有绿灯常亮。
2.当我们使用uni.closeBLEConnection断开与设备的连接时,进入了success回调,但开发板的绿灯还是常亮状态。

  1. 这时再使用蓝牙搜索设备,无法搜索到该设备。
  2. 手动关闭手机的蓝牙,绿灯灭了,再开启手机蓝牙才能搜索到。

一开始我以为是uni.notifyBLECharacteristicValueChange订阅了消息的原因,我使用了uni.notifyBLECharacteristicValueChange state=false取消订阅,依然有该现象,现象不是必现,偶有发生。

2025-07-15 11:20 负责人:无 分享
已邀请:
1***@qq.com

1***@qq.com (作者)

有该现象的代码在附件zip中,官方大神有空测试一下。

要回复问题请先登录注册