Showing posts with label php. Show all posts
Showing posts with label php. Show all posts

Monday, May 3, 2010

Arduino Email Manager - Part 2 - The Preprocessor

I freely admit that I am not the greatest programmer in the world. Never having been formally trained, my programs tend to be rather loopy and don't include all the error checking they should. This PHP script that I have written is a case in point. It will work with my POP email provider (Rogers in Canada), but it may NOT work with your provider! It seems like there are minor variations in the way some POP servers will respond to the standard commands and these can throw off the script slightly. The best bet is to log into your POP server via telnet and carefully watch the messages back and forth.

Also note that this will support SSL (if you have it set up with your PHP installation) just by putting "ssl:/" in front of the host name and using whatever port number has been assigned - usually 995.You can manually log into an SSL-enabled account using the OpenSSL client available from OpenSSL.org instead of telnet.

At this point, the script does not support Gmail, so don't write to me about that! I have been trying to get it to work and you can definitely log in, but it seems to give inconsistent results and the mail total includes both the inbox and sent folder somehow (which doesn't make sense to me). If anyone out there knows the trick with Gmail, please let me know. I see that there are some PHP classes available for accessing Gmail via IMAP and I will investigate these and post revised code when I can.

So, how does this script work? The script needs to run on a server with the current version of PHP running. This could be a Mac or a Linux/Windows box or it could be running on a remote webserver - assuming you have all the networking and firewall issues dealt with. There is a new project called Yaler that may help with the networking issues if your script is remotely hosted - check it out here. You need to start the script before pressing the "Connect" (or Select) button on the Arduino.

When running, the Preprocessor is a "host" for the requests from the Arduino, but is in turn acting as a "client" to the POP server. It maintains two separate PHP sockets - one to the Arduino and one to the POP server.



The script implements a very simple protocol with the Arduino:

Arduino Sends...
Preprocessor returns...
Arduino connects to IP/portthe ASCII "C"
NCurrent number of emails on the POP server.
S.x (where x is an integer)The from/subject information for email number "x" prefixed with MSG.
D.x (where x is an integer)Deletes email number "x".
EKills the socket and ends session - currently not implemented.

The script also provides the following error messages back (although I am not currently using these on the Arduino):

  • X.1 - Could not open socket to POP server
  • X.2 - Error from server
  • X.3 - Authentication failure
  • X.4 - Bad connection

I tend to prefer one letter protocols with the Arduino since it simplifies the text handling on the Arduino side.

And, without further ado, here is the code...

<?php

/*
*  PHP Pre-processor script for Arduino POP Mail Manager
*
* this is the pre-processor script for use with the Arduino email
* manager described on my blog. Complete description at:
* http://opensourceprojects-torchris.blogspot.com/
*
* This script can be used with SSL enabled POP services by putting
* "ssl:/" infront of the host name. It does NOT currently work with
* GMail POP service.
*
* This code is in the public domain. Please provide credit if it is used
* in another project.
*
* written by Chris Armour, Arpil 30th, 2010
*
*/

//=============================IP, Port, User Info=================//
//Modify to suit your network.

define("HOST_POP", "your.popserver..com");
define("PORT_POP", "110");
define("USER_POP", "user.name");
define("PASS_POP", "YourPassword");
//Server settings
$host_ard = "192.168.0.171"; //This is the IP of the server running the script.
$port_ard = "12345"; //Port number being used by the Arduino


//==========================Functions===================//

//GetMailCount grabs the number of emails in the mailbox using the STAT command
function GetMailCount()
{
$fp_pop = fsockopen (HOST_POP, PORT_POP, $errno, $errstr);
    // if a handle is not returned
    ob_implicit_flush();
    if (!$fp_pop)
        {
        echo("Error: could not open socket connection\n");
        return("X.1");
        }
    else
        {
        // get the welcome message
        $welcome = fgets ($fp_pop, 150);
        // check for success code
        if (substr($welcome, 0, 3) == "+OK")
        {
        // send username and read response
    fputs ($fp_pop, "user " . USER_POP . "\n");
    //fgets($fp_pop, 50);
    // send password and read response
    fputs ($fp_pop, "pass " . PASS_POP . "\n");
    $ack = fgets($fp_pop, 50);
    // check for success code
    if (substr($ack, 0, 3) == "+OK")
        {
        // send status request and read response
        fputs ($fp_pop, "STAT\n");
        $status = fgets($fp_pop, 50);
    if (substr($status, 0, 3) == "+OK")
        {
        // shut down connection
        fputs ($fp_pop, "QUIT\n");
        fclose ($fp_pop);
        }
// error getting status
    else  {
        echo ("Error - server said: $status");
        return("X.2");
        }
        }
    // auth failure
    else  {
        echo ("Error - server said: $ack");
        return("X.3");
        }
        }
        // bad welcome message
    else {
        echo ("Error - bad connection string\n");
        return("X.4");
        }
// get status string
// split by spaces
$arr = explode(" ", $status);
// the second element contains the total number of messages
echo $arr[3] . " messages in mailbox\n";
$GotMail = $arr[3];
return $GotMail;
}
}

