esp32联网获取时间和天气(四)

说明

本章节需要先学习之前(三)中获取当前时间方法,本文基于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":"今天"}

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: ESP32是一个高度集成的微控制器,可以轻松地获取时间天气信息。要实现这个功能,我们可以按照以下步骤进行: 1. 获取时间: 首先,我们需要连接到互联网ESP32支持Wi-Fi连接,可以通过其内置的Wi-Fi模块连接到无线网络。在成功连接到网络后,我们可以使用NTP(网络时间协议)服务器来获取当前的时间。ESP32可以使用内置的NTP客户端库,向NTP服务器发送请求,并接收到时间戳。通过简单的编程,我们可以将时间戳转换为可读的格式,例如年、月、日、时、分、秒。这样,我们就可以在ESP32上获取到准确的时间了。 2. 获取天气: 为了获取天气信息,我们可以使用一些开放的天气API。这些API可以提供实时的天气数据,例如温度、湿度、气压、风速等信息。首先,我们需要注册一个天气API账号,并获取API密钥。然后,我们可以使用ESP32的Wi-Fi连接,向天气API服务器发送请求,并传递所需的参数,如地理位置、API密钥等。服务器将返回相应的天气数据,我们可以解析这些数据并提取所需的信息。最后,我们可以在ESP32上显示或存储这些天气数据,以便后续使用。 综上所述,借助ESP32的强大功能和互联网连接,我们可以轻松地实现获取时间天气的功能。这样,我们可以在自己的项目中通过ESP32来监控和展示实时的时间和天气信息。 ### 回答2: 使用ESP32获取时间天气,可以通过以下步骤实现: 1. 连接到Wi-Fi网络:首先,通过ESP32的Wi-Fi模块连接到一个可用的Wi-Fi网络。这可以通过调用适当的库函数来完成。确保提供正确的凭证和网络名称。 2. 获取时间:连接到Wi-Fi网络后,可以使用网络时间协议(NTP)服务器来获取当前时间。ESP32上的库函数可用于与NTP服务器进行通信并获取正确的时间戳。使用该时间戳进行所需的日期和时间的计算。 3. 获取天气:获取天气需要从一个天气API获取数据。选择一个提供天气数据的信任和可用的API,并创建一个帐户。根据API提供的说明,使用ESP32上的HTTP请求库函数向API发送请求,并从响应中提取所需的天气数据。 4. 解析和显示:一旦获取了天气数据,可以将其解析为所需的格式。这可以根据所选择的API和数据结构来完成。然后将数据显示在连接到ESP32的显示屏上,或者使用其他输出设备来显示天气信息。 5. 循环刷新:在代码中设置一个循环,以便定期刷新时间和天气数据。这可以使用延时函数或定时器来实现。 需要注意的是,确保适当理解所使用的库函数和API文档,并确保将授权和权限考虑在内。此外,网络连接和数据获取的稳定性也需要考虑,以确保系统的可靠性和准确性。 ### 回答3: 要通过ESP32获取时间天气信息,我们可以采取以下步骤: 1. 首先,需要连接ESP32与互联网,可以通过WiFi或其他网络连接方式实现。建立稳定的网络连接,使ESP32能够访问互联网。 2. 使用一种合适的开发环境例如Arduino IDE,开始编写ESP32的代码。引入相关的库,例如WiFi库和HTTP客户端库以便进行网络数据传输。 3. 在代码中,需要使用适当的API或服务提供者来获取时间天气信息。可以通过调用时间API获取当前时间,例如使用NTP(网络时间协议)服务器。对于天气信息,可以使用天气API,例如OpenWeatherMap或其他提供天气数据的服务。 4. 配置和发送HTTP请求以获取所需的数据。使用所选的时间API和天气API的URL和参数设置HTTP请求。确保将请求中包括必要的身份验证信息(如果有)。 5. 处理返回的数据。从HTTP响应中提取时间和天气信息。根据API的响应格式,可以使用适当的JSON解析器来提取所需的数据。 6. 在ESP32上显示或使用所获取的时间和天气信息。可以使用适当的显示设备(例如OLED显示屏)来显示信息,或者将其发送到其他设备(例如移动应用程序或服务器)。 以上是大致的步骤,其中涉及到的具体代码和细节取决于所选择的开发环境和使用的API。这是一个基本框架,可以根据需要进行调整和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值