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包含三个大的功能组件:支撑Wea

同时,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分别基于不同的传输层协议,完成通信功能。下图示意了整个协议栈:

之所以设计两类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几乎无法使用。

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

Google物联网操作系统协同框架Weave深度解析的更多相关文章

  1. PHP框架深度解析

    PHP成为世界上最流行的脚本语言有许多原因:灵活性,易用性等等.但通常只用PHP或者其他语言编码就会显得单调.重复,这时候就需要一个PHP框架来代替程序员完成那些重复不变的部分.本文通过回答What, ...

  2. Kafka深度解析

    本文转发自Jason’s Blog,原文链接 http://www.jasongj.com/2015/01/02/Kafka深度解析 背景介绍 Kafka简介 Kafka是一种分布式的,基于发布/订阅 ...

  3. 深度解析SDN——利益、战略、技术、实践(实战派专家力作,业内众多专家推荐)

    深度解析SDN——利益.战略.技术.实践(实战派专家力作,业内众多专家推荐) 张卫峰 编   ISBN 978-7-121-21821-7 2013年11月出版 定价:59.00元 232页 16开 ...

  4. 物联网操作系统HelloX V1.80测试版发布

    经过HelloX开发团队近半年的努力,在HelloXV1.79版本基础上,增加许多功能特性,并对V1.79版本的一些特性进行了进一步优化之后,正式形成HelloX V1.80测试版本.经相对充分的测试 ...

  5. 物联网操作系统HelloX V1.78测试版正式发布

    经过HelloX开发团队近四个月的努力,在HelloX V1.77版本基础上,增加许多功能特性,并对V1.77版本的一些特性进行了进一步优化之后,正式形成HelloX V1.78测试版本,经相对充分的 ...

  6. Kafka深度解析(如何在producer中指定partition)(转)

    原文链接:Kafka深度解析 背景介绍 Kafka简介 Kafka是一种分布式的,基于发布/订阅的消息系统.主要设计目标如下: 以时间复杂度为O(1)的方式提供消息持久化能力,即使对TB级以上数据也能 ...

  7. 《SEO深度解析——全面挖掘搜索引擎优化的核心秘密》

    <SEO深度解析——全面挖掘搜索引擎优化的核心秘密> 基本信息 作者: 痞子瑞 出版社:电子工业出版社 ISBN:9787121224041 上架时间:2014-2-28 出版日期:201 ...

  8. 深度解析VC中的消息(转发)

    http://blog.csdn.net/chenlycly/article/details/7586067 这篇转发的文章总结的比较好,但是没有告诉我为什么ON_MESSAGE的返回值必须是LRES ...

  9. Flink 源码解析 —— 深度解析 Flink 是如何管理好内存的?

    前言 如今,许多用于分析大型数据集的开源系统都是用 Java 或者是基于 JVM 的编程语言实现的.最着名的例子是 Apache Hadoop,还有较新的框架,如 Apache Spark.Apach ...

随机推荐

  1. DOS常用的简单命令

    在windows下的cmd里使用 dir 列出当前目录下的文件及文件夹 md 创建目录 rd 删除目录(只能删除空目录) cd 进入指定目录 cd .. 返回上一级目录 cd / 返回到根目录 del ...

  2. Android Studio导入Fresco

    大概一周之前,Facebook开源了专为Android系统定制的图片下载缓存工具,当天该消息就上了各大技术论坛网站的头条,也成为了各个技术群里讨论的最主要的话题.也就在当天stay4it的QQ群里面就 ...

  3. SU suspike命令学习

    用默认参数生成的数据如下: 用别的软件打开数据查看, 依次查看4个脉冲的位置(第几道.出现的时间), 接下来我们做一些小练习,比如说在同一道上放两个脉冲 还可以增加道数,让脉冲位于不同地方,

  4. F Takio与Blue的人生赢家之战

    Time Limit:1000MS  Memory Limit:65535K 题型: 编程题   语言: 无限制 描述 在那个风起云涌的SCAU ACM里,有两位人生赢家,他们分别是大洲Takio神和 ...

  5. Noi2011 : 智能车比赛

    假设S在T左边,那么只能往右或者上下走 f[i]表示S到i点的最短路 f[i]=min(f[j]+dis(i,j)(i能看到j)) 判断i能看到j就维护一个上凸壳和一个下凸壳 时间复杂度$O(n^2) ...

  6. BZOJ3830 : [Poi2014]Freight

    首先为了保证发车时间都不同,T[i]=max(T[i],T[i-1]+1) 然后设f[i]表示前i列车回来的最早时刻 f[i]=min(max(T[i],f[j]+i-j-1)+s*2+i-j-1) ...

  7. 【Vijos】1431 守望者的逃离

    题目链接:https://vijos.org/p/1431 算法:贪心 描述 恶魔猎手尤迪安野心勃勃,他背叛了暗夜精灵,率领深藏在海底的娜迦族企图叛变.守望者在与尤迪安的交锋中遭遇了围杀,被困在一个荒 ...

  8. HighCharts入门

    一.什么是HighCharts 1.HighCharts是网页报表工具,开发语言是Javascript. 2.HighCharts是一个简单易用.美观.跨平台.跨浏览器的图表工具. 3.HighCha ...

  9. STL各种容器的使用时机详解

    C++标准程序库提供了各具特长的不同容器.现在的问题是:该如何选择最佳的容器类别?下表给出了概述. 但是其中有些描述可能不一定实际.例如:如果你需呀处理的元素数量很少,可以虎落复杂度,因为线性算法通常 ...

  10. Servlet 编程 http请求类型

    HTTP协议的8种请求类型介绍 HTTP协议中共定义了八种方法或者叫“动作”来表明对Request-URI指定的资源的不同操作方式,具体介绍如下: OPTIONS:返回服务器针对特定资源所支持的HTT ...