fix:改进atx usb 继电器适配;修复 webrtc 无法建立连接问题;网页样式优化

This commit is contained in:
mofeng-git
2026-05-05 00:52:16 +08:00
parent 6723f432a3
commit c27d3a6703
27 changed files with 1388 additions and 709 deletions

View File

@@ -34,7 +34,7 @@ pub async fn update_stream_config(
&state,
&old_stream_config,
&new_stream_config,
ConfigApplyOptions::forced(),
ConfigApplyOptions::default(),
)
.await?;

View File

@@ -509,6 +509,12 @@ impl AtxConfigUpdate {
}
crate::atx::AtxDriverType::UsbRelay => {
if let Some(pin) = key.pin {
if pin == 0 {
return Err(AppError::BadRequest(format!(
"{} USB relay channel must be 1-based (>= 1)",
name
)));
}
if pin > u8::MAX as u32 {
return Err(AppError::BadRequest(format!(
"{} USB relay channel must be <= {}",
@@ -516,6 +522,12 @@ impl AtxConfigUpdate {
u8::MAX
)));
}
if pin > 8 {
return Err(AppError::BadRequest(format!(
"{} USB HID relay channel must be <= 8",
name
)));
}
}
}
crate::atx::AtxDriverType::Gpio | crate::atx::AtxDriverType::None => {}
@@ -551,6 +563,12 @@ impl AtxConfigUpdate {
}
}
crate::atx::AtxDriverType::UsbRelay => {
if key.pin == 0 {
return Err(AppError::BadRequest(format!(
"{} USB relay channel must be 1-based (>= 1)",
name
)));
}
if key.pin > u8::MAX as u32 {
return Err(AppError::BadRequest(format!(
"{} USB relay channel must be <= {}",
@@ -558,6 +576,12 @@ impl AtxConfigUpdate {
u8::MAX
)));
}
if key.pin > 8 {
return Err(AppError::BadRequest(format!(
"{} USB HID relay channel must be <= 8",
name
)));
}
}
crate::atx::AtxDriverType::Gpio | crate::atx::AtxDriverType::None => {}
}

View File

@@ -1493,12 +1493,8 @@ pub async fn mjpeg_stream(
handler.clone(),
));
// Use bounded channel (capacity=1) to implement backpressure
// This ensures record_frame_sent() is only called when the previous frame
// has been successfully consumed by the HTTP client
let (tx, mut rx) = tokio::sync::mpsc::channel::<bytes::Bytes>(1);
// Spawn background task to send frames to channel
let guard_clone = guard.clone();
let handler_clone = handler.clone();
tokio::spawn(async move {
@@ -1593,20 +1589,19 @@ pub async fn mjpeg_stream(
}
}
// Guard is automatically dropped here
});
// Create stream that receives from channel
// Record FPS after yield - this is closer to actual TCP send than tx.send()
// Create stream that receives from channel and forwards to the HTTP
// body. Record FPS *before* yield so the final frame of a session
// still gets counted (after-yield code in async_stream! only runs
// when the consumer polls again, which never happens for the last
// frame of a closing connection).
let handler_for_stream = handler.clone();
let guard_for_stream = guard.clone();
let body_stream = async_stream::stream! {
// Consume from channel - this drives the backpressure
while let Some(data) = rx.recv().await {
yield Ok::<bytes::Bytes, std::io::Error>(data);
// Record FPS after yield - data has been handed to Axum/hyper
// This is closer to actual TCP send than recording at tx.send()
handler_for_stream.record_frame_sent(guard_for_stream.id());
yield Ok::<bytes::Bytes, std::io::Error>(data);
}
};