HTTP ESP8266 获取天气请求 单片机,嵌入式 2024/7/26 日志

通过http请求获取天气信息:

这里借鉴一下 中国气象局网站举例

首先根据网址 分析:
http://weather.cma.cn/
通过vscode插件:REST Client 发送请求我们会得到内容

首先我们的打开浏览器调试工具查看请求格式

筛选以下几个关键的格式,试着用插件发送请求

GET /web/weather/57516.html HTTP/1.1
Host: weather.cma.cn
Referer: http://weather.cma.cn/web/weather/58238.html
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.95 Safari/537.36

 可以看到我们获取到了内容,所有这个请求格式是正确的所以单片机请求应该这样写:

        这里用的库为ArduinoHttpClient.h

拿到一个库,首先应该是先看例程:

/*
  Dweet.io GET 客户端示例,使用 ArduinoHttpClient 库
  每隔十秒连接到 dweet.io,
  发送一个 GET 请求和请求体。使用 SSL 加密。

  展示了如何使用 Strings 组装路径和解析响应内容。
  dweet.io 预期的请求格式如下:
  https://dweet.io/get/latest/dweet/for/thingName

  更多关于 dweet.io 的信息,请参考 https://dweet.io/play/

  创建于 2016 年 2 月 15 日
  最后更新于 2019 年 1 月 22 日
  作者:Tom Igoe

  此示例代码属于公共领域,可自由使用
*/

// 包含 ArduinoHttpClient 库和 WiFi101 库
#include <ArduinoHttpClient.h>
#include <WiFi101.h>

// 包含敏感数据的头文件,如 WiFi 凭证
#include "arduino_secrets.h"

// WiFi 设置
// 注意:请在 Secret 标签下的 arduino_secrets.h 文件中输入您的敏感数据
char ssid[] = SECRET_SSID; // WiFi 网络名称
char pass[] = SECRET_PASS; // WiFi 密码

const char serverAddress[] = "dweet.io";  // 服务器地址
int port = 80;                            // 服务器端口
String dweetName = "scandalous-cheese-hoarder"; // 在此处使用您自己的设备名称

// 创建 WiFi 客户端和 HTTP 客户端实例
WiFiClient wifi;
HttpClient client = HttpClient(wifi, serverAddress, port);
int status = WL_IDLE_STATUS;              // WiFi 连接状态变量

// 初始化函数
void setup() {
  // 开始串行通信
  Serial.begin(9600);
  while (!Serial);

  // 尝试连接到指定的 WiFi 网络
  while (status != WL_CONNECTED) {
    Serial.print("尝试连接到名为: ");
    Serial.println(ssid); // 输出网络名称

    // 连接到 WPA/WPA2 网络
    status = WiFi.begin(ssid, pass);
  }

  // 输出已连接的 WiFi 网络的 SSID
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // 输出 WiFi 盾牌的 IP 地址
  IPAddress ip = WiFi.localIP();
  Serial.print("IP 地址: ");
  Serial.println(ip);
}

// 主循环函数
void loop() {
  // 组装 GET 请求的路径
  String path = "/get/latest/dweet/for/" + dweetName;

  // 发送 GET 请求
  Serial.println("发送 GET 请求");
  client.get(path);

  // 读取响应的状态码和响应体
  int statusCode = client.responseStatusCode();
  String response = client.responseBody();
  Serial.print("状态码: ");
  Serial.println(statusCode);
  Serial.print("响应: ");
  Serial.println(response);

  // 典型响应示例:
  // {"this":"succeeded","by":"getting","the":"dweets","with":[{"thing":"my-thing-name","created":"2016-02-16T05:10:36.589Z","content":{"sensorValue":456}}]}
  // 我们关心的是 "content": 数值

  // 现在解析响应,寻找 "content" 字段
  int labelStart = response.indexOf("content\":");
  // 找到 "content" 后的第一个 {
  int contentStart = response.indexOf("{", labelStart);
  // 找到紧接着的 },并获取大括号之间的内容
  int contentEnd = response.indexOf("}", labelStart);
  String content = response.substring(contentStart + 1, contentEnd);
  Serial.println(content);

  // 接下来获取冒号后的数值,并转换成整数
  int valueStart = content.indexOf(":");
  String valueString = content.substring(valueStart + 1);
  int number = valueString.toInt();
  Serial.print("数值字符串: ");
  Serial.println(valueString);
  Serial.print("实际数值: ");
  Serial.println(number);

  // 等待十秒钟
  Serial.println("等待十秒钟\n");
  delay(10000);
}

