ESP8266简易WIFI天气时钟

news/2025/3/15 7:37:43/

本篇介绍了如何使用ESP8266,通过WIFI连网获取网络天气和网络时间,然后借助U8g2库,在OLED上显示当前时间和天气信息。

1 HTTP获取网络天气

连网获取网络天气,一般需要通过http的方式,从天气信息提供商的网络地址获取天气信息。

1.1 注册开发者key

这里以心知天气为例,需要先注册一个开发者账号,然后获取自己的私钥,也就是等下要用到的key。

然后可以先在浏览器中输入如下链接,注意要将自己的key替换进去,然后就可以测试一下天气信息的获取情况。

https://api.seniverse.com/v3/weather/now.json?key=替换为你的私钥&location=HangZhou&language=en&unit=c

如下即为获取的天气信息,是json格式的:

1.2 http请求基本原理

上面先通过浏览器的方式获取到了天气信息,而ESP8266没有浏览器功能,需要编写代码实现http数据请求。

在编写代码之前,需要先了解一下基础的http请求原理。

url全称是资源描述符,一个url地址,用于描述一个网络上的资源,而http中的get、post、put、delete就对于着这个资源的查、改、增、删4个操作,get一般用于获取/查询资源信息。

url的格式:
【协议】://【主机名(或者叫域名)】【:端口号(可选)】/【文件路径】/【文件名】

例如:https://api.seniverse.com/v3/weather/now.json?key=替换为你的私钥&location=HangZhou&language=en&unit=c

  • 协议:https
  • 域名:api.seniverse.com

客户端发送一个HTTP请求到服务器的请求消息包括以下格式:请求行(request line)、请求头部(header)、空行和请求数据四个部分组成,下图给出了请求报文的一般格式。

服务器HTTP响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文。

根据http协议,可以编写ESP8266进行http请求的代码:

const char* host = "api.seniverse.com";     // 将要连接的服务器地址  
const int httpPort = 80;                    // 将要连接的服务器端口      // 心知天气HTTP请求所需信息
String reqUserKey = "xxxxxxxxxxxxxxxxx";   // 私钥
String reqLocation = "HangZhou";           // 城市
String reqUnit = "c";                      // 摄氏/华氏// 建立心知天气API当前天气请求资源地址
String reqRes = "/v3/weather/now.json?key=" + reqUserKey ++ "&location=" + reqLocation + "&language=en&unit=" +reqUnit;// 建立http请求信息
// 请求方法(GET)+空格+URL+空格+协议(HTTP/1.1)+回车+换行+
// 头部字段(Host)+冒号+值(服务器地址)+回车+换行+
// 头部字段(Connection)+冒号+值(close)+回车+换行+回车+换行
String httpRequest = String("GET ") + reqRes + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n";WiFiClient client;
// 尝试连接服务器
if (client.connect(host, 80))
{// 向服务器发送http请求信息client.print(httpRequest);Serial.println("Sending request: ");Serial.println(httpRequest);  // 获取并显示服务器响应状态行 String status_response = client.readStringUntil('\n');Serial.print("status_response: ");Serial.println(status_response);// 使用find跳过HTTP响应头if (client.find("\r\n\r\n")) {Serial.println("Found Header End. Start Parsing.");}// 利用ArduinoJson库解析心知天气响应信息parseInfo(client); 
} 

1.3 json数据解析

