保姆级微信小程序对接蓝牙设备教程。微信小程序发送不同蓝牙指令(定时发送,断开重连,判断是否有蓝牙权限等)

这篇具有很好参考价值的文章主要介绍了保姆级微信小程序对接蓝牙设备教程。微信小程序发送不同蓝牙指令(定时发送,断开重连,判断是否有蓝牙权限等)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文是一个完整的对接设备,发送不同指令监听不同返回的完整示例,可根据实际项目按需更改。

注:app.showModal 为在app.js中封装的showModal方法,then(()=>{})代表用户点击confirm,可用wx.showModal代替。

公用方法

function inArray(arr, key, val) {
    for (let i = 0; i < arr.length; i++) {
        if (arr[i][key] === val) {
            return i;
        }
    }
    return -1;
}

function split_array(arr, len) {
    var a_len = arr.length;
    var result = [];
    for (var i = 0; i < a_len; i += len) {
        result.push(arr.slice(i, i + len));
    }
    return result;
}

function calcCrc(dataView) {
	//计算指令的合取最低8位,是因为这个设备的指令是这个需求,实际按设备对接文档来
    let crc = 0;
    for (let i = 0; i < 15; i++) {
        crc += dataView.getUint8(i);
    }
    return crc
}
/**
 *ArrayBuffer转16进制字符串
 * @param {buffer} buffer 
 */
function ab2hex(buffer) {
    let hexArr = Array.prototype.map.call(
        new Uint8Array(buffer),
        function (bit) {
            return ('00' + bit.toString(16)).slice(-2)
        }
    )
    return hexArr.join('');
},
/**
 * 16进制字符串转字节数组
 * @param {string} str 
 */
function str2Bytes(str) {
    let pos = 0;
    let len = str.length;
    if (len % 2 != 0) {
        return null;
    }
    len /= 2;
    let hexA = new Array();
    for (let i = 0; i < len; i++) {
        let s = str.substr(pos, 2);
        let v = s; //处理
        hexA.push(v);
        pos += 2;
    }
    return hexA;
},
/**
 * 反转
 * @param {string} num 
 */
function reverse(num) {
    return num.split(',').reverse().join('');
},

请求设备列表

getList() {
    let ble = wx.getStorageSync('bleLink') || false; //设备是否连接中的变量,跳转其他页面也可使用
    wx.showLoading({
        title: '加载中...'
    });
    app.get("/getDevice").then(res => {
        if (res.data.data.length > 0) {
            console.log('有设备')
            let data = res.data.data[0];
            data.createTime = util.datatotime(data.createTime);
            this.setData({
                deviceList: [data],
                deviceId: data.deviceId,
                deviceName: data.deviceName,
                hasDevice: true,
                ble
            })
            this._discoveryStarted = false;
            this._deviceId = data.deviceId;
            console.log('--------- getList', this.data.deviceList)
            if (!ble) {
                console.log('已绑定设备但是未连接')
                this.settingBlue();
            } else {
                console.log('已绑定设备但是已连接')
                this.getBLEDeviceServices(this._deviceId);
            }
        } else {
            console.log('暂无设备')
            this._discoveryStarted = false;
        }
    })
},

1. 判断是否有蓝牙权限

/**
 * 开始蓝牙
 */
settingBlue() {
    wx.showLoading({
        title: '获取蓝牙中...',
    })
    wx.getSetting({
        success: (res) => {
            wx.hideLoading()
            if (res.authSetting.hasOwnProperty('scope.bluetooth')) {
                //'scope.bluetooth'属性存在,且为false
                if (!res.authSetting['scope.bluetooth']) {
                    //拒绝授权 弹窗授权
                    app.showModal({
                        content: '您还未授权使用蓝牙,请点击“确定”开启蓝牙授权~'
                    }).then(() => {
                        wx.openSetting({
                            success(res) {
                            	//监听到用户同意授权蓝牙
                                this.openBluetoothAdapter();
                            }
                        })
                    })
                } else {
                    this.openBluetoothAdapter();
                }
            } else
                //'scope.bluetooth'属性不存在,需要授权
                wx.authorize({
                    scope: 'scope.bluetooth',
                    success() {
                        this.openBluetoothAdapter();
                    }
                })

        }
    })
}

2. 初始化蓝牙

