Google物联网操作系统协同框架Weave深度解析

时间:2023-02-10 17:58:56

1.       Google Weave框架

在2015年的Google I/O大会上,负责Android业务的桑达.皮查伊(SundarPichai)宣布了Google最新的物联网战略。这包括一个基于Android裁剪过的叫做Brillo的操作系统,以及一个物联网通信框架Weave。对Brillo的分析,我们放在本书的后面部分,这部分对Weave进行解析。需要说明的是,截至目前,Weave有关的正式文档很少,我们只能通过阅读其源代码进行分析。

a)       Weave背景及定位

Google把Weave定位为物联网的一个通信层,但本质上,Weave应该属于物联网系统框架的范畴。因为它不依赖于任何底层的通信协议,它可以运行在任何常见的物联网通信协议之上,包括WiFi,BLE,Zigbee等等。

在这之前,Google已经通过多种方式进入物联网领域。最著名的,是收购了Nest,一个专门聚焦智能家居解决方案的技术公司,并对其做了整合。但是Nest的解决方案,只能运行在自有的智能家庭硬件之上,不能运行在非Nest的家庭设备之上,这样就限制了其进一步的应用范围。而且这种封闭的风格,与Google开放共享的风格完全背道而驰。

大概是认识到了Nest解决方案的不足,Google重新审视了物联网的特点,并结合自身优势,推出了Brillo和Weave的组合解决方案。该解决方案的大部分代码都是免费和开源的,因此可供广大物联网设备生产商直接使用。随着应用的广泛,Google会逐渐构筑起一个物联网领域的生态链。这种基于开源代码来构筑生态链的方式,完全符合Google的风格。

因此,Brillo和Weave就担负了构筑物联网生态链的重担。

b)       Weave的主要特点

Weave具备如下特点:

首先,它是与操作系统无关的一个物联网系统框架,可以移植到任意操作系统上,只要底层操作系统能够提供Weave需要的最基本函数接口。虽然Google在其I/O发布会上,同时发布Brillo与Weave,而且Brillo缺省会内置Weave,但是Weave却不给Brillo面子,并不与Brillo紧密绑定。同时,Weave也不依赖于任何通信协议,它可以运行在Wi-Fi,BLE,Zigbee等常见的通信协议之上。

其次,针对不同的目标设备,比如资源受限的嵌入式硬件设备,资源充足的硬件设备,智能手机客户端(Android或iOS),云平台等,分别有不同的代码与之对应。这些不同的代码或组件,共同组成了Weave。显然,由于缺乏一个弹性可伸缩的操作系统内核,Weave不得不把所有的“职责”,都揽到自己身上,并通过不同的实现方式来应对。假设Brillo能够做到高度的伸缩性,可以适应几十K内存的资源受限设备,也可以适应数十M内存的复杂设备的话,那么Weave就不用这么费事了,只需要提供一套统一的框架代码即可。

再次,Weave提供了一套标准的设备操作命令(叫做Schema),以及对应的认证机制。Weave对常见的物联网设备,当前主要是智能家居设备,进行了总结和抽象,并形成了一套固定的操作命令集合,内部叫做Schema,并以JSON格式进行描述。Weave这样做的目标,是希望达到不同设备厂商的设备之间,只要使用了Weave,就可以相互操作的目的。同时Weave还引入了一套认证机制,不在标准schema框架内的设备及操作,可以经过Google的认证后,添加到标准schema中。这样就确保了整个schema框架的可扩展性,长此以往,就可以形成一个完整和丰富的生态链。

最后,Weave的大部分代码都是开放的,而且采用了相对宽松的BSD协议。Google仍然认为,以自己在IT行业内的影响力,并充分利用开源模式,来构筑一个完整的生态链,从而奠定在物联网领域的霸主地位,仍然是可行的。同时,面向设备的Weave库,尤其是uWeave,设计了一组简明扼要的接口,成为Provider。Weave的核心功能只依赖于这一组Provider接口,不依赖于任何其它的功能,使得Weave具备高度的可移植性。这从侧面也反映了Weave并没有与Brillo物联网操作系统进行紧密绑定,说明Google内部对Brillo的定位和地位,可能会存在争议。

c)        Weave的整体架构

Weave是一个完整的物联网协同框架,它包含了一系列的组件,分别应用于不同的目标对象。下图是Weave的主要组成:

大致来说,Weave包含三个大的功能组件:支撑WeaGoogle物联网操作系统协同框架Weave深度解析

