Upload files to "Source Code Mobile"
This commit is contained in:
parent
c45291d36f
commit
30a2a84e44
|
|
@ -0,0 +1,41 @@
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:firebase_database/firebase_database.dart';
|
||||||
|
|
||||||
|
import '../services/firebase_service.dart';
|
||||||
|
|
||||||
|
class ACConfigProvider extends ChangeNotifier {
|
||||||
|
bool _hasConfig = false;
|
||||||
|
String _protocol = 'UNKNOWN';
|
||||||
|
int _model = -1;
|
||||||
|
|
||||||
|
bool get hasConfig => _hasConfig;
|
||||||
|
String get protocol => _protocol;
|
||||||
|
int get model => _model;
|
||||||
|
|
||||||
|
StreamSubscription<DatabaseEvent>? _subscription;
|
||||||
|
|
||||||
|
void startListening() {
|
||||||
|
_subscription?.cancel();
|
||||||
|
_subscription = FirebaseService.acStateRef.onValue.listen((event) {
|
||||||
|
if (event.snapshot.value == null) {
|
||||||
|
_hasConfig = false;
|
||||||
|
} else {
|
||||||
|
final data = Map<dynamic, dynamic>.from(event.snapshot.value as Map);
|
||||||
|
_hasConfig =
|
||||||
|
data['has_config'] == true ||
|
||||||
|
(data['protocol'] != null && data['protocol'] != 'UNKNOWN');
|
||||||
|
_protocol = data['protocol']?.toString() ?? 'UNKNOWN';
|
||||||
|
_model = int.tryParse(data['model']?.toString() ?? '-1') ?? -1;
|
||||||
|
}
|
||||||
|
notifyListeners();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_subscription?.cancel();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,136 @@
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:firebase_database/firebase_database.dart';
|
||||||
|
|
||||||
|
import '../models/ac_model.dart';
|
||||||
|
import '../services/firebase_service.dart';
|
||||||
|
|
||||||
|
class ACProvider extends ChangeNotifier {
|
||||||
|
ACModel _ac = ACModel(power: false, mode: 'COOL', temp: 24, fan: 'AUTO', swing: false, controlMode: 'auto');
|
||||||
|
|
||||||
|
ACModel get ac => _ac;
|
||||||
|
|
||||||
|
bool _isSending = false;
|
||||||
|
bool get isSending => _isSending;
|
||||||
|
|
||||||
|
StreamSubscription<DatabaseEvent>? _subscription;
|
||||||
|
|
||||||
|
// ================= LISTENER =================
|
||||||
|
|
||||||
|
void startListening() {
|
||||||
|
_subscription?.cancel();
|
||||||
|
|
||||||
|
_subscription = FirebaseService.acStateRef.onValue.listen((event) {
|
||||||
|
if (event.snapshot.value == null) return;
|
||||||
|
|
||||||
|
final data = Map<dynamic, dynamic>.from(event.snapshot.value as Map);
|
||||||
|
_ac = ACModel.fromMap(data);
|
||||||
|
notifyListeners();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================= SEND COMMAND =================
|
||||||
|
|
||||||
|
Future<void> _sendCommand(String cmd, String val) async {
|
||||||
|
try {
|
||||||
|
_isSending = true;
|
||||||
|
notifyListeners();
|
||||||
|
await FirebaseService.acCommandRef.set({'command': cmd, 'value': val});
|
||||||
|
|
||||||
|
// Write control history record to Firebase
|
||||||
|
String actionText = '$cmd: $val';
|
||||||
|
if (cmd == 'power') {
|
||||||
|
actionText = val == 'on' ? 'Menyalakan AC' : 'Mematikan AC';
|
||||||
|
} else if (cmd == 'mode') {
|
||||||
|
actionText = 'Mengubah Mode ke ${val.toUpperCase()}';
|
||||||
|
} else if (cmd == 'temp') {
|
||||||
|
actionText = 'Mengatur Suhu ke $val°C';
|
||||||
|
} else if (cmd == 'fan') {
|
||||||
|
actionText = 'Mengatur Kipas ke ${val.toUpperCase()}';
|
||||||
|
} else if (cmd == 'swing') {
|
||||||
|
actionText = val == 'on' ? 'Mengaktifkan Swing' : 'Mematikan Swing';
|
||||||
|
} else if (cmd == 'control_mode') {
|
||||||
|
actionText = 'Mengubah Mode Kontrol ke ${val.toUpperCase()}';
|
||||||
|
}
|
||||||
|
|
||||||
|
final timestamp = DateTime.now().millisecondsSinceEpoch ~/ 1000;
|
||||||
|
await FirebaseService.controlHistoryRef.push().set({
|
||||||
|
'action': actionText,
|
||||||
|
'source': 'Mobile',
|
||||||
|
'timestamp': timestamp,
|
||||||
|
});
|
||||||
|
|
||||||
|
_isSending = false;
|
||||||
|
notifyListeners();
|
||||||
|
} catch (e) {
|
||||||
|
_isSending = false;
|
||||||
|
notifyListeners();
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================= SINGLE FIELD UPDATES =================
|
||||||
|
|
||||||
|
Future<void> setPower(bool value) async {
|
||||||
|
await _sendCommand('power', value ? 'on' : 'off');
|
||||||
|
_ac = _ac.copyWith(power: value);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> setMode(String value) async {
|
||||||
|
await _sendCommand('mode', value.toLowerCase());
|
||||||
|
_ac = _ac.copyWith(mode: value);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> setTemp(int value) async {
|
||||||
|
if (value < 16 || value > 30) return;
|
||||||
|
await _sendCommand('temp', value.toString());
|
||||||
|
_ac = _ac.copyWith(temp: value);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> setFan(String value) async {
|
||||||
|
await _sendCommand('fan', value.toLowerCase());
|
||||||
|
_ac = _ac.copyWith(fan: value);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> toggleSwing() async {
|
||||||
|
final nextValue = !_ac.swing;
|
||||||
|
await _sendCommand('swing', nextValue ? 'on' : 'off');
|
||||||
|
_ac = _ac.copyWith(swing: nextValue);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> setControlMode(String value) async {
|
||||||
|
await _sendCommand('control_mode', value.toLowerCase());
|
||||||
|
_ac = _ac.copyWith(controlMode: value);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================= CYCLE HELPERS =================
|
||||||
|
|
||||||
|
/// Cycles through: COOL → DRY → HEAT → FAN → AUTO → COOL
|
||||||
|
Future<void> cycleMode() async {
|
||||||
|
const modes = ['COOL', 'DRY', 'HEAT', 'FAN', 'AUTO'];
|
||||||
|
final idx = modes.indexOf(_ac.mode.toUpperCase());
|
||||||
|
final next = modes[(idx == -1 ? 0 : idx + 1) % modes.length];
|
||||||
|
await setMode(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Cycles through: AUTO → LOW → MED → HIGH → MAX → AUTO
|
||||||
|
Future<void> cycleFan() async {
|
||||||
|
const fans = ['AUTO', 'LOW', 'MED', 'HIGH', 'MAX'];
|
||||||
|
final idx = fans.indexOf(_ac.fan.toUpperCase());
|
||||||
|
final next = fans[(idx == -1 ? 0 : idx + 1) % fans.length];
|
||||||
|
await setFan(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_subscription?.cancel();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,158 @@
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:firebase_database/firebase_database.dart';
|
||||||
|
|
||||||
|
import '../services/firebase_service.dart';
|
||||||
|
|
||||||
|
class ACSetupProvider extends ChangeNotifier {
|
||||||
|
// Status from Firebase
|
||||||
|
String _mode = 'idle'; // idle, config, sweep, learn
|
||||||
|
String _step = 'not_configured'; // not_configured, select_brand, confirm, learning, ready
|
||||||
|
bool _hasSavedConfig = false;
|
||||||
|
int _brandIndex = 0;
|
||||||
|
String _brandName = '';
|
||||||
|
String _brandDesc = '';
|
||||||
|
String _modelName = '';
|
||||||
|
String _message = '';
|
||||||
|
|
||||||
|
// Detected in learning
|
||||||
|
String _detectedProtocol = '';
|
||||||
|
String _detectedDesc = '';
|
||||||
|
|
||||||
|
// Brands list from Firebase
|
||||||
|
List<Map<String, dynamic>> _brands = [];
|
||||||
|
|
||||||
|
// Getters
|
||||||
|
String get mode => _mode;
|
||||||
|
String get step => _step;
|
||||||
|
bool get hasSavedConfig => _hasSavedConfig;
|
||||||
|
int get brandIndex => _brandIndex;
|
||||||
|
String get brandName => _brandName;
|
||||||
|
String get brandDesc => _brandDesc;
|
||||||
|
String get modelName => _modelName;
|
||||||
|
String get message => _message;
|
||||||
|
String get detectedProtocol => _detectedProtocol;
|
||||||
|
String get detectedDesc => _detectedDesc;
|
||||||
|
List<Map<String, dynamic>> get brands => _brands;
|
||||||
|
|
||||||
|
StreamSubscription<DatabaseEvent>? _statusSubscription;
|
||||||
|
StreamSubscription<DatabaseEvent>? _brandsSubscription;
|
||||||
|
|
||||||
|
bool _isSending = false;
|
||||||
|
bool get isSending => _isSending;
|
||||||
|
|
||||||
|
void startListening() {
|
||||||
|
_statusSubscription?.cancel();
|
||||||
|
_brandsSubscription?.cancel();
|
||||||
|
|
||||||
|
// 1. Listen to config status
|
||||||
|
_statusSubscription = FirebaseService.acConfigStatusRef.onValue.listen((event) {
|
||||||
|
if (event.snapshot.value == null) {
|
||||||
|
_mode = 'idle';
|
||||||
|
_step = 'not_configured';
|
||||||
|
_hasSavedConfig = false;
|
||||||
|
_brandIndex = 0;
|
||||||
|
_brandName = '';
|
||||||
|
_brandDesc = '';
|
||||||
|
_modelName = '';
|
||||||
|
_message = '';
|
||||||
|
_detectedProtocol = '';
|
||||||
|
_detectedDesc = '';
|
||||||
|
} else {
|
||||||
|
final data = Map<dynamic, dynamic>.from(event.snapshot.value as Map);
|
||||||
|
_mode = data['mode']?.toString() ?? 'idle';
|
||||||
|
_step = data['step']?.toString() ?? 'not_configured';
|
||||||
|
_hasSavedConfig = data['has_config'] == true;
|
||||||
|
_brandIndex = int.tryParse(data['brand_index']?.toString() ?? '0') ?? 0;
|
||||||
|
_brandName = data['brand_name']?.toString() ?? '';
|
||||||
|
_brandDesc = data['brand_desc']?.toString() ?? '';
|
||||||
|
_modelName = data['model_name']?.toString() ?? '';
|
||||||
|
_message = data['message']?.toString() ?? '';
|
||||||
|
_detectedProtocol = data['detected_protocol']?.toString() ?? '';
|
||||||
|
_detectedDesc = data['detected_desc']?.toString() ?? '';
|
||||||
|
}
|
||||||
|
notifyListeners();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2. Listen to config brands
|
||||||
|
_brandsSubscription = FirebaseService.acConfigBrandsRef.onValue.listen((event) {
|
||||||
|
if (event.snapshot.value == null) {
|
||||||
|
_brands = [];
|
||||||
|
} else {
|
||||||
|
final rawList = event.snapshot.value;
|
||||||
|
if (rawList is List) {
|
||||||
|
_brands = rawList
|
||||||
|
.where((item) => item != null)
|
||||||
|
.map((item) => Map<String, dynamic>.from(item as Map))
|
||||||
|
.toList();
|
||||||
|
} else if (rawList is Map) {
|
||||||
|
_brands = rawList.values
|
||||||
|
.where((item) => item != null)
|
||||||
|
.map((item) => Map<String, dynamic>.from(item as Map))
|
||||||
|
.toList();
|
||||||
|
} else {
|
||||||
|
_brands = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
notifyListeners();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _sendCommand(String cmd, String val) async {
|
||||||
|
try {
|
||||||
|
_isSending = true;
|
||||||
|
notifyListeners();
|
||||||
|
await FirebaseService.acCommandRef.set({
|
||||||
|
'command': cmd,
|
||||||
|
'value': val,
|
||||||
|
'timestamp': ServerValue.timestamp,
|
||||||
|
});
|
||||||
|
_isSending = false;
|
||||||
|
notifyListeners();
|
||||||
|
} catch (e) {
|
||||||
|
_isSending = false;
|
||||||
|
notifyListeners();
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> startConfigMode() async {
|
||||||
|
await _sendCommand('config', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> selectBrand(int index) async {
|
||||||
|
await _sendCommand('select_brand', index.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> confirm(String value) async {
|
||||||
|
await _sendCommand('confirm', value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> cancelConfig() async {
|
||||||
|
await _sendCommand('cancel_config', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> saveConfig() async {
|
||||||
|
await _sendCommand('save_config', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> clearConfig() async {
|
||||||
|
await _sendCommand('clear_config', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> startLearnMode() async {
|
||||||
|
await _sendCommand('learn', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> sendRaw() async {
|
||||||
|
await _sendCommand('sendraw', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_statusSubscription?.cancel();
|
||||||
|
_brandsSubscription?.cancel();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import '../services/auth_service.dart';
|
||||||
|
|
||||||
|
class AuthProvider extends ChangeNotifier {
|
||||||
|
final AuthService _authService = AuthService();
|
||||||
|
|
||||||
|
bool _isLoading = false;
|
||||||
|
|
||||||
|
bool get isLoading => _isLoading;
|
||||||
|
|
||||||
|
Map<String, dynamic>? userData;
|
||||||
|
|
||||||
|
// ================= LOGIN =================
|
||||||
|
|
||||||
|
Future<String?> login({
|
||||||
|
required String email,
|
||||||
|
required String password,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
_isLoading = true;
|
||||||
|
notifyListeners();
|
||||||
|
|
||||||
|
await _authService.login(email: email, password: password);
|
||||||
|
|
||||||
|
userData = await _authService.getUserData();
|
||||||
|
|
||||||
|
_isLoading = false;
|
||||||
|
notifyListeners();
|
||||||
|
|
||||||
|
return null;
|
||||||
|
} catch (e) {
|
||||||
|
_isLoading = false;
|
||||||
|
notifyListeners();
|
||||||
|
|
||||||
|
return e.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================= REGISTER =================
|
||||||
|
|
||||||
|
Future<String?> register({
|
||||||
|
required String name,
|
||||||
|
required String email,
|
||||||
|
required String password,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
_isLoading = true;
|
||||||
|
notifyListeners();
|
||||||
|
|
||||||
|
await _authService.register(name: name, email: email, password: password);
|
||||||
|
|
||||||
|
userData = await _authService.getUserData();
|
||||||
|
|
||||||
|
_isLoading = false;
|
||||||
|
notifyListeners();
|
||||||
|
|
||||||
|
return null;
|
||||||
|
} catch (e) {
|
||||||
|
_isLoading = false;
|
||||||
|
notifyListeners();
|
||||||
|
|
||||||
|
return e.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================= LOAD USER =================
|
||||||
|
|
||||||
|
Future<void> loadUser() async {
|
||||||
|
userData = await _authService.getUserData();
|
||||||
|
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================= LOGOUT =================
|
||||||
|
|
||||||
|
Future<void> logout() async {
|
||||||
|
await _authService.logout();
|
||||||
|
|
||||||
|
userData = null;
|
||||||
|
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,160 @@
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue