您的位置:首页 > 大数据 > 物联网

onenet物联网平台使用

2019-01-05 15:41 134 查看

    OneNET平台提供设备全生命周期管理相关工具,帮助个人、企业快速实现大规模设备的云端管理;开放第三方API接口,推进个性化应用系统构建;提供定制化“和物”APP,加速个性化智能应用生成。注册地址为https://open.iot.10086.cn/,用户可以根据其中的官方文档注册账号,创建设备应用。

本教程使用stm32系列芯片,完成硬件与onenet物联网平台进行交互。 stm32外接Enc28j60网卡芯片,该芯片内置以太网mac,phy层。使用该芯片完成网络传输,需要在该芯片上搭建一个软件TCP/IP协议栈,而UIP协议栈是一个很好的选择。在stm32上移植该协议栈,就可以把stm32采集到的传感器数据上传到onenet云平台。onenet平台支持多种协议,比如Http,MQTT,EDP等协议,而通过HTTP方式上传至云平台是一种常见而且简单的方式,只需要把stm32作为HTTP客户端,通过HTTP的一些标准请求,比如Get,Post等,就可以把数据上传到云端,或者从云端获取数据。 RestFul API 基于HTTP 协议(详见//www.w3.org/Protocols/HTTP/1.0/spec.html) 和json数据格式(详见//www.json.org/json-zh.html) ,适合平台资源管理、平台与平台之间数据对接、使用短连接上报终端数据、时间序列化数据存储等场景。

HTTP协议

HTTP是一个基于TCP/IP通信协议来传递数据,HTTP连接报文分为请求和响应两种,一次请求消息包含请求行,请求头部,空行和请求数据四部分组成。

  • 请求行

用来说明请求类型,要访问的资源目录以及HTTP使用版本,HTTP请求类型包含GET,POST等,它们的具体差别可以查看相关文档

  • 请求头部

接着请求行之后的部分,包含若干属性值,比如指定主机HOST,和onenet交互的API

  • 空行

空行位于报文首部和报文主体之间。

  • 请求数据

对于不同的请求过程,得到的请求数据不一样,比如HTML,JSON等.

 

OneNet HTTP API按照RESTful的方式向外提供服务,其资源模型中包含的资源种类有:用户、设备(device)、数据流(datastream)、数据点(datapoint)、触发器(trigger)、API key、命令等。

  • 数据点(Datapoint)

即一个数据流中的一个具体的数据值。数据点采用“Key-Value”的方式存储。其中Key的组成包括设备ID、数据流ID、时间等信息,value部分可以为任何数据对象,如整数、字符串或者JSON数据类型。

  • 数据流(Datastream)

一个数据流可以理解为一类数据,如传感器之温度、位置之经纬度,空气之湿度等。用户可以自定义数据流名称,即数据流ID;一个设备可以添加多个数据流。

根据onenet官方文档,使用onenet上传数据的POST请求如下所示,请求头部需要指定三个属性,分别为api-key,Host,Content-Length。Content-Length为请求数据的字节大小,在报文首部和报文主体之间还存在空行。使用restful上传的数据格式为json,请求资源的目录为 /devices/509226975/datapoints,其中509226975为创建的设备ID。

[code]POST /devices/509226975/datapoints HTTP/1.1
api-key:aH2orrDNlT1gKXrdurQBoPbm5SI=
Host:api.heclouds.com
Content-Length:63

{"datastreams":[{"id":"sys_time","datapoints":[{"value":50}]}]}

 

先使用上面的POST请求内容,通过网络调试组手上传到onenet服务器,由以下的截图得出,数据上传之后,服务器就会给客户端回复响应的响应。HTTP响应也由状态行、消息报头、空行和响应正文四个部分组成,其中响应的第一行为状态行,有HTTP协议版本号(HTTP/1.1),状态码(200),状态消息(OK)。其中第二行和第三行为消息报头,用来说明客户端要使用的附加信息,Date:生成响应的日期和时间;Content-Type:指定了MIME类型的json,Content-Length为效能感应正文的大小。第三部分为空行,消息报头后面的空行是必须的。第四部分为响应正文,服务器返回给客户端的文本信息,图中是返回得到的json数据。

 

curl是利用URL语法在命令行方式下工作的开源文件传输工具,在ubuntu主机上可以通过apt-get方式安装,使用它可以使用命令行的方式,完成一些HTTP请求。在请求行中指定http方法,使用--request GET或--request POST来指定,请求头部使用--header "请求头内容" 来指定,报文内容使用--data "请求内容"来指定。ubuntu上通过curl工具来向onenet请求获取数据命令如下所示:

[code]//向设备513591948查询数据
curl --request GET --header "api-key: oueSPcHZ0YdDypDfxY56ynJs=4o=" http://api.heclouds.com/devices/513591948/datastreams
//向设备509226975上传数据
curl --request POST --data "{\"datastreams\":[{\"id\":\"sys_time\",\"datapoints\":[{\"value\":888}]}]}" --header "api-key: aH2orrDNlT1gKXrdurQBoPbm5SI=" http://api.heclouds.com/devices/509226975/datapoints

 

 

stm32上传温度数据给onenet,使用stm32开启一个定时器,在定时器中将发送标志位置位,在UIp状态机空闲时不断判断该标志位是否置位,如果置位就将采集到的温度数据打包成上述讲解的HTTP报文并通过POST上传到onenet,然后用户在浏览器就可以看到相关数据。相关核心代码如下所示:

[code]void onenet_send()
{
float value=get_temperature();//获取stm32内部温度传感器数据
//打包请求数据
sprintf(http_content,"{\"datastreams\":[{\"id\":\"temp\",\"datapoints\":[{\"value\":%3.1f}]}]}",value);

//请求行
sprintf(http_header,"POST %s HTTP/1.1\r\n",remote_path);
strcpy(http_request,http_header);
//请求头部的属性
sprintf(http_attribute,"Host:%s\r\n",remote_server);
strcat(http_request,http_attribute);

memset(http_attribute,0,sizeof(http_attribute));
//添加请求头部的属性
sprintf(http_attribute,"api-key:%s\r\n",apikey);
strcat(http_request,http_attribute);
memset(http_attribute,0,sizeof(http_attribute));
//添加请求头部的属性
sprintf(http_attribute,"Content-Length:%d\r\n",strlen(http_content));
strcat(http_request,http_attribute);
memset(http_attribute,0,sizeof(http_attribute));

strcat(http_request,"\r\n");
strcat(http_request,http_content);
uip_send(http_request,sizeof(http_request));
}
//uip回调接口
void tcp_client_appcall()
{
if(uip_connected())//已经连接上服务器?
{
uip_sock_flag =CLIENT_CONNECT;
uip_log("tcp_client connected!\r\n");//
return;
}
if(uip_aborted())//意外终止?
{
//uip_abort();
uip_sock_flag =CLIENT_DISCONNECT;
uip_log("tcp_client aborted!\r\n");//´òÓ¡log
tcp_client_reconnect();
}
if(uip_timedout())//超时?
{

uip_sock_flag =CLIENT_TIMEOUT;
uip_log("tcp_client timeout!\r\n");//
tcp_client_reconnect();
}
if(uip_acked())//确认发出数据?
{
uip_ack_flag=1;
uip_log("tcp_client acked!\r\n");//±íʾ³É¹¦·¢ËÍ
}
if(uip_newdata())//远程主机已经发出数据
{
if(uip_ack_flag)
{
uip_log("*************tcp_client recv data!*********\r\n");//±íʾ³É¹¦·¢ËÍ
printf("\r\n%s\r\n",uip_appdata);
}
}
if(uip_rexmit())//重发?
{
uip_log("tcp_rexmit\r\n");
onenet_send();
return;
}
if(uip_poll())//应用程序循环运行
{
uip_log("uip_poll\r\n");
// 		if(uip_sock_flag!=CLIENT_CONNECT)
// 		{
// 			uip_abort();
// 		}
if(uip_send_flag)//判断发送标志位是否置位?
{
uip_send_flag=0;
onenet_send();
}
}
if(uip_closed())//由于onenet上传一次数据,连接会自动关闭  关闭后就重连
{
uip_ack_flag=0;
uip_sock_flag=CLIENT_DISCONNECT;
uip_log("tcp_client closed! reconnect!\r\n");//´òÓ¡log
tcp_client_reconnect();
return;
}
}
//定时器中断服务函数
void TIM3_IRQHandler(void)
{
static u8  tcnt;
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //
{
GPIOE->ODR ^= GPIO_Pin_8;

if(uip_sock_flag == CLIENT_CONNECT)//连接是否还存在?
{
uip_send_flag=1;

}
}
TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //
}

 

打开浏览器,进入onenet中的设备列表,进入此设备的设备流展示的选项,就可以观察到温度数据已经上传到云平台上了。

 

 

以上是通过一个POST请求将上传上传到云平台的例子,首先在网络调试助手中,通过一个get请求查询数据,使用报文如下:

[code]GET /devices/513591948/datastreams HTTP/1.1
Host:api.heclouds.com
api-key:oueSPcHZ0YdDypDfxY56ynJs=4o=

下面将使用stm32通过get请求不断查询服务器的数据,来控制板载LED灯的量灭,在使用过程中开启一个定时器每隔一段时间通过一个Get请求,查询其中的数据,然后在uip状态机的接受过程中接收服务器响应的数据,得到数据就解析其中的响应报文,然后解析json中的数据包,然后得到开关量,控制LED的亮灭

[code]//发送一个GET请求
void onenet_send()
{
//打包请求数据
sprintf(http_header,"GET %s HTTP/1.1\r\n",remote_path);
strcpy(http_request,http_header);
//请求行
sprintf(http_attribute,"Host:%s\r\n",remote_server);
strcat(http_request,http_attribute);

memset(http_attribute,0,sizeof(http_attribute));
//请求行添加属性
sprintf(http_attribute,"api-key:%s\r\n",apikey);
strcat(http_request,http_attribute);
memset(http_attribute,0,sizeof(http_attribute));

strcat(http_request,"\r\n");

uip_send(http_request,sizeof(http_request));
}
//uip回调接口
void tcp_client_appcall()
{
if(uip_connected())//已经连接上服务器?
{
uip_sock_flag =CLIENT_CONNECT;
uip_log("tcp_client connected!\r\n");//±íʾÁ¬½Ó³É¹¦
return;
}
if(uip_aborted())//意外终止?
{
//uip_abort();
uip_sock_flag =CLIENT_DISCONNECT;
uip_log("tcp_client aborted!\r\n");//´òÓ¡log
tcp_client_reconnect();
//uip_resolv_connect(remote_server,80);
}
if(uip_timedout())//超时?
{

uip_sock_flag =CLIENT_TIMEOUT;
uip_log("tcp_client timeout!\r\n");//´òÓ¡log
tcp_client_reconnect();
//uip_resolv_connect(remote_server,80);
return;
}
if(uip_acked())//确认已经发出数据?
{
uip_ack_flag=1;
uip_log("tcp_client acked!\r\n");//±íʾ³É¹¦·¢ËÍ
}
if(uip_newdata())//远程主机已经发出数据
{
if(uip_ack_flag)
{
uip_ack_flag=0;
uip_log("*************tcp_client recv data!*********\r\n");//±íʾ³É¹¦·¢ËÍ

len_temp=uip_datalen();
memcpy(tcp_client_databuf,uip_appdata,len_temp);
printf("\r\n%s\r\n",uip_appdata);
value_info=(u8 *)strstr(tcp_client_databuf,"\"current_value\"");//截取"\"current_value\""开头的子串
if(value_info!=NULL)
{
len_temp=strlen("\"current_value\":");

status=*(value_info+len_temp);
printf("\r\n%c\r\n",status);
if(status =='0')
{
printf("switch close!\r\n");
// GPIOE->ODR |= GPIO_Pin_8;
GPIOE->BRR = GPIO_Pin_8;
}
else
{
printf("switch open!\r\n");
//GPIOE->ODR &= ~GPIO_Pin_8;
GPIOE->BSRR = GPIO_Pin_8;
}
}
memset(tcp_client_databuf,0,sizeof(tcp_client_databuf));
}
}
if(uip_rexmit())//重发
{
uip_log("tcp_rexmit\r\n");
onenet_send();
return;
}
if(uip_poll())//应用程序循环运行
{
//uip_log("uip_poll\r\n");
if(uip_sock_flag!=CLIENT_CONNECT)
{
uip_abort();
}
if(uip_send_flag)//发送标志位是否置位
{
uip_send_flag=0;
onenet_send();
}
return;
}
if(uip_closed())//由于onenet上传一次数据,连接会自动关闭  关闭后就重连
{
uip_ack_flag=0;
uip_sock_flag=CLIENT_DISCONNECT;
uip_log("tcp_client closed! reconnect!\r\n");//´òÓ¡log
tcp_client_reconnect();
return;
}
}
//定时器3中断服务函数
void TIM3_IRQHandler(void)
{
static u8  tcnt;
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
{

if(uip_sock_flag == CLIENT_CONNECT)//还存在连接
{
uip_send_flag=1;

}
}
TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //
}

 

在浏览器中进入onenet中的应用管理,打开该应用,按下ON/OFF按钮,就可以控制板载LED灯的亮灭

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: