MIF_E31221269/lib/services/notification_service.dart

423 lines
16 KiB
Dart

//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<StreamSubscription> _subscriptions = [];
// Flag untuk mencegah duplikasi notifikasi dalam waktu singkat
final Map<String, DateTime> _lastNotificationTimes = {};
// Flag untuk menandai apakah service sudah diinisialisasi
bool _isInitialized = false;
NotificationService._internal();
Future<void> 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<void> _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<void> _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<dynamic, dynamic> 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<dynamic, dynamic> 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<dynamic, dynamic> 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<dynamic, dynamic> 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");
});
}
}