开发者中心

使用SmartREST

概述

QuarkIoEREST API提供了一个在多数环境下可以使用的简单通用IoT协议。它可以特别适应IoT场景, 并使用标准互联网通信和安全机制。 虽然这对使用定制的基于私有技术IoT协议是一个巨大跨越, 但对非常受限的环境如低端微控制器或低带宽通信通道带来了一些挑战。

对于这些环境, QuarkIoE提供了所谓的"SmartREST"协议。 SmartREST结合了标准技术和定制协议的优点:

  • 使用标准HTTP技术工作在任何网络。
  • 支持HTTP身份验证和加密。
  • 优雅处理协议版本。
  • 正常运行时只传输纯有效载荷数据, 网络流量的使用是接近自定义的优化协议。
  • 基于CSV(逗号分隔值),很容易在基于C语言的环境处理。
  • 支持为没有时钟的设备在服务器端生成时间戳。

在下一节中, 我们讨论SmartREST背后的概念以及使用的基本协议。SmartREST使用模板分离元数据和有效载荷数据, 有效载荷在后面描述。 最后, 我们展示如何用SmartREST发送和接收。 协议详细描述参阅 SmartREST参考

SmartREST如何工作?

下面的图片说明了SmartREST如何工作。设备和其他客户端连接到专有的QuarkIoESmartREST端点并按行发送逗号分隔值数据。这些行的数据通过QuarkIoESmartREST代理展开成标准的QuarkIoEREST API请求。类似的, 来自QuarkIoE的应答发送到设备前通过代理从原始JSON格式压缩为逗号分隔值格式。

SmartREST架构

QuarkIoE如何把逗号分隔值解释成有意义的REST请求? 为此, 设备要在QuarkIoE注册模板。模板包含用于扩展的REST请求和占位符, 后续QuarkIoESmartREST代理在次插入逗号分隔值。 对于应答, 模板描述从结构化的REST应答提取哪些值构造逗号分隔值。

模板和设备的软件或固件版本关联。通常, 设备或软件的一个特定实现只发出一组定义良好的请求类型。 相同实现的所有设备共享一组请求类型。因此, 模板可以在实现时定义。为了让模板在QuarkIoE中可用, 特定实现的第一个设备将发送模板并让所有类似设备可用。

这个过程描述如下。假定一个版本"Device_1.0"的设备通过SmartREST发起通信。 检索凭证后, 设备会询问SmartREST代理模板是否已知。如果服务器上没有, 设备通过单一静态文本向QuarkIoE发送模板。一旦过程执行完, 所有使用这个模板的类似设备直接使用SmartREST通信, 而不需要再向服务器发送模板。

SmartREST模板

这个例子粗略展示了转换过程。在"Template 1", "%%" 是一个由SmartREST代理来填充的占位符。 "time"用服务器端时间戳填充(如下)。 其余的占位符由请求的数据填充。 请求例子中的"1,200,20.5"这一行解释如下:

  • 第一列指使用的模板, 这里是模板 1。
  • "200" 指的是模板中第一个空闲占位符, 这里是"source"元素的ID。 (发送测量值的设备ID。)
  • "20.5" 指的是模板中的第二个空闲占位符, 这里是温度测量值。

基本SmartREST协议

所有SmartREST请求的级别结构如下:

  • 所有请求都POST到端点 "/s", 而不管这些请求最终转换到什么。
  • 使用标准HTTP "Authorization" 头来验证客户端。
  • 附加的 "X-Id:" 头用来区分不同的客户端实现, 或者是设备类型 (如 "Device_1.0") 或者是模板注册过程返回的标识符。
  • 请求正文包含逗号分隔值格式的文本行。每行对应一个标准QuarkIoEREST API。
  • 应答总是返回 "200 OK"。
  • 应答正文包含逗号分隔值的文本行。 一行对应对特定请求的一个QuarkIoEREST API应答。

