Mạch Điện

Hệ thống chấm công sinh trắc học tích hợp trang tính của Google Sheet

Trong các  công ty xí nghiệp việc chấm công rất quan trong .Các công ty phải đối mặt với rất nhiều vấn đề do thiếu một hệ thống giám sát chấm công thích hợp. Để khắc phục điều này, chúng ta phải cần một hệ thống chấm công nhanh chóng, không bị giả mạo, không cần giám sát và cách tốt nhất cho nó là sử dụng hệ thống nhận dạng sinh trắc học.

Trong số các Hệ thống chấm công sinh trắc học tích hợp trang tính của Google Sheet khác nhau, Hệ thống nhận dạng vân tay là một trong những hệ thống nổi tiếng và được sử dụng phổ biến nhất vì nó nhanh chóng, đáng tin cậy và chống giả mạo. Do tính duy nhất và tính nhất quán của chúng theo thời gian, dấu vân tay đã được sử dụng để nhận dạng trong nhiều năm, gần đây trở nên tự động hơn do những tiến bộ trong khả năng tính toán. Hãy tham khảo với hocdientu nhé !

Hệ thống chấm công sinh trắc học tích hợp trang tính của Google Sheet
Hệ thống chấm công sinh trắc học tích hợp trang tính của Google Sheet

Dấu vân tay của mỗi nhân viên sẽ được lưu trữ trong mô-đun dấu vân tay với một ID duy nhất. Cơ sở dữ liệu SQLite được lưu giữ và duy trì với tất cả các thông tin chi tiết về nhân viên với ID vân tay duy nhất tương ứng. Sau khi nhân viên quét dấu vân tay của họ, dấu vân tay đó sẽ được xác minh và ID duy nhất được tham chiếu chéo với cơ sở dữ liệu nhân viên. Khi nhân viên được xác định, việc tham dự sẽ được đánh dấu trong cơ sở dữ liệu cục bộ và dữ liệu tương tự sẽ được đồng bộ hóa với Google Trang tính. Việc tham dự có thể được theo dõi thông qua Google Trang tính.

Việc đăng ký nhân viên và quản lý cơ sở dữ liệu được thực hiện thông qua một cổng web được bảo vệ bằng mật khẩu và có thể tùy chỉnh. Quản trị viên cũng có thể thay đổi các cài đặt thiết bị cơ bản khác bao gồm tên thiết bị, thông tin đăng nhập mạng, cài đặt mạng, thời gian và thông tin đăng nhập Google Script. Cổng thông tin điện tử có thể được truy cập bằng địa chỉ IP hoặc địa chỉ MDNS. Thời gian được lưu giữ ngay cả khi mất điện với mô-đun RTC, vì vậy dữ liệu chấm công là chính xác.

Các linh kiện cần thiết để xây dựng hệ thống chấm công sinh trắc học

Số lượng các linh kiện cần thiết để xây dựng Project này rất ít. Các linh kiện bắt buộc phải có như sau:

  • ESP32
  • Mô-đun in dấu vân tay R307
  • Mô-đun RTC DS1307
  • Mô-đun OLED 128×64 SSD1306
  • Ván đục lỗ
  • Dây điện
  • Kết nối
  • Nguồn điện 5V

Sơ đồ mạch hệ thống chấm công sinh trắc học

Đây là sơ đồ mạch cho hệ thống điểm danh Sinh trắc học. Các kết nối khá đơn giản. Kết nối các chân VCC và GND của FR307, màn hình OLED và mô-đun RTC với chân 3,3V và chân GND tương ứng. Sau đó, kết nối các chân SDA và SCL của mô-đun RTC và màn hình OLED với GPIO21 và GPIO22 tương ứng. Bây giờ kết nối chân TX từ FR307 đến GPIO16 và chân RX với GPIO17.

Sơ đồ mạch hệ thống chấm công sinh trắc học
Sơ đồ mạch hệ thống chấm công sinh trắc học

Đây là mạch đã hoàn thành đầy đủ :

Chúng tôi đã tạo ra một vỏ bọc đơn giản cho Project này. Bạn có thể tải xuống các tệp 3D cần thiết từ repo GitHub. Vỏ được in bằng vật liệu PLA. Đây là vỏ máy in 3D.

Đây là hình ảnh bên trong của bao vây. Bạn có thể sử dụng một ít keo nóng để cố định màn hình vào vỏ máy.

Tạo Google Trang tính để ghi nhật ký chấm công

Khi tất cả các kết nối đã hoàn tất, đã đến lúc tạo Google Trang tính để ghi nhật ký tham dự. Đối với điều đó, hãy truy cập Google trang tính và đăng nhập bằng tài khoản Google của bạn. Sau đó, tạo một trang tính mới chính xác như được đưa ra bên dưới. Đặt tên trang tính là tham dự và đặt tên cho các cột như sau – DateTimeEmployee_IDEmpolyee_NameEmployee_Email_ID , Position và Punch_In_or_Out .

Tạo Google Trang tính để ghi nhật ký chấm công
Tạo Google Trang tính để ghi nhật ký chấm công

Bây giờ hãy lưu trang tính và chọn Apps Script từ Menu Tiện ích mở rộng và tạo một tập lệnh mới với Code sau trong đó và triển khai nó.

var sheet_id = "1tLe_DtcYxT_M7vxxxxxxxxxxxxxxxxxxxxxxy7uZs6aQ8";
var sheet_name = "attendance";
function doGet(e){
var ss = SpreadsheetApp.openById(sheet_id);
var sheet = ss.getSheetByName(sheet_name);
var Date = e.parameter.date;
var Time = e.parameter.time;
var Employee_ID = e.parameter.empid;
var Employee_Name = e.parameter.empname;
var Employee_Email_ID = e.parameter.empemail;
var Position = e.parameter.emppos;
var Punch_In_or_Out = e.parameter.emppio;
sheet.appendRow([Date,Time,Employee_ID,Employee_Name,Employee_Email_ID,Position,Punch_In_or_Out]);
}

Thay thế Sheet_id bằng ID trang tính của riêng bạn. Lưu nó và triển khai nó. Ghi lại ID Google Script, ID này sẽ được nhập vào Thiết bị để tải lên dữ liệu.

Tệp HTML và CSS

Thiết bị sử dụng HTML với CSS và JavaScript để lưu trữ và kiểm soát cổng thông tin web. Tất cả các tệp yêu cầu được đính kèm bên dưới bài viết này. Vui lòng tải chúng xuống và giữ chúng trong một thư mục có tên là dữ liệu trong thư mục phác thảo. Có nhiều trang HTML cho nhiều chức năng và tất cả đều quan trọng.

Mẫu cơ sở dữ liệu SQLLite

Đối với cơ sở dữ liệu, chúng tôi sẽ sử dụng thư viện SQLLite cho ESP32. Tải xuống và cài đặt thư viện từ liên kết được cung cấp trong phần Code bên dưới. Và chúng ta sẽ cần một mẫu cơ sở dữ liệu trống để ESP32 hoạt động. Tệp này, có tên là test1.db cũng được bao gồm trong tệp đã tải xuống và được giữ trong thư mục dữ liệu cùng với tệp HTML và CSS.

Tải lên tệp cơ sở dữ liệu HTML và SQL lên ESP32

Để tải các tệp này lên hệ thống tệp, chúng tôi sẽ cần một công cụ có tên là trình tải lên hệ thống tệp ESP32. Để cài đặt công cụ này vào Arduino IDE của bạn, hãy làm theo các bước sau

  • Truy cập https://github.com/me-no-dev/arduino-esp32fs-plugin/releases/  và tải xuống ESP32FS-1.0.zip .
  • Giải nén tệp zip vào thư mục Công cụ trong thư mục Arduino IDE. Sau khi giải nén, đường dẫn sẽ giống như sau “ C: \ Users \ Username \ Documents \ Arduino \ tools \ ESP32FS \ tool \ esp32fs.jar ”
  • Khởi động lại Arduino IDE và bạn có thể sử dụng công cụ này bằng cách nhấp vào Menu Công cụ.

Code Arduino cho Hệ thống chấm công sinh trắc học

Cùng với tệp .ino chính , có bốn tệp khác cần có trong thư mục phác thảo. Tải xuống chúng từ liên kết bên dưới bài viết và đặt chúng vào thư mục Sketch. Tệp icon.h chứa tất cả các biểu tượng được sử dụng cho màn hình OLED và tệp robotbold10.h và seg.h là tệp phông chữ cho OLED. Tệp credit.h chứa các tham số mặc định, bạn có thể thay đổi chúng theo nhu cầu của mình. Ngay cả khi bạn không thay đổi chúng, bạn có thể thay đổi chúng sau này thông qua cổng web.

Hầu hết các thư viện đã được cài đặt với gói bảng ESP32. Những người khác được bao gồm trong chính thư mục phác thảo. Tải xuống tất cả các tệp từ trang GitHub của Project và giải nén chúng vào một thư mục. Bạn không cần cài đặt bất kỳ thư viện nào khác. Đảm bảo rằng bạn không thay đổi bất kỳ đường dẫn tệp hoặc lệnh gọi tiêu đề nào.

Lưu ý: Code hoàn chỉnh được đưa ra ở cuối trang.

Và đảm bảo chọn No OTA (2MB APP / 2MB SPIFFS) từ tùy chọn Partition Scheme.

Sau khi được biên dịch, hãy lập trình nó vào ESP32.

Thiết lập ban đầu

Sau khi được lập trình, thiết bị sẽ khởi động và hiển thị hình ảnh khởi động và sau đó sẽ hiển thị biểu tượng Wi-Fi trên màn hình OLED. Đối với lần khởi động đầu tiên hoặc nếu không có thông tin đăng nhập Wi-Fi nào được lưu, thiết bị sẽ tìm kiếm mạng WiFi mặc định với chỉ số mạch SSID và chỉ số mật khẩu . Tạo điểm phát sóng WiFi bằng những thông tin đăng nhập này hoặc tạm thời thay đổi thông tin đăng nhập WiFi của bạn thành những thông tin này. Khi mạng được phát hiện, thiết bị sẽ kết nối với mạng đó và sẽ hoàn tất quá trình khởi động.