openBluetoothAdapter() {
    let _this = this;
    wx.showLoading({
        title: '连接中...',
    })
    wx.openBluetoothAdapter({
        success: (res) => {
            console.log('蓝牙初始化成功', res)
            wx.hideLoading();
            this.startBluetoothDevicesDiscovery()
        },
        fail: (res) => {
            wx.hideLoading();
            //针对一些特殊的错误返回进行不同的操作及提示,详细请看下文超链接
            if (res.errCode === 10001) {
                app.showModal({
                    content: '您当前未开启蓝牙,请打开手机蓝牙后再试~',
                    showCancel: 2 // 代表只有一个确认按钮
                }).then(res => {
                    wx.onBluetoothAdapterStateChange(function (res) {
                        // 监听蓝牙状态变化
                        if (res.available) {
                            wx.showToast({
                                title: '蓝牙已开启',
                                icon: 'none',
                                duration: 3000,
                            })
                            this.startBluetoothDevicesDiscovery()
                        } else {
                            wx.showToast({
                                title: '蓝牙未开启',
                                icon: 'none',
                                duration: 3000,
                            })
                        }
                    })
                });
            } else {
                app.showModal({
                    content: res.errMsg,
                    showCancel: 2
                }).then(res => {
                
                });
            }
        }
    })
},

wx.openBluetoothAdapter 错误代码详细

3. 开始搜寻附近的蓝牙外围设备及停止搜索设备的api

<van-popup show="{{ show }}" position="bottom" round closeable bind:close="onClosePopup">
    <view class="devices_summary">
        <view>
            已发现 {{devices.length}} 个设备:
        </view>
    </view>
    <view class="list_loading" wx:if="{{devices.length == 0 && loading}}">
        <van-loading type="spinner"></van-loading>蓝牙搜索中...
    </view>
    <view class="null" wx:if="{{devices.length == 0 && !loading}}">
        <image src="/images/null.png" mode="widthFix" />
        <view>搜索不到设备,请把设备靠近手机再试哦~</view>
    </view>
    <view class="list_loading" wx:if="{{devices.length == 0 && !loading}}" bindtap="settingBlue">
        <van-icon name="replay" />重新搜索
    </view>
    <scroll-view class="device_list" scroll-y scroll-with-animation>
        <view wx:for="{{devices}}" wx:key="idx" data-device-id="{{item.deviceId}}" data-name="{{item.name || item.localName}}" bindtap="createBLEConnection" class="device_item" hover-class="device_item_hover">
            <view> {{item.name}} </view>
            <view class="btn"> 连 接 </view>
            <!-- <view style="font-size: 10px">信号强度: {{item.RSSI}}dBm ({{tools.max(0, item.RSSI + 100)}}%)</view>
            <view style="font-size: 10px">UUID: {{item.deviceId}}</view>
            <view style="font-size: 10px">Service数量: {{tools.len(item.advertisServiceUUIDs)}}</view> -->
        </view>
    </scroll-view>
</van-popup>
startBluetoothDevicesDiscovery() {
    if (this._discoveryStarted) {
    	//正在搜索
        return
    }
    this._discoveryStarted = true
    wx.showLoading({
        title: '连接中...',
    })
    wx.startBluetoothDevicesDiscovery({
        allowDuplicatesKey: true,
        success: (res) => {
            console.log('startBluetoothDevicesDiscovery success', res)
            if (this._deviceId == '') {
                console.log('没有绑定设备,重新搜索')
                wx.hideLoading()
                this.onBluetoothDeviceFound()
            } else {
                //已有设备的话直接连接
                console.log('已有设备的话直接连接')
                wx.hideLoading()
                this.createBLEConnection({
                    currentTarget: {
                        dataset: {
                            deviceId: this._deviceId,
                            name: this.data.deviceName
                        }
                    }
                })
            }
        },
    })
},
//停止蓝牙搜索外围设备
stopBluetoothDevicesDiscovery() {
    wx.stopBluetoothDevicesDiscovery()
},
//监听搜索到新设备
onBluetoothDeviceFound() {
    this.setData({
        show: true, //展示搜索到的设备列表
        loading: true //搜索加载状态
    })
    wx.onBluetoothDeviceFound((res) => {
        res.devices.forEach(device => {
            if (!device.name && !device.localName) {
                return
            }
            //只显示包含 HDS 的设备(按实际设备名称更改)
            if ((device.name && device.name.includes('HDS')) || (device.localName && device.localName.includes('HDS'))) {
                const foundDevices = this.data.devices
                const idx = inArray(foundDevices, 'deviceId', device.deviceId)
                const data = {};
                if (idx === -1) {
                	//不存在时新增
                    data[`devices[${foundDevices.length}]`] = device
                } else {
                	//设备列表已存在,替换
                    data[`devices[${idx}]`] = device
                }
                this.setData(data)
            }
            setTimeout(() => {
            	//搜索设备超时,停止搜索
            	this._discoveryStarted = false
                if (this.data.loading) {
                    this.setData({
                        loading: false
                    })
                    if (this.data.devices.length == 0) {
                        wx.closeBluetoothAdapter()
                    }
                }
            }, 15000)
        })
    })
},

