本帖最后由 imxuheng 于 2022-10-27 14:13 编辑
Arduino平台解析ONENET返回的JSON数据
这里只讨论三种情况下ONENET返回的JSON数据,只解析数据记录中的数据值和采集时间。其他情况也类似。这是我自己摸索云平台的时候总结的,只是经验之谈。 附件提供proteus arduino仿真库 ,按需下载。先用proteus软件仿真调试好之后再烧录到板子上,效率高些。
1 一个节点,一种数据 比如我的设备A只储存了某测点的流速speed,通过如下查询语句查询设备B的最新数据,onenet服务器返回的JSON型数据如下表所示 表1 查询命令和返回数据 查询语句 | onenet服务器返回的内容 | GET /devices/divice_id/datapoints?datastream_id=temp,humi HTTP/1.1 api-key:your apikey
Host:api.heclouds.com
Connection:close
注意: 1.语句中divice_id换成捏设备ID
2.your apikey换成你的appi-key
3.Connection:close后面有两个回车 |
| { "errno": 0,
"data": {
"count": 1,
"datastreams": [{
"datapoints": [{
"at": "2021-08-17 17:11:22.000",
"value": 2 }], "id": "speed" }, "error": "succ" } |
|
画图分析本次onenet服务器返回的内容结构,为方便理解,绘制2种结构图,如下图所示,同一颜色的表示同一级别。
服务器返回的内容可以看做一层一层的JSON数据,解析服务器返回的JSON型数据实际就是一层一层地剥开这个数据团, - 第一层包含errno、data和error,我们关心data这部分
- 第二层包含count和datastreams,我们关心datastreams
- 第三层包含datapoints和id,我们关心datapoint
- 第四层是datapoints内的at和value,at表示采集时间,value表示采集值,就是流速speed的值
这里贴出主要的JSON解析程序,如表2所示。 表2 Arduino平台JSON解析程序 //1:计算要解析的json数据大小 int Strnum = strlen(str_json); //2:创建一个DynamicJsonDocument类型的doc对象,大小 Strnum*2 bytes DynamicJsonDocument doc(Strnum*2); //3:反序列化数据 deserializeJson(doc, str_json); //4:剥开得到data这一层 JsonObjectdatabuff = doc["data"]; //5:剥开得到datastreams这一层,[0]表示datastreams里面的第一个数组元素,就是第一个datapoints,这里datastreams里面的只有一个数组元素; JsonObjectdatapoints = databuff["datastreams"][0]; //6:剥开得到datapoints这一层,[0]表示datapoints这个JSON数组中的第一个对象,实际上两个datapoints数组里面都只有一个对象,这里命名为json_obj,json_obj代表一条关于测点的记录(时间和温度或者湿度) JsonObjectjson_obj = datapoints["datapoints"][0]; //7:将json_obj对象中的记录解析出来,得到采集值和时间 String tim=json_obj["at"].as<String>(); String val =json_obj["value"].as<String>(); Serial.print("res:\r\n"); Serial.print(tim+" "); Serial.print(val); |
2 一个节点,一种数据,多组值 比如我的设备B只储存了某测点的流速speed,通过如下查询语句查询设备B的历史数据(查询从2021-08-17 17:350:00以来的5条数据),onenet服务器返回许多条流速值,如下表所示 表3 查询命令和返回数据 查询语句 | onenet服务器返回的内容 | GET /devices/divice_id/datapoints?datastream_id=temp,humi&start=2021-08-17T17:350:00&limit=5 HTTP/1.1 api-key:your apikey Host:api.heclouds.com Connection:close
注意: 1.语句中divice_id换成捏设备ID 2.your apikey换成你的appi-key 3.Connection:close后面有两个回车 |
| { "errno": 0, "data": { "cursor": "444194_740741953_1629192912459", "count": 5, "datastreams": [{ "datapoints": [{ "at": "2021-08-17 17:35:00.609", "value": 1 }, { "at": "2021-08-17 17:35:02.996", "value": 2 }, { "at": "2021-08-17 17:35:05.343", "value": 3 }, { "at": "2021-08-17 17:35:08.734", "value": 3 }, { "at": "2021-08-17 17:35:10.109", "value": 5 }], "id": "test_stream" }, "error": "succ" }
|
|
同样的步骤再来剥这个数据团,前面三层都一样 4.第四层是datapoints内的多组at和value,一组at和value就是一条记录,at表示采集时间,value表示采集值,就是流速speed的值
这里贴出主要的JSON解析程序,如表2所示。 表4 Arduino平台JSON解析程序 //1:计算要解析的json数据大小 int Strnum = strlen(str_json); //2:创建一个DynamicJsonDocument类型的doc对象,大小Strnum*2 bytes DynamicJsonDocument doc(Strnum*2); //3:反序列化数据 deserializeJson(doc, str_json); //4:剥开得到data这一层 JsonObject databuff = doc["data"]; //5:剥开得到datastreams这一层,[0]表示datastreams里面的第一个数组元素,就是第一个datapoints;[1]表示datastreams里面的第二个数组元素,就是第二个datapoints; JsonObject datapoints = databuff["datastreams"][0]; //6:剥开得到datapoints这一层,[2]表示datapoints这个JSON数组中的第3个对象(实际datapoints数组里面都有5个对象),这里命名为json_obj,json_obj代表一条关于测点的记录(时间和温度或者湿度) JsonObject json_obj = datapoints["datapoints"][2]; //7:将json_obj对象中的记录解析出来,得到采集值和时间 String tim =json_obj["at"].as<String>(); Stringval = json_obj["value"].as<String>(); Serial.print("res:\r\n"); Serial.print(tim+" "); Serial.print(val); | |
3 一个节点,多种数据 我的设备C有两种参数,分别是温度和湿度,数据名分别为temp和humi,通过如下查询语句查询设备A的最新数据,onenet服务器返回的JSON型数据如下表所示 表5 命令和返回数据 查询语句 | onenet服务器返回的内容 | GET /devices/divice_id/datapoints?datastream_id=temp,humi HTTP/1.1 api-key:your apikey Host:api.heclouds.com Connection:close
注意: 1.语句中divice_id换成捏设备ID 2.your apikey换成你的appi-key,
3.Connection:close后面有两个回车
|
| { "errno": 0, "data": { "count": 2, "datastreams": [{ "datapoints": [{ "at": "2022-10-26 :44:29.000", "value": 23 }], "id": "temp" }, { "datapoints": [{ "at": "2021-08-17 17:42:22.755", "value": 88 }], "id": "humi"
},
"error": "succ"
}
|
|
画图分析本次onenet服务器返回的内容结构,为方便理解,绘制2种结构图,如下图所示,同一颜色的表示同一级别。看起来和前一节的差不多。
同样的步骤再来剥这个数据团,前两步一样 3.第三层包含两个datapoints和一个id,我们关心着两个datapoints,一个datapoints储存温度和温度采集时间;另一个datapoints储存湿度和湿度采集时间; 4.第四层是datapoints内的at和value,at表示采集时间,value表示采集值
这里贴出主要的JSON解析程序,如表3所示。 表6 Arduino平台JSON解析程序 //1:计算要解析的json数据大小 int Strnum = strlen(str_json); //2:创建一个DynamicJsonDocument类型的doc对象,大小 Strnum*2 bytes DynamicJsonDocument doc(Strnum*2); //3:反序列化数据 deserializeJson(doc, str_json); //4:剥开得到data这一层 JsonObjectdatabuff = doc["data"]; //5:剥开得到datastreams这一层,[1]表示datastreams里面的第2个数组元素,就是第2个datapoints;[0]表示datastreams里面的第1个数组元素,就是第1个datapoints; JsonObjectdatapoints = databuff["datastreams"][1]; //6:剥开得到datapoints这一层,[0]表示datapoints这个JSON数组中的第一个对象,实际上两个datapoints数组里面都只有一个对象,这里命名为json_obj,json_obj代表一条关于测点的记录(时间和温度或者湿度) JsonObjectjson_obj = datapoints["datapoints"][0]; //7:将json_obj对象中的记录解析出来,得到采集值和时间 String tim=json_obj["at"].as<String>(); String val =json_obj["value"].as<String>(); Serial.print("res:\r\n"); Serial.print(tim+" "); Serial.print(val); |
4 总结 “一个节点,一种数据”和“一个节点,一种数据,多组值”的JSON结构只在datapoints内不一样,前者一条记录(一组at和value),后者多条记录(多组at和value) “一个节点,一种数据”和“一个节点,多种数据”的JSON结构只在datastreams内不一样,前者一个datapoints(内含一条记录),后者多个datapoints(每个datapoints内含一条记录) 三种情况的程序也只有第5和6步有些区别 表7 不同情况下程序语句的区别 情况类型 | 有区别的程序语句 | | JsonObject datapoints = databuff["datastreams"][0]; JsonObject json_obj = datapoints["datapoints"][0]; |
| | JsonObject datapoints = databuff["datastreams"][0]; JsonObject json_obj = datapoints["datapoints"][2];//选择哪一条记录 |
| | JsonObject datapoints = databuff["datastreams"][1];//选择哪一个datapoints JsonObject json_obj = datapoints["datapoints"][0]; |
|
|