Sau khi khởi động, hãy mở trình duyệt web của bạn trên PC hoặc máy tính xách tay được kết nối với cùng một mạng và truy cập URL http: //biometric.local/ . Điều tương tự có thể được sử dụng với bất kỳ thiết bị Apple hoặc IOS. Xin lưu ý rằng URL này sẽ không hoạt động với các thiết bị Android vì Android không hỗ trợ MDNS. Để truy cập từ các thiết bị đó hoặc bất kỳ thiết bị nào khác, bạn có thể sử dụng địa chỉ IP của thiết bị. Sau khi truy cập URL, bạn sẽ được chào đón với trang đăng nhập. Đăng nhập với quản trị viên tên người dùng và mật khẩu mặc định.

Sau khi đăng nhập, hãy chuyển đến trang cài đặt. Trên trang cài đặt, cung cấp dữ liệu sau và lưu.

  • SSID: SSID WiFi của bạn.
  • Mật khẩu: SSID WiFi của bạn.
  • Tên thiết bị: Mặc định là sinh trắc học. Nếu bạn thay đổi điều này, địa chỉ gốc của bạn cũng sẽ được thay đổi (ví dụ: http: / /biometric.local/).
  • Google Script ID: ID  Google Script của bạn.
  • Tên người dùng đăng nhập: Tên người dùng đăng nhập, mặc định là quản trị viên.
  • Mật khẩu đăng nhập: Mật khẩu đăng nhập, mặc định là quản trị viên.
  • Tên tổ chức: Tên sẽ được hiển thị trên màn hình OLED.
  • IP tự động / IP thủ công: Chọn nếu bạn muốn sử dụng DHCP hoặc IP thủ công.
  • IP thủ công & Gateway:  thêm IP và cổng vào của bạn nếu bạn muốn sử dụng IP thủ công.
  • Ngày và giờ: Đặt ngày và giờ chính xác.

Khi bạn đã nhập tất cả các chi tiết, hãy nhấp vào lưu. Thiết bị sẽ cảnh báo rằng thiết bị sẽ khởi động lại. Nhấp vào ok và thiết bị sẽ khởi động lại và kết nối với mạng đã cấu hình. Bạn có thể thay đổi các cài đặt này bất cứ khi nào bạn muốn bằng cách đăng nhập vào cổng và thêm các giá trị vào trang cài đặt. Hãy nhớ rằng nếu bạn để trống bất kỳ trường nào trong khi nhấp vào lưu, trường đó sẽ được đặt lại về mặc định.

Đăng ký hoặc Thêm ID mới:

Đăng ký ID mới thực sự đơn giản. Đi tới trang Đăng ký và nhập tất cả các chi tiết. Sau khi tất cả các chi tiết được nhập, hãy nhấp vào Đăng ký và nhấp vào Ok khi trình duyệt nhắc. Sau đó, làm theo hướng dẫn trên màn hình OLED. Sau khi đăng ký xong, bạn sẽ được tự động chuyển đến trang Cơ sở dữ liệu. Nếu kết nạp thành công, thông tin chi tiết về nhân viên mới sẽ được thêm vào cơ sở dữ liệu và sẽ được hiển thị trong bảng.

Xóa Nhân viên khỏi Cơ sở dữ liệu:

Để xóa người dùng hoặc nhân viên, hãy truy cập trang Cơ sở dữ liệu và nhấp vào nút Xóa gần chi tiết người dùng và xác nhận bằng cách nhấp vào Ok khi được nhắc. Chi tiết người dùng và dữ liệu dấu vân tay sẽ bị xóa khỏi Cơ sở dữ liệu.

Hoạt động bình thường:

Sau khi thiết lập ban đầu, khi được bật nguồn, thiết bị sẽ kiểm tra mạng đã cấu hình. Nếu mạng được cấu hình khả dụng, thiết bị sẽ kết nối với mạng đó và hoàn tất quá trình khởi động. Nếu không có mạng, thiết bị sẽ kiểm tra trong vài giây rồi hoàn tất quá trình khởi động. Nếu mạng không được kết nối, thiết bị sẽ kiểm tra mạng định kỳ và sẽ kết nối với mạng đó khi có sẵn.

Khi một nhân viên quét ngón tay của mình nếu dấu vân tay được xác định, sự tham dự sẽ được đánh dấu trên cơ sở dữ liệu cục bộ và cũng sẽ được tải lên google sheet nếu kết nối đang hoạt động. Nếu người đó đang quét lần đầu tiên vào ngày đó, sự tham dự sẽ được đánh dấu là Punchin. Và nếu đó là lần thứ hai trong ngày, lượt tham dự sẽ được đánh dấu là Punchout. Nếu người dùng quét lại, tức là Hơn hai lần một ngày, thiết bị sẽ hiển thị thông báo lỗi Already punch out, hãy thử lại vào ngày mai. Tính năng này sẽ ngăn nhân viên giả mạo dữ liệu chấm công.

Thiết bị sẽ lưu dữ liệu chấm công trong 7 ngày. Nếu mạng không khả dụng trong bất kỳ khoảng thời gian nào, thiết bị sẽ tự động đồng bộ hóa dữ liệu chưa được đồng bộ hóa khi kết nối được thiết lập vào lần tiếp theo.

Truy cập Dữ liệu chấm công :

Để truy cập dữ liệu chấm công, bạn chỉ cần mở google sheet mà bạn đã tạo. Tất cả dữ liệu đã đồng bộ hóa sẽ có sẵn trên Google Trang tính.

Bây giờ chúng ta hãy xem các thành phần chính và thông số kỹ thuật của chúng.

ESP32

ESP32 bao gồm một mô-đun ESP-WROOM-32. Đó là bộ vi điều khiển lõi kép 32 bit với WiFi và Bluetooth tích hợp. ESP32 có thể hoạt động với xung nhịp lên đến 240MHz và có RAM 521kB. Mô-đun ESP-WROOM-32 cũng được trang bị bộ lưu trữ flash SPI 4MB, có thể được sử dụng cho khu vực ứng dụng cũng như hệ thống tệp. Dưới đây là thông số kỹ thuật của Bộ phát triển ESP-WROOM-32.

Bộ xử lý:

  • CPU: Bộ vi xử lý Xtensa lõi kép (hoặc lõi đơn) 32-bit LX6, hoạt động ở 160 hoặc 240 MHz và hiệu suất lên đến 600 DMIPS
  • Bộ đồng xử lý công suất cực thấp (ULP)

Kỉ niệm:

  • 320 KiB RAM, 448 KiB ROM

Kết nối không dây:

  • Wi-Fi: 802.11 b / g / n
  • Bluetooth: v4.2 BR / EDR và ​​BLE (chia sẻ radio với Wi-Fi)

Giao diện ngoại vi:

  • 34 × GPIO có thể lập trình
  • 12-bit SAR ADC lên đến 18 kênh
  • DAC 2 × 8-bit
  • Cảm biến cảm ứng 10 × (GPIO cảm ứng điện dung)
  • 4 × SPI
  • 2 × giao diện I²S
  • 2 × giao diện I²C
  • 3 × UART
  • Bộ điều khiển máy chủ lưu trữ SD / SDIO / CE-ATA / MMC / eMMC
  • Bộ điều khiển nô lệ SDIO / SPI
  • Giao diện Ethernet MAC với DMA chuyên dụng và hỗ trợ Giao thức thời gian chính xác IEEE 1588 theo kế hoạch [4]
  • CAN xe buýt 2.0
  • Bộ điều khiển từ xa hồng ngoại (TX / RX, lên đến 8 kênh)
  • Động cơ PWM
  • LED PWM (lên đến 16 kênh)
  • Cảm biến hiệu ứng hall
  • Bộ tiền khuếch đại analog công suất cực thấp

Bảo vệ:

  • Tất cả các tính năng bảo mật chuẩn IEEE 802.11 đều được hỗ trợ, bao gồm WPA, WPA2, WPA3 (tùy thuộc vào phiên bản) [5] và Cơ sở hạ tầng bảo mật và xác thực WLAN (WAPI)
  • Khởi động an toàn
  • Code hóa flash
  • 1024-bit OTP, lên đến 768-bit cho khách hàng
  • Tăng tốc phần cứng mật Code: AES, SHA-2, RSA, mật Code đường cong elliptic (ECC), trình tạo số ngẫu nhiên (RNG)

Quản lý năng lượng:

  • Cơ quan quản lý tỷ lệ bỏ học thấp nội bộ
  • Miền nguồn riêng cho RTC
  • Dòng điện không tải 5 μA
  • Đánh thức từ ngắt GPIO, hẹn giờ, đo ADC, ngắt cảm biến cảm ứng điện dung

Mô-đun cảm biến vân tay

Như đã đề cập, dấu vân tay là một trong những cách duy nhất để xác định một cá nhân. Có nhiều loại cảm biến vân tay có sẵn trên thị trường. Việc phân loại chính dựa trên cách họ thu thập dữ liệu dấu vân tay. Cảm biến vân tay quang học là cảm biến vân tay điện dung.

Cảm biến vân tay điện dung:

Cảm biến điện dung sử dụng các mảng mạch tụ điện cực nhỏ để thu thập dữ liệu. Khi các tụ điện lưu trữ điện tích, việc kết nối chúng với các tấm dẫn điện trên bề mặt của máy quét cho phép chúng được sử dụng để theo dõi các chi tiết của dấu vân tay. Điện tích được lưu trữ sẽ thay đổi một chút khi một đầu ngón tay đặt lên các tấm dẫn điện. Ngược lại, một khe hở không khí sẽ làm cho điện tích ở tụ điện tương đối không thay đổi. Một mạch tích hợp op-amp được sử dụng để theo dõi những thay đổi này, sau đó có thể được ghi lại bằng bộ chuyển đổi tương tự sang kỹ thuật số. Sau khi được chụp, dữ liệu kỹ thuật số này sẽ được phân tích để tìm kiếm các thuộc tính dấu vân tay đặc biệt và duy nhất.

Cảm biến vân tay quang học:

Cảm biến vân tay quang học dựa trên nguyên tắc Phản xạ toàn phần bên trong hoặc TRI. Cảm biến vân tay quang học bao gồm nguồn sáng, lăng kính, thấu kính và cảm biến hình ảnh. Ánh sáng từ một nguồn (thường là đèn LED) đi vào lăng kính từ một mặt ở một góc nhất định, sao cho nó bị phản xạ từ mặt liền kề và tồn tại qua mặt thứ ba. Ánh sáng này sau đó đi qua một ống kính và đến cảm biến hình ảnh. Khi không có ngón tay đặt trên cảm biến, ánh sáng sẽ hoàn toàn phản xạ khỏi bề mặt và điều này tạo ra hình ảnh đơn giản trên cảm biến hình ảnh. Khi có một ngón tay đặt trên cảm biến, một phần ánh sáng sẽ bị phản xạ và điều này tạo ra hình ảnh của mẫu vân tay. Ánh sáng bị rò rỉ dọc theo bề mặt của lăng kính được gọi là Sóng Evanescent.

