通过HTTP GET 请求互联网接口数据:ESP8266/NodeMCU

释放双眼,带上耳机,听听看~!

在本教程中,您将学习如何使用带有 Arduino IDE 的 ESP8266 NodeMCU 板发出 HTTP GET 请求。我们将演示如何使用 ThingSpeak 解码 OpenWeatherMap.org 中的 JSON 数据并在连接图中绘制值。

通过HTTP GET 请求互联网接口数据:ESP8266/NodeMCU

HTTP GET 请求方式

超文本传输协议 (HTTP) 用作客户端和服务器之间的请求-响应协议。下面是一个示例:

  • ESP8266(客户端)向服务器(例如:OpenWeatherMap.org 或 ThingSpeak)提交 HTTP 请求;
  • 服务器向ESP8266(客户端)返回响应;
  • 最后,响应包含有关请求的状态信息,也可能包含请求的内容。

 HTTP 获取

请注意,查询字符串(name = field1 和 value = value1)在 HTTP GET 请求的 URL 中发送。

(使用 HTTP GET,数据对 URL 请求中的每个人都可见。

 先决条件

在继续学习本教程之前,请确保完成以下先决条件。

 Arduino集成开发环境

我们将使用 Arduino IDE 对 ESP8266 NodeMCU 进行编程,因此请确保您已安装 ESP8266 附加组件。

 Arduino_JSON库

您还需要安装 Arduino_JSON 库。您可以在 Arduino IDE 库管理器中安装此库。只需转到“程序”>“包含库”>“管理库”,然后搜索库名称,如下所示:

通过HTTP GET 请求互联网接口数据:ESP8266/NodeMCU

其他 Web 服务或 API

在本教程中,您将学习如何设置 ESP8266 NodeMCU 开发板,以执行对 OpenWeatherMap.org 和 ThingSpeak 的 HTTP 请求。如果您更喜欢使用本地解决方案进行学习,则可以将 HTTP 与 Node-RED 一起使用。本教程中介绍的所有示例也适用于其他 API。

总之,要使本教程与任何服务兼容,您需要搜索服务 API 文档。然后,您需要服务器名称(URL 或 IP 地址)和要在请求中发送的参数(URL 路径或请求正文)。最后,修改我们的示例以与您要使用的任何 API 集成。

1. ESP8266 HTTP GET:JSON 数据(OpenWeatherMap.org)

在此示例中,你将了解如何发出 API 请求来访问数据。例如,我们将使用 OpenWeatherMap API。此 API 有一个免费计划,并提供了许多有关世界上几乎任何地方天气的有用信息。

通过HTTP GET 请求互联网接口数据:ESP8266/NodeMCU

使用 OpenWeatherMap API

应用程序编程接口 (API) 是由软件开发人员编写的一组函数,使任何人都可以使用他们的数据或服务。OpenWeatherMap 项目有一个 API,使用户能够请求天气数据。

通过HTTP GET 请求互联网接口数据:ESP8266/NodeMCU

在此项目中,您将使用该 API 请求所选位置的当天天气预报。学习使用 API 是一项很棒的技能,因为它允许您访问各种不断变化的信息,例如当前股价、货币汇率、最新新闻、流量更新、推文等等。

注意:API 密钥对用户是唯一的,不应与任何人共享。

OpenWeatherMap 的免费计划提供了完成此项目所需的一切。要使用 API,您需要一个 API 密钥,称为 APIID。若要获取 APIID,请执行以下操作:

  1. 打开浏览器并转到 https://openweathermap.org/appid/
  2. 按“注册”按钮并创建一个免费帐户。
  3. 转到此链接:https://home.openweathermap.org/api_keys 并获取您的 API 密钥。
通过HTTP GET 请求互联网接口数据:ESP8266/NodeMCU
  1. 在“API 密钥”选项卡上,你将看到一个默认密钥(在上图中以红色矩形突出显示);这是从站点中提取信息所需的唯一密钥。将此密钥复制并粘贴到某处;你一会儿就会用到它。
  2. 要提取所选位置的天气信息,请输入以下 URL:
http://api.openweathermap.org/data/2.5/weather?q=yourCityName,yourCountryCode&APPID=yourUniqueAPIkey

将 yourCityName 替换为要为其提供数据的城市,将 yourCountryCode 替换为该城市的国家/地区代码,将 yourUniqueAPIkey 替换为步骤 4 中的唯一 API 密钥。例如,葡萄牙波尔图市更新后的 API URL 为:

http://api.openweathermap.org/data/2.5/weather?q=Porto,
PT&APPID=801d2603e9f2e1c70e042e4f5f6e0---
  1. 将您的 URL 复制到浏览器中,API 将返回一堆与您当地天气相对应的信息。在编写本教程的当天,我们得到了有关葡萄牙波尔图天气的以下信息。
{"coord":{"lon":-8.611,"lat":41.1496},"weather":[{"id":803,"main":"Clouds","description":"broken clouds","icon":"04d"}],"base":"stations","main":{"temp":294.58,"feels_like":294.95,"temp_min":293.82,"temp_max":295.65,"pressure":1016,"humidity":83},"visibility":10000,"wind":{"speed":8.94,"deg":180,"gust":8.94},"clouds":{"all":75},"dt":1666877635,"sys":{"type":2,"id":2009460,"country":"PT","sunrise":1666853957,"sunset":1666892227},"timezone":3600,"id":2735943,"name":"Porto","cod":200}

这是缩进时的样子,以提高可读性。

{
  "coord": {
    "lon": -8.611,
    "lat": 41.1496
  },
  "weather": [
    {
      "id": 803,
      "main": "Clouds",
      "description": "broken clouds",
      "icon": "04d"
    }
  ],
  "base": "stations",
  "main": {
    "temp": 294.58,
    "feels_like": 294.95,
    "temp_min": 293.82,
    "temp_max": 295.65,
    "pressure": 1016,
    "humidity": 83
  },
  "visibility": 10000,
  "wind": {
    "speed": 8.94,
    "deg": 180,
    "gust": 8.94
  },
  "clouds": {
    "all": 75
  },
  "dt": 1666877635,
  "sys": {
    "type": 2,
    "id": 2009460,
    "country": "PT",
    "sunrise": 1666853957,
    "sunset": 1666892227
  },
  "timezone": 3600,
  "id": 2735943,
  "name": "Porto",
  "cod": 200
}

接下来,您将了解如何使用此信息来获取特定数据,例如温度、湿度、压力、风速等。

代码ESP8266 HTTP GET OpenWeatherMap.org

安装必要的板附加组件和库后,将以下代码复制到 Arduino IDE,但不要上传。您需要进行一些更改才能使其适合您。

/*
  
  更多Arduino/ESP8266/ESP32等教程请访问: https://www.qutaojiao.com
*/

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>
#include <Arduino_JSON.h>

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

// Your Domain name with URL path or IP address with path
String openWeatherMapApiKey = "REPLACE_WITH_YOUR_OPEN_WEATHER_MAP_API_KEY";
// Example:
//String openWeatherMapApiKey = "bd939aa3d23ff33d3c8f5dd1dd4";

// Replace with your country code and city
String city = "Porto";
String countryCode = "PT";

// THE DEFAULT TIMER IS SET TO 10 SECONDS FOR TESTING PURPOSES
// For a final application, check the API call limits per hour/minute to avoid getting blocked/banned
unsigned long lastTime = 0;
// Timer set to 10 minutes (600000)
//unsigned long timerDelay = 600000;
// Set timer to 10 seconds (10000)
unsigned long timerDelay = 10000;

String jsonBuffer;

void setup() {
  Serial.begin(115200);

  WiFi.begin(ssid, password);
  Serial.println("Connecting");
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to WiFi network with IP Address: ");
  Serial.println(WiFi.localIP());
 
  Serial.println("Timer set to 10 seconds (timerDelay variable), it will take 10 seconds before publishing the first reading.");
}

void loop() {
  // Send an HTTP GET request
  if ((millis() - lastTime) > timerDelay) {
    // Check WiFi connection status
    if(WiFi.status()== WL_CONNECTED){
      String serverPath = "http://api.openweathermap.org/data/2.5/weather?q=" + city + "," + countryCode + "&APPID=" + openWeatherMapApiKey;
      
      jsonBuffer = httpGETRequest(serverPath.c_str());
      Serial.println(jsonBuffer);
      JSONVar myObject = JSON.parse(jsonBuffer);
  
      // JSON.typeof(jsonVar) can be used to get the type of the var
      if (JSON.typeof(myObject) == "undefined") {
        Serial.println("Parsing input failed!");
        return;
      }
    
      Serial.print("JSON object = ");
      Serial.println(myObject);
      Serial.print("Temperature: ");
      Serial.println(myObject["main"]["temp"]);
      Serial.print("Pressure: ");
      Serial.println(myObject["main"]["pressure"]);
      Serial.print("Humidity: ");
      Serial.println(myObject["main"]["humidity"]);
      Serial.print("Wind Speed: ");
      Serial.println(myObject["wind"]["speed"]);
    }
    else {
      Serial.println("WiFi Disconnected");
    }
    lastTime = millis();
  }
}

String httpGETRequest(const char* serverName) {
  WiFiClient client;
  HTTPClient http;
    
  // Your IP address with path or Domain name with URL path 
  http.begin(client, serverName);
  
  // Send HTTP POST request
  int httpResponseCode = http.GET();
  
  String payload = "{}"; 
  
  if (httpResponseCode>0) {
    Serial.print("HTTP Response code: ");
    Serial.println(httpResponseCode);
    payload = http.getString();
  }
  else {
    Serial.print("Error code: ");
    Serial.println(httpResponseCode);
  }
  // Free resources
  http.end();

  return payload;
}

 

设置网络凭据

使用您的网络凭据修改下一行:SSID 和密码。该代码对您应该在何处进行更改进行了很好的注释。

// Replace with your network credentials
const char* ssid     = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

设置 OpenWeatherMap.org API 密钥

在以下行中插入 API 密钥:

String openWeatherMapApiKey = "REPLACE_WITH_YOUR_OPEN_WEATHER_MAP_API_KEY";

设置您的城市和国家/地区

在以下变量中输入要获取其数据的城市以及国家/地区代码(中国地区码是CN):

// Replace with your country code and city
String city = "Porto";
String countryCode = "PT";

进行这些更改后,您可以将代码上传到您的开发板。继续阅读以了解代码的工作原理。

HTTP GET 请求(JSON 对象)

在 loop() 中,调用 httpGETRequest() 函数以发出 HTTP GET 请求:

String serverPath = "http://api.openweathermap.org/data/2.5/weather?q=" + city + "," + countryCode + "&APPID=" + openWeatherMapApiKey;

jsonBuffer = httpGETRequest(serverPath.c_str());

httpGETRequest() 函数向 OpenWeatherMap 发出请求,并检索一个带有 JSON 对象的字符串,该对象包含有关您所在城市天气的所有信息。

String httpGETRequest(const char* serverName) {
  WiFiClient client;
  HTTPClient http;
    
  // Your IP address with path or Domain name with URL path 
  http.begin(client, serverName);

  // Send HTTP POST request
  int httpResponseCode = http.GET();

  String payload = "{}"; 

  if (httpResponseCode>0) {
    Serial.print("HTTP Response code: ");
    Serial.println(httpResponseCode);
    payload = http.getString();
  }
  else {
    Serial.print("Error code: ");
    Serial.println(httpResponseCode);
  }
  // Free resources
  http.end();

  return payload;
}

 解码 JSON 对象

若要访问这些值,请解码 JSON 对象并将所有值存储在 jsonBuffer 数组中。

JSONVar myObject = JSON.parse(jsonBuffer);
// JSON.typeof(jsonVar) can be used to get the type of the var

if (JSON.typeof(myObject) == "undefined") {
  Serial.println("Parsing input failed!");
  return;
}

Serial.print("JSON object = ");
Serial.println(myObject);
Serial.print("Temperature: ");
Serial.println(myObject["main"]["temp"]);
Serial.print("Pressure: ");
Serial.println(myObject["main"]["pressure"]);
Serial.print("Humidity: ");
Serial.println(myObject["main"]["humidity"]);
Serial.print("Wind Speed: ");
Serial.println(myObject["wind"]["speed"]);

 HTTP GET 演示

上传代码后,打开串行监视器,你将看到它正在接收以下 JSON 数据:

{"coord":{"lon":-8.61,"lat":41.15},"weather":[{"id":801,"main":"Clouds","description":"few clouds","icon":"02d"}],"base":"stations","main":{"temp":294.44,"feels_like":292.82,"temp_min":292.15,"temp_max":297.04,"pressure":1008,"humidity":63},"visibility":10000,"wind":{"speed":4.1,"deg":240},"clouds":{"all":20},"dt":1589288330,"sys":{"type":1,"id":6900,"country":"PT","sunrise":1589260737,"sunset":1589312564},"timezone":3600,"id":2735943,"name":"Porto","cod":200}

然后,它在 Arduino IDE 串行监视器中打印解码的 JSON 对象,以获取温度(以开尔文为单位)、压力、湿度和风速值。

通过HTTP GET 请求互联网接口数据:ESP8266/NodeMCU

出于演示目的,我们每 10 秒请求一次新数据。但是,对于长期项目,您应该增加计时器或检查每小时/分钟的 API 调用限制,以避免被阻止/禁止。

2. ESP8266 HTTP GET:更新值 (ThingSpeak)

在此示例中,ESP8266发出 HTTP GET 请求以更新 ThingSpeak 中的读数。

通过HTTP GET 请求互联网接口数据:ESP8266/NodeMCU

 使用 ThingSpeak API

ThingSpeak 有一个免费的 API,允许您使用 HTTP 存储和检索数据。在本教程中,您将使用 ThingSpeak API 从任何位置在连接图中发布和可视化数据。例如,我们将发布随机值,但在实际应用中,您将使用真实的传感器读数。

要将 ThingSpeak 与 ESP 配合使用,您需要一个 API 密钥。请按照以下步骤操作:

  1. 转到 ThingSpeak.com 并创建一个免费帐户。
  2. 然后,打开“频道”选项卡。
  3.  创建一个新频道。
通过HTTP GET 请求互联网接口数据:ESP8266/NodeMCU
  1. 打开新创建的频道,然后选择“API 密钥”选项卡以复制 API 密钥。
通过HTTP GET 请求互联网接口数据:ESP8266/NodeMCU

HTTP GET ThingSpeak ESP8266代码

将下一个程序复制到Arduino IDE(键入SSID,密码和API密钥):

/*
  
  更多Arduino/ESP8266/ESP32等教程请访问: https://www.qutaojiao.com
*/

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

// REPLACE WITH THINGSPEAK.COM API KEY
String serverName = "http://api.thingspeak.com/update?api_key=REPLACE_WITH_YOUR_API_KEY";
// EXAMPLE:
//String serverName = "http://api.thingspeak.com/update?api_key=7HQJM49R8JAPR";

// THE DEFAULT TIMER IS SET TO 10 SECONDS FOR TESTING PURPOSES
// For a final application, check the API call limits per hour/minute to avoid getting blocked/banned
unsigned long lastTime = 0;
// Timer set to 10 minutes (600000)
//unsigned long timerDelay = 600000;
// Set timer to 10 seconds (10000)
unsigned long timerDelay = 10000;

void setup() {
  Serial.begin(115200); 

  WiFi.begin(ssid, password);
  Serial.println("Connecting");
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to WiFi network with IP Address: ");
  Serial.println(WiFi.localIP());
 
  Serial.println("Timer set to 10 seconds (timerDelay variable), it will take 10 seconds before publishing the first reading.");
  
  // Random seed is a number used to initialize a pseudorandom number generator
  randomSeed(analogRead(0));
}

void loop() {
  // Send an HTTP GET request
  if ((millis() - lastTime) > timerDelay) {
    // Check WiFi connection status
    if(WiFi.status()== WL_CONNECTED){
      WiFiClient client;
      HTTPClient http;
    
      String serverPath = serverName + "&field1=" + String(random(40));
      
      // Your Domain name with URL path or IP address with path
      http.begin(client, serverPath.c_str());
      
      // Send HTTP GET request
      int httpResponseCode = http.GET();
      
      if (httpResponseCode>0) {
        Serial.print("HTTP Response code: ");
        Serial.println(httpResponseCode);
        String payload = http.getString();
        Serial.println(payload);
      }
      else {
        Serial.print("Error code: ");
        Serial.println(httpResponseCode);
      }
      // Free resources
      http.end();
    }
    else {
      Serial.println("WiFi Disconnected");
    }
    lastTime = millis();
  }
}

 

设置网络凭据

使用您的网络凭据修改下一行:SSID 和密码。该代码对您应该在何处进行更改进行了很好的注释。

// Replace with your network credentials
const char* ssid     = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

设置 serverName(API 密钥)

修改 serverName 变量以包含您的 API 密钥。

String serverName = "http://api.thingspeak.com/update?api_key=REPLACE_WITH_YOUR_API_KEY";

现在,将代码上传到您的开发板,它应该可以立即工作。如果您想了解如何发出 HTTP GET 请求,请阅读下一节。

 HTTP GET 请求

在 loop() 中,您每 10 秒使用随机值发出一次 HTTP GET 请求:

if(WiFi.status()== WL_CONNECTED){
  WiFiClient client;
  HTTPClient http;
    
  String serverPath = serverName + "&field1=" + String(random(40));
      
  // Your Domain name with URL path or IP address with path
  http.begin(client, serverPath.c_str());

  // Send HTTP GET request
  int httpResponseCode = http.GET();

ESP8266在以下 URL 中发出新请求,以使用新值 (30) 更新传感器 field1。

http://api.thingspeak.com/update?api_key=REPLACE_WITH_YOUR_API_KEY&field1=30

然后,以下代码行保存来自服务器的 HTTP 响应。

if (httpResponseCode>0) {
  Serial.print("HTTP Response code: ");
  Serial.println(httpResponseCode);
  String payload = http.getString();
  Serial.println(payload);
}
else {
  Serial.print("Error code: ");
  Serial.println(httpResponseCode);
}

在Arduino IDE串行监视器中,您应该看到HTTP响应代码200(这意味着请求已成功)。

通过HTTP GET 请求互联网接口数据:ESP8266/NodeMCU

您的 ThingSpeak 仪表板应该每 10 秒接收一次新读数。

通过HTTP GET 请求互联网接口数据:ESP8266/NodeMCU

对于最终应用程序,您可能需要增加计时器或检查每小时/分钟的 API 调用限制,以避免被阻止/禁止。

注意:为了更轻松地使用ESP8266将传感器读数发送到 ThingSpeak,我们推荐以下教程:

  • ESP8266 NodeMCU 将传感器读数发布到 ThingSpeak(最简单的方法)

 总结

在本教程中,您学习了如何使用 HTTP GET 请求将 ESP8266 与 Web 服务集成。您还可以使用 ESP8266发出 HTTP POST 请求。

给TA打赏
共{{data.count}}人
人已打赏
Nodemcu/ESP8266Nodemcu/ESP8266-进阶动态

HTTP GET 和 HTTP POST 请求教程:使用 ESP8266/NodeMCU

2023-12-11 22:22:35

ESP32ESP32-进阶Nodemcu/ESP8266Nodemcu/ESP8266-进阶免费项目

利用ESP32/ESP8266与OpenAI的ChatGPT实现对话的原理与步骤详解

2024-2-28 10:00:36

2 条回复 A文章作者 M管理员
  1. Lumilio

    666

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索
'); })();