示例程序二

/*
  简单的 WebSocket 客户端示例,使用 ArduinoHttpClient 库
  连接到 WebSocket 服务器,并每隔 5 秒发送一条问候消息

  创建于 2016 年 6 月 28 日
  作者:Sandeep Mistry
  修改于 2019 年 1 月 22 日
  修改者:Tom Igoe

  此示例代码属于公共领域,可自由使用
*/

// 包含 ArduinoHttpClient 库和 WiFi101 库
#include <ArduinoHttpClient.h>
#include <WiFi101.h>
// 包含敏感数据的头文件,如 WiFi 凭证
#include "arduino_secrets.h"

// WiFi 设置
// 注意:请在 Secret 标签下的 arduino_secrets.h 文件中输入您的敏感数据
char ssid[] = SECRET_SSID; // WiFi 网络名称
char pass[] = SECRET_PASS; // WiFi 密码

char serverAddress[] = "echo.websocket.org"; // 服务器地址
int port = 80;                              // 服务器端口

// 创建 WiFi 客户端和 WebSocket 客户端实例
WiFiClient wifi;
WebSocketClient client = WebSocketClient(wifi, serverAddress, port);
int status = WL_IDLE_STATUS;                // WiFi 连接状态变量
int count = 0;                              // 计数器,用于发送消息

// 初始化函数
void setup() {
  // 开始串行通信
  Serial.begin(9600);
  while (status != WL_CONNECTED) {
    Serial.print("尝试连接到名为: ");
    Serial.println(ssid); // 输出网络名称

    // 连接到 WPA/WPA2 网络
    status = WiFi.begin(ssid, pass);
  }

  // 输出已连接的 WiFi 网络的 SSID
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // 输出 WiFi 盾牌的 IP 地址
  IPAddress ip = WiFi.localIP();
  Serial.print("IP 地址: ");
  Serial.println(ip);
}

// 主循环函数
void loop() {
  // 开始 WebSocket 客户端
  Serial.println("启动 WebSocket 客户端");
  client.begin();

  // 当客户端与服务器保持连接时
  while (client.connected()) {
    Serial.print("发送问候 ");
    Serial.println(count); // 输出计数器的值

    // 发送一条文本类型的消息
    client.beginMessage(TYPE_TEXT);
    client.print("hello "); // 发送问候语
    client.print(count);    // 发送计数器的值
    client.endMessage();    // 结束消息发送

    // 增加计数器的值,用于下一次消息
    count++;

    // 检查是否有消息可接收
    int messageSize = client.parseMessage();

    if (messageSize > 0) {
      Serial.println("收到一条消息:");
      Serial.println(client.readString()); // 输出接收到的消息
    }

    // 等待 5 秒钟
    delay(5000);
  }

  Serial.println("已断开连接"); // 当不再连接时输出
}

单片机代码:

 然而结果不太理想

那么这里就会有一个问题了:为什么没有反馈

                我最开始的时候也是百思不得其解,甚至还尝试更换库
 然而终于,在2024/7/27 今天的 0:15分我_悟了:想明白一件事是很有成就感的(被bug折磨得人都要疯了)

一切全部都是 网址的问题,因为我一开始就错了:

现在我们从头开始复盘:

        首先,请求下发,得到如下结果:

最开始,我们以为请求结果由html生成

所以测试用例为:

当我们用这种方式去请求之后,确实如愿的取得了页面数据

当单片机发送请求之后,由于网页内容太多,加上,大部分内容都是由js控制动态生成.

所以获取页面信息然后走爬虫的路子,基本上要放弃.

直到刚刚,我才知道有这么一个请求,它就是数据!! json的交互数据请求: 是不是很眼熟? 53698!

 打开看看: 原来如此

看ip地址大致能猜出意思

api嘛就是 接口   now  现在  后面这个数字多半就是  表某城市 数字

验证一下: 很明显,数据正常!

更改单片机HTTP请求之后结果:

串口输出结果正常
,那么问题解决了.下一步就应该是json解析了.




===前面的都是废话,点击  一键直达  结果===