Các vật liệu khác nhau có các chỉ số phản xạ khác nhau và tương tác khác nhau với các sóng phát sáng. Khi đặt đầu ngón tay lên máy quét, các đường gờ tiếp xúc chặt chẽ với bề mặt máy quét trong khi các rãnh chứa đầy các túi khí. Da và không khí có các chỉ số phản xạ khác nhau gây ra các sóng phát sáng khác nhau, được gọi là Phản xạ tổng thể thất vọng (FTIR). Là kết quả của các sóng phát ra khác nhau từ các rặng núi và thung lũng, cường độ của tổng ánh sáng phản xạ bên trong thay đổi theo mô hình của các rặng núi và thung lũng. Cảm biến hình ảnh ghi lại hình ảnh có độ tương phản cao ghi lại dạng cường độ ánh sáng đã thay đổi, chụp dạng đường gờ và thung lũng dưới dạng hình ảnh kỹ thuật số có độ tương phản cao. Hình ảnh này sau đó được lưu trữ trong bộ nhớ flash với một id duy nhất làm mẫu.

Mô-đun cảm biến vân tay R307:

Trong Project này, chúng tôi sẽ sử dụng một cảm biến như vậy, Cảm biến vân tay quang học R307 phổ biến. Chúng được sản xuất bởi Hangzhou Grow Technology Co., Ltd. Mô-đun R307 hoạt động ở điện áp 4,2V ~ 6V và 50 mA với dung lượng lưu trữ là 1000 lần hiển thị. R307 có cả giao diện UART và USB 2.0 để giao tiếp với hệ thống máy tính ở tốc độ truyền theo bội số của 9600 bps.

Nó có khả năng khớp cả 1: 1 và 1: N với FAR (Tỷ lệ chấp nhận sai) ít hơn 0,001%. Mô-đun có thể quét ngón tay trực tiếp trong vòng chưa đầy 0,5 giây và hỗ trợ năm cấp độ bảo mật (1 ~ 5; 5 là mức cao nhất). Phạm vi nhiệt độ hoạt động của cảm biến này là -10˚C đến 40˚C, làm cho nó có thể triển khai ở hầu hết các vị trí.

R307 có mặt trên bằng kính, nơi có thể đặt đầu ngón tay để quét. Bên dưới mặt trên bằng thủy tinh có đặt một lăng kính. Bên trong cảm biến được chia thành hai phần bằng cách sử dụng một tấm chắn sáng. Ở một bên của tấm chắn sáng là một PCB bao gồm bốn đèn LED màu xanh lam. Ở phía bên kia của tấm chắn sáng là một cảm biến hình ảnh được kết nối với một bộ xử lý.

PCB bên ngoài có bộ xử lý, đầu nối và các phần tử mạch khác. Lăng kính, cùng với các đèn LED xanh lam và một cảm biến hình ảnh, được bố trí sao cho ánh sáng truyền qua các đèn LED xanh lam được phản xạ bên trong qua lăng kính tới cảm biến hình ảnh. R307 sử dụng AS606 DSP từ Synochip để xử lý tín hiệu và cảm biến cảm ứng TTP223 từ Tontek để phát hiện khoảng cách.

Mô-đun R307 có thể hoạt động ở cả 5V và 3.3V. Nếu cảm biến được sử dụng với bộ vi điều khiển 3.3V, thì jumper 3.3V trên PCB phải được nối tắt và để sử dụng 5V, hãy giữ jumper mở. Khi kết nối qua cổng USB, thiết bị sẽ tạo cổng com ảo và sẽ giao tiếp thông qua cổng đó. Bốn chân đầu tiên trên đầu nối dành cho nguồn và giao tiếp UART. Hai chân cuối cùng là để phát hiện cảm ứng. Nếu chân số 6 được kết nối với nguồn 3.3V, chân số 5 sẽ tăng cao khi đặt ngón tay lên cảm biến. Điều này rất hữu ích cho việc quét thủ công

Số chân

Tên

Sự mô tả

1

VCC

Nguồn (VCC)

2

GND

Tiếp đất (GND)

3

TXD

UART TX

4

RXD

UART RX

5

Touch

Tín hiệu phát hiện ngón tay

6

3,3V

Sức mạnh phát hiện ngón tay

Đây là bảng sơ đồ chân cho Cảm biến R307.

Mô-đun RTC DS1307:

Để chấm công, chúng ta sẽ sử dụng module DS1307 RTC khá phổ biến. Nó chứa một IC đồng hồ thời gian thực DS1307 với một pin dự phòng. Đây là một trong những RTC dễ sử dụng nhất hiện có, chỉ cần sử dụng các lệnh I2C để đặt và truy xuất ngày giờ. Đồng hồ / lịch cung cấp thông tin giây, phút, giờ, ngày, tháng, và năm. Ngày cuối tháng được tự động điều chỉnh cho các tháng có ít hơn 31 ngày, bao gồm cả các điều chỉnh cho năm nhuận. DS1307 được tích hợp mạch cảm biến nguồn giúp phát hiện sự cố mất điện và tự động chuyển sang nguồn dự phòng. Hoạt động chấm công vẫn tiếp tục trong khi bộ phận hoạt động từ nguồn cung cấp dự phòng. Mô-đun bao gồm một pin di động đồng xu CR2032, loại pin này sẽ tốt trong ít nhất vài năm. Cùng với chip đồng hồ thời gian thực DS1307, mô-đun còn có chip Atmel 24C32 EEPROM tiện dụng cho việc lưu trữ dữ liệu mà không lo mất điện. Trên bo mạch cũng có khoảng trống để hàn cảm biến nhiệt độ DS18B20 của riêng chúng tôi.

Link FIle :

Code :

#include <stdio.h>
#include <stdlib.h>
#include <SPI.h>
#include <FS.h>
#include "SPIFFS.h"
#include <WiFi.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#include <Wire.h>
#include <HTTPClient.h>
#include "src/Adafruit_SSD1306/Adafruit_GFX.h"
#include "src/Adafruit_SSD1306/Adafruit_SSD1306.h"
#include "src/Adafruit_SSD1306/RTClib.h"
#include "src/Adafruit_Fingerprint_Sensor_Library/Adafruit_Fingerprint.h"
#include "src/esp32_arduino_sqlite3_lib/sqlite3.h"               //https://github.com/siara-cc/esp32_arduino_sqlite3_lib
#include "config/credits.h"
#include "config/robotbold10.h"
#include "config/seg.h"
#include "config/icons.h"
RTC_DS1307 rtc;
char nameoftheday[7][12] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
char month_name[12][12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
int day_, month_, year_, hour24_, hour12_, minute_, second_, dtw_;
uint8_t id;
WebServer server(80);
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define Buzzer 25 //Buzzer 
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
HardwareSerial mySerial(2); //ESP32 Hardware Serial 2
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);
String mdnsdotlocalurl = "";

//Variables to save values from HTML form
String ssid_;
String pass_;
String ip_;
String gateway_;
String dispname_;
String wwwid_;
String wwwpass_;
String gsid_;
String mdns_;
String dhcpcheck;
String Empid, Sqid, Empname, EmpEmail, EmpPos, Empfid, sts7, sts8, sts9, sts10;
int SQLID = 0;
bool booting = false;

// File paths to save input values permanently
const char* ssidPath = "/ssid.txt";
const char* passPath = "/pass.txt";
const char* ipPath = "/ip.txt";
const char* gatewayPath = "/gateway.txt";
const char* dispnamePath = "/dispname.txt";
const char* wwwidPath = "/wwwid.txt";
const char* wwwpassPath = "/wwwpass.txt";
const char* gsidPath = "/gsid.txt";
const char* mdnsPath = "/mdns.txt";
const char* dhcpcheckPath = "/dhcpcheck.txt";
bool apmode = false;
IPAddress localIP(0, 0, 0, 0);
IPAddress gatewayIP(0, 0, 0, 0);
IPAddress subnetMask(255, 255, 255, 0);
uint8_t max_connections = 8; //Maximum Connection Limit for AP
sqlite3 *test1_db;
const char* data = "Callback function called";
char *zErrMsg = 0;
int openDb(const char *, sqlite3 **);
int db_exec(sqlite3 *, const char *);
int sqlreturn = 0;
static int callback(void *data, int argc, char **argv, char **azColName);
unsigned long lastwificheck = 0;

//Class declaration
void oledDisplayCenter();
String readFile();
void writeFile();
static int callback1();
int db_exec1();
int openDb();
static int callback();
int db_exec();
bool loadFromSPIFFS();
bool is_authentified();
void handleLogin();
void logout();
void handleRoot();
void Settings();
void handleNotFound();
void insertRecord();
void save();
void deleteRecord();
void showRecords();
void newRecordTable();
void getssid();
void getmdns();
void getip();
void getfpid();
int FingerprintID();
uint8_t deleteFingerprint();
uint8_t getFingerprintEnroll();
void connectwifi();
void offlinedataupload();


String web_content = "";


