公司项目需要用到BLE以CBCentralManager的身份和硬件交互,开发过程中解决了一些遇到的问题和一些处理思路,这里简单记录一下。如果有什么问题或写的不对的地方希望大家可以一起讨论。
首先了解一下什么是BLE,蓝牙低能耗(Bluetooth Low Energy,或称Bluetooth LE、BLE,旧商标Bluetooth Smart,蓝牙版本40),也称低功耗蓝牙。相较经典蓝牙(蓝牙版本20),低功耗蓝牙旨在保持同等通信范围的同时显著降低功耗和成本。
与设备的交互使用的是16进制,所以要对发送的数据进行16进制转换,转换方法放在末尾
连接和 *** 作一个设备就要持有这个设备对象,系统不维护设备对象的内存管理
发送数据异步回调可以封装一个任务机制,发送数据后生成一个任务,在收到想要的数据的时候关闭任务或者等待任务超时关闭任务。
iOS更换手机的时候设备的UUID会改变,如果想换手机后依然可以重连设备,就需要让设备端配合把设备唯一MAC地址放入广播内容中,给设备扩充MAC属性,根据MAC来选择设备进行连接,做到设备MAC和UUID的匹配
本篇只做了简单的功能介绍和使用,OTA部分需要按照实际协议来做。如果大家有遇到问题或者有好的主意可以找我一起讨论,万分荣幸。
iOS对蓝牙库进行了封装,封装在CoreBluetooth库,所以使用时
接下来是对一些名词的介绍
大致结构如下
注:一个CBPeripheral可以包含多个CBService ,而一个CBService 也可以包含多个CBCharacteristic 。
接下来介绍蓝牙从打开到连接到发送数据到接收数据的一整个流程
1首先肯定是权限设置,Infoplist里面加入
Privacy - Bluetooth Peripheral Usage Description
2然后是初始化中心管理者,初始化有三种方式,我使用的默认的初始化方法即
如果想自己设置线程和其他条件,则可以通过接下来的初始化方法一次性进行设置
3判断蓝牙状态,通过CBCentralManager的state来获取
4如果状态为打开,则可以进行搜索 *** 作
注:如果连接和 *** 作一个设备就要持有这个设备对象,系统不维护设备对象的内存管理
接下来就是一系列的代理事件了,我会把主要代理按照流程来进行说明,大致流程如下:
搜索-连接-连接成功/失败(设置外设代理,搜索服务)-搜索到服务(搜索特征)-搜索到特征-监听需要的特征(读写、读、写等根据情况来确定)-通过外设读写特征写入指令-收到设备返回信息-断开连接
接下来对每个代理来进行详细介绍
CBCentralManagerDelegate:中心管理者代理,负责搜索,设备状态的一些回调
CBPeripheralDelegate:外设代理,负责对外设的一些 *** 作,特征的订阅,以及设备信息和消息的更新回调
搜索&连接
连接成功&失败
搜索到服务
搜索到特征
收到外设消息更新
断开设备连接
接下来介绍OTA升级
OTA是DFU(Device Firmware Update)的一种类型,准确说,OTA的全称应该是OTA DFU,就是设备固件升级的意思。只不过大家为了方便起见,直接用OTA来指代固件空中升级(有时候大家也将OTA称为FOTA)。
OTA升级并不复杂,只需要按照硬件定制的协议,把数据按照正常的写入方式发送给硬件即可(注意查看硬件是否规定数据的大小端),如果遇到问题可以找我,可以一起讨论。
16进制类型的字符串[A-F,0-9]和Data之间的转换可以使用下面的方法。如果是包含=之类的可以直接用字符串转换Data即可
swift同样可以实现OC中AFNetworking+MJExtension的效果,实现方法是Alamofire+SwiftyJSON+HandyJSON
Alamofire:网络请求
SwiftyJSON:数据解析
HandyJSON:映射为model
节约系统开支不用每次网络请求都生成一个SessionManager子类对象
新建model类
使用方法
可以看到网络请求成功之后返回了一个数组,数组内是自定义数据类型
HandyJSON用于数据映射时注意
2重命名属性时实现方法
3映射为model类和映射为model数组的用法分别为
Demo地址
>
通常我们用 head 和 tail 指针来记录链表的头和尾。
注意,最后一个节点的“下一个”指针是nil,第一个节点的“前一个”指针也是nil。
链表和数组的比较
首先定义一个描述节点的类型:
构建 LinkedList
快慢指针
找到环的入口点
找出环开始的节点证明
题目描述:删除单链表倒数第 n 个节点,1 <= n <= length,尽量在一次遍历中完成。
题目描述:输出一个单链表的逆序反转后的链表。
方案一:
迭代:在链表第一个和第二个元素断开链表,保存后半段,前半段拼在新head前方,然后赋值给新head:具体如下面示意
方案二:
递归:递归找到最后一个节点作为新链表的头节点,然后再更新每一个node的next 值 ,实现链表的反转。而newhead 的值没有发生改变,为该链表的最后一个结点,所以,反转后,我们可以得到新链表的head。
更多链表算法题
从苹果公开的public文件内,我们能看到Codable 其实是Decodable和Encodable两个协议的总和遵从Codable协议就需要遵从这两个协议内声明的方法
Decodable内声明的init(from)方法来实现解析并实例化,
Encodable对应的encode(to encoder: Encoder)来实现归档
举例:结构体和Json 数据的相互转换
结构体要遵守Codable 协议
结构体-> json 数据 使用JSEncoder
json 数据转化为结构体,使用JSDecoder
Codable 可以将网络数据解析为自定义模型:
从苹果公开的public文件内,我们能看到Codable 其实是Decodable和Encodable两个协议的总和遵从Codable协议就需要遵从这两个协议内声明的方法Decodable内声明的init(from)方法来实现解析并实例化,Encodable对应的encode(to encoder: Encoder)来实现归档。
如何使用Codable
以结构体为模型数据为例:
首先定义的结构体要遵守Codable协议:
如果你的部分参数和后台字段不一致,需要定义CodingKeys枚举,并且遵守String 和CodingKey协议,注意,书写这个枚举是为了修正和后台字段不一致的情况,一旦写了这个枚举,所有需要自动解析的字段你都需要写进来,因为自动解析需要这个枚举;反之如果不需要修正,就不要写这个枚举。
然后你就可以将网络数据转换为你的目标类型模型:
创建JSONDecoder变量,然后调用decode方法转换即可
如果你把类作为数据模型,如果数据模型B继承于A,则需要做一些处理
像下面就会出现问题,你只能解析子类中的属性,父类中无法拿到
这里需要手动对父类的属性进行赋值,同时还必须声明CodingKeys枚举
以上就是关于swift 蓝牙开发、OTA升级全部的内容,包括:swift 蓝牙开发、OTA升级、swift网络请求、Swift 数据结构 - 链表等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)