4. 绑定设备及连接设备

/**
 * 绑定设备接口
 */
createBLEConnection(e) {
    const {
        deviceId,
        name
    } = e.currentTarget.dataset;
    console.log('createBLEConnection: ', name);
    wx.showLoading({
        title: '连接中...',
    })
    // 如果请求设备列表接口,这个设备已经在接口返回中,则不需要请求新增设备的接口
    if (this.data.hasDevice) {
        console.log('createBLEConnection----已绑定设备,直连')
        this.createBLEConnectionFn(deviceId, name);
    } else {
        console.log('createBLEConnection----没有绑定设备,新增')
        let param = {
            deviceId,
            deviceName: name
        };
        app.post('/addDevice', param).then(res => {
            wx.showLoading({
                title: '连接中...',
            })
            this.setData({
                show: false,
            })
            //重新请求设备列表
            this.getList();
        });
    }
},
/**
 * 连接设备蓝牙
 */
createBLEConnectionFn(deviceId, name) {
    let deviceList = this.data.deviceList,
        obj = {
            deviceName: name,
            deviceId
        };
    wx.createBLEConnection({
        deviceId,
        success: (res) => {
            console.log('createBLEConnection success:', res);
            obj.addTime = util.datatotime(new Date());
            if (deviceList.length == 0) deviceList.push(obj);
            this.setData({
                show: false,
                ble: true,
                deviceList
            })
            wx.hideLoading()
            wx.setStorageSync('bleLink', true);
            wx.setStorageSync('deviceId', deviceId);
            wx.setStorageSync('deviceName', name);
            setTimeout(() => {
                this.getBLEDeviceServices(deviceId);
            }, 300)
        },
        fail: (err) => {
            console.log('createBLEConnection fail:', err)
            wx.hideLoading()
            if (err.errCode === 10002) {
                app.showModal({
                    content: '未搜索到设备,请您把设备靠近手机后重新添加设备~',
                    showCancel: 2
                }).then(res => {
                    // this.destoryDevice();
                });
            } else if (err.errCode === 10003) {
                app.showModal({
                    content: '连接失败,请您把设备靠近手机后重新添加设备~',
                    showCancel: 2
                }).then(res => {
                    // this.destoryDevice();
                });
            } else if (err.errCode === 10012) {
                app.showModal({
                    content: '连接超时,请重试',
                    showCancel: 2
                }).then(res => {
                    // this.destoryDevice();
                });
            } else {
                app.showModal({
                    content: err.errMsg,
                    showCancel: 2
                }).then(res => {
                    // this.destoryDevice();
                });
            }
        }
    })
    this.stopBluetoothDevicesDiscovery()
},

5. 连接上某个设备后获取特征值

/**
 * 获取服务
 * @param {*} deviceId 
 */
getBLEDeviceServices(deviceId) {
    wx.showLoading({
        title: '加载中...',
    })
    wx.getBLEDeviceServices({
        deviceId,
        success: (res) => {
            for (let i = 0; i < res.services.length; i++) {
                //根据设备对接文档提供的Service UUID进行判断
                if (res.services[i].isPrimary && res.services[i].uuid.substr(0, 8) ==
                    '0000FFF0') { 
                    this.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid)
                    return
                }
            }
        },
        complete(err) {
            wx.hideLoading();
            console.log('getBLEDeviceServices:', err)
        }
    })
},
/**
 * 获取特征值
 * @param {*} deviceId 
 * @param {*} serviceId 
 */
