Sergei Bobyr / Mbed 2 deprecated RFID_CatDoor

Dependencies:   EthernetNetIf TextLCD mbed HTTPServer ID12RFID

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 // RFID Cat Door Project
00002 // The code runs on mbed and implements RFID Cat Door system. System comprises 3 sensors (RFID Reader, Proximity sensor, Reed sensor)
00003 // and 1 actuator (Solenoid door lock). System operates either in offline or online mode (if IP address is acquired). In online mode
00004 // a web page is created describing system's state. A lockdown override is available in online mode locking down the system.
00005 // The system is controlled by a state machine and provides RFID-based entry control. Exit is allowed without authorization.
00006 
00007 //#define NO_HW // uncomment if there's no HW attached to mbed
00008 
00009 #include "mbed.h"                   // mbed library
00010 #include "ID12RFID.h"               // ID12 RFID Reader library
00011 #include "TextLCD.h"                // OrangeBoard LCD library
00012 #include "EthernetNetIf.h"          // Ethernet library
00013 #include "HTTPServer.h"             // HTTP Server library
00014 #include "HTTPRequestHandler.h"     // HTTP Request Handler library
00015 #include <string>
00016 
00017 EthernetNetIf eth;
00018 HTTPServer svr;
00019 class CatDoorHandler;
00020 
00021 // State Machine Events
00022 enum Event { DoorOpenEvent, DoorClosedEvent, ProximityEvent, AuthTagReadEvent, DoorUnlockedTimeoutEvent, None };
00023 string eventNames[] = { "DoorOpen", "DoorClosed", "Proximity", "AuthTagRead", "DoorUnlockedTimeout", "None" };
00024 Event event = None;
00025 
00026 // State Machine States
00027 enum State { DoorLockedClosed, DoorUnlockedClosed, DoorUnlockedOpen };
00028 string stateNames[] = { "Door Locked & Closed", "Door Unlocked & Closed", "Door Unlocked & Open" };
00029 State state = DoorLockedClosed;
00030 
00031 bool bLockdown = false; // variable indicating a lockdown from the web page
00032 
00033 // Cat's possible locations
00034 enum Location { Inside, Outside, Unknown };
00035 string locationNames[] = { "Inside", "Outside", "Unknown" };
00036 
00037 // Each cat has tag, name, and location
00038 struct cat { int tag; string name; Location location; };
00039 // List of authorized cats
00040 cat cats[] = {
00041     5454121, "Yellow", Unknown,
00042     //9733970, "Blue", Unknown,
00043     //463733, "Red", Unknown
00044 };
00045 int catsN = sizeof(cats)/sizeof(cat);
00046 int catId = 0; // current cat ID
00047 
00048 TextLCD lcd(p24, p26, p27, p28, p29, p30);  // OrangeBoard LCD
00049 ID12RFID rfid(p14);                         // uart rx for ID12 RFID reader
00050 DigitalIn _door_open(p17);                  // reed sensor, 0 indicates door open
00051 DigitalIn _proximity(p16);                  // proximity sensor, 0 indicates an object within 10 cm
00052 DigitalOut unlock_door(p21);                // solenoid, 1 will unlock the door
00053 
00054 DigitalOut door_unlocked_led(LED1);         // ON when door is unlocked
00055 DigitalOut door_open_led(LED2);             // ON when door is open
00056 DigitalOut proximity_led(LED3);             // ON when proximity sensor is triggered
00057 PwmOut rfid_read_led(LED4);                 // DIM = unauthorized tag read; BRIGHT = authorized tag read
00058 
00059 const float LED_DIM = 0.05;
00060 const float LED_BRIGHT = 1;
00061 
00062 // Authorized RFID Tag Read Event
00063 Timer tagReadTimer;
00064 bool IsAuthTagReadEvent() {
00065     if(rfid.readable()) {
00066         int tag = rfid.read();  // read the tag
00067         tagReadTimer.reset();
00068         tagReadTimer.start();   // start 5 sec timer
00069         
00070         lcd.cls(); lcd.locate(0, 0); lcd.printf("Tag: %08d", tag);
00071         for (int i = 0; i < catsN; ++i) { // find if tag is authorized
00072             if (cats[i].tag == tag) {
00073                 catId = i;
00074                 lcd.locate(0, 1); lcd.printf("Cat: %s", cats[i].name.c_str());
00075                 rfid_read_led = LED_BRIGHT;
00076                 return true;
00077             }
00078         }
00079         
00080         lcd.locate(0, 1); lcd.printf("Cat: Unknown"); // unknown tag
00081         rfid_read_led = LED_DIM;
00082     }
00083     if (tagReadTimer.read() > 5.0) { // each tag is shown for 5 sec
00084         tagReadTimer.stop();
00085         tagReadTimer.reset();
00086         rfid_read_led = 0;
00087         lcd.cls();
00088     }
00089     return false;
00090 }
00091 
00092 // Proximity Event
00093 bool IsProximityEvent() {
00094     bool result = false;
00095     static bool wasProximity = false;       // last state
00096     bool bProximity = !_proximity.read();   // 0 indicates an object within 10 cm
00097     proximity_led = bProximity;
00098     if (bProximity & !wasProximity)         // create event on transition only
00099         result = true;
00100     wasProximity = bProximity;
00101     return result;
00102 }
00103 
00104 // Door Open Event
00105 bool IsDoorOpenEvent() {
00106     bool result = false;
00107     static bool wasOpen = false;            // last state
00108     bool bDoorOpen = !_door_open.read();    // 0 indicates door open
00109     door_open_led = bDoorOpen;
00110     if (bDoorOpen & !wasOpen)               // create event on transition only
00111         result = true;
00112     wasOpen = bDoorOpen;
00113     return result;
00114 }
00115 
00116 // Door Closed Event
00117 Timer doorClosedTimer;
00118 bool IsDoorClosedEvent() {
00119     bool result = false;
00120     static bool wasClosed = true;           // last state
00121     bool bDoorClosed = _door_open.read();
00122     if (bDoorClosed & !wasClosed) {         // start timer when door closes
00123         doorClosedTimer.reset();
00124         doorClosedTimer.start();
00125     }
00126     // event is only created if door has been closed for more than 1.2 sec
00127     if (bDoorClosed & doorClosedTimer.read() > 1.2) {
00128         doorClosedTimer.stop();
00129         doorClosedTimer.reset();
00130         result = true;
00131     }
00132     wasClosed = bDoorClosed;
00133     return result;
00134 }
00135 
00136 // Door locking/unlocking code
00137 Timer doorUnlockedTimer;
00138 void UnlockDoor(bool req) {
00139     unlock_door = (req) ? 1 : 0;
00140     door_unlocked_led = unlock_door;
00141     if (req) {
00142         doorUnlockedTimer.reset();
00143         doorUnlockedTimer.start();
00144     }
00145 }
00146 
00147 // Door Unlocked Timeout Event
00148 bool IsDoorUnlockedTimeoutEvent() {
00149     if (doorUnlockedTimer.read() > 5.0) { // fires if door has been unlocked for more than 5 sec
00150         doorUnlockedTimer.stop();
00151         doorUnlockedTimer.reset();
00152         return true;
00153     }
00154     return false;
00155 }
00156 
00157 // State Machine Logic
00158 void CatDoorStateMachine(Event event) {
00159     static Location destination = Outside; // destination variable helps determine location of a cat
00160     printf("State: %s\t Event: %s\n", stateNames[state].c_str(), eventNames[event].c_str());
00161     
00162     switch(state)
00163     {
00164         case DoorLockedClosed :
00165             if (bLockdown) break; // bLockdown doesn't let state machine exit DoorLockedClosed state
00166             switch(event)
00167             {
00168                 case ProximityEvent :
00169                     UnlockDoor(true);                   // unlock door
00170                     state = DoorUnlockedClosed;
00171                     destination = Outside;              // cat's coming outside
00172                     break;
00173                 case AuthTagReadEvent :
00174                     UnlockDoor(true);                   // unlock door
00175                     state = DoorUnlockedClosed;
00176                     destination = Inside;               // cat's coming inside
00177                     break;
00178                 default :
00179                     break;
00180             }
00181             break;
00182         case DoorUnlockedClosed :
00183             switch(event)
00184             {
00185                 case DoorUnlockedTimeoutEvent :         // lock door after 5 sec
00186                     UnlockDoor(false);                  // lock door
00187                     state = DoorLockedClosed;
00188                     break;
00189                 case DoorOpenEvent :
00190                     state = DoorUnlockedOpen;
00191                     break;
00192                 default :
00193                     break;
00194             }
00195             break;
00196         case DoorUnlockedOpen :
00197             switch(event)
00198             {
00199                 case DoorClosedEvent :                  // door closed, can lock it now
00200                     UnlockDoor(false);                  // lock door
00201                     state = DoorLockedClosed;
00202                     cats[catId].location = destination; // cat's location determined
00203                     break;
00204                 default :
00205                     break;
00206             }
00207             break;
00208         default :
00209             break;
00210     }
00211 }
00212 
00213 int main() {
00214     bool bEthPresent = true; // online/offline mode variable
00215     lcd.cls(); lcd.locate(0, 0); lcd.printf("RFID Cat Door");
00216     lcd.locate(0, 1); lcd.printf("Setting up ^..^");
00217     printf("RFID Cat Door\n");
00218     printf("Setting up Ethernet ^..^\n");
00219     EthernetErr ethErr = eth.setup(); // Ethernet setup
00220     if (ethErr) {
00221         printf("Error %d in Ethernet setup\n", ethErr);
00222         printf("Operating in offline mode ^..^\n");
00223         lcd.cls(); lcd.printf("Offline mode");
00224         bEthPresent = false; // offline mode set
00225     }
00226     else {
00227         printf("Ethernet setup OK\n");
00228         printf("Operating in online mode ^..^\n");
00229         IpAddr ip = eth.getIp(); // IP address
00230         lcd.cls(); lcd.locate(0, 0); lcd.printf("Online mode, IP:");
00231         lcd.locate(0, 1); lcd.printf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
00232       
00233         svr.addHandler<CatDoorHandler>("/");    // our HTTP handler added
00234         svr.bind(80);                           // port 80 bound
00235     }
00236 
00237     while(1) {
00238         if (bEthPresent)
00239             Net::poll();                        // service HTTP requests
00240 
00241 #ifndef NO_HW        
00242         if (IsAuthTagReadEvent()) {
00243             event = AuthTagReadEvent;           // Authorized Tag Read Event
00244             CatDoorStateMachine(event);
00245         }
00246 #endif    
00247         if (IsProximityEvent()) {
00248             event = ProximityEvent;             // Proximity Event
00249             CatDoorStateMachine(event);
00250         }
00251         
00252         if (IsDoorOpenEvent()) {
00253             event = DoorOpenEvent;              // Door Open Event
00254             CatDoorStateMachine(event);
00255         }
00256         
00257         if (IsDoorClosedEvent()) {
00258             event = DoorClosedEvent;            // Door Closed Event
00259             CatDoorStateMachine(event);
00260         }
00261         
00262         if (IsDoorUnlockedTimeoutEvent()) {
00263             event = DoorUnlockedTimeoutEvent;   // Door Unlocked Timeout Event
00264             CatDoorStateMachine(event);
00265         }
00266     }
00267 }
00268 
00269 // Cat Door HTTP Handler will handle HTTP GET requests
00270 class CatDoorHandler : public HTTPRequestHandler
00271 {
00272 public:
00273     CatDoorHandler(const char* rootPath, const char* path, TCPSocket* pTCPSocket) :
00274         HTTPRequestHandler(rootPath, path, pTCPSocket){}
00275 
00276     virtual ~CatDoorHandler(){}
00277 
00278     static inline HTTPRequestHandler* inst(const char* rootPath, const char* path, TCPSocket* pTCPSocket)
00279     { return new CatDoorHandler(rootPath, path, pTCPSocket); }
00280 
00281     virtual void doGet() // handles HTTP GET requests
00282     {
00283         string _path = path(); // path will have "lockdown=yes" if lockdown checkbox was checked
00284         printf("doGet path: %s\n", _path.c_str());
00285         bLockdown = (_path.find("lockdown=yes") == string::npos) ? false : true;
00286         if (bLockdown) {
00287             lcd.cls(); lcd.printf("System Lockdown!");
00288         }
00289         else {
00290             lcd.cls();
00291         }
00292         
00293         // Create HTML page with status information, lockdown checkbox, and submit/refresh button
00294         string rs = "<html><head><title>RFID Cat Door</title></head><body><h3>RFID Cat Door</h3>";
00295         string ds = "Door Status: <i>" + stateNames[state] + "</i><br>";
00296         string cs = "Cat Status: <i>" + locationNames[cats[catId].location] + "</i><p>";
00297         string ld = (bLockdown) ? " checked" : ""; // lockdownn checkbox reflects system lockdown state
00298         string fr = "<form method='get' action=''>"
00299         "<input type='checkbox' name='lockdown' value='yes'" + ld + "> Lockdown System <p>"
00300         "<input type='submit' value='Submit/Refresh Data'></form></body></html>";
00301         rs += ds + cs + fr;
00302         setContentLen(rs.length());
00303         respHeaders()["Connection"] = "close";
00304         writeData(rs.c_str(), rs.length());
00305     }
00306 
00307     virtual void doPost() {}
00308     virtual void doHead() {}
00309     virtual void onReadable() {}
00310     virtual void onWriteable() {}
00311     virtual void onClose() {}
00312 };