TKK_E32211340/lib/mode_kontrol_page.dart

290 lines
11 KiB
Dart

import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_gauges/gauges.dart';
import 'mqtt_manager.dart';
class ModeKontrolPage extends StatefulWidget {
final String title;
const ModeKontrolPage({Key? key, required this.title}) : super(key: key);
@override
_ModeKontrolPageState createState() => _ModeKontrolPageState();
}
class _ModeKontrolPageState extends State<ModeKontrolPage> {
bool relaySwitch = false;
bool autoSwitch = false;
int parameterMinimal = 0;
int parameterMaximal = 0;
String _soil = '0'; // Nilai default untuk menghindari format exception
late MQTTManager _mqttManager;
@override
void initState() {
super.initState();
final clientId = 'flutter_client_${DateTime.now().millisecondsSinceEpoch}';
_mqttManager = MQTTManager(
serverUri: '192.168.43.27', // URI server
clientId: clientId, // ID Client unik
onDataReceived: _onDataReceived,
);
_mqttManager.connect();
}
void _onDataReceived(String soil, String humidity, String temperature,
String intensity, String batLevel) {
double adcValue = double.tryParse(soil) ?? 0;
double adcMin = 570;
double adcMax = 650;
// Hitung persentase kelembapan menggunakan rumus kalibrasi
double soilPercentage = ((adcMax - adcValue) / (adcMax - adcMin)) * 100;
// Pastikan nilai persentase dalam rentang 0-100%
if (soilPercentage < 0) soilPercentage = 0;
if (soilPercentage > 100) soilPercentage = 100;
setState(() {
_soil = soilPercentage.toStringAsFixed(2);
});
if (autoSwitch) {
if (soilPercentage < parameterMinimal) {
_publishSwitchStatus(true); // Nyalakan pompa
} else if (soilPercentage > parameterMaximal) {
_publishSwitchStatus(false); // Matikan pompa
}
}
}
void _publishSwitchStatus(bool status) {
String switchStatus = status ? 'On' : 'Off';
_mqttManager.publishMessage('home/switch/status', switchStatus);
setState(() {
relaySwitch = status;
});
}
@override
Widget build(BuildContext context) {
double soilValue = double.tryParse(_soil) ?? 0;
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () {
Navigator.pushReplacementNamed(context, '/home');
},
),
backgroundColor: Colors.brown,
title: Text(
widget.title,
style: TextStyle(
fontFamily: 'Quicksand',
fontWeight: FontWeight.bold,
),
),
),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(
child: Column(
children: [
const Text(
'Kelembaban Tanah',
style: TextStyle(
fontSize: 18,
),
),
const SizedBox(height: 10),
AnimatedSwitcher(
duration: Duration(milliseconds: 500),
child: SfRadialGauge(
key: ValueKey(soilValue),
axes: <RadialAxis>[
RadialAxis(
minimum: 0,
maximum: 100,
ranges: <GaugeRange>[
GaugeRange(
startValue: 0,
endValue: 30,
color: Colors.red),
GaugeRange(
startValue: 30,
endValue: 70,
color: Colors.orange),
GaugeRange(
startValue: 70,
endValue: 100,
color: Colors.green),
],
pointers: <GaugePointer>[
NeedlePointer(value: soilValue),
],
annotations: <GaugeAnnotation>[
GaugeAnnotation(
widget: Container(
child: Text(
'$_soil %',
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold),
),
),
angle: 90,
positionFactor: 0.5,
),
],
),
],
),
),
const SizedBox(height: 20),
],
),
),
const Divider(),
const SizedBox(height: 20),
Card(
elevation: 5,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const Text(
'Kontrol Manual',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Kontrol Pompa:'),
Switch(
value: relaySwitch,
onChanged:
!autoSwitch // Nonaktifkan kontrol manual saat kontrol otomatis aktif
? (bool value) {
setState(() {
relaySwitch = value;
});
_publishSwitchStatus(value);
}
: null,
),
],
),
],
),
),
),
const SizedBox(height: 20),
Card(
elevation: 5,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const Text(
'Kontrol Otomatis',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Kontrol Otomatis:'),
Switch(
value: autoSwitch,
onChanged: (bool value) {
setState(() {
autoSwitch = value;
if (autoSwitch) {
relaySwitch =
false; // Matikan kontrol manual saat kontrol otomatis aktif
_publishSwitchStatus(
false); // Pastikan pompa mati saat kontrol otomatis aktif
}
});
},
),
],
),
const SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text('Parameter Minimum:'),
Container(
width: 100,
child: TextFormField(
initialValue: parameterMinimal.toString(),
keyboardType: TextInputType.number,
decoration: InputDecoration(
border: OutlineInputBorder(),
),
onChanged: (value) {
setState(() {
parameterMinimal =
int.tryParse(value) ?? parameterMinimal;
});
},
),
),
],
),
const SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text('Parameter Maksimum:'),
Container(
width: 100,
child: TextFormField(
initialValue: parameterMaximal.toString(),
keyboardType: TextInputType.number,
decoration: InputDecoration(
border: OutlineInputBorder(),
),
onChanged: (value) {
setState(() {
parameterMaximal =
int.tryParse(value) ?? parameterMaximal;
});
},
),
),
],
),
],
),
),
),
],
),
),
),
);
}
}