void setup() {
  booting = true;
  pinMode (Buzzer, OUTPUT);
  Serial.begin(115200);
  mySerial.begin(57600, SERIAL_8N1, 16, 17);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.drawBitmap(0, 20, logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
  display.display();
  delay(1000);
  display.clearDisplay();
  if (finger.verifyPassword())
  {
    Serial.println("Fingerprint Sensor Connected");

  }

  else
  {
    display.clearDisplay();
    display.setTextSize(2);             // Normal 1:1 pixel scale
    display.setTextColor(SSD1306_WHITE);        // Draw white text
    display.setCursor(25, 0);            // Start at top-left corner
    display.println(("Sensor"));
    display.setCursor(25, 35);
    display.println("Error");
    display.display();

    Serial.println("Unable to find Sensor");
    delay(3000);
    Serial.println("Check Connections");

    while (1) {
      delay(1);
    }
  }
  display.clearDisplay();
  rtc.begin();
  SPIFFS.begin(); // For SPIFFS

  // Load values saved in SPIFFS
  ssid_ = readFile(SPIFFS, ssidPath);
  Serial.println(ssid_);
  pass_ = readFile(SPIFFS, passPath);
  Serial.println(pass_);
  ip_ = readFile(SPIFFS, ipPath);
  Serial.println(ip_);
  gateway_ = readFile(SPIFFS, gatewayPath);
  Serial.println(gateway_);
  dispname_ = readFile(SPIFFS, dispnamePath);
  if (dispname_ == "")
  {
    dispname_ = DEFAULT_displayname;
  }
  Serial.println(dispname_);
  wwwid_ = readFile(SPIFFS, wwwidPath);
  if (wwwid_ == "")
  {
    wwwid_ = DEFAULT_wwwusername;
  }
  Serial.println(wwwid_);
  wwwpass_ = readFile(SPIFFS, wwwpassPath);
  if (wwwpass_ == "")
  {
    wwwpass_ = DEFAULT_wwwpassword;
  }
  Serial.println(wwwpass_);
  gsid_ = readFile(SPIFFS, gsidPath);
  Serial.println(gsid_);
  mdnsdotlocalurl = readFile(SPIFFS, mdnsPath);
  Serial.println(mdnsdotlocalurl);
  dhcpcheck = readFile(SPIFFS, dhcpcheckPath);
  Serial.println(dhcpcheck);

  display.drawBitmap(32, 0, logo_wifi, 64, 61, 1);
  display.display();
  display.clearDisplay();

  connectwifi();
  if (mdnsdotlocalurl == "")
  {
    mdnsdotlocalurl = DEFAULT_mdns;
  }

  if (!MDNS.begin(mdnsdotlocalurl.c_str())) {
    Serial.println("Error setting up MDNS responder!");
  }

  MDNS.addService("http", "tcp", 80);

  Serial.print("http://");
  Serial.print(mdnsdotlocalurl);
  Serial.println(".local");





  server.on("/", handleRoot);
  server.onNotFound(handleNotFound);
  server.on("/insert", insertRecord);
  server.on("/delete", deleteRecord);
  server.on("/show", showRecords);
  server.on("/newRecordTable", newRecordTable);
  server.on("/Settings", Settings);
  server.on("/save", save);
  server.on("/getssid", getssid);
  server.on("/getfpid", getfpid);
  server.on("/getmdns", getmdns);
  server.on("/getip", getip);
  server.on("/login", handleLogin);
  server.on("/signout", logout);



  //here the list of headers to be recorded
  const char * headerkeys[] = {"User-Agent", "Cookie"} ;
  size_t headerkeyssize = sizeof(headerkeys) / sizeof(char*);
  //ask server to track these headers
  server.collectHeaders(headerkeys, headerkeyssize );
  server.begin();


  int rc;
  sqlite3_initialize();

  if (openDb("/spiffs/test1.db", &test1_db))
    return;
  booting = false;

}



void loop() {

  server.handleClient();
  FingerprintID();
  if (WiFi.status() != WL_CONNECTED && millis() - lastwificheck > 1800000)
  {
    connectwifi();

  }
}

void oledDisplayCenter(String text, int x, int y) {
  int16_t x1;
  int16_t y1;
  uint16_t width;
  uint16_t height;

  display.getTextBounds(text, x, y, &x1, &y1, &width, &height);
  display.setCursor((SCREEN_WIDTH - width) / 2, y);
  display.print(text); // text to display
}

// Read File from SPIFFS
String readFile(fs::FS &fs, const char * path) {
  Serial.printf("Reading file: %s\r\n", path);

  File file = fs.open(path);
  if (!file || file.isDirectory()) {
    Serial.println("- failed to open file for reading");
    return String();
  }

  String fileContent;
  while (file.available()) {
    fileContent = file.readStringUntil('\n');
    break;
  }
  return fileContent;
}

// Write file to SPIFFS
void writeFile(fs::FS &fs, const char * path, const char * message) {
  Serial.printf("Writing file: %s\r\n", path);

  File file = fs.open(path, FILE_WRITE);
  if (!file) {
    Serial.println("- failed to open file for writing");
    return;
  }
  if (file.print(message)) {
    Serial.println("- file written");
  } else {
    Serial.println("- frite failed");
  }
}


const char* data1 = "Callback function called";
static int callback1(void *data1, int argc, char **argv, char **azColName) {
  int i;
  String t = "";
  String m = "";
  Serial.printf("%s: ", (const char*)data1);
  for (i = 0; i < argc; i++) {
    Serial.printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
    //printf(buffer, "%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
    if (i == 0)
    {
      Sqid = argv[i] ? argv[i] : "NULL";
    }
    else if (i == 1)
    {
      Empid = argv[i] ? argv[i] : "NULL";
    }
    else if (i == 2)
    {
      Empname = argv[i] ? argv[i] : "NULL";
    }
    else if (i == 3)
    {
      EmpEmail = argv[i] ? argv[i] : "NULL";
    }
    else if (i == 4)
    {
      EmpPos = argv[5] ? argv[i] : "NULL";
    }
    else if (i == 5)
    {
      Empfid = argv[i] ? argv[i] : "NULL";
    }
    else if (i == 6)
    {
      sts7 = argv[i] ? argv[i] : "NULL";
    }
    else if (i == 7)
    {
      sts8 = argv[i] ? argv[i] : "NULL";
    }
    else if (i == 8)
    {
      sts9 = argv[i] ? argv[i] : "NULL";
    }
    else if (i == 9)
    {
      sts10 = argv[i] ? argv[i] : "NULL";
    }
    m = argv[i] ? argv[i] : "NULL";
    //t += String(azColName[i] + m);
    Serial.println(m);
  }
  sqlreturn = m.toInt();
  Serial.printf("\n");
  return 0;
}

char *zErrMsg1 = 0;
int db_exec1(sqlite3 *db, const char *sql) {
  Serial.println(sql);
  long start = micros();
  int rc = sqlite3_exec(db, sql, callback1, (void*)data1, &zErrMsg1);
  if (rc != SQLITE_OK) {
    Serial.printf("SQL error: %s\n", zErrMsg1);
    sqlite3_free(zErrMsg1);
  } else {
    Serial.printf("Operation done successfully\n");
  }
  Serial.print(F("Time taken:"));
  Serial.println(micros() - start);
  return rc;
}




/*--------------------------------------------------------*/
int openDb(const char *filename, sqlite3 **db) {
  int rc = sqlite3_open(filename, db);
  if (rc) {
    Serial.printf("Can't open database: %s\n", sqlite3_errmsg(*db));
    return rc;
  } else {
    Serial.printf("Opened database successfully\n");
  }
  return rc;
}
/*--------------------------------------------------------*/

int db_exec(sqlite3 *db, const char *sql) {
  Serial.println('\n');
  int rc = sqlite3_exec(db, sql, callback, (void*)data, &zErrMsg);
  if (rc != SQLITE_OK) {
    Serial.printf("SQL error: %s\n", zErrMsg);
    sqlite3_free(zErrMsg);
  }
  return rc;
}


static int callback(void *data, int argc, char **argv, char **azColName) {
  web_content += "<tr>";
  for (int i = 0; i < argc; i++) {
    web_content += "<td>";
    web_content += argv[i];
    web_content += "</td>";
  }
  web_content += "<td><button onClick =\"del('";
  web_content += argv[0];
  web_content += "')\">Delete</button></td></tr>";
  return 0;
}
bool loadFromSPIFFS(String path) {
  String dataType = "text/html";

  Serial.print("Requested page -> ");
  Serial.println(path);
  if (SPIFFS.exists(path)) {
    File dataFile = SPIFFS.open(path, "r");
    if (!dataFile) {
      handleNotFound();
      return false;
    }

    if (server.streamFile(dataFile, dataType) != dataFile.size()) {
      Serial.println("Sent less data than expected!");
    } else {
      Serial.println("Page served!");
    }

    dataFile.close();
  } else {
    handleNotFound();
    return false;
  }
  return true;
}
//Check if header is present and correct
bool is_authentified() {
  Serial.println("Enter is_authentified");
  if (server.hasHeader("Cookie")) {
    Serial.print("Found cookie: ");
    String cookie = server.header("Cookie");
    Serial.println(cookie);
    if (cookie.indexOf("ESPSESSIONID=1") != -1) {
      Serial.println("Authentification Successful");
      return true;
    }
  }
  Serial.println("Authentification Failed");
  return false;
}



//login page, also called for disconnect
void handleLogin() {
  String msg;
  if (server.hasHeader("Cookie")) {
    Serial.print("Found cookie: ");
    String cookie = server.header("Cookie");
    Serial.println(cookie);
  }
  if (server.hasArg("DISCONNECT")) {
    Serial.println("Disconnection");
    server.sendHeader("Location", "/login");
    server.sendHeader("Cache-Control", "no-cache");
    server.sendHeader("Set-Cookie", "ESPSESSIONID=0");
    server.send(301);
    return;
  }
  if (server.hasArg("USERNAME") && server.hasArg("PASSWORD")) {
    Serial.println(server.hasArg("USERNAME"));
    Serial.println(server.hasArg("PASSWORD"));
    if (server.arg("USERNAME") == wwwid_ &&  server.arg("PASSWORD") == wwwpass_) {
      server.sendHeader("Location", "/");
      server.sendHeader("Cache-Control", "no-cache");
      server.sendHeader("Set-Cookie", "ESPSESSIONID=1");
      server.send(301);
      Serial.println("Log in Successful");
      return;
    }
    msg = "Wrong username/password! try again.";
    Serial.println("Log in Failed");
  }
  loadFromSPIFFS("/Login.html");
}
/*--------------------------------------------------------*/
void logout() {

  server.sendHeader("Cache-Control", "no-cache");
  server.sendHeader("Set-Cookie", "ESPSESSIONID=0");
  server.sendHeader("Location", "/login");
  server.sendHeader("Cache-Control", "no-cache");
  server.send(301);
  Serial.println("Signout ");
}
/*--------------------------------------------------------*/
/*--------------------------------------------------------*/
void handleRoot() {
  if (!is_authentified()) {
    server.sendHeader("Location", "/login");
    server.sendHeader("Cache-Control", "no-cache");
    server.send(301);
    return;
  }
  loadFromSPIFFS("/db.html");
}
/*--------------------------------------------------------*/
/*--------------------------------------------------------*/
void Settings() {
  if (!is_authentified()) {
    server.sendHeader("Location", "/login");
    server.sendHeader("Cache-Control", "no-cache");
    server.send(301);
    return;
  }
  //server.send(200, "text/html", web_page);
  loadFromSPIFFS("/Settings.html");

}
/*--------------------------------------------------------*/


void handleNotFound() {

  String message = "File Not Found\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += ( server.method() == HTTP_GET ) ? "GET" : "POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";

  for ( uint8_t i = 0; i < server.args(); i++ ) {
    message += " " + server.argName ( i ) + ": " + server.arg ( i ) + "\n";
  }

  server.send ( 404, "text/plain", message );

}

/*--------------------------------------------------------*/
void insertRecord() {
  web_content = "";
  String sql = "";
  String eemployee_id = server.arg("memployee_id");
  String ename = server.arg("mname");
  String eemail_id = server.arg("memail_id");
  String epos = server.arg("mpos");
  String efpid = server.arg("mfpid");

  id = efpid.toInt();

  if (getFingerprintEnroll() == true)
  {
    sql = "insert into attendance(id,eid,employee_name,employee_email,position,fpid) values(" + efpid + ",'" + eemployee_id + "','" + ename + "','" + eemail_id + "','" + epos + "'," + efpid + ")";
    Serial.println(sql);
    if (db_exec(test1_db, sql.c_str()) == SQLITE_OK) {
      web_content += "OK";
      Serial.println(web_content);
      display.clearDisplay();
      display.setTextColor(SSD1306_WHITE);        // Draw white text
      display.drawBitmap(47, 0, ok_bmp, 35, 45, 1);
      //display.setCursor(0, 60);            // Start at top-left corner
      //display.println(("Enroll Sucess"));
      oledDisplayCenter("Enroll Sucess!!", 0, 60);
      display.display();
      delay(2000);
    }
    else {
      web_content += "FAIL";
    }
  }
  else {
    web_content += "FAIL";
  }

  server.send (200, "text/html", web_content );
}
/*--------------------------------------------------------*/
/*--------------------------------------------------------*/
void save() {
  web_content = "";
  String _ssid = server.arg("ssid");
  String _password = server.arg("password");
  String _mdns = server.arg("mdns");
  String _gsid = server.arg("gsid");
  String _aip = server.arg("aip");
  String _mip = server.arg("mip");
  String _gateway = server.arg("gateway");
  String _dispname = server.arg("dispname");
  String _wwwid = server.arg("wwwid");
  String _wwwpass = server.arg("wwwpass");
  Serial.println(_ssid);
  Serial.println(_password);
  Serial.println(_mdns);
  Serial.println(_gsid);
  Serial.println(_aip);
  Serial.println(_mip);
  Serial.println(_gateway);
  Serial.println(_dispname);
  Serial.println(_wwwid);
  Serial.println(_wwwpass);
  if (_ssid != "")
  {
    writeFile(SPIFFS, ssidPath, _ssid.c_str());
  }
  else
  {
    Serial.println("Balnk SSID");
  }
  if (_password != "")
  {
    writeFile(SPIFFS, passPath, _password.c_str());
  }
  else
  {
    Serial.println("Balnk WiFi Password");
  }
  if (_mdns != "")
  {
    writeFile(SPIFFS, mdnsPath, _mdns.c_str());
  }
  else
  {
    Serial.println("Balnk mdns");
  }
  if (_gsid != "")
  {
    writeFile(SPIFFS, gsidPath, _gsid.c_str());
  }
  else
  {
    Serial.println("Balnk GSID");
  }
  if (_aip != "")
  {
    writeFile(SPIFFS, dhcpcheckPath, _aip.c_str());
  }
  else
  {
    Serial.println("Balnk IP config");
  }
  if (_mip != "")
  {
    writeFile(SPIFFS, ipPath, _mip.c_str());
  }
  else
  {
    Serial.println("Balnk Manual IP");
  }
  if (_gateway != "")
  {
    writeFile(SPIFFS, gatewayPath, _gateway.c_str());
  }
  else
  {
    Serial.println("Balnk Gateway");
  }
  if (_dispname != "")
  {
    writeFile(SPIFFS, dispnamePath, _dispname.c_str());
  }
  else
  {
    Serial.println("Balnk Display Name");
  }
  if (_wwwid != "")
  {
    writeFile(SPIFFS, wwwidPath, _wwwid.c_str());
  }
  else
  {
    Serial.println("Balnk Web User ID");
  }
  if (_wwwpass != "")
  {
    writeFile(SPIFFS, wwwpassPath, _wwwpass.c_str());
  }
  else
  {
    Serial.println("Balnk Web password");
  }

  String dtd = server.arg("dtd");
  String dtm = server.arg("dtm");
  String dty = server.arg("dty");
  String tmh = server.arg("tmh");
  String tmm = server.arg("tmm");
  String tms = server.arg("tms");
  String tmapm = server.arg("tmapm");
  Serial.println("Date received");

  Serial.println(dty);
  Serial.println(dtm);
  Serial.println(dtd);
  Serial.println(tmh);
  Serial.println(tmm);
  Serial.println(tmapm);
  if (dtd == "1" && dtm == "1" && dty == "2022")
   {
  Serial.println("Default date received!!! not saved");
  }
  else
  {
    year_ = dty.toInt();
    month_ = dtm.toInt();
    day_ = dtd.toInt();
    int ampm = tmapm.toInt();
    if (ampm == 2 && tmh.toInt() < 12)
    {
      hour24_ = tmh.toInt() + 12;
    }
    else if (ampm == 1 && tmh.toInt() == 12)
    {
      hour24_ = 0;
    }
    else
    {
      hour24_ = tmh.toInt();
    }
    minute_ = tmm.toInt();
    second_ = tms.toInt();;
    Serial.println("Date rescived");
    Serial.println(year_);
    Serial.println(month_);
    Serial.println(day_);
    Serial.println(hour24_);
    Serial.println(minute_);
    rtc.adjust(DateTime(year_, month_, day_, hour24_, minute_, second_));
    DateTime now = rtc.now();
    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(" (");
    Serial.print(nameoftheday[now.dayOfTheWeek()]);
    Serial.print(") ");
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();
  }
  web_content += "OK";
                 server.send (200, "text/html", web_content );
                 ESP.restart();

}
/*--------------------------------------------------------*/
void deleteRecord() {
  web_content = "";
  String sql = "";
  String id = server.arg("id");
  int dfpid = id.toInt();
  sql = "delete from attendance where id=" + id;
  Serial.println(sql);
  if (db_exec(test1_db, sql.c_str()) == SQLITE_OK) {
    web_content += "OK";
    Serial.println(web_content);
    deleteFingerprint(dfpid);
  }
  else
    web_content += "FAIL";
  server.send (200, "text/html", web_content );
}
/*--------------------------------------------------------*/
void showRecords() {
  if (!is_authentified()) {
    server.sendHeader("Location", "/login");
    server.sendHeader("Cache-Control", "no-cache");
    server.send(301);
    return;
  }
  web_content = "<table style='width:90%; margin-left:5%'><tr><th>Sl.No</th><th>Empl.ID</th><th>Employee Name</th><th>Employee Email</th><th>Position</th><th>FID</th><th>DEL</th></tr>";
  String sql = "Select * from attendance";
  if (db_exec(test1_db, sql.c_str()) == SQLITE_OK) {
    web_content += "</table>";
  }
  else
    web_content = "FAIL";
  server.send (200, "text/html", web_content );

}


/*--------------------------------------------------------*/
void newRecordTable() {
  if (!is_authentified()) {
    server.sendHeader("Location", "/login");
    server.sendHeader("Cache-Control", "no-cache");
    server.send(301);
    return;
  }
  String sql = "";
  Sqid = "NULL";
  sql = "SELECT * FROM attendance ORDER BY id DESC LIMIT 1";
  int temp = db_exec1(test1_db, sql.c_str());
  Serial.print("SQID : ");
  Serial.println(Sqid);
  if (Sqid == "NULL")
  {
    Sqid = "1";
  }
  else
  {
    int qid = Sqid.toInt();
    qid = qid + 1;
    Sqid = String(qid);
  }
  loadFromSPIFFS("/Enroll.html");

}
/*--------------------------------------------------------*/


/*--------------------------------------------------------*/
void getssid() {

  server.send(200, "text/plane", ssid_);

}
/*--------------------------------------------------------*/
/*--------------------------------------------------------*/
void getmdns() {

  server.send(200, "text/plane", mdnsdotlocalurl);

}
/*--------------------------------------------------------*/
/*--------------------------------------------------------*/
void getip() {

  server.send(200, "text/plane", ip_);

}
/*--------------------------------------------------------*/
/*--------------------------------------------------------*/
void getfpid() {


  server.send(200, "text/plane", Sqid);

}
/*--------------------------------------------------------*/
// returns -1 if failed, otherwise returns ID #
int FingerprintID()
{
  DateTime now = rtc.now();
  uint8_t p = finger.getImage();
  if (p != FINGERPRINT_OK)
  {
    display.clearDisplay();
    //display.setTextSize(2);             // Normal 1:1 pixel scale
    display.setFont(&Roboto_Bold_10);
    display.setTextColor(SSD1306_WHITE);        // Draw white text
    display.setCursor(0, 10);            // Start at top-left corner
    display.println(nameoftheday[now.dayOfTheWeek()]);
    display.setCursor(25, 10);
    display.println(now.day());
    display.setCursor(42, 10);
    display.println(month_name[now.month() - 1]);
    display.setCursor(67, 10);
    display.println(now.year(), DEC);
    //display.setCursor(0, 64);
    //display.print("Semicon Media Pvt Ltd");
    oledDisplayCenter(dispname_, 0, 60);
    if (WiFi.status() == WL_CONNECTED) {
      display.drawBitmap(110, 0, wifi_bmp, 12, 10, 1);
    }
    else
    {
      display.drawBitmap(110, 0, nowifi_bmp, 12, 10, 1);
    }
    display.setFont(&DSEG7_Classic_Bold_30);

    display.setCursor(0, 48);
    if (now.hour() < 10 || (now.hour() > 12 && now.hour() < 22))
    {
      display.print("0");
    }
    if (now.hour() < 13)
    {
      display.print(now.hour());
    }
    else
    {
      display.print(now.hour() - 12);
    }
    if ((now.second() % 2) == 0)
    {
      display.print(":");
    }
    else
    {
      display.print(" ");
    }

    if (now.minute() < 10)
    {
      display.print("0");
    }
    display.print(now.minute());
    display.setFont(&Roboto_Bold_10);
    if (now.hour() < 13)
    {
      display.print("AM");
    }
    else
    {
      display.print("PM");
    }
    display.display();
    //Serial.println("Waiting For Valid Finger");
    return -1;
  }

  p = finger.image2Tz();
  if (p != FINGERPRINT_OK)
  {
    display.clearDisplay();
    display.setTextColor(SSD1306_WHITE);        // Draw white text
    display.drawBitmap(47, 0, messy_bmp, 35, 45, 1);
    oledDisplayCenter("Messy Image Try Again", 0, 60);
    display.display();

    Serial.println("Messy Image Try Again");
    digitalWrite (Buzzer, HIGH); //turn buzzer on
    delay(500);
    digitalWrite (Buzzer, LOW); //turn buzzer on
    delay(500);
    digitalWrite (Buzzer, HIGH); //turn buzzer on
    delay(500);
    digitalWrite (Buzzer, LOW); //turn buzzer on
    delay(1500);
    display.clearDisplay();
    return -1;
  }

  p = finger.fingerFastSearch();
  if (p != FINGERPRINT_OK)  {

    display.clearDisplay();
    display.setTextColor(SSD1306_WHITE);        // Draw white text
    display.drawBitmap(47, 0, invalid_bmp, 35, 45, 1);
    oledDisplayCenter("Invalid ID Try Again", 0, 60);
    display.display();
    Serial.println("Not Valid Finger");
    digitalWrite (Buzzer, HIGH); //turn buzzer on
    delay(500);
    digitalWrite (Buzzer, LOW); //turn buzzer on
    delay(500);
    digitalWrite (Buzzer, HIGH); //turn buzzer on
    delay(500);
    digitalWrite (Buzzer, LOW); //turn buzzer on
    delay(500);
    digitalWrite (Buzzer, HIGH); //turn buzzer on
    delay(500);
    digitalWrite (Buzzer, LOW); //turn buzzer on
    delay(500);
    display.clearDisplay();
    return -1;
  }

  // found a match!
  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);        // Draw white text
  display.drawBitmap(47, 0, ok_bmp, 35, 45, 1);
  oledDisplayCenter("Finger Print Verified", 0, 60);
  display.display();
  Serial.println("Finger Print Verified");
  delay(1000);
  display.clearDisplay();
  int mnt, dday;
  String yr;
  if (now.month()  == 1)
  {
    mnt = 12;
  }
  else {
    mnt = now.month();
  }
  if ( now.day() < 7)
  {
    dday = 31 - (7 - (now.day() - 1));
  }
  else
  {
    dday = now.day() - 7;
  }
  if (now.month()  == 1 && now.day() < 7)
  {
    yr = String(now.year() - 1, DEC);
  }
  else {
    yr = String(now.year(), DEC);
  }
  String temp = String(dday) + month_name[mnt - 1] + yr;
  String sql = "drop table if exists date" + temp;
  int  rc = db_exec1(test1_db, sql.c_str());
  String att;
  temp = String(now.day()) + month_name[now.month() - 1] + String(now.year(), DEC);
  Serial.print("table name : ");
  Serial.println(temp);
  sql = "create table if not exists date" + temp + " (id INTEGER,date TEXT,time TEXT, eid TEXT,employee_name TEXT,employee_email TEXT,position TEXT,attend TEXT,fpid INTEGER,uploadsts INTEGER)";
  rc = db_exec1(test1_db, sql.c_str());

  Serial.print("Fingerprint ID : ");
  Serial.println(finger.fingerID);
  String SFPID = String (finger.fingerID);
  sql = "SELECT EXISTS(SELECT 1 from date" + temp + " where id =" + SFPID + " LIMIT 1)";
  rc = db_exec1(test1_db, sql.c_str());
  Serial.print("SQL retun : ");
  Serial.println(sqlreturn);
  if (sqlreturn == 1)
  {
    att = "Punch Out";
  }
  else
  {
    att = "Punch In";
  }
  sql = "select count(*) from date" + temp + " where id = " + SFPID;
  rc = db_exec1(test1_db, sql.c_str());
  Serial.print("No times : ");
  Serial.println(sqlreturn);
  if (sqlreturn < 2)
  {
    String hr = "";
    if (now.hour() < 10 || (now.hour() > 12 && now.hour() < 22))
    {
      hr += "0";
    }
    if (now.hour() < 13)
    {
      hr += String(now.hour());
    }
    else
    {
      hr += String(now.hour() - 12);
    }
    if (now.minute() < 10)
    {
      hr += ".0" + String(now.minute());
    }
    else
    {
      hr += "." + String(now.minute());
    }
    if (now.hour() < 12)
    {
      hr += " AM";
    }
    else
    {
      hr += " PM";
    }

    sql = "Select * from attendance where id =" + SFPID;
    rc = db_exec1(test1_db, sql.c_str());

    String urlFinal = "https://script.google.com/macros/s/" + gsid_ + "/exec?" + "date=" + temp + "&time=" + hr + "&empid=" + Empid + "&empname=" + Empname + "&empemail=" + EmpEmail + "&emppos=" + EmpPos + "&emppio=" + att;
    urlFinal.replace(" ", "%20");
    String uploadstatus = "";
    Serial.println(urlFinal);
    HTTPClient http;
    http.begin(urlFinal.c_str());
    http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
    int httpCode = http.GET();
    Serial.print("HTTP Status Code: ");
    Serial.println(httpCode);
    //---------------------------------------------------------------------
    //getting response from google sheet
    String payload;
    if (httpCode == 200) {
      uploadstatus = "0";
    }
    else
    {
      uploadstatus = "1";
    }
    //---------------------------------------------------------------------
    http.end();

    sql = "insert into date" + temp + "(id,date,time,eid,employee_name,employee_email,position,attend,fpid,uploadsts) values(" + Sqid + ",'" + temp + "','" + hr + "','" + Empid + "','" + Empname + "','" + EmpEmail + "','" + EmpPos + "','" + att + "'," + Empfid + "," + uploadstatus + ")";
    Serial.println(sql);
    if (db_exec(test1_db, sql.c_str()) == SQLITE_OK) {
      display.drawBitmap(0, 10, welcome_bmp, 128, 17, 1);
      oledDisplayCenter(Empname, 0, 50);
      display.display();
      Serial.print("Welcome : ");
      Serial.println(Empname);
      digitalWrite (Buzzer, HIGH); //turn buzzer on
      delay(1000);
      digitalWrite (Buzzer, LOW); //turn buzzer on
      delay(2000);
      display.clearDisplay();
    }
  }
  else {
    oledDisplayCenter("Already Punched Out", 0, 20);
    oledDisplayCenter("Try Again Tomorrow", 0, 50);
    display.display();
    Serial.print("Attendance already logged : ");
    Serial.println(Empname);
    digitalWrite (Buzzer, HIGH); //turn buzzer on
    delay(1000);
    digitalWrite (Buzzer, LOW); //turn buzzer on
    delay(2000);
    display.clearDisplay();
  }
  return finger.fingerID;
}

