G2A Many GEOs
SHARE
TWEET

Door Lock Device

androng Feb 15th, 2014 719 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();
RAW Paste Data
Ledger Nano X - The secure hardware wallet
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top