Jadiin satu mobile, web, dan arduino:
This commit is contained in:
commit
43b05c67e3
|
@ -0,0 +1 @@
|
|||
Subproject commit 5c8f883954503de6c8681b500e1080d90fb63778
|
|
@ -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) }
|
|
@ -0,0 +1 @@
|
|||
Subproject commit dd547f5e2f5d092e99b3f32a15882b4e3645d369
|
Loading…
Reference in New Issue