Advertisement
androng

Door Lock Device

Feb 15th, 2014
1,318
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /**
  2.  * Reads cards from HID reader UART
  3.  * and outputs access denied/granted.
  4.  */
  5.  
  6. /* Pins */
  7. UNLOCKPIN <- hardware.pin5;
  8. LOCKPIN <- hardware.pin7;
  9. LEDPIN <- hardware.pin8;
  10. DOORSWITCH <- hardware.pin9;
  11. /* Constants */
  12. const DEADBOLTSELFLOCKDELAY = 5000; /* Used in state 5 of deadboltSM */
  13.  
  14. /* States for Deadbolt SM */
  15. enum Deadbolt {
  16.     state0dummystate, /* To make debugging not start from zero*/
  17.     state1DLDC, /* Deadbolt locked Door closed */
  18.     state2Unlocking,
  19.     state3Locking,
  20.     state4DUDO, /* Deadbolt unlocked Door open */
  21.     state5DUDC, /* Deadbolt unlocked Door closed */
  22.     state6DLDO  /* Deadbolt locked Door open */
  23. }
  24.  
  25. /* Variables*/
  26. currentCard <- 0; /* Card byte buffer */
  27. currentCardBytessReceived <- 0; /* Number of bytes read by UART */
  28. accessGranted <- 0; /* Read and reset by deadboltSM */
  29. ledState <- 0; /* For LED blink*/
  30. deadboltState <- Deadbolt.state1DLDC;
  31.  
  32. /* Times */
  33. timeLastByteReceived <- 0;
  34. timeLastDeadboltSMChange <- 0;
  35.  
  36. /** OutputPorts */
  37. /** For reporting events like "Access granted/denied to ..."  */
  38. local accessLog = OutputPort("AccessLog");
  39. /** For reporting "0" for locked and "1" for unlocked.
  40.  *  This could be either an entrance or exit. */
  41. local unlockedLog = OutputPort("UnlockedLog");
  42.  
  43. /* 32-bit tag containers for 26-bit tags including parity bits */
  44. allowedIDs <- blob(24);
  45. allowedIDs.writen(0x00000000, 'i'); /* Andrew */
  46. allowedIDs.writen(0x00000000, 'i'); /* Person 2 */
  47. allowedIDs.writen(0x00000000, 'i'); /* Person 3 */
  48. allowedIDs.writen(0x00000000, 'i'); /* Person 4 */
  49. allowedIDs.writen(0x00000000, 'i'); /* Person 5 */
  50. allowedIDs.writen(0x00000000, 'i'); /* Person 6 */
  51.  
  52. /* String array that corresponds to the card numbers */
  53. allowedNames <- [
  54.     "Andrew Ong",
  55.     "Person 2",
  56.     "Person 3",
  57.     "Person 4",
  58.     "Person 5"
  59.     "Person 6"
  60.     ];
  61.  
  62. /** More IDs for people who I've identified but are not on the allowed list.
  63.  *  This is so that when they walk through the door, instead of seeing
  64.  *  "Access Denied: 99648 0x04170A80", you see
  65.  *  "Access Denied: Martin"
  66.  */
  67. otherIDs <- blob(28);
  68. otherIDs.writen(0x00000000, 'i'); /* AccessDenied Person1 */
  69. otherIDs.writen(0x00000000, 'i'); /* AccessDenied Person2 */
  70. otherIDs.writen(0x00000000, 'i'); /* AccessDenied Person3 */
  71. otherIDs.writen(0x00000000, 'i'); /* AccessDenied Person4 */
  72. otherIDs.writen(0x00000000, 'i'); /* AccessDenied Person5 */
  73. otherIDs.writen(0x00000000, 'i'); /* AccessDenied Person6 */
  74. otherIDs.writen(0x00000000, 'i'); /* AccessDenied Person7 */
  75.  
  76.  
  77. otherNames <- [
  78.     "AccessDenied Person1",
  79.     "AccessDenied Person2",
  80.     "AccessDenied Person3",
  81.     "AccessDenied Person4",
  82.     "AccessDenied Person5",
  83.     "AccessDenied Person6",
  84.     "AccessDenied Person7"
  85.     ];
  86.  
  87. function deadboltSM(){
  88.     /* Actions */
  89.    
  90.     /* Transitions */
  91.     switch(deadboltState){
  92.     case Deadbolt.state1DLDC: /* Deadbolt locked Door closed */
  93.         if(DOORSWITCH.read()){
  94.             deadboltState = Deadbolt.state4DUDO;
  95.             onDeadboltSMTransition();
  96.         }
  97.         else if(accessGranted == 1){
  98.             deadboltState = Deadbolt.state2Unlocking;
  99.             onDeadboltSMTransition();
  100.             UNLOCKPIN.write(1);
  101.         }
  102.         else if(accessGranted == 0){
  103.             /* Loopback transition */
  104.         }
  105.         break;
  106.     case Deadbolt.state2Unlocking:
  107.         if(hardware.millis() - timeLastDeadboltSMChange < 2000){
  108.             /* Loopback transition */
  109.         }
  110.         else if(DOORSWITCH.read() == 1){
  111.             deadboltState = Deadbolt.state4DUDO;
  112.             onDeadboltSMTransition();
  113.             UNLOCKPIN.write(0);
  114.         }
  115.         else if(DOORSWITCH.read() == 0){
  116.             deadboltState = Deadbolt.state5DUDC;
  117.             onDeadboltSMTransition();
  118.             UNLOCKPIN.write(0);
  119.         }
  120.         break;
  121.     case Deadbolt.state3Locking:
  122.         if(hardware.millis() - timeLastDeadboltSMChange < 2000){
  123.             /* Loopback transition */
  124.         }
  125.         else if(DOORSWITCH.read() == 1){
  126.             deadboltState = Deadbolt.state6DLDO;
  127.             onDeadboltSMTransition();
  128.             LOCKPIN.write(0);
  129.             accessGranted = 0;
  130.         }
  131.         else if(DOORSWITCH.read() == 0){
  132.             deadboltState = Deadbolt.state1DLDC;
  133.             onDeadboltSMTransition();
  134.             LOCKPIN.write(0);
  135.             accessGranted = 0;
  136.         }
  137.         break;
  138.     case Deadbolt.state4DUDO: /* Deadbolt unlocked Door open */
  139.         if(DOORSWITCH.read() == 1){
  140.             /* Loopback transition */
  141.         }
  142.         else if(DOORSWITCH.read() == 0){
  143.             deadboltState = Deadbolt.state3Locking;
  144.             onDeadboltSMTransition();
  145.             LOCKPIN.write(1);
  146.         }
  147.         break;
  148.     case Deadbolt.state5DUDC: /* Deadbolt unlocked Door closed */
  149.         if(DOORSWITCH.read() == 1){
  150.             deadboltState = Deadbolt.state4DUDO;
  151.             onDeadboltSMTransition();
  152.         }
  153.         else if(hardware.millis() - timeLastDeadboltSMChange > DEADBOLTSELFLOCKDELAY){
  154.             deadboltState = Deadbolt.state3Locking;
  155.             onDeadboltSMTransition();
  156.             LOCKPIN.write(1);
  157.         }
  158. //        else if(hardware.millis() - timeLastDeadboltSMChange > DEADBOLTSELFLOCKDELAY){
  159. //            /* Loopback transition */
  160. //        }
  161.         break;
  162.     case Deadbolt.state6DLDO: /* Deadbolt locked Door open */
  163.         deadboltState = Deadbolt.state2Unlocking;
  164.         onDeadboltSMTransition();
  165.         UNLOCKPIN.write(1);
  166.         break;
  167.     }
  168.    
  169.     imp.wakeup(0.05, deadboltSM);
  170. }
  171. /**
  172.  * Called when deadboltSM transitions. You have to
  173.  * remember to put this in the SM transitions.
  174.  */
  175. function onDeadboltSMTransition(){
  176.     timeLastDeadboltSMChange = hardware.millis();
  177. //    server.log(format("%s %i", "State: ", deadboltState));
  178. }
  179.  
  180. /**
  181.  * Blinks an LED
  182.  */
  183. function blink(){
  184.  
  185.     /* Change State */
  186.     ledState = ledState?0:1;
  187.    
  188.     /* Reflect state to pin */
  189.     LEDPIN.write(ledState);
  190.    
  191.     /* Schedule the next state change */
  192.     imp.wakeup(1, blink);
  193. }
  194.  
  195. /**
  196.  * Searches through card list and if match found, grants access.
  197.  * In both cases reports to server.
  198.  */
  199. function grantOrDeny(){
  200.     local foundCard = 0;
  201.     /* Iterate through the array and try to find scanned card  */
  202.     allowedIDs.seek(0); /* Move read/write head to beginning */
  203.     for(local i = 0; !allowedIDs.eos(); i++){
  204.         local id = allowedIDs.readn('i');
  205.         if(id == currentCard){
  206.             local s = format("Access Granted: %s", allowedNames[i]);
  207.             server.log(s);
  208.             agent.send("accessLog",s);
  209.             accessGranted = 1;
  210.             foundCard = 1;
  211.             break;
  212.         }
  213.     }
  214.     /* If access denied */
  215.     if(foundCard == 0){
  216.         /* Look for them in the known cards list (but don't grand access) */
  217.         otherIDs.seek(0); /* Move read/write head to beginning */
  218.         for(local i = 0; !otherIDs.eos(); i++){
  219.             local id = otherIDs.readn('i');
  220.             if(id == currentCard){
  221.                 local s = format("Access Denied: %s", otherNames[i]);
  222.                 server.log(s);
  223.                 agent.send("accessLog", s);
  224.                 foundCard = 1;
  225.                 break;
  226.             }
  227.         }
  228.        
  229.         /* If they are not on either list */
  230.         if(foundCard == 0){
  231.             /* Show number on back of card as well as full card with parity bits */
  232.             local s = format("Access Denied: %i 0x%08X", (currentCard & 0x03FFFE) >> 1 , currentCard);
  233.             server.log(s);
  234.             agent.send("accessLog", s);
  235.         }
  236.     }
  237. }
  238.  
  239.  
  240. /**
  241.  * Event handler for UART data ready flag.
  242.  * Reads UART (RS-232) output from HID reader.
  243.  * Puts data in buffer until buffer has a full card.
  244.  */
  245. function readSerial() {
  246.     local result;
  247.     do {
  248.         result = hardware.uart12.read();
  249.         /* Ignore lack of data */
  250.         if(result != -1){
  251.             currentCardBytessReceived++;
  252.             timeLastByteReceived = hardware.millis();
  253.             /* Only record bytes 5-12 from the reader */
  254.             if(currentCardBytessReceived >= 5
  255.             && currentCardBytessReceived <= 12){
  256.                 /* Shift by four to make room for new nibble */
  257.                 currentCard = currentCard << 4;
  258.                
  259.                 /** Decode the "ASCII" byte and add to card */
  260.                 /* If ASCII-encoded 0-9, subtract 0 (hex 0x30) */
  261.                 if(result >= 0x30 && result <= 0x39){
  262.                     result -= 0x30;
  263.                 }
  264.                 /* If ASCII-encoded A-F, subtract ('A'-10) (hex 0x41-0x0A) */
  265.                 else if(result <= 0x46){
  266.                     result -= 0x41-0x0A;
  267.                 }
  268.                 else{
  269.                     server.log("Invalid character read from UART");
  270.                 }
  271.                
  272.                 /* Add the nibble to the card buffer */
  273.                 currentCard += result;
  274.             }
  275.             /* When enough card data appears, grant or deny access*/
  276.             if(currentCardBytessReceived == 12){
  277.                 grantOrDeny();
  278.             }
  279.         }
  280.     } while (result != -1);
  281. }
  282.  
  283. function monitorBits(){
  284.     server.log(format("%08X", currentCard));
  285. //    server.log(format("%i",currentCardBitsReceived));
  286.     imp.wakeup(1, monitorBits);
  287. }
  288. /**
  289.  * Clears card buffer after a certain amount of time.
  290.  * Redundancy to remove any stray bytes on UART.  
  291.  */
  292. function clearBits(){
  293.     if(hardware.millis() - timeLastByteReceived > 1000){
  294.         currentCard = 0;
  295.         currentCardBytessReceived = 0;
  296.     }
  297.     imp.wakeup(3, clearBits);    
  298. }
  299. /**
  300.  * Logs all door opens/closes. (callback function for switch pin)
  301.  */
  302. function switchChanged(){
  303.     local status = DOORSWITCH.read();
  304.     if(status == 0){
  305.         server.log("Door locked");
  306.     }
  307.     else{
  308.         server.log("Door unlocked");
  309.         agent.send("unlockedLog", status);
  310.     }
  311. }
  312. /**
  313.  * Periodically logs whether door open/closed.
  314.  *
  315.  * It makes the log look nicer if you constantly output correct data
  316.     so that when a new open/close comes, there is not a giant ramp as
  317.     the graph tries to linearly interpolate between "open" and "closed".
  318.  
  319.  * Schdules itself to repeat. This
  320.  * needs to be a seperate function from the callback, otherwise the callback
  321.  * would schedule itself and there would be too many callbacks.
  322.  */
  323. function logSwitch(){
  324.     agent.send("unlockedLog", DOORSWITCH.read());
  325.     imp.wakeup(180.0, logSwitch);
  326. }
  327.  
  328. /* Configure a pin pair for UART TX/RX */
  329. hardware.uart12.configure(9600, 8, PARITY_NONE, 1, NO_CTSRTS, readSerial);
  330.  
  331. /* Configure pins */
  332. UNLOCKPIN.configure(DIGITAL_OUT);
  333. LOCKPIN.configure(DIGITAL_OUT);
  334. LEDPIN.configure(DIGITAL_OUT);
  335. DOORSWITCH.configure(DIGITAL_IN_PULLUP, switchChanged);
  336.  
  337. blink();
  338. //monitorBits();
  339. clearBits();
  340. deadboltSM();
  341. //logSwitch();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement