<h3> ESP32: HTTP Server </h3> <p> We previously looked at creating a web server on the Huzzah ESP32 board. However, you can also use the Huzzah as a web client, which can then access outside srvers. </p> <h3>Application Programming Interfaces (APIs)</h3> <p> An application programming interface is a computing interface to a software component or a system, that defines how other components or systems can use it. It defines the kinds of calls or requests that can be made, how to make them, the data formats that should be used, the conventions to follow, etc. </p> <p> APIs exist for all sorts of things. You can check some directory sites to see lists of popular APIs (thanks Chris!): </p> <ul> <li> <a href='https://github.com/public-apis/public-apis'> GitHub public APIs </a></li> <li> <a href='https://www.programmableweb.com/apis/directory'> Programmable Web </a></li> <li> <a href='https://any-api.com/'> Any API</a></li> <li> <a href='https://apilist.fun/'> API List </a></li> <!-- <li> <a href='https://app.swaggerhub.com/search'>SwaggerHub --> </ul> <p> SparkFun has a <a href='https://learn.sparkfun.com/tutorials/esp32-thing-plus-hookup-guide/'>tutorial for using an ESP32 to poll a remote domain</a> (http://example.com/) as a client. The following is a modification of that example to work the the <a href='https://www.weather.gov/documentation/services-web-api'>National Weather Service's API</a>. A <a href='https://techtutorialsx.com/2018/03/17/esp32-arduino-getting-weather-data-from-api/'>similar example</a> uses the OpenWeatherMap API, which requires you to register for an API key. </p> <pre><code class="language-arduino"> #include &lt;WiFi.h&gt; #include &lt;HTTPClient.h&gt; 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); } </code></pre> <!-- <p> The HTTPClient library </p> --> <p> 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: </p> <img src='./json.png' alt='example of json'> <p> This data format isn't designed to work with Arduino, but luckily we can use a library called <a href='https://arduinojson.org/'>ArduinoJson</a> to make sense of it. </p> <pre><code class="language-arduino"> #include &lt;WiFi.h&gt; #include &lt;HTTPClient.h&gt; #include &lt;ArduinoJson.h&gt; 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 } } </code></pre> <p> 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 <a href='https://arduinojson.org/v6/assistant/'>here</a> to see how large of a buffer you need. </p> <p> 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).</p> <p> You can also use similar methods to get accurate date and time information from an internet source. Here's <a href='https://randomnerdtutorials.com/esp32-date-time-ntp-client-server-arduino/'>a tutorial</a> that demonstrates that. </p>