//GetFromSubj grabs the content of the email MailNumber then passes this back to the main loop for extraction of the From & subject
//You may need to check the output from your POP3 server using telnet to check on the responses. This seems to vary from POP server to POP
//server.
function GetFromSubj($MailNumber){
$fp_pop = fsockopen (HOST_POP, PORT_POP, $errno, $errstr);
    // if a handle is not returned
    ob_implicit_flush();
    if (!$fp_pop)
        {
        echo("Error: could not open socket connection\n");
        return("X.1");
        }
    else
        {
        // get the welcome message
        $welcome = fgets ($fp_pop, 150);
        // check for success code
        if (substr($welcome, 0, 3) == "+OK")
        {
        // send username and read response
    fputs ($fp_pop, "user " . USER_POP . "\n");
    fgets($fp_pop);
    // send password and read response
    fputs ($fp_pop, "pass " . PASS_POP . "\n");
   $ack = fgets($fp_pop);
    // check for success code
    if (substr($ack, 0, 3) == "+OK")
       {
        // send request for email content & read response

        fputs ($fp_pop, "retr " . $MailNumber . "\n");
        $EmailContent = fread($fp_pop, 4096);
//        echo $EmailContent;
    if (substr($EmailContent, 0, 3) == "+OK")
        {
        // shut down connection
        return $EmailContent;
        fputs ($fp_pop, "QUIT\n");
        fclose ($fp_pop);
        }
// error getting status
    else
        {
        echo ("Error - Server said: $EmailContent");
        return("X.2");
        }
        }
    // auth failure
    else
        {
        echo ("Error - Server said: $ack");
        return("X.3");
        }
        }
        // bad welcome message
    else
        {
        echo ("Error - Bad connection string\n");
        return("X.4");
        }
}
}

//MsgDelete delets message # MailNumber using the dele command
function MsgDelete($MailNumber){

$fp_pop = fsockopen (HOST_POP, PORT_POP, $errno, $errstr);
    // if a handle is not returned
    ob_implicit_flush();
    if (!$fp_pop)
        {
        echo("Error: could not open socket connection\n");
        return("X.1");
        }
    else
        {
        // get the welcome message
        $welcome = fgets ($fp_pop, 150);
        // check for success code
        if (substr($welcome, 0, 3) == "+OK")
        {
        // send username and read response
    fputs ($fp_pop, "user " . USER_POP . "\n");
    fgets($fp_pop);
    // send password and read response
    fputs ($fp_pop, "pass " . PASS_POP . "\n");
   $ack = fgets($fp_pop);
    // check for success code
    if (substr($ack, 0, 3) == "+OK")
       {
        // send delete command

        fputs ($fp_pop, "dele " . $MailNumber . "\n");
        $DeleteAck = fgets($fp_pop);
//        echo $EmailContent;
    if (substr($DeleteAck, 0, 3) == "+OK")
        {
        // shut down connection
        echo ("Message " . $MailNumber . " deleted. \n");
        fputs ($fp_pop, "QUIT\n");
        fclose ($fp_pop);
        }
// error getting status
   else
        {
        echo ("Error - Server said: $EmailContent");
        return ("X.2");
        }
        }
    // auth failure
    else
        {
        echo ("Error - Server said: $ack");
        return("X.3");
        }
        }
        // bad welcome message
    else
        {
        echo ("Error - Bad connection string\n");
        return("X.4");
        }
        }
}

//=====================Create Socket to listen for Arduino======================//

ob_implicit_flush();

