//import 'package:flutter/material.dart'; import 'package:firebase_database/firebase_database.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:jago/services/db_helper.dart'; import 'dart:async'; class NotificationService { static final NotificationService _instance = NotificationService._internal(); factory NotificationService() => _instance; final DatabaseReference _database = FirebaseDatabase.instance.ref(); final DatabaseHelper dbHelper = DatabaseHelper(); int ageInWeeks = 2; // Inisialisasi notifikasi lokal final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); // Daftar subscription untuk dibersihkan saat dispose final List _subscriptions = []; // Flag untuk mencegah duplikasi notifikasi dalam waktu singkat final Map _lastNotificationTimes = {}; // Flag untuk menandai apakah service sudah diinisialisasi bool _isInitialized = false; NotificationService._internal(); Future initialize() async { if (_isInitialized) return; print("🚀 Menginisialisasi NotificationService..."); // Inisialisasi database await dbHelper.checkTables(); // Inisialisasi notifikasi lokal const AndroidInitializationSettings initializationSettingsAndroid = AndroidInitializationSettings('@mipmap/ic_launcher'); final InitializationSettings initializationSettings = InitializationSettings(android: initializationSettingsAndroid); await flutterLocalNotificationsPlugin.initialize(initializationSettings); // Setup Firebase Messaging FirebaseMessaging.onMessage.listen((RemoteMessage message) { _showNotification(message.notification?.title ?? 'Notifikasi', message.notification?.body ?? ''); }); FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler); // Ambil umur ayam dari Firebase _fetchAgeFromFirebase(); // Mulai memantau data _startMonitoring(); _isInitialized = true; print("✅ NotificationService berhasil diinisialisasi"); } void dispose() { for (var subscription in _subscriptions) { subscription.cancel(); } _subscriptions.clear(); _isInitialized = false; print("🛑 NotificationService dihentikan"); } static Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async { print("📱 Menerima pesan di background: ${message.notification?.title}"); await NotificationService().initialize(); NotificationService()._showNotification( message.notification?.title ?? 'Notifikasi', message.notification?.body ?? '' ); } Future _showNotification(String title, String body) async { const AndroidNotificationDetails androidPlatformChannelSpecifics = AndroidNotificationDetails( 'Jago', 'Notification', channelDescription: 'Cek Notification!!!', importance: Importance.max, priority: Priority.high, ); const NotificationDetails platformChannelSpecifics = NotificationDetails(android: androidPlatformChannelSpecifics); await flutterLocalNotificationsPlugin.show( 0, title, body, platformChannelSpecifics, ); } void _fetchAgeFromFirebase() { print("🐔 Memuat umur ayam dari Firebase..."); final subscription = _database.child("chicken_age").onValue.listen((event) { final data = event.snapshot.value; if (data != null) { ageInWeeks = int.parse(data.toString()); print("🐔 Umur ayam diperbarui: $ageInWeeks minggu"); } }); _subscriptions.add(subscription); } void _startMonitoring() { print("👀 Mulai memantau data dari Firebase..."); // Pastikan umur ayam diambil terlebih dahulu _fetchAgeFromFirebase(); // Delay sedikit untuk memastikan umur ayam sudah diambil Future.delayed(Duration(milliseconds: 500), () { _loadEmergencyData(); _loadFuzzyData(); _loadStatusData(); _loadSensorData(); }); } // Memuat data emergency dari Firebase void _loadEmergencyData() { try { print("🔄 Memuat data emergency..."); final subscription = _database.child('emergency').onValue.listen((event) { if (event.snapshot.value != null) { try { print("🔥 Data emergency diterima: ${event.snapshot.value}"); final Map emergencyData = event.snapshot.value as Map; if (emergencyData['low_temperature'] == true) { print("🔥 Kondisi emergency: Suhu sangat rendah terdeteksi"); _addNotification('Suhu sangat rendah! Kondisi darurat terdeteksi.'); } if (emergencyData['high_temperature'] == true) { print("🔥 Kondisi emergency: Suhu sangat tinggi terdeteksi"); _addNotification('Suhu sangat tinggi! Kondisi darurat terdeteksi.'); } if (emergencyData['low_humidity'] == true) { print("🔥 Kondisi emergency: Kelembapan sangat rendah terdeteksi"); _addNotification('Kelembapan sangat rendah! Kondisi darurat terdeteksi.'); } if (emergencyData['high_humidity'] == true) { print("🔥 Kondisi emergency: Kelembapan sangat tinggi terdeteksi"); _addNotification('Kelembapan sangat tinggi! Kondisi darurat terdeteksi.'); } } catch (e) { print("❌ Error saat memproses data emergency: $e"); } } }); _subscriptions.add(subscription); // Juga dengarkan perubahan pada node emergency final changeSubscription = _database.child('emergency').onChildChanged.listen((event) { if (event.snapshot.value == true) { String type = event.snapshot.key ?? "unknown"; String message = ""; print("🔥 Perubahan emergency terdeteksi: ${event.snapshot.key} = ${event.snapshot.value}"); if (type == "low_temperature") { message = "Suhu sangat rendah! Kondisi darurat terdeteksi."; } else if (type == "high_temperature") { message = "Suhu sangat tinggi! Kondisi darurat terdeteksi."; } else if (type == "low_humidity") { message = "Kelembapan sangat rendah! Kondisi darurat terdeteksi."; } else if (type == "high_humidity") { message = "Kelembapan sangat tinggi! Kondisi darurat terdeteksi."; } if (message.isNotEmpty) { _addNotification(message); } } }); _subscriptions.add(changeSubscription); } catch (e) { print("❌ Error saat setup listener emergency: $e"); } } // Memuat data fuzzy dari Firebase void _loadFuzzyData() { try { print("🔄 Memuat data fuzzy..."); // Memuat data fuzzy suhu final tempSubscription = _database.child('fuzzy/temperature').onValue.listen((event) { if (event.snapshot.value != null) { try { print("🧠 Data fuzzy temperature diterima: ${event.snapshot.value}"); final Map fuzzyTemp = event.snapshot.value as Map; if (fuzzyTemp.containsKey('veryHigh') && (fuzzyTemp['veryHigh'] as num).toDouble() > 0.7) { double value = (fuzzyTemp['veryHigh'] as num).toDouble(); print("🧠 Fuzzy suhu sangat tinggi terdeteksi: $value"); _addNotification('Fuzzy: Suhu sangat tinggi (${value.toStringAsFixed(2)})'); } if (fuzzyTemp.containsKey('veryLow') && (fuzzyTemp['veryLow'] as num).toDouble() > 0.7) { double value = (fuzzyTemp['veryLow'] as num).toDouble(); print("🧠 Fuzzy suhu sangat rendah terdeteksi: $value"); _addNotification('Fuzzy: Suhu sangat rendah (${value.toStringAsFixed(2)})'); } } catch (e) { print("❌ Error saat memproses data fuzzy temperature: $e"); } } }); _subscriptions.add(tempSubscription); // Memuat data fuzzy kelembapan final humSubscription = _database.child('fuzzy/humidity').onValue.listen((event) { if (event.snapshot.value != null) { try { print("🧠 Data fuzzy humidity diterima: ${event.snapshot.value}"); final Map fuzzyHum = event.snapshot.value as Map; if (fuzzyHum.containsKey('veryHigh') && (fuzzyHum['veryHigh'] as num).toDouble() > 0.7) { double value = (fuzzyHum['veryHigh'] as num).toDouble(); print("🧠 Fuzzy kelembapan sangat tinggi terdeteksi: $value"); _addNotification('Fuzzy: Kelembapan sangat tinggi (${value.toStringAsFixed(2)})'); } if (fuzzyHum.containsKey('veryLow') && (fuzzyHum['veryLow'] as num).toDouble() > 0.7) { double value = (fuzzyHum['veryLow'] as num).toDouble(); print("🧠 Fuzzy kelembapan sangat rendah terdeteksi: $value"); _addNotification('Fuzzy: Kelembapan sangat rendah (${value.toStringAsFixed(2)})'); } } catch (e) { print("❌ Error saat memproses data fuzzy humidity: $e"); } } }); _subscriptions.add(humSubscription); } catch (e) { print("❌ Error saat setup listener fuzzy: $e"); } } // Memuat data status dari Firebase void _loadStatusData() { try { print("🔄 Memuat data status..."); // Memuat status suhu final tempSubscription = _database.child('status/temperature').onValue.listen((event) { if (event.snapshot.value != null) { try { String tempStatus = event.snapshot.value.toString(); print("📊 Status suhu diterima: $tempStatus"); if (tempStatus.contains("Sangat Tinggi") || tempStatus.contains("Sangat Rendah")) { print("📊 Status suhu kritis terdeteksi: $tempStatus"); _addNotification('Status: $tempStatus'); } } catch (e) { print("❌ Error saat memproses data status temperature: $e"); } } }); _subscriptions.add(tempSubscription); // Memuat status kelembapan final humSubscription = _database.child('status/humidity').onValue.listen((event) { if (event.snapshot.value != null) { try { String humStatus = event.snapshot.value.toString(); print("📊 Status kelembapan diterima: $humStatus"); if (humStatus.contains("Sangat Tinggi") || humStatus.contains("Sangat Rendah")) { print("📊 Status kelembapan kritis terdeteksi: $humStatus"); _addNotification('Status: $humStatus'); } } catch (e) { print("❌ Error saat memproses data status humidity: $e"); } } }); _subscriptions.add(humSubscription); // Mendengarkan perubahan pada node status final statusSubscription = _database.child('status').onChildChanged.listen((event) { String status = event.snapshot.value.toString(); String type = event.snapshot.key ?? "unknown"; print("📊 Perubahan status terdeteksi: $type = $status"); if (status.contains("Sangat Tinggi") || status.contains("Sangat Rendah")) { print("📊 Status kritis pada perubahan terdeteksi: $type = $status"); _addNotification('Status $type: $status'); } }); _subscriptions.add(statusSubscription); } catch (e) { print("❌ Error saat setup listener status: $e"); } } void _loadSensorData() { print("🔄 Memuat data sensor..."); final subscription = _database.child('sensor').onValue.listen((event) { if (event.snapshot.value != null) { try { final Map sensorData = event.snapshot.value as Map; double temperature = (sensorData['temperature'] as num).toDouble(); double humidity = (sensorData['Humidity'] as num).toDouble(); print("🌡️ Data sensor diterima: Suhu=$temperature°C, Kelembapan=$humidity%"); // Tentukan rentang suhu berdasarkan umur ayam double tempMin, tempMax, humMin, humMax; switch (ageInWeeks) { case 1: tempMin = 33.0; tempMax = 35.0; humMin = 60.0; humMax = 70.0; break; case 2: tempMin = 30.0; tempMax = 33.0; humMin = 60.0; humMax = 65.0; break; case 3: tempMin = 28.0; tempMax = 30.0; humMin = 60.0; humMax = 65.0; break; case 4: tempMin = 25.0; tempMax = 28.0; humMin = 55.0; humMax = 60.0; break; default: tempMin = 25.0; tempMax = 28.0; humMin = 55.0; humMax = 60.0; } // Buat notifikasi berdasarkan kondisi suhu if (temperature < tempMin - 2) { print("🌡️ Suhu sangat rendah terdeteksi: $temperature°C"); _addNotification('Suhu sangat rendah: $temperature°C (Kritis)'); } else if (temperature < tempMin) { print("🌡️ Suhu rendah terdeteksi: $temperature°C"); _addNotification('Suhu rendah: $temperature°C'); } else if (temperature > tempMax + 2) { print("🌡️ Suhu sangat tinggi terdeteksi: $temperature°C"); _addNotification('Suhu sangat tinggi: $temperature°C (Kritis)'); } else if (temperature > tempMax) { print("🌡️ Suhu tinggi terdeteksi: $temperature°C"); _addNotification('Suhu tinggi: $temperature°C'); } else if (temperature >= tempMin && temperature <= tempMax) { print("🌡️ Suhu normal terdeteksi: $temperature°C"); _addNotification('Suhu normal: $temperature°C (Optimal)'); } // Buat notifikasi berdasarkan kondisi kelembapan if (humidity < humMin - 5) { print("💧 Kelembapan sangat rendah terdeteksi: $humidity%"); _addNotification('Kelembapan sangat rendah: $humidity% (Kritis)'); } else if (humidity < humMin) { print("💧 Kelembapan rendah terdeteksi: $humidity%"); _addNotification('Kelembapan rendah: $humidity%'); } else if (humidity > humMax + 5) { print("💧 Kelembapan sangat tinggi terdeteksi: $humidity%"); _addNotification('Kelembapan sangat tinggi: $humidity% (Kritis)'); } else if (humidity > humMax) { print("💧 Kelembapan tinggi terdeteksi: $humidity%"); _addNotification('Kelembapan tinggi: $humidity%'); } else if (humidity >= humMin && humidity <= humMax) { print("💧 Kelembapan normal terdeteksi: $humidity%"); _addNotification('Kelembapan normal: $humidity% (Optimal)'); } } catch (e) { print("❌ Error saat memproses data sensor: $e"); } } }); _subscriptions.add(subscription); } // Fungsi untuk menambahkan notifikasi baru void _addNotification(String event) { print("🔍 Mencoba menambahkan notifikasi: $event"); // Cek apakah notifikasi serupa sudah ditambahkan dalam 5 menit terakhir if (_lastNotificationTimes.containsKey(event)) { DateTime lastTime = _lastNotificationTimes[event]!; Duration difference = DateTime.now().difference(lastTime); // Jika notifikasi serupa sudah ditambahkan dalam 5 menit terakhir, abaikan if (difference.inMinutes < 5) { print("⏱️ Notifikasi serupa sudah ditambahkan ${difference.inSeconds} detik yang lalu, diabaikan: $event"); return; } } // Catat waktu notifikasi ini ditambahkan _lastNotificationTimes[event] = DateTime.now(); // Tambahkan informasi umur ayam ke event String eventWithAge = "$event [Umur: $ageInWeeks minggu]"; // Simpan ke database lokal dbHelper.insertNotification(eventWithAge).then((_) { print("✅ Berhasil menyimpan notifikasi: $eventWithAge"); // Tampilkan notifikasi lokal _showNotification('Peringatan Kandang Ayam', event); }).catchError((error) { print("❌ Gagal menyimpan notifikasi: $error"); }); } }