137 lines
4.0 KiB
Dart
137 lines
4.0 KiB
Dart
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();
|
|
}
|
|
}
|