建议使用以下浏览器,以获得最佳体验。 IE 9.0+以上版本 Chrome 31+ 谷歌浏览器 Firefox 30+ 火狐浏览器
请选择 进入手机版 | 继续访问电脑版
设置昵称

在此一键设置昵称,即可参与社区互动!

确定
我再想想
选择版块
标签
您还可以添加5个标签
  • 没有搜索到和“关键字”相关的标签
  • 云产品
  • 解决方案
  • 技术领域
  • 通用技术
  • 平台功能
取消

樊心昊

发帖: 172粉丝: 136

发消息 + 关注

发表于2020年06月15日 17:25:39 1060 3
直达本楼层的链接
楼主
显示全部楼层
[技术干货] 0x07 LiteOS_Lab仓库组件详解 cJSON(上)

摘要:我们将设备采集到的数据上传到云平台一般有两种主流的方式:二进制码流和json,本章用于讲解在LiteOS仓库中集成的cJson库,用于将需要上报的数据封装为json格式或者将云平台下发的json格式数据解析出来。

一、华为云平台需要的json数据格式

当我们下位机使用mqtt协议来进行通讯并且mcu的ram和flash也比较充裕,我们就可以采用json格式来和云平台进行数据交互。

首先在定义产品的时候协议类型选择MQTT和数据格式选择JSON:

image.png

大家可以查看下这个帮助手册,主要说明了华为云平台要求的JSON数据格式的要求,JSON数据格式分为设备命令、设备消息和设备属性,我这里主要说的是设备属性和设备命令:设备属性上报设备命令下发

image.png

services:类型为list(array),存放设备服务数据

service_id:类型为string,与我们产品中的服务相对应Agriculture

image.png

properties:类型为object,存放设备服务的属性,例如Temperature、Humidity等,和属性名称及值对应,在产品中定义的,如下图。

image.png

云平台收到的数据必须与我们在产品中定义的数据格式相同,必选的属性必须存在,否则该数据会被丢弃,如果收到的数据正确我们就可以在“设备”页面中看到如下显示:

image.png

二、cJSON库简介

到这里大家应该明白了为什么今天我们需要讲解cJson库了,cJson库的作用是什么了。

cJSON库是一个基于MIT的代码,项目仓库地址:https://github.com/DaveGamble/cJSON,我们在LiteOS中主要用到其中的两个文件:cJSON.h和cJSON.c。

该库可以十分方便的将我们的数据结构体,例如:

image.png

转换为json格式的,甚至还能直接以非格式化字符的形式打印出来,就是这样的:

image.png

,极大的提高了我们处理数据的效率,还能将json格式的数据转换为便于处理的键、值等等。

三、cJson库中封装相关函数详解

这里就以上面的Agriculture的上报属性数据的结构体为例,带领大家将它转换为JSON格式的数据。

几个重要概念

       Object和Item:Object和Item是相对的,不是绝对的,这句话有些抽象,我来举个例子向大家说明,例如之前我的定义的json数据:

image.png

1、 ①到⑩之间的所有数据可以称为一个Object,②到⑩之间的数据就是它的键为”services”,类型为array的item。

2、 ②到⑩之间的所有数据可以称为一个Object,其中③处的键值对是它的第一个键为“service_id”,类型为string的item,其中④到⑨处的键值对是它的第二个键为“properties”,类型为Object的item。

3、 ④到⑧之间的所有数据可以称为一个Object,其中⑤⑥⑦都是分别是该Object的三个item,他们的类型都是int。

 

       嵌套:嵌套的意思大家只要理解了上面我说的Object和Item的概念就算理解了。Object中嵌套了Object,那这个被嵌套的Object就是Item。

cJSON结构体

       该结构体的声明在cJSON.h文件中,大家可以自行查看。

image.png

next和prev指针:通过cJSON结构体定义的变量可以实现一个链表,在进行增、删、查、改时通过next和prev指针来完成。

child指针:当我们需要添加一个item到某个Object的时候(嵌套),就将这个item指针挂接到该节点的child成员上。

type变量:用于标记该item的类型,例如string、number、bool、array、object等。

valuestring指针:用于当item类型为string类型时,指向值所对应的字符串。

valueint变量:用于当item类型为number类型时,存储值对应的int类型数据。

Valuedouble变量:用于当item类型为number类型时,存储值对应的double类型数据。

string指针:指向该item键的对应的名称。

当该item为bool类型,其中的值为false或者true时,该值存储于type变量处。

绑定系统特有的内存分配及释放函数

       因为在创建object和删除object时需要使用到内存,所以在初始化cJSON库时,我们就需要将系统中进行内存分配及释放的函数注册到cJSON库中。

例如裸机开发时,用malloc分配内存,用free释放内存。

例如用LiteOS_Lab框架开发时,用osal_malloc分配内存,用osal_free释放内存。

通过如下操作即可完成注册:

image.png

Object的创建

我们需要进行json格式数据处理时,首先通过JSON数据类型定义一个JSON数据类型变量指针,并通过cJSON_CreateObject为其分配内存并初始化(如果是array类型的object则调用cJSON_CreateArray,其他类型的创建可以自己类比,创建相关函数见下图)。

image.png

向Object中添加item

例如我们要创建如下的一个JSON格式的数据。

image.png

首先需要创建两个Object,第一个称为root的Object,后面将键为properties的item挂上去,第二个为properties的Object,用于“温度、湿度、光照”键值对的挂接。

代码部分:

unsigned char* str_js = NULL;            //定义一个字符串指针

cJSON* cjson_root = NULL;               //定义cJSON类型的指针

cJSON* cjson_properties = NULL;

 

cjson_root = cJSON_CreateObject();  //为上面的指针分配内存并进行初始化

cjson_properties = cJSON_CreateObject();

 

//将温度、湿度、光照键值对添加到名为properties的Object中

cJSON_AddNumberToObject(cjson_properties, "Temperature", 20);

cJSON_AddNumberToObject(cjson_properties, "Humidity", 18);

cJSON_AddNumberToObject(cjson_properties, "luminance", 50);

 

//将名为cjson_data的Object挂接到名为cjson_root的Object上

cJSON_AddItemToObject(cjson_root, "properties", cjson_properties);

 

//将cJSON转换为非格式化字符串打印一下

str_json = cJSON_Print(cjson_root);

printf("Data is %s\r\n", str_json);

 

//用完之后一定要记得释放

cJSON_Delete(cjson_root);

if(str_json!=NULL)

osal_free(str_json);

 

效果图如下:

image.png

 

PS:关于指令的解析放在下一篇来说!

举报
分享

分享文章到朋友圈

分享文章到微博

Jasonchenbj

发帖: 132粉丝: 9

发消息 + 关注

发表于2020年06月15日 19:45:48
直达本楼层的链接
沙发
显示全部楼层

cJON,挺好用的

点赞 评论 引用 举报

ttking

发帖: 363粉丝: 21

发消息 + 关注

发表于2020年06月20日 08:43:19
直达本楼层的链接
板凳
显示全部楼层

cjson确实很好用 方便

点赞 评论 引用 举报

我是卤蛋

发帖: 121粉丝: 287

发消息 + 关注

发表于2020年06月26日 11:05:37
直达本楼层的链接
地板
显示全部楼层

深度好文,持续学习~

点赞 评论 引用 举报

游客

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