本篇介紹了如何使用ESP8266,通過WIFI連網(wǎng)獲取網(wǎng)絡(luò)天氣和網(wǎng)絡(luò)時(shí)間,然后借助U8g2庫,在OLED上顯示當(dāng)前時(shí)間和天氣信息。
1 HTTP獲取網(wǎng)絡(luò)天氣
連網(wǎng)獲取網(wǎng)絡(luò)天氣,一般需要通過http的方式,從天氣信息提供商的網(wǎng)絡(luò)地址獲取天氣信息。
1.1 注冊開發(fā)者key
這里以心知天氣為例,需要先注冊一個(gè)開發(fā)者賬號,然后獲取自己的私鑰,也就是等下要用到的key。
![pYYBAGKczR2AP8pFAADHRuQ2xoI534.png](https://file.elecfans.com/web2/M00/47/82/pYYBAGKczR2AP8pFAADHRuQ2xoI534.png)
然后可以先在瀏覽器中輸入如下鏈接,注意要將自己的key替換進(jìn)去,然后就可以測試一下天氣信息的獲取情況。
https://api.seniverse.com/v3/weather/now.json?key=替換為你的私鑰&location=HangZhou&language=en&unit=c
如下即為獲取的天氣信息,是json格式的:
![pYYBAGKczSqAEsxBAAD9z39vn7o109.png](https://file.elecfans.com/web2/M00/47/82/pYYBAGKczSqAEsxBAAD9z39vn7o109.png)
1.2 http請求基本原理
上面先通過瀏覽器的方式獲取到了天氣信息,而ESP8266沒有瀏覽器功能,需要編寫代碼實(shí)現(xiàn)http數(shù)據(jù)請求。
在編寫代碼之前,需要先了解一下基礎(chǔ)的http請求原理。
url全稱是資源描述符,一個(gè)url地址,用于描述一個(gè)網(wǎng)絡(luò)上的資源,而http中的get、post、put、delete就對于著這個(gè)資源的查、改、增、刪4個(gè)操作,get一般用于獲取/查詢資源信息。
url的格式: 【協(xié)議】://【主機(jī)名(或者叫域名)】【:端口號(可選)】/【文件路徑】/【文件名】
例如:https://api.seniverse.com/v3/weather/now.json?key=替換為你的私鑰&location=HangZhou&language=en&unit=c
協(xié)議:https
域名:api.seniverse.com
客戶端發(fā)送一個(gè)HTTP請求到服務(wù)器的請求消息包括以下格式:請求行(request line)、請求頭部(header)、空行和請求數(shù)據(jù)四個(gè)部分組成,下圖給出了請求報(bào)文的一般格式。
![poYBAGKczTGAA3FvAAA8OcVsn7A182.png](https://file.elecfans.com/web2/M00/47/83/poYBAGKczTGAA3FvAAA8OcVsn7A182.png)
服務(wù)器HTTP響應(yīng)也由四個(gè)部分組成,分別是:狀態(tài)行、消息報(bào)頭、空行和響應(yīng)正文。
![pYYBAGKczTeAcHSeAADSG00i2ao868.png](https://file.elecfans.com/web2/M00/47/82/pYYBAGKczTeAcHSeAADSG00i2ao868.png)
根據(jù)http協(xié)議,可以編寫ESP8266進(jìn)行http請求的代碼:
const char* host = "api.seniverse.com"; // 將要連接的服務(wù)器地址
const int httpPort = 80; // 將要連接的服務(wù)器端口
// 心知天氣HTTP請求所需信息
String reqUserKey = "xxxxxxxxxxxxxxxxx"; // 私鑰
String reqLocation = "HangZhou"; // 城市
String reqUnit = "c"; // 攝氏/華氏
// 建立心知天氣API當(dāng)前天氣請求資源地址
String reqRes = "/v3/weather/now.json?key=" + reqUserKey +
+ "&location=" + reqLocation +
"&language=en&unit=" +reqUnit;
// 建立http請求信息
// 請求方法(GET)+空格+URL+空格+協(xié)議(HTTP/1.1)+回車+換行+
// 頭部字段(Host)+冒號+值(服務(wù)器地址)+回車+換行+
// 頭部字段(Connection)+冒號+值(close)+回車+換行+回車+換行
String httpRequest = String("GET ") + reqRes + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Connection: close\r\n\r\n";
WiFiClient client;
// 嘗試連接服務(wù)器
if (client.connect(host, 80))
{
// 向服務(wù)器發(fā)送http請求信息
client.print(httpRequest);
Serial.println("Sending request: ");
Serial.println(httpRequest);
// 獲取并顯示服務(wù)器響應(yīng)狀態(tài)行
String status_response = client.readStringUntil('\n');
Serial.print("status_response: ");
Serial.println(status_response);
// 使用find跳過HTTP響應(yīng)頭
if (client.find("\r\n\r\n"))
{
Serial.println("Found Header End. Start Parsing.");
}
// 利用ArduinoJson庫解析心知天氣響應(yīng)信息
parseInfo(client);
}
1.3 json數(shù)據(jù)解析
http請求獲取到的天氣數(shù)據(jù)是json格式的(關(guān)于json的介紹可參考:),需要對數(shù)據(jù)進(jìn)行解析,獲取到具體的天氣和溫度等數(shù)據(jù)。
可以將獲取的json原始數(shù)據(jù)打印出來,方便確認(rèn)程序是否獲取到的天氣數(shù)據(jù)。
具體代碼如下:
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());
JsonObject result0 = doc["results"][0];
JsonObject result0_now = result0["now"];
// 通過串口監(jiān)視器顯示以上信息
g_strWeather = result0_now["text"].as();// "Sunny"
g_iCode = result0_now["code"].as();// "0"
g_iTemperature = result0_now["temperature"].as();// "32"
g_strUpdateTime = result0["last_update"].as();// "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格式的天氣數(shù)據(jù)和解析后的天氣和溫度數(shù)據(jù)如下:
![poYBAGKczT-AJANtAAEDvbsdX74343.png](https://file.elecfans.com/web2/M00/47/83/poYBAGKczT-AJANtAAEDvbsdX74343.png)
天氣現(xiàn)象代碼對照表
解析到的天氣數(shù)據(jù),除了英文形式的天氣信息(text),還有一個(gè)對應(yīng)的天氣碼(code),如上圖的Cloudy對應(yīng)的天氣碼是4。通過天氣碼,也可以轉(zhuǎn)換為天氣。天氣碼的對照表可參考心知天氣文檔:https://docs.seniverse.com/api/start/code.html
![poYBAGKczUiADexiAABqezKK6UI281.png](https://file.elecfans.com/web2/M00/47/83/poYBAGKczUiADexiAABqezKK6UI281.png)
簡化起見,這里只使用常用的4種天氣。
代碼 | 中文 | 英文 |
---|---|---|
0 | 晴(國內(nèi)城市白天晴) | Sunny |
4 | 多云 | Cloudy |
9 | 陰 | Overcast |
13 | 小雨 | Light Rain0 |
2 NTP網(wǎng)絡(luò)時(shí)間
NTP(Network Time Protocol) 是網(wǎng)絡(luò)時(shí)間協(xié)議,它是用來同步網(wǎng)絡(luò)中各個(gè)計(jì)算機(jī)時(shí)間的協(xié)議。
ESP8266可以連網(wǎng),那就也可以通過獲取網(wǎng)絡(luò)時(shí)間來得到當(dāng)前的時(shí)間:
time_t getNtpTime()
{
IPAddress ntpServerIP; // NTP服務(wù)器的地址
while(Udp.parsePacket() > 0); // 丟棄以前接收的任何數(shù)據(jù)包
Serial.println("Transmit NTP Request");
// 從池中獲取隨機(jī)服務(wù)器
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); // 將數(shù)據(jù)包讀取到緩沖區(qū)
unsigned long secsSince1900;
// 將從位置40開始的四個(gè)字節(jié)轉(zhuǎn)換為長整型,只取前32位整數(shù)部分
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響應(yīng)
isNTPConnected = false;
return 0; //如果未得到時(shí)間則返回0
}
3 OLED顯示頁面設(shè)計(jì)
獲取到天氣信息和時(shí)間后,需要將這些信息顯示出來。
這里使用0.96寸OLED顯示屏來顯示,借助U8g2庫,顯示文字與天氣圖標(biāo)(U8g2庫的使用,可參考:)。
具體的顯示代碼如下:
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;
//時(shí)分
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) //沒有對應(yīng)的天氣圖標(biāo)
{
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 最終效果
![pYYBAGKczVKAJskVAAKYT8UVGWI251.png](https://file.elecfans.com/web2/M00/47/82/pYYBAGKczVKAJskVAAKYT8UVGWI251.png)
5 總結(jié)
本篇介紹了http獲取網(wǎng)絡(luò)天氣的基本原理,并通過實(shí)踐,使用ESP8266連網(wǎng)獲取網(wǎng)絡(luò)天氣和網(wǎng)絡(luò)時(shí)間,借助U8g2庫,在OLED上顯示當(dāng)前時(shí)間和天氣信息。
-
嵌入式
+關(guān)注
關(guān)注
5095文章
19189瀏覽量
307960 -
WIFI
+關(guān)注
關(guān)注
81文章
5310瀏覽量
204940 -
Arduino
+關(guān)注
關(guān)注
188文章
6477瀏覽量
187952 -
ESP8266
+關(guān)注
關(guān)注
50文章
962瀏覽量
45367
發(fā)布評論請先 登錄
相關(guān)推薦
esp8266如何破解wifi密碼及詳細(xì)步驟
![<b class='flag-5'>esp8266</b>如何破解<b class='flag-5'>wifi</b>密碼及詳細(xì)步驟](https://file.elecfans.com/web1/M00/51/4E/o4YBAFsGEiCANwQEAAB7Tz8QQIY149.jpg)
ESP8266_wifi模塊說明書
ESP8266 WiFi模塊獲取網(wǎng)絡(luò)天氣適配戰(zhàn)艦開發(fā)板的使用實(shí)例
![<b class='flag-5'>ESP8266</b> <b class='flag-5'>WiFi</b>模塊獲取網(wǎng)絡(luò)<b class='flag-5'>天氣</b>適配戰(zhàn)艦開發(fā)板的使用實(shí)例](https://file.elecfans.com/web1/M00/BE/72/o4YBAF7jQ8GAZFc0AAZ4woC3luY603.png)
ESP8266 wifi模塊開發(fā)匯總
![<b class='flag-5'>ESP8266</b> <b class='flag-5'>wifi</b>模塊開發(fā)匯總](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
基于STM32的ESP8266天氣時(shí)鐘(2)--------MCU獲取天氣數(shù)據(jù)
![基于STM32的<b class='flag-5'>ESP8266</b><b class='flag-5'>天氣</b><b class='flag-5'>時(shí)鐘</b>(2)--------MCU獲取<b class='flag-5'>天氣</b>數(shù)據(jù)](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
STM32-ESP8266wifi模塊實(shí)現(xiàn)
![STM32-<b class='flag-5'>ESP8266wifi</b>模塊實(shí)現(xiàn)](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
基于STM32的ESP8266天氣時(shí)鐘(3)--------MCU數(shù)據(jù)處理及顯示
![基于STM32的<b class='flag-5'>ESP8266</b><b class='flag-5'>天氣</b><b class='flag-5'>時(shí)鐘</b>(3)--------MCU數(shù)據(jù)處理及顯示](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
基于ESP8266的電動(dòng)WiFi卷簾
![基于<b class='flag-5'>ESP8266</b>的電動(dòng)<b class='flag-5'>WiFi</b>卷簾](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
ESP8266 WIFI模擬GPS時(shí)鐘信號
![<b class='flag-5'>ESP8266</b> <b class='flag-5'>WIFI</b>模擬GPS<b class='flag-5'>時(shí)鐘</b>信號](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
基于ESP8266的NTP時(shí)鐘
![基于<b class='flag-5'>ESP8266</b>的NTP<b class='flag-5'>時(shí)鐘</b>](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
基于ESP8266的WiFi車
ESP8266或ESP32上的WiFi Webradio
![<b class='flag-5'>ESP8266</b>或<b class='flag-5'>ESP</b>32上的<b class='flag-5'>WiFi</b> Webradio](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
評論