同时,Weave提供了两类API:WeaveCloud API和Weave Local API。Weave Local API是Weave设备端组件与智能手机客户端之间的交互接口,而Weave Cloud API则是Weave Cloud API与其它两个Weave组件之间的通信接口。

下面分别对Weave的三个主要组件,以及两个API接口进行详细介绍。

LibWeave&uWeave

设备端组件又根据不同的目标设备,分成了两个:一个叫做LibWeave,适应于具备复杂计算能力的设备,这类设备支持Linux或者其它功能丰富的操作系统内核,具有数十M以上的内存空间。另外一个叫做uWeave,指的是微小(Micro)的意思。顾名思义,uWeave则是运行在资源受限的嵌入式设备上。

LibWeave是采用C++语言开发的,其代码已正式开发在Internet上。目前来说,LibWeave的主要目标操作系统是Linux,要求目标设备的CPU必须支持MMU(内存管理单元)功能,以实现支撑Linux有效运行的虚拟内存机制。

而uWeave则是面向资源受限的嵌入式领域应用,而专门实现的Weave协议栈。与LibWeave不同,uWeave专门对代码进行了定制和优化,使得整个uWeave的代码非常紧凑和高效。比如,uWeave以标准的C语言(C99)进行开发,这可使得整个代码库尺寸非常小,适应于资源受限的硬件设备。除此之外,uWeave还采用了一些其它的技术,比如采用CBOR编码格式来替代基于纯文本的JSON编码格式,来降低对网络的要求,针对低功耗蓝牙(BLE)进行了特殊的优化,采用更加简化的加密机制等等。


智能手机客户端

Weave开发了针对Android和Apple iOS两种智能手机操作系统的客户端程序库和对应的API,这样智能手机程序员可以直接调用Weave Client的API,来开发客户体验良好的Weave应用程序,来操控基于Weave的物联网设备。比如某个智慧灯泡生产商,在其智能灯泡中嵌入Weave设备端代码(LibWeave或uWeave),然后开发针对智能手机的客户端来操控这些智能灯泡。

同时,Google也开发了缺省的智能手机APP,这个APP可以做基本的Weave设备管理和控制工作。比如,可以通过这个APP,扫描局域网或蓝牙网络上是否有Weave设备。如果有Weave设备,则启动配对程序,把Weave设备纳入APP中进行管理。这时候如果Weave设备是基于Google认证的标准Schema来操作的,那么用户就可以通过Google的APP,来管理和控制Weave设备,而不用关心Weave设备是由哪个厂商生产的。

Weave设备的初始化配置,也是由智能手机APP进行的,下面以uWeave为例来说明这个过程。

物联网设备的安全性是必须要充分保证的,谁也不希望自己家的智能门锁,能够被别人轻易打开。这样就必须设计一套完整的初始化和配置管理流程,来确保设备的安全性。尤其是物联网设备刚刚拿到,还没有启用的时候,必须对齐进行初始化,设置账号信息,加密信息等等重要配置数据,然后才能运行。

一般情况下,uWeave设备通过低功耗蓝牙(BLE)与手机客户端进行通信。在用户刚刚拿到uWeave设备的时候,设备制造商会随设备一起,提供一个设备唯一的配对密码。这个密码可能是打印在设备上,也可能是打印在一张纸上,然后与设备一起密封起来。不论何种形式,只有设备的所有者(Owner)才能够看到这个配对密码。同时,这个配对密码会写到设备程的软件程序中。

用户必须在手机上安装一个智能手机客户端APP(WeaveClient APP),然后创建一个Google账号。这个过程需要连接到Weave Cloud上。智能手机客户端APP初始化好之后,就可以管理和配置基于uWeave的设备了。一般情况下,uWeave设备作为蓝牙通信的服务器端,手机客户端主动连接uWeave设备,然后启动配对过程。这个过程需要用户在手机客户端上输入随uWeave设备一起拿到的配对密码。只有密码正确,才会配对成功,从而进行下一步的通信,否则配对失败。因此,只要uWeave设备的初始配对密码不被泄漏,设备的初始化就是安全的。

一旦配对成功,uWeave设备和智能手机客户端就会协商一个一致的共享密码,用于后续通信数据的加密操作。这个共享密钥,当前是通过一种叫做SPAKE2的密钥交换技术实现的。详细的技术细节,可以参考参考文件【X】。这个共享密钥会同时存储在智能手机客户端和uWeave设备内。后续的所有通信,就可以直接使用这个密钥进行,而不用重新协商密钥。如果用户(uWeave设备Owner)希望授权其他用户来控制这个uWeave设备,则只需要通过智能手机客户端,把这个共享密钥分发给其它用户即可。

 WeaveCloud

