零、写在前面
今天看论坛有人问活动送的板子出了点灯不知道还有没有其它玩法。所以我在这里分享一下我的一些理解,对于大佬可能是很基础的东西,但对新人也能停供一些思路,有不对的地方大佬可以指正,新人可以交流学习。
一、处理JSON数据-CJson
首先不管什么单片机能访问互联网就大有可玩。我们要知道数据从哪来,拿到的是什么数据,拿到后才好做相应的处理。例如如果是请求API类的数据接口一般返回的是JSON,单片机上常用的处理JSON的库是CJSON。项目地址:https://github.com/DaveGamble/cJSON/tree/master 。对于任何一款单片机在你板载空间够的情况下可以只需要导入CJson.h和CJson.c到你的项目,做好正确文件引用,就可以调用它相关的方法根据返回的json进行解析。
CJson常用的方法如下(内容来自ChatGPT)
- 创建JSON对象:
○ cJSON_CreateObject():创建一个JSON对象,用于存储键值对。
- 添加键值对到JSON对象:
○ cJSON_AddItemToObject(object, key, value):向JSON对象中添加一个键值对,其中object是目标JSON对象,key是键名,value是对应的值。
- 创建JSON数组:
○ cJSON_CreateArray():创建一个JSON数组,用于存储多个值。
- 向JSON数组中添加元素:
○ cJSON_AddItemToArray(array, value):向JSON数组中添加一个元素,其中array是目标JSON数组,value是要添加的元素。
- 创建JSON字符串:
○ cJSON_Print(json):将JSON结构体转换为JSON格式的字符串。
- 解析JSON字符串:
○ cJSON_Parse(json_string):将JSON格式的字符串解析为JSON结构体。
- 获取JSON对象的值:
○ cJSON_GetObjectItem(object, key):获取JSON对象中指定键名的值。
- 获取JSON数组的元素:
○ cJSON_GetArrayItem(array, index):获取JSON数组中指定索引位置的元素。
- 获取JSON值的类型:
○ cJSON_typeof(item):获取JSON值的类型,例如对象、数组、字符串、数字等。
- 获取JSON字符串的值:
○ cJSON_GetStringValue(item):获取JSON字符串值的指针。
- 获取JSON数字的值:
○ cJSON_GetNumberValue(item):获取JSON数字值。
- 释放JSON结构体:
○ cJSON_Delete(item):释放一个JSON结构体及其所有子元素的内存。
当然既然可以处理天气的API也能同理处理其它开放的API,在网上找到自己想获取的数据对应的API接口进行处理展示即可变成不同的项目,不仅仅是一个天气时钟。类似的开放接口网站有:
https://www.juhe.cn/docs
当然如果你有简单的后端的开发能力你也可以自己搭建API上传下载保存一些你用板子采集到的数据。
二、处理HTML/XML数据-tinyxml2
当然有些时候你可能需要的不是JSON这样的数据,而是访问一个网页,列如对于一些简单的博客网站,我们拿到的是html文本,html其实和xml类似也是一个个节点,利用另外一个库tinyxml2就能对HTML进行解析,我们可以拿文本,拿图片地址拿链接,对网页进行一个类似爬虫的处理。tinyxml2的仓库地址在:https://github.com/leethomason/tinyxml2 值得注意的是它是一个C++库,它可能不适用所有的单片机。但是我把它用在ESP32上是没有问题的,对于aithinker_Ai-M6X系列理论上我觉得是一致,因为我手上没这块板子,如果有人手上有这块板子的有兴趣试了可行的希望评论分享。当然我的初衷并不是做爬虫而是做一个EPUB电子书,原理一致只是数据从哪来而已,EPUB的最终需要解析HTML文件拿到电子书内容,EPUB还需要先解压再解析对应的目录文件得到每章节的HTML文件然后解析。后续的电子书相关的如果有机会再做分享。这是我解析html拿到电子书内容的部分代码,仅供参考
tinyxml2::XMLDocument document;
document.Parse(xml);
tinyxml2::XMLElement* root= document.RootElement();
// 定位 <p> 节点
tinyxml2::XMLElement* pElement = root->FirstChildElement("body")->FirstChildElement("div")->FirstChildElement("p");;
while (pElement) {
// 获取 <p> 节点的内容
const char* pContent = pElement->GetText();
if (pContent) {
// 处理 <p> 节点的内容
Serial.println(pContent);
}
// 移动到下一个 <p> 节点
pElement = pElement->NextSiblingElement("p");
}
|