It could be cool to make a Raspberry Pi close my garage door remotely if I forget it open or even have it tell me if the door was forgotten open to begin with. There are lots of ways to communicate with a Raspberry Pi, but email is ubiquitous and bullet proof. It seems like a great way to command my Raspberry Pi to do my bidding.
Wanting this ability is one of the reasons I wrote the popfind utility. popfind can run on Raspberry Pi and search a POP server’s mailbox looking for messages with commands it can perform.
To demo this idea, I connected a Cobbler Pi to my Raspberry Pi. I then connected an LED to pin 25 like I did way back when I was first learning to interface hardware to the Pi.
I echoed 0 and 1 to the gpio pin as described in the link above to make sure everything was working properly.
My plan was to send an email with the subject line of “led:”. That would be the indication to the Raspberry Pi it was to act. Then after “led:”, I would indicate what I want done such as “led:on”, “led:off”, and “led:status”.
The following linux bash script implements that idea:
#!/bin/bash # Script to look for email messages with subject line of # led:on, led:off, or led:status #infinite loop reading and responding to messages okdelete=0 fname="" while true; do if [[ $okdelete == 1 ]]; then printf "deleting msg %s\n" $uid popfind -c gmail.cfg -d $uid okdelete=0 fi if [[ $fname != "" ]]; then rm $fname fname="" fi printf "Scanning for new message\n" # Are there any new messsages with "led:" in the subject line? uid=$(popfind -c gmail.cfg -s "led:" 2>/dev/null) if [[ $? == 0 ]]; then # yes, so set up to read the message to a file, $fname printf "UID=%s\n" $uid fname=/tmp/popfind$RANDOM popfind -c gmail.cfg -v $uid > $fname # search the file for the string "led:on" grep -iq "led:on" $fname if [[ $? == 0 ]]; then # Found it, so turn the led on printf "turn led on\n" sudo sh -c 'echo 1 > /sys/class/gpio/gpio25/value' okdelete=1 continue # go back to top of loop fi # search the file for the string "led:off" grep -iq "led:off" $fname if [[ $? == 0 ]]; then # found it, so turn the led off printf "turn led off\n" sudo sh -c 'echo 0 > /sys/class/gpio/gpio25/value' okdelete=1 continue # go back to top of loop fi # search the file for the string "led:status" grep -iq "led:status" $fname if [[ $? == 0 ]]; then # found it, so email led status (replying to the actual sendor # is an exercise left for the reader ;-) ) printf "return status\n" # put the status of the led into $x x=$(sudo sh -c 'cat /sys/class/gpio/gpio25/value') if [[ $x == 0 ]]; then msg="LED Status is OFF" else msg="LED Status is ON" fi echo "$msg" | mail -s "$msg" firstname.lastname@example.org okdelete=1 continue fi rm $fname if [[ $okdelete == 1 ]]; then printf "deleting msg\n" popfind -c gmail.cfg -d $uid fi fi printf "Waiting...\n" sleep 10s done
As far as Linux scripts go, this one is pretty straight forward. I implement an infinite while loop, constantly scanning for commands and then parsing and executing them when I find them.
In this demo, I wait only 10 seconds between scans. That’s OK for testing, but in reality that should be no less than one minute and 5 is probably a lot better. Scanning the POP server for email is not very efficient, especially if there are a lot of messages in the mailbox on the server.
I use popfind to scan the mail for “led” in the subject line. Note that I use 2>/dev/null to get rid of any popfind diagnostic messages. In this case, I don’t want them.
If popfind returns a status code of 0, then a message was found and I need to parse it.
To parse it, I read the entire message into a disk file, named $fname (which is a random temporary filename). I use grep to scan the file for “led:on”, “led:off”, and “led:status”.
If I find on or off, then I simply set the GPIO pin to the appropriate value to turn the LED on or off.
If I find status, I copy the status into $x. Then based on the value of $x, I create the appropriate respond string.
Finally the response string is emailed to a fixed email address. One could parse the flat file for the from address, and make sure that is used as the To address, but that was overkill for this simple example.
Here is a short-ish video of the script in operation (note that after I did the video, I cleaned the script up some so the output of the script in the video doesn’t match the actual script exactly).