//Open socket to listen for Arduino
$socket_ard = socket_create(AF_INET, SOCK_STREAM, 0) or die ("Could not bind to socket\n");
$result_ard = socket_bind($socket_ard, $host_ard, $port_ard) or die("Could not bind to socket\n");

// start listening for connections
$result_ard = socket_listen($socket_ard, 3) or die("Could not set up socket listener\n");
// accept incoming connections
// spawn another socket to handle communication
$spawn = socket_accept($socket_ard) or die("Could not accept incoming connection\n");
// read client input
socket_write($spawn,"C\n");
echo "Device connected.\n";

//=====================Main Socket loop======================//
do {

$input = socket_read($spawn, 2048, PHP_NORMAL_READ) or die("Could not read input\n");

echo $input;

if (trim($input[0]) == "N" || trim($input[0]) == "S" || trim($input[0]) == "D" || trim($input[0]) == "E" || trim($input[0]) == "\r\n") {
//Only do anything if N, S, D or E received.

    if (trim($input) == "N"){
        // This gets the mailcount using the GetMailCount function.
        $MailCount = GetMailCount();
        socket_write($spawn, "Total Number of Messages:" . $MailCount . "@");
        }

    if (trim($input[0]) == "S") {
        //This gets the from/subject info is an S.num is received.
       $MsgNum = explode (".",$input);
       //Use explode to break the info from the Arduino into an array.
        $MsgNumber = $MsgNum[1];
        //Get the Message number from the array.
        echo ("Value of MsgNumber= " . $MsgNumber . "\n");
        $MsgFromSubj = GetFromSubj($MsgNumber);
        //run the function to get the info from the POP server
            if ($MsgFromSubj[0] == "X")
            {
            //If there's an error, write back the server error text.
                socket_write($spawn,$MsgFromSubj);
            }
        else
            {
            $MsgFromLocn = strpos($MsgFromSubj, "From: ");
            $MsgFromName = substr($MsgFromSubj, ($MsgFromLocn + 6), 14);
            print ( "MSG". "F:" . $MsgFromName );
            $MsgSubjLocn = strpos($MsgFromSubj, "Subject: ");
            $MsgSubj = substr($MsgFromSubj, ($MsgSubjLocn + 9), 14);
            echo ("S:" . $MsgSubj );
            usleep(20000);
            socket_write ($spawn,  "MSG" . "F:" . $MsgFromName . "S:" . $MsgSubj . "\n");
            }
        }

    if (trim($input[0]) == "D") {
    //This sends the command to delete an email.
       $MsgNum = explode (".",$input);
        $MsgNumber = $MsgNum[1];
        $MsgDelRet = MsgDelete($MsgNumber);
        if ($MsgDelRet[0] == "X")
            {
                socket_write($spawn,$MsgDelRet ."\n");
            }
        else
            {
        socket_write($spawn, "D." . $MsgNum[1]);
        }
    }

    if (trim($input) == "E"){
  //This isn't actually currently used by the Arduino.
        socket_shutdown($spawn, 2);
        usleep(1000);
        socket_close($spawn);
        socket_shutdown($socket_ard, 2);
        usleep(1000);
        socket_close($socket_ard);
        echo "Sockets terminated\n";
 //       break;
        }
}

} while(true);

?>

Note that this code does not provide good handling of disconnect/reconnect nor can it handle multiple connections simultaneously. In other words, if the Arduino is reset, then the script needs to be restarted. Also, if multiple connection requests are received, it will just die. If anyone can improve on this, please make the suggestions.

Next up will be the Arduino code!

Wednesday, January 28, 2009

Gumstix Arduino Software

I would ask the programmers out there to bear with me! I am a pretty poor coder - probably the result of having two history degrees or being frequently dropped on my head as a child. I tend to not comment my code and I usually work from a single thing that works and just barnacle on elaborations rather than neatly putting things into functions and properly planning my work. I like working in PHP because it has all the ease of C without some of the traps (like handling strings or declaring variables).

So, for my sensor network, the Gumstix Linux box is running PHP 5.0 and the Cherokee web server. This seems to be very robust and I haven't had to reboot it in ages. The main webpage comes up on my internal network like this:


This displays the main info off of the remote sensors and also takes an RSS feed off of www.weatherunderground.com for the current weather in Hamilton, Ontario. This allows me to cross-check the temp readings with the actual weather reported for the area. Note that this still includes a "moisture" reading, but the sensor is now been taken off the system. This was my attempt to detect if it was raining or not based on this circuit from Rob Faludi.

The LED2 On button allows me to control the secondary LED on the remote unit. This is essentially just a way to test remote controlling a digital output over the web and the Zigbee link. When you click the button, it launches a small script that sends out an "h", which turns the light ON. The button will then toggle to the "off" mode and when you press it again it sends an "l" (lower case L) to turn off the LED.

Below is the source code in all it's messy glory. It uses the indispensable "php_serial.class.php" class from Remy Sanchez (found here ) which is absolutely essential to do anything between PHP and your serial port. The script then grabs the Weather Underground RSS feed and generates the HTML to load the web page.

Arduino.php:

<?php
include "php_serial.class.php";

// configure the serial port using php_serial.class.php
 $serial = new phpSerial;
 $serial->deviceSet("/dev/ttyS2");
 $serial->confBaudRate(9600);
 $serial->confParity("none");
 $serial->confCharacterLength(8);
 $serial->confStopBits(1);
 $serial->confFlowControl("none");
 $serial->deviceOpen();

 $serial->sendMessage("g");
 usleep(100000);
 $serial->flush;
 $read = $serial->readPort();
 $ard_array = explode(',',$read,7);

 if (empty($ard_array[6])){
  usleep(100000);
  $serial->sendMessage("g");
  usleep(100000);
  $read = $serial->readPort();
  $ard_array = explode(',',$read,7); 
 }

 if ($ard_array[0] == 1) {
  $plusMinus = "-";
 } elseif ($ard_array[0] == 0){
  $plusMinus = "+";
 }

$weather = 
simplexml_load_file('http://www.weatherunderground.com/auto/rss_full/global/stations/71297.xml?units=both');

echo "<!DOCTYPE html PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'>";
echo "<html>";
echo "<head>";
echo "<meta content='text/html; charset=ISO-8859-1'
 http-equiv='content-type'>";
echo "<meta http-equiv='refresh' content='6'>";
echo "<img style='float: left; width: 81px; height: 90px;' 
src='images/arduino-nano.jpg'>";
echo " <title>Arduino Control</title>";
echo "</head>";
echo "<body>";
echo "<br>";
echo "<h1><span style='font-family: Arial;'>Arduino Control Panel</h1>";
echo "<br></br>";
echo "<table style='text-align: left; width: 50%;' border='1'
 cellpadding='2' cellspacing='2'>";
echo "<tbody>";
echo "<tr>";
echo "<th>Deg C</th>";
echo "<th>Light Level</th>";
echo "<th>LED 1 ON/OFF</th>";
echo "<th>Moisture</th>";
echo "<th>LED 2 ON/OFF</th></tr>";
echo "<tr>";
echo "<td>$plusMinus$ard_array[1]</td>";
echo "<td>$ard_array[2]</td>";
echo "<td>$ard_array[3]</td>";
echo "<td>$ard_array[4]</td>";
echo "<td>$ard_array[5]</td>";
echo "</tr>";
echo "</tbody>";
echo "</table>";
echo "<br>";
echo "<h2><span style='font-family: Arial;'>Current Weather in Hamilton</h2>";
foreach ($weather->channel->item as $item) {
                $w = $item->description . "";
                $newchar = str_replace("|", "", $w);
                $newestchar = str_replace("Temperature","Current temp", $newchar);
                $newest2char = str_replace("°F","F",$newestchar);
                $newest3char = str_replace("°C","C",$newest2char);
                $newest4char = str_replace("percent","%",$newest3char);
                $newest5char = str_replace(" / "," ",$newest4char);
                $newest6char = str_replace("  "," ",$newest5char);
                $newest7char = str_replace("Direction:","Dir:",$newest6char);
                $newerchar = trim($newest7char);
                $wchar = substr($newerchar,0,80);

$wchar = substr($newerchar,0,300);

echo "<table style='text-align: left; width: 50%;' border='1'
 cellpadding='2' cellspacing='2'>";
echo "<tbody>";
echo "<tr>";
echo "<td>$wchar</td>";
echo "</tr>";
echo "</tbody>";
echo "</table>";
                }

