diff --git a/ESP8266_DHT11_FIREBASE/update_source copy.cpp b/ESP8266_DHT11_FIREBASE/update_source copy.cpp new file mode 100644 index 0000000..780ac4a --- /dev/null +++ b/ESP8266_DHT11_FIREBASE/update_source copy.cpp @@ -0,0 +1,351 @@ +#include +#include +#include +#include + +// Konfigurasi WiFi +#define WIFI_SSID "smartcab" +#define WIFI_PASSWORD "123123123" + +// Konfigurasi Firebase +#define FIREBASE_HOST "smartcab-8bb42-default-rtdb.firebaseio.com" +#define FIREBASE_AUTH "kiiQoFa6Ckp7bL2oRLbaTSGQth9z0PgN64Ybv8dw" + +FirebaseData firebaseData; +FirebaseConfig firebaseConfig; +FirebaseAuth firebaseAuth; + +// MPU6050 I2C address +#define MPU6050_ADDR 0x68 + +const int relayMPUPin = D6; // Relay untuk MPU6050 +const int relayKipasPin = D5; // Relay untuk kipas +const int dhtPin = D3; // DHT11 sensor +#define DHTTYPE DHT11 +DHT dht(dhtPin, DHTTYPE); + +float threshold = 0.05; +float baseAccelX, baseAccelY, baseAccelZ; +bool relayActive = false; +bool mpuEnabled = true; +unsigned long relayStartTime = 0; +unsigned long lastUpdateTime = 0; +unsigned long lastI2CCheckTime = 0; +const unsigned long restartInterval = 6 * 60 * 60 * 1000; // Restart otomatis 6 jam +unsigned long firebaseRetryCount = 0; // Menghitung percobaan koneksi ke Firebase + +// Tambahkan variabel global untuk timestamp +unsigned long lastHeartbeatTime = 0; +const unsigned long heartbeatInterval = 60000; // 60 detik = 1 menit +unsigned long lastFirebaseRetryTime = 0; +const unsigned long firebaseRetryInterval = 5000; // 5 detik antara percobaan + +// Fungsi untuk membaca data dari MPU6050 +void readMPU6050(int16_t* ax, int16_t* ay, int16_t* az) { + Wire.beginTransmission(MPU6050_ADDR); + Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H) + Wire.endTransmission(false); + Wire.requestFrom(MPU6050_ADDR, 6, true); // request a total of 6 registers + + *ax = Wire.read() << 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L) + *ay = Wire.read() << 8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L) + *az = Wire.read() << 8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L) +} + +// Fungsi untuk menginisialisasi MPU6050 +bool initMPU6050() { + Wire.beginTransmission(MPU6050_ADDR); + Wire.write(0x6B); // PWR_MGMT_1 register + Wire.write(0); // set to zero (wakes up the MPU-6050) + return Wire.endTransmission(true) == 0; +} + +void setup() { + Serial.begin(115200); + Wire.begin(D2, D1); // SDA = D2, SCL = D1 + + // Tambahkan pinMode untuk relay + pinMode(relayMPUPin, OUTPUT); + pinMode(relayKipasPin, OUTPUT); + + // Matikan semua relay saat startup + digitalWrite(relayMPUPin, HIGH); // Relay MPU OFF + digitalWrite(relayKipasPin, HIGH); // Relay Kipas OFF + + // Koneksi ke WiFi dulu + WiFi.begin(WIFI_SSID, WIFI_PASSWORD); + Serial.print("Menghubungkan ke WiFi"); + while (WiFi.status() != WL_CONNECTED) { + Serial.print("."); + delay(1000); + } + Serial.println("\nTerhubung ke WiFi"); + + // Konfigurasi Firebase + firebaseConfig.host = FIREBASE_HOST; + firebaseConfig.signer.tokens.legacy_token = FIREBASE_AUTH; + + Firebase.begin(&firebaseConfig, &firebaseAuth); + Firebase.reconnectWiFi(true); + + bool firebaseConnected = false; + for (int i = 0; i < 3; i++) { // Coba 3 kali + if (Firebase.setString(firebaseData, "/logs/systemESP", "Device online")) { + firebaseConnected = true; + Serial.println("Firebase terhubung"); + break; + } else { + Serial.println("Gagal menghubungkan ke Firebase, mencoba lagi..."); + delay(1000); + } + } + + if (!firebaseConnected) { + Serial.println("Tidak dapat terhubung ke Firebase. Sistem keamanan dimatikan."); + mpuEnabled = false; // Matikan keamanan jika Firebase tidak terhubung + } + + // Inisialisasi sensor + if (!initMPU6050()) { + Serial.println("MPU6050 tidak terhubung!"); + if (firebaseConnected) { + Firebase.setString(firebaseData, "/logs/mpu/status", "disconnected"); + } + mpuEnabled = false; + } else { + if (firebaseConnected) { + Firebase.setString(firebaseData, "/logs/mpu/status", "connected"); + } + calibrateSensor(); + } + + dht.begin(); + + // Cek DHT11 + float testReading = dht.readTemperature(); + if (isnan(testReading)) { + Serial.println("DHT11 tidak terhubung atau error!"); + if (firebaseConnected) { + Firebase.setString(firebaseData, "/logs/dht/status", "disconnected"); + } + } else { + if (firebaseConnected) { + Firebase.setString(firebaseData, "/logs/dht/status", "connected"); + } + } + + // Konfigurasi NTP + configTime(7 * 3600, 0, "pool.ntp.org"); + Serial.println("Waiting for time sync"); + while (time(nullptr) < 1000000000) { + Serial.print("."); + delay(100); + } + Serial.println("\nTime synchronized"); +} + +void loop() { + // Cek koneksi WiFi + if (WiFi.status() != WL_CONNECTED) { + Serial.println("WiFi terputus, mencoba menyambung kembali..."); + WiFi.begin(WIFI_SSID, WIFI_PASSWORD); + delay(5000); // Tunggu 5 detik + + // Jika masih tidak terhubung, matikan keamanan + if (WiFi.status() != WL_CONNECTED) { + mpuEnabled = false; + digitalWrite(relayMPUPin, HIGH); // Pastikan relay OFF + } + return; // Keluar dari loop dan coba lagi + } + + // Update lastActive dengan unix timestamp + if (millis() - lastHeartbeatTime >= heartbeatInterval) { + lastHeartbeatTime = millis(); + unsigned long epochTime = time(nullptr); + bool heartbeatSent = false; + + if (Firebase.setInt(firebaseData, "/device/lastActive", epochTime)) { + Serial.println("Heartbeat sent: " + String(epochTime)); + // Tambahkan update status Device online saat heartbeat berhasil + Firebase.setString(firebaseData, "/logs/systemESP", "Device online"); + Serial.println("Device status updated: Online"); + heartbeatSent = true; + firebaseRetryCount = 0; // Reset counter jika berhasil + } else { + Serial.println("Failed to send heartbeat: " + firebaseData.errorReason()); + // Jika gagal mengirim heartbeat, set status offline + firebaseRetryCount++; + + if (firebaseRetryCount >= 3) { // Setelah 3 kali gagal + Serial.println("Firebase tidak dapat diakses setelah beberapa percobaan, mematikan sistem keamanan"); + mpuEnabled = false; // Matikan keamanan + digitalWrite(relayMPUPin, HIGH); // Pastikan relay OFF + Firebase.setString(firebaseData, "/security/status", "off"); // Coba set status off + Firebase.setString(firebaseData, "/logs/systemESP", "Device offline"); + } + } + } + + // Cek jika tidak ada perubahan dalam 70 detik + if (millis() - lastHeartbeatTime > 70000) { + Firebase.setString(firebaseData, "/logs/systemESP", "Device offline"); + } + + // Tambahkan pengecekan status restart di awal loop + if (Firebase.getString(firebaseData, "/control/restartESP")) { + String restartStatus = firebaseData.stringData(); + if (restartStatus == "true") { + Serial.println("Perintah restart diterima dari Firebase"); + // Reset status restart di Firebase ke false + Firebase.setString(firebaseData, "/control/restartESP", "false"); + // Kirim log sebelum restart + Firebase.setString(firebaseData, "/logs/systemESP", "Device restarting by command..."); + delay(1000); // Tunggu sebentar agar data terkirim + ESP.restart(); + } + } else { + Serial.println("Gagal membaca status restart: " + firebaseData.errorReason()); + // Jika gagal membaca dari Firebase, tambahkan counter + firebaseRetryCount++; + + if (firebaseRetryCount >= 3) { // Setelah 3 kali gagal + Serial.println("Tidak dapat mengakses Firebase, mematikan sistem keamanan"); + mpuEnabled = false; // Matikan keamanan + digitalWrite(relayMPUPin, HIGH); // Pastikan relay OFF + // Masih coba set status meski kemungkinan gagal + Firebase.setString(firebaseData, "/security/status", "off"); + } + } + + // Cek auto-restart berdasarkan interval + if (millis() > restartInterval) { + Serial.println("Auto-restart setelah " + String(restartInterval/3600000) + " jam"); + Firebase.setString(firebaseData, "/logs/systemESP", "Device auto-restarting..."); + delay(1000); + ESP.restart(); + } + + // **Cek status MPU6050 setiap 30 detik** + if (millis() - lastI2CCheckTime >= 30000) { + lastI2CCheckTime = millis(); + if (!initMPU6050()) { + Serial.println("MPU6050 tidak merespons! Reset I2C..."); + Firebase.setString(firebaseData, "/logs/mpu/status", "error"); + + Wire.begin(D2, D1); + if (initMPU6050()) { + Firebase.setString(firebaseData, "/logs/mpu/status", "connected"); + } + } + } + + // **Baca status MPU dari Firebase** + bool readSuccess = false; + if (Firebase.getString(firebaseData, "/security/status")) { + String mpuStatus = firebaseData.stringData(); + Serial.print("Status MPU dari Firebase: "); + Serial.println(mpuStatus); + mpuEnabled = (mpuStatus == "on"); + readSuccess = true; + firebaseRetryCount = 0; // Reset counter jika berhasil + } else { + Serial.println("Gagal membaca data dari Firebase: " + firebaseData.errorReason()); + Firebase.setString(firebaseData, "/logs/error", firebaseData.errorReason()); + + // Jika gagal memperoleh data dari Firebase, tambahkan counter + firebaseRetryCount++; + + if (firebaseRetryCount >= 3) { // Setelah 3 kali gagal + // Cek jika waktu cukup berlalu untuk percobaan berikutnya + if (millis() - lastFirebaseRetryTime >= firebaseRetryInterval) { + lastFirebaseRetryTime = millis(); + + Serial.println("Tidak dapat membaca status dari Firebase, mematikan sistem keamanan"); + mpuEnabled = false; // Matikan keamanan + digitalWrite(relayMPUPin, HIGH); // Pastikan relay OFF + + // Masih coba set status meski kemungkinan gagal + Firebase.setString(firebaseData, "/security/status", "off"); + } + } + } + + // **Proses MPU6050** + if (mpuEnabled) { + if (millis() - lastUpdateTime >= 10) { + lastUpdateTime = millis(); + + int16_t ax, ay, az; + readMPU6050(&ax, &ay, &az); + + float accelX = ax / 16384.0; + float accelY = ay / 16384.0; + float accelZ = az / 16384.0; + + float deltaAccel = sqrt(pow(accelX - baseAccelX, 2) + pow(accelY - baseAccelY, 2) + pow(accelZ - baseAccelZ, 2)); + + if (deltaAccel > threshold && !relayActive) { + Serial.println("Getaran terdeteksi! Relay ON."); + digitalWrite(relayMPUPin, LOW); + relayActive = true; + relayStartTime = millis(); + Firebase.setString(firebaseData, "/security/motion", "detected"); + } + + if (relayActive && millis() - relayStartTime >= 8000) { + Serial.println("Relay mati, kalibrasi ulang."); + digitalWrite(relayMPUPin, HIGH); + relayActive = false; + calibrateSensor(); + Firebase.setString(firebaseData, "/security/motion", "clear"); + } + } + } else { + digitalWrite(relayMPUPin, HIGH); // Pastikan relay OFF saat disabled + relayActive = false; + Firebase.setString(firebaseData, "/security/motion", "disabled"); + } + + // **Baca suhu dan kelembaban dari DHT11** + float suhu = dht.readTemperature(); + float humidity = dht.readHumidity(); + + if (isnan(suhu) || isnan(humidity)) { + Serial.println("Gagal membaca data dari DHT11!"); + Firebase.setString(firebaseData, "/logs/dht/status", "error"); + } else { + Firebase.setString(firebaseData, "/logs/dht/status", "connected"); + + Serial.print("Suhu: "); + Serial.print(suhu); + Serial.println(" °C"); + Serial.print("Kelembaban: "); + Serial.print(humidity); + Serial.println(" %"); + + Firebase.setFloat(firebaseData, "/dht11/temperature", suhu); + Firebase.setFloat(firebaseData, "/dht11/humidity", humidity); + } + + // **Kendalikan relay kipas** + if (suhu > 40) { + Serial.println("Suhu tinggi! Kipas ON."); + digitalWrite(relayKipasPin, LOW); + Firebase.setString(firebaseData, "/security/fan", "ON"); + } else { + digitalWrite(relayKipasPin, HIGH); + Firebase.setString(firebaseData, "/security/fan", "OFF"); + } + + yield(); +} + +void calibrateSensor() { + int16_t ax, ay, az; + readMPU6050(&ax, &ay, &az); + baseAccelX = ax / 16384.0; + baseAccelY = ay / 16384.0; + baseAccelZ = az / 16384.0; + Serial.println("Kalibrasi selesai!"); +} \ No newline at end of file diff --git a/ESP8266_DHT11_FIREBASE/update_source.cpp b/ESP8266_DHT11_FIREBASE/update_source.cpp index e82dae2..7d59429 100644 --- a/ESP8266_DHT11_FIREBASE/update_source.cpp +++ b/ESP8266_DHT11_FIREBASE/update_source.cpp @@ -36,6 +36,10 @@ const unsigned long restartInterval = 6 * 60 * 60 * 1000; // Restart otomatis 6 unsigned long lastHeartbeatTime = 0; const unsigned long heartbeatInterval = 60000; // 60 detik = 1 menit +// Tambahkan variabel untuk pengecekan koneksi WiFi +unsigned long lastWiFiCheckTime = 0; +const unsigned long wifiCheckInterval = 10000; // 10 detik + void setup() { Serial.begin(115200); Wire.begin(D2, D1); // SDA = D2, SCL = D1 @@ -105,29 +109,67 @@ void setup() { } void loop() { + // Periksa koneksi WiFi dan Firebase + if (millis() - lastWiFiCheckTime >= wifiCheckInterval) { + lastWiFiCheckTime = millis(); + + // Cek koneksi WiFi + if (WiFi.status() != WL_CONNECTED) { + Serial.println("WiFi terputus! Security dinonaktifkan."); + mpuEnabled = false; + digitalWrite(relayMPUPin, HIGH); // Matikan relay MPU + relayActive = false; + + // Coba hubungkan kembali + WiFi.begin(WIFI_SSID, WIFI_PASSWORD); + } + } + // Update lastActive dengan unix timestamp if (millis() - lastHeartbeatTime >= heartbeatInterval) { lastHeartbeatTime = millis(); - unsigned long epochTime = time(nullptr); - if (Firebase.setInt(firebaseData, "/device/lastActive", epochTime)) { - Serial.println("Heartbeat sent: " + String(epochTime)); - // Tambahkan update status Device online saat heartbeat berhasil - Firebase.setString(firebaseData, "/logs/systemESP", "Device online"); - Serial.println("Device status updated: Online"); + + // Cek apakah terhubung ke WiFi + if (WiFi.status() == WL_CONNECTED) { + unsigned long epochTime = time(nullptr); + if (Firebase.setInt(firebaseData, "/device/lastActive", epochTime)) { + Serial.println("Heartbeat sent: " + String(epochTime)); + // Tambahkan update status Device online saat heartbeat berhasil + Firebase.setString(firebaseData, "/logs/systemESP", "Device online"); + Serial.println("Device status updated: Online"); + } else { + Serial.println("Failed to send heartbeat"); + // Jika gagal mengirim heartbeat, set status offline + Firebase.setString(firebaseData, "/logs/systemESP", "Device offline"); + // Matikan security karena Firebase tidak dapat diakses + mpuEnabled = false; + digitalWrite(relayMPUPin, HIGH); + relayActive = false; + Serial.println("Firebase tidak dapat diakses! Security dinonaktifkan."); + } } else { - Serial.println("Failed to send heartbeat"); - // Jika gagal mengirim heartbeat, set status offline - Firebase.setString(firebaseData, "/logs/systemESP", "Device offline"); + Serial.println("WiFi terputus! Tidak dapat mengirim heartbeat."); + // Pastikan security mati ketika WiFi terputus + mpuEnabled = false; + digitalWrite(relayMPUPin, HIGH); + relayActive = false; } } // Cek jika tidak ada perubahan dalam 70 detik if (millis() - lastHeartbeatTime > 70000) { - Firebase.setString(firebaseData, "/logs/systemESP", "Device offline"); + // WiFi atau Firebase bermasalah, set security off + mpuEnabled = false; + digitalWrite(relayMPUPin, HIGH); + relayActive = false; + + if (WiFi.status() == WL_CONNECTED) { + Firebase.setString(firebaseData, "/logs/systemESP", "Device offline"); + } } // Tambahkan pengecekan status restart di awal loop - if (Firebase.getString(firebaseData, "/control/restartESP")) { + if (WiFi.status() == WL_CONNECTED && Firebase.getString(firebaseData, "/control/restartESP")) { String restartStatus = firebaseData.stringData(); if (restartStatus == "true") { Serial.println("Perintah restart diterima dari Firebase"); @@ -143,8 +185,10 @@ void loop() { // Cek auto-restart berdasarkan interval if (millis() > restartInterval) { Serial.println("Auto-restart setelah " + String(restartInterval/3600000) + " jam"); - Firebase.setString(firebaseData, "/logs/systemESP", "Device auto-restarting..."); - delay(1000); + if (WiFi.status() == WL_CONNECTED) { + Firebase.setString(firebaseData, "/logs/systemESP", "Device auto-restarting..."); + delay(1000); + } ESP.restart(); } @@ -153,26 +197,42 @@ void loop() { lastI2CCheckTime = millis(); if (!mpu.testConnection()) { Serial.println("MPU6050 tidak merespons! Reset I2C..."); - Firebase.setString(firebaseData, "/logs/mpu/status", "error"); + if (WiFi.status() == WL_CONNECTED) { + Firebase.setString(firebaseData, "/logs/mpu/status", "error"); + } Wire.begin(D2, D1); mpu.initialize(); if (mpu.testConnection()) { - Firebase.setString(firebaseData, "/logs/mpu/status", "connected"); + if (WiFi.status() == WL_CONNECTED) { + Firebase.setString(firebaseData, "/logs/mpu/status", "connected"); + } } } } // **Baca status MPU dari Firebase** - if (Firebase.getString(firebaseData, "/security/status")) { - String mpuStatus = firebaseData.stringData(); - Serial.print("Status MPU dari Firebase: "); - Serial.println(mpuStatus); - mpuEnabled = (mpuStatus == "on"); + if (WiFi.status() == WL_CONNECTED) { + if (Firebase.getString(firebaseData, "/security/status")) { + String mpuStatus = firebaseData.stringData(); + Serial.print("Status MPU dari Firebase: "); + Serial.println(mpuStatus); + mpuEnabled = (mpuStatus == "on"); + } else { + Serial.println("Gagal membaca data dari Firebase!"); + if (WiFi.status() == WL_CONNECTED) { + Firebase.setString(firebaseData, "/logs/error", firebaseData.errorReason()); + } + // Matikan security karena Firebase tidak dapat diakses + mpuEnabled = false; + digitalWrite(relayMPUPin, HIGH); + relayActive = false; + Serial.println("Firebase tidak dapat diakses! Security dinonaktifkan."); + } } else { - Serial.println("Gagal membaca data dari Firebase!"); - Firebase.setString(firebaseData, "/logs/error", firebaseData.errorReason()); + // Pastikan security mati ketika WiFi terputus + mpuEnabled = false; } // **Proses MPU6050** @@ -194,7 +254,9 @@ void loop() { digitalWrite(relayMPUPin, LOW); relayActive = true; relayStartTime = millis(); - Firebase.setString(firebaseData, "/security/motion", "detected"); + if (WiFi.status() == WL_CONNECTED) { + Firebase.setString(firebaseData, "/security/motion", "detected"); + } } if (relayActive && millis() - relayStartTime >= 8000) { @@ -202,13 +264,17 @@ void loop() { digitalWrite(relayMPUPin, HIGH); relayActive = false; calibrateSensor(); - Firebase.setString(firebaseData, "/security/motion", "clear"); + if (WiFi.status() == WL_CONNECTED) { + Firebase.setString(firebaseData, "/security/motion", "clear"); + } } } } else { digitalWrite(relayMPUPin, HIGH); // Pastikan relay OFF saat disabled relayActive = false; - Firebase.setString(firebaseData, "/security/motion", "disabled"); + if (WiFi.status() == WL_CONNECTED) { + Firebase.setString(firebaseData, "/security/motion", "disabled"); + } } // **Baca suhu dan kelembaban dari DHT11** @@ -217,9 +283,16 @@ void loop() { if (isnan(suhu) || isnan(humidity)) { Serial.println("Gagal membaca data dari DHT11!"); - Firebase.setString(firebaseData, "/logs/dht/status", "error"); + if (WiFi.status() == WL_CONNECTED) { + Firebase.setString(firebaseData, "/logs/dht/status", "error"); + } } else { - Firebase.setString(firebaseData, "/logs/dht/status", "connected"); + if (WiFi.status() == WL_CONNECTED) { + Firebase.setString(firebaseData, "/logs/dht/status", "connected"); + + Firebase.setFloat(firebaseData, "/dht11/temperature", suhu); + Firebase.setFloat(firebaseData, "/dht11/humidity", humidity); + } Serial.print("Suhu: "); Serial.print(suhu); @@ -227,19 +300,20 @@ void loop() { Serial.print("Kelembaban: "); Serial.print(humidity); Serial.println(" %"); - - Firebase.setFloat(firebaseData, "/dht11/temperature", suhu); - Firebase.setFloat(firebaseData, "/dht11/humidity", humidity); } // **Kendalikan relay kipas** if (suhu > 40) { Serial.println("Suhu tinggi! Kipas ON."); digitalWrite(relayKipasPin, LOW); - Firebase.setString(firebaseData, "/security/fan", "ON"); + if (WiFi.status() == WL_CONNECTED) { + Firebase.setString(firebaseData, "/security/fan", "ON"); + } } else { digitalWrite(relayKipasPin, HIGH); - Firebase.setString(firebaseData, "/security/fan", "OFF"); + if (WiFi.status() == WL_CONNECTED) { + Firebase.setString(firebaseData, "/security/fan", "OFF"); + } } yield(); diff --git a/ESP8266_DHT11_FIREBASE/wemosv3update.cpp b/ESP8266_DHT11_FIREBASE/wemosv3update.cpp index 27bf09d..f9b4626 100644 --- a/ESP8266_DHT11_FIREBASE/wemosv3update.cpp +++ b/ESP8266_DHT11_FIREBASE/wemosv3update.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include // WiFi Credentials #define WIFI_SSID "smartcab" @@ -26,87 +26,182 @@ MFRC522 mfrc522(SS_PIN, RST_PIN); Servo myServo; #define SERVO_PIN D2 // Pin servo -// **ID kartu yang diizinkan** -String kartuTerdaftar[] = {"53ed8434", "3b4f7d9e", "5b85e19d", "cb31e19f", "5b58179f", "1b22e9f"}; -bool servoTerbuka = false; // Status awal servo (tertutup) +// EEPROM Configuration +#define EEPROM_SIZE 512 +#define MAX_CARDS 20 +#define CARD_SIZE 8 // 8 bytes per card (4 byte UID in hex = 8 chars) +#define EEPROM_SIGNATURE 0xAA // Signature byte to check if EEPROM is initialized -// Tambahkan variabel global untuk last active +// Status variables +bool servoTerbuka = false; // Status awal servo (tertutup) unsigned long previousMillis = 0; const long interval = 60000; // interval 1 menit dalam milliseconds - -// Tambahkan di bagian global variables unsigned long lastHeartbeatTime = 0; const long heartbeatInterval = 60000; // 1 menit dalam milliseconds +unsigned long lastCommandCheck = 0; +const long commandCheckInterval = 1000; // 1 detik interval untuk cek command +unsigned long bootTime = 0; // Waktu saat device booting +unsigned long lastWiFiCheck = 0; // Waktu terakhir cek WiFi +const long wifiCheckInterval = 5000; // Interval cek koneksi WiFi (5 detik) + +// Flag untuk status koneksi +bool isWiFiConnected = false; +bool isFirebaseConnected = false; + +// Flag untuk indikasi ada command baru dari Firebase +bool pendingCommand = false; +String currentCommand = ""; +String currentCardId = ""; void setup() { Serial.begin(115200); + Serial.println("\n=== Smart Cabinet System Starting ==="); - // Koneksi ke WiFi + // Catat waktu boot untuk referensi waktu lokal + bootTime = millis(); + + // Initialize EEPROM + EEPROM.begin(EEPROM_SIZE); + initializeEEPROM(); + + // Mulai koneksi WiFi (non-blocking) WiFi.begin(WIFI_SSID, WIFI_PASSWORD); - Serial.print("Menghubungkan ke WiFi"); - while (WiFi.status() != WL_CONNECTED) { - Serial.print("."); - delay(500); - } - Serial.println("\nWiFi Terhubung!"); - - // Konfigurasi Firebase - config.host = FIREBASE_HOST; - config.signer.tokens.legacy_token = FIREBASE_AUTH; - Firebase.begin(&config, &auth); - Firebase.reconnectWiFi(true); - - // Konfigurasi NTP dan tunggu sinkronisasi - configTime(7 * 3600, 0, "pool.ntp.org"); // GMT+7 - Serial.println("Menunggu sinkronisasi waktu"); - while (time(nullptr) < 1000000000) { - Serial.print("."); - delay(100); - } - Serial.println("\nWaktu tersinkronisasi!"); - - // Setelah waktu tersinkronisasi, baru kirim timestamp pertama - unsigned long epochTime = time(nullptr); - if (Firebase.setInt(firebaseData, "/device/lastActiveWemos", epochTime)) { - Serial.println("Initial timestamp sent: " + String(epochTime)); - } else { - Serial.println("Failed to send initial timestamp"); - } - + Serial.println("Memulai koneksi WiFi di background..."); + // Inisialisasi RFID SPI.begin(); mfrc522.PCD_Init(); - // Cek koneksi RFID dengan cara yang lebih aman + // Cek koneksi RFID byte v = mfrc522.PCD_ReadRegister(mfrc522.VersionReg); if (v == 0x00 || v == 0xFF) { - Firebase.setString(firebaseData, "/logs/RFID/status", "Disconnected"); Serial.println("RFID Connection Failed!"); } else { - Firebase.setString(firebaseData, "/logs/RFID/status", "Connected"); Serial.println("RFID Connected!"); } // Inisialisasi Servo myServo.attach(SERVO_PIN, 500, 2500); if (myServo.attached()) { - Firebase.setString(firebaseData, "/logs/servo/status", "Connected"); Serial.println("Servo Connected!"); } else { - Firebase.setString(firebaseData, "/logs/servo/status", "Disconnected"); Serial.println("Servo Connection Failed!"); } myServo.write(0); - - // Update path untuk restart control - Firebase.setBool(firebaseData, "/control/restartWemos", false); - // Update status device saat startup - Firebase.setString(firebaseData, "/logs/systemWemos", "Device Online"); + Serial.println("Setup selesai. Sistem berjalan..."); } void loop() { - // Update path untuk pengecekan restart + // Cek dan update status koneksi WiFi + if (millis() - lastWiFiCheck >= wifiCheckInterval) { + lastWiFiCheck = millis(); + checkWiFiConnection(); + } + + // Cek apakah kartu RFID terdeteksi - selalu berjalan terlepas dari WiFi + checkRFID(); + + // Fungsi-fungsi yang membutuhkan koneksi WiFi + if (isWiFiConnected) { + // Cek perintah restart + checkRestartCommand(); + + // Cek perintah dari Firebase dengan interval untuk menghindari blocking + if (millis() - lastCommandCheck >= commandCheckInterval) { + lastCommandCheck = millis(); + checkFirebaseCommands(); + } + + // Update status perangkat secara berkala + updateDeviceStatus(); + + // Heartbeat ke Firebase + sendHeartbeat(); + } + + delay(100); // Kurangi delay untuk respon lebih cepat +} + +// Fungsi untuk mengecek dan memperbarui status koneksi WiFi +void checkWiFiConnection() { + if (WiFi.status() == WL_CONNECTED) { + if (!isWiFiConnected) { + isWiFiConnected = true; + Serial.println("WiFi terhubung!"); + Serial.print("IP Address: "); + Serial.println(WiFi.localIP()); + + // Setup Firebase saat WiFi baru terhubung + setupFirebase(); + } + } else { + if (isWiFiConnected) { + isWiFiConnected = false; + isFirebaseConnected = false; + Serial.println("WiFi terputus!"); + } + } +} + +// Setup Firebase setelah WiFi terhubung +void setupFirebase() { + config.host = FIREBASE_HOST; + config.signer.tokens.legacy_token = FIREBASE_AUTH; + Firebase.begin(&config, &auth); + Firebase.reconnectWiFi(true); + + // Cek koneksi Firebase + if (Firebase.ready()) { + isFirebaseConnected = true; + Serial.println("Firebase terhubung!"); + + // Kirim timestamp lokal ke Firebase + unsigned long localTime = millis(); + if (Firebase.setInt(firebaseData, "/device/lastActiveWemos", localTime)) { + Serial.println("Initial timestamp sent: " + String(localTime)); + } else { + Serial.println("Failed to send initial timestamp"); + } + + // Update status device saat terhubung + Firebase.setString(firebaseData, "/logs/systemWemos", "Device Online"); + + // Setup struktur data kartu di Firebase + Firebase.setString(firebaseData, "/registered_cards/card", ""); + Firebase.setString(firebaseData, "/registered_cards/delete", ""); + Firebase.setString(firebaseData, "/registered_cards/status", "System connected"); + + // Update status peripheral + updatePeripheralStatus(); + + // Upload daftar kartu ke Firebase + uploadCardListToFirebase(); + } else { + Serial.println("Gagal terhubung ke Firebase!"); + } +} + +// Fungsi untuk update status peripheral +void updatePeripheralStatus() { + // Cek status RFID + byte v = mfrc522.PCD_ReadRegister(mfrc522.VersionReg); + if (v == 0x00 || v == 0xFF) { + Firebase.setString(firebaseData, "/logs/RFID/status", "Disconnected"); + } else { + Firebase.setString(firebaseData, "/logs/RFID/status", "Connected"); + } + + // Cek status Servo + if (myServo.attached()) { + Firebase.setString(firebaseData, "/logs/servo/status", "Connected"); + } else { + Firebase.setString(firebaseData, "/logs/servo/status", "Disconnected"); + } +} + +// Fungsi untuk cek perintah restart +void checkRestartCommand() { if (Firebase.getBool(firebaseData, "/control/restartWemos")) { if (firebaseData.boolData() == true) { // Update status sebelum restart @@ -116,8 +211,78 @@ void loop() { ESP.restart(); } } +} - // Cek status RFID secara periodik dengan cara yang lebih aman +// Fungsi untuk cek RFID +void checkRFID() { + // Cek apakah kartu RFID terdeteksi + if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) { + Serial.println("Kartu Terdeteksi!"); + + // Membaca UID kartu + String rfidUID = ""; + for (byte i = 0; i < mfrc522.uid.size; i++) { + rfidUID += String(mfrc522.uid.uidByte[i], HEX); + } + + Serial.print("UID: "); + Serial.println(rfidUID); + + // Cek apakah kartu terdaftar dalam EEPROM + bool isCardRegistered = isCardInEEPROM(rfidUID); + + if (isCardRegistered) { + Serial.println("Kartu Terdaftar!"); + + if (!servoTerbuka) { + Serial.println("Membuka kunci..."); + myServo.write(180); + servoTerbuka = true; + + // Update Firebase hanya jika terhubung + if (isWiFiConnected && isFirebaseConnected) { + Firebase.setString(firebaseData, "/smartcab/servo_status", "Terbuka"); + } + } else { + Serial.println("Mengunci kunci..."); + myServo.write(0); + servoTerbuka = false; + + // Update Firebase hanya jika terhubung + if (isWiFiConnected && isFirebaseConnected) { + Firebase.setString(firebaseData, "/smartcab/servo_status", "Terkunci"); + } + } + + // Kirim status ke Firebase jika terhubung + if (isWiFiConnected && isFirebaseConnected) { + Firebase.setString(firebaseData, "/smartcab/last_access", "Terdaftar"); + Firebase.setString(firebaseData, "/smartcab/status_device", rfidUID); + } + } + else { + Serial.println("Kartu Tidak Terdaftar! Mengunci servo..."); + + // Paksa servo terkunci jika kartu tidak dikenal + myServo.write(0); + servoTerbuka = false; + + // Update Firebase hanya jika terhubung + if (isWiFiConnected && isFirebaseConnected) { + Firebase.setString(firebaseData, "/smartcab/servo_status", "Terkunci"); + Firebase.setString(firebaseData, "/smartcab/last_access", "Tidak Terdaftar"); + Firebase.setString(firebaseData, "/smartcab/status_device", rfidUID); + } + } + + mfrc522.PICC_HaltA(); // Hentikan komunikasi RFID + mfrc522.PCD_StopCrypto1(); + } +} + +// Update status perangkat +void updateDeviceStatus() { + // Cek status RFID secara periodik byte v = mfrc522.PCD_ReadRegister(mfrc522.VersionReg); if (v == 0x00 || v == 0xFF) { if (Firebase.getString(firebaseData, "/logs/RFID/status") && @@ -138,13 +303,16 @@ void loop() { Firebase.setString(firebaseData, "/logs/servo/status", "Disconnected"); Serial.println("Servo Disconnected!"); } +} - // Update lastActive dengan unix timestamp +// Kirim heartbeat ke Firebase +void sendHeartbeat() { + // Update lastActive dengan timestamp lokal if (millis() - lastHeartbeatTime >= heartbeatInterval) { lastHeartbeatTime = millis(); - unsigned long epochTime = time(nullptr); - if (Firebase.setInt(firebaseData, "/device/lastActiveWemos", epochTime)) { - Serial.println("Heartbeat sent: " + String(epochTime)); + unsigned long localTime = millis(); + if (Firebase.setInt(firebaseData, "/device/lastActiveWemos", localTime)) { + Serial.println("Heartbeat sent: " + String(localTime)); // Tambahkan update status Device Online saat heartbeat berhasil Firebase.setString(firebaseData, "/logs/systemWemos", "Device Online"); Serial.println("Device status updated: Online"); @@ -159,62 +327,218 @@ void loop() { if (millis() - lastHeartbeatTime > 70000) { Firebase.setString(firebaseData, "/logs/systemWemos", "Device Offline"); } +} - // Cek apakah kartu RFID terdeteksi - if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) { - Serial.println("Kartu Terdeteksi!"); - - // Membaca UID kartu - String rfidUID = ""; - for (byte i = 0; i < mfrc522.uid.size; i++) { - rfidUID += String(mfrc522.uid.uidByte[i], HEX); +// Fungsi untuk inisialisasi EEPROM jika belum diinisialisasi +void initializeEEPROM() { + // Cek signature byte + if (EEPROM.read(0) != EEPROM_SIGNATURE) { + Serial.println("Initializing EEPROM for first use..."); + // Set signature + EEPROM.write(0, EEPROM_SIGNATURE); + // Clear card slots + for (int i = 1; i < EEPROM_SIZE; i++) { + EEPROM.write(i, 0xFF); } + EEPROM.commit(); + Serial.println("EEPROM initialized"); + } +} - Serial.print("UID: "); - Serial.println(rfidUID); +// Fungsi untuk cek apakah kartu terdaftar di EEPROM +bool isCardInEEPROM(String cardId) { + int startAddr = 1; // Skip signature byte + + for (int i = 0; i < MAX_CARDS; i++) { + int addr = startAddr + (i * CARD_SIZE); + if (EEPROM.read(addr) != 0xFF) { // Jika slot tidak kosong + char storedCard[CARD_SIZE+1]; + for (int j = 0; j < CARD_SIZE; j++) { + storedCard[j] = char(EEPROM.read(addr + j)); + } + storedCard[CARD_SIZE] = '\0'; + + if (cardId == String(storedCard)) { + return true; + } + } + } + return false; +} - // **Cek apakah kartu terdaftar** - bool isCardRegistered = false; - for (int i = 0; i < sizeof(kartuTerdaftar)/sizeof(kartuTerdaftar[0]); i++) { - if (rfidUID == kartuTerdaftar[i]) { - isCardRegistered = true; +// Fungsi untuk menambahkan kartu ke EEPROM +bool addCardToEEPROM(String cardId) { + if (cardId.length() != CARD_SIZE) { + Serial.println("Card ID harus " + String(CARD_SIZE) + " karakter!"); + return false; + } + + // Cek apakah kartu sudah terdaftar + if (isCardInEEPROM(cardId)) { + Serial.println("Kartu sudah terdaftar!"); + return false; + } + + int startAddr = 1; // Skip signature byte + bool cardAdded = false; + + // Cari slot kosong + for (int i = 0; i < MAX_CARDS; i++) { + int addr = startAddr + (i * CARD_SIZE); + if (EEPROM.read(addr) == 0xFF) { // Slot kosong + // Simpan card ID + for (int j = 0; j < CARD_SIZE; j++) { + EEPROM.write(addr + j, cardId[j]); + } + EEPROM.commit(); + cardAdded = true; + Serial.println("Kartu berhasil ditambahkan!"); + break; + } + } + + if (!cardAdded) { + Serial.println("EEPROM penuh! Hapus beberapa kartu terlebih dahulu."); + return false; + } + + return true; +} + +// Fungsi untuk menghapus kartu dari EEPROM +bool removeCardFromEEPROM(String cardId) { + int startAddr = 1; // Skip signature byte + bool cardRemoved = false; + + for (int i = 0; i < MAX_CARDS; i++) { + int addr = startAddr + (i * CARD_SIZE); + if (EEPROM.read(addr) != 0xFF) { // Jika slot tidak kosong + char storedCard[CARD_SIZE+1]; + for (int j = 0; j < CARD_SIZE; j++) { + storedCard[j] = char(EEPROM.read(addr + j)); + } + storedCard[CARD_SIZE] = '\0'; + + if (cardId == String(storedCard)) { + // Hapus card dengan mengisi 0xFF + for (int j = 0; j < CARD_SIZE; j++) { + EEPROM.write(addr + j, 0xFF); + } + EEPROM.commit(); + cardRemoved = true; + Serial.println("Kartu berhasil dihapus!"); break; } } - - if (isCardRegistered) { - Serial.println("Kartu Terdaftar!"); - - if (!servoTerbuka) { - Serial.println("Membuka kunci..."); - myServo.write(180); - servoTerbuka = true; - Firebase.setString(firebaseData, "/smartcab/servo_status", "Terbuka"); - } else { - Serial.println("Mengunci kunci..."); - myServo.write(0); - servoTerbuka = false; - Firebase.setString(firebaseData, "/smartcab/servo_status", "Terkunci"); - } - - // Kirim status ke Firebase - Firebase.setString(firebaseData, "/smartcab/last_access", "Terdaftar"); - Firebase.setString(firebaseData, "/smartcab/status_device", rfidUID); - } - else { - Serial.println("Kartu Tidak Terdaftar! Mengunci servo..."); - - // Paksa servo terkunci jika kartu tidak dikenal - myServo.write(0); - servoTerbuka = false; - Firebase.setString(firebaseData, "/smartcab/servo_status", "Terkunci"); - Firebase.setString(firebaseData, "/smartcab/last_access", "Tidak Terdaftar"); - Firebase.setString(firebaseData, "/smartcab/status_device", rfidUID); - } - - mfrc522.PICC_HaltA(); // Hentikan komunikasi RFID - mfrc522.PCD_StopCrypto1(); } - - delay(500); + + if (!cardRemoved) { + Serial.println("Kartu tidak ditemukan!"); + return false; + } + + return true; +} + +// Fungsi untuk menghapus semua kartu dari EEPROM +void clearAllCards() { + int startAddr = 1; // Skip signature byte + + for (int i = 0; i < MAX_CARDS * CARD_SIZE; i++) { + EEPROM.write(startAddr + i, 0xFF); + } + EEPROM.commit(); + Serial.println("Semua kartu berhasil dihapus!"); +} + +// Fungsi untuk mendapatkan jumlah kartu yang tersimpan di EEPROM +int getCardCount() { + int startAddr = 1; // Skip signature byte + int count = 0; + + for (int i = 0; i < MAX_CARDS; i++) { + int addr = startAddr + (i * CARD_SIZE); + if (EEPROM.read(addr) != 0xFF) { // Jika slot tidak kosong + count++; + } + } + + return count; +} + +// Fungsi untuk upload daftar kartu ke Firebase +void uploadCardListToFirebase() { + int startAddr = 1; // Skip signature byte + int count = 0; + + // Clear existing list + Firebase.deleteNode(firebaseData, "/registered_cards/list"); + + // Add cards to list + for (int i = 0; i < MAX_CARDS; i++) { + int addr = startAddr + (i * CARD_SIZE); + if (EEPROM.read(addr) != 0xFF) { // Jika slot tidak kosong + char storedCard[CARD_SIZE+1]; + for (int j = 0; j < CARD_SIZE; j++) { + storedCard[j] = char(EEPROM.read(addr + j)); + } + storedCard[CARD_SIZE] = '\0'; + + String cardKey = "card" + String(count + 1); + Firebase.setString(firebaseData, "/registered_cards/list/" + cardKey, String(storedCard)); + count++; + } + } + + // Update total count + Firebase.setInt(firebaseData, "/registered_cards/total", count); + + Serial.println("Daftar kartu berhasil diupload ke Firebase!"); +} + +// Fungsi untuk memeriksa perintah dari Firebase +void checkFirebaseCommands() { + // Check for new card to add + if (Firebase.getString(firebaseData, "/registered_cards/card")) { + String cardId = firebaseData.stringData(); + + if (cardId != "") { + Serial.println("Perintah baru: tambah kartu " + cardId); + + if (addCardToEEPROM(cardId)) { + Firebase.setString(firebaseData, "/registered_cards/status", "Kartu berhasil ditambahkan"); + uploadCardListToFirebase(); + } else { + Firebase.setString(firebaseData, "/registered_cards/status", "Gagal menambahkan kartu"); + } + + // Reset command + Firebase.setString(firebaseData, "/registered_cards/card", ""); + } + } + + // Check for card to delete + if (Firebase.getString(firebaseData, "/registered_cards/delete")) { + String cardId = firebaseData.stringData(); + + if (cardId != "") { + Serial.println("Perintah baru: hapus kartu " + cardId); + + if (cardId == "all") { + clearAllCards(); + Firebase.setString(firebaseData, "/registered_cards/status", "Semua kartu berhasil dihapus"); + uploadCardListToFirebase(); + } else { + if (removeCardFromEEPROM(cardId)) { + Firebase.setString(firebaseData, "/registered_cards/status", "Kartu berhasil dihapus"); + uploadCardListToFirebase(); + } else { + Firebase.setString(firebaseData, "/registered_cards/status", "Kartu tidak ditemukan"); + } + } + + // Reset command + Firebase.setString(firebaseData, "/registered_cards/delete", ""); + } + } } diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index b7e7c7d..a65e7fd 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -12,7 +12,8 @@ class Kernel extends ConsoleKernel */ protected function schedule(Schedule $schedule): void { - $schedule->command('firebase:fetch')->everyMinute(); + $schedule->command('firebase:fetch') + ->everySecond(); } /** * Register the commands for the application. diff --git a/app/Http/Controllers/CardController.php b/app/Http/Controllers/CardController.php new file mode 100644 index 0000000..4e0fe8f --- /dev/null +++ b/app/Http/Controllers/CardController.php @@ -0,0 +1,70 @@ +database = $database; + } + + public function index() + { + $cards = $this->database->getReference('registered_cards/list')->getValue(); + $total = $this->database->getReference('registered_cards/total')->getValue(); + $lastCardId = $this->database->getReference('smartcab/status_device')->getValue(); + $lastAccess = $this->database->getReference('smartcab/last_access')->getValue(); + + return view('view_card', compact('cards', 'total', 'lastCardId', 'lastAccess')); + } + + public function addCard(Request $request) + { + $request->validate([ + 'card_id' => 'required|string|min:7|max:8', + ]); + + $cardId = $request->input('card_id'); + $this->database->getReference('registered_cards/card')->set($cardId); + + // Wait for 1.5 seconds before resetting + usleep(1500000); + + // Reset the card value to empty string after sending command + $this->database->getReference('registered_cards/card')->set(''); + + return redirect()->route('view.cards')->with('success', 'Card added successfully!'); + } + + public function deleteCard($cardId) + { + $this->database->getReference('registered_cards/delete')->set($cardId); + + // Wait for 1.5 seconds before resetting + usleep(1500000); + + // Reset the delete value to empty string after sending command + $this->database->getReference('registered_cards/delete')->set(''); + + return redirect()->route('view.cards')->with('success', 'Card deletion requested'); + } + + public function deleteAllCards() + { + $this->database->getReference('registered_cards/delete')->set('all'); + + // Wait for 1.5 seconds before resetting + usleep(1500000); + + // Reset the delete value to empty string after sending command + $this->database->getReference('registered_cards/delete')->set(''); + + return redirect()->route('view.cards')->with('success', 'All cards deletion requested'); + } +} \ No newline at end of file diff --git a/resources/views/reports.blade.php b/resources/views/reports.blade.php index a924e1d..c8c0391 100644 --- a/resources/views/reports.blade.php +++ b/resources/views/reports.blade.php @@ -53,7 +53,6 @@ -

Laporan Keamanan dan Monitoring

@@ -214,37 +213,7 @@
- -
- - -
+
+
+ + +
+
+ + + + Registered Cards +
+
+ + + + + + + + + + @if(!empty($cards)) + @foreach($cards as $key => $cardId) + + + + + + @endforeach + @else + + + + @endif + +
No.Card IDAction
{{ $loop->iteration }}{{ $cardId }} + + + + + Delete + +
No cards registered
+
+
+ + + +
+
+
+ + + + System Status +
+
+
+
+ + + + + Total Cards: + + {{ $total ?? 0 }} +
+
+ + + + + System Status: + + Loading... +
+
+ + + + + RFID Status: + + Loading... +
+
+ + + + + + Servo Status: + + Loading... +
+
+ +
+
+
+ + + + + + + + + + + \ No newline at end of file diff --git a/resources/views/welcome.blade.php b/resources/views/welcome.blade.php index 3f0a52a..186a482 100644 --- a/resources/views/welcome.blade.php +++ b/resources/views/welcome.blade.php @@ -29,15 +29,19 @@ {{-- AI --}} - - + + + + + + + + + + + + +