TKK_E32210493/lib/dashboard.dart

694 lines
22 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:http/http.dart' as http;
import 'package:flutter/cupertino.dart';
import 'DataDisplayPage.dart';
import 'SettingsPage.dart';
DatabaseReference _dataListrikRef =
FirebaseDatabase.instance.reference().child('data-listrik');
final TextEditingController addTokenController = TextEditingController();
Stream<String> _streamArus = FirebaseDatabase.instance
.reference()
.child('sensor')
.child('current')
.onValue
.map((event) => event.snapshot.value.toString());
Stream<String> _streamTegangan = FirebaseDatabase.instance
.reference()
.child('sensor')
.child('voltage')
.onValue
.map((event) => event.snapshot.value.toString());
Stream<String> _streamKwh = FirebaseDatabase.instance
.reference()
.child('sensor')
.child('energy')
.onValue
.map((event) => event.snapshot.value.toString());
Stream<String> _streamWatt = FirebaseDatabase.instance
.reference()
.child('sensor')
.child('power')
.onValue
.map((event) => event.snapshot.value.toString());
class Dashboard extends StatefulWidget {
@override
_DashboardState createState() => _DashboardState();
static void sendMessageToTelegram(String s) {}
}
class _DashboardState extends State<Dashboard> {
DatabaseReference _tokenRef =
FirebaseDatabase.instance.reference().child('tokens');
DatabaseReference _channelRef =
FirebaseDatabase.instance.reference().child('channels');
static Future<void> sendMessageToTelegram(String message) async {
final String botToken = '6904712924:AAGEVa4_ejmj-4uKz_nt_i-ceghMPWYW_5M';
final String chatId = '1709517653';
final String url = 'https://api.telegram.org/bot$botToken/sendMessage';
try {
await http.post(
Uri.parse(url),
body: {
'chat_id': chatId,
'text': message,
},
);
} catch (e) {
print('Error: $e');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xFF102C57),
body: SingleChildScrollView(
child: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
account(context),
SizedBox(height: 20),
monitoring(),
resetButton(),
kwhInput(),
button(),
relayControl(),
SizedBox(height: 20),
],
),
),
),
);
}
void resetDataListrik() {
_dataListrikRef.remove().then((_) {
print('Data-listrik deleted successfully');
}).catchError((error) {
print('Error deleting data-listrik: $error');
});
}
void _showSuccessDialog() {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
backgroundColor: Colors.transparent,
content: Container(
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
color: Colors.black,
blurRadius: 10.0,
offset: Offset(0.0, 10.0),
),
],
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
"Proses",
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.w600,
),
textAlign: TextAlign.center,
),
SizedBox(height: 20),
Text(
"Token berhasil dimasukkan ke dalam database dan diproses.",
style: TextStyle(
fontSize: 16.0,
),
textAlign: TextAlign.left,
),
SizedBox(height: 24),
Align(
alignment: Alignment.bottomRight,
child: TextButton(
onPressed: () {
Navigator.of(context).pop(); // Tutup dialog
},
child: Text(
"OK",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
),
),
],
),
),
);
},
);
}
Future<bool> _checkIfTokenExists(String token) async {
DatabaseEvent event = await _tokenRef.child(token).once();
DataSnapshot snapshot = event.snapshot;
return snapshot.value != null;
}
void _addTokenToDatabase(String token) {
String tokenWithoutSpaces = token.replaceAll(' ', '');
if (tokenWithoutSpaces.isEmpty) {
print('Token harus diisi');
return;
}
try {
// Menyimpan token sebagai nilai di bawah node 'tokens'
_tokenRef.child('tokens').set(tokenWithoutSpaces).then((_) {
print('Token berhasil diperbarui: $tokenWithoutSpaces');
sendMessageToTelegram(
'Token berhasil diperbarui dan diproses: $tokenWithoutSpaces');
sendMessageToTelegram(
'Tunggu beberapa saat untuk memvalidasi token dan Silakan kirim kata /photo untuk memvalidasi kwh.');
_showSuccessDialog();
}).catchError((error) {
print('Error: $error');
sendMessageToTelegram('Gagal memperbarui token: $error');
});
} catch (e) {
print('Error: $e');
sendMessageToTelegram('Gagal memperbarui token: $e');
}
}
void _updateChannelStatus(String channelName, bool status) {
try {
_channelRef.update({
channelName: status ? "On" : "Off",
});
print(
'Status $channelName berhasil diperbarui: ${status ? "On" : "Off"}');
} catch (e) {
print('Error: $e');
}
}
Widget account(BuildContext context) {
return Center(
child: Container(
margin: EdgeInsets.only(top: 50),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Container(
margin: EdgeInsets.only(left: 20),
height: 40,
width: 40,
decoration: BoxDecoration(
shape: BoxShape.circle,
image: DecorationImage(
image: AssetImage('assets/user.png'),
fit: BoxFit.cover,
),
),
),
SizedBox(width: 20),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Hai !',
style: GoogleFonts.poppins(color: Colors.white),
),
Text(
'Nuril Akbar',
style: GoogleFonts.poppins(
fontSize: 16,
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
],
),
],
),
Row(
children: [
IconButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SettingsPage()),
);
},
icon: Icon(
Icons.settings,
color: Colors.white,
size: 30,
),
),
IconButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DataDisplayPage()),
);
},
icon: Icon(
CupertinoIcons.doc_chart_fill,
color: Colors.white,
size: 30,
),
),
],
),
],
),
),
);
}
Widget monitoring() {
return Center(
child: Container(
margin: EdgeInsets.only(top: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Monitoring',
style: GoogleFonts.poppins(
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
SizedBox(height: 14),
Container(
height: 230,
width: 330,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
color: Colors.white,
),
child: Container(
margin: EdgeInsets.all(10),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_buildMonitoringBox('Arus', _streamArus),
_buildMonitoringBox('Tegangan', _streamTegangan),
],
),
SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_buildMonitoringBox('kWh', _streamKwh),
_buildMonitoringBox('Watt', _streamWatt),
],
),
],
),
),
),
SizedBox(height: 2),
],
),
),
);
}
Widget _buildMonitoringBox(String title, Stream<String> stream) {
return Container(
width: 150,
child: Column(
children: [
Text(title),
SizedBox(height: 8),
Container(
height: 70,
width: double.infinity,
decoration: BoxDecoration(
color: Colors.amber,
borderRadius: BorderRadius.circular(8),
),
alignment: Alignment.center,
child: StreamBuilder(
stream: stream,
builder: (context, snapshot) {
if (!snapshot.hasData || snapshot.hasError) {
return CircularProgressIndicator(); // Placeholder jika data belum dimuat
}
var value = snapshot.data ?? '0';
return Text(
value,
style: TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
color: Colors.white,
),
);
},
),
),
],
),
);
}
Widget resetButton() {
return Column(
children: [
SizedBox(height: 2),
Align(
alignment: Alignment.center,
child: Container(
margin: EdgeInsets.symmetric(vertical: 20),
height: 54,
width: 220,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(28),
color: Color(0xFFDAC0A3),
),
child: TextButton(
onPressed: () {
resetDataListrik(); // Call the reset function here
},
child: Text(
'Reset',
style: GoogleFonts.poppins(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
),
),
),
],
);
}
Widget kwhInput() {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Token KWH',
style: GoogleFonts.poppins(
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
SizedBox(height: 12),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.white,
),
child: Padding(
padding: EdgeInsets.all(15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextFormField(
controller: addTokenController,
style: GoogleFonts.poppins(
fontWeight: FontWeight.w300,
fontSize: 20,
),
textAlign: TextAlign.center,
inputFormatters: [
LengthLimitingTextInputFormatter(24),
FilteringTextInputFormatter.digitsOnly,
_TokenInputFormatter(),
],
keyboardType: TextInputType.number,
decoration: InputDecoration.collapsed(
hintText: '',
hintStyle: GoogleFonts.poppins(
fontWeight: FontWeight.w300,
color: Colors.white,
),
),
validator: (value) {
if (value!.isEmpty) {
return 'Token harus diisi';
}
if (value.replaceAll(' ', '').length != 20) {
return 'Token harus terdiri dari 20 digit';
}
return null; // Remove validation message if length is 20
},
),
SizedBox(height: 8),
Text(
'*Token harus terdiri dari 20 digit',
style: TextStyle(color: Colors.red),
),
],
),
),
),
],
),
);
}
Widget button() {
return Padding(
padding: EdgeInsets.symmetric(vertical: 20),
child: Align(
alignment: Alignment.center,
child: Container(
height: 54,
width: 220,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(28),
color: Color(0xFFDAC0A3),
),
child: TextButton(
onPressed: () async {
String token = addTokenController.text.trim();
if (token.replaceAll(' ', '').length == 20) {
_addTokenToDatabase(token);
addTokenController
.clear(); // Membersihkan input field setelah menambahkan token
} else {
print('Token harus terdiri dari 20 karakter');
}
},
child: Text(
'Input',
style: GoogleFonts.poppins(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
),
),
),
);
}
Widget relayControl() {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Switch Control',
style: GoogleFonts.poppins(
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
SizedBox(height: 12),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Column(
children: [
Text(
'Switch 1',
style: TextStyle(fontSize: 16, color: Colors.white),
),
SizedBox(height: 8),
Transform.scale(
scale: 1.4,
child: StreamBuilder(
stream: _channelRef.child('channel1').onValue,
builder: (context, snapshot) {
if (!snapshot.hasData || snapshot.hasError) {
return CircularProgressIndicator(); // Placeholder jika data belum dimuat
}
var status = snapshot.data!.snapshot.value ?? false;
return Switch(
value: status == "On",
activeColor: Theme.of(context).primaryColor,
onChanged: (newValue) {
setState(() {
_updateChannelStatus('channel1', newValue);
});
},
);
},
),
),
],
),
Column(
children: [
Text(
'Switch 2',
style: TextStyle(fontSize: 16, color: Colors.white),
),
SizedBox(height: 8),
Transform.scale(
scale: 1.4,
child: StreamBuilder(
stream: _channelRef.child('channel2').onValue,
builder: (context, snapshot) {
if (!snapshot.hasData || snapshot.hasError) {
return CircularProgressIndicator(); // Placeholder jika data belum dimuat
}
var status = snapshot.data!.snapshot.value ?? false;
return Switch(
value: status == "On",
activeColor: Theme.of(context).primaryColor,
onChanged: (newValue) {
setState(() {
_updateChannelStatus('channel2', newValue);
});
},
);
},
),
),
],
),
],
),
SizedBox(height: 12),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Column(
children: [
Text(
'Switch 3',
style: TextStyle(fontSize: 16, color: Colors.white),
),
SizedBox(height: 8),
Transform.scale(
scale: 1.4,
child: StreamBuilder(
stream: _channelRef.child('channel3').onValue,
builder: (context, snapshot) {
if (!snapshot.hasData || snapshot.hasError) {
return CircularProgressIndicator(); // Placeholder jika data belum dimuat
}
var status = snapshot.data!.snapshot.value ?? false;
return Switch(
value: status == "On",
activeColor: Theme.of(context).primaryColor,
onChanged: (newValue) {
setState(() {
_updateChannelStatus('channel3', newValue);
});
},
);
},
),
),
],
),
Column(
children: [
Text(
'Switch 4',
style: TextStyle(fontSize: 16, color: Colors.white),
),
SizedBox(height: 8),
Transform.scale(
scale: 1.4,
child: StreamBuilder(
stream: _channelRef.child('channel4').onValue,
builder: (context, snapshot) {
if (!snapshot.hasData || snapshot.hasError) {
return CircularProgressIndicator(); // Placeholder jika data belum dimuat
}
var status = snapshot.data!.snapshot.value ?? false;
return Switch(
value: status == "On",
activeColor: Theme.of(context).primaryColor,
onChanged: (newValue) {
setState(() {
_updateChannelStatus('channel4', newValue);
});
},
);
},
),
),
],
),
],
),
],
),
);
}
}
class _TokenInputFormatter extends TextInputFormatter {
@override
TextEditingValue formatEditUpdate(
TextEditingValue oldValue, TextEditingValue newValue) {
if (newValue.selection.baseOffset == 0) {
return newValue;
}
final StringBuffer newText = StringBuffer();
for (int i = 0; i < newValue.text.length; i++) {
if (i > 0 && i % 4 == 0) {
newText.write(' ');
}
newText.write(newValue.text[i]);
}
return TextEditingValue(
text: newText.toString(),
selection: TextSelection.collapsed(offset: newText.length),
);
}
}