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

news2024/11/13 7:57:03

通过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  晚安!

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

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

相关文章

昇思25天学习打卡营第23天|基于MobileNetV2的垃圾分类

文章目录 昇思MindSpore应用实践1、MobileNetv2模型原理介绍2、数据准备数据预处理操作 3、基于MindSpore的MobileNetV2模型搭建ReLU6激活函数深度可分离卷积MobileNetV2网络结构 4、模型训练与测试5、模型推理 Reference 昇思MindSpore应用实践 本系列文章主要用于记录昇思25…

mysql面试(七)

前言 本章节列出了mysql在增删改查的时候&#xff0c;分别会涉及到哪些锁类型&#xff0c;又是如何交互的。 这个章节也是mysql面试基础系列的最后一章&#xff0c;后面准备更新redis数据类型和分布式锁相关问题。如果各位看官有什么问题的话&#xff0c;可以留言。 锁 之前…

【动态规划】不同路径

不同路径&#xff08;难度&#xff1a;中等&#xff09; AC代码 有点水 class Solution { public:int uniquePaths(int m, int n) {//以m为行&#xff0c;n为列&#xff0c;创建二维数组vector <vector<int>> dp(m1,vector<int>(n1));dp[0][1]1;dp[1][0]1;…

Python 教程(三):字符串特性大全

目录 专栏列表前言1. 字符串基础2. 字符串方法字符串查询字符串修改字符串切片 3. 字符串格式化旧式格式化&#xff08;% 操作符&#xff09;str.format() 方法f-string&#xff08;Python 3.6&#xff09; 4. 字符串编码5. Unicode 和 ASCII6. 正则表达式7. 字符串比较8. 字符…

LongAlign:大模型长文本处理能力提升之道

人工智能咨询培训老师叶梓 转载标明出处 大模型&#xff08;LLMs&#xff09;在处理长文本时&#xff0c;需要在输入序列上进行指令微调&#xff08;instruction finetuning&#xff09;&#xff0c;以确保它们能够有效地处理长文本。现有的方法主要集中在上下文扩展&#xff0…

ACC2.【C语言】经验积累 栈区简单剖析

int main() {int i0;int arr[10]{1,2,3,4,5,6,7,8,9,10};for (i0;i<12;i){arr[i]0;printf("A");}return 0; } 执行后无限打印A 在VS2022&#xff0c;X86,Debug环境下&#xff0c;用监视后&#xff0c;原因是arr[12]的地址与i的地址重合&#xff08;数组越界&…

c++语言学习注意事项

当学习C语言时&#xff0c;有几个重要的注意事项可以帮助初学者更有效地掌握这门强大的编程语言&#xff1a; 1. 理解基本概念和语法 C 是一门复杂且功能强大的编程语言&#xff0c;因此理解其基本概念和语法至关重要。初学者应该重点掌握以下几个方面&#xff1a; 基本语法和…

BIO示例代码

