TKK_E32230939/poultryrail/lib/main.dart

247 lines
4.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.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 'firebase_options.dart';
import 'dashboard.dart';
// 🔔 LOCAL NOTIFICATION
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
// 🔥 REALTIME DATABASE
final dbRef = FirebaseDatabase.instance.ref("sensor");
// 🔥 ANTI SPAM
bool notifHabisSudahMuncul = false;
bool notifKosongSudahMuncul = false;
bool notifFullSudahMuncul = false;
bool notifBerhasilSudahMuncul = false;
final statusRef = FirebaseDatabase.instance.ref("status");
int lastHeartbeat = 0;
DateTime lastHeartbeatTime = DateTime.now();
bool notifOfflineSudahMuncul = false;
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
FirebaseMessaging messaging = FirebaseMessaging.instance;
await messaging.requestPermission(
alert: true,
badge: true,
sound: true,
);
const AndroidInitializationSettings androidSettings =
AndroidInitializationSettings('@mipmap/ic_launcher');
const InitializationSettings settings =
InitializationSettings(
android: androidSettings,
);
await flutterLocalNotificationsPlugin.initialize(settings);
startRealtimeNotif();
monitorHeartbeat();
runApp(const MyApp());
}
// 🔥 MONITOR HEARTBEAT
void monitorHeartbeat() {
statusRef.child("heartbeat").onValue.listen((event) {
int heartbeat = 0;
if (event.snapshot.value != null) {
heartbeat = (event.snapshot.value as num).toInt();
}
if (heartbeat != lastHeartbeat) {
lastHeartbeat = heartbeat;
lastHeartbeatTime = DateTime.now();
notifOfflineSudahMuncul = false;
}
});
Stream.periodic(
const Duration(seconds: 1),
).listen((_) {
int selisih = DateTime.now()
.difference(lastHeartbeatTime)
.inSeconds;
if (selisih >= 5 &&
!notifOfflineSudahMuncul) {
notifOfflineSudahMuncul = true;
showNotif(
"⚠️ Perangkat Offline",
"Jaringan lemah atau perangkat tidak terhubung.",
);
}
});
}
// 🔥 REALTIME LISTENER
void startRealtimeNotif() {
dbRef.onValue.listen((event) {
final data = event.snapshot.value as Map?;
if (data != null) {
double jarak =
(data['jarak'] ?? 0).toDouble();
double berat1 =
(data['berat1'] ?? 0).toDouble();
double berat2 =
(data['berat2'] ?? 0).toDouble();
// 🔥 HITUNG PERSEN
double persen =
((12 - jarak) / 8) * 100;
if (persen < 0) persen = 0;
if (persen > 100) persen = 100;
// ================================
// 🔔 PAKAN FULL (100%)
// ================================
if (persen >= 100 &&
!notifFullSudahMuncul) {
notifFullSudahMuncul = true;
showNotif(
"Pakan Full",
"Wadah penampung pakan penuh.",
);
}
// RESET
if (persen < 100) {
notifFullSudahMuncul = false;
}
// ================================
// 🔔 PAKAN HAMPIR HABIS (25%)
// ================================
if (persen <= 25 &&
persen > 0 &&
!notifHabisSudahMuncul) {
notifHabisSudahMuncul = true;
showNotif(
"Pakan Hampir Habis",
"Segera isi ulang wadah penampung pakan.",
);
}
// RESET
if (persen > 25 || persen <= 0) {
notifHabisSudahMuncul = false;
}
// ================================
// 🔔 PAKAN HABIS (0%)
// ================================
if (persen <= 0 &&
!notifKosongSudahMuncul) {
notifKosongSudahMuncul = true;
showNotif(
"Pakan Habis",
"Wadah penampung pakan sudah kosong.",
);
}
// RESET
if (persen > 0) {
notifKosongSudahMuncul = false;
}
// ================================
// 🔔 PEMBERIAN PAKAN BERHASIL
// ================================
bool pakanBerhasil =
berat1 > 0 || berat2 > 0;
if (pakanBerhasil &&
!notifBerhasilSudahMuncul) {
notifBerhasilSudahMuncul = true;
showNotif(
"Pemberian Pakan Berhasil",
"Pakan berhasil diberikan ke wadah pakan.",
);
}
// RESET
if (!pakanBerhasil) {
notifBerhasilSudahMuncul = false;
}
}
});
}
// 🔔 FUNGSI TAMPILKAN NOTIFIKASI
Future<void> showNotif(
String title,
String body,
) async {
const AndroidNotificationDetails androidDetails =
AndroidNotificationDetails(
'pakan_channel',
'Notifikasi Pakan',
importance: Importance.max,
priority: Priority.high,
);
const NotificationDetails details =
NotificationDetails(
android: androidDetails,
);
await flutterLocalNotificationsPlugin.show(
0,
title,
body,
details,
);
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Dashboard(),
);
}
}