getBLEDeviceCharacteristics(deviceId, serviceId) {
    let self = this;
    wx.getBLEDeviceCharacteristics({
        deviceId,
        serviceId,
        success: (res) => {
            console.log('获取服务的信息包括特征值', res)
            for (let i = 0; i < res.characteristics.length; i++) {
                const item = res.characteristics[i];
                if ((item.properties.notify || item.properties.indicate) && item.uuid.substr(0, 8) == '0000FFF7') {
                	//监听指令返回的判断,根据设备对接文档提供的可读特征UUID进行判断
                    wx.notifyBLECharacteristicValueChange({
                        deviceId: deviceId,
                        serviceId: serviceId,
                        characteristicId: item.uuid,
                        state: true,
                        success: (res) => {
                            console.log('notifyBLECharacteristicValueChange success--', res);
                            this.openCall();
                            wx.showLoading({
                                title: '获取数据中...',
                            })
                            this.getDatas();
                        },
                        fail: (err) => {
                            console.error('notifyBLECharacteristicValueChange error--', err);
                        }
                    })
                }
                //用于发送指令,根据设备对接文档提供的可写特征UUID进行判断
                if (item.properties.write && item.uuid.substr(0, 8) == '0000FFF6') {
                    this._deviceId = deviceId;
                    this._serviceId = serviceId;
                    this._characteristicId = item.uuid;
                }
            }
        }
    })
},

6. 发送指令(对,终于到这一步了)

/**
 * 发送指令列表
 */
getDatas() {
    this.getEleNum();
    this.getInfo();
    setInterval(() => {
        this.getEleNum();
    }, 60 * 10 * 1000)
},
/**
 * 电量
 */
getEleNum() {
	/**
		文档提供的命令格式为0x01 AA 00 00 00 00 00 00 00 00 00 00 00 00 00 CRC
		AA:0X99,现在进行一次电量检测 
	*/
    let buffer = new ArrayBuffer(16);
    let dataView = new DataView(buffer);
    dataView.setUint8(0, 0x01);
    dataView.setUint8(1, 0x99);
    dataView.setUint8(15, calcCrc(dataView));
    this.writeBLE(buffer)
},
/**
 * 版本号
 */
getInfo() {
	/**
		文档提供的命令格式为0x02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 CRC
	*/
    let buffer = new ArrayBuffer(16);
    let dataView = new DataView(buffer);
    dataView.setUint8(0, 0x02);
    dataView.setUint8(15, 0x02); //只有一个0x02时无需计算
    this.writeBLE(buffer)
},
/**
 * 写入
 */
writeBLE(buffer) {
    wx.writeBLECharacteristicValue({
        deviceId: this._deviceId,
        serviceId: this._serviceId,
        characteristicId: this._characteristicId,
        value: buffer,
        success: (res) => {

        },
        fail: (err) => {
            console.log("写入失败--", err);
            if (err.errCode === 10002) {
                app.showModal({
                    content: '未搜索到设备,请您把设备靠近手机后重新添加设备~',
                    showCancel: 2
                }).then(res => {
                });
            } else if(err.errCode == 10006){
                // 重连
                wx.showToast({
                    title: '已断开连接,重连中...',
                })
                this.settingBlue();
            }
        }
    })
},

7. 监听发送指令的回调

openCall() {
    //监听命令返回事件
    let _this = this,
        deviceList = this.data.deviceList;
    wx.onBLECharacteristicValueChange(function (res) {
        wx.hideLoading()
        let dataList = str2Bytes(ab2hex(res.value));
        // console.log({dataList})
        if (dataList[0] == '01') {
            //电量
            let eleNum = parseInt('0x' + dataList[1])
            deviceList[0].eleNum = eleNum;
            _this.updateDevice({ eleNum });
        }
        if (dataList[0] == '02') {
            // 设备基础参数
            let deviceCode = 'v' + parseInt(dataList[1]) + '.' + parseInt(dataList[2]) + '.' + parseInt(dataList[3]) + '.' + parseInt(dataList[4]) + ' 20' + parseInt(dataList[5]) + '-' + parseInt(dataList[6]) + '-' + parseInt(dataList[7])
            deviceList[0].deviceCode = deviceCode;
            _this.updateDevice({ deviceCode });
        }
        }
        _this.setData({
            deviceList
        })
    })
},
updateDevice(obj){
	let param = {
		id: this.data.deviceList[0].id //数据库中的设备id,用于更新设备信息
	};
	param = {
        ...param,
        ...obj
    };
    //请求接口保存修改设备
}

补充一点:当小程序离开当前页面的时候停止监听蓝牙以及返回页面的时候继续监听

/**
 * 结束监听蓝牙蓝牙
 */
offBLECharacteristicValueChange() {
    wx.offBLECharacteristicValueChange()
},
/**
 * 生命周期函数--监听页面显示
 */
onShow() {
    if (this._deviceId && wx.getStorageSync('bleLink')) this.getBLEDeviceServices(this._deviceId);
},
/**
 * 生命周期函数--监听页面隐藏
 */
onHide() {
    this.offBLECharacteristicValueChange();
},

注意事项

