From: BuildTools Date: Mon, 23 Jan 2017 12:00:46 +0000 (+0000) Subject: Updated wiegand doorlock system X-Git-Url: http://stoneship.org.uk/projects/git/?p=doorlock_v1.git;a=commitdiff_plain;h=0d5d64752c60b389ba74f5ccd75ef75594a3fd63 Updated wiegand doorlock system --- diff --git a/door_wiegand.ino b/door_wiegand.ino index 7843d0e..4364e54 100644 --- a/door_wiegand.ino +++ b/door_wiegand.ino @@ -1,6 +1,9 @@ +#include +#include #include #include #include +#include #include #include #include @@ -51,17 +54,93 @@ // files to store card/fob data in #define CARD_TMPFILE "/cards.tmp" #define CARD_FILE "/cards.dat" +#define LOG_FILE "/log.dat" // how long to hold the latch open in millis #define LATCH_HOLD 5000 +// webserver for configuration portnumber +#define CONFIG_PORT 80 + +// ntp server to use +#define NTP_SERVER "1.uk.pool.ntp.org" + /*************************** * code below */ WIEGAND wg; -ESP8266WebServer server(80); +ESP8266WebServer server(CONFIG_PORT); + +const unsigned int localPort = 2390; +IPAddress ntpServerIP; + +const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message + +byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets + +WiFiUDP udp; + + +/* compose and send an NTP time request packet */ +void ntp_send() +{ + if (ntpServerIP == INADDR_NONE) { + WiFi.hostByName(NTP_SERVER, ntpServerIP); + Serial.print("Got NTP server " NTP_SERVER " address "); + Serial.println(ntpServerIP); + } + + + memset(packetBuffer, 0, NTP_PACKET_SIZE); + // Initialize values needed to form NTP request + // (see URL above for details on the packets) + packetBuffer[0] = 0b11100011; // LI, Version, Mode + packetBuffer[1] = 0; // Stratum, or type of clock + packetBuffer[2] = 6; // Polling Interval + packetBuffer[3] = 0xEC; // Peer Clock Precision + // 8 bytes of zero for Root Delay & Root Dispersion + packetBuffer[12] = 49; + packetBuffer[13] = 0x4E; + packetBuffer[14] = 49; + packetBuffer[15] = 52; + + // all NTP fields have been given values, now + // you can send a packet requesting a timestamp: + udp.beginPacket(ntpServerIP, 123); //NTP requests are to port 123 + udp.write(packetBuffer, NTP_PACKET_SIZE); + udp.endPacket(); + + Serial.println("Sending NTP request"); +} + +/* request a time update from NTP and parse the result */ +time_t ntp_fetch() +{ + while (udp.parsePacket() > 0); // discard old udp packets + ntp_send(); + uint32_t beginWait = millis(); + while (millis() - beginWait < 2500) { + int size = udp.parsePacket(); + if (size >= NTP_PACKET_SIZE) { + udp.read(packetBuffer, NTP_PACKET_SIZE); + + // this is NTP time (seconds since Jan 1 1900): + unsigned long secsSince1900 = packetBuffer[40] << 24 | packetBuffer[41] << 16 | packetBuffer[42] << 8 | packetBuffer[43]; + const unsigned long seventyYears = 2208988800UL; + time_t unixtime = secsSince1900 - seventyYears; + + Serial.print("NTP update unixtime="); + Serial.println(unixtime); + return unixtime; + } + } + Serial.println("No NTP response"); + return 0; +} + +/* how big is a file */ int fileSize(const char *filename) { int ret = -1; @@ -73,6 +152,8 @@ int fileSize(const char *filename) return ret; } + +/* HTTP page request for / */ void handleRoot() { char mtime[16]; @@ -92,7 +173,22 @@ void handleRoot() \ \

Door Lock!

\ -

Uptime: " + (String)mtime + "

"; +

Uptime: " + (String)mtime + "

\n"; + + if (timeStatus() == timeSet) { + time_t when = now(); + out += "

Time now: " + getDate(when) + " " + getTime(when) + "

\n"; + } + + + FSInfo fs_info; + if (SPIFFS.info(fs_info)) { + out += "

Onboard Flash disk: - Size:"+String(fs_info.totalBytes)+" Used:"+String(fs_info.usedBytes)+"

\n"; + } + + out += "

Lock is currently "; + if (digitalRead(SENSE) == HIGH) out += "LOCKED"; else out += "OPEN"; + out += "

