uni-app使用低功耗蓝牙自动连接售货机

    最近在做一个蓝牙售货机的项目,放在酒店房间内,哈哈,里边是什么自行脑补。

    因为需要适配微信小程序和支付宝小程序,所以最后选用uni-app来开发,省时省力更省钱。

    第一次对接蓝牙,做一次记录,话不多说,开始上代码。


    *uni-app蓝牙连接的整个流程 
    *1、初始化蓝牙 uni.openBluetoothAdapter(OBJECT) 
    *2、开始搜索蓝牙设备 uni.startBluetoothDevicesDiscovery(OBJECT) 
    *3、发现外围设备 uni.onBluetoothDeviceFound(CALLBACK) 
    *4、停止搜寻附近的蓝牙外围设备 uni.stopBluetoothDevicesDiscovery(OBJECT) 
    *5、连接低功耗蓝牙设备 uni.createBLEConnection(OBJECT) 
    *6、获取蓝牙设备所有服务 uni.getBLEDeviceServices(OBJECT) 
    *7、获取蓝牙特征 uni.getBLEDeviceCharacteristics(OBJECT) 
    *8、启用蓝牙设备特征值变化时的 notify 功能             uni.notifyBLECharacteristicValueChange(OBJECT) 
    *9、监听低功耗蓝牙设备的特征值变化 uni.onBLECharacteristicValueChange(CALLBACK) 
    *10、对需要操作的特征值进行读、写操作 

import store from '@/store/index.js'
let _self;
export default class deviceClass {
    constructor() {
        _self = this;
        _self.deviceId = "";
        _self.isConnect = false; //是否已连接
        _self.isStop = false; //是否停止搜所
        _self.UUID_SERVICE = '0000FEE0-0000-1000-8000-00805F9B34FB'; //服务UUID,设备方提供
        _self.UUID_CHAR = '0000FEE1-0000-1000-8000-00805F9B34FB'; //特征值UUID,设备方提供
    }
    /* 初始化并搜索蓝牙操作 */
    initEventDevice() {
        uni.showLoading({
            title: "蓝牙连接中"
        })

        /* 1、初始化蓝牙 uni.openBluetoothAdapter(OBJECT) */
        uni.openBluetoothAdapter({
            complete: () => {
				/* 监听蓝牙是否开启*/
                uni.onBluetoothAdapterStateChange(function(res) {
                    //res.available 蓝牙适配器是否可用
                    //res.discovering 蓝牙适配器是否处于搜索状态
                    console.log('适配器状态变化', res)

                    if(!res.available && !res.discovering){
                        _self.isStop = false;
                        uni.showToast({
                            duration: 2500,
                            title: "请打开手机蓝牙",
                            icon: 'error',
                        })
                        store.commit('updateStatus', false);
                    } else if(_self.isStop==false && res.available && !res.discovering){
                        console.log("蓝牙已开启,可以执行搜索操作")
                        _self.initEventDevice();
                    } else if(res.available && res.discovering){
                        console.log("蓝牙已开启,并且正在搜索中")
                    }
                })
            },
            success: (res) => {
                /* 初始化蓝牙成功 */
                /* 2、开始搜索蓝牙设备 uni.startBluetoothDevicesDiscovery(OBJECT) */
                /* 监听蓝牙适配器状态变化事件  可以检测当前设备的蓝牙的断开或者连接的情况*/
                _self.startBluetoothDevicesDiscovery();
                _self.connectTimeout();
                
            },
            fail: (res) => {
                console.log("初始化蓝牙失败:" + JSON.stringify(res))
                uni.hideLoading();
                uni.showToast({
                    duration: 2500,
                    title: "请打开手机蓝牙",
                    icon: 'error',
                })
            }
        })
    }
    /*搜索蓝牙*/
    startBluetoothDevicesDiscovery() {
        uni.startBluetoothDevicesDiscovery({
            allowDuplicatesKey: false, //是否允许同一设备多次上报,但RSSI值会有所不同
            success: (res) => {
                console.log("搜索成功:" + JSON.stringify(res))
                _self.onBluetoothDeviceFound();
            },
            fail: (res) => {
                uni.showModal({
                    title: '蓝牙连接失败了哦',
                    content: `
                        1、请查看周围是否有连接此设备的蓝牙;
                        2、请先关闭手机蓝牙在打开一次;
                        3、请检查位置信息是否打开;
                        4、退出小程序重新扫码进入。`,
                    showCancel: false,
                    confirmText: "我知道了",
                    success: () => {}
                })
                console.log("搜索失败:" + JSON.stringify(res))
            }
        })
    }
    