如果Weave设备和智能手机客户端在直接通信的范围之内,比如在同一个WiFi或蓝牙网络内,则可以通过智能手机客户端APP直接管理和操作Weave设备。但很多情况下,智能手机客户端与Weave设备并不在同一个局域网内,這时候就需要通过一个集中的后台来进行相互通信,这个集中的后台,就是Google的Weave云平台(Weave Cloud)。

首先,基于LibWeave的设备,在成功配置之后,会主动通过网络连接到Weave Cloud。同时,智能手机客户端APP也会主动连接到Weave Cloud。这两者都在同一个账号的约束范围之内,这个账号,就是客户的Google账号。

当进行远端控制的时候,智能手机客户端会首先把命令发给Weave Cloud,Weave Cloud再把命令转发给Weave设备。对于状态信息,则是由Weave设备先发送给Weave Cloud,然后中转到用户的智能手机客户端上。当然,这个过程中的所有通信数据,都是经过加密的。

除此之外,Weave Cloud还提供很多其它的辅助功能,比如可以为设备提供云端存储功能,设备的运行信息和中间产生的数据,可以同步到Weave Cloud中进行存储。根据Google的规划,将来还可能提供各种各样的大数据或人工智能功能,总之,Weave Cloud是整个Weave体系的核心。

目前来说,Google尚没有开源WeaveCloud的源代码的计划,所有的Weave客户端和Weave设备端,都需要连接到Google提供的Weave Cloud服务器上,因此这就要求,如果您希望基于Weave框架来开发物联网设备或解决方案,必须保证能够访问Google的服务器系统。

WeaveAPI

Weave组件之间是通过WeaveAPI进行通信和交互的,Weave定义了两类API:Weave Cloud API和Weave Local API。智能手机客户端和LibWeave与Weave Cloud通信,必须使用Weave Cloud API。而智能手机客户端与LibWeave之间的通信,则基于Weave Local API。这两类API分别基于不同的传输层协议,完成通信功能。下图示意了整个协议栈:

Google物联网操作系统协同框架Weave深度解析

之所以设计两类API,是因为这三个组件之间的不同通信需求决定的。首先看Weave Loacl API,它主要解决Weave设备端(LibWeave)与智能手机客户端之间的交互问题。这两个组件之间要正常通信,需要解决两个问题(或者两个需求):

1.      智能手机客户端如何定位到Weave设备。一般情况下,智能手机客户端通过局域网(WiFi,Ethernet等)与Weave设备通信,大部分的家庭局域网上,终端设备的IP地址是不固定的,通过DHCP动态分配。一般终端设备加电之后,会通过DHCP协议来向家庭网关申请一个动态的IP地址作为通信之用。一旦设备关闭,则会释放这个IP地址。家庭网关前后两次分配给终端的IP地址,一般是不同的,因此智能手机客户端无法通过固定的IP地址,直接与Weave设备进行通信;

2.      在定位到Weave设备,并建立通信连接之后,智能手机客户端与Weave设备之间的通信,必须是安全的。即使通信报文被截获,攻击者也无法查看具体内容。

Weave Local API采用mDNS协议解决第一个问题。我们知道,DNS协议用于完成计算机名字与IP地址之间的解析。在访问互联网的时候,用户一般在浏览器内输入待访问的网站的域名,本质上是一台服务器的名字。浏览器会查询DNS服务器,把服务器的名字转换成对应的IP地址,然后才通过TCP/IP协议与该服务器建立连接,并下载网页。这个过程需要一个重要角色-DNS服务器的支持。DNS服务器一般存在于具有成百上千台计算机的大型网络中,同时需要网络管理员进行复杂的管理和配置。在家庭网络等这类小型网络中,一般没有DNS服务器,因此无法采用传统的DNS协议来解析Weave设备的IP地址。而mDNS协议是专门为家庭网络等小型网络设计的。在mDNS架构中,无需集中的DNS服务器,只要终端设备都在一个局域网内(严格来说,应该是一个广播域内),且支持mDNS协议,就可以相互解析IP地址,并完成点对点通信。

