TKK_E32231446/lib/screens/home_screen.dart

507 lines
11 KiB
Dart

import 'package:flutter/material.dart';
import 'package:firebase_database/firebase_database.dart';
import 'setpoint_screen.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
final DatabaseReference dbRef =
FirebaseDatabase.instance.ref("hydroponic/monitoring");
final DatabaseReference controlRef =
FirebaseDatabase.instance.ref("hydroponic/control");
double ph = 0.0;
double ppm = 0.0;
int waterAir = 0;
int waterAbmix = 0;
int waterPHUp = 0;
int waterPHDown = 0;
bool relayAir = false;
bool relayNutrisi = false;
bool relayPhUp = false;
bool relayPhDown = false;
String statusPh = "-";
String statusTds = "-";
String wifiStatus = "-";
String mode = "AUTO";
@override
void initState() {
super.initState();
print("Firebase path: ${dbRef.path}");
dbRef.onValue.listen(
(event) {
print("===== FIREBASE EVENT =====");
print(event.snapshot.value);
if (event.snapshot.value == null) {
print("DATA NULL");
return;
}
try {
final data =
Map<dynamic, dynamic>.from(event.snapshot.value as Map);
setState(() {
ph = double.tryParse(data['ph'].toString()) ?? 0.0;
ppm = double.tryParse(data['ppm'].toString()) ?? 0.0;
waterAir = data['water_air'] ?? 0;
waterAbmix = data['water_abmix'] ?? 0;
waterPHUp = data['water_ph_up'] ?? 0;
waterPHDown = data['water_ph_down'] ?? 0;
relayAir = data['relay_air'] ?? false;
relayNutrisi = data['relay_nutrisi'] ?? false;
relayPhUp = data['relay_ph_up'] ?? false;
relayPhDown = data['relay_ph_down'] ?? false;
statusPh = data['status_ph']?.toString() ?? "-";
statusTds = data['status_tds']?.toString() ?? "-";
wifiStatus = data['wifi_status']?.toString() ?? "-";
});
print("PH = $ph");
print("PPM = $ppm");
print("STATUS PH = $statusPh");
print("STATUS TDS = $statusTds");
} catch (e) {
print("ERROR FIREBASE: $e");
}
},
onError: (error) {
print("FIREBASE ERROR:");
print(error);
},
);
controlRef.onValue.listen((event) {
if (event.snapshot.value == null) return;
try {
final data =
Map<dynamic, dynamic>.from(event.snapshot.value as Map);
setState(() {
mode = data['mode']?.toString() ?? "AUTO";
relayAir = data['relay_air'] ?? false;
relayNutrisi = data['relay_nutrisi'] ?? false;
relayPhUp = data['relay_ph_up'] ?? false;
relayPhDown = data['relay_ph_down'] ?? false;
});
print("MODE = $mode");
} catch (e) {
print("CONTROL ERROR: $e");
}
});
}
Widget sensorCard(
String title,
String value,
String status,
Color color,
) {
return Card(
elevation: 5,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
child: Padding(
padding: const EdgeInsets.all(16),
child: Row(
children: [
CircleAvatar(
radius: 35,
backgroundColor: color,
child: Text(
value,
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
),
const SizedBox(width: 15),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
const SizedBox(height: 5),
Text(
status,
style: TextStyle(
color: color,
fontWeight: FontWeight.bold,
),
),
],
),
),
],
),
),
);
}
Widget statusRow(
IconData icon,
String title,
bool status,
) {
return Card(
elevation: 3,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
),
child: ListTile(
leading: Icon(
icon,
color: status ? Colors.green : Colors.grey,
),
title: Text(
title,
style: const TextStyle(
fontWeight: FontWeight.w600,
),
),
trailing: Chip(
backgroundColor:
status ? Colors.green : Colors.red,
label: Text(
status ? "ON" : "OFF",
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
),
);
}
Widget manualButton(
String title,
String firebaseKey,
bool currentValue,
) {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15),
),
child: SwitchListTile(
title: Text(
title,
style: const TextStyle(
fontWeight: FontWeight.w600,
),
),
value: currentValue,
activeColor: Colors.green,
onChanged: (value) async {
await controlRef
.child(firebaseKey)
.set(value);
},
),
);
}
String getWaterLevelWarning() {
List<String> warningList = [];
if (waterAir < 1000) {
warningList.add("Tangki Air Bersih");
}
if (waterAbmix < 1000) {
warningList.add("Tangki AB Mix");
}
if (waterPHUp < 1000) {
warningList.add("Tangki pH Up");
}
if (waterPHDown < 1000) {
warningList.add("Tangki pH Down");
}
return warningList.join(", ");
}
@override
Widget build(BuildContext context) {
final phColor =
(ph >= 5.5 && ph <= 6.5) ? Colors.green : Colors.red;
final ppmColor =
(ppm >= 800 && ppm <= 1100) ? Colors.green : Colors.orange;
return Scaffold(
appBar: AppBar(
title: const Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.eco),
SizedBox(width: 8),
Text("Eco Green House"),
],
),
centerTitle: true,
backgroundColor: Colors.green,
actions: [
IconButton(
icon: const Icon(Icons.settings),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const SetpointScreen(),
),
);
},
),
],
),
body: ListView(
padding: const EdgeInsets.all(12),
children: [
if (
waterAir < 1000 ||
waterAbmix < 1000 ||
waterPHUp < 1000 ||
waterPHDown < 1000
)
Container(
margin: const EdgeInsets.only(bottom: 10),
padding: const EdgeInsets.all(15),
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(15),
),
child: Row(
children: [
const Icon(
Icons.warning,
color: Colors.white,
),
const SizedBox(width: 10),
Expanded(
child: Text(
"${getWaterLevelWarning()} rendah, segera isi tangki!",
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
],
),
),
Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.circular(20),
),
child: Column(
children: [
const Icon(
Icons.eco,
color: Colors.white,
size: 60,
),
const SizedBox(height: 10),
const Text(
"Eco Green House",
style: TextStyle(
color: Colors.white,
fontSize: 22,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 5),
Text(
"WiFi : $wifiStatus",
style: const TextStyle(
color: Colors.white,
),
),
],
),
),
const SizedBox(height: 15),
Row(
children: [
Expanded(
child: Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
const Icon(
Icons.science,
color: Colors.blue,
size: 35,
),
const SizedBox(height: 8),
const Text(
"pH",
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
Text(
ph.toStringAsFixed(2),
style: const TextStyle(
fontSize: 22,
fontWeight: FontWeight.bold,
),
),
],
),
),
),
),
Expanded(
child: Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
const Icon(
Icons.water_drop,
color: Colors.green,
size: 35,
),
const SizedBox(height: 8),
const Text(
"PPM",
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
Text(
ppm.toStringAsFixed(0),
style: const TextStyle(
fontSize: 22,
fontWeight: FontWeight.bold,
),
),
],
),
),
),
),
],
),
Card(
child: ListTile(
title: const Text("Mode Sistem"),
subtitle: Text("Status: $mode"),
trailing: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor:
mode == "AUTO" ? Colors.green : Colors.orange,
),
onPressed: () {
final newMode = mode == "AUTO" ? "MANUAL" : "AUTO";
controlRef.child("mode").set(newMode);
},
child: Text(
mode == "AUTO" ? "Switch MANUAL" : "Switch AUTO",
),
),
),
),
if (mode == "MANUAL") ...[
manualButton("Pompa Air", "relay_air", relayAir),
manualButton("Pompa Nutrisi", "relay_nutrisi", relayNutrisi),
manualButton("Pompa pH Up", "relay_ph_up", relayPhUp),
manualButton("Pompa pH Down", "relay_ph_down", relayPhDown),
const SizedBox(height: 10),
],
statusRow(
Icons.arrow_upward,
"Pompa pH Up",
relayPhUp,
),
statusRow(
Icons.arrow_downward,
"Pompa pH Down",
relayPhDown,
),
statusRow(
Icons.eco,
"Pompa Nutrisi",
relayNutrisi,
),
statusRow(
Icons.water_drop,
"Pompa Air",
relayAir,
),
Card(
child: ListTile(
leading: const Icon(Icons.wifi),
title: const Text("WiFi Status"),
trailing: Text(
wifiStatus,
style: TextStyle(
color: wifiStatus == "connected"
? Colors.green
: Colors.red,
fontWeight: FontWeight.bold,
),
),
),
),
],
),
);
}
}