Tuesday, September 8, 2009

Further on the POP3 email checker

Well, since this project has been a bit of a surpirse hit, I thought I would include a few further notes and refinements.

This is a small change to the updateClient function that just flashes the LED rapidly four times to indicate the network is down:


void updateClient() //This function contacts the POP3 server
{
if ((millis() - updateTimer) > 5000)
{
Ethernet.begin(mac, ip);
// Serial.println("connecting...");
delay(1000);
if (client.connect())
{
// Serial.println("connected");
client.println("user Pop.User"); //Insert your usual email login name
client.println("pass YourPassword"); //And your password here
client.println("quit");
client.println();
clientConnected = true;
}
else
{
// Serial.println("connection failed");
// Flash four time rapidly to indicate network down.
for (int x = 0; x < 4; x++){
digitalWrite(ledPin, HIGH);
delay(100);
digitalWrite(ledPin, LOW);
delay(100);
}
}
updateTimer = millis();
}
}


What is odd is that when I have tried this with another LED it blinks very dimly - even when I move around which digital pin the other LED is coming from. Very odd and I still haven't figured out what is causing that.

Another thing to watch for is that this assumes that the number of emails comes through in array position 106 & 107 (I then subtract 48 to make the ASCII code into an integer):


mailNum1 = inString[106] - 48; //Array position 106 contains the first digit
mailNum2 = inString[107] - 48; //Array position 107 contains the 2nd digit if it is available


This, of course, may vary depending on how many characters there are in your POP3 server name and so on. I would recommend starting with the basic commands for getting the POP3 string back:


#include <Ethernet.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192,168,0,172 };
byte server[] = { XXX, XXX, XXX, XXX }; // IP address of your POP3 server

Client client(server, 110);

long updateTimer;
boolean clientConnected = false;

void setup()
{
Serial.begin(9600);
}

void loop()
{
updateClient();
checkAvail();
}

void updateClient()
{
if ((millis() - updateTimer) > 10000)
{
Ethernet.begin(mac, ip);
Serial.println("connecting...");
delay(1000);
if (client.connect())
{
Serial.println("connected");
client.println("user user.name"); //Insert your usual email login name
client.println("pass YourEmailPassword"); //And your password here
client.println("quit");
client.println();
clientConnected = true;
}
else
{
Serial.println("connection failed");
}
updateTimer = millis();
}
}

void checkAvail()
{
if (clientConnected)
{
if (client.available())
{
char c = client.read();
Serial.print(c);
}
if (!client.connected())
{
Serial.println();
Serial.println("disconnecting.");
client.stop();
clientConnected = false;
}
}
}



Then watching the output in the serial window, which will look something like:


connecting...
connected
+OK hello from popgate 2.43 on pop108.xxx.xxx.xxx.xxx.xxx
+OK password required.
+OK maildrop ready, 0 messages (0 octets) (16335883)
+OK server signing off.

disconnecting.


You can then use this output to figure out the right position in the array for mailNum1 & mailNum2.

Hope that helps someone out there. It has been very flattering to see how many folks are interested in building this for themselves. As I explained in the first post, once you have the raw number of emails as an integer you can process with Arduino, you can do all sorts of interesting things beyond just flashing and LED!

Thursday, September 3, 2009

Arduino POP3 Email Checker

Since it turns out people actually occasionally READ this blog, I decided it was time to go back to do an Arduino project and try something different. Since I hadn't done any Arduino work with the Internet before, I decided to try something I thought would be relatively simple - having the Arduino check my email and give me some sort of visual indication of how many emails I have. I started out with:
Both were bought from the good people at Robotshop.ca.




These are just combined with a high intensity LED - which really should have a resistor and will have one eventually!



Here is a quick video - sorry it is a bit murky and the LED is a bit bright!