uint8_t deleteFingerprint(uint8_t id) {
  uint8_t p = -1;

  p = finger.deleteModel(id);

  if (p == FINGERPRINT_OK) {
    Serial.println("Deleted!");
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    Serial.println("Communication error");
  } else if (p == FINGERPRINT_BADLOCATION) {
    Serial.println("Could not delete in that location");
  } else if (p == FINGERPRINT_FLASHERR) {
    Serial.println("Error writing to flash");
  } else {
    Serial.print("Unknown error: 0x"); Serial.println(p, HEX);
  }

  return p;
}



uint8_t getFingerprintEnroll() {

  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);        // Draw white text
  display.drawBitmap(47, 0, finger_bmp, 35, 45, 1);
  display.setCursor(0, 60);            // Start at top-left corner
  display.println(("Place Finger to Enroll"));
  display.display();
  int p = -1;
  while (p != FINGERPRINT_OK) {
    p = finger.getImage();
    switch (p) {
      case FINGERPRINT_OK:
        Serial.println("Image taken");
        display.clearDisplay();
        display.setTextColor(SSD1306_WHITE);        // Draw white text
        display.drawBitmap(47, 0, ok_bmp, 35, 45, 1);
        oledDisplayCenter("Image taken", 0, 60);
        display.display();
        digitalWrite (Buzzer, HIGH); //turn buzzer on
        delay(500);
        digitalWrite (Buzzer, LOW); //turn buzzer on
        delay(500);
        break;
      case FINGERPRINT_NOFINGER:
        Serial.println(".");
        break;
      case FINGERPRINT_PACKETRECIEVEERR:
        Serial.println("Communication error");
        display.clearDisplay();
        display.setTextColor(SSD1306_WHITE);        // Draw white text
        display.drawBitmap(47, 0, invalid_bmp, 35, 45, 1);
        oledDisplayCenter("Communication error", 0, 60);
        display.display();
        digitalWrite (Buzzer, HIGH); //turn buzzer on
        delay(500);
        digitalWrite (Buzzer, LOW); //turn buzzer on
        delay(500);
        digitalWrite (Buzzer, HIGH); //turn buzzer on
        delay(500);
        digitalWrite (Buzzer, LOW); //turn buzzer on
        break;
      case FINGERPRINT_IMAGEFAIL:
        Serial.println("Imaging error");
        display.clearDisplay();
        display.setTextColor(SSD1306_WHITE);        // Draw white text
        display.drawBitmap(47, 0, invalid_bmp, 35, 45, 1);
        oledDisplayCenter("Imaging error", 0, 60);
        display.display();
        digitalWrite (Buzzer, HIGH); //turn buzzer on
        delay(500);
        digitalWrite (Buzzer, LOW); //turn buzzer on
        delay(500);
        digitalWrite (Buzzer, HIGH); //turn buzzer on
        delay(500);
        digitalWrite (Buzzer, LOW); //turn buzzer on
        break;
      default:
        Serial.println("Unknown error");
        display.clearDisplay();
        display.setTextColor(SSD1306_WHITE);        // Draw white text
        display.drawBitmap(47, 0, invalid_bmp, 35, 45, 1);
        oledDisplayCenter("Unknown error", 0, 60);
        display.display();
        digitalWrite (Buzzer, HIGH); //turn buzzer on
        delay(500);
        digitalWrite (Buzzer, LOW); //turn buzzer on
        delay(500);
        digitalWrite (Buzzer, HIGH); //turn buzzer on
        delay(500);
        digitalWrite (Buzzer, LOW); //turn buzzer on
        break;
    }
  }

  // OK success!

  p = finger.image2Tz(1);
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image converted");
      display.clearDisplay();
      display.setTextColor(SSD1306_WHITE);        // Draw white text
      display.drawBitmap(47, 0, ok_bmp, 35, 45, 1);
      oledDisplayCenter("Image converted", 0, 60);
      display.display();
      delay(1000);
      break;
    case FINGERPRINT_IMAGEMESS:
      Serial.println("Image too messy");
      display.clearDisplay();
      display.setTextColor(SSD1306_WHITE);        // Draw white text
      display.drawBitmap(47, 0, messy_bmp, 35, 45, 1);
      oledDisplayCenter("Image too messy", 0, 60);
      display.display();
      digitalWrite (Buzzer, HIGH); //turn buzzer on
      delay(500);
      digitalWrite (Buzzer, LOW); //turn buzzer on
      delay(500);
      digitalWrite (Buzzer, HIGH); //turn buzzer on
      delay(500);
      digitalWrite (Buzzer, LOW); //turn buzzer on
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      display.clearDisplay();
      display.setTextColor(SSD1306_WHITE);        // Draw white text
      display.drawBitmap(47, 0, invalid_bmp, 35, 45, 1);
      oledDisplayCenter("Communication errorr", 0, 60);
      display.display();
      digitalWrite (Buzzer, HIGH); //turn buzzer on
      delay(500);
      digitalWrite (Buzzer, LOW); //turn buzzer on
      delay(500);
      digitalWrite (Buzzer, HIGH); //turn buzzer on
      delay(500);
      digitalWrite (Buzzer, LOW); //turn buzzer on
      return p;
    case FINGERPRINT_FEATUREFAIL:
      Serial.println("Could not find fingerprint features");
      display.clearDisplay();
      display.setTextColor(SSD1306_WHITE);        // Draw white text
      display.drawBitmap(47, 0, invalid_bmp, 35, 45, 1);
      oledDisplayCenter("No fingerprint features", 0, 60);
      display.display();
      digitalWrite (Buzzer, HIGH); //turn buzzer on
      delay(500);
      digitalWrite (Buzzer, LOW); //turn buzzer on
      delay(500);
      digitalWrite (Buzzer, HIGH); //turn buzzer on
      delay(500);
      digitalWrite (Buzzer, LOW); //turn buzzer on
      return p;
    case FINGERPRINT_INVALIDIMAGE:
      Serial.println("Could not find fingerprint features");
      display.clearDisplay();
      display.setTextColor(SSD1306_WHITE);        // Draw white text
      display.drawBitmap(47, 0, invalid_bmp, 35, 45, 1);
      oledDisplayCenter("Imaging error", 0, 60);
      display.display();
      digitalWrite (Buzzer, HIGH); //turn buzzer on
      delay(500);
      digitalWrite (Buzzer, LOW); //turn buzzer on
      delay(500);
      digitalWrite (Buzzer, HIGH); //turn buzzer on
      delay(500);
      digitalWrite (Buzzer, LOW); //turn buzzer on
      return p;
    default:
      Serial.println("Unknown error");
      display.clearDisplay();
      display.setTextColor(SSD1306_WHITE);        // Draw white text
      display.drawBitmap(47, 0, invalid_bmp, 35, 45, 1);
      oledDisplayCenter("Unknown error", 0, 60);
      display.display();
      digitalWrite (Buzzer, HIGH); //turn buzzer on
      delay(500);
      digitalWrite (Buzzer, LOW); //turn buzzer on
      delay(500);
      digitalWrite (Buzzer, HIGH); //turn buzzer on
      delay(500);
      digitalWrite (Buzzer, LOW); //turn buzzer on
      return p;
  }

  Serial.println("Remove finger");
  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);        // Draw white text
  display.drawBitmap(47, 0, finger_bmp, 35, 45, 1);
  oledDisplayCenter("Remove finger", 0, 60);
  display.display();
  digitalWrite (Buzzer, HIGH); //turn buzzer on
  delay(500);
  digitalWrite (Buzzer, LOW); //turn buzzer on
  delay(500);
  delay(1000);
  p = 0;
  while (p != FINGERPRINT_NOFINGER) {
    p = finger.getImage();
  }
  Serial.print("ID "); Serial.println(id);
  p = -1;
  Serial.println("Place same finger again");
  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);        // Draw white text
  display.drawBitmap(47, 0, finger_bmp, 35, 45, 1);
  oledDisplayCenter("Place same finger again", 0, 60);
  display.display();
  while (p != FINGERPRINT_OK) {
    p = finger.getImage();
    switch (p) {
      case FINGERPRINT_OK:
        Serial.println("Image taken");
        display.clearDisplay();
        display.setTextColor(SSD1306_WHITE);        // Draw white text
        display.drawBitmap(47, 0, ok_bmp, 35, 45, 1);
        oledDisplayCenter("Image taken", 0, 60);
        display.display();
        digitalWrite (Buzzer, HIGH); //turn buzzer on
        delay(500);
        digitalWrite (Buzzer, LOW); //turn buzzer on
        delay(500);
        break;
      case FINGERPRINT_NOFINGER:
        Serial.print(".");
        break;
      case FINGERPRINT_PACKETRECIEVEERR:
        Serial.println("Communication error");
        display.clearDisplay();
        display.setTextColor(SSD1306_WHITE);        // Draw white text
        display.drawBitmap(47, 0, invalid_bmp, 35, 45, 1);
        oledDisplayCenter("Communication error", 0, 60);
        display.display();
        digitalWrite (Buzzer, HIGH); //turn buzzer on
        delay(500);
        digitalWrite (Buzzer, LOW); //turn buzzer on
        delay(500);
        digitalWrite (Buzzer, HIGH); //turn buzzer on
        delay(500);
        digitalWrite (Buzzer, LOW); //turn buzzer on
        break;
      case FINGERPRINT_IMAGEFAIL:
        Serial.println("Imaging error");
        display.clearDisplay();
        display.setTextColor(SSD1306_WHITE);        // Draw white text
        display.drawBitmap(47, 0, invalid_bmp, 35, 45, 1);
        oledDisplayCenter("Imaging error", 0, 60);
        display.display();
        digitalWrite (Buzzer, HIGH); //turn buzzer on
        delay(500);
        digitalWrite (Buzzer, LOW); //turn buzzer on
        delay(500);
        digitalWrite (Buzzer, HIGH); //turn buzzer on
        delay(500);
        digitalWrite (Buzzer, LOW); //turn buzzer on
        break;
      default:
        Serial.println("Unknown error");
        display.clearDisplay();
        display.setTextColor(SSD1306_WHITE);        // Draw white text
        display.drawBitmap(47, 0, invalid_bmp, 35, 45, 1);
        oledDisplayCenter("Unknown error", 0, 60);
        display.display();
        digitalWrite (Buzzer, HIGH); //turn buzzer on
        delay(500);
        digitalWrite (Buzzer, LOW); //turn buzzer on
        delay(500);
        digitalWrite (Buzzer, HIGH); //turn buzzer on
        delay(500);
        digitalWrite (Buzzer, LOW); //turn buzzer on
        break;
    }
  }

  // OK success!

  p = finger.image2Tz(2);
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image converted");
      display.clearDisplay();
      display.setTextColor(SSD1306_WHITE);        // Draw white text
      display.drawBitmap(47, 0, ok_bmp, 35, 45, 1);
      oledDisplayCenter("Image converted", 0, 60);
      display.display();
      delay(1000);
      break;
    case FINGERPRINT_IMAGEMESS:
      Serial.println("Image too messy");
      display.clearDisplay();
      display.setTextColor(SSD1306_WHITE);        // Draw white text
      display.drawBitmap(47, 0, messy_bmp, 35, 45, 1);
      oledDisplayCenter("Image too messy", 0, 60);
      display.display();
      digitalWrite (Buzzer, HIGH); //turn buzzer on
      delay(500);
      digitalWrite (Buzzer, LOW); //turn buzzer on
      delay(500);
      digitalWrite (Buzzer, HIGH); //turn buzzer on
      delay(500);
      digitalWrite (Buzzer, LOW); //turn buzzer on
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      display.clearDisplay();
      display.setTextColor(SSD1306_WHITE);        // Draw white text
      display.drawBitmap(47, 0, invalid_bmp, 35, 45, 1);
      oledDisplayCenter("Communication error", 0, 60);
      display.display();
      digitalWrite (Buzzer, HIGH); //turn buzzer on
      delay(500);
      digitalWrite (Buzzer, LOW); //turn buzzer on
      delay(500);
      digitalWrite (Buzzer, HIGH); //turn buzzer on
      delay(500);
      digitalWrite (Buzzer, LOW); //turn buzzer on
      return p;
    case FINGERPRINT_FEATUREFAIL:
      Serial.println("Could not find fingerprint features");
      display.clearDisplay();
      display.setTextColor(SSD1306_WHITE);        // Draw white text
      display.drawBitmap(47, 0, invalid_bmp, 35, 45, 1);
      oledDisplayCenter("No fingerprint features", 0, 60);
      display.display();
      digitalWrite (Buzzer, HIGH); //turn buzzer on
      delay(500);
      digitalWrite (Buzzer, LOW); //turn buzzer on
      delay(500);
      digitalWrite (Buzzer, HIGH); //turn buzzer on
      delay(500);
      digitalWrite (Buzzer, LOW); //turn buzzer on
      return p;
    case FINGERPRINT_INVALIDIMAGE:
      Serial.println("Could not find fingerprint features");
      display.clearDisplay();
      display.setTextColor(SSD1306_WHITE);        // Draw white text
      display.drawBitmap(47, 0, invalid_bmp, 35, 45, 1);
      oledDisplayCenter("Imaging error", 0, 60);
      display.display();
      digitalWrite (Buzzer, HIGH); //turn buzzer on
      delay(500);
      digitalWrite (Buzzer, LOW); //turn buzzer on
      delay(500);
      digitalWrite (Buzzer, HIGH); //turn buzzer on
      delay(500);
      digitalWrite (Buzzer, LOW); //turn buzzer on
      return p;
    default:
      Serial.println("Unknown error");
      display.clearDisplay();
      display.setTextColor(SSD1306_WHITE);        // Draw white text
      display.drawBitmap(47, 0, invalid_bmp, 35, 45, 1);
      oledDisplayCenter("Unknown error", 0, 60);
      display.display();
      digitalWrite (Buzzer, HIGH); //turn buzzer on
      delay(500);
      digitalWrite (Buzzer, LOW); //turn buzzer on
      delay(500);
      digitalWrite (Buzzer, HIGH); //turn buzzer on
      delay(500);
      digitalWrite (Buzzer, LOW); //turn buzzer on
      return p;
  }

  // OK converted!
  Serial.print("Creating model for #");  Serial.println(id);

  p = finger.createModel();
  if (p == FINGERPRINT_OK) {
    Serial.println("Prints matched!");
    display.clearDisplay();
    display.setTextColor(SSD1306_WHITE);        // Draw white text
    display.drawBitmap(47, 0, ok_bmp, 35, 45, 1);
    oledDisplayCenter("Prints matched!", 0, 60);
    display.display();
    digitalWrite (Buzzer, HIGH); //turn buzzer on
    delay(500);
    digitalWrite (Buzzer, LOW); //turn buzzer on
    delay(500);
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    Serial.println("Communication error");
    display.clearDisplay();
    display.setTextColor(SSD1306_WHITE);        // Draw white text
    display.drawBitmap(47, 0, invalid_bmp, 35, 45, 1);
    oledDisplayCenter("Communication error", 0, 60);
    display.display();
    digitalWrite (Buzzer, HIGH); //turn buzzer on
    delay(500);
    digitalWrite (Buzzer, LOW); //turn buzzer on
    delay(500);
    digitalWrite (Buzzer, HIGH); //turn buzzer on
    delay(500);
    digitalWrite (Buzzer, LOW); //turn buzzer on
    return p;
  } else if (p == FINGERPRINT_ENROLLMISMATCH) {
    Serial.println("Fingerprints did not match");
    display.clearDisplay();
    display.setTextColor(SSD1306_WHITE);        // Draw white text
    display.drawBitmap(47, 0, invalid_bmp, 35, 45, 1);
    oledDisplayCenter("Fingerprints didn't match", 0, 60);
    display.display();
    digitalWrite (Buzzer, HIGH); //turn buzzer on
    delay(500);
    digitalWrite (Buzzer, LOW); //turn buzzer on
    delay(500);
    digitalWrite (Buzzer, HIGH); //turn buzzer on
    delay(500);
    digitalWrite (Buzzer, LOW); //turn buzzer on
    return p;
  } else {
    Serial.println("Unknown error");
    display.clearDisplay();
    display.setTextColor(SSD1306_WHITE);        // Draw white text
    display.drawBitmap(47, 0, invalid_bmp, 35, 45, 1);
    oledDisplayCenter("Unknown error", 0, 60);
    display.display();
    digitalWrite (Buzzer, HIGH); //turn buzzer on
    delay(500);
    digitalWrite (Buzzer, LOW); //turn buzzer on
    delay(500);
    digitalWrite (Buzzer, HIGH); //turn buzzer on
    delay(500);
    digitalWrite (Buzzer, LOW); //turn buzzer on
    return p;
  }

  Serial.print("ID "); Serial.println(id);
  p = finger.storeModel(id);
  if (p == FINGERPRINT_OK) {
    Serial.println("Stored!");
    display.clearDisplay();
    display.setTextColor(SSD1306_WHITE);        // Draw white text
    display.drawBitmap(47, 0, ok_bmp, 35, 45, 1);
    oledDisplayCenter("Image Stored!", 0, 60);
    display.display();
    digitalWrite (Buzzer, HIGH); //turn buzzer on
    delay(500);
    digitalWrite (Buzzer, LOW); //turn buzzer on
    delay(500);
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    Serial.println("Communication error");
    display.clearDisplay();
    display.setTextColor(SSD1306_WHITE);        // Draw white text
    display.drawBitmap(47, 0, invalid_bmp, 35, 45, 1);
    oledDisplayCenter("Communication error", 0, 60);
    display.display();
    digitalWrite (Buzzer, HIGH); //turn buzzer on
    delay(500);
    digitalWrite (Buzzer, LOW); //turn buzzer on
    delay(500);
    digitalWrite (Buzzer, HIGH); //turn buzzer on
    delay(500);
    digitalWrite (Buzzer, LOW); //turn buzzer on
    return p;
  } else if (p == FINGERPRINT_BADLOCATION) {
    Serial.println("Could not store in that location");
    display.clearDisplay();
    display.setTextColor(SSD1306_WHITE);        // Draw white text
    display.drawBitmap(47, 0, invalid_bmp, 35, 45, 1);
    oledDisplayCenter("Location error", 0, 60);
    display.display();
    digitalWrite (Buzzer, HIGH); //turn buzzer on
    delay(500);
    digitalWrite (Buzzer, LOW); //turn buzzer on
    delay(500);
    digitalWrite (Buzzer, HIGH); //turn buzzer on
    delay(500);
    digitalWrite (Buzzer, LOW); //turn buzzer on
    return p;
  } else if (p == FINGERPRINT_FLASHERR) {
    Serial.println("Error writing to flash");
    display.clearDisplay();
    display.setTextColor(SSD1306_WHITE);        // Draw white text
    display.drawBitmap(47, 0, invalid_bmp, 35, 45, 1);
    oledDisplayCenter("Error writing to flash", 0, 60);
    display.display();
    digitalWrite (Buzzer, HIGH); //turn buzzer on
    delay(500);
    digitalWrite (Buzzer, LOW); //turn buzzer on
    delay(500);
    digitalWrite (Buzzer, HIGH); //turn buzzer on
    delay(500);
    digitalWrite (Buzzer, LOW); //turn buzzer on
    return p;
  } else {
    Serial.println("Unknown error");
    display.clearDisplay();
    display.setTextColor(SSD1306_WHITE);        // Draw white text
    display.drawBitmap(47, 0, invalid_bmp, 35, 45, 1);
    oledDisplayCenter("Unknown error", 0, 60);
    display.display();
    digitalWrite (Buzzer, HIGH); //turn buzzer on
    delay(500);
    digitalWrite (Buzzer, LOW); //turn buzzer on
    delay(500);
    digitalWrite (Buzzer, HIGH); //turn buzzer on
    delay(500);
    digitalWrite (Buzzer, LOW); //turn buzzer on
    return p;
  }

  return true;
}


