From beb4d15d112543f1304fb91dbe062992e4002578 Mon Sep 17 00:00:00 2001 From: Vckynando12 Date: Sun, 23 Mar 2025 17:42:37 +0700 Subject: [PATCH] fix report and add filter --- ESP8266_DHT11_FIREBASE/wemosv3update.cpp | 24 +- app/Console/Commands/FetchFirebaseData.php | 242 +++++++-- app/Events/ReportUpdated.php | 20 +- resources/views/reports.blade.php | 590 +++++++++++++-------- 4 files changed, 617 insertions(+), 259 deletions(-) diff --git a/ESP8266_DHT11_FIREBASE/wemosv3update.cpp b/ESP8266_DHT11_FIREBASE/wemosv3update.cpp index b1208ee..27bf09d 100644 --- a/ESP8266_DHT11_FIREBASE/wemosv3update.cpp +++ b/ESP8266_DHT11_FIREBASE/wemosv3update.cpp @@ -56,6 +56,23 @@ void setup() { 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"); + } + // Inisialisasi RFID SPI.begin(); mfrc522.PCD_Init(); @@ -84,13 +101,6 @@ void setup() { // Update path untuk restart control Firebase.setBool(firebaseData, "/control/restartWemos", false); - // Konfigurasi NTP - configTime(7 * 3600, 0, "pool.ntp.org"); // GMT+7 - - // Kirim timestamp pertama kali - unsigned long epochTime = time(nullptr); - Firebase.setInt(firebaseData, "/device/lastActiveWemos", epochTime); - // Update status device saat startup Firebase.setString(firebaseData, "/logs/systemWemos", "Device Online"); } diff --git a/app/Console/Commands/FetchFirebaseData.php b/app/Console/Commands/FetchFirebaseData.php index e1cb508..f6f6343 100644 --- a/app/Console/Commands/FetchFirebaseData.php +++ b/app/Console/Commands/FetchFirebaseData.php @@ -43,59 +43,135 @@ public function handle() // Ambil data terakhir jika ada $lastEntry = !empty($historyData) ? end($historyData) : null; - // Cek apakah ada perubahan pada security, smartcab, control, atau logs + // Cek perubahan pada setiap kategori data + $securityChanged = false; + $smartcabChanged = false; + $controlChanged = false; + $logsChanged = false; + $dht11Changed = false; + $deviceChanged = false; $hasChanges = false; + if ($lastEntry === null) { - $hasChanges = true; + // Jika belum ada data, anggap semua kategori berubah (kecuali yang dikecualikan) + $securityChanged = !empty($securityData); + $smartcabChanged = !empty($smartcabData); + $controlChanged = !empty($controlData); + $logsChanged = !empty($logsData); + + // Untuk DHT11 dan Device, kita hanya anggap berubah jika ada data selain yang dikecualikan + $dht11Changed = !empty($dht11Data) && $this->hasNonTrivialDHT11Data($dht11Data); + $deviceChanged = !empty($deviceData) && $this->hasNonTrivialDeviceData($deviceData); + + $hasChanges = $securityChanged || $smartcabChanged || $controlChanged || + $logsChanged || $dht11Changed || $deviceChanged; } else { + // Cek perubahan pada setiap kategori $securityChanged = $this->hasDataChanged($lastEntry['security'] ?? [], $securityData); $smartcabChanged = $this->hasDataChanged($lastEntry['smartcab'] ?? [], $smartcabData); $controlChanged = $this->hasDataChanged($lastEntry['control'] ?? [], $controlData); $logsChanged = $this->hasDataChanged($lastEntry['logs'] ?? [], $logsData); - $hasChanges = $securityChanged || $smartcabChanged || $controlChanged || $logsChanged; + // Untuk dht11 dan device kita periksa secara khusus, mengabaikan field yang sering berubah + $dht11Changed = $this->hasNonTrivialDHT11Changes($lastEntry['dht11'] ?? [], $dht11Data); + $deviceChanged = $this->hasNonTrivialDeviceChanges($lastEntry['device'] ?? [], $deviceData); + + $hasChanges = $securityChanged || $smartcabChanged || $controlChanged || + $logsChanged || $dht11Changed || $deviceChanged; } - // Hanya simpan jika ada perubahan - if ($hasChanges) { - $newData = [ - 'id' => Str::uuid()->toString(), // Generate ID unik - 'timestamp' => now()->toIso8601String(), + // Proses setiap perubahan secara terpisah + $changesMade = false; + + // Buat template data lengkap + $fullData = [ 'security' => $securityData, 'smartcab' => $smartcabData, 'control' => $controlData, - 'logs' => $logsData - ]; - - if (!empty($dht11Data)) { - $newData['dht11'] = $dht11Data; - } + 'logs' => $logsData, + 'dht11' => $dht11Data, + 'device' => $deviceData + ]; + + // Simpan setiap perubahan secara terpisah dengan data lengkap + if ($securityChanged && !empty($securityData)) { + $newEntry = $fullData; + $newEntry['id'] = Str::uuid()->toString(); + $newEntry['timestamp'] = now()->toIso8601String(); + $newEntry['change_type'] = 'security'; // Tambahkan informasi apa yang berubah - if (!empty($deviceData)) { - $newData['device'] = $deviceData; - } - - $historyData[] = $newData; + $historyData[] = $newEntry; + event(new ReportUpdated($newEntry, 'security')); + $this->info('Perubahan terdeteksi pada security, ID: ' . $newEntry['id']); + $changesMade = true; + } + + if ($smartcabChanged && !empty($smartcabData)) { + $newEntry = $fullData; + $newEntry['id'] = Str::uuid()->toString(); + $newEntry['timestamp'] = now()->toIso8601String(); + $newEntry['change_type'] = 'smartcab'; + + $historyData[] = $newEntry; + event(new ReportUpdated($newEntry, 'smartcab')); + $this->info('Perubahan terdeteksi pada smartcab, ID: ' . $newEntry['id']); + $changesMade = true; + } + + if ($controlChanged && !empty($controlData)) { + $newEntry = $fullData; + $newEntry['id'] = Str::uuid()->toString(); + $newEntry['timestamp'] = now()->toIso8601String(); + $newEntry['change_type'] = 'control'; + + $historyData[] = $newEntry; + event(new ReportUpdated($newEntry, 'control')); + $this->info('Perubahan terdeteksi pada control, ID: ' . $newEntry['id']); + $changesMade = true; + } + + if ($logsChanged && !empty($logsData)) { + $newEntry = $fullData; + $newEntry['id'] = Str::uuid()->toString(); + $newEntry['timestamp'] = now()->toIso8601String(); + $newEntry['change_type'] = 'logs'; + + $historyData[] = $newEntry; + event(new ReportUpdated($newEntry, 'logs')); + $this->info('Perubahan terdeteksi pada logs, ID: ' . $newEntry['id']); + $changesMade = true; + } + + if ($dht11Changed && !empty($dht11Data)) { + $newEntry = $fullData; + $newEntry['id'] = Str::uuid()->toString(); + $newEntry['timestamp'] = now()->toIso8601String(); + $newEntry['change_type'] = 'dht11'; + + $historyData[] = $newEntry; + event(new ReportUpdated($newEntry, 'dht11')); + $this->info('Perubahan signifikan terdeteksi pada dht11, ID: ' . $newEntry['id']); + $changesMade = true; + } + + if ($deviceChanged && !empty($deviceData)) { + $newEntry = $fullData; + $newEntry['id'] = Str::uuid()->toString(); + $newEntry['timestamp'] = now()->toIso8601String(); + $newEntry['change_type'] = 'device'; + + $historyData[] = $newEntry; + event(new ReportUpdated($newEntry, 'device')); + $this->info('Perubahan signifikan terdeteksi pada device, ID: ' . $newEntry['id']); + $changesMade = true; + } + + // Jika ada perubahan yang disimpan, update file + if ($changesMade) { Storage::put('reports.json', json_encode($historyData, JSON_PRETTY_PRINT)); - $this->info('Data baru tersimpan dengan ID: ' . $newData['id']); - - // Broadcast event untuk realtime update - event(new ReportUpdated($newData)); - - if (isset($securityChanged) && $securityChanged) { - $this->info('Perubahan terdeteksi pada security'); - } - if (isset($smartcabChanged) && $smartcabChanged) { - $this->info('Perubahan terdeteksi pada smartcab'); - } - if (isset($controlChanged) && $controlChanged) { - $this->info('Perubahan terdeteksi pada control'); - } - if (isset($logsChanged) && $logsChanged) { - $this->info('Perubahan terdeteksi pada logs'); - } + $this->info('Semua perubahan berhasil disimpan.'); } else { - $this->info('Tidak ada perubahan pada data, data tidak disimpan'); + $this->info('Tidak ada perubahan signifikan pada data, data tidak disimpan'); } } catch (\Exception $e) { @@ -110,4 +186,96 @@ private function hasDataChanged($oldData, $newData) return $oldJson !== $newJson; } + + /** + * Memeriksa perubahan pada data dht11 selain humidity dan temperature + */ + private function hasNonTrivialDHT11Changes($oldData, $newData) + { + // Buat salinan data untuk perbandingan + $oldDataCompare = is_array($oldData) ? $oldData : []; + $newDataCompare = is_array($newData) ? $newData : []; + + // Hapus field yang sering berubah + if (isset($oldDataCompare['humidity'])) { + unset($oldDataCompare['humidity']); + } + if (isset($oldDataCompare['temperature'])) { + unset($oldDataCompare['temperature']); + } + if (isset($newDataCompare['humidity'])) { + unset($newDataCompare['humidity']); + } + if (isset($newDataCompare['temperature'])) { + unset($newDataCompare['temperature']); + } + + // Bandingkan data yang tersisa + return json_encode($oldDataCompare) !== json_encode($newDataCompare); + } + + /** + * Memeriksa apakah DHT11 data memiliki field selain yang dikecualikan + */ + private function hasNonTrivialDHT11Data($data) + { + $dataCopy = is_array($data) ? $data : []; + + // Hapus field yang sering berubah + if (isset($dataCopy['humidity'])) { + unset($dataCopy['humidity']); + } + if (isset($dataCopy['temperature'])) { + unset($dataCopy['temperature']); + } + + // Periksa apakah masih ada data lain + return !empty($dataCopy); + } + + /** + * Memeriksa perubahan pada data device selain lastActive dan lastActiveWemos + */ + private function hasNonTrivialDeviceChanges($oldData, $newData) + { + // Buat salinan data untuk perbandingan + $oldDataCompare = is_array($oldData) ? $oldData : []; + $newDataCompare = is_array($newData) ? $newData : []; + + // Hapus field yang sering berubah + if (isset($oldDataCompare['lastActive'])) { + unset($oldDataCompare['lastActive']); + } + if (isset($oldDataCompare['lastActiveWemos'])) { + unset($oldDataCompare['lastActiveWemos']); + } + if (isset($newDataCompare['lastActive'])) { + unset($newDataCompare['lastActive']); + } + if (isset($newDataCompare['lastActiveWemos'])) { + unset($newDataCompare['lastActiveWemos']); + } + + // Bandingkan data yang tersisa + return json_encode($oldDataCompare) !== json_encode($newDataCompare); + } + + /** + * Memeriksa apakah Device data memiliki field selain yang dikecualikan + */ + private function hasNonTrivialDeviceData($data) + { + $dataCopy = is_array($data) ? $data : []; + + // Hapus field yang sering berubah + if (isset($dataCopy['lastActive'])) { + unset($dataCopy['lastActive']); + } + if (isset($dataCopy['lastActiveWemos'])) { + unset($dataCopy['lastActiveWemos']); + } + + // Periksa apakah masih ada data lain + return !empty($dataCopy); + } } \ No newline at end of file diff --git a/app/Events/ReportUpdated.php b/app/Events/ReportUpdated.php index 964bf3f..00dec7b 100644 --- a/app/Events/ReportUpdated.php +++ b/app/Events/ReportUpdated.php @@ -15,15 +15,19 @@ class ReportUpdated implements ShouldBroadcast use Dispatchable, InteractsWithSockets, SerializesModels; public $report; + public $changeType; /** * Create a new event instance. * + * @param array $report Data report + * @param string|null $changeType Tipe perubahan (security, smartcab, dll) * @return void */ - public function __construct($report) + public function __construct($report, $changeType = null) { $this->report = $report; + $this->changeType = $changeType ?? ($report['change_type'] ?? null); } /** @@ -35,4 +39,18 @@ public function broadcastOn() { return new Channel('reports'); } + + /** + * Get the data to broadcast. + * + * @return array + */ + public function broadcastWith() + { + return [ + 'report' => $this->report, + 'change_type' => $this->changeType, + 'timestamp' => now()->toIso8601String() + ]; + } } \ No newline at end of file diff --git a/resources/views/reports.blade.php b/resources/views/reports.blade.php index f383c4d..28a2707 100644 --- a/resources/views/reports.blade.php +++ b/resources/views/reports.blade.php @@ -29,6 +29,27 @@ 50% { background-color: #d1ecf1; } 100% { background-color: #fff; } } + /* Styling untuk multiple select */ + select[multiple] { + max-height: 200px; + overflow-y: auto; + } + + select[multiple] optgroup { + font-weight: 600; + color: #374151; + padding: 0.25rem 0; + } + + select[multiple] option { + padding: 0.25rem 0.5rem; + margin: 0.125rem 0; + } + + select[multiple] option:checked { + background-color: #2563eb; + color: white; + } @@ -57,43 +78,59 @@ @@ -169,6 +206,38 @@ + +
+ + +
+