echo "<br>";
echo "<a href='arduino_data2.php'>View Log</a><br>";
echo "<br>";
echo "<table>";
echo "<tbody>";
echo "<tr>";
echo "<td>";
if ($ard_array[5] == 1) {

echo "<form action='led_off.php' method='get'>"; 
echo "<input type='hidden' name='variablename' value='variablevalue'>"; 
echo "<input type='submit' value='TURN LED2 OFF'/>";
echo "</form>";
}
if ($ard_array[5] == 0){
echo "</td>";
echo "<td>";
echo "<form action='led_on.php' method='get'>";
echo "<input type='hidden' name='variablename' value='variablevalue'>";
echo "<input type='submit' value='TURN LED2 ON'/>";
echo "</form>";
}
echo "</td>";
echo "</tbody>";
echo "</table>";
echo "<br>";
echo "<hr style='width: 100%; height: 2px;'>";
echo "<br>";
echo "<img style='float: left; width: 81px; height: 90px;' 
src='images/gumlogo.gif'>";
echo "<h1><span style='font-family: Arial;'>Gumstix Controls</h1>";
echo "<br>";
echo "<table>";
echo "<tbody>";
echo "<td>";
echo "<form action='turn_off.php' method='get'>";
echo "<input type='hidden' name='variablename' value='variablevalue'>";
echo "<input type='submit' value='TURN OFF GUMSTIX'/>";
echo "</td><td>";
echo "</form>";
echo "<form action='reboot_gum.php' method='get'>";
echo "<input type='hidden' name='variablename' value='variablevalue'>";
echo "<input type='submit' value='REBOOT GUMSTIX'/>";
echo "</form>";
echo "</td>";
echo "</tbody>";
echo "</table>";
echo "<hr style='width: 100%; height: 2px;'>";
echo "<img src='images/powered_by_cherokee.png'>";
echo "</body>";
echo "</html>";

$serial->deviceClose();

?>


The other function of the Gumstix is also to act as a data logger. Clicking the link for the log takes you to this page:


This is a very small SQLite database that keeps track of the readings of the remote units sensors. The code below uses a PDO statement to open the database and generate the HTML to display its contents. Eventually, I will need to put some further refinements on it so you can select results from different days and maybe graph the temerature.

Arduino_data2.php:

<?php

$db = new PDO('sqlite:/media/card/back_up/home/root/arduino.db');
$st = $db->query('SELECT * FROM tbl');
$results = $st->fetchAll();
echo "<!DOCTYPE html PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'>";
echo "<html>";
echo "<head>";
echo "<meta content='text/html; charset=ISO-8859-1'
 http-equiv='content-type'>";
echo "<meta http-equiv='refresh' content='10' >";
echo " <title>Data Log</title>";
echo "</head>";
echo "<body>";
echo "<h1>Arduino Data Log</h1>";
echo "<br></br>";
echo "<form action='clear_log.php')'>";
echo "<input type='submit' value='Clear Log'/>";
echo "</form>";
echo "<table style='text-align: left; width: 50%;' border='1'
 cellpadding='2' cellspacing='2'>";
echo "<tbody>";
echo "<tr>";
echo "<th>Index</th>";
echo "<th>Date-Time</th>";
echo "<th>Light Level</th>";
echo "<th>LED1</th>";
echo "<th>Moisture</th>";
echo "<th>LED2</th>";
echo "<th>+/-</th>";
echo "<th>Temp</th>";
echo "</tr>";

$rows = count($results);
 
 for ($i=0; $i <= $rows; $i++){
  echo "<tr>";
  for ($x=0; $x <= 7; $x++){
   echo "<td>{$results[$i][$x]}</td>";
  }
  echo "</tr>";
 }
echo "</tbody>";
echo "</table>";
echo "<br>";
echo "<a href='arduino.php'>Return to Control Panel</a><br>";
echo "</body>";
echo "<html>";
$db = null;

?>


How does the data actually get into the database? This is pretty straightforward. Read the serial port with the aforementioned PHP serial class and put the results into an array, then use the SQL INSERT command to put it into the database:

data_logging.php:

<?php
include "php_serial.class.php";

// configure the serial port using php_serial.class.php
   $serial = new phpSerial;
   $serial->deviceSet("/dev/ttyS2");
   $serial->confBaudRate(9600);
   $serial->confParity("none");
   $serial->confCharacterLength(8);
   $serial->confStopBits(1);
   $serial->confFlowControl("none");
   $serial->deviceOpen();

   $serial->sendMessage("g");
   usleep(100000);
   $serial->flush;
   $read = $serial->readPort();
   $ard_array = explode(',',$read,7);
   $serial->deviceClose();
   if ($ard_array[0] == 0){
       $ard_array[0] = "'+'";
       }
   elseif ($ard_array[0] == 1){
       $ard_array[0] = "'-'";
       }