如果是进入其他页面,也可以复制以上代码进行监听及发送指令
以及需要按需求在离开小程序或者解绑设备的时候,关闭蓝牙连接释放设备文章来源地址https://www.toymoban.com/news/detail-841798.html

closeBLE(){
     if(this._deviceId){
         wx.closeBLEConnection({
             deviceId: this._deviceId
         })
     }
     wx.closeBluetoothAdapter();
     wx.setStorageSync('bleLink', false);
}

到了这里,关于保姆级微信小程序对接蓝牙设备教程。微信小程序发送不同蓝牙指令(定时发送,断开重连,判断是否有蓝牙权限等)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 微信小程序——实现蓝牙设备搜索及连接功能

    ✅作者简介:2022年 博客新星 第八 。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏:微信小程序学习分享 ✨特色专栏:国学周更-心性养成之路 🥭本文内容:微信小程序——实

    2024年02月08日
    浏览(62)
  • uniapp 蓝牙连接设备 下发命令 监听蓝牙与设备的连接状态(兼容 微信小程序和支付宝小程序)

    1:创建蓝牙需要调用的Api文件 ly.js 2 在页面中使用index.vue 

    2024年04月14日
    浏览(51)
  • 微信小程序实现蓝牙开锁、开门、开关、指令发送成功,但蓝牙设备毫无反应、坑

    wx联系本人获取源码(开源): MJ682517 需要从下往上阅读,使用函数自调的方式解决 API 不能及时获取数据的问题,替换方案是使用定时器,但是个人觉得定时器不好,所以使用了函数自调的方式实现获取不到数据的问题。 getBluetoothDevices 方法中获取 deviceId ; getBLEDeviceServices 方法

    2024年02月15日
    浏览(34)
  • 小程序蓝牙通讯设备数据对接实战uniapp

          最近很闲,但是行业很卷!因为公司有硬件设备对接,但是介于原生app。闲来无事,便研究了下这个小程序通过蓝牙与硬件设备进行通讯。废话少说上干货! 本次讲解的目录大致分为三模块。根据我写的代码做讲解。 初始化并搜索蓝牙 获取并启用service服务 数据读取

    2024年02月09日
    浏览(38)
  • 微信小程序对接微信支付详细教程

    小程序 微信支付官方文档 https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_11index=2 https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_8_0.shtml 前提 在进行对接微信支付之前,我们首先需要将以下几点准备好: 申请APPID 申请商户号 小程序开通微信支付,绑定已经申请好的商户号。

    2024年02月09日
    浏览(48)
  • 微信小程序入门教程 --(保姆级)

    一、小程序注册 1、首先,到小程序官网注册自己的小程序账号,以下附有地址和教程: 小程序官网 进入这个地址之后,会看到这样的页面,点击立即注册按钮 2、在接下来的页面,选择小程序 3、然后根据提示完成三个注册步骤,(1).填写正确的邮箱和密码格式;(2).进行邮箱

    2023年04月08日
    浏览(48)
  • 获取微信小程序页面路径【保姆级教程】

    1.进入微信小程序公众平台,登录账号,点击右上角生成小程序码 微信公众平台 2.输入小程序名称或者小程序的APPID或者原始ID,输入完成,然后点击搜索,然后下一步    3.输入自己的微信号之后,点击开启   4.看到提示开启成功之后,就可以在手机上去获取页面路径了  

    2024年02月16日
    浏览(49)
  • 微信小程序——Echarts使用(保姆式教程)

    ✅作者简介:2022年 博客新星 第八 。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏:微信小程序学习分享 ✨特色专栏:国学周更-心性养成之路 🥭本文内容:微信小程序——

    2024年02月09日
    浏览(45)
  • uniapp微信小程序获取微信运动步数(保姆级教程)

    官方文档 https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/signature.html 可以先了解一下,然后下载对应的解密文件 找到对应的解密语言版本,老师这里用的uniapp,只能选择node版 这里有具体的案例,可以参考一下,直接在代码中导入,在上面的getStepInfo方法中直接实例化

    2024年02月06日
    浏览(50)
  • 反编译微信小程序保姆级教程(PC端程序包)

    本教程仅供学习,请勿用于非法途径,代码抄袭属于违法行为,尊重他人才是尊重自己 我一比较啰嗦,二比较懒。前方一堆屁话,正文移步到第二段!!!   这段时间一直在研究html、css、JavaScript,本来想着顺带研究php,但是他喵的php有点局限,用着不是很顺手,就先放下

    2024年02月10日
    浏览(58)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包