因为篇幅有限该系列文章重点是在介绍蓝牙mesh相关的内容,但是由于蓝牙mesh并不是一个单独的技术,而是建立在低功耗蓝牙(BLE)
基础之上的,因此会涉及到一些 BLE 相关的知识需要读者自行查阅资料。读者最好对蓝牙
或者是BLE
的概念有一定了解,当然如果完全不了解也没问题,我会尽量用通俗易懂的方式来介绍蓝牙mesh 。
目前本系列的规划一共有3篇:
本篇正是第一篇基础概念介绍的文章,相信只要百度搜索“蓝牙mesh”就会搜索出来很多介绍基础概念的文章,但是经过我这段时间的查阅发现这些文章很多大同小异,基本都是从SIG 官网发表的官方Blog或者是蓝牙mesh协议文档翻译过来的。所以本篇文章也大量借鉴了这些文章的内容,但是蓝牙mesh的基本概念比较多,因此本篇文章着重介绍那些常用到的概念,浓缩的都是精华!如果想要详细了解的同学我推荐关注蓝牙技术联盟的微信公众号,里面有10篇汉化后的文章更详细的介绍了蓝牙基本概念,我相信对后续开发蓝牙MESH应用也会有很大的帮助。
蓝牙发展至今已经推出了2种不同的风格,分别是经典蓝牙(BR/EDR)
和低功耗蓝牙(BLE)
,这两种风格分别应对不同的场景。经典蓝牙通常是在对功耗不敏感并且要求高传输速度的产品上使用,比如音视频设备、蓝牙耳机之类的。而 BLE 是在经典蓝牙之后推出的风格,其对低功耗的功能进行了优化,可以满足用电池让一个设备工作很久,像共享单车和智能门锁通常使用 BLE 开发产品。虽然上述的两种风格在同一款产品上可以共存(比如手机),但并不意味着两种风格之间可以相互通信,他们是2个独立的协议栈因此只能跟对应风格的产品进行通信。
而蓝牙mesh的推出并不是意味着蓝牙推出了一种新的风格,其实蓝牙mesh网络使用、并且依赖于低功耗蓝牙。低功耗蓝牙技术是蓝牙mesh使用的无线通信协议栈,因此理论上只要是支持 BLE 的设备都能支持蓝牙mesh功能。
蓝牙mesh并非无线通信技术,而是一种网络技术。
下图显示了蓝牙BR / EDR、低功耗蓝牙和蓝牙mesh之间的关系。
蓝牙mesh能让我们建立无线设备之间的“多对多”(m:m)关系。此外,设备能够将数据中继到不在初始设备直接无线电覆盖范围内的其他设备。这样,mesh网络就能够跨越非常大的物理区域,并包含大量设备。
对于满足日益普及的各种通信需求,mesh拓扑结构能提供最佳的方式,因此蓝牙mesh网络应运而生,典型的应用包括楼宇自动化和传感器网络等。这些通信需求包括:
蓝牙mesh网络使用发布/订阅 (publish/subscribe)消息系统。
设备可以将消息发送至特定地址,这些地址的名称和含义与用户能够理解的高级概念相对应,如“花园灯”(Garden Lights)。这被称为“发布”(publishing)。
设备经配置后,可接收由其他设备发送到特定地址的消息。这被称为“订阅” (subscribing) 。
当设备向特定地址发布消息时,订阅该地址的所有其他设备将收到该地址的副本,对其进行处理,并以某种方式作出回应。
想象一下花园里安装的一套户外灯, 每盏灯都已经过配置,以便其订阅“花园灯”消息。现在,想像一个蓝牙mesh电灯开关向“花园灯”地址发送了“开”的消息。没错,花园里的所有灯都会收到“ON”消息,并做出开灯的回应。
就是这么简单!
得益于mesh网络,设备可以在非常广阔的区域中安装,同时彼此之间保持通信。想象一下购物中心、机场或办公大楼的占地空间有多广阔。因为存在墙壁和其他物理上的障碍物,楼宇中的设备可能无法与安装在同一楼宇远侧的设备、或临近楼宇中的设备建立直接的无线连接。而蓝牙mesh网络则能够将网络中的某些设备指定为“中继设备”,进而解决这一难题。
中继设备能够转发从其他设备接收到的消息。在转发消息时,它们能够与位于初始消息发布设备无线范围以外的设备进行通信。消息可多次被中继,每一次中继即为一“跳”,最多可进行127跳,足以在一片广阔的物理区域中进行消息传输。
功率非常受限的设备(例如由小型电池持续供电多年的传感器)可能被指定为“低功耗节点”。低功耗节点能够与一个或多个被指定为 “friends” 的设备协同工作。Friends并非功率受限,它可以作为低功耗节点,存储寻址到这一低功耗节点的消息,并且只有在低功耗节点需要时才传送消息。低功耗节点和“friends”之间的关系理所当然就称为“friendship”。
不过friendship相关的内容在本篇文章中不会详细介绍,感兴趣的读者可以自行研究一下。
蓝牙mesh网络采用一种称为“网络泛洪(flooding)”的方式来发布和中继消息。
这意味着消息不会通过某一进程进行路由, 也不会沿着由一系列特定设备构成的特定路径来进行传输。相反,传输范围内的所有设备都会接收消息,负责中继的设备能将消息转发至其传输范围内的所有其他设备。
网络泛洪的优势在于无需特定设备专门扮演集中式路由器的角色。
集中式路由器一旦发生故障,就可能会导致整个网络无法运行。没有特定的路由也可能对网络造成灾难性的影响,但这种情况也可以通过在mesh网络中采用网络泛洪的方法来避免。
网络泛洪的方式也意味着消息一般能够通过多重路径到达其目的地。这就构建了一个相当可靠的网络。
一个未加入到mesh网络中的设备称为未配置设备(unprovisioned device)
,而已经加入到mesh网络中的设备称为节点(node)
。一个称为Provisioner
的设备(通常是手机)被用来管理未配置设备和节点之间的转换。
未配置设备不能发送任何mesh消息,但是它能通过广播告诉Provisioner它的存在。Provisioner在认证未配置设备后,将邀请它加入到一个mesh网络中,这样它就从未配置设备变成了节点。
节点可以发送和接收mesh消息,并且它是通过Configuration Client管理的。Configuration Client通常和Provisioner是同一个设备,用来配置这个节点在mesh网络中如何与其他节点通讯。Configuration Client也能将节点从mesh网络中移除,让这个节点重新变成未配置设备。
关于Provioner
和Configuration Client
的内容在后续章节有介绍。
让我们来简单浏览一下蓝牙mesh的协议栈,我知道无论是谁初次接触陌生协议栈的时候都是一脸懵逼的,所以不要因为现在看不懂协议栈而感到懊恼。协议栈是实现上述功能的细节描述,可能现在你并不需要深入了解,但是如果你的设备发生了一些难以解决的问题,那么对协议栈的熟悉程度是解决问题的最好技能。并且通过后面内容的介绍再回过头来看协议栈可能就会有更多的领悟,让我们来一点一点了解蓝牙mesh协议栈吧!
蓝牙mesh网络引入了全新的协议栈。如之前所述,这一协议栈建立在低功耗蓝牙技术之上,因此协议栈的最下层是 BLE 。下图描绘了协议栈的层级。
想象一下由数千台设备组成的网络,每台设备均通过低功耗蓝牙(BLE)无线连接进行通信。蓝牙mesh网络中的这些设备被称为节点 (node) 。每个节点都能发送和接收消息。信息能够在节点之间被中继,从而让消息传输至比无线电波正常传输距离更远的位置。这样的节点网络可以被分布在制造工厂、办公楼、购物中心、商业园区以及更多环境中。
一些节点(如传感器)可能使用电池供电,而其他节点(如照明设备、制造机械和安防摄像机)则会通过主电网来获取电力。一些节点的处理能力会高于其他节点。这些节点在mesh网络中可承担更为复杂的任务,扮演不同的角色,表现出以下四个节点特征(Features):
每个节点至少拥有一个元素,称为主元素(Primary Element)
,同时还可能包含其他多个元素。一些节点的复杂性高于其他节点,由多个称为元素(Element)的独立部分组成。元素由定义节点功能和元素条件的实体组成。例如,一个灯泡内有一个元素, 并具有两种功能:
节点中的每个元素都有一个唯一的地址,称为单播地址(unicast address)
,使每个元素都有址可寻。我们将在地址章节中进一步解释“寻址”
。
节点的基本功能都由模型 (Model) 来定义和实施。模型位于元素内,元素必须具有至少一个模型。模型能够定义并实施节点的功能和行为,而状态 (State) 能够定义元素的条件
。
以灯泡为例,该模型的功能是开关和调节亮度。相关的状态分别为“开”/ “关”和0-10:
蓝牙mesh支持复合状态,即由两个或多个值组成的状态。变色灯就是这样的一个例子,灯的色彩可以分别由颜色饱和度或者亮度来改变。
“绑定状态” (Bound State) 这一术语的定义源自一种状态的变化导致另一状态变化的情况。级别状态和开/关状态通常就相互绑定。如果级别从0变为1,则“开/关”的状态也从“关”变为“开”。
每个模型都有唯一的标识符。SIG 采用16位 UID 的模型,而供应商采用32位 UID(其中包含 SIG 指定的16位公司标识符以及16位供应商指定的模型标识符)。这确保了每个模型的地址都独一无二并且能确定被寻址到。
蓝牙mesh网络可借助消息,通过客户端 - 服务器架构进行通信。
这种客户端 - 服务器架构产生了三种类型的模型:
地址有四种类型,其中的三类用于消息的传送:单播(unicast)、虚拟(virtual)和群组(group)地址。第四种被称为未分配(unassigned)地址。地址长度为16位,并按下述定义进行编码。
蓝牙mesh网络通过消息进行通信。消息可以分为控制消息和接入消息。
模型可实施并定义节点的功能。元素是节点内唯一可被寻址的实体(节点中可包含一个或多个模型),并由状态(state)定义元素的状况变化。对于每个状态,都有一组服务器模型支持的消息。例如请求状态值或请求改变状态的客户端模型、以及发送状态或状态改变相关消息的服务器模型。
消息可被操作码(opcode)识别,而操作码通常定义成set/get
这两种类型,并具有相关参数。操作码可识别消息的操作。示例包括:
接入消息分为两类:经确认的(acknowledged)
和未经确认的(unacknowledged)
。经确认的消息被发送至每个接收元素,并经其确认。响应通常为状态消息。对于未经确认的消息则不作出响应。例如蓝牙mesh网络的状态消息就是一种未经确认的消息。
所有蓝牙mesh网络消息的安全保障都来自网络密钥(NetKey)
和应用密钥(AppKey)
对消息的加密和验证。NetKey用于网络层通信。假设蓝牙mesh网络没有子网,则该mesh网络内的所有通信都使用相同的网络密钥。
AppKey用于应用程序的数据。网络中的一些节点具有特定应用,并且根据应用的需要对一些潜在敏感数据的访问进行限制。这些节点具有特定的AppKey,并与特定应用相关联。会使用不同AppKey的领域通常包括安全(楼宇门禁、机房门禁和CEO办公室门禁)、照明(制造厂房、外部楼宇照明和人行道)和HVAC系统。
中继节点(relay node)(如灯泡或墙壁开关)通常具有有效的NetKey,能够在网络内中继敏感性消息。然而,这些节点无法访问各种限制区域(如楼宇控制或HVAC系统)的特定AppKey,,亦无法解密应用程序的数据。
蓝牙mesh网络使用发布/订阅 (publish/subscribe)
模型来进行消息传输。生成消息的节点会发布消息。需要接收消息的节点会订阅它们所需的地址。消息可被发布至单播、群组或虚拟地址。
消息可以作为对其他消息的回复而发送,也可以作为非请求消息(unsolicited messages)被发送。当模型发送回复消息时,使用消息始发处的源地址作为目标地址。发送非请求消息时,模型将使用模型的发布地址作为目标地址。节点中的每个模型都有一个发布地址。
接收消息时,节点内模型(节点中可能存在多个模型)中的每个实例均可通过订阅方式从一个或多个群组或虚拟地址接收消息。
订阅消息的模型使用模型的订阅列表来定义用于接收消息的有效地址。当模型接收到消息时,模型将检查其订阅列表。当订阅列表上的地址设置为模型的元素单播地址或属于该节点的固定群组地址时,则视为一个匹配(match)。下图表示了接入消息的有效源地址和目标地址。
蓝牙mesh实体发布各种节点的状态时,无论其与发送数据的节点位置距离远近,整个蓝牙mesh网络中的系统均可订阅该数据。这就实现了网络一端的设备可通过低功耗无线消息与设施中的其他的管理者进行对话,而不受距离限制。
蓝牙mesh网络好比是一个VIP俱乐部。如果您是这个俱乐部的会员,就可以随意进入,享受与会员类别相对应的设施和服务。如果您不是会员,便无论如何也过不了门卫这一关。
蓝牙mesh设备有可能是某一特定蓝牙mesh网络的成员,也有可能不是。如果它是成员,则有权与同为该网络成员的其他设备进行通信(至少以一种基本的方式)。如果它不是成员,那么该设备传输的所有内容都将被网络中的其他设备忽略。
其实可以理解为蓝牙mesh设备也拥有不同的会员类型,例如可以使用某些特定的俱乐部服务设施(如健身房、高尔夫球场等),但不是全部。它只能与网络中的某些设备进行充分的交互。而对其进行管理的就是“应用”(application)这一概念。例如,蓝牙mesh照明开关可以在网络中打开或关闭蓝牙mesh照明灯,因为所有这些设备都是照明应用的一部分。而由于供暖系统并非照明应用的一部分,因此照明开关就无法打开供暖系统。
设备要想成为蓝牙mesh网络的成员,则必须经过一个称为“启动配置(provisioning)”的安全流程,将设备添加到网络中。
安全性是蓝牙mesh网络的核心,我们将在本系列的后续文章中详细介绍这一主题。将设备添加到蓝牙mesh网络、或从中移除设备的过程都将严格遵循安全性要求。
蓝牙mesh网络使用一套包含各类安全密钥的系统,从整体上保护网络,同时保护网络内的各个应用并将其彼此分离。拥有正确的安全密钥,设备才能成为网络成员并有权参与特定应用。网络中的所有节点(node)都拥有一个名为“网络密钥”或“NetKey”的密钥。只有设备拥有了这个密钥,才能成为该网络的成员,即成为其中的节点之一。
启动配置的流程会将普通的“设备(Device)”变身为“节点(Node)”,使其正式成为蓝牙mesh网络的成员。这一流程通常需要通过一个应用程序来实现,该程序一般由产品制造商所提供,可在智能手机或平板电脑上使用,但也可以采用其他形式,例如桌面或Web应用程序。
运行启动配置应用程序的设备称为“启动配置设备(Provisioner)”,由于它的作用至关重要,因此在物理上必须要保证它的安全性。
在启动配置期间,启动配置设备会采用称为“启动配置协议”的蓝牙mesh协议,与将要被启动配置的设备进行通信。启动配置设备可通过PB-ADV或PB-GATT承载层[i]两者中的任何一个使用启动配置协议,确保在较早版本的智能手机上亦可实施启动配置设备的应用程序,只要它们支持低功耗蓝牙(Bluetooth Low Energy)和GATT。
将设备添加至网络的过程中,最重要的一点是要为其提供网络所有其他节点拥有的网络密钥。当然,这一过程本身必须是安全的,这样恶意设备才无法窃取添加新设备时进行的通信,也无法窃取NetKey。
当购买了新的设备(Device)并需要将其添加至当前蓝牙mesh网络时,用户将使用启动配置设备( Provisioner),同时参考这一新设备制造商的说明,将其添加至蓝牙mesh网络。这样,新设备(Device)就变身为节点(Node),成为蓝牙mesh网络的成员。
该流程涉及几个步骤,见下方流程图:
蓝牙mesh网络规格中介绍了新的GAP广播类型,包括 Mesh Beacon 广播类型[ii]。
设备(Device)可采用 Mesh Beacon 广播类型来发出广播,声明自己是未经启动配置的设备,可被启动配置。用户可能需要根据制造商的说明,按照一定的流程,例如键入一组按钮,或将某一按钮长按一段时间等,以此方式启动新设备的广播。
用户还需要在启动配置设备中启动“添加设备到网络”的流程,以便从Beacon设备(Device)接收广播数据包。需要记住的一点是,启动配置设备可能是智能手机或平板电脑应用,因此在实际操作中会涉及到智能手机解锁、应用程序启动、也许还需要登录应用程序(为了进一步确保安全性),并通过其用户界面启动Beacon设备(Devices)搜寻。这样,启动配置设备就会意识到新设备(Device)的存在和准备就绪状态,可进入后续的启动配置流程。
接下来,启动配置设备将以启动配置邀请PDU(Provisioning Invite PDU)的形式向要进行启动配置设备发送邀请,这是启动配置协议的一部分。Beacon设备会在启动配置功能PDU中回应有关自身的信息。
启动配置功能PDU可提供一系列信息,例如其所拥有的元素数量、所支持的启动配置相关算法等。它还能指示设备(Device)拥有的输入输出功能类型,这些信息将用于认证(Authentication)步骤。
包括启动配置设备在内的所有蓝牙mesh设备都支持FIPS P-256椭圆曲线算法,因此必须拥有公共密钥。可通过基于该算法的非对称加密来创建安全通道,以完成剩余的启动配置流程。为此,启动配置设备会与将被启动配置的设备(Device)交换公共密钥。需注意的是,将被启动配置的设备(Device)可以通过带外方式(Out of Band),例如QR码,来提供公共密钥。本系列的后续文章将重点讨论mesh安全性,包括启动配置的安全性。
启动配置设备基于对新设备(Device)功能的了解,向其发送消息,指示其输出单一或多位数值,对其所支持的多种用户操作(例如按下按钮)作出响应。值的形式会因设备差异而有所不同。一台设备可能会在LED面板上显示一个三位的数值,另一台设备则可能是红色LED灯闪烁几次,闪烁的次数就是输出的验证值。启动配置设备的用户将观察到设备(Device)输出的值,并将值输入启动配置设备的用户界面。
然后,设备(Device)和启动配置设备交换密码散列,这些数据来源包括设备(Device)输出的随机值,允许它们完成对彼此的验证。
认证成功完成之后,会通过两台设备的私有密钥(Private Key)和交换的对等公共密钥生成会话密钥(Session Key)。随后,会话密钥即可用于保护完成启动配置流程所需数据的后续分发,包括网络密钥(NetKey)和设备的唯一地址,即单播地址(Unicast Address)。
启动配置完成后,启动配置设备就会拥有网络的NetKey,这是一个称为“IV索引(IV Index)”的蓝牙mesh安全性参数,且拥有一个由启动配置设备分配的单播地址[iii]。至此,新设备就正式成为了节点,即成为蓝牙mesh网络中的一员。
本章节内容需要读者对 BLE 概念有一定的了解。
低功耗蓝牙(Bluetooth Low Energy)是一项相当成功的无线技术。如今已经很难找到不支持低功耗蓝牙的智能手机或平板电脑了。可以说它是可穿戴技术兴起的关键因素。在医疗设备、智能家居设备、传感器等很多设备中,低功耗蓝牙的身影随处可见。
目前有数十亿支持低功耗蓝牙的设备已投入使用。那么,这些设备都能成为蓝牙mesh网络的一员吗?这也是本文将会回答的问题。知道你已经迫不及待,早想对着电脑屏幕、平板电脑或手机大喊“天呐,快告诉我吧!”, 我就不卖关子啦:
答案就是YES。
低功耗蓝牙设备只要具有正确的低功耗蓝牙功能和一些附加软件,就能加入蓝牙mesh网络中。以智能手机为例,可能只需要一个可以与蓝牙mesh网络对话的普通应用程序(App)就足够了。换句话说,这是任何开发者都能编写的应用程序。
要了解非mesh低功耗蓝牙设备如何成为蓝牙mesh网络的一员,我们需要回顾一下蓝牙mesh协议栈
蓝牙mesh网络采用低功耗蓝牙作为其射频通信协议栈。而具体如何使用,则是蓝牙mesh网络协议栈最底层的承载层需要负责的工作。
目前定义了两个承载层:广播承载层 (advertising bearer)和GATT承载层 (GATT bearer)。蓝牙mesh网络设备默认使用的是广播承载层,它负责在低功耗蓝牙广播数据包内收发蓝牙mesh数据包。
具有低功耗蓝牙协议栈、能够进行广播和扫描的设备具有基本的、必备的低功耗特性,因此能够支持广播承载层、乃至完整的蓝牙mesh网络协议栈。
既不支持也无法升级使用广播承载层的设备,则必须使用GATT承载层。使用GATT承载层时需要将蓝牙mesh协议数据单元(PDU)封装在代理协议(Proxy Protocol)中,我们将在下文中对此进行详细介绍。
请回顾节点和特性两个章节的内容。
非mesh低功耗蓝牙设备成为蓝牙mesh网络成员的过程中,代理节点是关键。代理节点的根本目的是执行承载层转换。它能够实现从广播承载层到GATT承载层的转换,反之亦然。因此,不支持广播承载层的设备可通过GATT连接来收发各类蓝牙mesh消息。
节点可通过在特性字段中设置代理特性位(proxy feature bit),来表示自身可用作代理节点。特性字段是所有节点都具有的成分数据状态的一部分。
代理节点(Proxy Node)可实施称为mesh代理服务的GATT服务,即本文中的“代理服务器(Proxy Server)”。mesh代理服务包含两个GATT特性:mesh代理数据输入和mesh代理数据输出。代理客户端(Proxy Client) 使用“GATT Write Without Response”子程序,将代理协议(见下图)PDU写入mesh代理数据输入特性,并从GATT通知中的mesh代理数据输出特性接收代理协议PDU。这就是互联GATT设备通过代理节点在蓝牙mesh网络中进行数据交换的机制。
低功耗蓝牙设备使用GAP广播来帮助其他设备发现自己。蓝牙mesh代理节点使用完全相同的技术,即通过“GAP可连接型广播(connectable advertising)数据包”,对自身的可用性、可作为代理节点的角色、及其身份进行广播。
代理客户端和代理服务器使用代理协议进行通信,并向对方发送代理PDU。这些PDU就像是存放各类蓝牙mesh PDU的容器。
蓝牙mesh接入消息使用核心蓝牙mesh协议栈,因此消息包含在网络PDU内。网络PDU可被封装在代理PDU中。
蓝牙mesh配置文件规格中定义了各种Beacon,包括未经启动配置的设备Beacon、以及安全网络Beacon。可通过代理协议将蓝牙mesh Beacon纳入网络。
启动配置过程涉及其自身协议,且启动配置PDU也可在代理PDU内进行交换。
最后,代理客户端和代理服务器可以交换特殊的代理配置消息,这些消息也可被封装于代理PDU中。
大多数类型的mesh数据可使用代理协议进行交换,因此可通过连接至代理节点的GATT客户端进行收发。
不同设备代理PDU的大小各异,PDU的大小是根据低功耗蓝牙属性协议(ATT)的最大传输单元(MTU)进行动态设置的,这是通过GATT连接来传输代理PDU的基础。此外,代理协议可以将完整的蓝牙mesh消息封装在代理PDU或多段消息的各个段中,借此来容纳较长的蓝牙mesh消息。
需要注意的一点是,任何蓝牙mesh节点(而非只有代理节点)都可以实施代理协议,从而支持基于GATT连接的直接交互。这在启动配置(provisioning)场景中非常有用。
通常使用智能手机或平板电脑执行启动配置流程,以将新设备添加至蓝牙mesh网络。大多数此类设备不会实施完整的蓝牙mesh网络协议栈,而且与蓝牙mesh网络进行的所有交互(包括启动配置)都很可能会使用代理协议。如前所述,启动配置PDU可被封装于代理PDU中,因此可通过代理服务器节点、利用GATT连接进行交换。蓝牙mesh配置文件规格中将采用代理协议的启动配置协议称为PB-GATT。