一个请求开一个线程 package org.example.demo;import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;/*** author hrui* …

2024年第四届网络通信与信息安全国际学术会议(ICNCIS 2024,8月23-25)

2024年第四届网络通信与信息安全国际学术会议&#xff08;ICNCIS2024&#xff09;将于2024年8月23-25日于杭州召开。 会议围绕网络通信在信息安全领域中的最新研究成果&#xff0c;为来自国内外高等院校、科学研究所、企事业单位的专家、教授、学者、工程师等提供一个分享专业经…

智能化车载视频监控技术的崭新发展与应用

随着国内4G网络的快速建设和发展&#xff0c;智能车载终端监控领域的高清化进程也日益加快。尽管传统的车载终端监控已经在视频录像、GPS定位等基本应用方面取得了一定的成果&#xff0c;但随着视频分析技术的不断进步&#xff0c;普通视频监控已经无法满足日益增长的车载监控新…

基于DMASM镜像的DMDSC共享存储集群部署

DMv8镜像模式共享存储集群部署 环境说明 操作系统&#xff1a;centos7.6 服务器&#xff1a;2台虚拟机 达梦数据库版本&#xff1a;达梦V8 安装前准备工作 参考文档《DM8共享存储集群》-第11、12章节 参考文档《DM8_Linux服务脚本使用手册》 1、系统环境(all nodes) 1…

Hive3:基本介绍

一、概述 Apache Hive是一款分布式SQL计算的工具&#xff0c; 其主要功能是&#xff1a; 将SQL语句翻译成MapReduce程序运行 Hive是单机工具&#xff0c;只需要部署在一台服务器即可。 Hive虽然是单机的&#xff0c;但是它可以提交分布式运行的MapReduce程序运行。 二、基本…

7月23日JavaSE学习笔记

异常&#xff1a; 程序中一些程序处理不了的特殊情况 异常类 Exception 继承自 Throwable 类&#xff08;可抛出的&#xff09; Throwable继承树 Error&#xff1a;错误/事故&#xff0c;Java程序无法处理&#xff0c;如 OOM内存溢出错误、内存泄漏...会导出程序崩溃 常见的…

C++客户端Qt开发——Qt窗口(对话框)

5.对话框 ①对话框介绍 对话框是GUI程序中不可或缺的组成部分。一些不适合在主窗口实现的功能组件可以设置在对话框中。对话框通常是一个顶层窗口&#xff0c;出现在程序最上层&#xff0c;用于实现短期任务或者简洁的用户交互。Qt常用的内置对话框有&#xff1a;QFiledialog…

【NLP自然语言处理】为什么说BERT是bidirectional

首先&#xff0c;来看一下Transformer架构图&#xff1a; 我们知道&#xff0c;Bert设计时主要采用的是Transformer编码器部分&#xff0c;要论述Bert为啥是双向的&#xff0c;我想从编码器和解码器的注意力机制来阐述。 在看这篇博客前&#xff0c;需要对Transformer有一定的…

如何录制电脑内部声音?全方位介绍电脑录音软件:8款在线录音!(2024重新整理)

如何录制电脑内部声音&#xff1f;不管是娱乐圈还是现实生活&#xff0c;【录音】这个功能的重要性不言而喻。而电脑录音已在影视配音、音视频剪辑、会议记录、在线教育等多个领域发光发热&#xff01; 本文将为您推荐8款电脑录音软件&#xff0c;并详细介绍电脑录音的多种方式…

【Windows和Linux校验文件MD5值(详细)】

1、 什么是MD5&#xff1f; 文件的MD5校验是一种常用的文件完整性验证方法。MD5&#xff08;Message Digest Algorithm 5&#xff09;是一种广泛应用的哈希算法&#xff0c;它能够将任意长度的数据转换为固定长度的哈希值。在文件校验中&#xff0c;MD5算法通过计算文件的哈希…

访问所有节点的最短路径

847. 访问所有节点的最短路径 存在一个由 n 个节点组成的无向连通图&#xff0c;图中的节点按从 0 到 n - 1 编号。 给你一个数组 graph 表示这个图。其中&#xff0c;graph[i] 是一个列表&#xff0c;由所有与节点 i 直接相连的节点组成。 返回能够访问所有节点的最短路径的…

【吊打面试官系列-Dubbo面试题】服务调用是阻塞的吗?

大家好&#xff0c;我是锋哥。今天分享关于 【服务调用是阻塞的吗&#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; 服务调用是阻塞的吗&#xff1f; 默认是阻塞的&#xff0c;可以异步调用&#xff0c;没有返回值的可以这么做。 Dubbo 是基于 NIO 的非阻塞实现…

渗透测试:筑牢网络安全的坚固防线

在当今这个互联网高度发达的时代&#xff0c;网络安全已成为维护社会稳定和经济发展的重要基石。随着互联网的普及&#xff0c;网络攻击手段日益复杂多变&#xff0c;各类安全威胁层出不穷。为了有效应对这些挑战&#xff0c;渗透测试作为一种重要的安全测试与评估方法&#xf…