我们来看看一个简单的物联网系统。就以智能电灯为例子,假设我们需要能够电灯在光线比较暗的时候自动打开,在光线较亮的时候自动关闭,能够随着光线强弱的改变调整亮度。并且能够人工控制开启、关闭、亮度调节。在这样一套系统中,通常会包含以下的组件:
- 数据采集组件:我们需要采集光线强度的数据,这里使用的采集组件是光照强度的传感器。
- 执行组件:我们要实现电灯的开启和关闭,需要控制电路的通断,这个通常使用继电器。我们要控制亮度,通常需要控制电压(无级调节)或者将发光器件分为几组,分别控制开启和关闭(分级调节),这就需要有变压器或者继电器。这些都是执行组件。
- 控制组件:执行组件会执行命令,命令从哪里来?由控制组件发出。控制组件负责基于数据采集组件采集的数据,执行设定的应用逻辑,发出命令驱动执行组件执行指定的动作。 控制组件的实现形式有很多,比如专用的开发板、集成在网关(后面会讲到)中、嵌入到边缘计算设备中等。
- 网关: 在家庭环境中,我们通常采用BLE技术作为通信技术,但是要接入互联网,完成远程控制,则需要有桥接设备。通常我们选择一个设备来桥接家庭中所有的智能设备,这个桥接设备就被称为网关。网关不一定是由路由器来担当,也可以由电视、智能音箱等设备担当网关。
- 用户界面:既然需要人工控制,那么一定要有一个交互的方式,或者叫用户界面。可以是App应用,也可以是摄像头、音箱这样的设备。
如果只是要自娱自乐,做一个系统练练手,上面这样设计基本就可以了。怎样控制电灯,电灯要上报什么信息,我们自己知道就可以了。
但是在一个成熟的系统中,如果想让智能台灯能够成为物联网系统的一部分,则还需要考虑一些问题:
- 如果其他的应用也需要和台灯交互,怎样获取电灯的信息和控制电灯的行为?
- 如果台灯坏了,需要更换,只能使用同样的台灯吗?还是可以更换其他的台灯型号?
做过开发的同学一定很容易想到解决的方案——标准化接口。还是那句名言:计算机科学领域的任何问题,都可以通过增加一个中间层来解决。 标准化接口其实就是在使用者和提供者之间添加了一个中间层。
8 物模型
在物联网中,提供了Thing Specification Language,缩写为TSL,直译过来就是“物规范语言”。TSL是用来描述物联网中的物的一种规范语言。使用TSL描述的物联网中的实体模型,就称为物模型。物模型就是这个中间的标准化接口。
8.1 物模型和设备之间的关系
物模型其实就是对现实世界中物的抽象,抽取我们所关注的方面,然后使用TSL描述为计算机能够处理的信息。主要的作用就是说清楚这个物是什么,可以提供什么信息,能够完成什么事情。
在抽象的过程中,需要提取产品的共同特征,形成模型。例如上面的智能台灯,无论采用哪种类型,都必须有开关属性。将这些共同的特征标准化之后,就形成了智能台灯的物模型。一旦形成标准之后,后续的产品则需要遵循标准。
因为物模型是基于一类产品的共同特征抽取的,因此采用了物模型之后,应用程序就不再耦合于一个具体的产品,而是可以应用于遵循这个规范的所有的产品。就像程序开发中的接口类和实现类一样,这其实也是面向接口编程的一种思路和体现。
8.2 怎样来定义物模型
对于一个模型的定义,通常我们从属性、事件和动作这三种功能元素来定义。和我们大家熟悉的面向对象编程中类的抽象过程是一脉相承的。
还是以智能台灯为例,所有的智能台灯,都必须具备开、关状态。很多台灯有亮度状态,还有一些台灯有色温等状态。这些描述智能台灯的运行时的状态的数据项,我们称之为属性(Property)。
通常来说,属性是可读可写的。应用程序需要读取属性来了解设备的运行状态,需要写入属性来控制设备的运行状态。
另外,有些时候,智能台灯需要主动向物联网平台报告状态的变化,比如硬件故障。向这样的设备主动报告的情形,我们称之为事件(Event)。一个事件中可以包含多个信息,对应事件的不同参数。事件是由设备主动上报的,不能由应用来设置。
其实有了属性和事件,我们已经能够完成基本的功能。但是很多情况下,让我们逐一控制各个属性,比较繁琐。我们可以把常用的状态组合设置为一个预先定义好的场景,或者叫模式。这样在使用的时候,可以通过一个指令修改多个属性的值。这种方式就叫动作(Action),有些时候也被称为设备对外提供的服务(Service)。
8.2.1 物模型描述的总体结构
抽取了属性、事件、动作这些特征之后,需要能够描述为计算机能够读懂的信息,这就轮到TSL上场了。
在TSL中,基本的数据类型有6中:
- 布尔型 bool
- 整数型 int
- 字符串 string
- 浮点型 float
- 枚举型 enum
- 时间型 timestamp
TSL中采用JSON格式来描述物模型,我们来看看一个物模型的完整的组成形式:
{
"version": "1.0",
"properties": [ //属性列表
{......},
......
{......}
],
"events": [ //事件列表
{......},
......
{......}
],
"actions": [ //动作列表
{......},
......
{......}
],
"profile": { //产品参数
"ProductId": "abcd1234",
"CategoryId": "141"
}
}
上面的物模型的描述中,主要的就是属性列表、事件列表和动作列表。下面我来看看怎样定义一个属性、事件和动作。
8.2.2 描述属性
以所有的智能台灯都需要的开关属性为例,这个属性只能有两种值:开或者关。在TSL中可以如下表示:
{
"identifier":"powerSwitch", //属性的唯一id
"name":"电源开关", // 属性的名称
"accessMode":"rw", //属性的访问模式,r表示可读,w表示可写
"required":true, //是否是必须提供的属性
"dataType":{ //属性值的定义
"type":"bool", //属性值的类型
"mapping":{
"0":"关”,
"1":"开"
}
}
}
注意这里面的required,描述了属性是否是必须的。因为有些属性,例如色温,并不是每个产品都提供的。
注意,不同的物联网平台所使用的TSL是有细微的差别的,需要根据实际的情况调整。
8.2.3 描述事件
描述事件的方法和描述属性的方法大同小异。
{
"identifier":"voltageLow",
"name":"电压过低",
"type":"alert",
"required":false,
"outputData":[
{
"identifier":"voltage",
"name":"电压",
"desc": "当前电压",
"dataType":{
"type":"int",
"specs":{
"min":"0",
"max":"220"
}
}
}
]
}
事件需要向物联网平台上报信息,因此需要outputData。
8.2.4 描述动作
动作的描述和前面的属性和事件的描述也差不多,但是需要有inputData和outputData。
{
"identifier":"changeToMode",
"name":"切换到指定的模式",
"required":false,
"callType":"async",
"inputData":[
{
"identifier":"mode",
"name":模式",
"dataType":{
"type":"int"
}
}
],
"outputData":[
{
"identifier":"currentMode",
"name":"切换后的模式",
"dataType":{
"type":"int"
}
}
]
}
网友评论