import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; import 'dart:async'; import 'package:google_fonts/google_fonts.dart'; import 'package:inkubator/login.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:inkubator/theme.dart'; class HomeView extends StatefulWidget { final String espIpAddress; HomeView({required this.espIpAddress}); @override _HomeViewState createState() => _HomeViewState(); } class _HomeViewState extends State { final TextEditingController _dayController = TextEditingController(); String _response = ''; double temperature = 0.0; double humidity = 0.0; int _day = 0; int _sec = 0; Timer? _timer; Timer? _dataTimer; @override void initState() { super.initState(); _fetchCurrentTime(); _fetchSensorData(); _startTimer(); } @override void dispose() { _timer?.cancel(); _dataTimer?.cancel(); super.dispose(); } void _startTimer() { _timer = Timer.periodic(Duration(seconds: 1), (timer) { setState(() { _sec++; if (_sec >= 3600) { _fetchCurrentTime(); _fetchSensorData(); } }); }); _dataTimer = Timer.periodic(Duration(seconds: 2), (timer) { _fetchSensorData(); }); } Future _fetchCurrentTime() async { try { final response = await http.get(Uri.parse('http://${widget.espIpAddress}/')); if (response.statusCode == 200) { final data = json.decode(response.body); setState(() { _day = data['day']; _sec = data['hours'] * 3600 + data['minutes'] * 60 + data['seconds']; }); } else { setState(() { _response = 'Failed to connect: ${response.statusCode}'; }); } } catch (e) { setState(() { _response = 'Error: $e'; }); } } Future _fetchSensorData() async { try { final response = await http.get(Uri.parse('http://${widget.espIpAddress}/dht')); if (response.statusCode == 200) { final data = json.decode(response.body); setState(() { temperature = data['temperature']; humidity = data['humidity']; }); } else { setState(() { _response = 'Failed to connect: ${response.statusCode}'; }); } } catch (e) { setState(() { _response = 'Error: $e'; }); } } Future _sendTimeToESP() async { final url = 'http://${widget.espIpAddress}/'; Map data = { 'day': int.parse(_dayController.text), }; try { final response = await http.post( Uri.parse(url), headers: {"Content-Type": "application/json"}, body: json.encode(data), ); if (response.statusCode == 200) { _fetchCurrentTime(); Navigator.of(context).pop(); // Close the dialog on success } else { setState(() { _response = 'Failed to connect: ${response.statusCode}'; }); } } catch (e) { setState(() { _response = 'Error: $e'; }); } } Future _powerOn() async { final response = await http.post( Uri.parse('http://${widget.espIpAddress}/inkubator'), headers: {"Content-Type": "application/json"}, body: '{"inkubator": "on"}', ); if (response.statusCode == 200) { print('Power On'); _showSnackbar('Power On Successful'); } else { print('Failed to Power On'); _showSnackbar('Failed to Power On'); } } Future _powerOff() async { final response = await http.post( Uri.parse('http://${widget.espIpAddress}/inkubator'), headers: {"Content-Type": "application/json"}, body: '{"inkubator": "off"}', ); if (response.statusCode == 200) { print('Power Off'); _showSnackbar('Power Off Successful'); } else { print('Failed to Power Off'); _showSnackbar('Power Off Successful'); } } void _showSnackbar(String message) { final snackBar = SnackBar( content: Text(message), duration: Duration(seconds: 2), ); ScaffoldMessenger.of(context).showSnackBar(snackBar); } Future _showDayInputDialog() async { return showDialog( context: context, barrierDismissible: false, // user must tap button! builder: (BuildContext context) { return AlertDialog( title: Text('Set Elapsed Day'), content: TextField( controller: _dayController, keyboardType: TextInputType.number, decoration: InputDecoration(hintText: "Enter new elapsed day"), ), actions: [ TextButton( child: Text('Cancel'), onPressed: () { Navigator.of(context).pop(); }, ), TextButton( child: Text('Set'), onPressed: _sendTimeToESP, ), ], ); }, ); } void _logout() async { SharedPreferences prefs = await SharedPreferences.getInstance(); await prefs.remove('espIpAddress'); Navigator.of(context).pushReplacement( MaterialPageRoute(builder: (context) => LoginView()), ); } int parseTime(String time) { List parts = time.split(' '); _day = int.parse(parts[0]); List timeParts = parts[1].split(':'); int hours = int.parse(timeParts[0]); int minutes = int.parse(timeParts[1]); int seconds = int.parse(timeParts[2]); return (hours * 3600 + minutes * 60 + seconds); } Widget countDown() { int hours = _sec ~/ 3600; int minutes = (_sec % 3600) ~/ 60; int seconds = _sec % 60; String dayStr = _day.toString().padLeft(2, '0'); String hoursStr = hours.toString().padLeft(2, '0'); String minutesStr = minutes.toString().padLeft(2, '0'); String secondsStr = seconds.toString().padLeft(2, '0'); return Center( child: Container( margin: EdgeInsets.only(top: 36), height: 100, width: 400, decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), color: Colors.white, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.5), blurRadius: 1, offset: Offset(0, 1), ), ], ), child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( 'Day: $dayStr', style: GoogleFonts.spaceMono( fontSize: 32, fontWeight: FontWeight.bold, color: Colors.black), ), Text( '$hoursStr:$minutesStr:$secondsStr', style: GoogleFonts.spaceMono( fontSize: 32, fontWeight: FontWeight.bold, color: Colors.black), ), ], ), ), ), ); } Widget Power() { return Center( child: Container( margin: EdgeInsets.only(top: 36), height: 100, width: 400, decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), color: Colors.white, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.5), blurRadius: 1, offset: Offset(0, 1), ), ], ), child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( "Power", style: GoogleFonts.spaceMono(fontSize: 18), ), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton( onPressed: _powerOn, child: Text('Power On'), style: ElevatedButton.styleFrom(fixedSize: Size(120, 40)), ), SizedBox( width: 20, ), ElevatedButton( onPressed: _powerOff, child: Text('Power Off'), style: ElevatedButton.styleFrom( backgroundColor: Colors.redAccent, fixedSize: Size(120, 40)), ), ], ), ], ), ), ), ); } Widget title() { return Container( margin: EdgeInsets.only(top: 22), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Suhu dan Kelembapan", style: GoogleFonts.spaceMono(fontSize: 18), ), Container( child: Text( "", style: GoogleFonts.spaceMono( color: Colors.redAccent, fontWeight: FontWeight.bold, ), ), ) ], ), ); } Widget temperature1() { return Container( width: double.infinity, margin: EdgeInsets.only(top: 8), padding: EdgeInsets.all(8), decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), color: Colors.white, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.5), blurRadius: 1, offset: Offset(0, 1), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( flex: 2, child: ClipRRect( borderRadius: BorderRadius.circular(15), child: Container( height: 60, width: double.infinity, decoration: BoxDecoration( color: Color(0xFFF6DBDB), borderRadius: BorderRadius.circular(15), image: DecorationImage( image: AssetImage('assets/images/suhu.png'), ), ), ), ), ), SizedBox(width: 12), Expanded( flex: 6, child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Suhu', style: GoogleFonts.spaceMono(fontSize: 18), ), Text( '${temperature.toStringAsFixed(2)} °C', style: GoogleFonts.spaceMono( fontSize: 20, fontWeight: FontWeight.bold, ), ), ], ), ), ], ), Divider(color: Colors.grey), Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( flex: 2, child: ClipRRect( borderRadius: BorderRadius.circular(15), child: Container( height: 60, width: double.infinity, decoration: BoxDecoration( color: Color(0xFFE2F2F5), borderRadius: BorderRadius.circular(15), image: DecorationImage( image: AssetImage('assets/images/kelembapan.png'), ), ), ), ), ), SizedBox(width: 12), Expanded( flex: 6, child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Kelembapan', style: GoogleFonts.spaceMono(fontSize: 18), ), Text( '${humidity.toStringAsFixed(2)} %', style: GoogleFonts.spaceMono( fontSize: 20, fontWeight: FontWeight.bold, ), ), ], ), ), ], ), ], ), ); } // Widget tombol() { // return Container( // width: double.infinity, // // height: 250, // margin: EdgeInsets.only(top: 8), // padding: EdgeInsets.all(8), // decoration: BoxDecoration( // borderRadius: BorderRadius.circular(15), // color: Colors.white, // boxShadow: [ // BoxShadow( // color: Colors.black.withOpacity(0.5), // blurRadius: 1, // offset: Offset(0, 1), // changes position of shadow // ), // ], // ), // child: Column( // children: [ // Row( // mainAxisAlignment: MainAxisAlignment.spaceBetween, // children: [ // Text( // 'Kontrol Alat', // style: primaryTextStyle.copyWith(fontSize: 18), // ), // TextButton( // onPressed: () { // Navigator.push( // context, // MaterialPageRoute( // builder: (context) => KontrolView( // espIpAddress: widget.espIpAddress, // ), // )); // }, // child: Text('Buka')), // ], // ), // ], // ), // ); // } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( iconTheme: IconThemeData(color: Colors.black), elevation: 0, backgroundColor: Colors.black, automaticallyImplyLeading: false, centerTitle: true, title: Text( "Home", style: secondaryTextStyle.copyWith(fontSize: 16), ), actions: [ IconButton( icon: Icon(Icons.edit), color: Colors.white, onPressed: _showDayInputDialog, ), SizedBox( width: 3, ), IconButton( onPressed: _logout, icon: Icon(Icons.logout_rounded), color: Colors.white, ) ], ), body: Padding( padding: const EdgeInsets.all(16.0), child: ListView( physics: NeverScrollableScrollPhysics(), children: [ Power(), countDown(), title(), temperature1(), ], ), ), ); } }