GMail Notifier on an Arduino
Equipment
- A computer with an internet connection
- Python
- pySerial
- Arduino ( I'm using Duemilanove )
- Red LED
- Pushbutton (optional)
- Wires
On the computer
A python script will run continuously on the computer, and fetch the Gmail RSS feed every few minutes. pySerial will be used to notify the Arduino of new mails.Here are our imports and constants
# ~ Gmail Notifier for Arduino
# ~ This file is released under the public domain
import httplib
import getpass
import base64
import re
import time
import serial
INTERVAL = 5 # check every INTERVAL minutes
serv = 'mail.google.com'
path = '/mail/feed/atom'
# ask user name and password and encode them for authentication
auth = base64.encodestring(
'%s:%s'%(raw_input('Username: '),
getpass.getpass()))
So first, fetching the feed. We'll use httplib. Here is the code:
def getfeed():
print 'Checking...'
conn = httplib.HTTPSConnection(serv)
conn.putrequest('GET', path)
conn.putheader('Authorization', 'Basic %s'%auth)
conn.endheaders()
return conn.getresponse().read()
Next lets get the count. Gmail replies in the following format. In the case of new mails there is more information, but we don't care about that. We're mainly interested in fullcount.
<?xml version="1.0" encoding="UTF-8"?>
<feed version="0.3" xmlns="http://purl.org/atom/ns#">
<title>Gmail - Inbox for nsm.nikhil@gmail.com</title>
<tagline>New messages in your Gmail Inbox</tagline>
<fullcount>0</fullcount>
<link rel="alternate" href="http://mail.google.com/mail" type="text/html" />
<modified>2009-02-22T11:00:33Z</modified>
</feed>
So we'll use regular expressions to get the count.
def count(data):
matches = re.findall('<fullcount>([0-9]+)</fullcount>', data)
if len(matches) == 0:
print 'Error in parsing feed, check user name and password are correct'
return 0
return int(matches[0])
We'll need to write this to the serial port.
def writeSer(data):
try:
# the best way to find this out is to launch the Arduino environment
# and see what it says under Tools -> Serial Port
ser = serial.Serial('/dev/ttyUSB0')
ser.write(data)
except serial.serialutil.SerialException:
print 'Error writing to serial device'
raise
Now that we're done with the functions, it's time to make them work together
# subtract so that we check first time
last_check = time.time() - INTERVAL*60
while True:
if time.time() - last_check < INTERVAL*60:
continue
last_check = time.time()
msgs = count(getfeed())
print msgs,'mails'
writeSer(str(msgs))
Thats the computer part.
On the Arduino
The circuit :
The LED is on pin 13 and goes to ground. The button takes 5V through the power pins on the analog side, via a 220 ohm resistor. The other leg is grounded. Pin 4 can be used to read the state of the button. The wire from pin 4 connects to the 5V leg of the button.
The code is dead simple and so is presented together.
int ledPin = 13; // connect led to digital pin 13, or use default small one
int bPin = 4; // connect button to digital pin 4
boolean blink = false; // holds our current state
int INTERVAL = 200; // led blink rate in milliseconds
void setup() {
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
}
void loop() {
if(Serial.available() > 0)
blink = Serial.read() > 48;// 48 is 0 is ASCII
if(digitalRead(bPin) == LOW) // button pressed
blink = false;
// blink is true if we got serial input
// or we had got serial input and button hasn't been pressed yet.
if(blink) {
digitalWrite(ledPin, HIGH);
delay(INTERVAL);
digitalWrite(ledPin, LOW);
delay(INTERVAL);
}
else
digitalWrite(ledPin, LOW);
}
The button is used to switch off the blinking once you've noticed that you've got mail and don't want it to keep blinking till the next check.
Running
Verify and Upload the code to the Arduino. You can try entering numbers in the Serial Monitor to check that the circuit works. Remember to switch off the Serial Monitor.Now start your script, python mailarduino.py. Enter authentication details. Now sit back and relax... oh wait, you've got mail.
Full python script ( mailarduino.py )
import httplib
import getpass
import base64
import re
import time
import serial
INTERVAL = 5 # check every INTERVAL minutes
serv = 'mail.google.com'
path = '/mail/feed/atom'
auth = base64.encodestring(
'%s:%s'%(raw_input('Username: '),
getpass.getpass()))
def count(data):
matches = re.findall('<fullcount>([0-9]+)</fullcount>', data)
if len(matches) == 0:
print 'Error in parsing feed, check user name and password are correct'
return 0
return int(matches[0])
def getfeed():
print 'Checking...'
conn = httplib.HTTPSConnection(serv)
conn.putrequest('GET', path)
conn.putheader('Authorization', 'Basic %s'%auth)
conn.endheaders()
return conn.getresponse().read()
def writeSer(data):
try:
ser = serial.Serial('/dev/ttyUSB0')
ser.write(data)
except serial.serialutil.SerialException:
print 'Error writing to serial device'
raise
last_check = time.time() - INTERVAL*60 # subtract so that we check first time
while True:
if time.time() - last_check < INTERVAL*60:
continue
last_check = time.time()
msgs = count(getfeed())
print msgs,'mails'
writeSer(str(msgs))