SparkFun has a tutorial for using an ESP32 to poll a remote domain (http://example.com/) as a client. The following is a modification of that example to work the the National Weather Service's API. A similar example uses the OpenWeatherMap API, which requires you to register for an API key.
#include <WiFi.h>
#include <HTTPClient.h>
const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASSWORD";
const String endpoint = "https://api.weather.gov/gridpoints/TOP/31,80/forecast";
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
Serial.println("Connected to the WiFi network");
}
void loop() {
if ((WiFi.status() == WL_CONNECTED)) { //Check the current connection status
HTTPClient http;
http.begin(endpoint); //Specify the URL
int httpCode = http.GET(); //Make the request
if (httpCode > 0) { //Check for the returning code
String payload = http.getString();
Serial.println(httpCode);
Serial.println(payload);
}
else {
Serial.println("Error on HTTP request");
}
http.end(); //Free the resources
}
delay(30000);
}
But often, we'll want to process the data we get in the response, for example, to extract just the forecast low temperature for tonight. The response comes in the JSON format, and looks something like this:
This data format isn't designed to work with Arduino, but luckily we can use a library called ArduinoJson to make sense of it.
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASSWORD";
const String endpoint = "https://api.weather.gov/gridpoints/TOP/31,80/forecast";
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
Serial.println("Connected to the WiFi network");
}
void loop() {
if ((WiFi.status() == WL_CONNECTED)) { //Check the current connection status
HTTPClient http;
http.begin(url); //Specify the URL
int httpResponseCode = http.GET(); // Make the GET request
if (httpResponseCode > 0) { // Execute if we get a good response
String payload = http.getString();
Serial.println(httpResponseCode);
// Serial.println(payload); // Uncomment to view the entire payload
DynamicJsonDocument doc(10000); // Create a buffer of 10000 bytes
// Deserialize the JSON document
DeserializationError error = deserializeJson(doc, payload);
// Test if parsing succeeds.
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.c_str());
return;
}
// Navigate through JSON document, extracting some values
const int temp = doc["properties"]["periods"][0]["temperature"];
const char* unit = doc["properties"]["periods"][0]["temperatureUnit"];
const char* forecast = doc["properties"]["periods"][0]["shortForecast"];
Serial.print("All I care about is the current weather, which is ");
Serial.print(temp);
Serial.print(unit);
Serial.print(", ");
Serial.println(forecast);
http.end(); // Close the connection
}
delay(30000); // Wait 30 seconds between requests
}
}
This example uses a buffer of 10000 bytes, which is fine for this application but may be too large for polling in quick succession. To use this example on a different API, plug in a JSON sample here to see how large of a buffer you need.
In addition to APIs, you can use this method to "scrape" any website (including your own GitHub webpage). However, you will be limited to static results (whatever your page serves to the client).
You can also use similar methods to get accurate date and time information from an internet source. Here's a tutorial that demonstrates that.