前端使用低功耗蓝牙开发的坑1(分包操作之分包接收)

• 阅读 1459

最近用uniapp开发微信小程序的一个项目中用到了低功耗蓝牙,但是其中收包 ,发包的时候不能超过20字节,所以就需要我们来进行分包操作了

接收蓝牙设备传过来的数据,并进行分包接收处理

说明: 我项目中的数据结构中05是帧头, FE是帧尾,所以需要判断接收到的这个数据是否是05开头,FE结尾, 我是将接收到的数据保存到了缓存中 前端使用低功耗蓝牙开发的坑1(分包操作之分包接收)

思路: 根据协议中的帧头帧尾和数据长度来进行处理 符合条件的就可以接收处理 不符合条件的就丢掉

    1. 如果开头结尾和帧头帧尾一致并且长度一致就保留(说明长度完整)
    1. 如果帧头对 帧尾不对 则为前边部分
    1. 如果帧头不对 帧尾不对 则为中间部分
    1. 如果帧头不对 帧尾对 则为最后一部分

      根据以上四个步骤基本可以得到一串正常的数据,但是此时还有一个很重要的步骤 需要根据接收到的数据的长度判断一下实际的长度,因为很有可能接收到的帧头帧尾之间还有一个帧尾,此时需要我们把进行截取操作得到我们真正想要的数据

以下是我项目中处理分包接收数据的全部代码:

// 11 监听notify功能
var packData = '' // 分包操作
var first = '' // 开始部分
var center = '' // 中间拼接部分
var last = '' // 结尾部分
var len = 0 // 包的长度
// var flag = true // flag判断是否进行了分包操作 如果分包需要清空开始部分 中间部分 结尾部分
export function    watchNotify(isHeart) {
    // ArrayBuffer转16进度字符串示例
    function ab2hex(buffer) {
        const hexArr = Array.prototype.map.call(
            new Uint8Array(buffer),
            function (bit) {
                return ('00' + bit.toString(16)).slice(-2)
            }
        )
        return hexArr.join('')
    }

    return new Promise((resolve, reject) => { 
        uni.onBLECharacteristicValueChange(function (res) {
            console.log(res)
            // 监听帧头帧尾
            var resCode1 = ab2hex(res.value)
            var resCode = resCode1.toUpperCase()
            console.log(resCode, '收到的')

            // 1. 如果开头结尾和帧头帧尾一致并且长度一致就保留(说明长度完整)
            if (resCode.substring(resCode.length - 2, resCode.length) == 'FE' && resCode.substring(0, 2) == '05') {
                let lenTo10 = parseInt(resCode.substring(2,resCode.length - 2).length)/2
                // 1.1找出内容16进制
                let lengthTo16 = lenTo10.toString(16) + ''
                // 2.1 对16进制进行大小写转换并且补零操作
                lengthTo16 = lengthTo16.length == 1 ? '0' +  lengthTo16.toUpperCase() : lengthTo16.toUpperCase()
                let length1 = resCode.substring(2,4)
                console.log(lengthTo16, length1)
                if (lengthTo16 == length1) {
                     if (resCode.substring(8,12) == 'F020') {
                         uni.setStorageSync('RESCODE', resCode)
                         console.log(resCode, 'F020')
                     } else {
                         uni.setStorageSync('RESPARAMS', resCode)
                     }
                }

            } else if (resCode.substring(resCode.length - 2, resCode.length) != 'FE' && resCode.substring(0, 2) == '05') { 
                // 2. 如果帧头对 帧尾不对 则为前边部分
                first = resCode

                console.log(first, '这个是开头部分first')
            } else if (resCode.substring(resCode.length - 2, resCode.length) != 'FE' && resCode.substring(0, 2) != '05') { 
                // 3. 如果帧头不对 帧尾不对 则为中间部分
                center = center + resCode
                console.log(center, '中间部分center')
            } else if (resCode.substring(resCode.length - 2, resCode.length) == 'FE' && resCode.substring(0, 2) != '05') {
                // 4. 如果帧头不对 帧尾对 则为最后一部分
                last = resCode
                console.log(last, '最后一部分last')

                // 得到实际内容

                var content = first + center + last
                console.log(content, '实际的内容')
                // 4.1找出内容16进制
                var resLen = (content.length - 4) / 2 // 减去4是剪掉帧头和帧尾,除以2是为了得到字节
                console.log(resLen, '实际的长度10进制')
                var lenTo16 = resLen.toString(16) + ''
                // 4.2 对16进制进行大小写转换并且补零操作
                lenTo16 = lenTo16.length == 1 ? '0' +  lenTo16.toUpperCase() : lenTo16.toUpperCase()
                console.log(lenTo16, 'lenTo16')
                // 得到包的长度
                len = content.substring(2,4)
                console.log(len, 'len')
                // 判断是否得到长度和实际长度相等
                if (lenTo16 == len) {
                    if (content.substring(8,12) == 'F020') {
                        uni.setStorageSync('RESCODE', content)
                        console.log(content, 'F020')
                    } else {
                        uni.setStorageSync('RESPARAMS', content)
                        console.log(content, '!F020')
                    }
                } else {
                    // 如果不相等, 找一下字符串中间有没有FE  然后再进行长度 帧头帧尾判断

                    // 1.截取帧尾的FE 求出帧尾之前是否有FE
                    let substrFE = content.substring(0, content.length - 2)
                    console.log(substrFE, 'substrFE')
                    // 2.判断是否还有FE
                    // 2.1 转换为两个字符一起的数组
                    let hasFEArr = strToArr(substrFE, 2)
                     // 2.2 找出是否有FE 并确定位置
                    let hasFE = hasFEArr.indexOf('FE')

                    console.log(hasFEArr, 'hasFEArr')
                    console.log(hasFE, 'hasFE')
                    // 如果有FE,截取到FE之处 判断帧头帧尾长度
                    if (hasFE != -1) {
                        // 将最后的数据保存到这个数组里面
                        let lastConArr = []
                        // 得到05-FE的内容
                        hasFEArr.forEach((item, index) => {
                            if (index <= hasFE) {
                                lastConArr.push(item)
                            }
                        })
                        console.log(lastConArr, 'lastConArr')
                        // 判断是否是05开头FE结尾
                        console.log(lastConArr[lastConArr.length - 1], 'lastConArr[lastConArr.length - 1]')
                        console.log(lastConArr[0], 'lastConArr[0]')
                        if (lastConArr[0] == '05' && lastConArr[lastConArr.length - 1] == 'FE') {
                            // 判断得到的长度与实际长度
                            let getLen = lastConArr[1]
                            console.log(getLen, 'getLen')
                            // 实际长度 并且转换为十六进制字符串
                            let resLen = (lastConArr.length - 2).toString(16) + ''
                            console.log(resLen, 'resLen1')
                            // 实际长度补零操作
                            resLen = resLen.length == 1 ? '0' + resLen : resLen,
                            console.log(resLen, 'resLen2')
                            // 判断得到的长度与实际长度相等之后才是实际的结果
                            if (getLen == resLen.toUpperCase()) {
                                // 数组转换为字符串
                                let lastStr = lastConArr.join('')
                                console.log(lastStr, 'lastStr')
                                if (lastStr.substring(8,12) == 'F020') {
                                    uni.setStorageSync('RESCODE', lastStr)
                                    console.log(lastStr, 'F020')
                                } else {
                                    uni.setStorageSync('RESPARAMS', lastStr)
                                    console.log('!f')
                                }
                            }
                        }
                    }
                }
                // 清空内容和收到的数据
                first = '' // 开始部分
                center = '' // 中间拼接部分
                last = '' // 结尾部分
                len = 0 // 包的长度

            }
        })
    })

}

