RFID Cat Door Project
Dependencies: EthernetNetIf TextLCD mbed HTTPServer ID12RFID
main.cpp
- Committer:
- sbobyr
- Date:
- 2011-08-30
- Revision:
- 2:9cc95c486c7b
- Parent:
- 1:25a4acc15210
File content as of revision 2:9cc95c486c7b:
// RFID Cat Door Project // The code runs on mbed and implements RFID Cat Door system. System comprises 3 sensors (RFID Reader, Proximity sensor, Reed sensor) // and 1 actuator (Solenoid door lock). System operates either in offline or online mode (if IP address is acquired). In online mode // a web page is created describing system's state. A lockdown override is available in online mode locking down the system. // The system is controlled by a state machine and provides RFID-based entry control. Exit is allowed without authorization. //#define NO_HW // uncomment if there's no HW attached to mbed #include "mbed.h" // mbed library #include "ID12RFID.h" // ID12 RFID Reader library #include "TextLCD.h" // OrangeBoard LCD library #include "EthernetNetIf.h" // Ethernet library #include "HTTPServer.h" // HTTP Server library #include "HTTPRequestHandler.h" // HTTP Request Handler library #include <string> EthernetNetIf eth; HTTPServer svr; class CatDoorHandler; // State Machine Events enum Event { DoorOpenEvent, DoorClosedEvent, ProximityEvent, AuthTagReadEvent, DoorUnlockedTimeoutEvent, None }; string eventNames[] = { "DoorOpen", "DoorClosed", "Proximity", "AuthTagRead", "DoorUnlockedTimeout", "None" }; Event event = None; // State Machine States enum State { DoorLockedClosed, DoorUnlockedClosed, DoorUnlockedOpen }; string stateNames[] = { "Door Locked & Closed", "Door Unlocked & Closed", "Door Unlocked & Open" }; State state = DoorLockedClosed; bool bLockdown = false; // variable indicating a lockdown from the web page // Cat's possible locations enum Location { Inside, Outside, Unknown }; string locationNames[] = { "Inside", "Outside", "Unknown" }; // Each cat has tag, name, and location struct cat { int tag; string name; Location location; }; // List of authorized cats cat cats[] = { 5454121, "Yellow", Unknown, //9733970, "Blue", Unknown, //463733, "Red", Unknown }; int catsN = sizeof(cats)/sizeof(cat); int catId = 0; // current cat ID TextLCD lcd(p24, p26, p27, p28, p29, p30); // OrangeBoard LCD ID12RFID rfid(p14); // uart rx for ID12 RFID reader DigitalIn _door_open(p17); // reed sensor, 0 indicates door open DigitalIn _proximity(p16); // proximity sensor, 0 indicates an object within 10 cm DigitalOut unlock_door(p21); // solenoid, 1 will unlock the door DigitalOut door_unlocked_led(LED1); // ON when door is unlocked DigitalOut door_open_led(LED2); // ON when door is open DigitalOut proximity_led(LED3); // ON when proximity sensor is triggered PwmOut rfid_read_led(LED4); // DIM = unauthorized tag read; BRIGHT = authorized tag read const float LED_DIM = 0.05; const float LED_BRIGHT = 1; // Authorized RFID Tag Read Event Timer tagReadTimer; bool IsAuthTagReadEvent() { if(rfid.readable()) { int tag = rfid.read(); // read the tag tagReadTimer.reset(); tagReadTimer.start(); // start 5 sec timer lcd.cls(); lcd.locate(0, 0); lcd.printf("Tag: %08d", tag); for (int i = 0; i < catsN; ++i) { // find if tag is authorized if (cats[i].tag == tag) { catId = i; lcd.locate(0, 1); lcd.printf("Cat: %s", cats[i].name.c_str()); rfid_read_led = LED_BRIGHT; return true; } } lcd.locate(0, 1); lcd.printf("Cat: Unknown"); // unknown tag rfid_read_led = LED_DIM; } if (tagReadTimer.read() > 5.0) { // each tag is shown for 5 sec tagReadTimer.stop(); tagReadTimer.reset(); rfid_read_led = 0; lcd.cls(); } return false; } // Proximity Event bool IsProximityEvent() { bool result = false; static bool wasProximity = false; // last state bool bProximity = !_proximity.read(); // 0 indicates an object within 10 cm proximity_led = bProximity; if (bProximity & !wasProximity) // create event on transition only result = true; wasProximity = bProximity; return result; } // Door Open Event bool IsDoorOpenEvent() { bool result = false; static bool wasOpen = false; // last state bool bDoorOpen = !_door_open.read(); // 0 indicates door open door_open_led = bDoorOpen; if (bDoorOpen & !wasOpen) // create event on transition only result = true; wasOpen = bDoorOpen; return result; } // Door Closed Event Timer doorClosedTimer; bool IsDoorClosedEvent() { bool result = false; static bool wasClosed = true; // last state bool bDoorClosed = _door_open.read(); if (bDoorClosed & !wasClosed) { // start timer when door closes doorClosedTimer.reset(); doorClosedTimer.start(); } // event is only created if door has been closed for more than 1.2 sec if (bDoorClosed & doorClosedTimer.read() > 1.2) { doorClosedTimer.stop(); doorClosedTimer.reset(); result = true; } wasClosed = bDoorClosed; return result; } // Door locking/unlocking code Timer doorUnlockedTimer; void UnlockDoor(bool req) { unlock_door = (req) ? 1 : 0; door_unlocked_led = unlock_door; if (req) { doorUnlockedTimer.reset(); doorUnlockedTimer.start(); } } // Door Unlocked Timeout Event bool IsDoorUnlockedTimeoutEvent() { if (doorUnlockedTimer.read() > 5.0) { // fires if door has been unlocked for more than 5 sec doorUnlockedTimer.stop(); doorUnlockedTimer.reset(); return true; } return false; } // State Machine Logic void CatDoorStateMachine(Event event) { static Location destination = Outside; // destination variable helps determine location of a cat printf("State: %s\t Event: %s\n", stateNames[state].c_str(), eventNames[event].c_str()); switch(state) { case DoorLockedClosed : if (bLockdown) break; // bLockdown doesn't let state machine exit DoorLockedClosed state switch(event) { case ProximityEvent : UnlockDoor(true); // unlock door state = DoorUnlockedClosed; destination = Outside; // cat's coming outside break; case AuthTagReadEvent : UnlockDoor(true); // unlock door state = DoorUnlockedClosed; destination = Inside; // cat's coming inside break; default : break; } break; case DoorUnlockedClosed : switch(event) { case DoorUnlockedTimeoutEvent : // lock door after 5 sec UnlockDoor(false); // lock door state = DoorLockedClosed; break; case DoorOpenEvent : state = DoorUnlockedOpen; break; default : break; } break; case DoorUnlockedOpen : switch(event) { case DoorClosedEvent : // door closed, can lock it now UnlockDoor(false); // lock door state = DoorLockedClosed; cats[catId].location = destination; // cat's location determined break; default : break; } break; default : break; } } int main() { bool bEthPresent = true; // online/offline mode variable lcd.cls(); lcd.locate(0, 0); lcd.printf("RFID Cat Door"); lcd.locate(0, 1); lcd.printf("Setting up ^..^"); printf("RFID Cat Door\n"); printf("Setting up Ethernet ^..^\n"); EthernetErr ethErr = eth.setup(); // Ethernet setup if (ethErr) { printf("Error %d in Ethernet setup\n", ethErr); printf("Operating in offline mode ^..^\n"); lcd.cls(); lcd.printf("Offline mode"); bEthPresent = false; // offline mode set } else { printf("Ethernet setup OK\n"); printf("Operating in online mode ^..^\n"); IpAddr ip = eth.getIp(); // IP address lcd.cls(); lcd.locate(0, 0); lcd.printf("Online mode, IP:"); lcd.locate(0, 1); lcd.printf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); svr.addHandler<CatDoorHandler>("/"); // our HTTP handler added svr.bind(80); // port 80 bound } while(1) { if (bEthPresent) Net::poll(); // service HTTP requests #ifndef NO_HW if (IsAuthTagReadEvent()) { event = AuthTagReadEvent; // Authorized Tag Read Event CatDoorStateMachine(event); } #endif if (IsProximityEvent()) { event = ProximityEvent; // Proximity Event CatDoorStateMachine(event); } if (IsDoorOpenEvent()) { event = DoorOpenEvent; // Door Open Event CatDoorStateMachine(event); } if (IsDoorClosedEvent()) { event = DoorClosedEvent; // Door Closed Event CatDoorStateMachine(event); } if (IsDoorUnlockedTimeoutEvent()) { event = DoorUnlockedTimeoutEvent; // Door Unlocked Timeout Event CatDoorStateMachine(event); } } } // Cat Door HTTP Handler will handle HTTP GET requests class CatDoorHandler : public HTTPRequestHandler { public: CatDoorHandler(const char* rootPath, const char* path, TCPSocket* pTCPSocket) : HTTPRequestHandler(rootPath, path, pTCPSocket){} virtual ~CatDoorHandler(){} static inline HTTPRequestHandler* inst(const char* rootPath, const char* path, TCPSocket* pTCPSocket) { return new CatDoorHandler(rootPath, path, pTCPSocket); } virtual void doGet() // handles HTTP GET requests { string _path = path(); // path will have "lockdown=yes" if lockdown checkbox was checked printf("doGet path: %s\n", _path.c_str()); bLockdown = (_path.find("lockdown=yes") == string::npos) ? false : true; if (bLockdown) { lcd.cls(); lcd.printf("System Lockdown!"); } else { lcd.cls(); } // Create HTML page with status information, lockdown checkbox, and submit/refresh button string rs = "<html><head><title>RFID Cat Door</title></head><body><h3>RFID Cat Door</h3>"; string ds = "Door Status: <i>" + stateNames[state] + "</i><br>"; string cs = "Cat Status: <i>" + locationNames[cats[catId].location] + "</i><p>"; string ld = (bLockdown) ? " checked" : ""; // lockdownn checkbox reflects system lockdown state string fr = "<form method='get' action=''>" "<input type='checkbox' name='lockdown' value='yes'" + ld + "> Lockdown System <p>" "<input type='submit' value='Submit/Refresh Data'></form></body></html>"; rs += ds + cs + fr; setContentLen(rs.length()); respHeaders()["Connection"] = "close"; writeData(rs.c_str(), rs.length()); } virtual void doPost() {} virtual void doHead() {} virtual void onReadable() {} virtual void onWriteable() {} virtual void onClose() {} };