Jadiin satu mobile, web, dan arduino:

This commit is contained in:
fitriyah123 2025-07-30 14:28:04 +07:00
commit 43b05c67e3
3 changed files with 458 additions and 0 deletions

1
API laravel Submodule

@ -0,0 +1 @@
Subproject commit 5c8f883954503de6c8681b500e1080d90fb63778

View File

@ -0,0 +1,456 @@
1) #include <WiFi.h>
2) #include <HTTPClient.h>
3) #include <SPI.h>
4) #include <Wire.h>
5) #include <MFRC522.h>
6) #include <LiquidCrystal_I2C.h>
7) #include <ArduinoJson.h>
8)
9) #define DEBUG_MODE true
10)
11) const char* ssid = "KOPI";
12) const char* password = "digoreng123";
13) const String API_BASE_URL = "https://smartlocker.punyapadias.my.id/api/";
14)
15) #define SS_PIN 21
16) #define RST_PIN 5
17) MFRC522 mfrc522(SS_PIN, RST_PIN);
18)
19) LiquidCrystal_I2C lcd(0x27, 16, 2);
20)
21) const int trigPins[3] = {17, 16, 33};
22) const int echoPins[3] = {35, 34, 32};
23)
24) #define RELAY1_PIN 14
25) #define RELAY2_PIN 27
26) #define RELAY3_PIN 26
27)
28) #define BUZZER_PIN 13
29)
30) enum SystemState {
31) STATE_IDLE,
32) STATE_RFID_DETECTED,
33) STATE_OPENING_LOCKER,
34) STATE_REGISTERING_RFID,
35) STATE_ERROR
36) };
37) SystemState currentState = STATE_IDLE;
38)
39) unsigned long lastApiCallTime = 0;
40) const long apiCallInterval = 5000;
41) unsigned long rfidActionStartTime = 0;
42) const long rfidActionDuration = 10000;
43) bool lcdIdleShown = false;
44)
45)
46) struct RFIDMapping {
47) String uid;
48) int lokerId;
49) int relayPin;
50) };
51)
52) RFIDMapping rfidMappings[] = {
53) {"36CB3503", 1, RELAY1_PIN},
54) {"5C312903", 2, RELAY2_PIN},
55) {"611B2803", 3, RELAY3_PIN},
56) };
57) const int jumlahRFID = sizeof(rfidMappings) / sizeof(rfidMappings[0]);
58)
59) void setRFIDtoLoker(int lokerId, String rfid);
60) void updateStatusLoker(int lokerId, String status);
61) int getFirstEmptyRFIDLokerId();
62) String getStatusLoker(int lokerId);
63) void clearRFID();
64) void playBuzzer(int count, int durationMs, int pauseMs);
65) void displayLcdMessage(String line1, String line2, int duration = 0);
66) void handleRFIDAction(String uidStr, int mappedLokerId, int mappedRelayPin);
67) void handleNewRFIDRegistration(String uidStr);
68)
69) void displayDefaultScreen() {
70) lcd.clear();
71) lcd.setCursor(0, 0);
72) lcd.print("Loker Pintar");
73) lcd.setCursor(0, 1);
74) lcd.print("Scan Kartu");
75) }
76)
77) void setup() {
78) Serial.begin(115200);
79) Wire.begin(4, 22);
80) lcd.init();
81) lcd.backlight();
82) lcd.setCursor(0, 0);
83) lcd.print("Inisialisasi...");
84)
85) // Menyambung ke WiFi
86) WiFi.begin(ssid, password);
87) lcd.setCursor(0, 1);
88) lcd.print("WiFi connecting...");
89) while (WiFi.status() != WL_CONNECTED) {
90) delay(500);
91) Serial.print(".");
92) }
93)
94) lcd.setCursor(0, 1);
95) lcd.print("WiFi connected ");
96) Serial.println("\nWiFi Connected. IP: " + WiFi.localIP().toString());
97)
98) // Inisialisasi RFID
99) SPI.begin();
100) mfrc522.PCD_Init();
101)
102) // Inisialisasi sensor ultrasonik
103) for (int i = 0; i < 3; i++) {
104) pinMode(trigPins[i], OUTPUT);
105) pinMode(echoPins[i], INPUT);
106) }
107)
108) // Inisialisasi relay dan buzzer
109) pinMode(RELAY1_PIN, OUTPUT); digitalWrite(RELAY1_PIN, HIGH);
110) pinMode(RELAY2_PIN, OUTPUT); digitalWrite(RELAY2_PIN, HIGH);
111) pinMode(RELAY3_PIN, OUTPUT); digitalWrite(RELAY3_PIN, HIGH);
112)
113) pinMode(BUZZER_PIN, OUTPUT);
114) digitalWrite(BUZZER_PIN, LOW);
115)
116) // Tampilkan layar utama
117) lcd.clear();
118) displayDefaultScreen();
119)
120) lastApiCallTime = millis();
121) }
122)
123) void loop() {
124) // Debug: tampilkan state saat ini setiap 1 detik
125) static unsigned long lastDebugTime = 0;
126) if (millis() - lastDebugTime > 1000) {
127) Serial.println("[DEBUG] Current state: " + String(currentState));
128) lastDebugTime = millis();
129) }
130)
131) // Recovery: jika RFID tidak terbaca dalam waktu lama, inisialisasi ulang
132) static unsigned long lastRFIDScanTime = 0;
133) if (millis() - lastRFIDScanTime > 10000) {
134) Serial.println("[RFID] Timeout, re-initialize RFID.");
135) mfrc522.PCD_Init();
136) lastRFIDScanTime = millis();
137) }
138)
139) switch (currentState) {
140) case STATE_IDLE:
141) // Tampilkan LCD hanya sekali saat idle
142) if (!lcdIdleShown) {
143) displayDefaultScreen();
144) lcdIdleShown = true;
145) }
146)
147) // Cek kartu RFID
148) if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {
149) lcdIdleShown = false; // agar layar bisa refresh nanti
150) playBuzzer(1, 50, 0);
151) lastRFIDScanTime = millis(); // reset timeout counter
152)
153) // Ambil UID
154) String uidStr = "";
155) for (byte i = 0; i < mfrc522.uid.size; i++) {
156) if (mfrc522.uid.uidByte[i] < 0x10) uidStr += "0";
157) uidStr += String(mfrc522.uid.uidByte[i], HEX);
158) }
159) uidStr.toUpperCase();
160)
161) Serial.println("[RFID] UID: " + uidStr);
162) displayLcdMessage("RFID Terbaca:", uidStr);
163)
164) // Cek UID pada daftar
165) bool found = false;
166) int lokerId = -1;
167) int relayPin = -1;
168) for (int i = 0; i < jumlahRFID; i++) {
169) if (uidStr == rfidMappings[i].uid) {
170) found = true;
171) lokerId = rfidMappings[i].lokerId;
172) relayPin = rfidMappings[i].relayPin;
173) break;
174) }
175) }
176)
177) if (found) {
178) currentState = STATE_OPENING_LOCKER;
179) handleRFIDAction(uidStr, lokerId, relayPin);
180) } else {
181) // Jika tidak ditemukan, aktifkan buzzer "tit-tit-tit" dan tampilkan pesan
182) playBuzzer(3, 100, 100); // Bunyi 3 kali dengan interval 100ms
183) displayLcdMessage("Kartu Tidak", "Terdaftar!", 2000);
184) currentState = STATE_REGISTERING_RFID;
185) handleNewRFIDRegistration(uidStr);
186) }
187)
188) clearRFID();
189) delay(200); // beri waktu recovery RFID
190) }
191) break;
192)
193) case STATE_REGISTERING_RFID:
194) case STATE_OPENING_LOCKER:
195) lcdIdleShown = false;
196) currentState = STATE_IDLE;
197) break;
198)
199) case STATE_ERROR:
200) if (WiFi.status() != WL_CONNECTED) {
201) displayLcdMessage("WiFi Disconnect!", "Reconnecting...");
202) WiFi.reconnect();
203) delay(1000);
204) } else {
205) lcdIdleShown = false;
206) currentState = STATE_IDLE;
207) }
208) break;
209) }
210) }
211)
212)
213)
214)
215)
216) void handleRFIDAction(String uidStr, int mappedLokerId, int mappedRelayPin) {
217) if (DEBUG_MODE) Serial.println("[RFID Action] Membuka Loker ID: " + String(mappedLokerId) + " dengan UID: " + uidStr);
218)
219) // Aktifkan relay untuk membuka loker
220) digitalWrite(mappedRelayPin, LOW);
221) playBuzzer(2, 70, 50);
222) if (DEBUG_MODE) Serial.println("[RFID Action] Relay " + String(mappedRelayPin) + " AKTIF (Membuka).");
223)
224) // Menunggu beberapa detik sambil menampilkan jarak & status loker
225) unsigned long showStart = millis();
226) float jarak = 0.0;
227) String status = "";
228)
229) // Baca sensor ultrasonik hanya sekali
230) int trigPin = trigPins[mappedLokerId - 1];
231) int echoPin = echoPins[mappedLokerId - 1];
232)
233) // Tunggu 10 detik dan update status loker
234) while (millis() - showStart < 10000) {
235) // Menghitung jarak dengan sensor ultrasonik
236) digitalWrite(trigPin, LOW);
237) delayMicroseconds(2);
238) digitalWrite(trigPin, HIGH);
239) delayMicroseconds(10);
240) digitalWrite(trigPin, LOW);
241)
242) long durasi = pulseIn(echoPin, HIGH);
243) jarak = durasi * 0.034 / 2; // Menghitung jarak dalam cm
244) status = (jarak < 10) ? "digunakan" : "kosong"; // Status jika jarak < 10 cm dianggap 'digunakan'
245)
246) // Tampilkan informasi di LCD
247) displayLcdMessage("Loker " + String(mappedLokerId),
248) status + " | " + String(jarak, 0) + "cm");
249) delay(500); // Mengurangi delay untuk responsifitas yang lebih cepat
250) }
251)
252) // Matikan relay setelah 10 detik
253) digitalWrite(mappedRelayPin, HIGH);
254) if (DEBUG_MODE) Serial.println("[RFID Action] Relay " + String(mappedRelayPin) + " NONAKTIF (Terkunci).");
255)
256) // Perbarui status loker ke API
257) updateStatusLoker(mappedLokerId, status);
258)
259) // Kembali ke state idle setelah selesai
260) currentState = STATE_IDLE;
261) }
262)
263)
264)
265) void handleNewRFIDRegistration(String uidStr) {
266) displayLcdMessage("Mencari Loker", "Kosong...");
267) int kosongLokerIdAPI = getFirstEmptyRFIDLokerId();
268)
269) if (kosongLokerIdAPI != -1) {
270) setRFIDtoLoker(kosongLokerIdAPI, uidStr);
271) displayLcdMessage("RFID Diset", "Loker ID: " + String(kosongLokerIdAPI), 2000);
272) playBuzzer(1, 150, 0);
273) } else {
274) displayLcdMessage("Gagal Set RFID", "Loker Penuh", 2000);
275) playBuzzer(3, 100, 50);
276) }
277) }
278)
279) void updateStatusLoker(int lokerId, String status) {
280) if (WiFi.status() == WL_CONNECTED) {
281) HTTPClient http;
282) String url = API_BASE_URL + "lokers/" + String(lokerId) + "/status";
283)
284) http.begin(url);
285) http.setTimeout(3000);
286) http.addHeader("Content-Type", "application/json");
287)
288) String jsonPayload = "{\"status\": \"" + status + "\"}";
289) int httpResponseCode = http.POST(jsonPayload);
290)
291) if (httpResponseCode > 0) {
292) String response = http.getString();
293) if (DEBUG_MODE) Serial.println("[API] Status update response: " + response);
294) } else {
295) currentState = STATE_ERROR;
296) displayLcdMessage("API Gagal", "Update Status", 2000);
297) playBuzzer(2, 100, 50);
298) }
299) http.end();
300) } else {
301) if (DEBUG_MODE) Serial.println("[API] WiFi belum terhubung, tidak bisa update status.");
302) currentState = STATE_ERROR;
303) displayLcdMessage("WiFi Disconnect!", "API Update Gagal", 2000);
304) playBuzzer(2, 100, 50);
305) }
306) }
307)
308) int getFirstEmptyRFIDLokerId() {
309) if (WiFi.status() == WL_CONNECTED) {
310) HTTPClient http;
311) String url = API_BASE_URL + "lokers/pertama-rfid-null";
312)
313) http.begin(url);
314) http.setTimeout(3000);
315) int httpCode = http.GET();
316)
317) if (httpCode == 200) {
318) String response = http.getString();
319) StaticJsonDocument<256> doc;
320) DeserializationError error = deserializeJson(doc, response);
321)
322) if (error) return -1;
323)
324) if (doc.containsKey("data") && doc["data"].containsKey("id")) {
325) int parsedId = doc["data"]["id"].as<int>();
326) if (DEBUG_MODE) Serial.println("[API] ID loker kosong ditemukan: " + String(parsedId));
327) http.end();
328) return parsedId;
329) } else {
330) if (DEBUG_MODE) Serial.println("[API] Respons JSON tidak mengandung 'data.id'.");
331) http.end();
332) return -1;
333) }
334) } else if (httpCode == 404) {
335) http.end();
336) return -1;
337) } else {
338) currentState = STATE_ERROR;
339) http.end();
340) }
341) } else {
342) currentState = STATE_ERROR;
343) displayLcdMessage("WiFi Disconnect!", "API Get Gagal", 2000);
344) playBuzzer(2, 100, 50);
345) }
346) return -1;
347) }
348)
349) void setRFIDtoLoker(int lokerId, String rfid) {
350) if (WiFi.status() == WL_CONNECTED) {
351) HTTPClient http;
352) String url = API_BASE_URL + "lokers/" + String(lokerId) + "/setrfid";
353)
354) http.begin(url);
355) http.setTimeout(3000);
356) http.addHeader("Content-Type", "application/json");
357)
358) String jsonPayload = "{\"rfid\": \"" + rfid + "\"}";
359) int httpResponseCode = http.POST(jsonPayload);
360)
361) if (httpResponseCode > 0) {
362) String response = http.getString();
363) if (DEBUG_MODE) Serial.println("[API] SET RFID Response: " + response);
364) StaticJsonDocument<256> doc;
365) DeserializationError error = deserializeJson(doc, response);
366)
367) if (!error && doc.containsKey("message")) {
368) String message = doc["message"].as<String>();
369) if (message.indexOf("RFID sudah digunakan") != -1) {
370) if (DEBUG_MODE) Serial.println("[API] Server Report: RFID sudah digunakan.");
371) displayLcdMessage("RFID Sudah", "Terdaftar", 2000);
372) playBuzzer(2, 100, 50);
373) }
374) }
375) } else {
376) if (DEBUG_MODE) Serial.println("[API] Gagal kirim set RFID: " + http.errorToString(httpResponseCode));
377) currentState = STATE_ERROR;
378) displayLcdMessage("API Gagal", "Set RFID", 2000);
379) playBuzzer(2, 100, 50);
380) }
381) http.end();
382) } else {
383) if (DEBUG_MODE) Serial.println("[API] WiFi belum terhubung, tidak bisa set RFID.");
384) currentState = STATE_ERROR;
385) displayLcdMessage("WiFi Disconnect!", "API Set RFID Gagal", 2000);
386) playBuzzer(2, 100, 50);
387) }
388) }
389)
390) String getStatusLoker(int lokerId) {
391) if (DEBUG_MODE) Serial.println("[API] getStatusLoker dipanggil untuk Loker " + String(lokerId));
392) if (WiFi.status() == WL_CONNECTED) {
393) HTTPClient http;
394) String url = API_BASE_URL + "single-loker/" + String(lokerId);
395)
396) http.begin(url);
397) http.setTimeout(3000);
398) int httpCode = http.GET();
399) if (DEBUG_MODE) Serial.println("[API] HTTP Code (getStatusLoker): " + String(httpCode));
400)
401) if (httpCode == 200) {
402) String payload = http.getString();
403) if (DEBUG_MODE) Serial.println("[API] GET LOKER Status Response: " + payload);
404)
405) StaticJsonDocument<256> doc;
406) DeserializationError error = deserializeJson(doc, payload);
407)
408) if (!error && doc.containsKey("data") && doc["data"].containsKey("status")) {
409) String status = doc["data"]["status"].as<String>();
410) if (DEBUG_MODE) Serial.println("[API] Status dari API: " + status);
411) http.end();
412) return status;
413) } else {
414) if (DEBUG_MODE) Serial.println("[API] Parsing JSON error atau format tidak sesuai.");
415) if (DEBUG_MODE) Serial.println(error.c_str());
416) http.end();
417) }
418) } else if (httpCode == 404) {
419) if (DEBUG_MODE) Serial.println("[API] Loker " + String(lokerId) + " tidak ditemukan.");
420) http.end();
421) return "NotFound";
422) } else {
423) if (DEBUG_MODE) Serial.println("[API] Gagal ambil status loker: " + http.errorToString(httpCode));
424) currentState = STATE_ERROR;
425) http.end();
426) }
427) } else {
428) if (DEBUG_MODE) Serial.println("[API] WiFi belum terhubung, tidak bisa get status loker.");
429) currentState = STATE_ERROR;
430) }
431) return "Unknown";
432) }
433)
434) void clearRFID() {
435) mfrc522.PICC_HaltA();
436) mfrc522.PCD_StopCrypto1();
437) if (DEBUG_MODE) Serial.println("[RFID] RFID Reader Direset.");
438) }
439)
440) void playBuzzer(int count, int durationMs, int pauseMs) {
441) for (int i = 0; i < count; i++) {
442) digitalWrite(BUZZER_PIN, HIGH);
443) delay(durationMs);
444) digitalWrite(BUZZER_PIN, LOW);
445) if (i < count - 1) delay(pauseMs);
446) }
447) }
448)
449) void displayLcdMessage(String line1, String line2, int duration) {
450) lcd.clear();
451) lcd.setCursor(0, 0);
452) lcd.print(line1);
453) lcd.setCursor(0, 1);
454) lcd.print(line2);
455) if (duration > 0) delay(duration);
456) }

1
mobile-smart-locker Submodule

@ -0,0 +1 @@
Subproject commit dd547f5e2f5d092e99b3f32a15882b4e3645d369