    /* 搜索蓝牙设备回调 */
    onBluetoothDeviceFound() {
        uni.onBluetoothDeviceFound(function(CALLBACK) {
            console.log('搜索蓝牙设备回调===' + JSON.stringify(CALLBACK))
            /* 每次遍历指定设备,一旦搜索到指定设备就结束搜索*/
            
            let bluename = JSON.parse(uni.getStorageSync('deviceInfo')).bluename; //需要搜索的设备名称
			/* 搜索过程中如果搜索到需要的设备,就停止搜索 */
            CALLBACK.devices.forEach(device => {
                /* 筛选需要的deviceId */
                if (device.deviceId === bluename) {
                    //找到需要的设备之后,停止搜索
                    console.log("搜索到指定设备=="+device.deviceId)
                    _self.isConnect = true;
                    /*停止搜索*/
                    _self.stopBluetoothDevicesDiscovery();
                    /* 执行连接 */
                    _self.connectDevice(device.deviceId);
                }
            })
        })
    }
    
    /*设置蓝牙搜索时间30秒, 如果超时没有搜索到就停止搜索*/
    connectTimeout() {
        setTimeout(() => {
            if(!_self.isConnect) {
                uni.hideLoading();
                _self.stopBluetoothDevicesDiscovery();
                uni.showModal({
                    title: '蓝牙连接失败了哦',
                    content: `
                        1、请查看周围是否有连接此设备的蓝牙;
                        2、请先关闭手机蓝牙在打开一次;
                        3、请检查位置信息是否打开;
                        4、退出小程序重新扫码进入。`,
                    showCancel: false,
                    confirmText: "我知道了",
                    success: () => {}
                })
            } 
        }, 30000)
    }
    
    /* 停止搜索 */
    stopBluetoothDevicesDiscovery() {
        uni.stopBluetoothDevicesDiscovery({
            complete: () => {
                _self.isStop = true;
            },
            success: (res) => {
                console.log("停止搜索成功")
            },
            fail: (res) => {
                console.log("停止失败")
                uni.hideLoading();
            }
        })
    }
    
    /* 连接低功耗蓝牙 */
    connectDevice(deviceId) {
        console.log("执行到这里了")
        uni.createBLEConnection({
            deviceId, //点击的DeviceId
            timeout: 5000,
            success: (res) => {
                console.log("连接成功")
                _self.deviceId = deviceId;
                /* 这边获取全部的服务,并筛选出当前需要的*/
                _self.getBLEDeviceServices(deviceId)
    
            },
            fail: (error) => {
                /* 连接失败 */
                uni.hideLoading();
                console.log("连接失败")
                console.log(error);
                uni.showModal({
                    title: '蓝牙连接失败了哦',
                    content: `
                        1、请查看周围是否有连接此设备的蓝牙;
                        2、请先关闭手机蓝牙在打开一次;
                        3、请检查位置信息是否打开;
                        4、退出小程序重新扫码进入。`,
                    showCancel: false,
                    confirmText: "我知道了",
                    success: () => {}
                })
            }
        })
        /* 监听蓝牙设备的连接状态 */
        uni.onBLEConnectionStateChange(function(res) {
            console.log(res.deviceId + "连接状态:" + res.connected)
        })
    }
    
    /* 获取所有的服务*/
    getBLEDeviceServices(deviceId) {
        console.log("开始获取服务")
        //连接成功之后需要延时,继续操作才不会出问题,延时时间短一点都没关系,我这边用了1秒
        setTimeout(() => {
            uni.getBLEDeviceServices({
                // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
                deviceId,
                success: (res) => {
                    console.log('device services:', res)
                    res.services.forEach((item) => {
						//这里微信小程序获取的服务ID是大写,支付宝是小写,所以统一转换为大写
                        let serviceId = item.uuid.toUpperCase();

                        if (serviceId == _self.UUID_SERVICE) {
                            console.log('serverId:', serviceId)
                            /* 进入特征值 */
                            _self.getBLEDeviceCharacteristics(deviceId, serviceId);
                        }
                    })
                },
                fail: (error) => {
                    console.log("获取服务失败")
                    console.log(error)
                    uni.hideLoading();
                }
            })
        }, 1000)
    }

