Add files via upload

This commit is contained in:
fitriyah123 2025-07-30 10:43:12 +07:00 committed by GitHub
parent 81d97fa744
commit 2c813c15d6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 456 additions and 0 deletions

456
codefix.ino Normal file
View File

@ -0,0 +1,456 @@
#include <WiFi.h>
#include <HTTPClient.h>
#include <SPI.h>
#include <Wire.h>
#include <MFRC522.h>
#include <LiquidCrystal_I2C.h>
#include <ArduinoJson.h>
#define DEBUG_MODE true
const char* ssid = "KOPI";
const char* password = "digoreng123";
const String API_BASE_URL = "https://smartlocker.punyapadias.my.id/api/";
#define SS_PIN 21
#define RST_PIN 5
MFRC522 mfrc522(SS_PIN, RST_PIN);
LiquidCrystal_I2C lcd(0x27, 16, 2);
const int trigPins[3] = {17, 16, 33};
const int echoPins[3] = {35, 34, 32};
#define RELAY1_PIN 14
#define RELAY2_PIN 27
#define RELAY3_PIN 26
#define BUZZER_PIN 13
enum SystemState {
STATE_IDLE,
STATE_RFID_DETECTED,
STATE_OPENING_LOCKER,
STATE_REGISTERING_RFID,
STATE_ERROR
};
SystemState currentState = STATE_IDLE;
unsigned long lastApiCallTime = 0;
const long apiCallInterval = 5000;
unsigned long rfidActionStartTime = 0;
const long rfidActionDuration = 10000;
bool lcdIdleShown = false;
struct RFIDMapping {
String uid;
int lokerId;
int relayPin;
};
RFIDMapping rfidMappings[] = {
{"36CB3503", 1, RELAY1_PIN},
{"5C312903", 2, RELAY2_PIN},
{"611B2803", 3, RELAY3_PIN},
};
const int jumlahRFID = sizeof(rfidMappings) / sizeof(rfidMappings[0]);
void setRFIDtoLoker(int lokerId, String rfid);
void updateStatusLoker(int lokerId, String status);
int getFirstEmptyRFIDLokerId();
String getStatusLoker(int lokerId);
void clearRFID();
void playBuzzer(int count, int durationMs, int pauseMs);
void displayLcdMessage(String line1, String line2, int duration = 0);
void handleRFIDAction(String uidStr, int mappedLokerId, int mappedRelayPin);
void handleNewRFIDRegistration(String uidStr);
void displayDefaultScreen() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Loker Pintar");
lcd.setCursor(0, 1);
lcd.print("Scan Kartu");
}
void setup() {
Serial.begin(115200);
Wire.begin(4, 22);
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Inisialisasi...");
// Menyambung ke WiFi
WiFi.begin(ssid, password);
lcd.setCursor(0, 1);
lcd.print("WiFi connecting...");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
lcd.setCursor(0, 1);
lcd.print("WiFi connected ");
Serial.println("\nWiFi Connected. IP: " + WiFi.localIP().toString());
// Inisialisasi RFID
SPI.begin();
mfrc522.PCD_Init();
// Inisialisasi sensor ultrasonik
for (int i = 0; i < 3; i++) {
pinMode(trigPins[i], OUTPUT);
pinMode(echoPins[i], INPUT);
}
// Inisialisasi relay dan buzzer
pinMode(RELAY1_PIN, OUTPUT); digitalWrite(RELAY1_PIN, HIGH);
pinMode(RELAY2_PIN, OUTPUT); digitalWrite(RELAY2_PIN, HIGH);
pinMode(RELAY3_PIN, OUTPUT); digitalWrite(RELAY3_PIN, HIGH);
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(BUZZER_PIN, LOW);
// Tampilkan layar utama
lcd.clear();
displayDefaultScreen();
lastApiCallTime = millis();
}
void loop() {
// Debug: tampilkan state saat ini setiap 1 detik
static unsigned long lastDebugTime = 0;
if (millis() - lastDebugTime > 1000) {
Serial.println("[DEBUG] Current state: " + String(currentState));
lastDebugTime = millis();
}
// Recovery: jika RFID tidak terbaca dalam waktu lama, inisialisasi ulang
static unsigned long lastRFIDScanTime = 0;
if (millis() - lastRFIDScanTime > 10000) {
Serial.println("[RFID] Timeout, re-initialize RFID.");
mfrc522.PCD_Init();
lastRFIDScanTime = millis();
}
switch (currentState) {
case STATE_IDLE:
// Tampilkan LCD hanya sekali saat idle
if (!lcdIdleShown) {
displayDefaultScreen();
lcdIdleShown = true;
}
// Cek kartu RFID
if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {
lcdIdleShown = false; // agar layar bisa refresh nanti
playBuzzer(1, 50, 0);
lastRFIDScanTime = millis(); // reset timeout counter
// Ambil UID
String uidStr = "";
for (byte i = 0; i < mfrc522.uid.size; i++) {
if (mfrc522.uid.uidByte[i] < 0x10) uidStr += "0";
uidStr += String(mfrc522.uid.uidByte[i], HEX);
}
uidStr.toUpperCase();
Serial.println("[RFID] UID: " + uidStr);
displayLcdMessage("RFID Terbaca:", uidStr);
// Cek UID pada daftar
bool found = false;
int lokerId = -1;
int relayPin = -1;
for (int i = 0; i < jumlahRFID; i++) {
if (uidStr == rfidMappings[i].uid) {
found = true;
lokerId = rfidMappings[i].lokerId;
relayPin = rfidMappings[i].relayPin;
break;
}
}
if (found) {
currentState = STATE_OPENING_LOCKER;
handleRFIDAction(uidStr, lokerId, relayPin);
} else {
// Jika tidak ditemukan, aktifkan buzzer "tit-tit-tit" dan tampilkan pesan
playBuzzer(3, 100, 100); // Bunyi 3 kali dengan interval 100ms
displayLcdMessage("Kartu Tidak", "Terdaftar!", 2000);
currentState = STATE_REGISTERING_RFID;
handleNewRFIDRegistration(uidStr);
}
clearRFID();
delay(200); // beri waktu recovery RFID
}
break;
case STATE_REGISTERING_RFID:
case STATE_OPENING_LOCKER:
lcdIdleShown = false;
currentState = STATE_IDLE;
break;
case STATE_ERROR:
if (WiFi.status() != WL_CONNECTED) {
displayLcdMessage("WiFi Disconnect!", "Reconnecting...");
WiFi.reconnect();
delay(1000);
} else {
lcdIdleShown = false;
currentState = STATE_IDLE;
}
break;
}
}
void handleRFIDAction(String uidStr, int mappedLokerId, int mappedRelayPin) {
if (DEBUG_MODE) Serial.println("[RFID Action] Membuka Loker ID: " + String(mappedLokerId) + " dengan UID: " + uidStr);
// Aktifkan relay untuk membuka loker
digitalWrite(mappedRelayPin, LOW);
playBuzzer(2, 70, 50);
if (DEBUG_MODE) Serial.println("[RFID Action] Relay " + String(mappedRelayPin) + " AKTIF (Membuka).");
// Menunggu beberapa detik sambil menampilkan jarak & status loker
unsigned long showStart = millis();
float jarak = 0.0;
String status = "";
// Baca sensor ultrasonik hanya sekali
int trigPin = trigPins[mappedLokerId - 1];
int echoPin = echoPins[mappedLokerId - 1];
// Tunggu 10 detik dan update status loker
while (millis() - showStart < 10000) {
// Menghitung jarak dengan sensor ultrasonik
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
long durasi = pulseIn(echoPin, HIGH);
jarak = durasi * 0.034 / 2; // Menghitung jarak dalam cm
status = (jarak < 10) ? "digunakan" : "kosong"; // Status jika jarak < 10 cm dianggap 'digunakan'
// Tampilkan informasi di LCD
displayLcdMessage("Loker " + String(mappedLokerId),
status + " | " + String(jarak, 0) + "cm");
delay(500); // Mengurangi delay untuk responsifitas yang lebih cepat
}
// Matikan relay setelah 10 detik
digitalWrite(mappedRelayPin, HIGH);
if (DEBUG_MODE) Serial.println("[RFID Action] Relay " + String(mappedRelayPin) + " NONAKTIF (Terkunci).");
// Perbarui status loker ke API
updateStatusLoker(mappedLokerId, status);
// Kembali ke state idle setelah selesai
currentState = STATE_IDLE;
}
void handleNewRFIDRegistration(String uidStr) {
displayLcdMessage("Mencari Loker", "Kosong...");
int kosongLokerIdAPI = getFirstEmptyRFIDLokerId();
if (kosongLokerIdAPI != -1) {
setRFIDtoLoker(kosongLokerIdAPI, uidStr);
displayLcdMessage("RFID Diset", "Loker ID: " + String(kosongLokerIdAPI), 2000);
playBuzzer(1, 150, 0);
} else {
displayLcdMessage("Gagal Set RFID", "Loker Penuh", 2000);
playBuzzer(3, 100, 50);
}
}
void updateStatusLoker(int lokerId, String status) {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
String url = API_BASE_URL + "lokers/" + String(lokerId) + "/status";
http.begin(url);
http.setTimeout(3000);
http.addHeader("Content-Type", "application/json");
String jsonPayload = "{\"status\": \"" + status + "\"}";
int httpResponseCode = http.POST(jsonPayload);
if (httpResponseCode > 0) {
String response = http.getString();
if (DEBUG_MODE) Serial.println("[API] Status update response: " + response);
} else {
currentState = STATE_ERROR;
displayLcdMessage("API Gagal", "Update Status", 2000);
playBuzzer(2, 100, 50);
}
http.end();
} else {
if (DEBUG_MODE) Serial.println("[API] WiFi belum terhubung, tidak bisa update status.");
currentState = STATE_ERROR;
displayLcdMessage("WiFi Disconnect!", "API Update Gagal", 2000);
playBuzzer(2, 100, 50);
}
}
int getFirstEmptyRFIDLokerId() {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
String url = API_BASE_URL + "lokers/pertama-rfid-null";
http.begin(url);
http.setTimeout(3000);
int httpCode = http.GET();
if (httpCode == 200) {
String response = http.getString();
StaticJsonDocument<256> doc;
DeserializationError error = deserializeJson(doc, response);
if (error) return -1;
if (doc.containsKey("data") && doc["data"].containsKey("id")) {
int parsedId = doc["data"]["id"].as<int>();
if (DEBUG_MODE) Serial.println("[API] ID loker kosong ditemukan: " + String(parsedId));
http.end();
return parsedId;
} else {
if (DEBUG_MODE) Serial.println("[API] Respons JSON tidak mengandung 'data.id'.");
http.end();
return -1;
}
} else if (httpCode == 404) {
http.end();
return -1;
} else {
currentState = STATE_ERROR;
http.end();
}
} else {
currentState = STATE_ERROR;
displayLcdMessage("WiFi Disconnect!", "API Get Gagal", 2000);
playBuzzer(2, 100, 50);
}
return -1;
}
void setRFIDtoLoker(int lokerId, String rfid) {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
String url = API_BASE_URL + "lokers/" + String(lokerId) + "/setrfid";
http.begin(url);
http.setTimeout(3000);
http.addHeader("Content-Type", "application/json");
String jsonPayload = "{\"rfid\": \"" + rfid + "\"}";
int httpResponseCode = http.POST(jsonPayload);
if (httpResponseCode > 0) {
String response = http.getString();
if (DEBUG_MODE) Serial.println("[API] SET RFID Response: " + response);
StaticJsonDocument<256> doc;
DeserializationError error = deserializeJson(doc, response);
if (!error && doc.containsKey("message")) {
String message = doc["message"].as<String>();
if (message.indexOf("RFID sudah digunakan") != -1) {
if (DEBUG_MODE) Serial.println("[API] Server Report: RFID sudah digunakan.");
displayLcdMessage("RFID Sudah", "Terdaftar", 2000);
playBuzzer(2, 100, 50);
}
}
} else {
if (DEBUG_MODE) Serial.println("[API] Gagal kirim set RFID: " + http.errorToString(httpResponseCode));
currentState = STATE_ERROR;
displayLcdMessage("API Gagal", "Set RFID", 2000);
playBuzzer(2, 100, 50);
}
http.end();
} else {
if (DEBUG_MODE) Serial.println("[API] WiFi belum terhubung, tidak bisa set RFID.");
currentState = STATE_ERROR;
displayLcdMessage("WiFi Disconnect!", "API Set RFID Gagal", 2000);
playBuzzer(2, 100, 50);
}
}
String getStatusLoker(int lokerId) {
if (DEBUG_MODE) Serial.println("[API] getStatusLoker dipanggil untuk Loker " + String(lokerId));
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
String url = API_BASE_URL + "single-loker/" + String(lokerId);
http.begin(url);
http.setTimeout(3000);
int httpCode = http.GET();
if (DEBUG_MODE) Serial.println("[API] HTTP Code (getStatusLoker): " + String(httpCode));
if (httpCode == 200) {
String payload = http.getString();
if (DEBUG_MODE) Serial.println("[API] GET LOKER Status Response: " + payload);
StaticJsonDocument<256> doc;
DeserializationError error = deserializeJson(doc, payload);
if (!error && doc.containsKey("data") && doc["data"].containsKey("status")) {
String status = doc["data"]["status"].as<String>();
if (DEBUG_MODE) Serial.println("[API] Status dari API: " + status);
http.end();
return status;
} else {
if (DEBUG_MODE) Serial.println("[API] Parsing JSON error atau format tidak sesuai.");
if (DEBUG_MODE) Serial.println(error.c_str());
http.end();
}
} else if (httpCode == 404) {
if (DEBUG_MODE) Serial.println("[API] Loker " + String(lokerId) + " tidak ditemukan.");
http.end();
return "NotFound";
} else {
if (DEBUG_MODE) Serial.println("[API] Gagal ambil status loker: " + http.errorToString(httpCode));
currentState = STATE_ERROR;
http.end();
}
} else {
if (DEBUG_MODE) Serial.println("[API] WiFi belum terhubung, tidak bisa get status loker.");
currentState = STATE_ERROR;
}
return "Unknown";
}
void clearRFID() {
mfrc522.PICC_HaltA();
mfrc522.PCD_StopCrypto1();
if (DEBUG_MODE) Serial.println("[RFID] RFID Reader Direset.");
}
void playBuzzer(int count, int durationMs, int pauseMs) {
for (int i = 0; i < count; i++) {
digitalWrite(BUZZER_PIN, HIGH);
delay(durationMs);
digitalWrite(BUZZER_PIN, LOW);
if (i < count - 1) delay(pauseMs);
}
}
void displayLcdMessage(String line1, String line2, int duration) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(line1);
lcd.setCursor(0, 1);
lcd.print(line2);
if (duration > 0) delay(duration);
}