ESP8266-使用ESP8266 NONOS SDK的JSON API
来源:互联网 发布:剑3萝莉捏脸数据下载 编辑:程序博客网 时间:2024/04/29 07:14
2016年9月30日更新:本人移植了cJSON到ESP8266的NONOS SDK,详情可以查看这篇文章:
http://blog.csdn.net/yannanxiu/article/details/52713746
一、概述
这篇文章是讲解如何用ESP8266官方提供的Json接口处理数据。
首先要在esp_iot_sdk/example/IoT_Demo示例目录下找到user_json.c和user_json.h,把这两个文件包含进自己的工程。
查看json.h文件,里面有一下宏定义
#define JSON_TYPE_ARRAY '['#define JSON_TYPE_OBJECT '{'#define JSON_TYPE_PAIR ':'#define JSON_TYPE_PAIR_NAME 'N' /* for N:V pairs */#define JSON_TYPE_STRING '"'#define JSON_TYPE_INT 'I'#define JSON_TYPE_NUMBER '0'#define JSON_TYPE_ERROR 0
后面的例程都是用此宏定义来判断Json的键值的数据类型。
二、生成一个Json
下面给出生成Json树的示例,生成的JSON树get_h内容如下:"hi":{"hello":"world"}
/***************************************************/LOCAL int ICACHE_FLASH_ATTRhello_get(struct jsontree_context *js_ctx){ const char *path = jsontree_path_name(js_ctx, js_ctx->depth - 1); char string[32]; if (os_strncmp(path, "hello", 5) == 0) { os_sprintf(string, "world"); } jsontree_write_string(js_ctx, string); return 0;}LOCAL struct jsontree_callback hello_callback = JSONTREE_CALLBACK(hello_get, NULL);JSONTREE_OBJECT(get_hello, JSONTREE_PAIR("hello", &hello_callback));JSONTREE_OBJECT(get_h, JSONTREE_PAIR("hi", &get_hello));
其中宏定义JSONTREE_OBJECT是生成一个JSON数的对象,第一个参数是该对象的名称(get_h),JSONTREE_PAIR是生成一个键值对的宏。
JSONTREE_CALLBACL是生成一个回调指针的宏,该宏有两个参数,第一个参数是设置读取JSON树的值的函数,这里为hello_get函数,第二个参数是设置写入JSON树的值的函数,这里没有用到,为NULL。
hello_get是生成JSON树的值的函数。其中用os_strncnp进行Json键的判断,如果键为hello,则对该键写入"world"值。
这里生成的JSON是:"hi":{"hello","world"},hi是用来调用后面Json数据的:
#define BUF_LENTH 64LOCAL char buf[BUF_LENTH];json_ws_send((struct jsontree_value *)&get_h, "hi", buf);os_printf("%s\n",buf);
使用json_ws_send函数可以把hi后面的数据写入buf,json_ws_send函数在IoT_demo例程中的user_json.c文件里。
最后打印结果是:
{
"hello":"world"
}
三、生成一个温湿度Json数据
下面是一个生成温湿度的例程:
/********************DHT11***********************/LOCAL int ICACHE_FLASH_ATTRdht11_get(struct jsontree_context *js_ctx){ const char *path = jsontree_path_name(js_ctx, js_ctx->depth - 1); char string[32]; if (os_strncmp(path, "temp", 4) == 0) { //os_sprintf(string, "%d",temperture); os_sprintf(string,"25"); } else if(os_strncmp(path, "hum", 3) == 0){ //os_sprintf(string, "%d",hum); os_sprintf(string,"40"); } jsontree_write_string(js_ctx, string); return 0;}LOCAL struct jsontree_callback dht11_callback = JSONTREE_CALLBACK(dht11_get, NULL);JSONTREE_OBJECT(get_dht11, JSONTREE_PAIR("temp", &dht11_callback),JSONTREE_PAIR("hum", &dht11_callback));JSONTREE_OBJECT(DHT11JSON, JSONTREE_PAIR("dht11", &get_dht11));//返回DHT11数据的json格式char* ICACHE_FLASH_ATTRget_dht11_json(void){static char dht11_buf[64];os_memset(dht11_buf,0,64);//清空json_ws_send((struct jsontree_value *)&DHT11JSON, "dht11", dht11_buf);return dht11_buf;}
os_printf(get_dht11_json());
就可以看到串口打印出
{
"temp":"25",
"hum":"40"
}
四、一个完整的生成Json数据示例
下面是一个完整的生成Json数据的示例,可以生成字符串、整型值、数组、Json对象的Value。
Json数据的生成最重要的是理解函数回调机制,看代码要从下往上看,如果看官接触过异步回调机制的代码,阅读起来可能会有一种相似的感觉。
#include "user_json.h"#include "ets_sys.h"#include "os_type.h"#include "osapi.h"#include "mem.h"#include "user_interface.h"LOCAL int ICACHE_FLASH_ATTRjsonTree_get(struct jsontree_context *js_ctx){ const char *path = jsontree_path_name(js_ctx, js_ctx->depth - 1); //生成"String":"data" if (os_strncmp(path, "String", os_strlen("String")) == 0) { jsontree_write_string(js_ctx, "data"); //生成"Integer":1 } else if (os_strncmp(path, "Integer", os_strlen("Integer")) == 0) { jsontree_write_int(js_ctx, 1); //生成"Array":[0,1,2] } else if (os_strncmp(path, "Array", os_strlen("Array")) == 0) { int array[3] = {0,1,2}; jsontree_write_atom(js_ctx, "["); jsontree_write_int_array(js_ctx, array, 3); jsontree_write_atom(js_ctx, "]"); } return 0;}LOCAL int ICACHE_FLASH_ATTRjsonArray_get(struct jsontree_context *js_ctx){ const char *path = jsontree_path_name(js_ctx, js_ctx->depth - 1); if (os_strncmp(path, "K1", os_strlen("K2")) == 0) { jsontree_write_string(js_ctx, "D1"); } else if (os_strncmp(path, "K2", os_strlen("K2")) == 0) { jsontree_write_string(js_ctx, "D2"); } else if (os_strncmp(path, "K3", os_strlen("K3")) == 0) { jsontree_write_string(js_ctx, "D3"); } return 0;}//初始化一个Json数据回调函数//JSONTREE_CALLBACK第一个参数为生成Json数据的函数指针,第二个为获取Json数据的函数指针LOCAL struct jsontree_callback jsonArrayCallback = JSONTREE_CALLBACK(jsonArray_get, NULL);JSONTREE_OBJECT(jsonArrayData, JSONTREE_PAIR("K1", &jsonArrayCallback), JSONTREE_PAIR("K2", &jsonArrayCallback),JSONTREE_PAIR("K3", &jsonArrayCallback));JSONTREE_ARRAY(jsonArray, JSONTREE_PAIR_ARRAY(&jsonArrayData), JSONTREE_PAIR_ARRAY(&jsonArrayData), JSONTREE_PAIR_ARRAY(&jsonArrayData));LOCAL struct jsontree_callback jsonCallback = JSONTREE_CALLBACK(jsonTree_get, NULL);JSONTREE_OBJECT(jsonObject, JSONTREE_PAIR("String", &jsonCallback), JSONTREE_PAIR("Integer", &jsonCallback), JSONTREE_PAIR("JsonArray", &jsonArray));JSONTREE_OBJECT(jsonTestTrees, JSONTREE_PAIR("String", &jsonCallback), //生成一个String键,并设置一个回调函数JSONTREE_PAIR("Integer", &jsonCallback), //生成一个Integer键,并设置一个回调函数JSONTREE_PAIR("Array", &jsonCallback), //生成一个Array键,并设置一个回调函数JSONTREE_PAIR("JsonObject", &jsonObject)); //生成一个jsonObject键,并设置一个Json对象JSONTREE_OBJECT(jsonTestTree, JSONTREE_PAIR("jsonTest", &jsonTestTrees));#define LENGTH 512char* getJsonTree(void){ static char jsonbuf[LENGTH]; os_memset(jsonbuf, 0, LENGTH); //初始化字符串json_ws_send((struct jsontree_value *)&jsonTestTree, "jsonTest", jsonbuf);//os_printf("%s\n", jsonbuf);return jsonbuf;}
该代码会生成如下Json数据:
{ "String": "data", "Integer": 1, "Array": [ 0, 1, 2 ], "JsonObject": { "String": "data", "Integer": 1, "JsonArray": [ { "K1": "D1", "K2": "D2", "K3": "D3" }, { "K1": "D1", "K2": "D2", "K3": "D3" }, { "K1": "D1", "K2": "D2", "K3": "D3" } ] }}
五、从Json提取数据
如果网络发送一串JSON数据给ESP8266,如何使用该接口获取JSON的键值呢?下面给出示例代码,这里使用的数据是上面生成的数据。
其中第二次的Json对象数据获取很麻烦,所以传给8266的Json尽量用一层,如果是数组里面再有Json对象,那么就更麻烦了,具体请看代码。
LOCAL int ICACHE_FLASH_ATTRjsonTree_set(struct jsontree_context *js_ctx, struct jsonparse_state *parser){ int type; while ((type = jsonparse_next(parser)) != 0) { //如果是KEY类型 if (type == JSON_TYPE_PAIR_NAME) { char buffer[64]; os_bzero(buffer, 64); if (jsonparse_strcmp_value(parser, "String") == 0) { jsonparse_next(parser);//返回的是冒号字符 type = jsonparse_next(parser);//返回的是双引号字符 os_printf("String Value type = %c\n", type);// = " //如果Value是字符串类型,则读取数据到buffer if (JSON_TYPE_STRING == type){//#define JSON_TYPE_STRING '"' jsonparse_copy_value(parser, buffer, sizeof(buffer)); os_printf("String Value = %s\n", buffer); } } else if (jsonparse_strcmp_value(parser, "Integer") == 0) { jsonparse_next(parser); type = jsonparse_next(parser); os_printf("Integer Value type = %c\n", type);// = 0 //如果Value是数值类型 if(JSON_TYPE_NUMBER == type){//#define JSON_TYPE_NUMBER '0' //jsonparse_copy_value(parser, buffer, sizeof(buffer)); int num = 0; num = jsonparse_get_value_as_int(parser); os_printf("Integer Value = %d\n", num);// = 1 } } else if (jsonparse_strcmp_value(parser, "Array") == 0) { jsonparse_next(parser);//跳过冒号 type = jsonparse_next(parser); os_printf("Array Value type = %c\n", type);// = [ //如果Value是数组类型 if(JSON_TYPE_ARRAY == type){//#define JSON_TYPE_ARRAY '[' //jsonparse_copy_value(parser, buffer, sizeof(buffer)); int length = jsonparse_get_len(parser); os_printf("Array Length = %d\n", length);//= 5, 数据是[0,1,2],可能把逗号也算在内 int i; int num = 100; //循环读取数组的数据 for(i=0; i<length; i++){ type = jsonparse_next(parser); // 如果是逗号,则直接打印, 如果是数值则打印0 os_printf("Array[%d] type = %c ", i, type); //如果是数值类型,则转换成int并打印出来 if(JSON_TYPE_NUMBER==type){ num = jsonparse_get_value_as_int(parser); os_printf("Array[%d] = %d\n", i, num); } //后面可以添加else if判断是否是其他类型 //比如 else if(JSON_TYPE_OBJECT==type),判断是否是Json对象 else{ os_printf("\n"); } } } }#if 1 else if (jsonparse_strcmp_value(parser, "JsonObject") == 0) { jsonparse_next(parser);//跳过冒号 type = jsonparse_next(parser); os_printf("JsonObject Value type = %c\n", type);// = { if(JSON_TYPE_OBJECT == type){//#define JSON_TYPE_OBJECT '{' int length = jsonparse_get_len(parser); os_printf("JsonObject Length = %d\n", length); //char temp[128] = {0}; //jsonparse_copy_value(parser, temp, 128); //os_printf("JsonObject Value = %s\n", temp); //循环读取数据 int i = 0; //for(i=0; i<length; i++){ while(type != '}'){ i++; type = jsonparse_next(parser); os_printf("JsonObject[%d] type = %c", i, type); os_printf("\n"); //os_memset(temp, 0, 128); //jsonparse_copy_value(parser, temp, 128); //os_printf("JsonObject Value = %s\n", temp); //读取第二层的Json对象的数据 jsonObject_set(parser); } } }#endif } } return 0;}LOCAL int ICACHE_FLASH_ATTRjsonObject_set(struct jsonparse_state *parser){int type = jsonparse_get_type(parser);int vtype = parser->vtype;//os_printf("json Object type=%c, vtype=%c\n", type, vtype);char buffer[64];os_bzero(buffer, 64);//如果是KEY类型if (vtype == JSON_TYPE_PAIR_NAME) { if (jsonparse_strcmp_value(parser, "String") == 0) {jsonparse_next(parser);//返回的是冒号字符type = jsonparse_next(parser);//返回的是双引号字符//os_printf("jsonObject String Value type = %c\n", type);// = "//如果Value是字符串类型,则读取数据到bufferif (JSON_TYPE_STRING == type){//#define JSON_TYPE_STRING '"'jsonparse_copy_value(parser, buffer, sizeof(buffer));os_printf("jsonObject String Value = %s\n", buffer);}} else if (jsonparse_strcmp_value(parser, "Integer") == 0) {jsonparse_next(parser);type = jsonparse_next(parser);//os_printf("jsonObject Integer Value type = %c\n", type);// = 0//如果Value是数值类型if(JSON_TYPE_NUMBER == type){//#define JSON_TYPE_NUMBER '0'//jsonparse_copy_value(parser, buffer, sizeof(buffer));int num = 0;num = jsonparse_get_value_as_int(parser);os_printf("jsonObject Integer Value = %d\n", num);// = 1}} else if (jsonparse_strcmp_value(parser, "JsonArray") == 0) {jsonparse_next(parser);type = jsonparse_next(parser);//os_printf("jsonObject Integer Value type = %c\n", type);// = 0//如果Value是数值类型if(JSON_TYPE_ARRAY == type){//jsonparse_copy_value(parser, buffer, sizeof(buffer));//os_printf("buffer = %s\n", buffer); int length = jsonparse_get_len(parser); os_printf("JsonArray Length = %d\n", length);//读取出来的长度不准确 //循环读取Json对象数据int i = 0;//for(i=0; i<length; i++){while(type != ']'){i++;//用']'判断是否达到数组末尾type = jsonparse_next(parser);os_printf("JsonArray[%d] type = %c", i, type);os_printf("\n");//如果是KEY类型if (type == JSON_TYPE_PAIR_NAME) { if (jsonparse_strcmp_value(parser, "K1") == 0) {jsonparse_next(parser);//返回的是冒号字符type = jsonparse_next(parser);//返回的是双引号字符//os_printf("K1 Value type = %c\n", type);// = "//如果Value是字符串类型,则读取数据到bufferif (JSON_TYPE_STRING == type){//#define JSON_TYPE_STRING '"'os_bzero(buffer, 64);jsonparse_copy_value(parser, buffer, sizeof(buffer));os_printf("K1 = %s\n", buffer);}} else if(jsonparse_strcmp_value(parser, "K2") == 0){jsonparse_next(parser);//返回的是冒号字符type = jsonparse_next(parser);//返回的是双引号字符//如果Value是字符串类型,则读取数据到bufferif (JSON_TYPE_STRING == type){//#define JSON_TYPE_STRING '"'os_bzero(buffer, 64);jsonparse_copy_value(parser, buffer, sizeof(buffer));os_printf("K2 = %s\n", buffer);}} else if(jsonparse_strcmp_value(parser, "K3") == 0){jsonparse_next(parser);//返回的是冒号字符type = jsonparse_next(parser);//返回的是双引号字符//如果Value是字符串类型,则读取数据到bufferif (JSON_TYPE_STRING == type){//#define JSON_TYPE_STRING '"'os_bzero(buffer, 64);jsonparse_copy_value(parser, buffer, sizeof(buffer));os_printf("K3 = %s\n", buffer);}}}}}}}}LOCAL int ICACHE_FLASH_ATTRjsonArray_set(struct jsontree_context *js_ctx, struct jsonparse_state *parser){int type;while ((type = jsonparse_next(parser)) == 0) {//如果是KEY类型if (type == JSON_TYPE_PAIR_NAME) {char buffer[64];os_bzero(buffer, 64);if (jsonparse_strcmp_value(parser, "K1") == 0) { if (JSON_TYPE_STRING == type){//#define JSON_TYPE_STRING '"' jsonparse_copy_value(parser, buffer, sizeof(buffer)); os_printf("K1 Value = %s\n", buffer); }} else if (jsonparse_strcmp_value(parser, "K2")==0) { if (JSON_TYPE_STRING == type){//#define JSON_TYPE_STRING '"' jsonparse_copy_value(parser, buffer, sizeof(buffer)); os_printf("K2 Value = %s\n", buffer); }} else if (jsonparse_strcmp_value(parser, "K3")==0) { if (JSON_TYPE_STRING == type){//#define JSON_TYPE_STRING '"' jsonparse_copy_value(parser, buffer, sizeof(buffer)); os_printf("K3 Value = %s\n", buffer); }}}} return 0;}void ICACHE_FLASH_ATTRsetJsonTree(char *json){ struct jsontree_context js; jsontree_setup(&js, (struct jsontree_value *)&jsonTestTree, json_putchar); json_parse(&js, json);}void ICACHE_FLASH_ATTRsetJsonObject(char *json){ struct jsontree_context js; jsontree_setup(&js, (struct jsontree_value *)&jsonObject, json_putchar); json_parse(&js, json);}
最后要修改一下这条语句,给jsonCallback第二个参数添加jsonTree_set。
LOCAL struct jsontree_callback jsonCallback = JSONTREE_CALLBACK(jsonTree_get, jsonTree_set);
打印:
String Value type = "
String Value = data
Integer Value type = 0
Integer Value = 1
Array Value type = [
Array Length = 5
Array[0] type = 0 Array[0] = 0
Array[1] type = ,
Array[2] type = 0 Array[2] = 1
Array[3] type = ,
Array[4] type = 0 Array[4] = 2
JsonObject Value type = {
JsonObject Length = 10
JsonObject[1] type = N
jsonObject String Value = data
JsonObject[2] type = ,
JsonObject[3] type = N
jsonObject Integer Value = 1
JsonObject[4] type = ,
JsonObject[5] type = N
JsonArray Length = 9
JsonArray[1] type = {
JsonArray[2] type = N
K1 = D1
JsonArray[3] type = ,
JsonArray[4] type = N
K2 = D2
JsonArray[5] type = ,
JsonArray[6] type = N
K3 = D3
JsonArray[7] type = }
JsonArray[8] type = ,
JsonArray[9] type = {
JsonArray[10] type = N
K1 = D1
JsonArray[11] type = ,
JsonArray[12] type = N
K2 = D2
JsonArray[13] type = ,
JsonArray[14] type = N
K3 = D3
JsonArray[15] type = }
JsonArray[16] type = ,
JsonArray[17] type = {
JsonArray[18] type = N
K1 = D1
JsonArray[19] type = ,
JsonArray[20] type = N
K2 = D2
JsonArray[21] type = ,
JsonArray[22] type = N
K3 = D3
JsonArray[23] type = }
JsonArray[24] type = ]
JsonObject[6] type = }
六、代码下载
如果想要示例代码,可以从这里下载:http://download.csdn.net/detail/u012163234/9638834
- ESP8266-使用ESP8266 NONOS SDK的JSON API
- 【ESP8266】使用ESP8266 NONOS SDK的JSON API
- ESP8266-使用ESP8266 NONOS SDK的driver/key API
- 【ESP8266】ESP8266 sniffer使用示例(基于NONOS SDK)
- ESP8266 NONOS SDK 调度与优先级
- 【ESP8266】NONOS SDK开发,发送HTTP请求
- 4. ESP8266固件的编译(NONOS SDK固件 AT固件)
- 【ESP8266】NONOS SDK开发,串口发送、接收与中断
- 【ESP8266】NONOS SDK开发, smartconfig/AirKiss与flash读写
- 【ESP8266】NONOS SDK开发,串口发送、接收与中断
- esp8266 SDK使用注意事项
- ESP8266-SDK中I2C的使用
- ESP8266-SDK的外部中断
- ESP8266-SDK的硬件定时器
- ESP8266的SDK开发入门教程
- ESP8266-SDK的硬件定时器
- ESP8266 NONOS SDK2.0 自定义库编译
- <WIFI>ESP8266定时器的使用(基于安信可SDK)
- SSH之Struts2框架--简单登陆模拟
- Oracle Study之--Oracle 11gR2构建RAC之hosts文件故障
- push本地代码到github出错
- android 安装软件进程的框
- vim教程---version1.7
- ESP8266-使用ESP8266 NONOS SDK的JSON API
- Shell脚本中的:>/dev/null 2>&1 的作用
- js中的立即执行函数
- 框架EventBus soeazy
- Markdown书写代码
- textview显示更多的
- Java读取文件目录和文件,并且按照文件层次输出文件名和目录名。
- struts中的验证框架的使用
- KMP算法