使用上面的例子, 一个SmartREST请求如下:


	POST /s HTTP/1.1
	Authorization: Basic ...
	X-Id: Device_1.0

	1,200,20.5
                    	

相应的应答如下:


	HTTP/1.1 200 OK
	Content-Length: 6

	20,0
                    	

要匹配请求和应答, 应答行相邻错误码的地方包含应答相应的对应请求行号。在这个例子里, "20" 表示 "OK", "0" 表示请求的第1行。

如何注册模板?

如上所属, 使用SmartREST的客户端首先询问服务器是否已知使用SmartREST模板。 这通过一个空的SmartREST请求完成:


	POST /s HTTP/1.1
	Authorization: Basic ...
	X-Id: Device_1.0
                    	

如果设备实现是已知的, 应答将返回一个ID作为后续"X-Id"头中使用的快捷方式。


	HTTP/1.1 200 OK

    20,<id>
                    	

如果设备实现未知, 应答将是:


	HTTP/1.1 200 OK

	40,"No template for this X-ID"
                    	

在这种情况下, 要创建设备实现中的所有模板。


	POST /s HTTP/1.1
	Authorization: Basic ...
	X-Id: Device_1.0

	10,1,POST,/measurement/measurements,application/vnd.com.nsn.cumulocity.measurement+json,,%%,NOW UNSIGNED NUMBER,{ "time": "%%", "type": ... }
                    	...
                    	

在这个例子中, "10" 指的是一个请求模板 (而 "11" 则指一个应答模板)。 模板编号是 "1", 所以这个使用模板的SmartREST请求在第1列是 "1"。 这个模板指的是一个到端点"/measurement/measurements"的"POST"请求, 内容类型是"application/vnd.com.nsn.cumulocity.measurement+json"。模板使用的占位符是"%%"。 这个占位符是一个时间戳("NOW"), 一个无符号数和一个一般的数。最后一列包含需要填充发送的请求正文。

如何处理应答?

上面的例子展示了请求和请求模板的处理。对于应答, JSONPath表达式 转换QuarkIoEREST应答到CSV格式。 假设, 一个设备有个可以显示信息的显示器。一个更新消息的操作将是这样的:


{
    "c8y_Message": {
    "text": "Hello, world!"
    },
    "creationTime": "2014-02-25T08:32:45.435+01:00",
    "deviceId": "8789602",
    "status": "PENDING",
    ...
}
            			

在客户端侧, 设备主要需要知道哪些文本需要显示。在JSONPath, "text"属性用下面的语法提取:


  $.c8y_Message.text 
            			

在这个语法中, "$" 指的是数据结构的根, "." 从数据结构中选择一个元素。更多选项请参考 JSONPath参考

设备通常查询和它相关的所有挂起状态的操作。对这样的请求, 标准QuarkIoE应答是:


    {
        "operations": [
            {
        "c8y_Message": {
            "text": "Hello, world!"
            },
        "creationTime": "2014-02-25T08:32:45.435+01:00",
        "deviceId": "8789602",
        "status": "PENDING",
            ...
        }, {
        "c8y_Relay": {
        ...
    }
    ...
    ]
    ]
   						

也就是说, 应答包含一个操作列表, 而这些操作可以有不同的类型。要用这样的结构, 使用以下相应模板:


    11,2,$.operations,$.c8y_Message,$.c8y_Message.text 
						

这意味着, 一个值一个值描述:

  • 1: 这是一个应答模板。
  • 2: 编号是2。
  • $.operations: 应答是一个列表并且列表属性是"operations"。
  • $.c8y_Message: 模板用属性"c8y_Message"应用到应答。
  • $.c8y_Message.text: 从消息中提取文本并返回。

SmartREST客户端因此将得到下面的应答:


  HTTP/1.1 200 OK

  2,0,"Hello, world!"
						

也就是说, 应答用模板2创建, 模板用来转换显示的消息。应答指对应的是第1个请求。 设置的事件消息是 "Hello, world!"。