因为没有集中的DNS服务器,运行mDNS协议的终端之间是通过组播(可以理解为广播)来相互交流的。智能手机客户端知道Weave设备的名字(通过注册机制完成,并记录在智能手机客户端中),它会发送一个mDNS请求广播,请求中包含了目标设备的名字。这个广播请求被所有在同一个局域网内的设备收到,但是只有请求的名字与自己的名字匹配的设备,才会向智能手机客户端回应一个应答。这个应答中包含了自己的IP地址。于是智能手机客户端就知道了Weave设备的IP地址,后续就可以基于普通的TCP/IP协议进行通信了。

而在Weave Cloud API中,则使用普通的DNS协议解析IP地址,无需用到mDNS。

Weave Local API采用HTTPS(HTTP Secure,安全的HTTP协议)协议解决安全问题。在解析到Weave设备的IP地址之后,智能手机客户端会与Weave设备之间建立一个HTTPS连接,所有的通信消息,都会被加密。这样即使是在WiFi这样可以很容易被窃听的网络上,网络通信也是安全的,用户无需担心信息泄露。

在通信安全的问题上,Weave CloudAPI与Weave Local API的需求是一样的,因此HTTPS协议也被Weave Cloud API所采用。但是Weave Cloud API的另外一个特征,是Weave Local API所不具备的,就是Weave Cloud API的星形通信模式。

所谓星形通信,指的是所有的智能手机客户端,以及所有的Weave设备,都需要连接到Weave Cloud上,然后所有的通信,都必须经Weave Cloud转接,必须经过Weave Cloud这个“中心”。这样做的核心目的,是确保Weave Cloud能够掌控所有的通信内容,可以做到非常细粒度的权限管理。同时也可以确保Weave Cloud在整个Weave协同框架中的核心地位。而XMPP协议是天生支持星形通信的,该协议基于XML来描述通信的内容,然后通过加密的TCP连接,把通信内容传递给中心服务器(Weave Cloud)。中心服务器根据安全规则等做一番检查之后,再把相关内容转发给目标设备。因此,Weave Cloud API采用XMPP协议。

因为XMPP/HTTPS/mDNS等协议是传送层或应用层协议,其底层依赖于TCP/IP协议。而IP协议是一种开放独立的网络层协议,与底层具体的传输技术保持足够的独立,因此从理论上说,Weave可以运行在任何底层的网络之上。Wi-Fi和Ethernet是最常见的家庭网络通信技术。

需要说明的是,uWeave与智能手机客户端之间的通信,也是Weave Local API的范畴。但是由于uWeave是针对资源受限的嵌入式应用场景所定制,很多情况下并不支持TCP/IP协议,因此无法采用mDNS和HTTPS等技术,而是直接采用了低功耗蓝牙(BLE)技术。从目前的实现来看,运行uWeave的物联网设备只会接受智能手机客户端的管理和控制,不会与Weave Cloud建立连接,因此不会用到Weave Cloud API。

d)       Weave的主要技术实现

当前的Weave框架虽然还不是非常成熟(并没有基于Weave的商用物联网设备上市),但是其设计理念和设计技术,却非常先进和有代表意义。下面对Weave框架中的几个典型技术进行介绍和分析,以便读者更好的理解Weave框架,更好的理解物联网操作系统中的协同框架的概念。

i.             标准的命令和状态Schema

当前阻碍物联网发展的最大障碍,就是缺乏标准,这样不同厂商之间的物联网设备或软件,就无法互通,从而把整个物联网市场分割成以厂商为单位的小的“解决方案碎片”。举例来说,物联网设备厂商A生产的智能灯泡,只能通过厂商A与之配套的智能手机APP来进行管理和控制。因为标准缺失,所以智能手机APP与智能灯泡之间的交互协议,只能是A厂商自己定义。同样的道理,厂商B生产的智能门锁,也只能由厂商B配套的智能手机APP来管理和控制。这样的一个结果就是,一个用户购买了多少个厂商的设备,那么其手机上就需要安装多少个客户端APP。如果有一两个厂商还好说,一旦设备类型和生产商多了,那么用户的手机就被这些不同厂商的APP占满了,变成“应用市场”了。

Google试图通过定义一种标准的操作模式,来打破这种“厂商隔离”的状态。其设想的目标就是,用户只需要安装一个智能手机客户端,就可以控制所有厂商的物联网设备,只要物联网设备的软件符合Google的标准。这套标准的操作模式,叫做Schema。

