using System;
using System.Threading;
using IvfTl.Hardware.HilTests.Infrastructure;
using IvfTl.Hardware.Impl;
using Xunit;
using Xunit.Abstractions;
namespace IvfTl.Hardware.HilTests
{
///
/// M-01/02/03 防回归:写命令(排气阀时间/灯光亮度)真下发到下位机,读回随写变化,写后立即恢复原值(非破坏)。
/// 安全口径:默认 Skip(零写入);仅环境变量 HIL_ALLOW_WRITE=1 才执行。全程仅 EEPROM,无电机。
///
[Collection("HIL")]
public class EepromWriteHilTests
{
private readonly HardwareRigFixture _rig;
private readonly ITestOutputHelper _out;
public EepromWriteHilTests(HardwareRigFixture rig, ITestOutputHelper o) { _rig = rig; _out = o; }
private static bool WriteAllowed =>
Environment.GetEnvironmentVariable("HIL_ALLOW_WRITE") == "1";
[SkippableFact]
public void WriteVentTime_RoundTrips_AndRestoresOriginal()
{
Skip.IfNot(WriteAllowed, "写路径默认关闭;设 HIL_ALLOW_WRITE=1 才跑(写后立即恢复原值)");
RoundTrip("排气阀时间(M-01写/M-02读)",
ch => ch.ReadOpenVentTimeWait(), (ch, v) => ch.WriteOpenVentTimeWait(v));
}
[SkippableFact]
public void WriteLightBrightness_RoundTrips_AndRestoresOriginal()
{
Skip.IfNot(WriteAllowed, "写路径默认关闭;设 HIL_ALLOW_WRITE=1 才跑(写后立即恢复原值)");
RoundTrip("灯光亮度(M-03写)",
ch => ch.ReadLightBrightnessWait(), (ch, v) => ch.WriteLightBrightnessWait(v));
}
private void RoundTrip(string label, Func read, Action write)
{
Skip.If(_rig.FirstChamberWithWells() == null, "无响应真舱:无硬件 / control 正占用串口 / 未连接");
// 逐舱(排除舱11)找到第一个能读到该项的真舱再验:不同舱配置不同 E方,
// 单一固定舱可能无此项(如灯光),逐舱试避免漏验该命令(对齐原 harness 取证逻辑)。
foreach (var chamber in _rig.Chambers)
{
if (chamber.HouseSn == 11) continue; // 缓冲瓶/总控,无舱室排气阀/灯光
SerialChannelImpl ch = null;
try
{
ch = new SerialChannelImpl(0, chamber.Port);
if (!ch.Open()) continue;
// 读前丢弃一帧 + 间隔排空(隔离任何尾噪声),拿稳定原值。
int ReadStable()
{
try { read(ch); } catch { }
Thread.Sleep(700);
int a = read(ch);
Thread.Sleep(700);
return a;
}
int v0 = ReadStable();
if (v0 < 0) { _out.WriteLine($"[{label}] 舱{chamber.HouseSn} 无此项(读={v0}),试下一舱"); continue; }
_out.WriteLine($"[{label}] 舱{chamber.HouseSn} 原值 V0={v0}");
int target = v0 + 1;
write(ch, target); Thread.Sleep(700);
int v1 = ReadStable();
_out.WriteLine($"[{label}] 写 {target} 后读回={v1}");
write(ch, v0); Thread.Sleep(700); // 恢复原值
int v2 = ReadStable();
_out.WriteLine($"[{label}] 写回 {v0} 后读回={v2}");
Assert.Equal(target, v1); // 写真下发:读回随写变化
Assert.Equal(v0, v2); // 已恢复原值:非破坏
return; // 已在该舱取得证据
}
finally { try { ch?.Close(); } catch { } }
}
Skip.If(true, $"[{label}] 所有真舱均无此项,无法取证(非失败)");
}
}
}