495 lines
13 KiB
Dart
495 lines
13 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:carousel_slider/carousel_slider.dart';
|
|
import 'package:dots_indicator/dots_indicator.dart';
|
|
import 'package:intl/intl.dart';
|
|
import 'package:firebase_core/firebase_core.dart';
|
|
import 'package:firebase_database/firebase_database.dart';
|
|
|
|
class AmoniaPage extends StatefulWidget {
|
|
const AmoniaPage({Key? key}) : super(key: key);
|
|
|
|
@override
|
|
State<AmoniaPage> createState() => _AmoniaPageState();
|
|
}
|
|
|
|
class _AmoniaPageState extends State<AmoniaPage> {
|
|
double amoniaLevel = 0.0;
|
|
double temperature = 0.0;
|
|
double humidity = 0.0;
|
|
bool prebioticSprayer = false;
|
|
bool waterSprayer = false;
|
|
int currentIndex = 0;
|
|
String currentDate = "";
|
|
|
|
CarouselController _carouselController = CarouselController();
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_updateDate();
|
|
_setupFirebaseListeners();
|
|
}
|
|
|
|
void _updateDate() {
|
|
final now = DateTime.now();
|
|
final formattedDate = DateFormat('EEEE, d MMMM yyyy', 'id_ID').format(now);
|
|
setState(() {
|
|
currentDate = formattedDate;
|
|
});
|
|
}
|
|
|
|
void _setupFirebaseListeners() {
|
|
DatabaseReference amoniaRef =
|
|
FirebaseDatabase.instance.reference().child('kandang').child('amonia');
|
|
DatabaseReference tempRef =
|
|
FirebaseDatabase.instance.reference().child('kandang').child('suhu');
|
|
DatabaseReference humidityRef = FirebaseDatabase.instance
|
|
.reference()
|
|
.child('kandang')
|
|
.child('kelembaban');
|
|
DatabaseReference prebioticSprayerRef =
|
|
FirebaseDatabase.instance.reference().child('kandang').child('sprayer');
|
|
DatabaseReference waterSprayerRef = FirebaseDatabase.instance
|
|
.reference()
|
|
.child('kandang')
|
|
.child('sprayer2');
|
|
|
|
amoniaRef.onValue.listen((event) {
|
|
if (event.snapshot.value != null) {
|
|
setState(() {
|
|
amoniaLevel = double.parse(event.snapshot.value.toString());
|
|
});
|
|
}
|
|
});
|
|
|
|
tempRef.onValue.listen((event) {
|
|
if (event.snapshot.value != null) {
|
|
setState(() {
|
|
temperature = double.parse(event.snapshot.value.toString());
|
|
});
|
|
}
|
|
});
|
|
|
|
humidityRef.onValue.listen((event) {
|
|
if (event.snapshot.value != null) {
|
|
setState(() {
|
|
humidity = double.parse(event.snapshot.value.toString());
|
|
});
|
|
}
|
|
});
|
|
|
|
prebioticSprayerRef.onValue.listen((event) {
|
|
if (event.snapshot.value != null) {
|
|
setState(() {
|
|
prebioticSprayer = event.snapshot.value.toString() == 'true';
|
|
});
|
|
}
|
|
});
|
|
|
|
waterSprayerRef.onValue.listen((event) {
|
|
if (event.snapshot.value != null) {
|
|
setState(() {
|
|
waterSprayer = event.snapshot.value.toString() == 'true';
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final List<Widget> slides = [
|
|
Container(
|
|
margin: EdgeInsets.only(top: 10.0),
|
|
child: Center(
|
|
child: CircularIndicator(
|
|
value: amoniaLevel,
|
|
label: 'Amonia',
|
|
unit: 'Ppm',
|
|
max: 1000,
|
|
),
|
|
),
|
|
),
|
|
Container(
|
|
margin: EdgeInsets.only(top: 10.0),
|
|
child: Center(
|
|
child: CircularIndicator(
|
|
value: temperature,
|
|
label: 'Suhu',
|
|
unit: 'C',
|
|
max: 100,
|
|
),
|
|
),
|
|
),
|
|
Container(
|
|
margin: EdgeInsets.only(top: 10.0),
|
|
child: Center(
|
|
child: CircularIndicator(
|
|
value: humidity,
|
|
label: 'Kelembaban',
|
|
unit: '%',
|
|
max: 100,
|
|
),
|
|
),
|
|
),
|
|
];
|
|
|
|
return Scaffold(
|
|
body: ListView(
|
|
children: [
|
|
Padding(
|
|
padding: const EdgeInsets.only(left: 30, right: 30, top: 20),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
"Hari ini",
|
|
style: TextStyle(
|
|
fontSize: 25,
|
|
fontWeight: FontWeight.w700,
|
|
),
|
|
),
|
|
Text(
|
|
currentDate,
|
|
style: TextStyle(
|
|
fontSize: 20,
|
|
fontWeight: FontWeight.w500,
|
|
),
|
|
),
|
|
SizedBox(height: 20),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
SprayerStatus(
|
|
isActive: prebioticSprayer,
|
|
label: "Prebiotik Sprayer",
|
|
activeColor: Colors.lightBlue,
|
|
inactiveColor: Colors.grey,
|
|
activeText: "Prebiotik Sprayer On",
|
|
inactiveText: "Prebiotik Sprayer Off",
|
|
iconSize: 18,
|
|
textSize: 12,
|
|
),
|
|
SprayerStatus(
|
|
isActive: waterSprayer,
|
|
label: "Water Sprayer",
|
|
activeColor: Colors.lightBlue,
|
|
inactiveColor: Colors.grey,
|
|
activeText: "Water Sprayer On",
|
|
inactiveText: "Water Sprayer Off",
|
|
iconSize: 18,
|
|
textSize: 12,
|
|
),
|
|
],
|
|
),
|
|
SizedBox(height: 20),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
IconButton(
|
|
icon: Icon(Icons.arrow_back),
|
|
onPressed: () {
|
|
if (currentIndex > 0) {
|
|
_carouselController.previousPage();
|
|
}
|
|
},
|
|
),
|
|
Expanded(
|
|
child: CarouselSlider(
|
|
items: slides,
|
|
carouselController: _carouselController,
|
|
options: CarouselOptions(
|
|
viewportFraction: 1,
|
|
aspectRatio: 3 / 4,
|
|
onPageChanged: (index, reason) {
|
|
setState(() {
|
|
currentIndex = index;
|
|
});
|
|
},
|
|
),
|
|
),
|
|
),
|
|
IconButton(
|
|
icon: Icon(Icons.arrow_forward),
|
|
onPressed: () {
|
|
if (currentIndex < slides.length - 1) {
|
|
_carouselController.nextPage();
|
|
}
|
|
},
|
|
),
|
|
],
|
|
),
|
|
SizedBox(height: 10),
|
|
Center(
|
|
child: DotsIndicator(
|
|
dotsCount: slides.length,
|
|
position: currentIndex.toDouble(),
|
|
decorator: DotsDecorator(
|
|
activeColor: Colors.amber,
|
|
),
|
|
),
|
|
),
|
|
SizedBox(height: 20),
|
|
Padding(
|
|
padding: const EdgeInsets.only(top: 10),
|
|
child: Column(
|
|
children: [
|
|
InfoCard(
|
|
label: 'Kadar Amonia',
|
|
value: '$amoniaLevel Ppm',
|
|
status: _getAmoniaStatus(),
|
|
color: Colors.purple.shade200,
|
|
),
|
|
SizedBox(height: 10),
|
|
InfoCard(
|
|
label: 'Suhu',
|
|
value: '$temperature C',
|
|
status: _getTemperatureStatus(),
|
|
color: _getTemperatureColor(),
|
|
),
|
|
SizedBox(height: 10),
|
|
InfoCard(
|
|
label: 'Kelembaban',
|
|
value: '$humidity %',
|
|
status: _getHumidityStatus(),
|
|
color: _getHumidityColor(),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
SizedBox(height: 20),
|
|
Center(
|
|
child: Text(
|
|
"Copyright @2023 Team Dev MBKM All Right Reserved",
|
|
style: TextStyle(fontSize: 11),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
String _getAmoniaStatus() {
|
|
if (amoniaLevel > 500) {
|
|
return 'Amonia Tinggi! Perlu tindakan segera.';
|
|
} else if (amoniaLevel >= 400) {
|
|
return 'Amonia Sedang, Waspada.';
|
|
} else {
|
|
return 'Kadar Amonia Normal';
|
|
}
|
|
}
|
|
|
|
String _getTemperatureStatus() {
|
|
if (temperature > 34) {
|
|
return 'Suhu Terlalu Panas!';
|
|
} else if (temperature < 20) {
|
|
return 'Suhu Terlalu Dingin!';
|
|
} else {
|
|
return 'Suhu Optimal';
|
|
}
|
|
}
|
|
|
|
Color _getTemperatureColor() {
|
|
if (temperature > 34) {
|
|
return Colors.orange;
|
|
} else if (temperature < 20) {
|
|
return Colors.blue;
|
|
} else {
|
|
return Colors.green;
|
|
}
|
|
}
|
|
|
|
String _getHumidityStatus() {
|
|
if (humidity > 70) {
|
|
return 'Kelembaban Terlalu Tinggi!';
|
|
} else if (humidity < 21) {
|
|
return 'Kelembaban Terlalu Rendah!';
|
|
} else {
|
|
return 'Kelembaban Optimal';
|
|
}
|
|
}
|
|
|
|
Color _getHumidityColor() {
|
|
if (humidity > 70) {
|
|
return Colors.blue;
|
|
} else if (humidity < 21) {
|
|
return Colors.brown;
|
|
} else {
|
|
return Colors.green;
|
|
}
|
|
}
|
|
}
|
|
|
|
class CircularIndicator extends StatelessWidget {
|
|
final double value;
|
|
final String label;
|
|
final String unit;
|
|
final double max;
|
|
|
|
CircularIndicator({
|
|
required this.value,
|
|
required this.label,
|
|
required this.unit,
|
|
required this.max,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
Color indicatorColor;
|
|
|
|
if (label == 'Suhu') {
|
|
indicatorColor = _getTemperatureIndicatorColor(value);
|
|
} else if (label == 'Kelembaban') {
|
|
indicatorColor = _getHumidityIndicatorColor(value);
|
|
} else {
|
|
indicatorColor = Colors.purple;
|
|
}
|
|
|
|
return Column(
|
|
children: [
|
|
Text(
|
|
label,
|
|
style: TextStyle(
|
|
fontSize: 20,
|
|
fontWeight: FontWeight.w700,
|
|
),
|
|
),
|
|
SizedBox(height: 10),
|
|
Stack(
|
|
alignment: Alignment.center,
|
|
children: [
|
|
SizedBox(
|
|
width: 200,
|
|
height: 200,
|
|
child: CircularProgressIndicator(
|
|
value: value / max,
|
|
strokeWidth: 15,
|
|
backgroundColor: Colors.grey.shade300,
|
|
valueColor: AlwaysStoppedAnimation(indicatorColor),
|
|
),
|
|
),
|
|
Text(
|
|
'$value $unit',
|
|
style: TextStyle(
|
|
fontSize: 24,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
Color _getTemperatureIndicatorColor(double temperature) {
|
|
if (temperature > 34) {
|
|
return Colors.orange;
|
|
} else if (temperature < 20) {
|
|
return Colors.blue;
|
|
} else {
|
|
return Colors.green;
|
|
}
|
|
}
|
|
|
|
Color _getHumidityIndicatorColor(double humidity) {
|
|
if (humidity > 70) {
|
|
return Colors.blue;
|
|
} else if (humidity < 21) {
|
|
return Colors.brown;
|
|
} else {
|
|
return Colors.green;
|
|
}
|
|
}
|
|
}
|
|
|
|
class InfoCard extends StatelessWidget {
|
|
final String label;
|
|
final String value;
|
|
final String status;
|
|
final Color color;
|
|
|
|
InfoCard({
|
|
required this.label,
|
|
required this.value,
|
|
required this.status,
|
|
required this.color,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Container(
|
|
margin: EdgeInsets.only(top: 10, bottom: 5, left: 8, right: 8),
|
|
padding: EdgeInsets.all(10),
|
|
width: MediaQuery.of(context).size.width,
|
|
decoration: BoxDecoration(
|
|
color: color,
|
|
borderRadius: BorderRadius.circular(5),
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
'$label : $value',
|
|
style: TextStyle(
|
|
height: 1.5,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
Divider(),
|
|
Text(
|
|
status,
|
|
style: TextStyle(
|
|
fontSize: 15,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class SprayerStatus extends StatelessWidget {
|
|
final bool isActive;
|
|
final String label;
|
|
final Color activeColor;
|
|
final Color inactiveColor;
|
|
final String activeText;
|
|
final String inactiveText;
|
|
final double iconSize;
|
|
final double textSize;
|
|
|
|
SprayerStatus({
|
|
required this.isActive,
|
|
required this.label,
|
|
required this.activeColor,
|
|
required this.inactiveColor,
|
|
required this.activeText,
|
|
required this.inactiveText,
|
|
this.iconSize = 24.0,
|
|
this.textSize = 18.0,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Column(
|
|
children: [
|
|
Icon(
|
|
Icons.water_drop,
|
|
color: isActive ? activeColor : inactiveColor,
|
|
size: iconSize,
|
|
),
|
|
Text(
|
|
isActive ? activeText : inactiveText,
|
|
style: TextStyle(
|
|
fontSize: textSize,
|
|
fontWeight: FontWeight.bold,
|
|
color: isActive ? activeColor : inactiveColor,
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|