Google分析后认为,智能手机APP与物联网设备之间,以及物联网设备与物联网设备之间,传递的数据无非分为两类:命令(command)和状态(state)。其中命令是由智能手机APP发送给物联网设备的,要求物联网设备做某个或某些指定的动作。而状态,则是物联网设备返回给智能手机APP的,也可以是智能手机APP主动向物联网设备索取后,物联网设备返回给手机APP的。比如智能门锁的例子,智能手机APP可以给门锁发一个“关闭(lock)”的命令。智能门锁收到这个命令后,执行关闭操作。完成后,向智能手机APP返回一个当前的状态,比如“已关闭(closed)”。这样通过命令和状态的交互,这个控制过程就完成了。

于是,Google把当前常见的物联网设备,尤其是针对智慧家庭解决方案的物联网设备,进行了分类,并定义了每种类别的设备的标准命令和状态。比如,Weave把智慧家庭物联网设备分为智能门锁,LED灯泡,摄像头,温度传感器,等等类别。每类设备赋予一个标准的类别编码,通过类别编码类识别设备的类别。比如,针对智能门锁,Weave的类别编码是“AO”。这是一个两个字符的字符串,在智能门锁运行期间,会定期的通过低功耗蓝牙(BLE)广播自己的相关信息,其中之一就是设备类别编码。智能手机APP会根据设备的类别编码,选择对应的标准操作schema,对设备进行操作。

设备类别编码定义好之后,针对每类设备,Weave定义了标准的命令和状态操作代码,并用JSON格式进行表示。比如,下面是一个针对LED灯泡的标准命令和状态schema:

const char kTraits[] = R"({

"onOff" : {

"commands" : {

"setConfig" : {

"minimalRole" : "user",

"parameters" : {

"state" : {

"type" : "string",

"enum" :["on","off"]

}

}

}

},

"state" : {

"state" : {

"isRequired" : true,

"type" : "string",

"enum" : ["on","off"]

}

}

}

})";

JSON是一种采用键值对(key-valuepair)来表示对象的方法。中间用冒号(:)隔开,左边的字符串是键,右面的字符串是对应的值。如果一个对象包含了多个键值对,则通过大括号把这个对象的所有键值对组合起来,形成一个对象。需要注意的是,键值对是可以嵌套的,即键值对的“值”,也可以是包含多个键值对的对象。

在上面的例子中,“onOff”是一个对LED灯泡的抽象描述,可以理解为LED灯泡。其右面大括号圈起来的整个部分,就是这个LED灯泡对象的操作属性。操作属性又分了两类,一类是命令(对应commands),一类是状态(对应state)。可以理解为command和state是两个二级键值对,这两个二级键值对组合到一起,就描述了对LED灯泡的标准操作。

可以把命令(commands)键值对进一步展开,为便于分析,单独摘录出来,如下:

"commands" : {

"setConfig" : {

"minimalRole" : "user",

"parameters" : {

"state" : {

"type" : "string",

"enum" : ["on","off"]

}

}

}

},

左边的“commands”是命令键值对的“键”,冒号右面大括号内括起来的,是对应的值。可见,这个“值”本身也是由一个叫做“setConfig”的三级键值对组成的。也就是说,对LED灯泡的操作命令,可以是“setConfig”(修改配置),而setConfig对应的值,则是该命令的参数,以及其它信息。从上面的描述可以看出,要执行setConfig操作,用户的最低角色(role)必须是user。这个操作对应的参数,也是一个键值对,键是“state”,对应的值可以是“on”或“off”。

需要注意的是,标准schema描述了Weave设备可以接受的所有命令的总和,以及每个命令所对应的参数描述。只要是在schema的描述范围之内的命令或状态操作,Weave设备就可以支持。否则Weave设备不支持。针对上述LED灯泡的schema,如果希望点燃LED灯泡,则需要向其发送下列命令:

{

“deviceId”: “52c867ca-17d5-f422-a2c8-b31c4e02743e”,

“name”: “onOff.setConfig”,

“parameters”: {

“state” : “on”

}

}

把上述JSON描述的命令及参数封装在网络报文中,发送给基于Weave的LED灯泡即可。上面的设备ID(DeviceId)标识了目标LED设备,因为在同一个用户账号下,可能存在很多Weave设备,Weave采用全球唯一ID(GUID)来标识每个设备。

在这个LED灯泡的schema中,只有setConfig这一个操作。如果需要添加其它操作,比如setColor,则可以直接在commands键值对中的值域部分追加,如下:

"commands" : {

      "setConfig" : {

"minimalRole" : "user",

"parameters" : {

"state" : {

"type" : "string",

"enum" : ["on","off"]

}

}

}

      "setColor" : {

"minimalRole" : "user",

"parameters" : {

"color" : {

"type" : "string",

"enum" : ["red","green","blue"]

}

}

}

},

