查看: 7526|回复: 0

[8月赛] 【云上的你】OneNET平台模拟设备接入测试

[复制链接]

3

主题

3

帖子

17

积分

新手上路

Rank: 1

积分
17
发表于 2017-8-1 23:53:14 | 显示全部楼层 |阅读模式
本帖最后由 胡凌炜 于 2017-8-3 09:57 编辑

       作为实习生,OneNET平台对于我来说是一件新奇的事物。经过培训我知道了麒麟开发板接入OneNET平台的基本操作。为了更好地理解OneNET平台是如何为物联网海洋中各种各样设备与应用提供服务的,我对于OneNET平台支持的协议进行了学习,并应用开放SDK完成了不同协议对于OneNET平台的接入测试。接下来就让我简单介绍一下OneNET平台模拟设备接入的相关要点。
OneNET平台支持支持多种行业标准协议的解析和转换,如HTTPEDP、MQTTModbus等,本文主要介绍前三种协议的消息格式和接入方式。同时OneNET还支持多种语言开发环境,在本文我主要介绍如何采用C语言进行模拟设备接入。
1.      HTTP协议接入测试:
1.1   协议简介
OneNET平台支持HTTP协议的接入。使用HTTP协议,可以实现终端不需要实时接收控制命令的业务模型,终端只是采集数据并上报到业务平台,当用户不需要平台向终端设备下发命令时,可以采用该协议方式接入终端设备。因此该协议主要应用于自定义业务平台,可通过HTTP 协议的RESTful API操作OnetNet提供的资源,进行设备、数据点、命令控制等资源的增删查改等操作。
1.2   协议消息格式及其类型
HTTP协议的消息格式不做过多介绍,这里主要直接介绍设备采用HTTP协议接入时采用的方法及请求报文格式,如表一和表二所示。
表一、 HTTP方法
  
HTTP  方法
  
描述
POST
新增资源信息
PUT
更新资源信息
GET
查看资源信息
DELETE
删除资源

HTTP原始报文格式由请求行(request line)、请求头部(header)、空行和请求内容(content) 4个部分组成,具体如表二所示。
表二、 HTTP请求原始报文
  
请求行
  
空格
URL
空格
协议版本
回车符
换行符
头部字段
:(冒号)
回车符
换行符
……
头部字段
:(冒号)
回车符
换行符
空行
HTTP请求内容


我们需要自己封装HTTP报文,完成对应的操作。根据协议与平台SDK的规定,如新增设备,我们需要发送的请求中包括请求方法、URL、APIKey等信息,其中APIKey用于对用户进行鉴权以及让平台知晓该设备属于哪一个产品。此外还可以在请求内容中添加设备的基本信息。对应的添加设备的HTTP请求报文如表三所示,其中创建设备的APIKey必须为Master APIKey。对应的添加数据流、更新设备信息、添加数据点等操作都有类似的请求报文,这类操作的APIKey可以为设备级的APIKey。其中数据点上传支持的类型包括整型、浮点数、字符串、JSON和二进制。
                                                                                           表三、添加设备HTTP请求报文
  
POST   /devices  HTTP/1.1\rundefined
  api-key:<your_api_key>\rundefined
  Host:api.heclouds.com\rundefined
  Content-Length: 32\rundefined
  \rundefined
  {"title":"898602B2221430000029"}
  
