Преглед изворни кода

fix(d2-02): 相对运动钳位改回读真实位(红线C-1)+ motorDelay透传/reset守卫/dispose日志

huangjie пре 1 дан
родитељ
комит
91afb0331b

+ 16 - 0
ivf_tl_operate_2.0/control/IvfTl.ControlHost.Tests/DebugExecuteTests.cs

@@ -68,5 +68,21 @@ namespace IvfTl.ControlHost.Tests
             Assert.True(mgr.Execute(sid, "WriteScanStep", JObject.FromObject(new { value = 300 })).Ok);
             Assert.Contains("WriteScanStep(300)", serial.Calls);
         }
+        [Fact] public void Vertical_Forward_From_RealNonZeroPos_OutOfRange_Rejected()
+        {
+            var (mgr, serial, sid) = New();
+            serial.VerPos = 120000;                 // 真机电机已在 120000(未经 MoveTo,跟踪位仍 -1)
+            var r = mgr.Execute(sid, "VerticalForward", JObject.FromObject(new { value = 10000 })); // 目标 130000>125000
+            Assert.Equal("OUT_OF_RANGE", r.Code);
+            Assert.DoesNotContain("VFwd(10000)", serial.Calls);   // 越界绝不下发
+        }
+        [Fact] public void Vertical_Forward_From_RealPos_InRange_Dispatches_And_TracksRealPos()
+        {
+            var (mgr, serial, sid) = New();
+            serial.VerPos = 90000;
+            var r = mgr.Execute(sid, "VerticalForward", JObject.FromObject(new { value = 10000 })); // 目标 100000 OK
+            Assert.True(r.Ok);
+            Assert.Contains("VFwd(10000)", serial.Calls);
+        }
     }
 }

+ 12 - 10
ivf_tl_operate_2.0/control/IvfTl.ControlHost.Tests/Fakes/FakeHardware.cs

@@ -27,16 +27,18 @@ namespace IvfTl.ControlHost.Tests.Fakes
         public bool WriteOpenVentTimeWait(int v) { Calls.Add($"WriteVent({v})"); return true; }
         public int ReadOpenVentTimeWait() { Calls.Add("ReadVent"); return 200; }
         public bool WriteLightBrightnessWait(int v) { Calls.Add($"WriteLight({v})"); return true; }
-        public bool VerticalMoveToWait(int p, int d = -1) { Calls.Add($"VMoveTo({p})"); return true; }
-        public bool VerticalForwardWait(int p, int d = -1) { Calls.Add($"VFwd({p})"); return true; }
-        public bool VerticalBackwardWait(int p, int d = -1) { Calls.Add($"VBack({p})"); return true; }
-        public bool VerticalResetWait(int d = -1) { Calls.Add("VReset"); return true; }
-        public int ReadVerticalPositionWait() => 0;
-        public bool HorizontalMoveToWait(int p, int d = -1) { Calls.Add($"HMoveTo({p})"); return true; }
-        public bool HorizontalForwardWait(int p, int d = -1) { Calls.Add($"HFwd({p})"); return true; }
-        public bool HorizontalBackwardWait(int p, int d = -1) { Calls.Add($"HBack({p})"); return true; }
-        public bool HorizontalResetWait(int d = -1) { Calls.Add("HReset"); return true; }
-        public int ReadHorizontalPositionWait() => 0;
+        public int VerPos;
+        public int HorPos;
+        public bool VerticalMoveToWait(int p, int d = -1) { Calls.Add($"VMoveTo({p})"); VerPos = p; return true; }
+        public bool VerticalForwardWait(int p, int d = -1) { Calls.Add($"VFwd({p})"); VerPos += p; return true; }
+        public bool VerticalBackwardWait(int p, int d = -1) { Calls.Add($"VBack({p})"); VerPos -= p; return true; }
+        public bool VerticalResetWait(int d = -1) { Calls.Add("VReset"); VerPos = 0; return true; }
+        public int ReadVerticalPositionWait() => VerPos;
+        public bool HorizontalMoveToWait(int p, int d = -1) { Calls.Add($"HMoveTo({p})"); HorPos = p; return true; }
+        public bool HorizontalForwardWait(int p, int d = -1) { Calls.Add($"HFwd({p})"); HorPos += p; return true; }
+        public bool HorizontalBackwardWait(int p, int d = -1) { Calls.Add($"HBack({p})"); HorPos -= p; return true; }
+        public bool HorizontalResetWait(int d = -1) { Calls.Add("HReset"); HorPos = 0; return true; }
+        public int ReadHorizontalPositionWait() => HorPos;
         public decimal TemperatureWait() { Calls.Add("Temp"); return 37.0m; }
         public decimal ShangTemperatureWait() => 37.0m;
         public decimal BoLiTemperatureWait() => 37.0m;

+ 11 - 9
ivf_tl_operate_2.0/control/ivf_tl_ControlHost/Debug/DebugSessionManager.cs

