Get Any Reddit Post using ESP32

Reddit's API has been piquing my curiosity for some time. However, my past experiences with APIs, especially with Twitter and Facebook have left a bad taste in my mouth. Then one day I had the courage to try it again using ESP32 and to my surprise, it's far easier than it looks!

You can acquire data from subreddits without needing to authenticate. A simple GET request, for example, to get the top posts from r/jokes would only require this URL:

https://www.reddit.com/r/jokes/top.json?

Copy-pasting that URL to your web browser would show JSON data that looks like this:

With this, you can then use ArduinoJSON to extract any data you want from a specific subreddit!

For a full rundown of Reddit's API, see Reddit API Docs 

For this project, I will be extracting the top post for today from a subreddit and have that displayed on a 20x4 LCD. This means I'm limited to subreddits with text posts like r/jokes, r/showerthoughts, r/askreddit, etc.

Factoring in the average post length and usefulness, I decided on r/showerthoughts.

Step 1: Getting the Target Data

Since I only need the top post in a day, I use this URL to filter the results:

https://www.reddit.com/r/showerthoughts/top.json?limit=1&t=day

This will give me filtered results, but it's still a lot of data. Thankfully, the ArduinoJSON assistant can help in extracting the only data I need, which is in this case, the post title.

Go to https://arduinojson.org/v6/assistant/. The first step requires you to select the processor, mode, and input type. I am using an ESP32, I need to decode JSON and the data is coming from a stream, hence the field values below:

The next step is to paste the JSON data:


You can also click the "Prettify" button to have a clearer view of the nodes.

The next step is about the size needed to hold the JSON data:

Since the ESP32 has memory enough to hold the JSON data, there's no warning here. But if your JSON data exceeds that of what your processor is capable of, you'll see something like this:

This is something to keep in mind when handling large JSON data.

Finally, the assistant will give you an example program for processing the data. The program is quite long so I will just point out the things that relate to my project requirement. If you look back at the JSON data, the title of the Reddit post is under a couple of nodes:

{
  "kind": "Listing",
  "data": {
    "after": "t3_r4sx4e",
    "dist": 1,
    "modhash": "ro4zfp0ks461a5e0b7f9b2f294189d5a3bd9e8a9a45c64a792",
    "geo_filter": "",
    "children": [
      {
        "kind": "t3",
        "data": {
          "approved_at_utc": null,
          "subreddit": "Showerthoughts",
          "selftext": "",
          "author_fullname": "t2_dq6lvrft",
          "saved": false,
          "mod_reason_title": null,
          "gilded": 1,
          "clicked": false,
          "title": "If reincarnation was real, there would probably be a lot more support for those born into poverty or hardship.",
          "link_flair_richtext": [],
...

The root objects are "kind" and "data". Under "data", there's an object called "children" and under that is another "data" field.  You'll then see the "title" under that second "data".

Step 2. Writing the ESP32 Code

Link to source code

External libraries:

Built-in libraries:

  • HTTPClient
  • WiFi
  • Wire

Obviously, the ESP32 needs to be connected to the Internet first. The following lines of code do that:

WiFi.mode(WIFI_STA);
  
Serial.println("Starting WiFi Station...");

WiFi.begin(ssid, password);

int retrycon = 50;

while (WiFi.status() != WL_CONNECTED)
{  
  Serial.println("Connecting...");
  delay(500);
  if (--retrycon == 0)
  {
    Serial.println("RESTART");
    ESP.restart();
  }
  Serial.print(".");
}

Serial.print("WiFi connected with IP: ");

Next, an instance of the HTTPClient library and the API URL is declared:

HTTPClient http_reddit;
String reddit_json = "";
String reddit_server = "https://www.reddit.com/r/showerthoughts/top.json?limit=1&t=day";

To acquire the JSON data, a GET request function is used:

http_reddit.begin(reddit_server);
int resp = http_reddit.GET();
if(resp > 0){
   reddit_json = http_reddit.getString();
}else{
  Serial.println("Cannot get reddit post");
  return "";
}
http_reddit.end();

The raw JSON data will then be inside the string variable reddit_json.

Before calling setup(), a JSON document object is declared with size as suggested by the ArduinoJSON assistant:

DynamicJsonDocument doc(16384);

This object will house the deserialized data from the raw JSON:

deserializeJson(doc, reddit_json);

Next is to filter our data. To get only the items under the first "data" object, we use this filter:

JsonObject data = doc["data"];

Then, we acquire only the "data" object under the "children" object. Note that the "children" is an array. To get only the first post, we specify the index as 0:

JsonObject data_children_0_data = data["children"][0]["data"];

Finally, to get the title of the post, we use this filter:

const char* data_children_0_data_title = data_children_0_data["title"];

The full code found in this repository allows you to choose your own subreddit and filter type. Just look for the #defines's near the top of the code and change that:

// other possible filters: month, year, week, hour
#define FILTER "day"
// the subreddit where we want to get data
#define SUBREDDIT "showerthoughts"

Step 3: Wire the LCD

For this project, I am using a 20 x 4 LCD (I2C) to fit more characters. Sometimes, however, this is still not enough as some r/showerthoughts posts can be more than 80 characters long. You could opt for a graphic LCD if your target is to handle more characters.

A non-I2C LCD wiring is provided as the featured image.

Step 4: Upload the Code

With the circuit in place, the final step is to upload the code.

Now, the code in the repository should be able to get the top post for the day from /r/showerthoughts. There's no method yet to acquire new data: to do that, you need to reset the ESP32. If you want to make your project get a post, say every 24 hours, you can add this inside the loop function:

if(millis() - timer >= 86400000)
{
    ESP.restart();
}

This will restart the ESP32 after 86400000 milliseconds, equivalent to 24 hours.

Oh, and don't forget to add this before setup():

long timer = millis();

I hope you find this tutorial helpful!

Leave a Reply

Your email address will not be published. Required fields are marked *