This was actually probably the hardest Arduino code I ever wrote! For one thing, I hadn't done anything substantial with the Arduino for a while and I found I had forgotten much of what I thought I knew. Also, getting the timing right and getting the number of emails out of the return string actually proved pretty difficult. I made things more difficult for myself by trying to use the String library (formerly TextString), which for some reason didn't return consistent results and was generally not documented and finicky. Then I found the usual LED 13 wouldn't work properly - perhaps because the Ethernet Shield was interfering with it. All-in-all, this small program must have taken me three weeks to write!

I did have a bit of help with the code from Digger450 on the Arduino forum in this exchange, which I am very grateful for!

However, now that it is done, this is a nice little demo of Ardunio on the Internet that does do something at least semi-useful. My next extension may be to hook it up to a servo so that it shows my emails on a physical chart or something. I could also use my SparkFun SerialLCD unit to display the subject lines or something.

Here is the source code:

/*=================================================
Ethernet POP3 Mail Checker & indicator

Checks how many messages are waiting on the POP 3 server
and flashed LED on Pin 9 to indicate number of messages.

It will handle up to 99 messages in the POP3 mailbox.

Uncomment the serial lines for troubleshooting.

Copyright by Chris Armour
3 September 2009
http://opensourceprojects-torchris.blogspot.com/

===================================================*/

#include <Ethernet.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192,168,0,167 }; // IP address you wish to assign to Arduino
byte server[] = { XXX, XXX, XXX, XXX }; // IP address of your POP3 server
char inString[165]; // Number of characters to be collected
int i = 0;
int mailNum1 = 0; // First digit of the email number
int mailNum2 = 0; // Second digit
int mailTotal = 0; // Total # of messsage
char d;
int ledPin = 9;

Client client(server, 110); //The default POP port is 110

long updateTimer;
boolean clientConnected = false;

void setup()
{
//  Serial.begin(9600);
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, LOW);
}

void loop()
{
   
updateClient();
d = checkAvail();
if (d >= 10){
getMailNum();
}

}

/*========================================
        Functions
=========================================*/

void updateClient() //This function contacts the POP3 server
{
if ((millis() - updateTimer) > 5000)
{
 Ethernet.begin(mac, ip);
//    Serial.println("connecting...");
 delay(1000);
 if (client.connect())
 {
//    Serial.println("connected");
 client.println("user Your.Name"); //Insert your usual email login name
 client.println("pass PassWord"); //And your password here
 client.println("quit");
 client.println();
 clientConnected = true;
 }
 else
 {
//    Serial.println("connection failed");
 }
 updateTimer = millis();
}
}

char checkAvail() //This checks if there is data available and returns a char
{
if (clientConnected)
{
 if (client.available())
 {
 char c = client.read();
     return(c);
 }
 if (!client.connected())
 {
//    Serial.println();
//    Serial.println("disconnecting.");
 client.stop();
 clientConnected = false;
 }
}
}

int getMailNum() //This actually loads the char returned by checkAvail() and puts in into an array
{
inString[i] = d;
i++;
if (i == 165){
   i = 0;
       client.flush();
       mailNum1 = inString[106] - 48; //Array position 106 contains the first digit
       mailNum2 = inString[107] - 48; //Array position 107 contains the 2nd digit if it is available
       if ((mailNum2 >= 0) && (mailNum2 <= 9)){ //If mailNum2 is present, then it is a two digit mail count
         mailTotal = (mailNum1 * 10) + mailNum2; //when 2 digits are present, multiply the 1st by 10 then add to mailTotal
//            Serial.print("Total emails:  ");
//            Serial.println(mailTotal);
          blinkLED(); //Run the blink function as many times as there are emails
       }
       else {
         if ((mailNum1 >= 0) && (mailNum1 <= 9)){//if there is only one digit, then that is mailTotal
         mailTotal = mailNum1;
//        Serial.print("Total emails:  ");
//        Serial.println(mailTotal);
         blinkLED(); //Blink the LED
         }
         }
     }
 }

void blinkLED(){ //Blinks the LED for as many times as indicated by mailTotal
         for(int x = mailTotal; x >= 1; x--){
           digitalWrite(ledPin, HIGH);
           delay(200);             
           digitalWrite(ledPin, LOW);
           delay(200);
         }
}