void connectwifi()
{
  if (ssid_ == "" ) {  // no ip // made it DHCP
    Serial.print("\n No wifi config found Connecting to Default Wifi ");
    Serial.println(DEFAULT_WIFI_SSID);
    WiFi.mode(WIFI_STA);
    int connectcount = 0;
    WiFi.begin(DEFAULT_WIFI_SSID, DEFAULT_WIFI_PASS);
    while (WiFi.status() != WL_CONNECTED) {
      delay(250);
      Serial.print(".");

    }
    if (WiFi.status() == WL_CONNECTED) {
      Serial.print("\n Connected. IP adress: ");
      Serial.println(WiFi.localIP());
    }
  }
  else {
    Serial.print("\n Wifi config found Connecting to  Wifi");
    WiFi.mode(WIFI_STA);
    if (dhcpcheck == "2" && ip_ != "" && gateway_ != "") {
      // fixed ip
      localIP.fromString(ip_.c_str());
      gatewayIP.fromString(gateway_.c_str());
      if (!WiFi.config(localIP, gatewayIP, subnetMask)) {
        Serial.println("STA Failed to configure");
      }

    } else {
      //dhcp
    }
    int connectcount = 0;
    WiFi.begin(ssid_.c_str(), pass_.c_str());
    while (WiFi.status() != WL_CONNECTED) {
      delay(250);
      Serial.print(".");
      connectcount++;
      if (connectcount > 50)
      {
        Serial.println("Failed to Connect to WiFi...");
        break;
      }
    }
    if (WiFi.status() == WL_CONNECTED) {
      Serial.print("\n Connected. IP adress: ");
      Serial.println(WiFi.localIP());
      if (booting == false)
      {
        String urlFinal = "https://script.google.com/macros/s/" + gsid_ + "/exec?";
        String uploadstatus = "";
        Serial.println(urlFinal);
        HTTPClient http;
        http.begin(urlFinal.c_str());
        http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
        int httpCode = http.GET();
        Serial.print("HTTP Status Code: ");
        Serial.println(httpCode);
        int j = httpCode;
        http.end();
        //---------------------------------------------------------------------
        //getting response from google sheet
        String payload;
        if (j == 200) {
          offlinedataupload();
        }
        else
        {
          Serial.print("Device offline");
        }
        //---------------------------------------------------------------------


      }
    }
  }
  lastwificheck = millis();
}


