iOS蓝牙Mesh开发总结二

3,650 阅读6分钟

蓝牙Mesh

回顾上篇

上篇文章讲述了蓝牙Mesh的概念、iOS要怎么去开发蓝牙Mesh、以及iOS在开发蓝牙Mesh中需要做哪些事情?详细讲解了蓝牙Mesh的设备是如何进行配网的。上篇文章iOS蓝牙Mesh开发总结一,本篇文章就开始继续上篇遗留下来的问题:手机如何给Mesh网络内的节点发送消息。

消息分类

消息从使用场景上进行分类可分为以下三类:

  • 配置消息:给已配网的节点设置配置信息的消息,如:节点添加/删除AppKey、节点里的Model绑定/解绑AppKey、添加订阅地址、设置发布地址、重置节点 这类消息。
  • 通用消息:由SIG定义的蓝牙Mesh通用消息,如:通用开关状态消息,通用亮度消息等。配置消息其实也是通用消息,只是对应的功能不同,所以这里进行了区分。
  • 自定义消息:虽然通用消息在第三方库中已经帮我们实现了,用起来很方便。但是由于功能太过简单,基本上满足不了我们的开发需求,这时就只能使用自定义消息了。

以上三种类型的消息的前两种在nrf第三方库中基本上都已经实现,我们只需使用其中的方法去实现需求即可,对于第三方库的用法这里不再进行过多的讲解,想要用好还是得自己仔细研究研究。

自定义消息

这里主要讲解自定义消息相关的内容,但还是要简单说下通用消息,经过对比可以了解这两种消息的区别。
通用消息:由SIG定义的功能,消息的opcode最多占2个字节(比如:模型绑定AppKeyopcode0X803D模型设置发布地址opcode0X03),这里说明下opcode是功能的唯一标识,一个opcode对应一个功能。
自定义消息自定义消息的opcode通用消息的opcode不同,自定义消息的opcode3个字节,其中后面两个字节厂商模型的厂商在SIG注册的id,第一个字节是0xC0和我们自定义的opcode与运算计算出的,因此能给我们使用的opcode只有2的6次方 = 64个。下面是厂商自定义消息有关opcode的代码:

public extension VendorMessage {
    
    /// The Op Code as defined by the company.
    ///
    /// There are 64 3-octet opcodes available per company identifier.
    /// Op Code is encoded in the 6 least significant
    /// bits of the first octet of the message Op Code.
    var opCode: UInt8 {
        // 3 和 F连在一起发布时会提示有敏感词,无法发布
        // 所以16进制就被我改成了二进制--> 0b00111111
        return UInt8(opCode >> 16) & 0b00111111
    }
    
    /// The Company Identifiers are 16-bit values defined by the
    /// Bluetooth SIG and are coded into the second and third octets
    /// of the 3-octet opcodes
    var companyIdentifier: UInt16 {
        return UInt16(opCode & 0xFFFF).bigEndian
    }
    
}

那个nrf第三方库现在的第二版提供了自定义消息的类定义,如上。但是目前这个SDK中并没有提供专门用来发送接收自定义消息的接口。也就是说如果要实现自定义消息的收发功能,只能自己在这个库的基础上使用库中定义的格式自己实现。可以参考这个库的demo中的一个自定义消息收发功能。

上面已经描述了iOS开发蓝牙Mesh需要做哪些东西,需要怎么做?

----------------------------------分割线-------------------------------------

下面的内容是笔者在开发蓝牙Mesh时的一些总结。

蓝牙Mesh工作流程

配网流程

1、扫描带有1827服务的蓝牙设备。
2、连接设备,发现服务,特征,订阅读特征。
3、调用第三方库中的入网邀请方法邀请设备入网,等待设备返回成分数据。 4、调用第三方库中的设备配网方法完成配网并给节点及元素分配唯一地址。 5、给节点添加AppKey
6、给模型绑定指定的AppKey
7、执行我们公司自己商议的设备认证协议,全部完成后才算真正配网成功。

连接代理节点的流程

1、扫描带有1828服务的蓝牙设备(设备一旦配网完成后里面的服务就会发生变化,由1827变成1828,相应的服务下的特征UUID也会有所变化,但还是一个读一个写,这是由蓝牙Mesh协议定义的)
2、扫描到之后就验证这个节点是否属于当前的Mesh网络,可从代理节点的广播的数据中进行验证。
3、验证通过后连接设备,发现服务,特征,订阅读特征。
4、开始定时发送心跳包,同步节点和手机的时间。

Mesh网络的数据持久化

创建了一个Mesh并给Mesh网络中配几个节点,那么这些信息肯定不能保存到设备上,毕竟设备能存储的数据并不多,因此只能由我们手机端进行持久化存储。
在蓝牙Mesh的那个第三方库中有提供数据缓存相关的功能,但不满足我们需要存储多个网络的需求。因此,只能改第三方库代码了,哈哈哈。

1、最开始是修改了数据缓存类,将Mesh网络的id作为保存路径,将不同的Mesh网络的数据保存在不同的路径下。
2、后来需要做Mesh网络的导入导出功能,可以和用户进行绑定,用户在另一个手机登录账号,只需要调用以下获取网络列表接口即可获取Mesh网络的数据并保存在这个手机内。
3、因为要保证iOS安卓Mesh信息共享,因此就商议了一套协议用来保存Mesh网络的关键数据,以此实现了Mesh网络与用户绑定,并能够跨平台的需求。

总结起来数据缓存这一块实现起来还是很复杂的,因为要时刻保证Mesh网络的数据同步。

好了,本次iOS蓝牙Mesh开发总结到此也就结束了,主要目的是对开发蓝牙Mesh中遇到的比较重要的地方的实现思路进行记录,方便自己以后忘记的时候查找。同样也希望可以给正在开发蓝牙Mesh的iOS同行提供一些经验和资料。