Firmware innoiti FT-1 untuk TPQ Al-Munawwarah, tidak ada batasan presensi harian
#include <WiFi.h>
#include <HTTPClient.h>
#include <Adafruit_Fingerprint.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Fonts/FreeSansBold12pt7b.h> // Font kustom
#include <Fonts/FreeSansBold9pt7b.h> // Font kustom
#include <Fonts/FreeSerif9pt7b.h> // Font kustom
#include <Fonts/FreeSans9pt7b.h> // Font kustom
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <Fonts/TomThumb.h> // Menyertakan font TomThumb
#define MODEM_RX 16
#define MODEM_TX 17
#define mySerial Serial2 // gunakan untuk ESP32
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define BUZZER_PIN 5 // Pin untuk buzzer
#define LED_PIN 18 // Pin untuk buzzer
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// Tambahkan untuk NTP Client
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", 25200, 60000); // GMT+7 (25200 detik)
// Struktur data untuk menyimpan ID dan nama
struct FingerprintData {
uint16_t id;
const char* name;
};
// Daftar ID dan nama
FingerprintData userData[] = {
{1, "U. Zidan"},
{2, "U. Andri"},
{3, "U. Azril"},
{4, "U. Zakka"},
{5, "U. Wasis"},
{6, "U. Tain"},
{7, "U. Umrotul"},
{8, "U. Rista"},
{9, "U. Indah"},
{10, "U. Arum"},
{11, "U. Wulan"},
{21, "Lonny"},
{22, "Aini"},
{23, "Ahmad"},
{24, "Azzam"},
{25, "Rifqi"},
{26, "Nazwa"},
{27, "Alby"},
{28, "Vero"},
{29, "Iyo"},
{30, "Asya"},
{31, "Calingga"},
{32, "Kiran"},
{33, "Elang"},
{34, "Endra"},
{35, "Rohit"},
{36, "Asa"},
{37, "Afa"},
{38, "Kevin"},
{39, "Keysha"},
{40, "Neneng"},
{41, "Laras"},
{42, "Abror"},
{43, "Ahsan"},
{44, "Calief"},
{45, "Hafy"},
{46, "Haikal"},
{47, "Rizqi"},
{48, "Nanda"},
{49, "Kaisa"},
{50, "Nayla"},
{51, "Novi"},
{52, "Vica"},
{53, "Nuril"},
{54, "Fino"},
{55, "Raffi"},
{56, "Rafif"},
{57, "Bahi"},
{58, "Shofia"},
{59, "Syahidah"},
{60, "Alfath"},
{61, "Syirin"},
{62, "Uwais"},
{63, "Vicko"},
{64, "Yolla"},
{65, "Niel"},
{66, "Wihra"},
{67, "Fina"},
{120, "Zara"},
{121, "Huda"},
{122, "Kalya"}
};
const int userCount = sizeof(userData) / sizeof(userData[0]); // Hitung jumlah data
// Informasi Wi-Fi
const char* ssid = "CreativeNet"; // Ganti dengan nama Wi-Fi
const char* password = "Creanet123"; // Ganti dengan password Wi-Fi
const char* serverName = "http://zidcreative.com/simunawwarah/jurnalsantri/absensi/absensi.php"; // URL PHP server
// Variabel untuk menyimpan waktu absensi terakhir
unsigned long lastAttendanceTime[130] = {0}; // Menyimpan waktu absensi per ID pengguna
void setup() {
Serial.begin(9600);
while (!Serial);
delay(100);
Serial.println("\n\nzidCreative Innoiti TF 1 Verifikasi");
// Koneksi Wi-Fi
Serial.print("Menghubungkan ke Wi-Fi");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWi-Fi Terhubung!");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
// Mulai komunikasi dengan sensor sidik jari
finger.begin(57600);
if (finger.verifyPassword()) {
Serial.println("Sensor sidik jari ditemukan!");
} else {
Serial.println("Sensor sidik jari tidak ditemukan :(");
while (1) { delay(1); }
}
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
display.clearDisplay();
display.setFont(&FreeSansBold12pt7b); // Menggunakan font kustom
display.setTextColor(WHITE);
display.setCursor(5, 20);
display.println("Innoiti");
display.setCursor(5, 45);
display.println("FT1");
display.display();
pinMode(BUZZER_PIN, OUTPUT);
pinMode(LED_PIN, OUTPUT);
digitalWrite(BUZZER_PIN, LOW);
digitalWrite(LED_PIN, LOW);
timeClient.begin();
}
void loop() {
// Tunggu sidik jari
uint8_t result = getFingerprintID();
if (result == FINGERPRINT_OK) {
handleAttendance(); // Tangani absensi
} else if (result == FINGERPRINT_NOTFOUND) {
displayError("Siapa Ya?");
playErrorSound();
} else {
displayTime();
}
delay(1000); // Tunggu 1 detik sebelum mencoba lagi
}
void handleAttendance() {
// Periksa apakah sudah absen hari ini
int userID = finger.fingerID;
unsigned long currentTime = timeClient.getEpochTime();
unsigned long currentDay = currentTime / 86400; // Hari sejak 1 Jan 1970
//if (currentDay == lastAttendanceTime[userID]) {
// Jika sudah absen hari ini
//displaySudahAbsen();
//playErrorSound();
//return;
//}
// Proses absensi jika belum absen hari ini
lastAttendanceTime[userID] = currentDay; // Simpan waktu absensi
displayFingerprintID(); // Tampilkan ID di OLED
playSuccessSound(); // Bunyi sukses
}
// Fungsi untuk menampilkan pesan kesalahan
void displayError(String errorMsg) {
display.clearDisplay();
display.setFont(&FreeSansBold12pt7b);
display.setTextColor(WHITE);
display.setCursor(0, 40);
display.println(errorMsg);
display.display();
}
// Fungsi untuk menampilkan pesan kesalahan
void displaySudahAbsen() {
display.clearDisplay();
display.setFont(&FreeSansBold9pt7b);
display.setTextColor(WHITE);
display.setCursor(5, 20);
display.println("Kamu sudah");
display.setCursor(5, 40);
display.println("absen hari ini");
display.setCursor(5, 60);
display.println("Besok lagi ya...");
display.display();
}
uint8_t getFingerprintID() {
uint8_t p = finger.getImage();
if (p != FINGERPRINT_OK) {
if (p == FINGERPRINT_NOFINGER) {
Serial.println("Tidak ada jari yang terdeteksi.");
}
return p;
}
p = finger.image2Tz();
if (p != FINGERPRINT_OK) {
Serial.println("Gagal mengonversi gambar menjadi template.");
return p;
}
p = finger.fingerFastSearch();
if (p == FINGERPRINT_OK) {
Serial.print("Sidik jari ditemukan dengan ID: ");
Serial.println(finger.fingerID);
Serial.print("Confidence: ");
Serial.println(finger.confidence);
}
return p;
}
const char* getNameByID(uint16_t id) {
for (int i = 0; i < userCount; i++) {
if (userData[i].id == id) {
return userData[i].name;
}
}
return "-";
}
void displayFingerprintID() {
display.clearDisplay();
display.setFont(&FreeSansBold12pt7b);
display.setTextColor(WHITE);
const char* userName = getNameByID(finger.fingerID);
display.setCursor(5, 20);
display.println("************");
display.setCursor(5, 35);
display.println("Tunggu");
display.setCursor(5, 62);
display.println("************");
display.display();
sendData(finger.fingerID, userName);
Serial.print("ID: ");
Serial.print(finger.fingerID);
Serial.print(", Nama: ");
Serial.println(userName);
}
void sendData(uint16_t id_jari, const char* name) {
if (WiFi.status() != WL_CONNECTED) {
Serial.println("WiFi tidak terhubung! Mencoba reconnect...");
WiFi.disconnect();
WiFi.reconnect();
delay(5000); // Tunggu 5 detik sebelum mencoba lagi
if (WiFi.status() != WL_CONNECTED) {
Serial.println("WiFi gagal terhubung. Data tidak dikirim.");
displayError("WiFi Error!");
return;
}
}
HTTPClient http;
http.begin(serverName);
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
String postData = "id_jari=" + String(id_jari) + "&name=" + String(name);
// Kirim data hanya 1 kali
int httpResponseCode = http.POST(postData);
if (httpResponseCode > 0) {
Serial.print("Data berhasil dikirim! HTTP Response: ");
Serial.println(httpResponseCode);
// Tambahkan notifikasi OLED
const char* userName = getNameByID(finger.fingerID);
displaySuccess(userName);
} else {
Serial.println("Gagal mengirim data.");
displayError("restart!");
playErrorSound();
}
http.end(); // Tutup HTTPClient
}
void playSuccessSound() {
for (int i = 0; i < 2; i++) {
digitalWrite(BUZZER_PIN, HIGH);
digitalWrite(LED_PIN, HIGH);
delay(100);
digitalWrite(BUZZER_PIN, LOW);
digitalWrite(LED_PIN, LOW);
delay(100);
}
}
void playErrorSound() {
digitalWrite(BUZZER_PIN, HIGH);
digitalWrite(LED_PIN, HIGH);
delay(1000);
digitalWrite(BUZZER_PIN, LOW);
digitalWrite(LED_PIN, LOW);
}
void displayTime() {
display.clearDisplay();
timeClient.update();
String formattedTime = timeClient.getFormattedTime();
display.setCursor(2, 15);
display.setFont(&FreeSerif9pt7b);
display.println("Al-Munawwarah");
display.setCursor(15, 42);
display.setFont(&FreeSansBold12pt7b);
display.println(formattedTime);
display.setCursor(7, 60);
display.setFont(&FreeSansBold9pt7b);
display.println(">>>>>>>>>>");
display.display();
}
void displaySuccess(const char* message) {
display.clearDisplay();
int centerX = display.width() / 6;
int centerY = display.height() / 4;
// Gambar lingkaran putih lebih kecil sebagai background
display.fillCircle(centerX, centerY, 12, WHITE);
display.drawCircle(centerX, centerY, 12, BLACK); // Garis luar hitam
display.display();
delay(100);
// Animasi menggambar tanda centang lebih tebal
for (int i = 0; i <= 10; i++) {
display.fillCircle(centerX, centerY, 10, WHITE);
display.drawCircle(centerX, centerY, 10, BLACK); // Garis luar hitam
int startX = centerX - 5;
int startY = centerY;
int midX = centerX - 2;
int midY = centerY + 4;
int endX = centerX + 6;
int endY = centerY - 6;
int drawMidX = startX + (midX - startX) * i / 10;
int drawMidY = startY + (midY - startY) * i / 10;
// Gambar bagian pertama centang (garis ke tengah) lebih tebal
for (int j = -1; j <= 1; j++) {
display.drawLine(startX, startY + j, drawMidX, drawMidY + j, BLACK);
}
if (i > 5) {
int drawEndX = midX + (endX - midX) * (i - 5) / 5;
int drawEndY = midY + (endY - midY) * (i - 5) / 5;
// Gambar bagian kedua centang (garis dari tengah ke ujung) lebih tebal
for (int j = -1; j <= 1; j++) {
display.drawLine(drawMidX, drawMidY + j, drawEndX, drawEndY + j, BLACK);
}
}
display.display();
delay(50);
}
// Tampilkan pesan sukses setelah animasi selesai
display.setCursor(centerX + 15, centerY + 14);
display.println("-----------");
display.setCursor(13, centerY + 35); // Pesan lebih ke bawah
display.setTextColor(WHITE);
display.println(message);
display.display();
}
void displayError(const char* message) {
display.clearDisplay();
display.setFont(&FreeSansBold9pt7b);
display.setTextColor(WHITE);
display.setCursor(10, 15);
display.println("Gagal!");
display.setCursor(10, 35);
display.println("--------");
display.setCursor(10, 40);
display.println(message);
display.display();
}