赞
踩
本章节需要先学习之前(三)中获取当前时间方法,本文基于platformIO,需提前安装timelib库,可以参考之前(三)
代码如下,需要一点http知识,可以自行百度
- #include <WiFi.h>
- #include <HTTPClient.h>
- #include <Arduino.h>
- #include <TimeLib.h>
- #include <WiFiUdp.h>
-
- void getCityCode(); // 发送HTTP请求并且将服务器响应通过串口输出
- void getCityWeater();
- time_t getNtpTime();
- void sendNTPpacket(IPAddress &address);
- /* *****************************************************************
- * 参数设置
- * *****************************************************************/
- // NTP Servers:
- static const char ntpServerName[] = "ntp6.aliyun.com"; // 阿里云的时间服务器
- /* NTP设置 */
- const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
- byte packetBuffer[NTP_PACKET_SIZE]; // buffer to hold incoming & outgoing packets
- const int timeZone = 8; // 时区
-
- WiFiUDP Udp;
- unsigned int localPort = 8888; // local port to listen for UDP packets
- struct config_type
- {
- char stassid[32]; // 定义配网得到的WIFI名长度(最大32字节)
- char stapsw[64]; // 定义配网得到的WIFI密码长度(最大64字节)
- };
- config_type wificonf = {{"PDCN"}, {"1234567890"}};
-
- unsigned int updateweater_time = 30000;
- struct Weather_Msg
- {
- String cityDZ;
- String dataSK;
- String dataFC;
- };
- Weather_Msg weather_msg = {{""}, {""}, {""}};
-
- uint32_t targetTime = 0;
- String cityCode = "101190402"; // 天气城市代码
- WiFiClient wificlient;
- // 发送HTTP请求并且将服务器响应通过串口输出
- void getCityCode()
- {
- String URL = "http://wgeo.weather.com.cn/ip/?_=" + String(now());
- // 创建 HTTPClient 对象
- HTTPClient httpClient;
-
- // 配置请求地址。此处也可以不使用端口号和PATH而单纯的
- httpClient.begin(wificlient, URL);
-
- // 设置请求头中的User-Agent
- httpClient.setUserAgent("Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1");
- httpClient.addHeader("Referer", "http://www.weather.com.cn/");
-
- // 启动连接并发送HTTP请求
- int httpCode = httpClient.GET();
- Serial.print("Send GET request to URL: ");
- Serial.println(URL);
-
- // 如果服务器响应OK则从服务器获取响应体信息并通过串口输出
- if (httpCode == HTTP_CODE_OK)
- {
- String str = httpClient.getString();
- Serial.println("getCityCode中返回值:\n");
- Serial.println(str);
- int aa = str.indexOf("id=");
- if (aa > -1)
- {
- // cityCode = str.substring(aa+4,aa+4+9).toInt();
- cityCode = str.substring(aa + 4, aa + 4 + 9);
- Serial.println(cityCode);
- }
- else
- {
- Serial.println("获取城市代码失败");
- }
- }
- else
- {
- Serial.println("请求城市代码错误:");
- Serial.println(httpCode);
- }
-
- // 关闭ESP8266与服务器连接
- httpClient.end();
- }
-
- // 获取城市天气
- void getCityWeater()
- {
- // String URL = "http://d1.weather.com.cn/dingzhi/" + cityCode + ".html?_="+String(now());//新
- String URL = "http://d1.weather.com.cn/weather_index/" + cityCode + ".html?_=" + String(now()); // 原来
- // 创建 HTTPClient 对象
- HTTPClient httpClient;
-
- // httpClient.begin(URL);
- httpClient.begin(wificlient, URL); // 使用新方法
-
- // 设置请求头中的User-Agent
- httpClient.setUserAgent("Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1");
- httpClient.addHeader("Referer", "http://www.weather.com.cn/");
-
- // 启动连接并发送HTTP请求
- int httpCode = httpClient.GET();
- Serial.println("正在获取天气数据");
- Serial.println(URL);
-
- // 如果服务器响应OK则从服务器获取响应体信息并通过串口输出
- if (httpCode == HTTP_CODE_OK)
- {
-
- String str = httpClient.getString();
- Serial.println(str);
- // Serial.println("httpdata=" + str);
- int indexStart = str.indexOf("weatherinfo\":");
- int indexEnd = str.indexOf("};var alarmDZ");
-
- weather_msg.cityDZ = str.substring(indexStart + 13, indexEnd);
- // Serial.println(jsonCityDZ);
-
- indexStart = str.indexOf("dataSK =");
- indexEnd = str.indexOf(";var dataZS");
- weather_msg.dataSK = str.substring(indexStart + 8, indexEnd);
- // Serial.println(jsonDataSK);
-
- indexStart = str.indexOf("\"f\":[");
- indexEnd = str.indexOf(",{\"fa");
- weather_msg.dataFC = str.substring(indexStart + 5, indexEnd);
- // Serial.println(jsonFC);
-
- // weaterData(&jsonCityDZ, &jsonDataSK, &jsonFC);
-
- Serial.println("获取成功");
- Serial.println(weather_msg.cityDZ);
- Serial.println(weather_msg.dataSK);
- Serial.println(weather_msg.dataFC);
- }
- else
- {
- Serial.println("请求城市天气错误:");
- Serial.print(httpCode);
- }
-
- // 关闭ESP8266与服务器连接
- httpClient.end();
- }
- void setup()
- {
-
- Serial.begin(115200);
-
- Serial.print("正在连接WIFI ");
- Serial.println(wificonf.stassid);
- WiFi.begin(wificonf.stassid, wificonf.stapsw);
-
- while (WiFi.status() != WL_CONNECTED)
- {
- delay(500);
- Serial.print(".");
- }
- Serial.print("本地IP: ");
- Serial.println(WiFi.localIP());
- Serial.println(Udp.remotePort());
- Serial.println("waiting for sync");
- setSyncProvider(getNtpTime);
- setSyncInterval(300);
- }
- void loop()
- {
- getCityCode();
- getCityWeater();
- delay(60000);
- }
-
- time_t getNtpTime()
- {
- IPAddress ntpServerIP; // NTP server's ip address
-
- while (Udp.parsePacket() > 0)
- ; // discard any previously received packets
- Serial.println("Transmit NTP Request");
- // get a random server from the pool
- 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");
- Udp.read(packetBuffer, NTP_PACKET_SIZE); // read packet into the buffer
- unsigned long secsSince1900;
- // convert four bytes starting at location 40 to a long integer
- secsSince1900 = (unsigned long)packetBuffer[40] << 24;
- secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
- secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
- secsSince1900 |= (unsigned long)packetBuffer[43];
- return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
- }
- }
- Serial.println("No NTP Response :-(");
- return 0; // return 0 if unable to get the time
- }
-
- // send an NTP request to the time server at the given address
- void sendNTPpacket(IPAddress &address)
- {
- // set all bytes in the buffer to 0
- memset(packetBuffer, 0, NTP_PACKET_SIZE);
- // Initialize values needed to form NTP request
- // (see URL above for details on the packets)
- packetBuffer[0] = 0b11100011; // LI, Version, Mode
- packetBuffer[1] = 0; // Stratum, or type of clock
- packetBuffer[2] = 6; // Polling Interval
- packetBuffer[3] = 0xEC; // Peer Clock Precision
- // 8 bytes of zero for Root Delay & Root Dispersion
- packetBuffer[12] = 49;
- packetBuffer[13] = 0x4E;
- packetBuffer[14] = 49;
- packetBuffer[15] = 52;
- // all NTP fields have been given values, now
- // you can send a packet requesting a timestamp:
- Udp.beginPacket(address, 123); // NTP requests are to port 123
- Udp.write(packetBuffer, NTP_PACKET_SIZE);
- Udp.endPacket();
- }
实验结果如下,返回json格式,之后可以通过ArduinoJson库来解析需要的键值对。
- 获取成功
- {"city":"常熟","cityname":"changshu","temp":"999","tempn":"18","weather":"阴","wd":"北风转东南风","ws":"3-4级转<3级","weathercode":"d2","weathercoden":"n2","fctime":"202404150800"}
- {"nameen":"changshu","cityname":"常熟","city":"101190402","temp":"21.4","tempf":"70.5","WD":"东风","wde":"E","WS":"2级","wse":"8km\/h","SD":"73%","sd":"73%","qy":"1011","njd":"10km","time":"20:05","rain":"0","rain24h":"0","aqi":"53","aqi_pm25":"53","weather":"多云","weathere":"Cloudy","weathercode":"d01","limitnumber":"","date":"04月15日(星期一)"}
- {"fa":"02","fb":"02","fc":"26","fd":"16","fe":"北风","ff":"东南风","fg":"3-4级","fh":"<3级","fk":"8","fl":"3","fm":"999.9","fn":"82.5","fi":"4\/15","fj":"今天"}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。