void offlinedataupload()
{
  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);        // Draw white text
  oledDisplayCenter("Please Waite!!", 0, 20);
  oledDisplayCenter("Uploading Offline Data", 0, 40);
  display.display();
  int j;
  for (int i = 6; i > -1; i--)
  {

    DateTime now = rtc.now();
    int mnt, dday;
    String yr;
    if (now.month()  == 1)
    {
      mnt = 12;
    }
    else {
      mnt = now.month();
    }
    if ( now.day() < 7)
    {
      dday = 31 - (i - (now.day() - 1));
    }
    else
    {
      dday = now.day() - i;
    }
    if (now.month()  == 1 && now.day() < 7)
    {
      yr = String(now.year() - 1, DEC);
    }
    else {
      yr = String(now.year(), DEC);
    }
    String temp = "date" + String(dday) + month_name[mnt - 1] + yr;
    while (1)
    {

      String number = "1";
      String sql = "Select * from " + temp + " where uploadsts =" + number;
      int rc = db_exec1(test1_db, sql.c_str());
      if (sqlreturn != 1 || j != 200)
      {
        break;
      }
      else
      {


        sql = "Select * from " + temp + " where id =" + Sqid + " and attend ='" + sts8 + "'";
        rc = db_exec1(test1_db, sql.c_str());

        String urlFinal = "https://script.google.com/macros/s/" + gsid_ + "/exec?" + "date=" + Empid + "&time=" + Empname + "&empid=" + EmpEmail + "&empname=" + EmpPos + "&empemail=" + Empfid + "&emppos=" + sts7 + "&emppio=" + sts8;
        urlFinal.replace(" ", "%20");
        String uploadstatus = "";
        Serial.println(urlFinal);
        HTTPClient http;
        http.begin(urlFinal.c_str());
        http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
        int httpCode = http.GET();
        Serial.print("HTTP Status Code: ");
        Serial.println(httpCode);
        j = httpCode;
        //---------------------------------------------------------------------
        //getting response from google sheet
        String payload;
        if (httpCode == 200) {
          sql = "update " + temp + " set uploadsts = '0' where id = " + Sqid + " and attend ='" + sts8 + "'";
          Serial.println(sql);
          rc = db_exec(test1_db, sql.c_str());
        }
        else
        {
          delay(1);
        }
        //---------------------------------------------------------------------
        http.end();

      }//
    }
  }

}

Đỗ Thủy Học Điện Tử

Tôi một người đam mê cung cấp kiến thức cuộc sống và kiến thức giáo dục văn học , vật lý , điện tử đến cho mọi người hãy cùng tôi tiếp nhận kiến thức mới nhé !

Trả lời

Email của bạn sẽ không được hiển thị công khai.

Back to top button