    /* 获取所有特征值 */
    getBLEDeviceCharacteristics(deviceId, serviceId) {
        console.log("开始获取特征")
        setTimeout(() => {
            uni.getBLEDeviceCharacteristics({
                deviceId,
                serviceId,
                success: (res) => {
                    console.log(res)
                    res.characteristics.forEach((item) => {
                        console.log(item)
						//这里跟服务ID一样,支付宝需要转换为大写
                        //#ifdef MP-ALIPAY
                        let characterId = item.characteristicId.toUpperCase();
                        //#endif
                        //#ifdef MP-WEIXIN
                        let characterId = item.uuid;
                        //#endif
                        /* 只要用到的唤醒即可 */
                        if (characterId == _self.UUID_CHAR) {
                            console.log('characteristicId:', characterId)
                            _self.notifyBLECharacteristicValueChange(deviceId, serviceId, characterId)
                        }
                    })
                },
                fail: (res) => {
                    uni.hideLoading();
                    console.log(res)
                }
            })
        }, 1000)
    }
	/* 启用蓝牙设备特征值变化时的 notify 功能 */
    notifyBLECharacteristicValueChange(deviceId, serviceId, characteristicId) {
        console.log("开始唤醒")
        uni.notifyBLECharacteristicValueChange({
            state: true, // 启用 notify 功能
            // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
            deviceId,
            // 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
            serviceId,
            // 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
            characteristicId,
            success: (res) => {
                uni.hideLoading();
                /* 连接成功 */
                uni.showToast({
                    title: "连接成功",
                    icon: 'success'
                });
                //储存蓝牙连接状态
                store.commit('updateStatus', true);
                
                console.log('notifyBLECharacteristicValueChange success', res.errMsg)
                /* 连接成功以后,执行设置的操作,并且打开返回值的监听开关并监听 */
                //获取设备信息
                let DeviceCommand = "01,02,03,04," + func("01020304") + ",1E";
                let DeviceArrayBuffer = string2buffer(DeviceCommand);
                _self.writeDevice(DeviceArrayBuffer);
                
                //出货后关门延时设置
                let delayedCommand = "01,02,03,04,0A," + func("010203040A") + ",1E";
                let delayedArrayBuffer = string2buffer(delayedCommand);
                _self.writeDevice(delayedArrayBuffer);

				/* 监听低功耗蓝牙设备的特征值变化 */
                uni.onBLECharacteristicValueChange(function(CALLBACK) {
                    let result = blueTool.ab2hex(CALLBACK.value);
                    console.log("收到的数据值==", result);
					// 这里做一些具体的业务逻辑
					//我这里是监听低功耗蓝牙设备的特征值变化,然后调后台接口获取设备的电量,展示在页面
                    if ("73080182" === result.substring(0, 8)) {
                        var o = result.substring(8, 10);
                        o = parseInt(o, 16);
                        let dl = "";
                        if (o >= 41) {
                            dl = 100;
                        } else if (o <= 37) {
                            dl = 0;
                        } else {
                            dl = (o - 37) * 100 / (41 - 37);
                        }
                        //获取设备电量
                        uni.request({
                            url:  baseUrl+"/api/*****",
                            method: "POST",
                            data: {
                                key: value
                            },
                            header: {
                                "Content-Type": "application/x-www-form-urlencoded"
                            },
                            success: function(t) {
                                store.commit('setDeviceBattery', t.data.data);
                                console.log("设备上传回调" + JSON.stringify(t.data));
                            },
                            fail: function(t) {}
                        });
                    }
                })
            },
            fail: (res) => {
                uni.hideLoading();
                console.log('notifyBLECharacteristicValueChange success', res.errMsg)
            }
        })
    }
    /* 执行写入命令操作 */
    writeDevice(_Buffer) {
            uni.writeBLECharacteristicValue({
                deviceId: _self.deviceId,
                serviceId: _self.UUID_SERVICE,
                characteristicId: _self.UUID_CHAR,
                value: _Buffer,
                success: (res) => {
                    /* 发送成功 */
                    console.log('最后一次写入成功', res)
                },
                fail: (error) => {
                    /* 发送失败 */
                    console.log('最后一次写入失败', error)
                }
            })
    }
    
    /* 获取本机蓝牙适配器状态 */
    getBluetoothState() {
        uni.getBluetoothAdapterState({
            success: (res) => {
                console.log("状态" + JSON.stringify(res))
            }
        })
    }
    
    /* 关闭蓝牙适配器*/
    closeBlueAdapter() {
        uni.closeBluetoothAdapter({
            success() {
                console.log("关闭蓝牙适配器成功")
            }
        })
    }
    
    /* 断开低功耗蓝牙的连接 */
    disconnectBle() {
        uni.closeBLEConnection({
            deviceId: _self.deviceId,
            success: (res) => {
                console.log("断开成功" + res)
                store.commit('updateStatus', false);
                store.commit('setDeviceBattery', 0);
            }
        })
    }, 

	/* 具体的命令BCC校验*/
	func(t) {
		for (var e = t, a = [], i = 0; i < e.length - 1; i += 2) a.push(e.substring(i, i + 2));
		for (var o = a[0], s = 0; s < a.length - 1; s++) o ^= a[s + 1];
		return o;
	},

	/* 字符串转arraybuffer */
	string2buffer: function(str) {
		// 首先将字符串转为16进制
		let val = str
		console.log(val)
		// 将16进制转化为ArrayBuffer
		return new Uint8Array(val.match(/[\da-f]{2}/gi).map(function(h) {
			return parseInt(h, 16)
		})).buffer
	},
}

猜你喜欢

转载自blog.csdn.net/qq_41939902/article/details/116235882
今日推荐