按照这个schema,对LED灯泡的命令,就可以有两个了:一个是setConfig,用于设置灯泡的开关状态,另外一个是setColor,用于设置灯泡的颜色。

Schema中state键值对的含义,与commands类似,就不做进一步解释了。需要注意的是,在这个例子中,setConfig操作描述中也包含一个“state”,这个是setConfig的参数,不一定非要用state,也可以用其它诸如“onoff”等表示参数含义的字符串。而Schema中描述设备向客户端返回的状态(“state”),则是一个与commands一样的内置关键字,不能任意修改。

Weave针对常见的物联网设备,都定义了标准的schema。如果物联网设备是基于Weave开发的,且遵循Google的这一套标准Schema,那么从理论上说,这种物联网设备就可以被运行在智能手机上的Weave Client和运行在后台的Weave Cloud控制和管理。对于Weave没有定义的设备类型和对应的schema,设备厂商可以自己定义,然后向Google申请认证。一旦认证通过,那么就会被纳入标准的schema库内。可以看出,通过定义这套标准的shcema,并配以认证程序,Google实际上是在构筑一套物联网设备的“标准语言”,希望借此标准语言,来统一物联网世界。可见,Schema在Google的整个物联网战略中,是最核心的一环。

用户权限管理

为了对物联网设备进行分权分层的管理,Weave定义了不同的角色,每类角色具备不同的设备操作权限。主要有:

1.      Owner:是设备的所有者,拥有最高权限。Owner可以设定其它的用户角色;

2.      Manager,具备对其它(除Owner和Manager之外)用户角色的管理职责,可以给用户分配角色;

3.      User:设备的使用者,具备对设备执行命令(commands)的权限;

4.      Viewer:设备的查看者,可以对设备的状态(state)进行查询,但是不能对设备进行命令操作;

5.      Unspecified/anonymous:没有被授予任何权限的角色。

任何试图链接到Weave设备上进行操作的用户,都会被分配一个固定的角色。在操作的时候,Weave会检查用户的角色,看看用户是否有特定的操作权限。如果具备权限,则运行执行指定的操作,否则则拒绝操作。

基于这样一种分级的访问机制,可以实现灵活的管理功能。比如,一个智能门锁设备的Owner可以给所有的家人,都设置User权限。这样所有的家人就都具备开锁和关锁的能力。Owner也可以给邻居或亲戚设置Viewer权限,这样这些用户就可以查看门锁的状态,万一门锁没有锁好,可及时通知Owner或User。

需要注意的是,用户(user)与角色(role)是不同的概念。用户是一个一个的实体,而角色则是某一类用户的集合,这一类用户具备相同的操作权限。用户和角色的概念,被广泛应用于权限管理系统中。

针对低功耗蓝牙的深度优化

这里主要是针对uWeave而言的。低功耗蓝牙(BLE)是一种广泛应用的局域内无线通信技术,它提供了一种低功耗的数据传输技术,被广泛应用在低成本的芯片上。同时也被智能手机等设备广泛支持。Weave架构的最主要应用场景,就是通过智能手机发现和控制物联网设备,因此既然BLE技术是这种通信场景的主流支撑技术,uWeave专门针对这种场景做了深度优化。

在BLE场景中,运行了uWeave的物联网设备,充当一个蓝牙服务器(专业名称叫做GATT Server)的角色,而运行Weave Client的智能手机,则充当了一个蓝牙客户端的角色。在uWeave设备还没有被任何客户端连接的时候,它通过BLE不断的广播自己的存在,以便客户端能够发现自己。

一旦被运行Weave Client的智能手机(Android或iOS等)发现并连接上,uWeave设备就接受客户端的控制。需要注意的是,不论是uWeave,还是LibWeave,都受相同的Weave Client控制。虽然这两者的底层通信协议稍有不同,但Weave Client屏蔽了这种不同,客户端应用程序开发者(开发智能手机APP的开发人员)只需要调用一套API,就可以同时控制这两类设备。

第一个针对BLE优化的特性,就是命令和状态的编码格式。在传统的Weave中,采用JSON格式描述Weave Client和Weave设备之间的交互命令和状态信息。虽然JSON是一种高度简化的对象表示方式,但是其本质上仍然是文本字符串的标识形式,占用的存储空间和网络带宽,比纯粹的数字形式大很多。这在WiFi或以太网情况下没有问题,因为这些通信技术的最大数据报文单元可以达到1K到2K字节,几乎可以容纳任何JSON格式的命令和状态字符串。但是在BLE环境下,其最大数据传输单元只有几十个字节。这样如果仍然采用JSON格式来表示命令和状态,则会出现一个数据单元无法传输的情况,必须对传输的数据进行分片处理。同时,过多的数据传输,会造成功耗的浪费。