@@ -39,7 +39,7 @@ namespace IvfTl.ControlHost.Debug
         {
             if (sid != null && _sessions.TryRemove(sid, out var s))
             {
-                try { s.Lease.Dispose(); } catch { }
+                try { s.Lease.Dispose(); } catch (Exception ex) { _log($"[debug] dispose 异常 sid={sid} 舱{s.HouseSn}: {ex.Message}"); }
                 _log($"[debug] release sid={sid} 舱{s.HouseSn}");
             }
             return DebugCommandResult.Okay();
@@ -54,7 +54,7 @@ namespace IvfTl.ControlHost.Debug
                 {
                     if (_sessions.TryRemove(kv.Key, out var s))
                     {
-                        try { s.Lease.Dispose(); } catch { }
+                        try { s.Lease.Dispose(); } catch (Exception ex) { _log($"[debug] dispose 异常 sid={kv.Key} 舱{s.HouseSn}: {ex.Message}"); }
                         _log($"[debug] 会话超时自动回收 sid={kv.Key} 舱{s.HouseSn}");
                         n++;
                     }
@@ -97,10 +97,10 @@ namespace IvfTl.ControlHost.Debug
         private DebugCommandResult ExecuteMotorOrEeprom(DebugSession s, IvfTl.Hardware.ISerialChannel ser, string op, JObject args)
         {
             int Arg(string k, int def = 0) => args?[k] != null ? args[k].Value<int>() : def;
-            int delay = -1;
+            int delay = Arg("motorDelay", -1);
             switch (op)
             {
-                case "VerticalReset": { bool ok = ser.VerticalResetWait(delay); s.CurrentVer = 0; return DebugCommandResult.Okay(ok); }
+                case "VerticalReset": { bool ok = ser.VerticalResetWait(delay); if (ok) s.CurrentVer = 0; return DebugCommandResult.Okay(ok); }
                 case "VerticalMoveTo":
                 {
                     int pos = Arg("pos");
@@ -110,14 +110,15 @@ namespace IvfTl.ControlHost.Debug
                 case "VerticalForward":
                 case "VerticalBackward":
                 {
+                    // 红线钳位必须基于回读的真实物理位,不信任会话跟踪位(防真机已在高位时相对运动越红线)。
+                    int basePos = ser.ReadVerticalPositionWait();
                     int delta = Arg("value") * (op == "VerticalBackward" ? -1 : 1);
-                    int basePos = s.CurrentVer < 0 ? 0 : s.CurrentVer;
                     int target = MotorClamp.RelativeTarget(basePos, delta);
                     if (!MotorClamp.IsVerticalInRange(target)) return DebugCommandResult.Fail("OUT_OF_RANGE", $"垂直目标{target}越界");
                     bool ok = op == "VerticalBackward" ? ser.VerticalBackwardWait(Arg("value"), delay) : ser.VerticalForwardWait(Arg("value"), delay);
-                    if (ok) s.CurrentVer = target; return DebugCommandResult.Okay(ok);
+                    if (ok) s.CurrentVer = ser.ReadVerticalPositionWait(); return DebugCommandResult.Okay(ok);
                 }
-                case "HorizontalReset": { bool ok = ser.HorizontalResetWait(delay); s.CurrentHor = 0; return DebugCommandResult.Okay(ok); }
+                case "HorizontalReset": { bool ok = ser.HorizontalResetWait(delay); if (ok) s.CurrentHor = 0; return DebugCommandResult.Okay(ok); }
                 case "HorizontalMoveTo":
                 {
                     int pos = Arg("pos");
@@ -127,12 +128,13 @@ namespace IvfTl.ControlHost.Debug
                 case "HorizontalForward":
                 case "HorizontalBackward":
                 {
+                    // 红线钳位必须基于回读的真实物理位,不信任会话跟踪位。
+                    int basePos = ser.ReadHorizontalPositionWait();
                     int delta = Arg("value") * (op == "HorizontalBackward" ? -1 : 1);
-                    int basePos = s.CurrentHor < 0 ? 0 : s.CurrentHor;
                     int target = MotorClamp.RelativeTarget(basePos, delta);
                     if (!MotorClamp.IsHorizontalInRange(target)) return DebugCommandResult.Fail("OUT_OF_RANGE", $"水平目标{target}越界");
                     bool ok = op == "HorizontalBackward" ? ser.HorizontalBackwardWait(Arg("value"), delay) : ser.HorizontalForwardWait(Arg("value"), delay);
-                    if (ok) s.CurrentHor = target; return DebugCommandResult.Okay(ok);
+                    if (ok) s.CurrentHor = ser.ReadHorizontalPositionWait(); return DebugCommandResult.Okay(ok);
                 }
                 case "WriteScanStep": return DebugCommandResult.Okay(ser.WriteScanStepWait(Arg("value")));
                 case "WriteOpenIntakeTime": return DebugCommandResult.Okay(ser.WriteOpenIntakeTimeWait(Arg("value")));