Text Editor

Adafruit recommends using the Mu editor for editing your CircuitPython code. You can get more info in this guide.

Alternatively, you can use any text editor that saves simple text files.

Download the Project Bundle

Once you've finished setting up your Feather TFT ESP32-S2 Express with CircuitPython, you can access the code and necessary libraries by downloading the Project Bundle.

To do this, click on the Download Project Bundle button in the window below. It will download as a zipped folder.

# SPDX-FileCopyrightText: 2022 Liz Clark for Adafruit Industries
#
# SPDX-License-Identifier: MIT

import time
import ssl
import wifi
import terminalio
import socketpool
import displayio
import board
from adafruit_display_text import bitmap_label,  wrap_text_to_lines
import adafruit_requests
from digitalio import DigitalInOut, Direction, Pull
from adafruit_debouncer import Debouncer

alarm_out = DigitalInOut(board.A1)
alarm_out.direction = Direction.OUTPUT
alarm_out.value = False

button_in = DigitalInOut(board.BUTTON)  # on-board Boot button on Feather ESP32-S2 TFT
button_in.pull = Pull.UP
button = Debouncer(button_in)


# Get wifi details and more from a secrets.py file
try:
    from secrets import secrets
except ImportError:
    print("WiFi secrets are kept in secrets.py, please add them there!")
    raise

print("Adafruit Raspberry Pi In Stock Tweet Listener")

#  import your bearer token
bear = secrets['bearer_token']

#  query URL for tweets. looking for hashtag partyparrot sent to a specific username
#  disabling line-too-long because queries for tweet_query & TIME_URL cannot have line breaks
#  pylint: disable=line-too-long
tweet_query = 'https://api.twitter.com/2/tweets/search/recent?query=In Stock at Adafruit from:rpilocator&tweet.fields=created_at'

headers = {'Authorization': 'Bearer ' + bear}

print("Connecting to %s"%secrets["ssid"])
wifi.radio.connect(secrets["ssid"], secrets["password"])
print("Connected to %s!"%secrets["ssid"])
print("My IP address is", wifi.radio.ipv4_address)

pool = socketpool.SocketPool(wifi.radio)
requests = adafruit_requests.Session(pool, ssl.create_default_context())

#  gets and formats time from adafruit.io
aio_username = secrets["aio_username"]
aio_key = secrets["aio_key"]
location = secrets.get("timezone", None)
TIME_URL = "https://io.adafruit.com/api/v2/%s/integrations/time/strftime?x-aio-key=%s" % (aio_username, aio_key)
TIME_URL += "&fmt=%25Y-%25m-%25dT%25H%3A%25M%3A%25S.%25L%25j%25u%25z%25Z"

display = board.DISPLAY

group = displayio.Group()
font = terminalio.FONT
text = ''
text_area = bitmap_label.Label(font, text=text, scale=2, color=0xFFFFFF)
text_area.x = 0
text_area.y = 15
clock = ''
clock_area = bitmap_label.Label(font, text=clock, color=0xFFFFFF)
clock_area.x = 125
clock_area.y = 128
group.append(text_area)
group.append(clock_area)
display.show(group)

last_value = 0 #  checks last tweet's ID
check = 0 #  time.monotonic() holder

#  fetching current time
print("Fetching text from", TIME_URL)
current_time = requests.get(TIME_URL)
print("-" * 40)
print(current_time.text)
print("-" * 40)

alarm_out.value = False  # this starts the alarm so you can test turning it off w the boot button


