using Google.Protobuf.WellKnownTypes;
using ivf_tl_Com;
using IvfTl.Control.Entity.DTO;
using IvfTl.Control.Entity.DTO.ApiRequestDTO;
using IvfTl.Control.Entity.DTO.ControllerResults;
using IvfTl.Control.Entity.GlobalEntitys;
using IvfTl.Control.Entity.GlobalEnums;
using IvfTl.Control.Entity.InitEntitys;
using ivf_tl_UtilHelper;
using Newtonsoft.Json;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
namespace ivf_tl_Control
{
public class StartMain
{
AppData AppData { get; set; }
public int CamNum { get; set; } = 0;
public StartMain()
{
//HouseBin houseBin = new HouseBin();
//houseBin.ComBin._channel.ErrorLogEvent += AppData.logControl.TLLog;
//houseBin.ComBin._channel.ExceptionLogEvent += AppData.logControl.ExceptionLog;
//houseBin.ComBin._channel.CommandLogEvent += AppData.logControl.HouseLog;
}
public string StartRun()
{
try
{
string errorInfo = "";
AppData = AppData.Instance;
AppData.LogService.TLLog($"程序开始启动", LogEnum.RunRecord);
var initTLResult = InitTL(ref errorInfo);
if (!string.IsNullOrEmpty(errorInfo)) return errorInfo;
if (errorInfo == "结束") return errorInfo;
AppData.TLSetting = initTLResult.Item1.TLSetting;
PathHelper.pan = initTLResult.Item1.TLSetting.tmpDir;
AppData.LogService.Pan = initTLResult.Item1.TLSetting.tmpDir;
if (!InitHouse(initTLResult.Item1, initTLResult.Item2, ref errorInfo)) return errorInfo;
// 舱室故障隔离:好舱继续后,把完整启动坏舱清单(扫口期 + InitHouse 构造期)经现有 reportAlarm
// 报警闭环上报一次(alarm 表/双端列表/短信电话/可消警);失败不影响启动。
try { AppData.ReportStartupFaults(); } catch { }
AppData.StartAsync().Wait();
return null;
}
catch (Exception ex)
{
AppData.LogService.ExceptionLog(ex, "仪器初始化", null, LogEnum.RunException);
return ex.Message;
}
}
///
/// TL数据初始化
///
///
public (TLInitControllerResult, List) InitTL(ref string errora)
{
try
{
SerialBin serialBin = new SerialBin();
serialBin.TLLogEvent += AppData.LogService.TLLog;
serialBin.ExceptionLogEvent += AppData.LogService.ExceptionLog;
serialBin.HouseLogEvent += AppData.LogService.HouseLog;
var errorList = serialBin.UpdataCamera();
AppData.LogService.TLLog($"相机信息:{JsonConvert.SerializeObject(serialBin.CCDidSn)}", LogEnum.RunRecord);
if (errorList.Any())
{
// 舱室故障隔离:相机枚举异常不再整机中止,只记日志;受影响舱稍后在 CCDSN 配对时落坏舱被剔除。
AppData.LogService.TLLog($"相机枚举有异常(不中止,受影响舱将按坏舱剔除):{JsonConvert.SerializeObject(errorList)}", LogEnum.RunRecord);
}
CamNum = serialBin.CCDidSn.Where(x => x.Value != null).Count();
errorList = serialBin.Start();
AppData.LogService.TLLog($"仓室信息:{JsonConvert.SerializeObject(serialBin.SerialModels)}", LogEnum.RunRecord);
AppData.LogService.TLLog($"E方数据:{JsonConvert.SerializeObject(serialBin.HouseEEPROInfos)}", LogEnum.RunRecord);
if (errorList.Any())
{
// 舱室故障隔离:扫口异常不再整机中止,剔除坏舱后用好舱继续(见下方 RunnableHouses)。
AppData.LogService.TLLog($"扫口有异常(将剔除坏舱后继续):{JsonConvert.SerializeObject(errorList)}", LogEnum.RunRecord);
}
var modelCount = serialBin.SerialModels.Count;
if (modelCount != 11)
{
// M1-01 步骤2:合并后是单进程无人值守前台,不能弹模态框。
// 原 hack(MessageBox + Task.Delay(3000) + FindWindow/EnumChildWindows/SendMessage(BM_CLICK) 自动点 Yes)
// 改为静默 + 日志记录;是否继续由配置项 ContinueOnModuleCountMismatch 控制(默认继续)。
// 相关 [DllImport] 声明(FindWindow/SendMessage/EnumChildWindows/GetClassName/GetWindowText)按代码隔离原则保留为死代码,仅停止调用。
bool continueOnMismatch = true;
try
{
string cfg = System.Configuration.ConfigurationManager.AppSettings["ContinueOnModuleCountMismatch"];
if (!string.IsNullOrEmpty(cfg) && bool.TryParse(cfg, out bool parsed)) continueOnMismatch = parsed;
}
catch { /* 读取配置失败时按默认(继续)处理 */ }
AppData.LogService.TLLog($"检测到 {modelCount} 个模块(期望 11),ContinueOnModuleCountMismatch={continueOnMismatch},按配置策略{(continueOnMismatch ? "继续运行" : "中止初始化")}", LogEnum.RunRecord);
if (!continueOnMismatch)
{
errora = "结束";
return (new TLInitControllerResult(), new List());
}
}
// 舱室故障隔离:坏舱 = 故障清单中已知舱号;可跑舱 = 发现的舱 − 坏舱;仅零可跑才整机中止。
var discovered = serialBin.SerialModels.Select(x => x.houseSn).ToList();
List listIntRunHoues = StartupFaultPolicy.RunnableHouses(discovered, serialBin.Faults);
foreach (var f in serialBin.Faults) if (f.HouseSn > 0) f.Isolated = true;
AppData.StartupFaults = serialBin.Faults;
if (serialBin.Faults.Any())
AppData.LogService.TLLog($"启动坏舱清单:{JsonConvert.SerializeObject(serialBin.Faults)};可跑舱:{string.Join(",", listIntRunHoues)}", LogEnum.RunRecord);
if (StartupFaultPolicy.IsFatal(listIntRunHoues))
{
errora = "所有舱室初始化失败,无可运行舱室";
AppData.LogService.TLLog(errora, LogEnum.RunRecord);
return (new TLInitControllerResult(), new List());
}
TLInitData tLInitData = new TLInitData();
tLInitData.tlSn = $"NEO-1-{serialBin.TLNum}";
tLInitData.dayLighting = serialBin.dayLighting;
tLInitData.softwareVersion = "V2.0.0";
tLInitData.verticalMotorPulseMax = 125000;
tLInitData.houseLinkDataList = serialBin.SerialModels.OrderBy(x => x.houseSn).ToList();
foreach (var item in serialBin.HouseEEPROInfos)
{
item.tlSn = tLInitData.tlSn;
}
tLInitData.houseEEPROInitDTOList = serialBin.HouseEEPROInfos.OrderBy(x => x.houseSn).ToList();
AppData.LogService.TLLog($"【CamNum:{CamNum}】设备基础数据:{JsonConvert.SerializeObject(tLInitData)}", LogEnum.RunRecord);
TLInitControllerResult tLInitControllerResult = AppData.SerialBinController.UpdateTLInfoController(tLInitData);
if (tLInitControllerResult == null)
{
errora = "获取TL设置失败";
AppData.LogService.TLLog(errora, LogEnum.RunRecord);
return (new TLInitControllerResult(), new List());
}
//AppData.LogService.TLLog($"TL初始化结果:{JsonConvert.SerializeObject(tLInitControllerResult)};{string.Join("_", listIntRunHoues)}", LogEnum.RunRecord);
return (tLInitControllerResult, listIntRunHoues);
}
catch (Exception ex)
{
errora = ex.Message;
AppData.LogService.ExceptionLog(ex, "数据初始化", null, LogEnum.RunException);
return (new TLInitControllerResult(), new List());
}
}
///
/// 仓室初始化
///
///
///
///
///
private bool InitHouse(TLInitControllerResult tLInitControllerResult, List runHouses, ref string errorInfo)
{
try
{
TLSetting tLSetting = tLInitControllerResult.TLSetting;
AppData.TLSetting = tLSetting;
var allList = AppData.SerialBinController.GetDishAndBalanceDataController(tLSetting.tlSn);
// 舱室故障隔离:单舱构造/启动各自兜底——抛异常只登记坏舱 + 跳过该舱,绝不拖垮其余舱(spec §35)。
void Build(int sn, Action build)
{
try { build(); }
catch (Exception ex)
{
AppData.LogService.ExceptionLog(ex, $"舱{sn}构造失败(已隔离,其余舱继续)", null, LogEnum.RunException);
AppData.StartupFaults?.Add(new HouseFault
{
HouseSn = sn,
Type = HouseFaultType.InitException,
Reason = $"舱{sn}构造异常:{ex.Message}",
Stage = "舱初始化",
At = DateTime.UtcNow,
Isolated = true
});
}
}
void Start(int sn, Action start)
{
try { start(); }
catch (Exception ex)
{
AppData.LogService.ExceptionLog(ex, $"舱{sn} StartTask 失败(已隔离)", null, LogEnum.RunException);
}
}
Build(11, () =>
{
AppData.BufferBottleBin = new BufferBottleBin(tLSetting, tLInitControllerResult.HouseList.FirstOrDefault(x => x.houseSn == 11), AppData.Instance.guanbiTime);
AppData.InitBufferBottleBinEvent(AppData.BufferBottleBin);
});
Build(1, () => { AppData.HouseBin1 = new HouseBin(tLSetting, tLInitControllerResult.HouseList.FirstOrDefault(x => x.houseSn == 1), allList.Dishes.FirstOrDefault(x => x.houseSn == 1), allList.BalanceList.FirstOrDefault(x => x.houseSn == 1), tLInitControllerResult.HouseWellList.Where(x => x.houseSn == 1).ToList()); AppData.InitHouseBinEvent(AppData.HouseBin1); });
Build(2, () => { AppData.HouseBin2 = new HouseBin(tLSetting, tLInitControllerResult.HouseList.FirstOrDefault(x => x.houseSn == 2), allList.Dishes.FirstOrDefault(x => x.houseSn == 2), allList.BalanceList.FirstOrDefault(x => x.houseSn == 2), tLInitControllerResult.HouseWellList.Where(x => x.houseSn == 2).ToList()); AppData.InitHouseBinEvent(AppData.HouseBin2); });
Build(3, () => { AppData.HouseBin3 = new HouseBin(tLSetting, tLInitControllerResult.HouseList.FirstOrDefault(x => x.houseSn == 3), allList.Dishes.FirstOrDefault(x => x.houseSn == 3), allList.BalanceList.FirstOrDefault(x => x.houseSn == 3), tLInitControllerResult.HouseWellList.Where(x => x.houseSn == 3).ToList()); AppData.InitHouseBinEvent(AppData.HouseBin3); });
Build(4, () => { AppData.HouseBin4 = new HouseBin(tLSetting, tLInitControllerResult.HouseList.FirstOrDefault(x => x.houseSn == 4), allList.Dishes.FirstOrDefault(x => x.houseSn == 4), allList.BalanceList.FirstOrDefault(x => x.houseSn == 4), tLInitControllerResult.HouseWellList.Where(x => x.houseSn == 4).ToList()); AppData.InitHouseBinEvent(AppData.HouseBin4); });
Build(5, () => { AppData.HouseBin5 = new HouseBin(tLSetting, tLInitControllerResult.HouseList.FirstOrDefault(x => x.houseSn == 5), allList.Dishes.FirstOrDefault(x => x.houseSn == 5), allList.BalanceList.FirstOrDefault(x => x.houseSn == 5), tLInitControllerResult.HouseWellList.Where(x => x.houseSn == 5).ToList()); AppData.InitHouseBinEvent(AppData.HouseBin5); });
Build(6, () => { AppData.HouseBin6 = new HouseBin(tLSetting, tLInitControllerResult.HouseList.FirstOrDefault(x => x.houseSn == 6), allList.Dishes.FirstOrDefault(x => x.houseSn == 6), allList.BalanceList.FirstOrDefault(x => x.houseSn == 6), tLInitControllerResult.HouseWellList.Where(x => x.houseSn == 6).ToList()); AppData.InitHouseBinEvent(AppData.HouseBin6); });
Build(7, () => { AppData.HouseBin7 = new HouseBin(tLSetting, tLInitControllerResult.HouseList.FirstOrDefault(x => x.houseSn == 7), allList.Dishes.FirstOrDefault(x => x.houseSn == 7), allList.BalanceList.FirstOrDefault(x => x.houseSn == 7), tLInitControllerResult.HouseWellList.Where(x => x.houseSn == 7).ToList()); AppData.InitHouseBinEvent(AppData.HouseBin7); });
Build(8, () => { AppData.HouseBin8 = new HouseBin(tLSetting, tLInitControllerResult.HouseList.FirstOrDefault(x => x.houseSn == 8), allList.Dishes.FirstOrDefault(x => x.houseSn == 8), allList.BalanceList.FirstOrDefault(x => x.houseSn == 8), tLInitControllerResult.HouseWellList.Where(x => x.houseSn == 8).ToList()); AppData.InitHouseBinEvent(AppData.HouseBin8); });
Build(9, () => { AppData.HouseBin9 = new HouseBin(tLSetting, tLInitControllerResult.HouseList.FirstOrDefault(x => x.houseSn == 9), allList.Dishes.FirstOrDefault(x => x.houseSn == 9), allList.BalanceList.FirstOrDefault(x => x.houseSn == 9), tLInitControllerResult.HouseWellList.Where(x => x.houseSn == 9).ToList()); AppData.InitHouseBinEvent(AppData.HouseBin9); });
Build(10, () => { AppData.HouseBin10 = new HouseBin(tLSetting, tLInitControllerResult.HouseList.FirstOrDefault(x => x.houseSn == 10), allList.Dishes.FirstOrDefault(x => x.houseSn == 10), allList.BalanceList.FirstOrDefault(x => x.houseSn == 10), tLInitControllerResult.HouseWellList.Where(x => x.houseSn == 10).ToList()); AppData.InitHouseBinEvent(AppData.HouseBin10); });
if (AppData.HouseBin1 != null) AppData.HouseBin1.CamNum = CamNum;
if (AppData.HouseBin2 != null) AppData.HouseBin2.CamNum = CamNum;
if (AppData.HouseBin3 != null) AppData.HouseBin3.CamNum = CamNum;
if (AppData.HouseBin4 != null) AppData.HouseBin4.CamNum = CamNum;
if (AppData.HouseBin5 != null) AppData.HouseBin5.CamNum = CamNum;
if (AppData.HouseBin6 != null) AppData.HouseBin6.CamNum = CamNum;
if (AppData.HouseBin7 != null) AppData.HouseBin7.CamNum = CamNum;
if (AppData.HouseBin8 != null) AppData.HouseBin8.CamNum = CamNum;
if (AppData.HouseBin9 != null) AppData.HouseBin9.CamNum = CamNum;
if (AppData.HouseBin10 != null) AppData.HouseBin10.CamNum = CamNum;
if (!AppData.MvcTest)
{
if (runHouses.Contains(1) && AppData.HouseBin1 != null) Start(1, () => AppData.HouseBin1.StartTask());
if (runHouses.Contains(2) && AppData.HouseBin2 != null) Start(2, () => AppData.HouseBin2.StartTask());
if (runHouses.Contains(3) && AppData.HouseBin3 != null) Start(3, () => AppData.HouseBin3.StartTask());
if (runHouses.Contains(4) && AppData.HouseBin4 != null) Start(4, () => AppData.HouseBin4.StartTask());
if (runHouses.Contains(6) && AppData.HouseBin6 != null) Start(6, () => AppData.HouseBin6.StartTask());
if (runHouses.Contains(7) && AppData.HouseBin7 != null) Start(7, () => AppData.HouseBin7.StartTask());
if (runHouses.Contains(8) && AppData.HouseBin8 != null) Start(8, () => AppData.HouseBin8.StartTask());
if (runHouses.Contains(9) && AppData.HouseBin9 != null) Start(9, () => AppData.HouseBin9.StartTask());
if (runHouses.Contains(10) && AppData.HouseBin10 != null) Start(10, () => AppData.HouseBin10.StartTask());
}
if (runHouses.Contains(5) && AppData.HouseBin5 != null) Start(5, () => AppData.HouseBin5.StartTask());
if (runHouses.Contains(11) && AppData.BufferBottleBin != null) Start(11, () => AppData.BufferBottleBin.StartTask());
return true;
}
catch (Exception ex)
{
AppData.LogService.ExceptionLog(ex, "仓室初始化", null, LogEnum.RunException);
errorInfo = ex.Message;
return false;
}
}
public void testc()
{
AppData = AppData.Instance;
string body1 = AppData.ReadText(@"C:\Users\jxb\Desktop\work\10 时差\8 开发文档\6 服务器架构\link接口请求参数.txt");
string body2 = AppData.ReadText(@"C:\Users\jxb\Desktop\work\10 时差\8 开发文档\6 服务器架构\init接口请求参数.txt");
//AppData.SerialBinController.TLInitController(body1, body2);
}
public void testGetAutoFocusController()
{
AppData = AppData.Instance;
PositionRequestDTO autoFocusDTO = new PositionRequestDTO
{
tlSn = "NEO-1-20230101",
houseSn = 1,
};
AppData.HouseBinController.GetAutoFocusController(autoFocusDTO);
}
public void TestGetCCDPositionController()
{
AppData = AppData.Instance;
PositionRequestDTO autoFocusDTO = new PositionRequestDTO
{
tlSn = "NEO-1-20230101",
houseSn = 1,
};
AppData.HouseBinController.GetCCDPositionController(autoFocusDTO);
}
public void TestGetDishAndBalanceDataController()
{
AppData = AppData.Instance;
//AppData.HouseBinController.GetDishAndBalanceDataController("NEO-1-20230101");
}
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll")]
static extern bool EnumChildWindows(IntPtr hWndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam);
[DllImport("user32.dll")]
static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
const uint WM_CLOSE = 0x0010;
const uint BM_CLICK = 0x00F5;
}
}