1.3  接入流程及代码分析
这里我们以创建设备为例说明接入的流程及代码。
(1)     创建产品,这一步需要登录OneNET平台,用户在网站上进行,指定接入协议为HTTP;
(2)     创建设备;
                 RFDeviceConfigconfig;
                 memset(&config,0, sizeof(config));
                 strcpy(config.APIKey,myAPIKey);
                 ret =RFDevice_Create(&config, deviceID))
              其中RFDeviceConfig是一个结构体,存储着创建设备需要的APIKey和一些设备配置信息,包括设备名、设备描述、设备是否为私有等信息。
              在调用RFDevice_Create函    数前需要给config.APIKey赋MsterAPIKey值, RFDevice_Create函数用于创建设备,第二个参数用于存储创建的设备ID。在RFDevice_Create  函数               内需要调用
                 HTTPComm_CreateDefaultHeader(HTTP_METHOD_POST,CLOUD_RES_TYPE_DEVICE, devConfig->APIKey, NULL, NULL);
              生成对应的HTTP头部,第一个参数指明请求方法为POST。接下来调用HTTPComm_Connect函数建立本机到指定主机的HTTP连接。
              HTTPComm_Connect("api.heclouds.com",80);
              再调用DeviceJsonBodyGen函数生成构造新增或更新设备的JSON字符串,即生成请求内容。
                 ret = DeviceJsonBodyGen(pJsonBody, devConfig, DEVICEINFO_MASK_ALL);
              参数DEVICEINFO_MASK_ALL表明更新设备所有信息。
              最后调用HTTPComm_Process函数发送HTTP请求并获取响应。
                 pRespBody =HTTPComm_Process(pJsonBody, strlen((const char *)pJsonBody), NULL);
(3)     更新设备信息的基本过程与创建设备类似,调用RFDevice_UpdateInfo函数,其中DEVICEINFO_MASK_LOCATION表明更新设备位置信息。
                 ret =RFDevice_UpdateInfo(&config, DEVICEINFO_MASK_LOCATION)
              因为OneNET平台没有采用的HTTP的长连接功能,所以RFDevice_UpdateInfo函数需要重新建立连接,再生成HTTP请求头,填充请求内容,其中包含更新的位置信息,
              最后发送请求并获取响应;
(4)     创建数据流和发送数据点与上面的操作基本上具有同样的步骤,区别在于调用的函数具有不同参数,因此可以生成不同的HTTP请求内容,而接口函数内部建立连接、发送请求等                 实现流程是一样的。
              最后给出采用HTTP协议接入OneNET平台并创建设备的测试结果,如图一所示
IMG_20170802_100945.jpg
IMG_20170802_101010.jpg

图一、HTTP协议接入测试结果
2.      EDP协议接入测试:
        2.1  协议简介
              EDP协议是OneNET平台根据物联网特点专门定制的完全公开的基于TCP的协议,在平台中主要承载业务数据和控制命令。EDP协议是一个长连接协议,支持数据加密、数据南北         向传输和端到端数据转发。该协议能够广泛应用于家具、交通、物流、能源等行业的物联网相关应用中。
         2.2  协议消息格式及其类型
表四、EDP消息格式
  
字节\bit
  
7
6
5
4
3
2
1
0
Byte  1
消息类型
保留位(全零)
Multi-bytes
剩余消息长度(1-4字节,指示选项+消息体的长度)
Multi-bytes
选项(根据消息类型0个或多个)
Multi-bytes
消息体(根据消息类型0或多个字节)
      
          消息格式的第一个字节中的高4位指定消息类型,低四位为保留位。接下来为剩余消息长度,占据第二至第五字节。
          EDP支持15种消息类型,如表五所示
表五、EDP协议消息类型
  
类型值
  
含义
方向
1
CONN_REQ:连接建立请求
C(client)->S(server)
2
CONN_RESP:连接建立响应
S->C
3
PUSH_DATA:转发(透传)数据
双向
4
CONN_CLOSE:连接关闭
S->C
5
UPDATE_REQ:上报当前使用的软件信息
C->S
6
UPDATE_RESP:平台下发当前最新的软件信息
S->C
7
SUB_DEVICE:子设备请求
双向
8
SAVE_DATA:存储(&转发)数据
双向
9
SAVE_ACK:存储确认
S->C
10
CMD_REQ
S->C
11
CMD_RESP
C->S
12
PING_REQ:  心跳请求
C->S
13
PING_RESP:  心跳响应
S->C
14
ENCRYPT_REQ
C->S
15
ENCRYPT_RESP
S->C
其他值
保留

                由于EDP消息类型较多,本文只介绍建立连接请求和转发数据两个消息类型。
            (1)    连接请求消息格式:
                         连接请求包含三部分:消息头,一些选项和消息体。其中,选项包括协议名称、协议版本、连接标志、保持连接时间。消息体中可能包含设备ID、产品ID(可选)、鉴权                   信息。三项内容都为长度+内容的字符串格式。EDP登录方式有两种,方式1为设备ID和APIKey;方式2为产品ID和鉴权信息。这里我们采用登陆方式1登录平台,消息格式具体                  如表六所示
