Part 7: Python code overview (Optional for those interested in the inner workings of the AlertTube)

High Level Code Overview:

Variable initialization then check for weather alerts the first time followed by starting the fetch timer(default set at 10 min) and then set up and register the interrupts.

Next enter the while loop forever and check for button presses to toggle visual alerts, fetch todays weather and weather alerts or fetch tomorrow’s weather.  If any alerts exist then display them if enabled.  All of this is done in parallel with the main while loop which checks for button presses.

Lower Level Code Overview:

__main__:
Initialize variables, check WeatherAlerts the first time the code is run, start the fetch_timer function, setup_and_register_interrupts then loop forever while  checking for button presses, modifying the LED state as needed and spawning a thread to display_events of the RGB LEDs.  Exit the while loop if a keyboard interrupt is generated(only used when running the script from the command line) and run the shutdown function.

shutdown:
Removes unnecessary files, turns off the LED, stops the fetch timer thread from running.  Future functionality will be to power the system down by pressing and holding a button.  Currently you need to remotely login and type ‘sudo shutdown -h now’ to safely power off the AlertTube

display_events:
Check alert state, if True then adds the LED sequence to the to-do list else if False then remove the RGB LED sequence from the to-do list.  Then cycle through the to-do list and display the RGB LED sequence.  LED options are solid|snooze|blink|die RRR GGG BBB intensity(0-100) RRR|GGG|BBB take values between 0-255

aplay_not_active:
Determine if the aplay command is currently running.  Returns a True if no wav file is playing else returns a false.  This function makes sure we don’t try to play a sound, when one is already being played.

play_todays_forecast:
Play a short beep for the user indicating that the button has been pushed to fetch today’s weather forecast from the Nation Weather Service(USA weather only) and strip out any color escape codes.  The color escape codes are used when this script is run from a command line prompt.  Next, send today’s weather forecast text to a text to speech engine on the web, which converts the text to speech in the form of a .wav file.  Lastly play the wave file with today’s weather forecast.

play_tomorrows_forecast:
Play a short beep for the user indicating that the button has been pushed to fetch tomorrow’s weather forecast from the Nation Weather Service(USA weather only). Next, send tomorrow’s weather forecast text to a text to speech engine on the web, which converts the text to speech in the form of a .wav file.  Lastly play the wave file with tomorrow’s weather forecast.

expand_and_format:
Expand certain abbreviations; remove certain words that weren’t useful to say and rephrase certain things to sound better when the were converted from text to speech.

sunny_tomorrow:
If sunny or clear in the forecast then return True, else False

cloudy_tomorrow:
If cloudy or overcast in the forecast then return True ,else False

snow_tomorrow:
If snow tomorrow and a greater than X% chance of precipitation then return True, else false

rain_tomorrow:
If rain tomorrow and a greater than X% chance of precipitation then return True, else false

fetch_timer:
Call fetch_weather and fetch_mail every CHECK_DELAY minutes.  Currently set to 600 sec = 10 minutes.

fetch_weather:
Try to fetch the temp, current conditions and today’s weather forecast from the web, if not then wait  30 seconds and try again.  If there’s a new weather alert then play the alert sound.  If it’s before 18:00 hours then save the forecast for today, otherwise if it’s after 18:00 hours then save the forecast for tonight.

fetch_mail:
Try to check emails X(currently set to 1) number of days back(i.e. today) and from action@ifttt.com.  If the email matches a Personal Recipe number then find the interesting part of the email alert and save it.  Once that has been done delete the email, so we don’t have to worry about processing it ever again.  As the code is currently written Personal Recipe 3430936 is matched, which means that we know this alert is a Stock Alert, so we save the interesting part of the email and convert it from text to speech and then play it.  The same goes for Personal Recipe 3439586, if we match that Personal Recipe number then we know that the email is a calendar alert, so we set calendar_alert to True, which will result in a blue flashing RGB LED alert until the next time the mail is fetched again, which is 10 minutes by default.  If we aren’t able to check emails then wait 30 seconds and try again.

weather_alert:
Try to fetch alerts from the National Weather Service (USA only).  If we’re not able to then try again in 30 seconds.  If the alert is severe then return true else false, or if the alert is major then return true else false, or if the alert is moderate then return true else false, or if the alert is minor then return true else false.

off_LED:
Turn off all LEDs via the ws2801 module of pigredients, which controls the SPI bus.

snooze_LED:
Display a growing and shrinking RGB LED sequence via the ws2801 module of pigredients, which controls the SPI bus.  This is similar to the LED effect on Apple laptops when they’re sleeping.

blink_LED:
Display a blinking RGB LED sequence via the ws2801 module of pigredients, which controls the SPI bus.

flicker_LED:
Display a random flickering RGB LED sequence via the ws2801 module of pigredients, which controls the SPI bus.

solid_LED:
Display a solid RGB LED sequence via the ws2801 module of pigredients, which controls the SPI bus.

read_GPIO:
Try to read the state of GPIO4, GPIO23, and GPIO24.  If we get an error, wait a quarter second and try again.

setup_and_register_interrupts:
GPIO export Raspberry Pi P1 pins 7, 16, 18, and 22 for GPIO.  Setup GPIO pins by setting the direction to in with a rising edge.  Lastly create a polling object and register GPIO pins.

Part 8: Next Steps and Future Enhancements

Next Steps:

I would encourage you to make a backup of your working code and start experimenting with it.  You can create a new IFTTT alert and do the following on the AlertTube.py side:

Create New Alert in AlertsTube.py:

1. Initialize a global variable name to False in __main__
2. Create the search criteria in def fetch_mail() and set global variable name to True
3. Add the below similar code to def check_and_color_code_events()
New Alert Code

Test Your Alerts:

You can view screen output of AlertsTube.py, for debugging purposes, by doing the following:
1. Kill the version of AlertsTube.py that runs at startup by typing: sudo pkill AlertsTube.py
2. Open a new terminal window and type: cd ./AlertsTube then sudo ./AlertsTube.py

Future Enhancements

* Provide a ‘Quiet Time’ feature, so that visual alerts are not displayed during certain hours (i.e. bed time)
* Add flickering to red LED when there’s a weather or mail connection fault
* Push and hold a button to initiate a software shutdown to turn off the AlertTube
* Modify the steel enclosure, so power cord and WiFi are in the back. Initially, I had planned for the power cord, buttons, and LED to be in the back, but after using it for a while, I like the look of the buttons and the LED, so I’m going to make another enclosure, where those are in the front and the power cord and WiFi dongle are in the back.

Thank Yous

* A big thank you to Jeff Keyzer for his WiFi Radio, which inspired me to document and share this project.

* A big thank you to Zeb Palmer for his work on WeatherAlerts. He went out of his way to rewrite sections of the code for me, which made this project possible.