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 网络的 SSIDSerial.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 网络的 SSIDSerial.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.1String 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中locationJsonObject 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  晚安!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1489283.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【项目日记(三)】梦幻笔耕-前端模块

❣博主主页: 33的博客❣ ▶️文章专栏分类:项目日记◀️ &#x1f69a;我的代码仓库: 33的代码仓库&#x1f69a; &#x1faf5;&#x1faf5;&#x1faf5;关注我带你了解更多项目内容 目录 1.前言,2.登录界面3.注册界面4.博客列表界面5.博客编辑页6.博客详情页7.博客更新界面…

Java 8 中 20 个高频面试题及答案

文章目录 前言20 道高频题问题 1&#xff1a;给定一个整数列表&#xff0c;使用 Stream 函数找出列表中所有的偶数&#xff1f;问题 2&#xff1a;给定一个整数列表&#xff0c;使用 Stream 函数找出所有以 1 开头的数字&#xff1f;问题 3&#xff1a;如何使用 Stream 函数在给…

stm32入门-----TIM定时器(输入捕获模式——下)

目录 前言 一、C语言编程初始化步骤 1.开启时钟 2.配置GPIO口 3.配置时基单元 4.配置输入捕获单元&#xff08;主模式&#xff09; 5.配置触发源于从模式 6.开启定时器 二、项目实操&#xff08;测周法&#xff09; 1.定时器测量方波 2.定时器测量方波的占空比 前言 接…

el-table表格 及其el-pagination分页 封装及其使用

1、首页在components文件夹中新建table文件夹 table文件夹下table.vue全部代码&#xff1a; <template><el-table:stripe"stripe":row-key"handlerRowKey()":tree-props"treeProps":border"border":show-summary"showS…

无人机之降落操作及紧急情况处理

一、无人机降落操作 1、选择降落地点 a.提前选择一个平坦且没有障碍物的降落点&#xff1b; b.确认降落点周围没有行人或障碍物&#xff0c;保证降落的安全性。 2、降低飞行高度 a.缓慢降低飞行高度&#xff0c;尽量保持匀速下降&#xff0c;防止因下降过快导致无人机受损…

Android 软键盘挡住输入框

Android原生输入法软键盘挡住输入框,网上各种解法,但不起效。 输入框都是被挡住了,第二张图的小点,实际就是输入法的光标。 解法: packages\inputmethods\LatinIME\java\res\values-land config.xml <!-- <fraction name="config_min_keyboard_height"&g…

数据库变更导致的 Salesforce 史上最严重安全事故

这两天的 Windows 全球蓝屏事件让大家又一次看到了光鲜软件背后的脆落。借此我们也来回顾另一个软件巨头 Salesforce 史上最严重的一次安全事故。 1 事件回顾 事情发生在 2019 年 5 月 19 日&#xff0c;同样是一个周五。 Salesforce 的工程师往旗下产品 Pardot (B2B Marketi…

董宇辉离职,我一点都不意外!只不过感觉来的太快

下面这张图&#xff0c;是我在半年多前写的一段随笔&#xff0c;没想到来的这么快&#xff01; 碰巧的是今天中午&#xff0c;在开发者群里有两位老铁自曝&#xff0c;本以为能公司干到老&#xff0c;但公司却不给机会&#xff0c;已经不在是公司员工了。 最近&#xff0c;晓衡…

加速下载,揭秘Internet Download Manager2024下载器的威力!

1. Internet Download Manager&#xff08;IDM&#xff09;是一款广受欢迎的下载管理软件&#xff0c;以其强大的下载加速功能和用户友好的界面著称。 IDM马丁正版下载如下: https://wm.makeding.com/iclk/?zoneid34275 idm最新绿色版一键安装包链接&#xff1a;抓紧保存以…

学习在测试时学习(Learning at Test Time): 具有表达性隐藏状态的循环神经网络(RNNs)

摘要 https://arxiv.org/pdf/2407.04620 自注意力机制在长文本语境中表现良好&#xff0c;但其复杂度为二次方。现有的循环神经网络&#xff08;RNN&#xff09;层具有线性复杂度&#xff0c;但其在长文本语境中的性能受到隐藏状态表达能力的限制。我们提出了一种新的序列建模…

Django Form表单,常用表单字段

