TKK_E32232282/Source Code Mobile/history_provider.dart

161 lines
5.0 KiB
Dart

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:firebase_database/firebase_database.dart';
import '../models/history_model.dart';
import '../models/control_history_model.dart';
import '../services/firebase_service.dart';
class HistoryProvider extends ChangeNotifier {
List<HistoryModel> monitoringHistory = [];
List<ControlHistoryModel> controlHistory = [];
bool isLoading = false;
StreamSubscription<DatabaseEvent>? monitoringSubscription;
StreamSubscription<DatabaseEvent>? _manualSubscription;
StreamSubscription<DatabaseEvent>? _autoSubscription;
final List<ControlHistoryModel> _manualHistory = [];
final List<ControlHistoryModel> _autoHistory = [];
// ================= MONITORING =================
void startMonitoringListener() {
monitoringSubscription?.cancel();
monitoringSubscription = FirebaseService.monitoringHistoryRef.onValue
.listen((event) {
monitoringHistory.clear();
if (event.snapshot.value == null) {
notifyListeners();
return;
}
final data = Map<dynamic, dynamic>.from(event.snapshot.value as Map);
data.forEach((key, value) {
monitoringHistory.add(
HistoryModel.fromMap(Map<dynamic, dynamic>.from(value)),
);
});
monitoringHistory.sort((a, b) => b.timestamp.compareTo(a.timestamp));
notifyListeners();
});
}
// ================= CONTROL (Manual & Auto triggers combined) =================
void startControlListener() {
_manualSubscription?.cancel();
_autoSubscription?.cancel();
// 1. Listen to manual controls
_manualSubscription = FirebaseService.controlHistoryRef.onValue.listen((event) {
_manualHistory.clear();
if (event.snapshot.value != null) {
final data = Map<dynamic, dynamic>.from(event.snapshot.value as Map);
data.forEach((key, value) {
_manualHistory.add(
ControlHistoryModel.fromMap(Map<dynamic, dynamic>.from(value)),
);
});
}
_combineAndSortHistory();
});
// 2. Listen to auto triggers
_autoSubscription = FirebaseService.acAutoTriggerHistoryRef.onValue.listen((event) {
_autoHistory.clear();
if (event.snapshot.value != null) {
final data = Map<dynamic, dynamic>.from(event.snapshot.value as Map);
data.forEach((key, value) {
final mapVal = Map<dynamic, dynamic>.from(value);
final rawAction = mapVal['action']?.toString() ?? 'unknown';
String actionText = rawAction;
if (rawAction == 'auto_off') {
actionText = 'AC Dimatikan Otomatis (Semua Parameter Baik)';
} else if (rawAction == 'auto_dry') {
actionText = 'Mode Dry Otomatis (Kelembapan Tinggi)';
} else if (rawAction == 'auto_cool') {
actionText = 'Mode Cool Otomatis (Suhu/Kelembapan Luar Batas)';
} else if (rawAction == 'auto_fan') {
actionText = 'Mode Fan Otomatis (Udara Buruk)';
}
final ts = mapVal['timestamp'] is int ? mapVal['timestamp'] : 0;
_autoHistory.add(
ControlHistoryModel(
action: actionText,
source: 'Auto (ESP32)',
timestamp: _parseTimestampString(ts),
rawTimestamp: ts,
),
);
});
}
_combineAndSortHistory();
});
}
void _combineAndSortHistory() {
controlHistory = [..._manualHistory, ..._autoHistory];
controlHistory.sort((a, b) => b.rawTimestamp.compareTo(a.rawTimestamp));
notifyListeners();
}
String _parseTimestampString(int value) {
if (value == 0) return '';
final dt = DateTime.fromMillisecondsSinceEpoch(value * 1000);
return "${dt.year}-${dt.month.toString().padLeft(2, '0')}-${dt.day.toString().padLeft(2, '0')} "
"${dt.hour.toString().padLeft(2, '0')}:${dt.minute.toString().padLeft(2, '0')}:${dt.second.toString().padLeft(2, '0')}";
}
// ================= CLEAR HISTORIES =================
Future<void> clearMonitoringHistory() async {
try {
isLoading = true;
notifyListeners();
await FirebaseService.monitoringHistoryRef.remove();
monitoringHistory.clear();
isLoading = false;
notifyListeners();
} catch (e) {
isLoading = false;
notifyListeners();
rethrow;
}
}
Future<void> clearControlHistory() async {
try {
isLoading = true;
notifyListeners();
await FirebaseService.controlHistoryRef.remove();
await FirebaseService.acAutoTriggerHistoryRef.remove();
_manualHistory.clear();
_autoHistory.clear();
controlHistory.clear();
isLoading = false;
notifyListeners();
} catch (e) {
isLoading = false;
notifyListeners();
rethrow;
}
}
@override
void dispose() {
monitoringSubscription?.cancel();
_manualSubscription?.cancel();
_autoSubscription?.cancel();
super.dispose();
}
}