表六、连接请求消息格式
  
字节
  
说明\bit
7
6
5
4
3
2
1
0
消息头
Byte  1
第一字节:
  
Bit4-7):消息类型,值为1
  
Bit0-3):保留位,值为0
0
0
0
1
0
0
0
0
变长剩余消息长度(25编码后需要占用1个字节)
Byte  2
第二字节:
  
消息剩余字节长度,值为50
0
0
0
1
1
0
0
1
选项1:协议描述(字符串格式)
Byte  3
长度高位字节,值为0
0
0
0
0
0
0
0
0
Byte  4
长度低位字节,值为3
0
0
0
0
0
0
1
1
Byte  5
字母’E’
0
1
0
0
0
1
0
1
Byte  6
字母’D’
0
1
0
0
0
1
0
0
Byte  7
字母’P’
0
1
0
1
0
0
0
0
选项2:协议版本
Byte  8
一个字节表示,值为1
0
0
0
0
0
0
0
1
选项3:连接标志
Byte  9
Bit7):产品ID标志位,值0
  
Bit6):鉴权信息标志位,值1,表示后面消息体有该项
  
Bit0-5):系统保留位,填0
0
1
0
0
0
0
0
0
选项4:保持连接时间(256=0x0100
Byte  10
  
第一字节,时间值的高位字节,值1
0
0
0
0
0
0
0
1
Byte  11
第二字节,时间值的低位字节,值0
0
0
0
0
0
0
0
0
消息体-设备ID(字符串格式)
Byte  12
长度高位字节,值为0
0
0
0
0
0
0
0
0
Byte  13
长度低位字节,值为5
0
0
0
0
1
0
0
1
Byte  14
字符’9’
0
0
1
1
1
0
0
1
…….(假设设备ID9位数字组成)
Byte  22
字符’1’
0
0
1
1
0
0
0
1
消息体-鉴权信息(字符串格式)
Byte  23
长度高位字节,值为0
0
0
0
0
0
0
0
0
Byte  24
长度低位字节,值为7
0
0
0
0
0
1
1
1
Byte  25
字符’a’
0
1
1
0
0
0
0
1
…….(假设设备APIKey28个字符组成)
Byte  52
字符’c’
0
1
1
0
0
0
1
1
      
(2)     数据转发消息类型
              该消息类型具有两个方向,可以由设备向OneNET平台,也可以由平台向设备发送控制命令。由设备向平台发送数据,平台收到该消息,选项中的地址是该数据转发的目的地址                  (目的设备ID号);由平台向设备发送数据,设备收到该消息,选项中的地址是该数据发送的发送者地址。

2.3  接入流程及代码分析
(1)    创建socket套接字并连接服务器,注意EDP协议接入的服务器端口为876,IP地址为jjfaedp.hedevice.com 。
(2)    如果是加密请求则调用PacketEncryptReq函数打包由设备到设备云的EDP协议包;
                   EdpPacket* send_pkg;
                   send_pkg = PacketEncryptReq(kTypeAes);
               其中EdpPacket为定义的EDP包结构体,PacketEncryptReq的参数为加密类型。目前只支持AES加密算法,对应的参数为kTypeAes;
               如果不是加密请求,那么则调用PacketConnect1函数打包由设备到平台的EDP连接请求包,并采用认证方式1登录OneNET平台
                   send_pkg = PacketConnect1(src_dev,src_api_key);
(3)      将send_pkt中的内容写入到socket描述符,发送连接请求;
                   ret=DoSend(sockfd, (const char*)send_pkg->_data,send_pkg->_write_pos);
(4)      send_pkt清零;
(5)       封装需要发送的EDP数据包,调用PacketSavedataInt函数打包设备到设备云的EDP协议包, 数据类型为JSON,该函数适用于数据点为int型的数据,对应着还有类似的函数用于
         封装EDP数据包。
               send_pkg =PacketSavedataInt(data_type, dst_dev, ds_for_send, dp, 0, 0);
         其中dst_dev为目标设备,ds_for_send为数据流编号, dp为int型数据点,后面两个参数分别代表着消息时间和消息标志,第一个‘0’代表默认系统时间,否则采用给定时间,  第二           个‘0’代表包不携带消息标志。
(6)       调用DoSend函数发送携带有数据的EDP包
(7)       释放send_pkt,关闭套接字。
         EDP协议的测试结果与MQTT协议类似,这里不再过多展示。

3.       MQTT协议接入测试:
  3.1  协议简介
                MQTT协议是一个面向物联网应用的即时通信协议,使用TCP/IP提供网络连接,能够对负载内容实现消息屏蔽传输,开销小,可以有效降低网络流量。该协议除了EDP协议所具          有 的一些特点外还支持基于Topic的订阅、发布以及消息推送等功能。
  3.2  消息格式及其类型
         MQTT消息包由三部分组成
表8、MQTT消息包格式
  
固定请求头
  
所有类型消息中都必须有
可变请求头
部分包含有
载荷
部分包含有

           MQTT有9种消息类型,如表9所示
  
名字
  
流向
描述
CONNECT
1
C->S
客户端请求与服务端建立连接
CONNACK
2
S->C
服务端确认连接建立
PUBLISH
3
CóS
发布消息
PUBACK
4
CóS
收到发布消息确认
SUBSCRIBE
8
C->S
订阅请求
SUBACK
9
S->C
订阅确认
UNSUBSCRIBE
10
C->S
取消订阅
UNSUBACK
11
S->C
取消订阅确认
PING
12
C->S
客户端发送PING(连接保活)命令
PINGRSP
13
S->C
PING命令回复
DISCONNECT
14
C->S
断开连接

   3.3  接入流程
(1)调用Mqtt_InitContext初始化MqttContext,MqttContext为MQTT运行时上下文,主要包括一些读取数据回调函数、发送数据和处理响应的等一些回调函数;
(2)创建MqttBuffer, 并通过MqttBuffer_Init进行初始化;
(3)创建socket套接字并连接服务器,注意MQTT协议接入的服务器端口为6002,IP地址为183.230.40.39。
(3)调用Mqtt_PackConnectPkt,封装MQTT连接包;
               ret = Mqtt_PackConnectPkt( buf, keep_alive,id, clean_session,  will_topic,
          will_msg, msg_len, qos,  will_retain, user,  password,  pswd_len)   
其中id需设置为设备ID,user需设置为project ID,password需设置为auth-info,这些信息都是用于连接平台时进行鉴权的信息;
(4)调用Mqtt_SendPkt发送MQTT连接包;
bytes = Mqtt_SendPkt(mqttctx, mqttbuf, 0);
(5)mqttbuf清零;  
(6)封装需要发送的MQTT数据包,调用Mqtt_PackDataPointByString函数打包设备到设备云的MQTT协议包, 数据点类型为String字符串,对应着还有类似的函数用于封装MQTT数据包。
err = Mqtt_PackDataPointByString(mqttbuf,g_pkt_id++, 0, kTypeFullJson, str, size, MQTT_QOS_LEVEL1, retain, own);
其中kTypeFullJson表明字符串中的内容为JSON类型,g_pkt_id为数据包ID,为非零整数,str为数据起始地址,retain 非0时,服务器将该publish消息保存到topic下,并替换已有的publish消息。
(7)调用Mqtt_SendPkt发送MQTT数据包;
(8)释放mqttbuf和mqttctx,关闭套接字;
最后给出采用MQTT协议接入OneNET平台建立连接并连续发送三个数据的测试结果,如图二所示,主要显示了发送的鉴权信息以及数据的十六进制表示。
3.png
图二、MQTT测试结果


回复

举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表