浏览代码

feat(d2-02): 调试页预览接入 MjpegStreamClient——OpenVideo/CloseVideo 改连/断 MJPEG 流+<Image>显示+断开提示;每次 new 实例;VM 加 CurrentSessionId;ControlClient.BaseUrl 提 public

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
huangjie 1 天之前
父节点
当前提交
02a043a5a8

+ 1 - 1
ivf_tl_operate_2.0/ivf_tl_Operate/Helpers/ControlClient.cs

@@ -20,7 +20,7 @@ namespace ivf_tl_Operate.Helpers
         public static int Port =>
             int.TryParse(ConfigurationManager.AppSettings["controlPort"], out var p) ? p : 38080;
 
-        private static string BaseUrl => $"http://127.0.0.1:{Port}";
+        public static string BaseUrl => $"http://127.0.0.1:{Port}";
 
         /// <summary>GET /status → 取回 control 的 MonitorSnapshot(失败返回 null,监控页据此显示"未托管")。</summary>
         public static MonitorSnapshot GetStatusSnapshot()

+ 4 - 1
ivf_tl_operate_2.0/ivf_tl_Operate/View/HouseDebugPageView.xaml

@@ -286,7 +286,10 @@
 
             <StackPanel Grid.Row="5" Orientation="Horizontal" HorizontalAlignment="Center" >
                 <!--<Rectangle Visibility="Hidden" Fill="Black" Width="800" Height="600"/>-->
-                <Border Width="800" Height="600" BorderBrush="Black" BorderThickness="1"/>
+                <Border Width="800" Height="600" BorderBrush="Black" BorderThickness="1">
+                    <!-- D2-02 第二阶段:MJPEG 预览画面(替代原贴窗口句柄方式) -->
+                    <Image x:Name="_previewImage" Width="800" Height="600" Stretch="Uniform"/>
+                </Border>
                 <StackPanel x:Name="_stackPanel2" VerticalAlignment="Center" Margin="150 0 0 0" IsEnabled="False">
                     <customControl:ButtonCornerRadius Click="OpenVideo_Click" Content="{DynamicResource C0079}" FontSize="24" Margin="0 0 0 100"  Width="218" Height="250" CornerRadius="20" Background="#BFD87D" EnabledBackground="#bdbdbd"  BorderThickness="0"/>
                     <customControl:ButtonCornerRadius Click="CloseVideo_Click"  Content="{DynamicResource C0080}" FontSize="24"   Width="218" Height="250" CornerRadius="20" Background="#BFD87D" EnabledBackground="#bdbdbd"  BorderThickness="0"/>

+ 24 - 23
ivf_tl_operate_2.0/ivf_tl_Operate/View/HouseDebugPageView.xaml.cs

@@ -1,6 +1,7 @@
 using ivf_tl_CustomControls;
 using ivf_tl_Entity.CameraEntitys;
 using ivf_tl_Entity.GlobalEnums;
+using ivf_tl_Operate.Debug;
 using ivf_tl_Operate.ViewModel;
 using ivf_tl_Operate.Windows;
 using Newtonsoft.Json.Linq;
@@ -41,6 +42,9 @@ namespace ivf_tl_Operate.View
         /// </summary>
         private bool isOpen = false;
 
+        /// <summary>D2-02 第二阶段:MJPEG 预览客户端(一次性,每次开预览 new 新实例)。</summary>
+        private MjpegStreamClient _mjpeg;
+
         private object locker = new object();
 
         //#bdbdbd  #bfd87d
@@ -206,19 +210,21 @@ namespace ivf_tl_Operate.View
         {
             try
             {
-                if (isOpen)
-                {
-                    AddMessageInfo($"图像已打开");
-                    return;
-                }
-                IntPtr hwnd = ((System.Windows.Interop.HwndSource)PresentationSource.FromVisual(AppData.Instance.MainWindow)).Handle;
-                //var a = vm.camera.Usb2Start(hwnd, 328, 865, 800, 600);
-                var a = vm.StartPreview(hwnd, 328, 805, 800, 600);
-                AddMessageInfo($"图像打开结果:{a}[注:0表示成功]");
-                if (a == 0)
+                if (isOpen) { AddMessageInfo($"图像已打开"); return; }
+                string sessionId = vm.CurrentSessionId;
+                if (string.IsNullOrEmpty(sessionId)) { AddMessageInfo("未借用会话,无法预览(请先初始化)"); return; }
+
+                // 每次开预览 new 新实例(MjpegStreamClient 一次性,不可复用)
+                _mjpeg = new MjpegStreamClient(ivf_tl_Operate.Helpers.ControlClient.BaseUrl);
+                _mjpeg.FrameReceived += img => Dispatcher.Invoke(() => { _previewImage.Source = img; });
+                _mjpeg.Stopped += reason => Dispatcher.Invoke(() =>
                 {
-                    isOpen = true;
-                }
+                    isOpen = false;
+                    AddMessageInfo($"⚠ {reason}");   // 明确提示操作人员手动重开(不自动重连)
+                });
+                _mjpeg.Start(sessionId);
+                isOpen = true;
+                AddMessageInfo("图像已打开(MJPEG 实时预览)");
             }
             catch (Exception ex)
             {
@@ -231,17 +237,12 @@ namespace ivf_tl_Operate.View
         {
             try
             {
-                if (!isOpen)
-                {
-                    AddMessageInfo($"图像未打开,无需关闭");
-                    return;
-                }
-                var a = vm.StopPreview();
-                AddMessageInfo($"图像关闭结果:{a}[注:0表示成功]");
-                if (a == 0)
-                {
-                    isOpen = false;
-                }
+                if (!isOpen) { AddMessageInfo($"图像未打开,无需关闭"); return; }
+                _mjpeg?.Stop();
+                _mjpeg = null;   // 丢弃实例(一次性,下次开预览 new 新的)
+                Dispatcher.Invoke(() => { _previewImage.Source = null; });
+                isOpen = false;
+                AddMessageInfo("图像已关闭");
             }
             catch (Exception ex)
             {

+ 3 - 0
ivf_tl_operate_2.0/ivf_tl_Operate/ViewModel/HouseDebugPageViewModel.cs

@@ -61,6 +61,9 @@ namespace ivf_tl_Operate.ViewModel
         /// </summary>
         public int CurrentHouseId { get; set; } = 1;
 
+        /// <summary>当前借用会话 id(D2-02 第三阶段 acquire 时赋值;第二阶段预览用)。</summary>
+        public string CurrentSessionId { get; set; }
+
         /// <summary>
         /// 当前ccdID
         /// </summary>