【国民技术N32项目移植】4.天气显示及预报系统之ESP8266联网以及获取天气和时间信息
本篇文章介绍了如何使用开发板在RTT下驱动ESP8266以及联网获取相应信息。
1、功能介绍
使用ESP8266连接相应WiFi,首先获取网络时间配置RTC,然后根据自己设定的URI获取相应的天气信息(丫丫天气)。
2、软件包使用
使用到的软件包如下图所示,AT_DEVICE用于配置ESP8266的联网信息,WebClient用于获取时间和天气信息,cJSON用于解析网络服务器返回的JSON文本内容。
![image-20230220185204578](https://s2.loli.net/2023/02/20/uy2UDf1KQqJbtsI.png)
3、编写程序
#define ESP8266_SAMPLE_DEIVCE_NAME "esp0"
static struct at_device_esp8266 esp0 =
{
ESP8266_SAMPLE_DEIVCE_NAME,
ESP8266_SAMPLE_CLIENT_NAME,
ESP8266_SAMPLE_WIFI_SSID,
ESP8266_SAMPLE_WIFI_PASSWORD,
ESP8266_SAMPLE_RECV_BUFF_LEN,
};
int Esp8266_Init(void){
struct at_device_esp8266 *esp8266 = &esp0;
return at_device_register(&(esp8266->device),
esp8266->device_name,
esp8266->client_name,
AT_DEVICE_CLASS_ESP8266,
(void *) esp8266);
}
ESP8266配置联网信息
![image-20230220185741162](https://s2.loli.net/2023/02/20/bIlq9nH7VaJFLo6.png)
static int webclient_get_comm(const char *uri)
{
struct webclient_session* session = RT_NULL;
unsigned char *buffer = RT_NULL;
int index, ret = 0;
int bytes_read, resp_status;
int content_length = -1;
buffer = (unsigned char *) web_malloc(BUFFER_SIZE);
if (buffer == RT_NULL)
{
rt_kprintf("no memory for receive buffer.\n");
ret = -RT_ENOMEM;
goto __exit;
}
session = webclient_session_create(BUFFER_SIZE);
if (session == RT_NULL)
{
ret = -RT_ENOMEM;
goto __exit;
}
if ((resp_status = webclient_get(session, uri)) != 200)
{
rt_kprintf("webclient GET request failed, response(%d) error.\n", resp_status);
ret = -RT_ERROR;
goto __exit;
}
rt_kprintf("webclient get response data: \n");
content_length = webclient_content_length_get(session);
rt_kprintf("content_length:\t %d\n", content_length);
if (content_length < 0)
{
rt_kprintf("webclient GET request type is chunked.\n");
bytes_read = webclient_read(session, (void *)buffer, BUFFER_SIZE);
rt_kprintf("data length:%d\n", bytes_read);
for (index = 0; index < bytes_read; index++)
{
rt_kprintf("%c", buffer[index]);
}
if(rt_memcmp(WEATHERDATA_URI,uri,rt_strlen(WEATHERDATA_URI)) == 0){
parseWeatherData(buffer);
} else if(rt_memcmp(FORECASTDATA_URI,uri,rt_strlen(FORECASTDATA_URI)) == 0){
parseForecastData(buffer);
} else {
rt_kprintf("\nURI analysis Error\n");
}
}
else
{
int content_pos = 0;
do
{
bytes_read = webclient_read(session, (void *)buffer,
content_length - content_pos > BUFFER_SIZE ?
BUFFER_SIZE : content_length - content_pos);
if (bytes_read <= 0)
{
break;
}
for (index = 0; index < bytes_read; index++)
{
rt_kprintf("%c", buffer[index]);
}
content_pos += bytes_read;
} while (content_pos < content_length);
rt_kprintf("\ntime uri analysis\n");
for (index = 0; index < content_length - 1; index++)
{
buffer[index] = buffer[index+13];
}
parseTimeData(buffer);
}
__exit:
if (session)
{
webclient_close(session);
}
if (buffer)
{
web_free(buffer);
}
return ret;
}
#include "weatherData.h"
#include <webclient.h>
#include <cJSON.h>
void parseWeatherData(uint8_t *buffer){
int ret = 0;
cJSON *root, *data_arr;
cJSON *weather;
root = cJSON_Parse((const char*) buffer);
if(root != 0){
rt_kprintf("JSON format ok.\n");
weather = cJSON_GetObjectItem(root, "data");
if(weather->type == cJSON_Object){
rt_kprintf("begin parse data.\n");
rt_strncpy(DalianData.UpdateTime,
cJSON_GetObjectItem(weather, "lastUpdate")->valuestring,
rt_strlen(cJSON_GetObjectItem(weather, "lastUpdate")->valuestring));
rt_strncpy(DalianData.numtq,
cJSON_GetObjectItem(weather, "numtq")->valuestring,
rt_strlen(cJSON_GetObjectItem(weather, "numtq")->valuestring));
DalianData.numfl = cJSON_GetObjectItem(weather, "numfl")->valueint,
rt_strncpy(DalianData.temp,
cJSON_GetObjectItem(weather, "qw")->valuestring,
rt_strlen(cJSON_GetObjectItem(weather, "qw")->valuestring));
rt_strncpy(DalianData.humidity,
cJSON_GetObjectItem(weather, "sd")->valuestring,
rt_strlen(cJSON_GetObjectItem(weather, "sd")->valuestring));
rt_kprintf("UpdateTime\t%s\n",DalianData.UpdateTime);
rt_kprintf("numtq\t\t%s\n",DalianData.numtq);
rt_kprintf("numfl\t\t%d\n",DalianData.numfl);
rt_kprintf("temp\t\t%s\n",DalianData.temp);
rt_kprintf("humidity\t%s\n",DalianData.humidity);
}
}else {
rt_kprintf("JSON format error.\n");
}
}
void parseForecastData(uint8_t *buffer){
int ret = 0;
cJSON *root, *day1, *day2;
cJSON *list, *data;
root = cJSON_Parse((const char*) buffer);
if(root != 0){
rt_kprintf("JSON format ok.\n");
data = cJSON_GetObjectItem(root, "data");
list = cJSON_GetObjectItem(data, "list");
if(list->type == cJSON_Array){
rt_kprintf("Array format ok.\n");
day1 = cJSON_GetArrayItem(list, 0);
if(day1->type == cJSON_Object){
rt_kprintf("day1 format ok.\n");
rt_strncpy(Day1.numtq ,
cJSON_GetObjectItem(day1, "numtq1")->valuestring,
rt_strlen(cJSON_GetObjectItem(day1, "numtq1")->valuestring));
rt_strncpy(Day1.numfl ,
cJSON_GetObjectItem(day1, "numfl1")->valuestring,
rt_strlen(cJSON_GetObjectItem(day1, "numfl1")->valuestring));
rt_strncpy(Day1.Lowtemp ,
cJSON_GetObjectItem(day1, "qw2")->valuestring,
rt_strlen(cJSON_GetObjectItem(day1, "qw2")->valuestring));
rt_strncpy(Day1.Hightemp ,
cJSON_GetObjectItem(day1, "qw1")->valuestring,
rt_strlen(cJSON_GetObjectItem(day1, "qw1")->valuestring));
rt_kprintf("天气\t%s\n",Day1.numtq);
rt_kprintf("风力\t\t%s\t%d\t%d\n",Day1.numfl,Day1.numfl[0],Day1.numfl[1]);
rt_kprintf("低温\t\t%s\n",Day1.Lowtemp);
rt_kprintf("高温\t\t%s\n",Day1.Hightemp);
}
day2 = cJSON_GetArrayItem(list, 1);
if(day2->type == cJSON_Object){
rt_kprintf("day2 format ok.\n");
rt_kprintf("day1 format ok.\n");
rt_strncpy(Day2.numtq ,
cJSON_GetObjectItem(day2, "numtq1")->valuestring,
rt_strlen(cJSON_GetObjectItem(day1, "numtq1")->valuestring));
rt_strncpy(Day2.numfl ,
cJSON_GetObjectItem(day2, "numfl1")->valuestring,
rt_strlen(cJSON_GetObjectItem(day2, "numfl1")->valuestring));
rt_strncpy(Day2.Lowtemp ,
cJSON_GetObjectItem(day2, "qw2")->valuestring,
rt_strlen(cJSON_GetObjectItem(day2, "qw2")->valuestring));
rt_strncpy(Day2.Hightemp ,
cJSON_GetObjectItem(day2, "qw1")->valuestring,
rt_strlen(cJSON_GetObjectItem(day2, "qw1")->valuestring));
rt_kprintf("天气\t%s\n",Day2.numtq);
rt_kprintf("风力\t\t%s\n",Day2.numfl);
rt_kprintf("低温\t\t%s\n",Day2.Lowtemp);
rt_kprintf("高温\t\t%s\n",Day2.Hightemp);
}
}
} else {
rt_kprintf("JSON format error.\n");
}
}
void parseTimeData(uint8_t *buffer){
int ret = 0;
cJSON *root;
root = cJSON_Parse((const char*) buffer);
if(root != 0){
QQTime = cJSON_GetObjectItem(root, "t")->valueint;
rt_kprintf("\ntime:\t%d\n",QQTime);
}else {
rt_kprintf("JSON format error.\n");
}
}
4、功能验证
打印信息 天气信息 以及 未来两天的预报
![image-20230220195049788](https://s2.loli.net/2023/02/20/frnZc1KPyagqsFj.png)
5、避坑部分
1.ntp功能无法实现
问题描述:配置RTC更新网络时间本来想用RTT自带的NTP功能,但一直无法驱动,提示服务器时间超时。也因为自己不太熟悉网络编程,同时查阅资料后也没有解决,就先放下准备后面再仔细钻研。
解决方法:使用其他的服务器获取时间戳,然后自己配置RTC。
2.ESP8266固件版本太低,无法兼容RTT软件包的指令
问题描述:一开始使用ESP8266联网的时候一直提示无法识别指令,最后发现是自己的固件太低,最后使用安信可提供的固件下载软件进行升级即可。