写点什么

ESP8266 获取天气预报信息,并使用 CJSON 解析天气预报数据

作者:DS小龙哥
  • 2023-06-08
    重庆
  • 本文字数:3499 字

    阅读完需:约 11 分钟

一、实现功能

当前文章介绍如何使用 ESP8266 和 STM32 微控制器,搭配 OLED 显示屏,制作一个能够实时显示天气预报的智能设备。将使用心知天气 API 来获取天气数据,并使用 MQTT 协议将数据传递给 STM32 控制器,最终在 OLED 显示屏上显示。


心知天气是一家专业的气象数据服务提供商,致力于为全球用户提供高质量、定制化的气象数据服务。其主要产品包括天气 API、空气质量 API、灾害预警 API 等。用户可以通过心知天气的 API 接口,获取准确、实时的天气数据,从而为各种应用场景提供支持,例如智能家居、出行、电商等。心知天气的数据覆盖全球 200 多个国家和地区,每日处理超过 10 亿次 API 请求,是业内领先的气象数据服务提供商之一。


二、硬件准备

1. ESP8266 模块

ESP8266 是一款 WiFi 模块,它具有强大的网络连接功能,可以轻松地连接到互联网。将使用 ESP8266 模块来获取天气数据,并将其发送给 STM32 控制器。具体来说,我们将使用正点原子 ATK-ESP8266 模块,这是一款集成 ESP8266 芯片的小板子。

2. STM32 微控制器

STM32 是一款强大的 32 位微控制器,具有多种接口和功能。将使用 STM32F103C8T6 控制器,这是一款非常流行的型号,易于获得且价格较为合理。

3. OLED 显示屏

OLED 是一种非常流行的显示技术,具有高对比度、低功耗、快速响应等优点。将使用 0.96 英寸 128x64 像素的 OLED 显示屏。

三、CJSON 解析天气预报数据

3.1 接口返回的数据

{  "results": [    {      "location": {        "id": "WTEMH46Z5N09",        "name": "合肥",        "country": "CN",        "path": "合肥,合肥,安徽,中国",        "timezone": "Asia/Shanghai",        "timezone_offset": "+08:00"      },      "now": {        "text": "阴",        "code": "9",        "temperature": "12",        "feels_like": "18",        "pressure": "1000",        "humidity": "89",        "visibility": "12.0",        "wind_direction": "西南",        "wind_direction_degree": "245",        "wind_speed": "19.0",        "wind_scale": "3",        "clouds": "85",        "dew_point": ""      },      "last_update": "2023-04-04T14:20:13+08:00"    }  ]}
复制代码

3.2 CJSON 是什么

CJSON 是一款轻量级的 C 语言 JSON 解析器,其全称是“cJSON”,由 Dave Gamble 编写。它简单易用,可嵌入到 C 应用程序中,既支持 JSON 字符串的解析,也支持 JSON 对象的创建及操作。CJSON 不依赖于任何其他的库或组件,使用它只需要引入其头文件即可。


CJSON 的使用方式相对来说比较简单,需要进行以下几个步骤:


1. 在应用程序中包含cJSON的头文件:#include "cJSON.h"。2. 调用cJSON_Parse函数,将JSON字符串转换为CJSON对象。3. 使用cJSON提供的API函数对CJSON对象进行操作,包括读取、修改、删除、添加等。4. 在程序结束时,记得释放cJSON对象的内存空间,避免内存泄漏。
复制代码


CJSON 的解析速度相对较快,占用的内存开销也比较小,因此非常适用于资源有限的嵌入式系统中使用。

3.3 解析数据

使用 CJSON 解析上述 JSON 数据非常简单,只需要按照以下步骤操作:


  1. 引入 CJSON 库文件


#include <cJSON.h>
复制代码


  1. 解析 JSON 数据并创建 cJSON 对象


char* json_data = "{\"results\":[{\"location\":{\"id\":\"WTEMH46Z5N09\",\"name\":\"合肥\",\"country\":\"CN\",\"path\":\"合肥,合肥,安徽,中国\",\"timezone\":\"Asia/Shanghai\",\"timezone_offset\":\"+08:00\"},\"now\":{\"text\":\"阴\",\"code\":\"9\",\"temperature\":\"12\",\"feels_like\":\"18\",\"pressure\":\"1000\",\"humidity\":\"89\",\"visibility\":\"12.0\",\"wind_direction\":\"西南\",\"wind_direction_degree\":\"245\",\"wind_speed\":\"19.0\",\"wind_scale\":\"3\",\"clouds\":\"85\",\"dew_point\":\"\"},\"last_update\":\"2023-04-04T14:20:13+08:00\"}]}";cJSON* root = cJSON_Parse(json_data);
复制代码


在这个代码片段中,首先定义了一个字符串类型的变量json_data,用于存储上述 JSON 数据。然后,调用cJSON_Parse()函数来解析 JSON 数据,并将解析结果保存在root指针所指向的 cJSON 对象中。


  1. 从 cJSON 对象中提取数据


cJSON* location = cJSON_GetObjectItem(root, "location");char* city = cJSON_GetObjectItem(location, "name")->valuestring;cJSON* now = cJSON_GetObjectItem(root, "now");int temperature = cJSON_GetObjectItem(now, "temperature")->valueint;char* text = cJSON_GetObjectItem(now, "text")->valuestring;
复制代码


在这个代码片段中,使用cJSON_GetObjectItem()函数从root指针所指向的 cJSON 对象中提取一个名为location的 JSON 对象,并从该 JSON 对象中获取名为name的字符串类型变量。类似地,也可以从root指针所指向的 cJSON 对象中提取名为now的 JSON 对象,并从该 JSON 对象中获取名为temperaturetext的整型和字符串类型变量。


  1. 释放 cJSON 对象


cJSON_Delete(root);
复制代码


最后,需要释放之前创建的 cJSON 对象,以释放内存空间。


完整的代码示例如下:


#include <cJSON.h>#include <stdio.h>
int main() { char* json_data = "{\"results\":[{\"location\":{\"id\":\"WTEMH46Z5N09\",\"name\":\"合肥\",\"country\":\"CN\",\"path\":\"合肥,合肥,安徽,中国\",\"timezone\":\"Asia/Shanghai\",\"timezone_offset\":\"+08:00\"},\"now\":{\"text\":\"阴\",\"code\":\"9\",\"temperature\":\"12\",\"feels_like\":\"18\",\"pressure\":\"1000\",\"humidity\":\"89\",\"visibility\":\"12.0\",\"wind_direction\":\"西南\",\"wind_direction_degree\":\"245\",\"wind_speed\":\"19.0\",\"wind_scale\":\"3\",\"clouds\":\"85\",\"dew_point\":\"\"},\"last_update\":\"2023-04-04T14:20:13+08:00\"}]}"; cJSON* root = cJSON_Parse(json_data);
cJSON* location = cJSON_GetObjectItem(root, "location"); char* city = cJSON_GetObjectItem(location, "name")->valuestring; cJSON* now = cJSON_GetObjectItem(root, "now"); int temperature = cJSON_GetObjectItem(now, "temperature")->valueint; char* text = cJSON_GetObjectItem(now, "text")->valuestring;
printf("City: %s\n", city); printf("Temperature: %d\n", temperature); printf("Weather: %s\n", text);
cJSON_Delete(root);
return 0;}
复制代码


在这个代码示例中,使用了cJSON_Parse()cJSON_GetObjectItem()cJSON_Delete()等函数来解析和处理 JSON 数据。

3.4 获取数据

下面是 ESP8266 访问 HTTP 接口请求的代码:


#include <SoftwareSerial.h>
// 定义ESP8266串口对象SoftwareSerial esp8266(PA10, PA9); // RX, TX
void setup() { Serial.begin(9600);
// 初始化ESP8266串口通信波特率为9600 esp8266.begin(9600);
// 发送AT指令测试ESP8266是否正常工作 esp8266.println("AT"); delay(500); if (esp8266.find("OK")) { Serial.println("ESP8266 is working properly."); } else { Serial.println("ESP8266 is not working properly."); }}
void loop() { // 向ESP8266发送HTTP请求 esp8266.println("AT+CIPSTART=\"TCP\",\"api.seniverse.com\",80"); if (esp8266.find("OK")) { Serial.println("TCP connection established."); } else { Serial.println("TCP connection failed."); }
String url = "/v3/weather/now.json?key=your_API_KEY&location=your_LOCATION"; String request = "GET " + url + " HTTP/1.1\r\n" + "Host: api.seniverse.com\r\n" + "User-Agent: STM32/1.0\r\n" + "Connection: close\r\n\r\n"; int length = request.length(); String cmd = "AT+CIPSEND=" + String(length); esp8266.println(cmd); if (esp8266.find(">")) { Serial.println("Sending HTTP request..."); esp8266.print(request); } else { Serial.println("Failed to send HTTP request."); }
// 接收HTTP响应 while (esp8266.available()) { String response = esp8266.readStringUntil('\n'); Serial.println(response); }
// 关闭TCP连接 esp8266.println("AT+CIPCLOSE"); delay(1000);}
复制代码


在这个示例代码中,初始化了 ESP8266 串口对象,并通过发送AT指令测试 ESP8266 是否正常工作。然后,在loop()函数中,向 ESP8266 发送一个 HTTP 请求,包括请求头和请求体。发送完毕后,等待 ESP8266 返回 HTTP 响应并将其打印出来。最后,关闭 TCP 连接并等待一秒钟,然后重复上述步骤。

发布于: 2023-06-08阅读数: 26
用户头像

DS小龙哥

关注

之所以觉得累,是因为说的比做的多。 2022-01-06 加入

熟悉C/C++、51单片机、STM32、Linux应用开发、Linux驱动开发、音视频开发、QT开发. 目前已经完成的项目涉及音视频、物联网、智能家居、工业控制领域

评论

发布
暂无评论
ESP8266获取天气预报信息,并使用CJSON解析天气预报数据_6 月优质更文活动_DS小龙哥_InfoQ写作社区