http请求获取到的天气数据是json格式的(关于json的介绍可参考:https://blog.csdn.net/hbsyaaa/article/details/115561257),需要对数据进行解析,获取到具体的天气和温度等数据。

可以将获取的json原始数据打印出来,方便确认程序是否获取到的天气数据。

具体代码如下:

void parseInfo(WiFiClient client)
{const size_t capacity = JSON_ARRAY_SIZE(1) + JSON_OBJECT_SIZE(1) + 2 * JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(6) + 230;DynamicJsonDocument doc(capacity);deserializeJson(doc, client);Serial.println(doc.as<String>());JsonObject result0 = doc["results"][0];JsonObject result0_now = result0["now"];// 通过串口监视器显示以上信息g_strWeather = result0_now["text"].as<String>();// "Sunny"g_iCode = result0_now["code"].as<int>();// "0"g_iTemperature = result0_now["temperature"].as<int>();// "32"g_strUpdateTime = result0["last_update"].as<String>();// "2020-06-02T14:40:00+08:00"Serial.println(F("======Weahter Now======="));Serial.print(F("Weather Now: "));Serial.print(g_strWeather);Serial.print(F(" -> "));Serial.println(g_iCode);Serial.print(F("Temperature: "));Serial.println(g_iTemperature);Serial.print(F("Last Update: "));Serial.println(g_strUpdateTime);Serial.println(F("========================"));
}

原始json格式的天气数据和解析后的天气和温度数据如下:

天气现象代码对照表

解析到的天气数据,除了英文形式的天气信息(text),还有一个对应的天气码(code),如上图的Cloudy对应的天气码是4。通过天气码,也可以转换为天气。天气码的对照表可参考心知天气文档:https://docs.seniverse.com/api/start/code.html

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ny9efaMH-1653319704707)(https://xxpcb-1259761082.cos.ap-shanghai.myqcloud.com/pic2/esp8266/3/6.png)]

简化起见,这里只使用常用的4种天气。

代码中文英文
0晴(国内城市白天晴)Sunny
4多云Cloudy
9Overcast
13小雨Light Rain0

2 NTP网络时间

NTP(Network Time Protocol) 是网络时间协议,它是用来同步网络中各个计算机时间的协议。

ESP8266可以连网,那就也可以通过获取网络时间来得到当前的时间:

time_t getNtpTime()
{IPAddress ntpServerIP; // NTP服务器的地址while(Udp.parsePacket() > 0); // 丢弃以前接收的任何数据包Serial.println("Transmit NTP Request");// 从池中获取随机服务器WiFi.hostByName(ntpServerName, ntpServerIP);Serial.print(ntpServerName);Serial.print(": ");Serial.println(ntpServerIP);sendNTPpacket(ntpServerIP);uint32_t beginWait = millis();while (millis() - beginWait < 1500){int size = Udp.parsePacket();if (size >= NTP_PACKET_SIZE){Serial.println("Receive NTP Response");isNTPConnected = true;Udp.read(packetBuffer, NTP_PACKET_SIZE); // 将数据包读取到缓冲区unsigned long secsSince1900;// 将从位置40开始的四个字节转换为长整型,只取前32位整数部分secsSince1900 = (unsigned long)packetBuffer[40] << 24;secsSince1900 |= (unsigned long)packetBuffer[41] << 16;secsSince1900 |= (unsigned long)packetBuffer[42] << 8;secsSince1900 |= (unsigned long)packetBuffer[43];Serial.println(secsSince1900);Serial.println(secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR);return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;}}Serial.println("No NTP Response :-("); //无NTP响应isNTPConnected = false;return 0; //如果未得到时间则返回0
}

3 OLED显示页面设计

获取到天气信息和时间后,需要将这些信息显示出来。

这里使用0.96寸OLED显示屏来显示,借助U8g2库,显示文字与天气图标(U8g2库的使用,可参考:https://blog.csdn.net/hbsyaaa/article/details/123966095)。

具体的显示代码如下:

void testShowTimeAndWeather(rtc_time_t &now_time, weather_info_t &weather_info)
{u8g2.clearBuffer();int tm_year = now_time.tm_year;int tm_month = now_time.tm_mon;int tm_day = now_time.tm_mday;int tm_hour = now_time.tm_hour;int tm_minute = now_time.tm_min;int tm_sec = now_time.tm_sec;int tm_week = now_time.tm_week;//时分char str_big_time[] = "";my_strcat(str_big_time, tm_hour);strcat(str_big_time,":");my_strcat(str_big_time, tm_minute);u8g2.setFont(u8g2_font_logisoso24_tf); u8g2.drawStr(0, 30, str_big_time);//秒char str_small_sec[] = "";my_strcat(str_small_sec, tm_sec);u8g2.setFont(u8g2_font_wqy14_t_gb2312);u8g2.drawStr(73, 30, str_small_sec);//日期char str_date[] = "";char str_temp[6];itoa(tm_year,str_temp,10);strcat(str_date,str_temp);strcat(str_date,"-");my_strcat(str_date, tm_month);strcat(str_date,"-");my_strcat(str_date, tm_day);u8g2.drawStr(0, 47, str_date);u8g2.setCursor(0, 63);u8g2.print("星期");switch (tm_week){case 1: u8g2.print("日"); break;case 2: u8g2.print("一"); break;case 3: u8g2.print("二"); break;case 4: u8g2.print("三"); break;case 5: u8g2.print("四"); break;case 6: u8g2.print("五"); break;case 7: u8g2.print("六"); break;default: break;}u8g2.setCursor(60, 63);u8g2.print("杭州");//分割线u8g2.drawLine(90, 0, 90, 63);//天气if (weather_info.iconIdx<0 || weather_info.iconIdx>3) //没有对应的天气图标{Serial.print("no icon for weather: ");Serial.println(weather_info.weather);}else{u8g2.setFont(u8g2_font_open_iconic_weather_4x_t );u8g2.drawStr(96, 34, icon_index[weather_info.iconIdx]);}char temperature_tmp[25];itoa(weather_info.temp, temperature_tmp, 10);strcat(temperature_tmp,"℃");u8g2.setFont(u8g2_font_wqy16_t_gb2312);u8g2.setCursor(96, 55);u8g2.print(temperature_tmp);u8g2.sendBuffer();
}

4 最终效果

5 总结

本篇介绍了http获取网络天气的基本原理,并通过实践,使用ESP8266连网获取网络天气和网络时间,借助U8g2库,在OLED上显示当前时间和天气信息。


http://www.ppmy.cn/news/412788.html

相关文章

国内免费wifi覆盖最新盘点

近日来&#xff0c;不少好消息出炉&#xff0c;无锡开通了第一条地铁&#xff0c;南京新加了两条地铁线路&#xff0c;方便了不少市民。学生们迎来了暑假&#xff0c;火车站面临着暑运&#xff0c;不少客运车更是趁此计划开启了免费wifi服务。下面&#xff0c;我就为大家盘点一…

wifi模组厂商

庆科&#xff0c;乐鑫&#xff0c;村田&#xff0c;正基&#xff0c;TDK&#xff0c;USI 村田和usi为iphone4/5c提供的wifi模组&#xff0c;主要是村田 iphone6 用的usi(环隆电器)的wifi iphone7用intel的wifi了 最近2015年的文章转载:http://mengkeji.com/NewsDetail-38F6F2E5…

查看电脑已经连接的WiFi的密码(Windows系统)

查看电脑已经连接的WiFi的密码&#xff08;Windows系统&#xff09; 1.进入命令行程序2.查看电脑已连接的WiFi信息3.选择对应的WiFi产看密码 1.进入命令行程序 同时按下 win R ,输入cmd 进入命令行程序 2.查看电脑已连接的WiFi信息 输入指令&#xff1a; netsh wlan show …

杭州市WiFi免费向公众开放

也许不久的将来&#xff0c;运营商最终沦为管道 -------------------------------------------------------------------------------------------- 早报讯   昨日&#xff0c;"杭州市WiFi免费向公众开放启动仪式"在杭举行&#xff0c;宣布即日起免费向杭州市民开…

wifi模块调研

一.目的 项目应用中&#xff0c;越来越多的设备需要通过网络与外界进行通讯&#xff0c;制作一款通用的wifi模块是非常有必要的&#xff0c;故对市场上常用的wifi解决方案进行调研&#xff0c;综合各个因素&#xff0c;选取最优的解决方案。 二. 关键术语 术语、缩略语 解 …

CICD详解(十四)——Gitlab忘记密码恢复

今天继续给大家介绍Linux运维相关知识&#xff0c;本文主要内容是gitlab忘记密码后的恢复。 有时&#xff0c;我们因为长时间没有使用Gitlab&#xff0c;而忘记了管理员用户的密码&#xff0c;从而导致无法登录系统的状况&#xff0c;又或者是由于系统BUG&#xff0c;Gitlab在初…

交换机之恢复重置设备密码

1、使用console连接交换机&#xff0c;设备加电使重新启动 在设备管理器中可查看console线连接的COM口 2、使用xshell或CRT等进行连接 连接中选择鞋业SERIAL 再点击串口&#xff0c;修改端口号为COM3&#xff0c;波特率为9600 3、连接成功后不停按CtrlC&#xff0c;进入…

iPad忘记密码时恢复出厂设置

iPad忘记密码恢复出厂设置&#xff1a; 第一步&#xff1a;下载iTunes iTunes云盘下载链接&#xff1a;https://pan.baidu.com/s/1TIaUoB_ElhdAmUQRf3K80g 提取码&#xff1a;h7im 电脑上安装iTunes&#xff0c;安装完毕打开它&#xff0c;iPad连接电脑&#xff0c;将iPad关机…