\n"; if (SPIFFS.exists(CARD_FILE)) { @@ -112,16 +208,18 @@ void handleRoot()
  • Reset Configuration\
  • Upload Cardlist"; - FSInfo fs_info; - if (SPIFFS.info(fs_info)) { - out += "
  • Format SPIFFS - Size:"+String(fs_info.totalBytes)+" Used:"+String(fs_info.usedBytes); + + if (SPIFFS.exists(LOG_FILE)) { + out += "
  • Wipe log file"; + out += "
  • Download full logfile"; } - - out += "
  • Lock is currently "; - if (digitalRead(SENSE) == HIGH) out += "LOCKED"; else out += "OPEN"; + - out += "\ - \ + out += ""; + + if (SPIFFS.exists(LOG_FILE)) out += printLog(true, 10); + + out += "\ "; server.send( 200, "text/html", out); @@ -142,6 +240,24 @@ void handleDownload() f.close(); } +void handleWipelog() +{ + if (!server.authenticate(www_username, www_password)) + return server.requestAuthentication(); + + SPIFFS.remove(LOG_FILE); + server.send(200, "text/plain", "logfile deleted"); +} + +void handleDownloadLogfile() +{ + if (!server.authenticate(www_username, www_password)) + return server.requestAuthentication(); + + String result = printLog(false, 0); + server.send(200, "text/csv", result); +} + void handleNotFound() { String out = "File Not found\n\n"; server.send(404, "text/plain", out); @@ -220,6 +336,7 @@ void handleUploadComplete() SPIFFS.remove(CARD_FILE); SPIFFS.rename(CARD_TMPFILE, CARD_FILE); } + out += "

    Back"; server.send(upload_code, "text/plain", out); } @@ -228,82 +345,32 @@ void returnOK() { server.send(200, "text/plain", ""); } - -static InputDebounce release_button; - -void setup() { - // some serial, for debug - Serial.begin(115200); - - // The lock mechanism, set HIGH to turn on and connect ground to output pin - pinMode(MOSFET, OUTPUT); - digitalWrite(MOSFET, LOCK_CLOSE); - - // lock sense microswitch - pinMode(SENSE, INPUT_PULLUP); - - // emergency door release switch - pinMode(ERELEASE, INPUT); - - // indicators on the keyfob reader - pinMode(BUZZER, OUTPUT); - pinMode(DOORLED, OUTPUT); - digitalWrite(BUZZER, BUZZ_OFF); - digitalWrite(DOORLED, DLED_RED); - - Serial.println("DoorLock. Testing WiFi config..."); - - // if we have no config, enter config mode - WiFiManager wfm; - wfm.autoConnect(MANAGER_AP); - - // we have config, enable web server - server.on( "/", handleRoot ); - server.on( "/reset", handleReset ); - server.onFileUpload( handleFileUpload); - server.on( "/upload", HTTP_GET, handleUploadRequest); - server.on( "/upload", HTTP_POST, handleUploadComplete); - server.on( "/download", handleDownload ); - server.onNotFound( handleNotFound ); - server.begin(); - - // advertise we exist via MDNS - if (!MDNS.begin("doorlock")) { - Serial.println("Error setting up MDNS responder."); - } else { - MDNS.addService("http", "tcp", 80); - } - - // enable internal flash filesystem - SPIFFS.begin(); - - // init wiegand keyfob reader - Serial.println("Starting Wiegand test reader"); - wg.begin(WD0, WD0, WD1, WD1); - - // setup button debounce for the release switch - release_button.setup(ERELEASE, 20, InputDebounce::PIM_EXT_PULL_DOWN_RES); +String getTime(time_t when) +{ + String ans; + int h = hour(when); + int m = minute(when); + int s = second(when); + + if (h<10) ans += "0"; + ans += String(h) + ":"; + if (m<10) ans += "0"; + ans += String(m) + ":"; + if (s<10) ans += "0"; + ans += String(s); + + return ans; } -unsigned long locktime = 0; - - -void unlock_door() +String getDate(time_t when) { - digitalWrite(DOORLED, DLED_GREEN); - digitalWrite(MOSFET, LOCK_OPEN); - if (locktime == 0) { - digitalWrite(BUZZER, BUZZ_ON); - delay(100); - digitalWrite(BUZZER, BUZZ_OFF); - delay(50); - digitalWrite(BUZZER, BUZZ_ON); - delay(100); - digitalWrite(BUZZER, BUZZ_OFF); - } - locktime = millis(); + String ans; + + ans += String(year(when)) + "-" + String(month(when)) + "-" + String(day(when)); + return ans; } + int sanityCheck(const char * filename) { int count = 0; @@ -375,12 +442,161 @@ String findKeyfob(unsigned int code) return answer; } -void loop() { - unsigned long now = millis(); +void logEntry(time_t when, uint32_t card) +{ + unsigned char entry[8]; + + File f = SPIFFS.open(LOG_FILE, "a"); + if (!f) { + Serial.println("Error opening log file"); + return; + } + + // compose the record to write + ((uint32_t *)entry)[0] = when; + ((uint32_t *)entry)[1] = card; + f.write(entry, 8); + f.close(); +} + +String printLog(int html, int last) +{ + String out; + File f = SPIFFS.open(LOG_FILE, "r"); + if (!f) return String("Could not open log file"); + + unsigned char entry[8]; + uint32_t * data = (uint32_t *)entry; + + if (last != 0) { + // print only the last N items + int pos = f.size() / 8; + if (pos > last) pos -= last; else pos = 0; + f.seek( pos * 8, SeekSet); + if (html) out += "Last " + String(last) + " log entries :-"; + } + if (html) out += "
      "; + + while (f.available()) { + f.read(entry, 8); + if (html) out += "
    • "; + out += getDate( data[0] ); + out += " "; + out += getTime( data[0] ); + if (html) out += " - "; else out += "," + String(data[1]) + ","; + + if (data[1] == 0) { + if (html) out += ""; + out += "Emergency Release"; + if (html) out += ""; + } else { + String whom = findKeyfob(data[1]); + if (whom == "") { + if (html) out += "by "; + out += "Unknown keyfob"; + if (html) out += ""; + } else { + out += whom; + } + if (html) out += " (" + String(data[1]) + ")"; + } + out += "\n"; + } + f.close(); + if (html) out += "
    "; + return out; +} + + +static InputDebounce release_button; + +/******************************************** + * Main setup routine + */ +void setup() { + // some serial, for debug + Serial.begin(115200); + + // The lock mechanism, set HIGH to turn on and connect ground to output pin + pinMode(MOSFET, OUTPUT); + digitalWrite(MOSFET, LOCK_CLOSE); + + // lock sense microswitch + pinMode(SENSE, INPUT_PULLUP); + + // emergency door release switch + pinMode(ERELEASE, INPUT); + + // indicators on the keyfob reader + pinMode(BUZZER, OUTPUT); + pinMode(DOORLED, OUTPUT); + digitalWrite(BUZZER, BUZZ_OFF); + digitalWrite(DOORLED, DLED_RED); + Serial.println("DoorLock. Testing WiFi config..."); + + // if we have no config, enter config mode + WiFiManager wfm; + wfm.autoConnect(MANAGER_AP); + + // we have config, enable web server + server.on( "/", handleRoot ); + server.on( "/reset", handleReset ); + server.on( "/download", handleDownload ); + server.on( "/wipelog", handleWipelog ); + server.on( "/download_logfile", handleDownloadLogfile ); + server.onFileUpload( handleFileUpload); + server.on( "/upload", HTTP_GET, handleUploadRequest); + server.on( "/upload", HTTP_POST, handleUploadComplete); + server.onNotFound( handleNotFound ); + server.begin(); + + // advertise we exist via MDNS + if (!MDNS.begin("doorlock")) { + Serial.println("Error setting up MDNS responder."); + } else { + MDNS.addService("http", "tcp", 80); + } + + // enable internal flash filesystem + SPIFFS.begin(); + + // init wiegand keyfob reader + Serial.println("Starting Wiegand test reader"); + wg.begin(WD0, WD0, WD1, WD1); + + // setup button debounce for the release switch + release_button.setup(ERELEASE, 20, InputDebounce::PIM_EXT_PULL_DOWN_RES); + + // listener port for replies from NTP + udp.begin(localPort); + setSyncProvider(ntp_fetch); +} + +unsigned long locktime = 0; + + +void unlock_door() +{ + digitalWrite(DOORLED, DLED_GREEN); + digitalWrite(MOSFET, LOCK_OPEN); + if (locktime == 0) { + digitalWrite(BUZZER, BUZZ_ON); + delay(100); + digitalWrite(BUZZER, BUZZ_OFF); + delay(50); + digitalWrite(BUZZER, BUZZ_ON); + delay(100); + digitalWrite(BUZZER, BUZZ_OFF); + } + locktime = millis(); +} + + +void loop() { // is the latch held open ? if (locktime != 0) { - if (locktime + LATCH_HOLD < now) { + if (locktime + LATCH_HOLD < millis()) { locktime = 0; digitalWrite(MOSFET, LOCK_CLOSE); digitalWrite(DOORLED, DLED_RED); @@ -389,7 +605,7 @@ void loop() { // handle web requests server.handleClient(); - unsigned int ertime = release_button.process(now); + unsigned int ertime = release_button.process(millis()); unsigned int count = release_button.getStateOnCount(); static unsigned last_count = 0; if (ertime > 0) { @@ -397,6 +613,7 @@ void loop() { last_count = count; Serial.println("Door Release button triggered."); unlock_door(); + logEntry(now(), 0); } else { // buttons is still pressed, do nothing } @@ -418,6 +635,7 @@ void loop() { Serial.print("Unlocking door for "); Serial.println(who); unlock_door(); + logEntry(now(), code); } } diff --git a/hardware/doorlock_v1.fzz b/hardware/doorlock_v1.fzz index 66e94bd..c87bd5d 100644 Binary files a/hardware/doorlock_v1.fzz and b/hardware/doorlock_v1.fzz differ diff --git a/wiring_wiegand.svg b/wiring_wiegand.svg new file mode 100644 index 0000000..14a85c4 --- /dev/null +++ b/wiring_wiegand.svg @@ -0,0 +1,838 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Programming/Debug Port + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Door Release + + + Gnd + + + + + + + + + + + + + Yellow: Beep + + 2 + 1 + 3 + 4 + 5 + 6 + + Blue: LED + + Green: D0 + 7 + 8 + + white: D1 + +  +  + 12v d.c. + + + + + + 12v IN + 3.3v Out + + + Red: 12v + + Black: ground + + Yellow: NC + + Green: NO + + Orange: COM + + Red: 12v + + Black: Gnd + + NO COM NC + Hackspace Door wiring v1: Jan 2017 + +