在Django中&#xff0c;表单&#xff08;Forms&#xff09;是处理用户输入数据的重要工具。Django提供了两种主要方式来创建和处理表单&#xff1a;使用Django的表单API手动创建表单&#xff0c;或者使用模型表单&#xff08;ModelForms&#xff09;自动从数据库模型生成表单。…

[SaaS] 盒马设计->AI如何为企业经营创造价值

D20【AIGC x 零售】AI设计如何为企业经营创造价值&#xff1f;AIGC能力不仅仅是设计师的效率工具&#xff0c;也可以当好企业的大脑&#xff0c;帮助构建企业自己的数字化设计工作流&#xff0c;让设计资产和数据发挥更大价值https://mp.weixin.qq.com/s/tk1ahorN_yQ0N-RTZ2U9x…

【告别截图烦恼】4款超神截图软件,让你的设计工作飞起来!

你是否还在为截图时的繁琐操作头疼&#xff1f;网页内容截不全&#xff0c;图片模糊不清&#xff0c;或是在图层中翻找素材时手忙脚乱&#xff1f;今天&#xff0c;米兔要带你摆脱这些烦恼&#xff0c;介绍四款让你事半功倍的截图软件&#xff01; 1. Snipaste&#xff1a;简单…

ArrayList底层原理

1. ArrayList 的基本结构 ArrayList 内部使用一个 Object 类型的数组 elementData 来存储所有的元素。数组的长度可以动态调整。 2. 初始容量和扩容机制 初始容量&#xff1a;当使用无参构造创建一个 ArrayList 实例时会在底层创建一个默认长度为0的数组&#xff0c;可以通过…

解决vscode+UE5中vscode无法识别头文件,无法函数无法跳转,也无法自动补全的问题。

一、概述 接上一条博客&#xff0c;虽然解决了报错的问题&#xff0c;但是实际上的问题却没有解决&#xff0c;无论我怎么点击&#xff0c;其都无法完成跳转&#xff0c;也无法完成自动补全的问题。 在网络上搜索了很多资料后&#xff0c;发现是在使用vscode时候UE5在vscode中的…

masscan 端口扫描——(Golang 简单使用总结)

1. 前言 最近要做一个扫描 ip 端口的功能 扫描的工具有很多&#xff0c;但是如何做到短时间扫描大量的 ip 是个相对困难的事情。 市场上比较出名的工具有 masscan和nmap masscan 支持异步扫描&#xff0c;对多线程的利用很好&#xff0c;同时仅仅支持 syn 半开扫描&#xff…

大模型深度神经网络(Deep Neural Network, DNN)

大模型深度神经网络&#xff08;Deep Neural Network, DNN&#xff09;是一种复杂的机器学习模型&#xff0c;其特点在于包含多个隐藏层&#xff0c;从而赋予模型强大的非线性表达能力和对复杂数据模式的学习能力。以下是对大模型DNN的详细介绍&#xff1a; 一、基本概念 深度…

AR 眼镜之-充电动画定制-实现方案

目录 &#x1f4c2; 前言 AR 眼镜系统版本 充电动画 1. &#x1f531; 技术方案 1.1 方案介绍 1.2 实现方案 关机充电动画 亮屏/锁屏充电动画 2. &#x1f4a0; 关机充电动画 2.1 关机充电动画核心处理类与路径 2.2 实现细节 步骤一&#xff1a;1&#xff09;定制 …

Mac printf处理参数的奇特之处(macOS中,printf使用%d输出一个浮点数会发生什么情况?)

今天早上网上冲浪的时候看到了 2016 年的一篇文章&#xff0c;里面提到了一段代码&#xff1a; #include <stdio.h> int main() {double a 10;printf("a %d\n", a);return 0; }说这段代码在 x86&#xff08;IA-32&#xff09;上运行时&#xff0c;输出为0&a…

通过 C# 写入数据到Excel表格

Excel 是一款广泛应用于数据处理、分析和报告制作的电子表格软件。在商业、学术和日常生活中&#xff0c;Excel 的使用极为普遍。本文将详细介绍如何使用免费.NET库将数据写入到 Excel 中&#xff0c;包括文本、数值、数组、和DataTable数据的输入。 文章目录 C# 在Excel单元格…