From 1c6178d5bdacecbff6113f7804bd2c1fa2fd150d Mon Sep 17 00:00:00 2001 From: Furqon44 Date: Wed, 18 Jun 2025 15:08:04 +0700 Subject: [PATCH] Add files via upload --- main.dart | 550 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 550 insertions(+) create mode 100644 main.dart diff --git a/main.dart b/main.dart new file mode 100644 index 0000000..463768e --- /dev/null +++ b/main.dart @@ -0,0 +1,550 @@ +import 'package:flutter/material.dart'; +import 'package:firebase_core/firebase_core.dart'; +import 'package:firebase_database/firebase_database.dart'; +import 'package:intl/intl.dart'; +import 'dart:async'; + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + await Firebase.initializeApp( + options: const FirebaseOptions( + apiKey: "AIzaSyB4_8od06WpwWi0JnH5AsumeMfS4J-6z94", + authDomain: "tess-2d281.firebaseapp.com", + databaseURL: "https://tess-2d281-default-rtdb.firebaseio.com", + projectId: "tess-2d281", + storageBucket: "tess-2d281.firebasestorage.app", + messagingSenderId: "125497189118", + appId: "1:125497189118:web:c5e86434ed027f1b8fbbaf", + measurementId: "G-35VV44S694", + ), + ); + + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Smart Planting Pot', + debugShowCheckedModeBanner: false, + theme: ThemeData( + primarySwatch: Colors.green, + scaffoldBackgroundColor: Colors.white, + ), + home: const HomeScreen(), + ); + } +} + +class HomeScreen extends StatefulWidget { + const HomeScreen({Key? key}) : super(key: key); + + @override + State createState() => _HomeScreenState(); +} + +class _HomeScreenState extends State { + final DatabaseReference _database = FirebaseDatabase.instance.ref(); + + String _humidity = "50%"; + String _temperature = "50%"; + String _soilMoisture = "50%"; + String _light = "50%"; + String _currentTime = "00:00"; + String _greeting = "Good Morning"; + + bool _isWaterPumpOn = false; + bool _isFertilizerPumpOn = false; + + String _waterPumpRange = "50%-80%"; + String _fertilizerPumpDate = "30-03-2025"; + String _fertilizerPumpTime = "12:00"; + + final TextEditingController _waterPumpRangeController = TextEditingController(); + final TextEditingController _fertilizerPumpDateController = TextEditingController(); + final TextEditingController _fertilizerPumpTimeController = TextEditingController(); + + @override + void initState() { + super.initState(); + _setupFirebaseListeners(); + _setupCurrentTime(); + } + + void _setupCurrentTime() { + Timer.periodic(Duration(seconds: 1), (timer) { + final now = DateTime.now(); + setState(() { + _currentTime = DateFormat('HH:mm:ss').format(now); + _updateGreeting(now.hour); + }); + }); + } + + void _updateGreeting(int hour) { + if (hour >= 5 && hour < 12) { + _greeting = "Good Morning"; + } else if (hour >= 12 && hour < 17) { + _greeting = "Good Afternoon"; + } else if (hour >= 17 && hour < 21) { + _greeting = "Good Evening"; + } else { + _greeting = "Good Night"; + } + } + + void _setupFirebaseListeners() { + _database.child('sensors').onValue.listen((event) { + final data = event.snapshot.value as Map?; + if (data != null) { + setState(() { + _humidity = "${data['humidity'] ?? 50}%"; + _temperature = "${(data['temperature'] ?? 25).toStringAsFixed(1)}°C"; + _soilMoisture = "${data['soilMoisture'] ?? 50}%"; + _light = "${data['light'] ?? 50}%"; + }); + } + }); + + _database.child('pumps').onValue.listen((event) { + final data = event.snapshot.value as Map?; + if (data != null) { + setState(() { + _isWaterPumpOn = data['waterPump'] ?? false; + _isFertilizerPumpOn = data['fertilizerPump'] ?? false; + }); + } + }); + + _database.child('pump_settings').onValue.listen((event) { + final data = event.snapshot.value as Map?; + if (data != null) { + setState(() { + _waterPumpRange = data['waterPumpRange'] ?? "50%-80%"; + _fertilizerPumpDate = data['fertilizerPumpDate'] ?? "30-03-2025"; + _fertilizerPumpTime = data['fertilizerPumpTime'] ?? "12:00"; + }); + } + }); + } + + void _togglePump(String pumpName, bool value) { + _database.child('pumps').update({pumpName: value}); + } + + void _updatePumpSettings() { + _database.child('pump_settings').update({ + 'waterPumpRange': _waterPumpRangeController.text, + 'fertilizerPumpDate': _fertilizerPumpDateController.text, + 'fertilizerPumpTime': _fertilizerPumpTimeController.text, + }); + + setState(() { + _waterPumpRange = _waterPumpRangeController.text; + _fertilizerPumpDate = _fertilizerPumpDateController.text; + _fertilizerPumpTime = _fertilizerPumpTimeController.text; + }); + + Navigator.pop(context); + } + + Future _selectDate(BuildContext context) async { + final DateTime? picked = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime.now(), + lastDate: DateTime(2030), + ); + if (picked != null) { + setState(() { + _fertilizerPumpDateController.text = DateFormat('dd-MM-yyyy').format(picked); + }); + } + } + + Future _selectTime(BuildContext context) async { + final TimeOfDay? picked = await showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ); + if (picked != null) { + setState(() { + _fertilizerPumpTimeController.text = + picked.hour.toString().padLeft(2, '0') + ':' + + picked.minute.toString().padLeft(2, '0'); + }); + } + } + + void _showPumpSettingsDialog() { + _waterPumpRangeController.text = _waterPumpRange; + _fertilizerPumpDateController.text = _fertilizerPumpDate; + _fertilizerPumpTimeController.text = _fertilizerPumpTime; + + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Pump Settings'), + content: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + TextField( + controller: _waterPumpRangeController, + decoration: const InputDecoration( + labelText: 'Water Pump Range', + hintText: 'Enter range (e.g., 50%-80%)', + ), + ), + Row( + children: [ + Expanded( + child: TextField( + controller: _fertilizerPumpDateController, + decoration: const InputDecoration( + labelText: 'Fertilizer Pump Date', + hintText: 'Select Date', + ), + readOnly: true, + onTap: () => _selectDate(context), + ), + ), + IconButton( + icon: const Icon(Icons.calendar_today), + onPressed: () => _selectDate(context), + ), + ], + ), + Row( + children: [ + Expanded( + child: TextField( + controller: _fertilizerPumpTimeController, + decoration: const InputDecoration( + labelText: 'Fertilizer Pump Time', + hintText: 'Select Time', + ), + readOnly: true, + onTap: () => _selectTime(context), + ), + ), + IconButton( + icon: const Icon(Icons.access_time), + onPressed: () => _selectTime(context), + ), + ], + ), + ], + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: const Text('Cancel'), + ), + ElevatedButton( + onPressed: _updatePumpSettings, + child: const Text('Save'), + ), + ], + ); + }, + ); + } + + void _showInfoDialog() { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('Settings Information'), + content: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + 'Water Pump Range:', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 16, + ), + ), + const SizedBox(height: 8), + Text( + 'Current setting: $_waterPumpRange', + style: const TextStyle(fontSize: 14), + ), + const SizedBox(height: 16), + const Text( + 'Fertilizer Schedule:', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 16, + ), + ), + const SizedBox(height: 8), + Text( + 'Scheduled for: $_fertilizerPumpDate at $_fertilizerPumpTime', + style: const TextStyle(fontSize: 14), + ), + ], + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: const Text('Close'), + ), + ], + ); + }, + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: SafeArea( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + "HELLO,", + style: TextStyle( + fontSize: 28, + fontWeight: FontWeight.bold, + color: Colors.black87, + ), + ), + Text( + _greeting, + style: const TextStyle( + fontSize: 28, + fontWeight: FontWeight.bold, + color: Colors.black87, + ), + ), + ], + ), + Row( + children: [ + IconButton( + icon: const Icon(Icons.settings_outlined, size: 28), + color: Colors.green, + onPressed: _showPumpSettingsDialog, + ), + IconButton( + icon: const Icon(Icons.info_outline, size: 28), + color: Colors.green, + onPressed: _showInfoDialog, + ), + ], + ), + ], + ), + const SizedBox(height: 24), + Center( + child: Column( + children: [ + Container( + width: 120, + height: 120, + decoration: const BoxDecoration( + shape: BoxShape.circle, + color: Colors.white, + boxShadow: [ + BoxShadow( + color: Colors.black12, + blurRadius: 10, + offset: Offset(0, 4), + ) + ], + ), + child: const Center( + child: Icon( + Icons.energy_savings_leaf, + color: Colors.green, + size: 80, + ), + ), + ), + const SizedBox(height: 12), + Container( + width: 250, + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 16, + ), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: Colors.black12, + blurRadius: 10, + offset: Offset(0, 4), + ) + ], + ), + child: Column( + children: [ + const Text( + "Smart Planting pot", + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + ), + ), + const SizedBox(height: 4), + Text( + _currentTime, + style: const TextStyle( + fontSize: 14, + color: Colors.grey, + ), + ), + ], + ), + ), + ], + ), + ), + const SizedBox(height: 24), + GridView.count( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + crossAxisCount: 2, + mainAxisSpacing: 16, + crossAxisSpacing: 16, + childAspectRatio: 1.2, + children: [ + _buildSensorCard( + icon: Icons.water_drop, + label: "Humidity", + value: _humidity, + ), + _buildSensorCard( + icon: Icons.device_thermostat, + label: "Temperature", + value: _temperature, + ), + _buildSensorCard( + icon: Icons.opacity, + label: "Soil Moisture", + value: _soilMoisture, + ), + _buildSensorCard( + icon: Icons.light_mode, + label: "Light", + value: _light, + ), + ], + ), + const SizedBox(height: 24), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Column( + children: [ + const Text( + 'Water Pump', + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w600, + ), + ), + const SizedBox(height: 8), + Switch( + activeColor: Colors.green, + value: _isWaterPumpOn, + onChanged: (value) => _togglePump('waterPump', value), + ), + ], + ), + Column( + children: [ + const Text( + 'Fertilizing Pump', + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w600, + ), + ), + const SizedBox(height: 8), + Switch( + activeColor: Colors.green, + value: _isFertilizerPumpOn, + onChanged: (value) => _togglePump('fertilizerPump', value), + ), + ], + ), + ], + ), + ], + ), + ), + ), + ), + ); + } + + Widget _buildSensorCard({ + required IconData icon, + required String label, + required String value, + }) { + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: Colors.black12, + blurRadius: 10, + offset: Offset(0, 4), + ) + ], + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Icon(icon, size: 32, color: Colors.green), + const SizedBox(height: 8), + Text( + label, + style: const TextStyle( + fontWeight: FontWeight.w600, + fontSize: 14, + ), + textAlign: TextAlign.center, + ), + const SizedBox(height: 4), + Text( + value, + style: const TextStyle( + fontSize: 14, + color: Colors.grey, + ), + textAlign: TextAlign.center, + ), + ], + ), + ); + } +} \ No newline at end of file