Files
ShowenV2/clients/flutter/lib/providers/wifi_provider.dart
showen bff9ec535d feat: Flutter 客户端 App + Web UI APK 下载入口
- 新增 Flutter 跨平台客户端项目 (clients/flutter/)
  - 29 个 Dart 文件: 服务层/状态管理/5个页面/BLE配网
  - BLE 蓝牙配网: 扫描设备、写入WiFi凭据、配网状态监听
  - HTTP API 客户端: 覆盖全部端点 (播放/场景/WiFi/视频/配置/文件/插件)
  - WebSocket 实时通信: 事件流 + 自动重连
  - 暗色主题 Material 3 UI, 中文界面
  - Android 配置: minSdkVersion 21, BLE/网络权限
  - PRD 产品需求文档 + 开发任务看板
- Web UI 添加 APK 下载入口 (routes.rs)
  - 下载弹窗 + 二维码 + /download/{filename} 静态文件路由
- BLE 插件增加自动重连循环 (ble/mod.rs)
- BLE 默认设备名修正为 'Showen' (config.rs)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 02:09:52 +08:00

133 lines
3.3 KiB
Dart

import 'dart:async';
import 'package:flutter/foundation.dart';
import '../models/wifi_network.dart';
import '../models/wifi_status.dart';
import '../services/http_api_service.dart';
import '../services/web_socket_service.dart';
class WifiProvider extends ChangeNotifier {
WifiProvider({
required HttpApiService httpApiService,
required WebSocketService webSocketService,
}) : _httpApiService = httpApiService,
_webSocketService = webSocketService {
_wifiSubscription = _webSocketService.onWifiUpdate.listen((payload) {
_status = WifiStatus.fromJson(payload);
notifyListeners();
});
}
final HttpApiService _httpApiService;
final WebSocketService _webSocketService;
late final StreamSubscription<Map<String, dynamic>> _wifiSubscription;
WifiStatus _status = WifiStatus.disconnected();
List<WifiNetwork> _networks = const <WifiNetwork>[];
bool _isLoading = false;
String? _errorMessage;
bool _hotspotEnabled = false;
WifiStatus get status => _status;
List<WifiNetwork> get networks => _networks;
bool get isLoading => _isLoading;
String? get errorMessage => _errorMessage;
bool get hotspotEnabled => _hotspotEnabled;
Future<void> bootstrap() async {
_setLoading(true);
try {
final results = await Future.wait<dynamic>([
_httpApiService.getWifiStatus(),
_httpApiService.scanWifi(),
]);
_status = results[0] as WifiStatus;
_networks = results[1] as List<WifiNetwork>;
_errorMessage = null;
} catch (error) {
_errorMessage = error.toString();
} finally {
_setLoading(false);
}
}
Future<void> refreshStatus() async {
try {
_status = await _httpApiService.getWifiStatus();
notifyListeners();
} catch (error) {
_errorMessage = error.toString();
notifyListeners();
}
}
Future<void> scanNetworks() async {
_setLoading(true);
try {
_networks = await _httpApiService.scanWifi();
_errorMessage = null;
} catch (error) {
_errorMessage = error.toString();
} finally {
_setLoading(false);
}
}
Future<void> connect({required String ssid, required String password}) async {
_setLoading(true);
try {
await _httpApiService.connectWifi(ssid, password);
await refreshStatus();
_hotspotEnabled = false;
_errorMessage = null;
} catch (error) {
_errorMessage = error.toString();
notifyListeners();
} finally {
_setLoading(false);
}
}
Future<void> startHotspot({String? ssid, String? password}) async {
_setLoading(true);
try {
await _httpApiService.startAP(ssid, password);
_hotspotEnabled = true;
_errorMessage = null;
notifyListeners();
} catch (error) {
_errorMessage = error.toString();
notifyListeners();
} finally {
_setLoading(false);
}
}
Future<void> stopHotspot() async {
_setLoading(true);
try {
await _httpApiService.stopAP();
_hotspotEnabled = false;
_errorMessage = null;
notifyListeners();
} catch (error) {
_errorMessage = error.toString();
notifyListeners();
} finally {
_setLoading(false);
}
}
void _setLoading(bool value) {
_isLoading = value;
notifyListeners();
}
@override
void dispose() {
unawaited(_wifiSubscription.cancel());
super.dispose();
}
}