STM32使用CJSON获取心知天气
文章目录1、cJSON库的使用1、程序配置2、新建json数据3、读取json数据2、onenet实战3、腾讯云实战4、阿里云实战本文是接着上一篇文章的后续来写,上一篇写的太长了后面太累了就没写完,决定就是新开一篇来继续把他写完。上一篇文章为: STM32使用esp01s上云,MQTT.fx调试1、cJSON库的使用1、程序配置建议可以看这篇博主讲的,我觉得讲的很好,这里我把他的内容变成我自己的来
本文是接着上一篇文章的后续来写,上一篇写的太长了后面太累了就没写完,决定就是新开一篇来继续把他写完。
上一篇文章为: STM32使用esp01s上云,MQTT.fx调试
1、程序配置
建议可以看这篇博主讲的,我觉得讲的很好,这里我把他的内容变成我自己的来用下,链接如下:
https://blog.csdn.net/weixin_45488643/article/details/107132066
我们使用的别人库来进行解析和生成json的,库文件地址 https://github.com/DaveGamble/cJSON
之后就可以配置串口了,这里最好是把工程的堆栈设置的大一点,可能会出现溢出的问题
新建工程将文件添加到我们工程目录下
2、新建json数据
下面就可以测试新建json数据和解析json数据了
新建数据,就是上面提到的那个test.c里面提供了我们需要的测试函数,这里我贴出源码,供测试使用
struct record
{
const char *precision;
double lat;
double lon;
const char *address;
const char *city;
const char *state;
const char *zip;
const char *country;
};
/* Create a bunch of objects as demonstration. */
static int print_preallocated(cJSON *root)
{
/* declarations */
char *out = NULL;
char *buf = NULL;
char *buf_fail = NULL;
size_t len = 0;
size_t len_fail = 0;
/* formatted print */
out = cJSON_Print(root);
/* create buffer to succeed */
/* the extra 5 bytes are because of inaccuracies when reserving memory */
len = strlen(out) + 5;
buf = (char*)malloc(len);
if (buf == NULL)
{
printf("Failed to allocate memory.\n");
exit(1);
}
/* create buffer to fail */
len_fail = strlen(out);
buf_fail = (char*)malloc(len_fail);
if (buf_fail == NULL)
{
printf("Failed to allocate memory.\n");
exit(1);
}
/* Print to buffer */
if (!cJSON_PrintPreallocated(root, buf, (int)len, 1)) {
printf("cJSON_PrintPreallocated failed!\n");
if (strcmp(out, buf) != 0) {
printf("cJSON_PrintPreallocated not the same as cJSON_Print!\n");
printf("cJSON_Print result:\n%s\n", out);
printf("cJSON_PrintPreallocated result:\n%s\n", buf);
}
free(out);
free(buf_fail);
free(buf);
return -1;
}
/* success */
printf("%s\n", buf);
/* force it to fail */
if (cJSON_PrintPreallocated(root, buf_fail, (int)len_fail, 1)) {
printf("cJSON_PrintPreallocated failed to show error with insufficient memory!\n");
printf("cJSON_Print result:\n%s\n", out);
printf("cJSON_PrintPreallocated result:\n%s\n", buf_fail);
free(out);
free(buf_fail);
free(buf);
return -1;
}
free(out);
free(buf_fail);
free(buf);
return 0;
}
static void create_objects(void)
{
/* declare a few. */
cJSON *root = NULL;
cJSON *fmt = NULL;
cJSON *img = NULL;
cJSON *thm = NULL;
cJSON *fld = NULL;
int i = 0;
/* Our "days of the week" array: */
const char *strings[7] =
{
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
};
/* Our matrix: */
int numbers[3][3] =
{
{0, -1, 0},
{1, 0, 0},
{0 ,0, 1}
};
/* Our "gallery" item: */
int ids[4] = { 116, 943, 234, 38793 };
/* Our array of "records": */
struct record fields[2] =
{
{
"zip",
37.7668,
-1.223959e+2,
"",
"SAN FRANCISCO",
"CA",
"94107",
"US"
},
{
"zip",
37.371991,
-1.22026e+2,
"",
"SUNNYVALE",
"CA",
"94085",
"US"
}
};
volatile double zero = 0.0;
/* Here we construct some JSON standards, from the JSON site. */
/* Our "Video" datatype: */
root = cJSON_CreateObject();
cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble"));
cJSON_AddItemToObject(root, "format", fmt = cJSON_CreateObject());
cJSON_AddStringToObject(fmt, "type", "rect");
cJSON_AddNumberToObject(fmt, "width", 1920);
cJSON_AddNumberToObject(fmt, "height", 1080);
cJSON_AddFalseToObject (fmt, "interlace");
cJSON_AddNumberToObject(fmt, "frame rate", 24);
/* Print to text */
if (print_preallocated(root) != 0) {
cJSON_Delete(root);
exit(EXIT_FAILURE);
}
cJSON_Delete(root);
/* Our "days of the week" array: */
root = cJSON_CreateStringArray(strings, 7);
if (print_preallocated(root) != 0) {
cJSON_Delete(root);
exit(EXIT_FAILURE);
}
cJSON_Delete(root);
/* Our matrix: */
root = cJSON_CreateArray();
for (i = 0; i < 3; i++)
{
cJSON_AddItemToArray(root, cJSON_CreateIntArray(numbers[i], 3));
}
/* cJSON_ReplaceItemInArray(root, 1, cJSON_CreateString("Replacement")); */
if (print_preallocated(root) != 0) {
cJSON_Delete(root);
exit(EXIT_FAILURE);
}
cJSON_Delete(root);
/* Our "gallery" item: */
root = cJSON_CreateObject();
cJSON_AddItemToObject(root, "Image", img = cJSON_CreateObject());
cJSON_AddNumberToObject(img, "Width", 800);
cJSON_AddNumberToObject(img, "Height", 600);
cJSON_AddStringToObject(img, "Title", "View from 15th Floor");
cJSON_AddItemToObject(img, "Thumbnail", thm = cJSON_CreateObject());
cJSON_AddStringToObject(thm, "Url", "http:/*www.example.com/image/481989943");
cJSON_AddNumberToObject(thm, "Height", 125);
cJSON_AddStringToObject(thm, "Width", "100");
cJSON_AddItemToObject(img, "IDs", cJSON_CreateIntArray(ids, 4));
if (print_preallocated(root) != 0) {
cJSON_Delete(root);
exit(EXIT_FAILURE);
}
cJSON_Delete(root);
/* Our array of "records": */
root = cJSON_CreateArray();
for (i = 0; i < 2; i++)
{
cJSON_AddItemToArray(root, fld = cJSON_CreateObject());
cJSON_AddStringToObject(fld, "precision", fields[i].precision);
cJSON_AddNumberToObject(fld, "Latitude", fields[i].lat);
cJSON_AddNumberToObject(fld, "Longitude", fields[i].lon);
cJSON_AddStringToObject(fld, "Address", fields[i].address);
cJSON_AddStringToObject(fld, "City", fields[i].city);
cJSON_AddStringToObject(fld, "State", fields[i].state);
cJSON_AddStringToObject(fld, "Zip", fields[i].zip);
cJSON_AddStringToObject(fld, "Country", fields[i].country);
}
/* cJSON_ReplaceItemInObject(cJSON_GetArrayItem(root, 1), "City", cJSON_CreateIntArray(ids, 4)); */
if (print_preallocated(root) != 0) {
cJSON_Delete(root);
exit(EXIT_FAILURE);
}
cJSON_Delete(root);
root = cJSON_CreateObject();
cJSON_AddNumberToObject(root, "number", 1.0 / zero);
if (print_preallocated(root) != 0) {
cJSON_Delete(root);
exit(EXIT_FAILURE);
}
cJSON_Delete(root);
}
将函数添加到初始话并打印数据,结果如下
将串口的数据复制到VSCODE中,进行格式化这样更方便我们查看数据
这里我们截取一段,可以看到就是比较标准的数据格式了
当然就是我们一般也用不到这么复杂啊,这多麻烦啊,因此我们这里在来做一个精简版的看看效果
源码如下
void Create_BJTime_JSON(void)
{
cJSON *root; cJSON *result;
root = cJSON_CreateObject();
result = cJSON_CreateObject();
cJSON_AddItemToObject(result, "姓名", cJSON_CreateString("水语茗言"));
cJSON_AddItemToObject(result, "时间", cJSON_CreateString("2020/03/09"));
cJSON_AddItemToObject(result, "place", cJSON_CreateString("安徽合肥"));
cJSON_AddItemToObject(result, "星期", cJSON_CreateString("周五"));
cJSON_AddItemToObject(result, "xxx", cJSON_CreateString("xxx1"));
cJSON_AddItemToObject(result, "xxx2", cJSON_CreateString("xxx3"));
cJSON_AddItemToObject(result, "xxx3", cJSON_CreateString("xxx4"));
cJSON_AddItemToObject(root, "status", cJSON_CreateString("success"));
cJSON_AddItemToObject(root, "result", result);
cJSON_AddStringToObject(root, "wiki", "https://blog.csdn.net/m0_51220742?spm=1010.2135.3001.5343");
printf("\n%s\r\n", cJSON_Print(root)); cJSON_Delete(root);
}
将程序下载到开发板,效果如下
3、读取json数据
读取相对简单点,只要我们稍微进行设置即可
这里我用到了空闲中断+DMA的方式来处理数据,关于处理方法,在我其他的博文中有相关的介绍,这里不作介绍
这里我准备了一段数据模版
源代码如下
{
"state": {
"desired": {
"hz": 5,
"temp_comp": 0.1
}
},
"metadata": {
"reported": {
"hz": {
"timestamp": 1559720433
},
"temp_comp": {
"timestamp": 1559720433
}
},
"desired": {
"hz": {
"timestamp": 1559720433
},
"temp_comp": {
"timestamp": 1559720433
}
}
},
"timestamp": 1559720433,
"version": 3
}
将程序下载到开发板,效果如下所示,可以看到数据已经成功的打印出来了
这里还有一点很重要的就是每次用完之后就要吧这个清理掉,不然程序跑一段时间就会莫名其妙出错,据说是动态内存产生的问题
4、解析心知天气
很多创客项目都会一些桌面天气项目之类的,这个目前资料也比较齐全,使用也很方便,就是去百度搜索然后注册个账号就行了
这里我声明下,看到我博客的请不要用我的私钥,因为一定时间限制使用次数的,虽然免费但不是高频使用的
获取私钥的方法如下所示
使用API的方法如下。官方提供了说明文档 https://seniverse.yuque.com/books/share/e52aa43f-8fe9-4ffa-860d-96c0f3cf1c49/nyiu3t
简单说就是把下面的APIke替换为你自己的然后城市也变为自己的,城市只要是名字改用英文名即可,比如合肥 -> hefei
https://api.seniverse.com/v3/weather/now.json?key=your_api_key&location=beijing&language=zh-Hans&unit=c
之后可以测试下输入,最方便的就是浏览器直接输入
将返回的数据放到VSCODE里面解析就这样了
5、ESP01S获取数据
那么下面我们用ESP01S来连上获取设备试试
首先第一步还是测试AT是否能用
设置ESP01S的模式(1是当成手机用,2是路由器,3是两种兼容)
连WIFI
连上心知天气
开启透传:
发送数据:
向网站发起请求,就是GET加上我们前面说的那个申请的链接,可以看到数据接收OK的
6、STM32获取数据
前面的一直用的都是ESP01S的模块,这次换个模块试试,好家伙,不换不知道,一换一堆坑,所以使用的一定要注意了,本次我使用正点原子的esp8266wifi模块如下
常见引脚连接如下所示:
VCC | 电源(3.3V 5V) |
---|---|
GND | 电源地 |
TXD | 模块串口发送脚(TTL电平,不能直接接RS232电平!),可接单片机的RXD |
RXD | 模块串口接收脚(TTL电平,不能直接接RS232电平!),可接单片机的TXD |
RST | 复位(低电平有效) |
IO0 | 用于进入固件烧写模式,低电平是烧写模式,高电平是运行模式(默认状态) |
这里提个醒,一定要注意,模块上电是蓝灯常亮的,如果你的模块不亮就给他接上5v,不然固件更新不过去,会一直抱错的!
这里固件更新的页面设置如下
按照习惯还是先擦除后更新,上面的两个bin文件在官方提供的资料包里面!
更新完成之后拔掉,重新上电(这里要注意啊,一定要重新上电),然后将IO2恢复为悬空状态,这个时候我们在测试AT指令就OK了!
好,那么我们下面就可以来解析天气了,首相还是一样的就是把我们的这个串口打开并开启DMA接收
关于串口DMA的这一部分可以看我之前的文章:串口通信中一些常用的小工具
下面可以根据前面AT指令设置的进行调节:
下面是一个要注意的地方
下面我们就可以使用串口来查看数据了
下面调用上面讲的进行解析:
打印数据如下所示,可以看到是完全ok的!
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)