获取天气,分3步:

                     第一步:得到请求地址: http://weather.cma.cn/api/now/54511  

                                  拆分为:
                                                服务器地址:weather.cma.cn
                                                天气请求地址:/api/now/
                                                 城市代码:54511  (北京)

                      第二步:编写请求代码,这里以  HttpClient.h 库 举例

WiFiClient ClientA;          
// 设置一个 联网 后客户端实例 类似于打开浏览器

HttpClient clienta(ClientA,"weather.cma.cn",80);
//把这个客户端 绑定到这个服务器  类似于用浏览器打开了这一个网页

clienta.kUserAgent="User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36";
//一个通用的浏览器标识  类似于告诉服务器 我是一个正儿八经的浏览器  不要拒绝我
//实际上单片机不设置这条,它也能...................

clienta.get("/api/now/53698");
//发送get请求  类似这样 GET /api/now/53698 HTTP/1.1

String buf=clienta.responseBody();
//获取返回的结果  


Serial.println(buf);
//串口输出

                     第三步:处理json数据了,这里用 ArduinoJson.h 库举例

//json数据解析
DynamicJsonDocument doc(1024); // 动态分配内存用于存储JSON数据
deserializeJson(doc, buf);// 将JSON数据反序列化为doc
JsonObject locationobj= doc["data"]["location"].as<JsonObject>();// 获取JSON对象 data中location

JsonObject nowobj = doc["data"]["now"].as<JsonObject>();// 获取JSON对象data中now
JsonObject  lastUpdateobj= doc["data"]["lastUpdate"];// 获取JSON对象data中lastUpdate
String strjson=locationobj["path"];// 获取JSON对象data中location中的path属性


  int index1 = strjson.indexOf(",");  // 查找第一个逗号的位置
  int index2 = strjson.indexOf(",", index1 + 1);  // 查找第二个逗号的位置
  
  String part1 = strjson.substring(0, index1);  // 截取第一个部分
  String part2 = strjson.substring(index1 + 1, index2);  // 截取第二个部分
  String part3 = strjson.substring(index2 + 1);  // 截取第三个部分
  
  Serial.println("国家"+part1);// 输出第一个部分
  Serial.println("城市"+part2);// 输出第二个部分 这一步:还需进一步处理,测试结果显示补全
  Serial.println("区县"+part3);// 输出第三个部分
  Serial.println("温度"+String(nowobj["temperature"])+"℃");
  Serial.println("湿度"+String(nowobj["humidity"])+"%");
  Serial.println("气压"+String(nowobj["pressure"])+"hPa");


// 获取时间 这一步:还需进一步处理,测试结果显示补全
Serial.println("时间:"+String(lastUpdateobj["lastUpdate"]));



整篇结果展示: 现在时间2024/7/27 1:46  晚安!

  • 10
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ESP8266是一款低功耗的Wi-Fi模块,可以轻松地与各种设备和应用进行通信。要获取天气信息,可以使用ESP8266的SDK(Software Development Kit)来实现。 首先,我们需要一个可靠的天气数据源。可以选择使用一些第三方天气API,例如,OpenWeatherMap、Weather.com等。这些API提供了实时的天气数据和预报来满足我们的需求。 接下来,需要使用ESP8266的SDK来进行网络连接和数据处理。ESP8266的SDK支持TCP/IP协议栈,可以通过HTTP请求天气API获取天气数据。具体而言,我们需要实现以下步骤: 1. 设置Wi-Fi连接:使用ESP8266的SDK来配置Wi-Fi连接参数,例如SSID和密码。 2. 建立HTTP连接:使用ESP8266的SDK建立TCP连接,并发送HTTP请求天气API的服务器地址。 3. 接收和处理数据:使用ESP8266的SDK接收来自服务器的HTTP响应,并解析其中的天气数据。 4. 根据需求进行数据处理:根据需要,可以提取所需的天气信息,例如温度、湿度和天气状况等。 5. 可选的展示方式:可以将实时的天气信息通过串口输出,在串口监视器中查看结果。也可以通过LCD显示屏或者其他外部设备来实现可视化展示。 总结来说,使用ESP8266的SDK可以很方便地获取天气数据。通过配置Wi-Fi连接和发送HTTP请求,我们可以从天气API获取数据,并进行相应的数据处理和展示。这种方式能够使我们的设备具备实时获取和展示天气信息的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值