161 lines
5.0 KiB
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();
|
|
}
|
|
}
|