while True:
    button.update()
    if button.fell:
        print("Alarm off")
        alarm_out.value = False

    #  every 30 seconds...
    if (check + 30) < time.monotonic():
        #  updates current time
        current_time = requests.get(TIME_URL)
        print(current_time.text)
        #  get tweets from rpilocator containing in stock at adafruit
        the_tweet = requests.request("GET", url=tweet_query, headers=headers)
        #  gets data portion of json
        data = the_tweet.json()['data']
        #  tweet ID number
        value = data[0]['id']
        #  tweet text
        stock_check = data[0]['text']
        #  timestamp
        timestamp = data[0]['created_at']
        #  reset time count
        check = time.monotonic()
        #  compare last tweet ID and current tweet ID
        if last_value != value:
            #  compares date of tweet timestamp with current date
            if timestamp.startswith(current_time.text[0 : 10]):
                print("match")
                #  grabs the hour of the tweet timestamp
                tweet_hour = int(timestamp[11:13])
                print(tweet_hour)
                #  grabs the current hour
                current_hour = int(current_time.text[11:13])
                print(current_hour)
                #  if it's been less than an hour since the tweet...
                if abs(current_hour - tweet_hour) < 1:
                    print("in the last hour")
                    #  displays tweet text and time on screen
                    text_area.text = "\n".join(wrap_text_to_lines(stock_check, 21))
                    print(stock_check)
                    clock_area.text = timestamp
                    print("Raspberry Pi in stock at Adafruit!")
                    alarm_out.value = True

                else:
                    #  if it's not new, then the wait continues
                    no_tweet_text = ("No stock in last hour :( Last stock: %s" % (timestamp))
                    text_area.text = "\n".join(wrap_text_to_lines(no_tweet_text, 21))
                    print("no new in stock notifications :(")
            #  updates tweet ID
            last_value = value
        #  if the tweet wasn't today
        else:
            #  if it's not new, then the wait continues
            no_tweet_text = ("No stock in last hour :( Last stock: %s" % (timestamp))
            text_area.text = "\n".join(wrap_text_to_lines(no_tweet_text, 21))
            print("no new in stock notifications :(")

Upload the Code and Libraries to the Feather TFT ESP32-S2

After downloading the Project Bundle, plug your Feather TFT ESP32-S2 into the computer's USB port with a known good USB data+power cable. You should see a new flash drive appear in the computer's File Explorer or Finder (depending on your operating system) called CIRCUITPY. Unzip the folder and copy the following items to the Feather M4 Express' CIRCUITPY drive. 

  • lib folder
  • code.py

Your Feather TFT ESP32-S2 CIRCUITPY drive should look like this after copying the lib folder and the code.py file.

circuitpy

How the CircuitPython Code Works

The code has a query that is sent through the Twitter API to check if a tweet that contains the text "In Stock at Adafruit" has been sent from the account @rpilocator. You can customize this query to look for other text or to look at tweets from a different account.

tweet_query = 'https://api.twitter.com/2/tweets/search/recent?query=In Stock at Adafruit from:rpilocator&tweet.fields=created_at'

In the loop, a request is sent every 30 seconds to check the current time and to send the tweet query. The response from Twitter is parsed into a JSON feed stored in data. The feed is sliced to see the tweet ID, tweet text and the tweet timestamp.

The tweet ID is compared to the last tweet ID that was stored in last_value. If they don't match, that means a new tweet has been received that matches the query. The tweet's timestamp is compared against the current time. If the tweet was sent in the last hour, then the alarm goes off and the text on the TFT display is updated.

#  every 30 seconds...
    if (check + 30) < time.monotonic():
        #  updates current time
        current_time = requests.get(TIME_URL)
        print(current_time.text)
        #  get tweets from rpilocator containing in stock at adafruit
        the_tweet = requests.request("GET", url=tweet_query, headers=headers)
        #  gets data portion of json
        data = the_tweet.json()['data']
        #  tweet ID number
        value = data[0]['id']
        #  tweet text
        stock_check = data[0]['text']
        #  timestamp
        timestamp = data[0]['created_at']
        #  reset time count
        check = time.monotonic()
        #  compare last tweet ID and current tweet ID
        if last_value != value:
            #  compares date of tweet timestamp with current date
            if timestamp.startswith(current_time.text[0 : 10]):
                print("match")
                #  grabs the hour of the tweet timestamp
                tweet_hour = int(timestamp[11:12])
                print(tweet_hour)
                #  grabs the current hour
                current_hour = int(current_time.text[11:12])
                print(current_hour)
                #  if it's been less than an hour since the tweet...
                if abs(current_hour - tweet_hour) < 2:
                    print("in the last hour")
                    #  displays tweet text and time on screen
                    text_area.text = "\n".join(wrap_text_to_lines(stock_check, 21))
                    print(stock_check)
                    clock_area.text = timestamp
                    print("Raspberry Pi in stock at Adafruit!")
                    alarm_out.value = True

This guide was first published on May 11, 2022. It was last updated on May 11, 2022.

This page (Code the RPi Stock Alarm) was last updated on May 19, 2022.

Text editor powered by tinymce.