// Get from ThingSpeak API and parse JSON
// ESP32 + Wokwi
// Khalil Ouali
#include <Arduino.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
const String SSID = "Wokwi-GUEST";
const String PW = "";
const String CHANNEL = "";
const String READ_KEY = "";
const String TIMEZONE = "";
const String TEMPERATURE_FIELD = "1";
WiFiClient wifi;
HTTPClient http;
StaticJsonDocument<1024> jsonDoc;
void fetch_information() {
// returns some information about the channel with an empty feeds array in json format
String endpoint = "http://api.thingspeak.com/channels/" + CHANNEL + "/fields/1.json?results=0&timezone=" + TIMEZONE + "&api_key=" + READ_KEY;
http.begin(wifi, endpoint);
int status = http.GET();
Serial.println();
if (status > 0) {
String payload = http.getString();
if (status == 200) {
deserializeJson(jsonDoc, payload);
String name = jsonDoc["channel"]["name"];
Serial.println("> Channel Name: " + name);
for (int i = 1; i <= 8; i++) {
String field_key = "field" + String(i);
if (!jsonDoc["channel"].containsKey(field_key)) break;
String field_name = jsonDoc["channel"][field_key];
Serial.println("\t- Field " + String(i) + ": " + field_name);
}
String created_at = jsonDoc["channel"]["created_at"];
Serial.println("\tCreated at: " + created_at);
String updated_at = jsonDoc["channel"]["updated_at"];
Serial.println("\tUpdated at: " + updated_at);
jsonDoc.clear();
} else {
Serial.println("E: Couldn't get information. Server responded with " + String(status) + ":\n" + payload);
}
} else {
Serial.println("E: Couldn't get information. Couldn't reach server. Code: " + String(status));
}
http.end();
}
void fetch_last_temp() {
// returns the value with the degree C symbol (%E2%84%83) in text format
String endpoint = "http://api.thingspeak.com/channels/" + CHANNEL + "/fields/" + TEMPERATURE_FIELD + "/last.txt?append=%20%E2%84%83&api_key=" + READ_KEY;
http.begin(wifi, endpoint);
int status = http.GET();
Serial.println();
if (status > 0) {
String payload = http.getString();
if (status == 200) {
Serial.println("> Last recorded temperature: " + payload);
} else {
Serial.println("E: Couldn't get last recorded temperature. Server responded with " + String(status) + ". Payload:\n" + payload);
}
} else {
Serial.println("E: Couldn't get last recorded temperature. Couldn't reach server. Code: " + String(status) + ".");
}
http.end();
}
void fetch_last_entry() {
// returns last entry in json format
String endpoint = "http://api.thingspeak.com/channels/" + CHANNEL + "/feeds/last.json?timezone=" + TIMEZONE + "&api_key=" + READ_KEY;
http.begin(wifi, endpoint);
int status = http.GET();
Serial.println();
if (status > 0) {
String payload = http.getString();
if (status == 200) {
deserializeJson(jsonDoc, payload);
long id = jsonDoc["entry_id"];
Serial.println("> Last entry ID: " + String(id));
for (int i = 1; i <= 8; i++) {
String field_key = "field" + String(i);
if (!jsonDoc.containsKey(field_key)) break;
float field_value = jsonDoc[field_key];
Serial.println("\t- Val " + String(i) + ": " + String(field_value));
}
String created_at = jsonDoc["created_at"];
Serial.println("\tCreated at: " + created_at);
jsonDoc.clear();
} else {
Serial.println("E: Couldn't get last entry. Server responded with " + String(status) + ". Payload:\n" + payload);
}
} else {
Serial.println("E: Couldn't get last entry. Couldn't reach server. Code: " + String(status) + ".");
}
http.end();
}
void fetch_last_data_age() {
// returns time since last entry and its unit in json format
String endpoint = "http://api.thingspeak.com/channels/" + CHANNEL + "/feeds/last_data_age.json?api_key=" + READ_KEY;
http.begin(wifi, endpoint);
int status = http.GET();
Serial.println();
if (status > 0) {
String payload = http.getString();
if (status == 200) {
deserializeJson(jsonDoc, payload);
long age = jsonDoc["last_data_age"];
String unit = jsonDoc["last_data_age_units"];
Serial.println("> Last entry is " + String(age) + unit + " old.");
jsonDoc.clear();
} else {
Serial.println("E: Couldn't get last data age. Server responded with " + String(status) + ". Payload:\n" + payload);
}
} else {
Serial.println("E: Couldn't get last data age. Couldn't reach server. Code: " + String(status) + ".");
}
http.end();
}
void fetch_daily_temp_average() {
// returns some channel info and rounded daily temperature average in json format
String endpoint = "http://api.thingspeak.com/channels/" + CHANNEL + "/fields/" + TEMPERATURE_FIELD + ".json?average=daily&round=2&timezone=" + TIMEZONE + "&api_key=" + READ_KEY;
http.begin(wifi, endpoint);
int status = http.GET();
Serial.println();
if (status > 0) {
String payload = http.getString();
if (status == 200) {
deserializeJson(jsonDoc, payload);
Serial.println("> Date \t\tAverage Temperature");
for (JsonVariant entry : jsonDoc["feeds"].as<JsonArray>()) {
String day = entry["created_at"];
float avg = entry["field" + TEMPERATURE_FIELD];
Serial.println(" " + day.substring(0, 10) + "\t" + String(avg));
}
jsonDoc.clear();
} else {
Serial.println("E: Couldn't get temperature averages. Server responded with " + String(status) + ". Payload:\n" + payload);
}
} else {
Serial.println("E: Couldn't get temperature averages. Couldn't reach server. Code: " + String(status) + ".");
}
http.end();
}
void setup() {
Serial.begin(115200);
while (!Serial) continue;
Serial.println();
Serial.print("Started. Connecting...");
WiFi.begin(SSID.c_str(), PW.c_str());
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.println(" Connected.");
fetch_information();
fetch_last_temp();
fetch_last_entry();
fetch_last_data_age();
fetch_daily_temp_average();
}
void loop() {
delay(5000);
}