Advertisement
skymike

Untitled

Sep 29th, 2017
151
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 26.65 KB | None | 0 0
  1. /*
  2.   Copyright (c) 2017 Omer Siar Baysal
  3.  
  4.   Released to Public Domain
  5.  
  6.   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  7.   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  8.   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  9.   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  10.   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  11.   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  12.   THE SOFTWARE.
  13.  
  14.   The following table shows the typical pin layout used:
  15.  
  16.   | Signal        | MFRC522       | WeMos D1 mini  | NodeMcu | Generic      |
  17.   |---------------|:-------------:|:--------------:| :------:|:------------:|
  18.   | RST/Reset     | RST           | NC             | NC      | NC           |
  19.   | SPI SS        | SDA [3]       | D8 [2]         | D8 [2]  | GPIO-15 [2]  |
  20.   | SPI MOSI      | MOSI          | D7             | D7      | GPIO-13      |
  21.   | SPI MISO      | MISO          | D6             | D6      | GPIO-12      |
  22.   | SPI SCK       | SCK           | D5             | D5      | GPIO-14      |
  23.  
  24.   NC. Not Connected
  25.   2. Configurable via web page
  26.   3. The SDA pin might be labeled SS on some/older MFRC522 boards.
  27.  
  28. */
  29.  
  30. #include <ESP8266WiFi.h>              // Whole thing is about using Wi-Fi networks
  31. #include <SPI.h>                      // RFID MFRC522 Module uses SPI protocol
  32. #include <ESP8266mDNS.h>              // Zero-config Library (Bonjour, Avahi) http://esp-rfid.local
  33. #include <MFRC522.h>                  // Library for Mifare RC522 Devices
  34. #include <ArduinoJson.h>              // JSON Library for Encoding and Parsing Json object to send browser. We do that because Javascript has built-in JSON parsing.
  35. #include <FS.h>                       // SPIFFS Library for storing web files to serve to web browsers
  36. #include <ESPAsyncTCP.h>              // Async TCP Library is mandatory for Async Web Server
  37. #include <ESPAsyncWebServer.h>        // Async Web Server with built-in WebSocket Plug-in
  38. #include <SPIFFSEditor.h>             // This creates a web page on server which can be used to edit text based files.
  39. #include <NtpClientLib.h>             // To timestamp RFID scans we get Unix Time from NTP Server
  40. #include <TimeLib.h>                  // Library for converting epochtime to a date
  41. #include <WiFiUdp.h>                  // Library for manipulating UDP packets which is used by NTP Client to get Timestamps
  42. #include <Servo.h>
  43.  
  44. // Variables for whole scope
  45.  
  46. unsigned long previousMillis = 0;
  47. unsigned long cooldown = 0;
  48. bool shouldReboot = false;
  49. bool activateServo = false;
  50. bool inAPMode = false;
  51. int pos = 0;
  52. int relayPin;
  53. int relayType;
  54. int activateTime;
  55. int timeZone;
  56.  
  57.  
  58. // Create MFRC522 RFID instance
  59. Servo servo;
  60. MFRC522 mfrc522 = MFRC522();
  61.  
  62. // Create AsyncWebServer instance on port "80"
  63. AsyncWebServer server(80);
  64. // Create WebSocket instance on URL "/ws"
  65. AsyncWebSocket ws("/ws");
  66.  
  67. // Set things up
  68. void setup() {
  69.   Serial.begin(115200);
  70.   Serial.println();
  71.   Serial.println(F("[ INFO ] ESP RFID v0.3alpha"));
  72.   servo.attach(5);  // attaches the servo on pin D1 to the servo object
  73.  
  74.   // Start SPIFFS filesystem
  75.   SPIFFS.begin();
  76.  
  77.   /* Remove Users Helper
  78.     Dir dir = SPIFFS.openDir("/P/");
  79.     while (dir.next()){
  80.     SPIFFS.remove(dir.fileName());
  81.     }
  82.   */
  83.  
  84.   // Try to load configuration file so we can connect to an Wi-Fi Access Point
  85.   // Do not worry if no config file is present, we fall back to Access Point mode and device can be easily configured
  86.   if (!loadConfiguration()) {
  87.     fallbacktoAPMode();
  88.   }
  89.  
  90.   // Start WebSocket Plug-in and handle incoming message on "onWsEvent" function
  91.   server.addHandler(&ws);
  92.   ws.onEvent(onWsEvent);
  93.  
  94.   // Configure web server
  95.   // Add Text Editor (http://esp-rfid.local/edit) to Web Server. This feature likely will be dropped on final release.
  96.   server.addHandler(new SPIFFSEditor("admin", "admin"));
  97.  
  98.  
  99.   // Serve all files in root folder
  100.   server.serveStatic("/", SPIFFS, "/");
  101.   // Handle what happens when requested web file couldn't be found
  102.  server.onNotFound([](AsyncWebServerRequest * request) {
  103.    AsyncWebServerResponse *response = request->beginResponse(302, "text/plain", "");
  104.    response->addHeader("Location", "http://192.168.4.1");
  105.    request->send(response);
  106.  });
  107.  
  108.  // Simple Firmware Update Handler
  109.  server.on("/auth/update", HTTP_POST, [](AsyncWebServerRequest * request) {
  110.    shouldReboot = !Update.hasError();
  111.    AsyncWebServerResponse *response = request->beginResponse(200, "text/plain", shouldReboot ? "OK" : "FAIL");
  112.    response->addHeader("Connection", "close");
  113.    request->send(response);
  114.  }, [](AsyncWebServerRequest * request, String filename, size_t index, uint8_t *data, size_t len, bool final) {
  115.    if (!index) {
  116.      Serial.printf("[ UPDT ] Firmware update started: %s\n", filename.c_str());
  117.      Update.runAsync(true);
  118.      if (!Update.begin((ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000)) {
  119.        Update.printError(Serial);
  120.      }
  121.    }
  122.    if (!Update.hasError()) {
  123.      if (Update.write(data, len) != len) {
  124.        Update.printError(Serial);
  125.      }
  126.    }
  127.    if (final) {
  128.      if (Update.end(true)) {
  129.        Serial.printf("[ UPDT ] Firmware update finished: %uB\n", index + len);
  130.      } else {
  131.        Update.printError(Serial);
  132.      }
  133.    }
  134.  });
  135.  
  136.  
  137.  
  138.  
  139.  
  140.  // Start Web Server
  141.  server.begin();
  142. }
  143.  
  144. // Main Loop
  145. void loop() {
  146.  // check for a new update and restart
  147.  if (shouldReboot) {
  148.    Serial.println(F("[ UPDT ] Rebooting..."));
  149.    delay(100);
  150.    ESP.restart();
  151.  }
  152.  unsigned long currentMillis = millis();
  153.  if (currentMillis - previousMillis >= activateTime && activateServo) {
  154.    for(pos = 0; pos <= 180; pos += 1) // goes from 0 degrees to 180 degrees
  155.    activateServo = false;
  156.  {
  157.    servo.write(pos);              // tell servo to go to position in variable 'pos'
  158.    delay(15);                       // waits 15ms for the servo to reach the position
  159.  }
  160.  }
  161.  if (activateServo) {
  162.    for(pos = 0; pos <= 180; pos += 1) // goes from 0 degrees to 180 degrees
  163.  {
  164.    servo.write(pos);              // tell servo to go to position in variable 'pos'
  165.    delay(15);                       // waits 15ms for the servo to reach the position
  166.  }
  167.  }
  168.  // Another loop for RFID Events, since we are using polling method instead of Interrupt we need to check RFID hardware for events
  169.  if (currentMillis >= cooldown) {
  170.    rfidloop();
  171.  }
  172. }
  173.  
  174.  
  175. /* ------------------ RFID Functions ------------------- */
  176. // RFID Specific Loop
  177. void rfidloop() {
  178.  //If a new PICC placed to RFID reader continue
  179.  if ( ! mfrc522.PICC_IsNewCardPresent()) {
  180.    delay(50);
  181.    return;
  182.  }
  183.  //Since a PICC placed get Serial (UID) and continue
  184.  if ( ! mfrc522.PICC_ReadCardSerial()) {
  185.    delay(50);
  186.    return;
  187.  }
  188.  // We got UID tell PICC to stop responding
  189.  mfrc522.PICC_HaltA();
  190.  cooldown = millis() + 2000;
  191.  
  192.  // There are Mifare PICCs which have 4 byte or 7 byte UID
  193.  // Get PICC's UID and store on a variable
  194.   Serial.print(F("[ INFO ] PICC's UID: "));
  195.   String uid = "";
  196.   for (int i = 0; i < mfrc522.uid.size; ++i) {
  197.     uid += String(mfrc522.uid.uidByte[i], HEX);
  198.   }
  199.   Serial.print(uid);
  200.   // Get PICC type
  201.   MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
  202.   String type = mfrc522.PICC_GetTypeName(piccType);
  203.  
  204.   // We are going to use filesystem to store known UIDs.
  205.   // If we know the PICC we need to know if its User have an Access
  206.   int AccType = 0;  // First assume User do not have access
  207.   // Prepend /P/ on filename so we distinguish UIDs from the other files
  208.   String filename = "/P/";
  209.   filename += uid;
  210.  
  211.   File f = SPIFFS.open(filename, "r");
  212.   // Check if we could find it above function returns true if the file is exist
  213.   if (f) {
  214.     // Now we need to read contents of the file to parse JSON object contains Username and Access Status
  215.     size_t size = f.size();
  216.     // Allocate a buffer to store contents of the file.
  217.     std::unique_ptr<char[]> buf(new char[size]);
  218.     // We don't use String here because ArduinoJson library requires the input
  219.    // buffer to be mutable. If you don't use ArduinoJson, you may as well
  220.     // use configFile.readString instead.
  221.     f.readBytes(buf.get(), size);
  222.     DynamicJsonBuffer jsonBuffer;
  223.     JsonObject& json = jsonBuffer.parseObject(buf.get());
  224.     // Check if we succesfully parse JSON object
  225.     if (json.success()) {
  226.       // Get username Access Status
  227.       String username = json["user"];
  228.       AccType = json["acctype"];
  229.       Serial.println(" = known PICC");
  230.       Serial.print("[ INFO ] User Name: ");
  231.       Serial.print(username);
  232.       // Check if user have an access
  233.       if (AccType == 1) {
  234.         activateServo = true;  // Give user Access to Door, Safe, Box whatever you like
  235.         previousMillis = millis();
  236.         Serial.println(" have access");
  237.       }
  238.       else {
  239.         Serial.println(" does not have access");
  240.       }
  241.       LogLatest(uid, username);
  242.       // Also inform Administrator Portal
  243.       // Encode a JSON Object and send it to All WebSocket Clients
  244.       DynamicJsonBuffer jsonBuffer2;
  245.       JsonObject& root = jsonBuffer2.createObject();
  246.       root["command"] = "piccscan";
  247.       // UID of Scanned RFID Tag
  248.       root["uid"] = uid;
  249.       // Type of PICC
  250.       root["type"] = type;
  251.       root["known"] = 1;
  252.       root["acctype"] = AccType;
  253.       // Username
  254.       root["user"] = username;
  255.       size_t len = root.measureLength();
  256.       AsyncWebSocketMessageBuffer * buffer = ws.makeBuffer(len); //  creates a buffer (len + 1) for you.
  257.       if (buffer) {
  258.         root.printTo((char *)buffer->get(), len + 1);
  259.         ws.textAll(buffer);
  260.       }
  261.     }
  262.     else {
  263.       Serial.println("");
  264.       Serial.println(F("[ WARN ] Failed to parse User Data"));
  265.     }
  266.     f.close();
  267.   }
  268.   else {
  269.     // If we don't know the UID, inform Administrator Portal so admin can give access or add it to database
  270.    LogLatest(uid, "Unknown");
  271.    Serial.println(" = unknown PICC");
  272.    DynamicJsonBuffer jsonBuffer;
  273.    JsonObject& root = jsonBuffer.createObject();
  274.    root["command"] = "piccscan";
  275.    // UID of Scanned RFID Tag
  276.    root["uid"] = uid;
  277.    // Type of PICC
  278.    root["type"] = type;
  279.    root["known"] = 0;
  280.    size_t len = root.measureLength();
  281.    AsyncWebSocketMessageBuffer * buffer = ws.makeBuffer(len); //  creates a buffer (len + 1) for you.
  282.    if (buffer) {
  283.      root.printTo((char *)buffer->get(), len + 1);
  284.      ws.textAll(buffer);
  285.    }
  286.  }
  287.  // So far got we got UID of Scanned RFID Tag, checked it if it's on the database and access status, informed Administrator Portal
  288. }
  289.  
  290. void LogLatest(String uid, String username) {
  291.   File logFile = SPIFFS.open("/auth/latestlog.json", "r");
  292.   if (!logFile) {
  293.     // Can not open file create it.
  294.     File logFile = SPIFFS.open("/auth/latestlog.json", "w");
  295.     DynamicJsonBuffer jsonBuffer3;
  296.     JsonObject& root = jsonBuffer3.createObject();
  297.     root["type"] = "latestlog";
  298.     JsonArray& list = root.createNestedArray("list");
  299.     root.printTo(logFile);
  300.     logFile.close();
  301.   }
  302.   else {
  303.     size_t size = logFile.size();
  304.     std::unique_ptr<char[]> buf (new char[size]);
  305.     logFile.readBytes(buf.get(), size);
  306.     DynamicJsonBuffer jsonBuffer4;
  307.     JsonObject& root = jsonBuffer4.parseObject(buf.get());
  308.     JsonArray& list = root["list"];
  309.     if (!root.success()) {
  310.       Serial.println("Impossible to read JSON file");
  311.     } else {
  312.       logFile.close();
  313.       if ( list.size() >= 15 ) {
  314.         list.remove(0);
  315.       }
  316.       File logFile = SPIFFS.open("/auth/latestlog.json", "w");
  317.       DynamicJsonBuffer jsonBuffer5;
  318.       JsonObject& item = jsonBuffer5.createObject();
  319.       item["uid"] = uid;
  320.       item["username"] = username;
  321.       item["timestamp"] = now();
  322.       list.add(item);
  323.       root.printTo(logFile);
  324.     }
  325.     logFile.close();
  326.   }
  327. }
  328.  
  329. // Handles WebSocket Events
  330. void onWsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len) {
  331.   if (type == WS_EVT_ERROR) {
  332.     Serial.printf("[ WARN ] WebSocket[%s][%u] error(%u): %s\r\n", server->url(), client->id(), *((uint16_t*)arg), (char*)data);
  333.   }
  334.   else if (type == WS_EVT_DATA) {
  335.  
  336.     AwsFrameInfo * info = (AwsFrameInfo*)arg;
  337.     String msg = "";
  338.  
  339.     if (info->final && info->index == 0 && info->len == len) {
  340.       //the whole message is in a single frame and we got all of it's data
  341.      for (size_t i = 0; i < info->len; i++) {
  342.        msg += (char) data[i];
  343.      }
  344.  
  345.      // We should always get a JSON object (stringfied) from browser, so parse it
  346.      DynamicJsonBuffer jsonBuffer;
  347.      JsonObject& root = jsonBuffer.parseObject(msg);
  348.      if (!root.success()) {
  349.        Serial.println(F("[ WARN ] Couldn't parse WebSocket message"));
  350.        return;
  351.      }
  352.  
  353.      // Web Browser sends some commands, check which command is given
  354.      const char * command = root["command"];
  355.  
  356.      // Check whatever the command is and act accordingly
  357.      if (strcmp(command, "remove")  == 0) {
  358.        const char* uid = root["uid"];
  359.        String filename = "/P/";
  360.        filename += uid;
  361.        SPIFFS.remove(filename);
  362.      }
  363.      else if (strcmp(command, "configfile")  == 0) {
  364.        File f = SPIFFS.open("/auth/config.json", "w+");
  365.        if (f) {
  366.          root.prettyPrintTo(f);
  367.          //f.print(msg);
  368.          f.close();
  369.          ESP.reset();
  370.        }
  371.      }
  372.      else if (strcmp(command, "userlist")  == 0) {
  373.        int page = root["page"];
  374.        sendUserList(page, client);
  375.      }
  376.      else if (strcmp(command, "status")  == 0) {
  377.        sendStatus();
  378.      }
  379.      else if (strcmp(command, "userfile")  == 0) {
  380.        const char* uid = root["uid"];
  381.        String filename = "/P/";
  382.        filename += uid;
  383.        File f = SPIFFS.open(filename, "w+");
  384.        // Check if we created the file
  385.        if (f) {
  386.          f.print(msg);
  387.        }
  388.        f.close();
  389.        ws.textAll("{\"command\":\"result\",\"resultof\":\"userfile\",\"result\": true}");
  390.       }
  391.       else if (strcmp(command, "testrelay")  == 0) {
  392.         activateServo = true;
  393.         previousMillis = millis();
  394.       }
  395.       else if (strcmp(command, "latestlog")  == 0) {
  396.         File logFile = SPIFFS.open("/auth/latestlog.json", "r");
  397.         if (logFile) {
  398.           size_t len = logFile.size();
  399.           AsyncWebSocketMessageBuffer * buffer = ws.makeBuffer(len); //  creates a buffer (len + 1) for you.
  400.           if (buffer) {
  401.             logFile.readBytes((char *)buffer->get(), len + 1);
  402.             ws.textAll(buffer);
  403.           }
  404.           logFile.close();
  405.         }
  406.       }
  407.       else if (strcmp(command, "scan")  == 0) {
  408.         WiFi.scanNetworksAsync(printScanResult, true);
  409.       }
  410.       else if (strcmp(command, "gettime")  == 0) {
  411.         sendTime();
  412.       }
  413.       else if (strcmp(command, "settime")  == 0) {
  414.         unsigned long t = root["epoch"];
  415.         setTime(t);
  416.         sendTime();
  417.       }
  418.       else if (strcmp(command, "getconf")  == 0) {
  419.         File configFile = SPIFFS.open("/auth/config.json", "r");
  420.         if (configFile) {
  421.           size_t len = configFile.size();
  422.           AsyncWebSocketMessageBuffer * buffer = ws.makeBuffer(len); //  creates a buffer (len + 1) for you.
  423.           if (buffer) {
  424.             configFile.readBytes((char *)buffer->get(), len + 1);
  425.             ws.textAll(buffer);
  426.           }
  427.           configFile.close();
  428.         }
  429.       }
  430.     }
  431.   }
  432. }
  433.  
  434. void sendTime() {
  435.   DynamicJsonBuffer jsonBuffer;
  436.   JsonObject& root = jsonBuffer.createObject();
  437.   root["command"] = "gettime";
  438.   root["epoch"] = now();
  439.   root["timezone"] = timeZone;
  440.   size_t len = root.measureLength();
  441.   AsyncWebSocketMessageBuffer * buffer = ws.makeBuffer(len); //  creates a buffer (len + 1) for you.
  442.   if (buffer) {
  443.     root.printTo((char *)buffer->get(), len + 1);
  444.     ws.textAll(buffer);
  445.   }
  446. }
  447.  
  448.  
  449. void sendUserList(int page, AsyncWebSocketClient * client) {
  450.   DynamicJsonBuffer jsonBuffer;
  451.   JsonObject& root = jsonBuffer.createObject();
  452.   root["command"] = "userlist";
  453.   root["page"] = page;
  454.   JsonArray& users = root.createNestedArray("list");
  455.   Dir dir = SPIFFS.openDir("/P/");
  456.   int first = (page - 1) * 15;
  457.   int last = page * 15;
  458.   int i = 0;
  459.   while (dir.next()) {
  460.     if (i >= first && i < last) {
  461.       JsonObject& item = users.createNestedObject();
  462.       String uid = dir.fileName();
  463.       uid.remove(0, 3);
  464.       item["uid"] = uid;
  465.       File f = SPIFFS.open(dir.fileName(), "r");
  466.       size_t size = f.size();
  467.       // Allocate a buffer to store contents of the file.
  468.       std::unique_ptr<char[]> buf(new char[size]);
  469.       // We don't use String here because ArduinoJson library requires the input
  470.      // buffer to be mutable. If you don't use ArduinoJson, you may as well
  471.       // use configFile.readString instead.
  472.       f.readBytes(buf.get(), size);
  473.       DynamicJsonBuffer jsonBuffer2;
  474.       JsonObject& json = jsonBuffer2.parseObject(buf.get());
  475.       if (json.success()) {
  476.         String username = json["user"];
  477.         int AccType = json["acctype"];
  478.         unsigned long validuntil = json["validuntil"];
  479.         item["username"] = username;
  480.         item["acctype"] = AccType;
  481.         item["validuntil"] = validuntil;
  482.       }
  483.     }
  484.     i++;
  485.   }
  486.   float pages = i / 15.0;
  487.   root["haspages"] = ceil(pages);
  488.   size_t len = root.measureLength();
  489.   AsyncWebSocketMessageBuffer * buffer = ws.makeBuffer(len); //  creates a buffer (len + 1) for you.
  490.   if (buffer) {
  491.     root.printTo((char *)buffer->get(), len + 1);
  492.     if (client) {
  493.       client->text(buffer);
  494.       client->text("{\"command\":\"result\",\"resultof\":\"userlist\",\"result\": true}");
  495.     } else {
  496.       ws.textAll("{\"command\":\"result\",\"resultof\":\"userlist\",\"result\": false}");
  497.     }
  498.   }
  499. }
  500.  
  501. #ifdef ESP8266
  502. extern "C" {
  503. #include "user_interface.h"  // Used to get Wifi status information
  504. }
  505. #endif
  506.  
  507. void sendStatus() {
  508.   struct ip_info info;
  509.   FSInfo fsinfo;
  510.   if (!SPIFFS.info(fsinfo)) {
  511.     Serial.print(F("[ WARN ] Error getting info on SPIFFS"));
  512.   }
  513.   DynamicJsonBuffer jsonBuffer;
  514.   JsonObject& root = jsonBuffer.createObject();
  515.   root["command"] = "status";
  516.  
  517.   root["heap"] = ESP.getFreeHeap();
  518.   root["chipid"] = String(ESP.getChipId(), HEX);
  519.   root["cpu"] = ESP.getCpuFreqMHz();
  520.   root["availsize"] = ESP.getFreeSketchSpace();
  521.   root["availspiffs"] = fsinfo.totalBytes - fsinfo.usedBytes;
  522.   root["spiffssize"] = fsinfo.totalBytes;
  523.   root["uptime"] = NTP.getUptimeString();
  524.  
  525.   if (inAPMode) {
  526.     wifi_get_ip_info(SOFTAP_IF, &info);
  527.     struct softap_config conf;
  528.     wifi_softap_get_config(&conf);
  529.     root["ssid"] = String(reinterpret_cast<char*>(conf.ssid));
  530.     root["dns"] = printIP(WiFi.softAPIP());
  531.     root["mac"] = WiFi.softAPmacAddress();
  532.   }
  533.   else {
  534.     wifi_get_ip_info(STATION_IF, &info);
  535.     struct station_config conf;
  536.     wifi_station_get_config(&conf);
  537.     root["ssid"] = String(reinterpret_cast<char*>(conf.ssid));
  538.     root["dns"] = printIP(WiFi.dnsIP());
  539.     root["mac"] = WiFi.macAddress();
  540.   }
  541.  
  542.   IPAddress ipaddr = IPAddress(info.ip.addr);
  543.   IPAddress gwaddr = IPAddress(info.gw.addr);
  544.   IPAddress nmaddr = IPAddress(info.netmask.addr);
  545.   root["ip"] = printIP(ipaddr);
  546.   root["gateway"] = printIP(gwaddr);
  547.   root["netmask"] = printIP(nmaddr);
  548.  
  549.   size_t len = root.measureLength();
  550.   AsyncWebSocketMessageBuffer * buffer = ws.makeBuffer(len); //  creates a buffer (len + 1) for you.
  551.   if (buffer) {
  552.     root.printTo((char *)buffer->get(), len + 1);
  553.     ws.textAll(buffer);
  554.   }
  555. }
  556.  
  557. String printIP(IPAddress adress) {
  558.   return (String)adress[0] + "." + (String)adress[1] + "." + (String)adress[2] + "." + (String)adress[3];
  559. }
  560.  
  561. // Send Scanned SSIDs to websocket clients as JSON object
  562. void printScanResult(int networksFound) {
  563.   DynamicJsonBuffer jsonBuffer;
  564.   JsonObject& root = jsonBuffer.createObject();
  565.   root["command"] = "ssidlist";
  566.   JsonArray& scan = root.createNestedArray("list");
  567.   for (int i = 0; i < networksFound; ++i) {
  568.     JsonObject& item = scan.createNestedObject();
  569.     // Print SSID for each network found
  570.     item["ssid"] = WiFi.SSID(i);
  571.     item["bssid"] = WiFi.BSSIDstr(i);
  572.     item["rssi"] = WiFi.RSSI(i);
  573.     item["channel"] = WiFi.channel(i);
  574.     item["enctype"] = WiFi.encryptionType(i);
  575.     item["hidden"] = WiFi.isHidden(i)?true:false;
  576.   }
  577.   size_t len = root.measureLength();
  578.   AsyncWebSocketMessageBuffer * buffer = ws.makeBuffer(len); //  creates a buffer (len + 1) for you.
  579.   if (buffer) {
  580.     root.printTo((char *)buffer->get(), len + 1);
  581.     ws.textAll(buffer);
  582.   }
  583.   WiFi.scanDelete();
  584. }
  585.  
  586.  
  587. // Fallback to AP Mode, so we can connect to ESP if there is no Internet connection
  588. void fallbacktoAPMode() {
  589.   inAPMode = true;
  590.   WiFi.mode(WIFI_AP);
  591.   Serial.print(F("[ INFO ] Configuring access point... "));
  592.   Serial.println(WiFi.softAP("ESP-RFID") ? "Ready" : "Failed!");
  593.   // Access Point IP
  594.   IPAddress myIP = WiFi.softAPIP();
  595.   Serial.print(F("[ INFO ] AP IP address: "));
  596.   Serial.println(myIP);
  597.   server.serveStatic("/auth/", SPIFFS, "/auth/").setDefaultFile("users.htm").setAuthentication("admin", "admin");
  598. }
  599. void parseBytes(const char* str, char sep, byte* bytes, int maxBytes, int base) {
  600.   for (int i = 0; i < maxBytes; i++) {
  601.     bytes[i] = strtoul(str, NULL, base);  // Convert byte
  602.     str = strchr(str, sep);               // Find next separator
  603.     if (str == NULL || *str == '\0') {
  604.       break;                            // No more separators, exit
  605.     }
  606.     str++;                                // Point to next character after separator
  607.   }
  608. }
  609. bool loadConfiguration() {
  610.   File configFile = SPIFFS.open("/auth/config.json", "r");
  611.   if (!configFile) {
  612.     Serial.println(F("[ WARN ] Failed to open config file"));
  613.     return false;
  614.   }
  615.   size_t size = configFile.size();
  616.   // Allocate a buffer to store contents of the file.
  617.   std::unique_ptr<char[]> buf(new char[size]);
  618.   // We don't use String here because ArduinoJson library requires the input
  619.  // buffer to be mutable. If you don't use ArduinoJson, you may as well
  620.   // use configFile.readString instead.
  621.   configFile.readBytes(buf.get(), size);
  622.   DynamicJsonBuffer jsonBuffer;
  623.   JsonObject& json = jsonBuffer.parseObject(buf.get());
  624.   if (!json.success()) {
  625.     Serial.println(F("[ WARN ] Failed to parse config file"));
  626.     return false;
  627.   }
  628.   Serial.println(F("[ INFO ] Config file found"));
  629.   json.prettyPrintTo(Serial);
  630.   Serial.println();
  631.   int rfidss = json["sspin"];
  632.   int rfidgain = json["rfidgain"];
  633.   Serial.println(F("[ INFO ] Trying to setup RFID Hardware"));
  634.   setupRFID(rfidss, rfidgain);
  635.  
  636.   const char * hstname = json["hostnm"];
  637.   const char * bssidmac = json["bssid"];
  638.   byte bssid[6];
  639.   parseBytes(bssidmac, ':', bssid, 6, 16);
  640.  
  641.   // Set Hostname.
  642.   WiFi.hostname(hstname);
  643.  
  644.   // Start mDNS service so we can connect to http://esp-rfid.local (if Bonjour installed on Windows or Avahi on Linux)
  645.   if (!MDNS.begin(hstname)) {
  646.     Serial.println("Error setting up MDNS responder!");
  647.   }
  648.   // Add Web Server service to mDNS
  649.   MDNS.addService("http", "tcp", 80);
  650.  
  651.   const char * ntpserver = json["ntpserver"];
  652.   int ntpinter = json["ntpinterval"];
  653.   timeZone = json["timezone"];
  654.  
  655.   activateTime = json["rtime"];
  656.   relayPin = json["rpin"];
  657.   relayType = json["rtype"];
  658.   pinMode(relayPin, OUTPUT);
  659.   digitalWrite(relayPin, relayType);
  660.  
  661.   const char * ssid = json["ssid"];
  662.   const char * password = json["pswd"];
  663.   int wmode = json["wmode"];
  664.  
  665.   const char * adminpass = json["adminpwd"];
  666.  
  667.   // Serve confidential files in /auth/ folder with a Basic HTTP authentication
  668.   server.serveStatic("/auth/", SPIFFS, "/auth/").setDefaultFile("users.htm").setAuthentication("admin", adminpass);
  669.  
  670.   if (wmode == 1) {
  671.     inAPMode = true;
  672.     Serial.println(F("[ INFO ] ESP-RFID is running in AP Mode "));
  673.     WiFi.mode(WIFI_AP);
  674.     Serial.print(F("[ INFO ] Configuring access point... "));
  675.     Serial.println(WiFi.softAP(ssid, password) ? "Ready" : "Failed!");
  676.     // Access Point IP
  677.     IPAddress myIP = WiFi.softAPIP();
  678.     Serial.print(F("[ INFO ] AP IP address: "));
  679.     Serial.println(myIP);
  680.     Serial.print(F("[ INFO ] AP SSID: "));
  681.     Serial.println(ssid);
  682.     return true;
  683.   }
  684.   else if (!connectSTA(ssid, password, bssid)) {
  685.     return false;
  686.   }
  687.   NTP.begin(ntpserver, timeZone);
  688.   NTP.setInterval(ntpinter * 60); // Poll every x minutes
  689.  
  690.   return true;
  691. }
  692.  
  693. // Configure RFID Hardware
  694. void setupRFID(int rfidss, int rfidgain) {
  695.   SPI.begin();           // MFRC522 Hardware uses SPI protocol
  696.   mfrc522.PCD_Init(rfidss, UINT8_MAX);    // Initialize MFRC522 Hardware
  697.   // Set RFID Hardware Antenna Gain
  698.   // This may not work with some boards
  699.   mfrc522.PCD_SetAntennaGain(rfidgain);
  700.   Serial.printf("[ INFO ] RFID SS_PIN: %u and Gain Factor: %u", rfidss, rfidgain);
  701.   Serial.println("");
  702.   ShowReaderDetails(); // Show details of PCD - MFRC522 Card Reader details
  703. }
  704.  
  705. // Try to connect Wi-Fi
  706. bool connectSTA(const char* ssid, const char* password, byte bssid[6]) {
  707.   WiFi.mode(WIFI_STA);
  708.   // First connect to a wi-fi network
  709.   WiFi.begin(ssid, password, 0, bssid);
  710.   // Inform user we are trying to connect
  711.   Serial.print(F("[ INFO ] Trying to connect WiFi: "));
  712.   Serial.print(ssid);
  713.   // We try it for 20 seconds and give up on if we can't connect
  714.  unsigned long now = millis();
  715.  uint8_t timeout = 20; // define when to time out in seconds
  716.  // Wait until we connect or 20 seconds pass
  717.  do {
  718.    if (WiFi.status() == WL_CONNECTED) {
  719.      break;
  720.    }
  721.    delay(500);
  722.    Serial.print(F("."));
  723.  }
  724.  while (millis() - now < timeout * 1000);
  725.  // We now out of the while loop, either time is out or we connected. check what happened
  726.  if (WiFi.status() == WL_CONNECTED) { // Assume time is out first and check
  727.    Serial.println();
  728.    Serial.print(F("[ INFO ] Client IP address: ")); // Great, we connected, inform
  729.    Serial.println(WiFi.localIP());
  730.    return true;
  731.  }
  732.  else { // We couln't connect, time is out, inform
  733.     Serial.println();
  734.     Serial.println(F("[ WARN ] Couldn't connect in time"));
  735.     return false;
  736.   }
  737. }
  738.  
  739. void ShowReaderDetails() {
  740.   // Get the MFRC522 software version
  741.   byte v = mfrc522.PCD_ReadRegister(mfrc522.VersionReg);
  742.   Serial.print(F("[ INFO ] MFRC522 Version: 0x"));
  743.   Serial.print(v, HEX);
  744.   if (v == 0x91)
  745.     Serial.print(F(" = v1.0"));
  746.   else if (v == 0x92)
  747.     Serial.print(F(" = v2.0"));
  748.   else if (v == 0x88)
  749.     Serial.print(F(" = clone"));
  750.   else
  751.     Serial.print(F(" (unknown)"));
  752.   Serial.println("");
  753.   // When 0x00 or 0xFF is returned, communication probably failed
  754.   if ((v == 0x00) || (v == 0xFF)) {
  755.     Serial.println(F("[ WARN ] Communication failure, check if MFRC522 properly connected"));
  756.   }
  757. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement