TKK_E32220213/code aplikasi/lib/services/firebase_service.dart

132 lines
4.4 KiB
Dart

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_database/firebase_database.dart';
import '../models/sensor_data.dart';
class FirebaseService {
final DatabaseReference _database = FirebaseDatabase.instance.ref();
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
// === PENGAMBILAN PATH RTDB ===
Stream<SensorData> getSensorData() {
return _database.onValue.map((event) {
final data = event.snapshot.value as Map<dynamic, dynamic>;
return SensorData(
suhu: (data['suhu'] ?? 0.0).toDouble(),
timer: data['timer'] ?? 0,
manualMode: data['manualMode'] ?? false,
manualButton: data['manualButton'] ?? false,
elemen: data['elemen']?.toString() ?? 'off',
suhuMaks: data['suhuMaks'] ?? 45,
suhuMin: data['suhuMin'] ?? 40,
kadarAir: (data['kadarAir'] ?? 0.0).toDouble(),
);
});
}
// === UPDATEDATA RTDB ===
Future<void> updateManualMode(bool value) =>
_database.child('manualMode').set(value);
Future<void> updateManualButton(bool value) =>
_database.child('manualButton').set(value);
Future<void> updateElemen(String value) =>
_database.child('elemen').set(value);
Future<void> updateTimer(int value) => _database.child('timer').set(value);
Future<void> updateSuhuMaks(int value) =>
_database.child('suhuMaks').set(value);
Future<void> updateSuhuMin(int value) =>
_database.child('suhuMin').set(value);
Future<void> updateKadarAir(double value) =>
_database.child('kadarAir').set(value);
Future<void> updateKoneksiAndroid(bool value) =>
_database.child('koneksiandroid').set(value);
// Fungsi untuk mereset timer ke 0
Future<void> resetTimer() => _database.child('timer').set(0);
// === SYNC DATA RTDB TO FIRESTORE ===
/// Sinkron seluruh data dari RTDB path ke koleksi Firestore
Future<void> syncPathToFirestore(
String rtdbPath, String firestoreCollection) async {
try {
final snapshot = await _database.child(rtdbPath).get();
if (!snapshot.exists) return;
final data = snapshot.value as Map<dynamic, dynamic>;
final batch = _firestore.batch();
data.forEach((key, value) {
final docData = Map<String, dynamic>.from(value as Map)
..['timestamp'] = FieldValue.serverTimestamp();
final docRef =
_firestore.collection(firestoreCollection).doc(key.toString());
batch.set(docRef, docData);
});
await batch.commit();
print('Sync RTDB `$rtdbPath` → Firestore `$firestoreCollection` selesai');
} catch (e) {
print('Error syncPathToFirestore: $e');
}
}
/// Mirror perubahan RTDB secara realtime ke Firestore
void listenAndMirror(String rtdbPath, String firestoreCollection) {
final ref = _database.child(rtdbPath);
ref.onChildAdded.listen((event) {
final key = event.snapshot.key!;
final data = Map<String, dynamic>.from(event.snapshot.value as Map)
..['timestamp'] = FieldValue.serverTimestamp();
_firestore
.collection(firestoreCollection)
.doc(key)
.set(data)
.then((_) => verifyDocument(key))
.catchError((err) => print('onChildAdded error: $err'));
}, onError: (err) => print('RTDB onChildAdded listener error: $err'));
ref.onChildChanged.listen((event) {
final key = event.snapshot.key!;
final data = Map<String, dynamic>.from(event.snapshot.value as Map);
_firestore
.collection(firestoreCollection)
.doc(key)
.update(data)
.catchError((err) => print('onChildChanged error: $err'));
}, onError: (err) => print('RTDB onChildChanged listener error: $err'));
ref.onChildRemoved.listen((event) {
final key = event.snapshot.key!;
_firestore
.collection(firestoreCollection)
.doc(key)
.delete()
.catchError((err) => print('onChildRemoved error: $err'));
}, onError: (err) => print('RTDB onChildRemoved listener error: $err'));
}
/// Verifikasi bahwa dokumen tersimpan di Firestore
Future<void> verifyDocument(String docId) async {
try {
final doc =
await _firestore.collection('sensorData_firestore').doc(docId).get();
if (doc.exists) {
print('Verifikasi berhasil: ${doc.data()}');
} else {
print('Dokumen $docId tidak ditemukan di Firestore');
}
} catch (e) {
print('Verifikasi error: $e');
}
}
}