源码地址

https://github.com/menglin1997/BLEConn

点赞
收藏
评论区
推荐文章
Jacquelyn38 Jacquelyn38
1年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
刚刚好 刚刚好
4个月前
css问题
1、在IOS中图片不显示(给图片加了圆角或者img没有父级)<div<imgsrc""/</divdiv{width:20px;height:20px;borderradius:20px;overflow:h
blmius blmius
1年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
翼
2年前
前端使用低功耗蓝牙开发的坑2(分包操作之分包发送)
最近用uniapp开发微信小程序的一个项目中用到了低功耗蓝牙,但是其中收包,发包的时候不能超过20字节,所以就需要我们来进行分包操作了以下是对分包发送的一些处理,分包接收操作请看上篇文章说明:我项目中的数据结构中05是帧头,FE是帧尾image.png(https://imghelloworld.osscnbeijing.
Souleigh ✨ Souleigh ✨
1年前
前端性能优化 - 雅虎军规
无论是在工作中,还是在面试中,web前端性能的优化都是很重要的,那么我们进行优化需要从哪些方面入手呢?可以遵循雅虎的前端优化35条军规,这样对于优化有一个比较清晰的方向.35条军规1.尽量减少HTTP请求个数——须权衡2.使用CDN(内容分发网络)3.为文件头指定Expires或CacheControl,使内容具有缓存性。4.避免空的
小森森 小森森
4个月前
校园表白墙微信小程序V1.0 SayLove -基于微信云开发-一键快速搭建,开箱即用
后续会继续更新,敬请期待2.0全新版本欢迎添加左边的微信一起探讨!项目地址:(https://www.aliyun.com/activity/daily/bestoffer?userCodesskuuw5n)\2.Bug修复更新日历2.情侣脸功能大家不要使用了,现在阿里云的接口已经要收费了(土豪请随意),\\和注意
晴空闲云 晴空闲云
4个月前
css中box-sizing解放盒子实际宽高计算
我们知道传统的盒子模型,如果增加内边距padding和边框border,那么会撑大整个盒子,造成盒子的宽度不好计算,在实务中特别不方便。boxsizing可以设置盒模型的方式,可以很好的设置固定宽高的盒模型。盒子宽高计算假如我们设置如下盒子:宽度和高度均为200px,那么这会这个盒子实际的宽高就都是200px。但是当我们设置这个盒子的边框和内间距的时候,那
艾木酱 艾木酱
3个月前
快速入门|使用MemFire Cloud构建React Native应用程序
MemFireCloud是一款提供云数据库,用户可以创建云数据库,并对数据库进行管理,还可以对数据库进行备份操作。它还提供后端即服务,用户可以在1分钟内新建一个应用,使用自动生成的API和SDK,访问云数据库、对象存储、用户认证与授权等功能,可专
helloworld_28799839 helloworld_28799839
4个月前
常用知识整理
Javascript判断对象是否为空jsObject.keys(myObject).length0经常使用的三元运算我们经常遇到处理表格列状态字段如status的时候可以用到vue
helloworld_34035044 helloworld_34035044
6个月前
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为