mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2026-06-15 20:22:00 +08:00
feat: 初步增加 Windows 支持
This commit is contained in:
261
src/web/handlers/setup.rs
Normal file
261
src/web/handlers/setup.rs
Normal file
@@ -0,0 +1,261 @@
|
||||
use super::*;
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct SetupStatus {
|
||||
pub initialized: bool,
|
||||
pub needs_setup: bool,
|
||||
pub platform: PlatformCapabilities,
|
||||
}
|
||||
|
||||
pub async fn setup_status(State(state): State<Arc<AppState>>) -> Json<SetupStatus> {
|
||||
let initialized = state.config.is_initialized();
|
||||
Json(SetupStatus {
|
||||
initialized,
|
||||
needs_setup: !initialized,
|
||||
platform: PlatformCapabilities::current(),
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct SetupRequest {
|
||||
// Account settings
|
||||
pub username: String,
|
||||
pub password: String,
|
||||
// Video settings
|
||||
pub video_device: Option<String>,
|
||||
pub video_format: Option<String>,
|
||||
pub video_width: Option<u32>,
|
||||
pub video_height: Option<u32>,
|
||||
pub video_fps: Option<u32>,
|
||||
// Audio settings
|
||||
pub audio_device: Option<String>,
|
||||
// HID settings
|
||||
pub hid_backend: Option<String>,
|
||||
pub hid_ch9329_port: Option<String>,
|
||||
pub hid_ch9329_baudrate: Option<u32>,
|
||||
pub hid_otg_udc: Option<String>,
|
||||
pub hid_otg_profile: Option<String>,
|
||||
pub hid_otg_endpoint_budget: Option<crate::config::OtgEndpointBudget>,
|
||||
pub hid_otg_keyboard_leds: Option<bool>,
|
||||
pub msd_enabled: Option<bool>,
|
||||
// Extension settings
|
||||
pub ttyd_enabled: Option<bool>,
|
||||
pub rustdesk_enabled: Option<bool>,
|
||||
}
|
||||
|
||||
pub async fn setup_init(
|
||||
State(state): State<Arc<AppState>>,
|
||||
Json(req): Json<SetupRequest>,
|
||||
) -> Result<Json<LoginResponse>> {
|
||||
// Check if already initialized
|
||||
if state.config.is_initialized() {
|
||||
return Err(AppError::BadRequest("Already initialized".to_string()));
|
||||
}
|
||||
|
||||
// Validate username
|
||||
if req.username.len() < 2 {
|
||||
return Err(AppError::BadRequest(
|
||||
"Username must be at least 2 characters".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
// Validate password
|
||||
if req.password.len() < 4 {
|
||||
return Err(AppError::BadRequest(
|
||||
"Password must be at least 4 characters".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
// Create single system user
|
||||
state
|
||||
.users
|
||||
.create_first_user(&req.username, &req.password)
|
||||
.await?;
|
||||
|
||||
// Update config
|
||||
state
|
||||
.config
|
||||
.update(|config| {
|
||||
config.initialized = true;
|
||||
|
||||
// Video settings
|
||||
if let Some(device) = req.video_device.clone() {
|
||||
config.video.device = Some(device);
|
||||
}
|
||||
if let Some(format) = req.video_format.clone() {
|
||||
config.video.format = Some(format);
|
||||
}
|
||||
if let Some(width) = req.video_width {
|
||||
config.video.width = width;
|
||||
}
|
||||
if let Some(height) = req.video_height {
|
||||
config.video.height = height;
|
||||
}
|
||||
if let Some(fps) = req.video_fps {
|
||||
config.video.fps = fps;
|
||||
}
|
||||
|
||||
// Audio settings
|
||||
if let Some(device) = req.audio_device.clone() {
|
||||
config.audio.device = device;
|
||||
config.audio.enabled = true;
|
||||
}
|
||||
|
||||
// HID settings
|
||||
if let Some(backend) = req.hid_backend.clone() {
|
||||
config.hid.backend = match backend.as_str() {
|
||||
"otg" => crate::config::HidBackend::Otg,
|
||||
"ch9329" => crate::config::HidBackend::Ch9329,
|
||||
_ => crate::config::HidBackend::None,
|
||||
};
|
||||
}
|
||||
if let Some(port) = req.hid_ch9329_port.clone() {
|
||||
config.hid.ch9329_port = port;
|
||||
}
|
||||
if let Some(baudrate) = req.hid_ch9329_baudrate {
|
||||
config.hid.ch9329_baudrate = baudrate;
|
||||
}
|
||||
if let Some(udc) = req.hid_otg_udc.clone() {
|
||||
config.hid.otg_udc = Some(udc);
|
||||
}
|
||||
if let Some(profile) = req.hid_otg_profile.clone() {
|
||||
if let Some(parsed) = crate::config::OtgHidProfile::from_legacy_str(&profile) {
|
||||
config.hid.otg_profile = parsed;
|
||||
}
|
||||
}
|
||||
if let Some(budget) = req.hid_otg_endpoint_budget {
|
||||
config.hid.otg_endpoint_budget = budget;
|
||||
}
|
||||
if let Some(enabled) = req.hid_otg_keyboard_leds {
|
||||
config.hid.otg_keyboard_leds = enabled;
|
||||
}
|
||||
if let Some(enabled) = req.msd_enabled {
|
||||
config.msd.enabled = enabled;
|
||||
}
|
||||
|
||||
// Extension settings
|
||||
if let Some(enabled) = req.ttyd_enabled {
|
||||
config.extensions.ttyd.enabled = enabled;
|
||||
}
|
||||
if let Some(enabled) = req.rustdesk_enabled {
|
||||
config.rustdesk.enabled = enabled;
|
||||
}
|
||||
})
|
||||
.await?;
|
||||
|
||||
// Get updated config for HID reload
|
||||
let new_config = state.config.get();
|
||||
|
||||
#[cfg(unix)]
|
||||
{
|
||||
if let Err(e) = state
|
||||
.otg_service
|
||||
.apply_config(&new_config.hid, &new_config.msd)
|
||||
.await
|
||||
{
|
||||
tracing::warn!("Failed to apply OTG config during setup: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
tracing::info!(
|
||||
"Extension config after save: ttyd.enabled={}, rustdesk.enabled={}",
|
||||
new_config.extensions.ttyd.enabled,
|
||||
new_config.rustdesk.enabled
|
||||
);
|
||||
|
||||
// Initialize HID backend with new config
|
||||
let new_hid_backend = match new_config.hid.backend {
|
||||
crate::config::HidBackend::Otg => crate::hid::HidBackendType::Otg,
|
||||
crate::config::HidBackend::Ch9329 => crate::hid::HidBackendType::Ch9329 {
|
||||
port: new_config.hid.ch9329_port.clone(),
|
||||
baud_rate: new_config.hid.ch9329_baudrate,
|
||||
},
|
||||
crate::config::HidBackend::None => crate::hid::HidBackendType::None,
|
||||
};
|
||||
|
||||
// Reload HID backend
|
||||
if let Err(e) = state.hid.reload(new_hid_backend).await {
|
||||
tracing::warn!("Failed to initialize HID backend during setup: {}", e);
|
||||
// Don't fail setup, just warn
|
||||
} else {
|
||||
tracing::info!("HID backend initialized: {:?}", new_config.hid.backend);
|
||||
}
|
||||
|
||||
// Start extensions if enabled
|
||||
if new_config.extensions.ttyd.enabled {
|
||||
if let Err(e) = state
|
||||
.extensions
|
||||
.start(crate::extensions::ExtensionId::Ttyd, &new_config.extensions)
|
||||
.await
|
||||
{
|
||||
tracing::warn!("Failed to start ttyd during setup: {}", e);
|
||||
} else {
|
||||
tracing::info!("ttyd started during setup");
|
||||
}
|
||||
}
|
||||
|
||||
// Start RustDesk if enabled
|
||||
if new_config.rustdesk.enabled {
|
||||
let empty_config = crate::rustdesk::config::RustDeskConfig::default();
|
||||
if let Err(e) = config::apply::apply_rustdesk_config(
|
||||
&state,
|
||||
&empty_config,
|
||||
&new_config.rustdesk,
|
||||
ConfigApplyOptions::default(),
|
||||
)
|
||||
.await
|
||||
{
|
||||
tracing::warn!("Failed to start RustDesk during setup: {}", e);
|
||||
} else {
|
||||
tracing::info!("RustDesk started during setup");
|
||||
}
|
||||
}
|
||||
|
||||
// Start RTSP if enabled
|
||||
if new_config.rtsp.enabled {
|
||||
let empty_config = crate::config::RtspConfig::default();
|
||||
if let Err(e) = config::apply::apply_rtsp_config(
|
||||
&state,
|
||||
&empty_config,
|
||||
&new_config.rtsp,
|
||||
ConfigApplyOptions::default(),
|
||||
)
|
||||
.await
|
||||
{
|
||||
tracing::warn!("Failed to start RTSP during setup: {}", e);
|
||||
} else {
|
||||
tracing::info!("RTSP started during setup");
|
||||
}
|
||||
}
|
||||
|
||||
// Start audio streaming if audio device was selected during setup
|
||||
if new_config.audio.enabled {
|
||||
let audio_config = crate::audio::AudioControllerConfig {
|
||||
enabled: true,
|
||||
device: new_config.audio.device.clone(),
|
||||
quality: new_config
|
||||
.audio
|
||||
.quality
|
||||
.parse::<crate::audio::AudioQuality>()?,
|
||||
};
|
||||
if let Err(e) = state.audio.update_config(audio_config).await {
|
||||
tracing::warn!("Failed to start audio during setup: {}", e);
|
||||
} else {
|
||||
tracing::info!(
|
||||
"Audio started during setup: device={}",
|
||||
new_config.audio.device
|
||||
);
|
||||
}
|
||||
// Also enable WebRTC audio
|
||||
if let Err(e) = state.stream_manager.set_webrtc_audio_enabled(true).await {
|
||||
tracing::warn!("Failed to enable WebRTC audio during setup: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
tracing::info!("System initialized successfully");
|
||||
|
||||
Ok(Json(LoginResponse {
|
||||
success: true,
|
||||
message: Some("Setup completed".to_string()),
|
||||
}))
|
||||
}
|
||||
Reference in New Issue
Block a user