因此,在BLE环境下,uWeave采用了CBOR(ConciseBinary Object Representation,一种用二进制表示对象的表示方法)的编码格式,这样就大大降低了网络传输的数据量。与JSON采用文本表示对象不同,CBOR采用二进制的数字来表示对象。下面是一个实例:

uint8_t request_buffer[] = {

0xA3,                          // {

0x01,       0x08,             // api : EXECUTE

0x02,       0x07,             // request_id : 7

0x10,       0xA2,             // api_params : {

0x00,       kExpectedTrait,//   trait : 1

0x02,       0xA1,             //   execute_params : {

kConfigId,  0x09,            //     configId : 9

};                                  //  }}

这是一个典型的命令块,它定义了三个顶层的键值对,即API对应EXECUTE,request_id对应7,api_params对应一个下一层的键值对。下一层的键值对描述了trait和执行命令的参数。在上面的表示中,左边部分是CBOR表示方式,右边则是传统的JSON表示格式。显然,CBOR表示格式只占用了13个字节,而JSON标识格式则需要80个字节。CBOR表示的命令块,可以通过一个BLE数据单元传送,但是JSON表示的结果就无法压缩到一个BLE数据单元中。之所以有这种效率的提升,是因为在CBOR表示方法中,对JSON的某些关键字做了映射关系,把JSON字符串映射为一个数字。比如,把“api”映射为0x01,把“EXECUTE”映射为0x08,等等。

另外一个针对BLE做的深度优化,就是短周期连接。所谓短周期连接,指的是Weave Client一旦发现一个uWeave设备,并不会主动去建立连接,而是等待用户的驱动。uWeave设备会周期性的通过BLE广播自己的存在,这种广播信息,由于经过特殊设计,消耗的资源很少。运行在智能手机上的Weave Client发现uWeave设备后,只会把这个设备呈现给用户,比如一个门锁,一个智能灯泡,或者一个智能小车。用户发起操作指令,比如用户点击“开锁”之后,Weave Client才试图与uWeave设备建立连接,发送操作命令,等待操作结果。待得到uWeave回复的操作结果之后,Weave Client就会主动断开连接,以节约电源。这种短周期连接机制,可以大大降低uWeave设备的功耗。

显然,这与传统的LibWeave客户端不同。LibWeave端会一直尝试与WeaveCloud或Weave Client建立连接,一旦建立连接,则永久保持,除非用户主动断开,或网络质量问题导致中断。

针对资源受限系统的专门优化

出针对BLE场景的专门优化外,uWeave还针对资源受限的嵌入式系统,做了专门的优化。主要表现在下列几个方面:

首先,是内存分配模式上的优化。一般情况下的嵌入式代码,都会依赖malloc和free等标准的C函数来申请和分配内存。但是这样做会导致一个问题,就是让开发者无法确定准确的内存数量,除非开发者对整个模块的实现了如指掌。因为有些内存是开发者所写的应用程序代码分配的,而有些内存又是诸如uWeave等既有模块分配的。这样开发者就无法跟踪所有的内存使用情况,这在内存资源非常受限的嵌入式领域,是十分严重的问题,开发者无法判断物理内存数量是否能满足所有的需求。

在uWeave的实现中,uWeave代码设计得尽量少的使用堆内存(即通过malloc和free动态分配的内存),尽量使用局部变量或静态全局变量来存储数据。在必须使用堆内存的情况下,uWeave也不自己分配内存,而是让开发者分配内存,然后传递给uWeave。比如下面这个代码片段:

UwDevice* device =(UwDevice*)malloc(uw_device_sizeof());

uw_device_init(device,settings,NULL);

...

这段代码的作用是创建一个uWeave设备对象,然后初始化。可以看出,这个过程没有涉及到任何需要用户输入的数据。在这种情况下,通常的做法是,uWeave直接调用malloc函数,创建一个UwDevice对象,然后初始化即可。但是uWeave却没有这样做,而是提供了uw_device_sizeof和uw_device_init等函数,把整个初始化过程分解为两个步骤,分别由开发者进行调用,完成uWeave设备的创建和初始化。

这样uWeave设备的创建,就由开发者控制,从而可以掌握已经分配的内存数量。这样就不会出现内存耗尽而开发者不知的情况。

