159 lines
4.5 KiB
Dart
159 lines
4.5 KiB
Dart
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();
|
|
}
|
|
}
|