build: 控制端功能移植到flutter版本
This commit is contained in:
117
webrtc_controller_flutter/lib/controller/remote_controller.dart
Normal file
117
webrtc_controller_flutter/lib/controller/remote_controller.dart
Normal file
@@ -0,0 +1,117 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter_webrtc/flutter_webrtc.dart';
|
||||
|
||||
import '../models/signal_message.dart';
|
||||
import '../signaling/signaling_client.dart';
|
||||
import '../webrtc/webrtc_controller.dart';
|
||||
|
||||
/// 控制端编排器:组合信令客户端与 WebRTC 控制器,
|
||||
/// 对外暴露连接/断开/发送指令等高层接口(对应 Android 端 MainActivity 的流程)。
|
||||
class RemoteController {
|
||||
final String serverUrl;
|
||||
final String deviceId;
|
||||
final String targetDeviceId;
|
||||
|
||||
late final SignalingClient _signaling;
|
||||
WebRtcController? _webRtc;
|
||||
Timer? _statsTimer;
|
||||
|
||||
/// 信令状态变化(如“正在连接…”、“已连接…”)。
|
||||
void Function(String status)? onStatusChanged;
|
||||
|
||||
/// WebRTC 连接建立(可开始远程控制)。
|
||||
void Function()? onConnectionEstablished;
|
||||
|
||||
/// 连接断开。
|
||||
void Function()? onDisconnected;
|
||||
|
||||
/// 远端视频渲染器就绪。
|
||||
void Function(RTCVideoRenderer renderer)? onRemoteStream;
|
||||
|
||||
/// 统计信息刷新(每秒一次)。
|
||||
void Function(String stats)? onStats;
|
||||
|
||||
RemoteController({
|
||||
required this.serverUrl,
|
||||
required this.deviceId,
|
||||
required this.targetDeviceId,
|
||||
});
|
||||
|
||||
/// 发起连接:先连接信令服务器,成功后建立 WebRTC 并创建 Offer。
|
||||
void connect() {
|
||||
onStatusChanged?.call('状态: 正在连接信令服务器...');
|
||||
|
||||
_signaling = SignalingClient(serverUrl: serverUrl, deviceId: deviceId);
|
||||
_signaling.onConnected = () {
|
||||
onStatusChanged?.call('状态: 已连接信令服务器,正在发起连接...');
|
||||
_initWebRtc();
|
||||
};
|
||||
_signaling.onMessage = _handleSignalMessage;
|
||||
_signaling.onDisconnected = () {
|
||||
onStatusChanged?.call('状态: 已断开连接');
|
||||
onDisconnected?.call();
|
||||
};
|
||||
_signaling.onError = (error) {
|
||||
onStatusChanged?.call('状态: 连接错误 - $error');
|
||||
};
|
||||
_signaling.connect();
|
||||
}
|
||||
|
||||
void _initWebRtc() {
|
||||
_webRtc = WebRtcController(
|
||||
signaling: _signaling,
|
||||
deviceId: deviceId,
|
||||
targetDeviceId: targetDeviceId,
|
||||
);
|
||||
_webRtc!.onConnectionEstablished = () {
|
||||
onConnectionEstablished?.call();
|
||||
_startStats();
|
||||
};
|
||||
_webRtc!.onDisconnected = () {
|
||||
onDisconnected?.call();
|
||||
};
|
||||
_webRtc!.onRemoteStream = (renderer) => onRemoteStream?.call(renderer);
|
||||
_webRtc!.initialize().catchError((e) {
|
||||
onStatusChanged?.call('状态: 连接失败 - $e');
|
||||
});
|
||||
}
|
||||
|
||||
void _handleSignalMessage(SignalMessage message) {
|
||||
switch (message.type?.toUpperCase()) {
|
||||
case 'ANSWER':
|
||||
final payload = jsonDecode(message.payload!) as Map<String, dynamic>;
|
||||
_webRtc?.handleAnswer(payload['sdp'] as String);
|
||||
break;
|
||||
case 'ICE_CANDIDATE':
|
||||
final payload = jsonDecode(message.payload!) as Map<String, dynamic>;
|
||||
_webRtc?.handleIceCandidate(payload);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void _startStats() {
|
||||
_statsTimer?.cancel();
|
||||
_statsTimer = Timer.periodic(const Duration(seconds: 1), (_) async {
|
||||
final text = await _webRtc?.getStatsText();
|
||||
if (text != null && text.isNotEmpty) {
|
||||
onStats?.call(text);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// 发送控制指令(JSON 字符串)。
|
||||
void sendControlCommand(String commandJson) {
|
||||
_webRtc?.sendControlCommand(commandJson);
|
||||
}
|
||||
|
||||
/// 断开连接并释放资源。
|
||||
Future<void> disconnect() async {
|
||||
_statsTimer?.cancel();
|
||||
_statsTimer = null;
|
||||
await _webRtc?.close();
|
||||
_webRtc = null;
|
||||
_signaling.disconnect();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user