//print_r($ard_array);

putenv("TZ=UTC+5");


$db = new PDO('sqlite:/media/card/back_up/home/root/arduino.db');
$db->exec("INSERT INTO tbl (lightLev,LED1,SW1,LED2,plus_minus,temp)
VALUES
($ard_array[2],$ard_array[3],$ard_array[4],$ard_array[5],$ard_array[0],$ard_array[1])");

Print("Insert successful\n");

?>


This is driven by a crontab item on the Gumstix that runs every 15 minutes. For those out there who might be struggling to figure out crontab on Linux, the way I did this was via the command "crontab -e" and I included the line:

*/15 * * * * /usr/bin/php /var/www/data_logging.php > /dev/null

Well, that should be enough for now on my sensor network project. Soon, I will have to start actually building some of the elements of the solar pool heater concept that started all this. I now have some solenoid valves and a small pump, so I need to do a proptype of an Arduino managing flud control. Maybe I might do something again with RFID first!

Saturday, January 3, 2009

More on the RFID updater

In the spirit of full disclosure, I thought I would describe a bit more of the internals of how the RFID Updater works for those who might be interested.

Here is what it actually looks like in Facebook:


This is generated by three different PHP files.

rfid_test.php - This one actually does the interaction with the serial port on my Gumstix to read the value of the most recent RFID card:


<?php
include "php_serial.class.php";
$tagfile = 'tag.txt';

// configure the serial port using php_serial.class.php
$serial = new phpSerial;
$serial->deviceSet("/dev/ttyS2");
$serial->confBaudRate(9600);
$serial->confParity("none");
$serial->confCharacterLength(8);
$serial->confStopBits(1);
$serial->confFlowControl("none");
$serial->deviceOpen();

while(1){
$rfidTag = $serial->readPort();
if ($rfidTag != NULL) {
$filehandle = fopen($tagfile, "w");
$rfidTagTrim = trim($rfidTag, "\x02..\x03");
$rfidTagShort = substr($rfidTagTrim,7,5);
print("The shortened tag is $rfidTagShort\n");
fwrite($filehandle,$rfidTagShort);
fclose($filehandle);
if (strlen($rfidTagTrim) < 10) {
echo "oops";
}
}
usleep(1500000);
// $serial->flush;
}
?>


This writes the RFID tag number to a small file in the application directory. Note that this references the highly useful "php_serial.class.php" class which can be found at this location. I would be lost without the ability to interact with the serial port!

facebook_rfid.php - This presents the screen shown up above in Facebook and some basic info about me as a user and my last status. Most importantly, it calls up the "iFrame"!


<?php
// Copyright 2008 Chris Armour. All Rights Reserved.
//
// Application: RFID Updater
//
// RFID updater updates your status based on various RFID tokens set
//up in the system.
//

require_once 'facebook.php';

$appapikey = 'XXXXXXXXXXXXXXXXXXX';
$appsecret = 'XXXXXXXXXXXXXXXXXXX';
$facebook = new Facebook($appapikey, $appsecret);
$facebook->require_frame();
$user_id = $facebook->require_login();

echo "<img style='width: 49px; height: 50px; float: left;' alt='' src='http://gumstix.dlinkddns.com/rfid_update/rfid_components_large.gif'>";
echo "<h1> Radio Frequency ID Tag Status Updater</h1>";
echo "<br>";
echo "<br>";
echo "<br>";
echo "<fb:profile-pic uid='$user_id' linked='true' />";
echo "<p>Hello, <fb:name uid='$user_id' useyou='false'/>!</p>";
echo "<p>$user_id</p>";
echo "<p>Current status is: <fb:user-status uid='$user_id' linked='true'/></p>";
echo "<fb:prompt-permission perms='status_update'>Would you like to receive status updates from our application?</fb:prompt-permission>";
echo "<fb:prompt-permission perms='offline_access'>Do you want this application to have offline acceess?</fb:prompt-permission>";
echo "<fb:iframe src='http://gumstix.dlinkddns.com/rfid_update/run_script.php' style= 'width: 99%;height:350px' smartsize='false' frameborder='yes'>";
echo "</fb:iframe>";
?>


The interesting thing to note here is line "$facebook->require_frame();". This was actually MISSING from the sample application provided by Facebook and without it nothing worked! It took a while to figure this out.

run_script.php - Finally, the actual script that changes the darned status! This is what runs inside the "iFrame". Why did I do it this way? Because, the main application PHP script cannot run an auto-refresh. With no refresh, it never bothers to detect the new RFID card!! So, the solution is to have a window running an iFrame (which is basically a window running another web page) that then has an auto-refresh which checks the RFID tag file periodically to see if it has changed. If it changes, then it spits out a new Facebook update.

Here is the script:


<?php
// Copyright 2008 Chris Armour. All Rights Reserved.
//
// Application: This is the script that actually detects the stat change and updates the status.
//
// RFID updater updates your status based on various RFID tokens set
//up in the system.
//

$logfile = 'log.txt';
$tagfile = 'tag.txt';
$filehandle1 = fopen($logfile, "r");
$filehandle2 = fopen($tagfile, "r");
$old_state = fread($filehandle1, filesize($logfile));
$tag_num = fread($filehandle2, filesize($tagfile));
fclose($filehandle1);
fclose($filehandle2);
require_once 'facebook.php';
$appapikey = 'XXXXXXXXXXXXXXXXXXXX';
$appsecret = 'XXXXXXXXXXXXXXXXX';
$facebook = new Facebook($appapikey, $appsecret);


echo "<!DOCTYPE html PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'>";
echo "<html>";
echo "<head>";
echo "<meta content='text/html; charset=ISO-8859-1' http-equiv='content-type'>";
echo "<meta http-equiv='refresh' content='10'>";
echo "</head>";
echo "<body>";
$csv = "588777472";


if ($tag_num == $old_state){
echo "<p>Place an RFID tag near the reader to update your status.<p>";
}
elseif ($tag_num != $old_state){
switch($tag_num){
case "51EAE":
$result = $facebook->api_client->Users_setStatus('is gone for a workout.',false);
echo "<p>Status changed to 51EAE - gone for a workout.</p>";
echo "<p>Return code is = $result</p>";
$result=$facebook->api_client->notifications_sendEmail($csv,"RFID Status now gone for a workout", "RFID Updater has changed your status to Gone for a workout","<b><i><u>RFID Updater has reset status to gone for a workout.</u></i></b>");
break;
case "A503F":
$result = $facebook->api_client->Users_setStatus('is not in the office',false);
echo "<p>Status changed to A503F - not in the office</p>";
echo "<p>Return code is = $result</p>";
$result=$facebook->api_client->notifications_sendEmail($csv,"RFID Status now not in the office", "RFID Updater has reset your status to not in the office","<b><i><u>RFID Updater has reset your status to not in the office.</u></i></b>");
break;
case "12B8F":
$result = $facebook->api_client->Users_setStatus('is at work.',false);
echo "<p>Status changed to 12B8F - at work</p>";
echo "<p>Return code is = $result</p>";
$result=$facebook->api_client->notifications_sendEmail($csv,"RFID Status is at work", "RFID Updater has reset your status to at work","<b><i><u>RFID Updater has reset your status to at work.</u></i></b>");
break;
case "48EEF":
$result = $facebook->api_client->Users_setStatus('is testing the RFID updater',false);
echo "<p>Status changed to 48EEF - testing</p>";
echo "<p>Return code is = $result</p>";
$result=$facebook->api_client->notifications_sendEmail($csv,"RFID Status now Testing", "RFID Updater has reset your status to testing","<b><i><u>RFID Updater has reset your status to testing.</u></i></b>");
break;
case "5BC0C":
$result = $facebook->api_client->Users_setStatus('is watching TV',false);
echo "<p>status changed to 5BC0C - watching TV</p>";
echo "<p>Return code is = $result</p>";
$result=$facebook->api_client->notifications_sendEmail($csv,"RFID Status now watching TV", "RFID Updater has reset your status to watching TV","<b><i><u>RFID Updater has reset your status to watching TV.</u></i></b>");
break;
default:
echo "<p>Card not read. Try again.</p>";
}
}
echo "</body>";
echo "</html>";

$old_state = $tag_num;
$filehandle3 = fopen($logfile, "w");
fwrite($filehandle3,$old_state);
fclose($filehandle3);

?>