另外一个专门针对资源受限的嵌入式系统的设计,就是uWeave完全以静态库(static library)的形式存在。这个静态库会与应用程序代码一同连接在一起,形成一个唯一的二进制模块,加载到嵌入式设备中。uWeave这个静态库不依赖于任何外部的模块。这样就要求uWeave尽可能的实现所有自己所需要的功能代码,同时以标准可移植的C语言(C99)进行实现。这与面向普通设备的LibWeave不同,LibWeave是采用C++语言实现的,而且广泛使用了C++语言的一些高级特性,比如模板(template),弱指针等等。这样就对外部的模块产生了广泛的依赖。一旦加载一个LibWeave模块,该模块依赖的外部模块,也必须被操作系统同时加载。显然,这种广泛依赖外部模块的模式,不适合在嵌入式领域中应用。

uWeave的最后一个针对嵌入式系统的设计优化,是代码的执行时间。我们知道,嵌入式系统往往对程序的执行时间有严格要求,程序不能在规定的时间内完成执行,与执行失败的效果是一样的,甚至更严重。嵌入式领域的每一个函数,都需要有相对固定的执行周期,这样就便于开发者对整个系统的响应时间做出计算和评估。uWeave对每个函数的大致执行时间进行了统计,给出了大致的执行时间上限。这样就方便开发者计算整体的系统响应时间。

上述这些针对资源受限的嵌入式系统的优化和专门设计,并没有为uWeave带来额外的功能,但是却使得uWeave非常适合嵌入式领域应用,符合uWeave的定位。同时,这些设计原则,也可以作为其它嵌入式软件开发的参考,非常具有典型意义。

e)       Weave开发举例

f)        Weave优点和不足分析

Weave是一个相对完整的物联网协同框架,包括了运行在物联网设备上的LibWeave和uWeave,运行在智能手机上的客户端Weave Client,以提供后台服务的Weave Cloud。为了对设备进行一致化的管理和操作,Weave定义了一套基于JSON的Schema,用于描述设备控制命令和状态。Google引入了认证制度,希望把这套Schema做成一个标准,这样只要基于Weave实现的物联网设备,不管是不是Google开发的,就都可以纳入Weave的整个体系,可以通过Weave Cloud和Weave Client进行控制和管理。对用户来说,只要在自己的智能手机上安装一个Weave Client APP,就可以控制所有的物联网设备。

与此同时,Weave在实现上,也有诸多的两点。比如专门针对资源受限的嵌入式系统,开发了uWeave,并专门针对低功耗蓝牙BLE和嵌入式系统做了优化和定制。同时为了充分提高程序开发的便捷性,又采用C++实现了LibWeave,用于计算资源丰富的硬件系统。

但是Weave也有其明显的不足,主要有以下几点:

1.      当前Weave框架实现的功能,还只是人对设备的控制和交互功能。即人可以通过Weave Client或Weave Cloud,来对Weave Device进行控制和管理。并没有实现物联网设备与设备之间的协同。举例来说,如果家里的煤气报警系统被触发,那么煤气报警系统可以立即通知通风系统,加强通风。同时立即通知智能门锁,尽快打开大门,以便家人快速逃生。显然这种物联网系统之间的直接通信,Weave并没有实现。因此严格意义上说,Weave并不能算作一个真正的物联网协同框架;

2.      Weave虽然试图通过标准的Schema建立设备的通信标准,但是并没有引入一套完整的层次化的设备命名体系。一个基于Weave的物联网设备,只能在用户的Google账号范围内可以唯一识别,一旦超出了Google账号的范围,则无法识别;

3.      Weave的底层通信机制,也并没有基于一个统一的标准。在WiFi和Ethernet等局域网环境内,Weave是基于TCP协议进行通信的。但是在低功耗蓝牙领域,则直接基于蓝牙API通信。针对Zigbee以及LoRa等无线通信技术,Weave还没有对应的解决方案。这种相对割裂的通信方式,会大大限制Weave的可移植性;

4.      最后,作为Weave核心组件的Weave Cloud,并没有开源。这样用户就只能使用Gogole的Weave Cloud作为后台服务系统。对一些希望建设自己的后台系统的物联网设备商来说,这是一个严重的阻碍。同时,由于Google的服务器并不是每个地方都能访问到,对于一些无法访问Google服务的地方,则Weave几乎无法使用。

版权所有,请勿对文章内容进行部分裁剪,修改等。转载请注明出处和作者,感谢朋友们支持。