AdgController.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. using CliWrap;
  2. using Ips.Library.Basic;
  3. using Ips.Library.Entity;
  4. using Ips.Library.LocLib;
  5. using Ips.Library.Signals;
  6. namespace Ips.AdcAlgorithm
  7. {
  8. public class AdgController : IAdController
  9. {
  10. public AdgController()
  11. {
  12. _ddcOneStopTimer = new Timer(async obj => await Stop(), null, Timeout.Infinite, Timeout.Infinite);
  13. _getDdcSrcFileName = GetDdcSrcFileName;
  14. _getAdcSrcFileName = GetAdcSrcFileName;
  15. }
  16. static readonly string CliPath = Path.Combine(IpsPath.CliRootDir, "adg");
  17. static readonly string CliFile = Path.Combine(CliPath, "adg.exe");
  18. static readonly string CliAppCfg = Path.Combine(CliPath, "app.cfg");
  19. static readonly string QFStopExe = Path.Combine(CliPath, "stop.exe");
  20. Timer _ddcOneStopTimer, _ddcRestartTimer;
  21. Func<AdcOptions, AdcChOptions, AdcSigOptions, string> _getDdcSrcFileName;
  22. Func<AdcOptions, int, string> _getAdcSrcFileName;
  23. public AdcOptions CurrentAdcOptions { get; set; }
  24. /// <summary>
  25. /// ADC采集
  26. /// </summary>
  27. public async Task<ExeResult<AdcResult>> StartAdc(AdcOptions options, Action<string> handline = null, CancellationToken token = default)
  28. {
  29. //停止采集
  30. await Stop();
  31. //修改配置
  32. await SetAppCfg(options);
  33. if (options.StartTime < DateTime.Now.AddSeconds(AdcConst.MinWaitTime))
  34. options.StartTime = DateTime.Now.AddSeconds(AdcConst.MinWaitTime);
  35. DirectoryUtil.CreateIfNotExists(options.StorePath);
  36. var cmd = CliWrap.Cli.Wrap(CliFile)
  37. .WithWorkingDirectory(CliPath)
  38. .WithValidation(CommandResultValidation.None)
  39. .WithArguments(args =>
  40. {
  41. args.Add(1);
  42. args.Add(DateTimeUtil.To1970s(options.StartTime));
  43. args.Add(options.ClockType.ToString("D"));
  44. args.Add(options.TriggerMode.ToString("D"));
  45. args.Add(options.DdcFreq.E6m().ToString());
  46. args.Add(options.ClockFreq.E6m().ToString());
  47. args.Add(options.Mutil == 1 ? 0 : options.Mutil);
  48. args.Add(options.ChCount);
  49. args.Add(options.StorePath, true);
  50. args.Add(options.TimeLen);
  51. });
  52. if (handline != null)
  53. {
  54. cmd = cmd.WithStandardErrorPipe(PipeTarget.ToDelegate(handline))
  55. .WithStandardOutputPipe(PipeTarget.ToDelegate(handline));
  56. }
  57. var result = await cmd.ExecuteAsync(token);
  58. var adcResult = await AdcFileUtil.BuildAdcResult(options, _getAdcSrcFileName);
  59. return ExeResult.Create(adcResult, cmd.Arguments, result.StartTime, result.ExitTime, result.ExitCode);
  60. }
  61. /// <summary>
  62. /// DDC采集
  63. /// </summary>
  64. public async Task<ExeResult<AdcResult>> StartDdcOne(AdcOptions options, Action<string> handline = null, CancellationToken token = default)
  65. {
  66. await Stop();
  67. await SetAppCfg(options);
  68. if (options.StartTime < DateTime.Now.AddSeconds(AdcConst.MinWaitTime))
  69. options.StartTime = DateTime.Now.AddSeconds(AdcConst.MinWaitTime);
  70. var cmd = BuildDdcCommand(options, handline);
  71. //由于DDC采集不会停止,到时间后结束进程
  72. var stopTimeSpan = options.StartTime.AddSeconds(options.TimeLen + AdcConst.DDCFindFileDelay) - DateTime.Now;
  73. _ddcOneStopTimer.Change(stopTimeSpan, Timeout.InfiniteTimeSpan);
  74. var cmdRes = await cmd.ExecuteAsync(token);
  75. var adcResult = AdcFileUtil.BuildDdcResult(options, _getDdcSrcFileName);
  76. return ExeResult.Create(adcResult, cmd.Arguments, cmdRes.StartTime, cmdRes.ExitTime, cmdRes.ExitCode);
  77. }
  78. /// <summary>
  79. /// DDC持续采集
  80. /// </summary>
  81. public async Task<ExeResult<AdcResult>> StartDdcKeep(AdcOptions options, Action<AdcResult> resultCallback, Action<string> handline = null, CancellationToken token = default)
  82. {
  83. //停止原有采集
  84. await Stop();
  85. //设置配置文件
  86. await SetAppCfg(options);
  87. if (options.StartTime < DateTime.Now.AddSeconds(AdcConst.MinWaitTime))
  88. options.StartTime = DateTime.Now.AddSeconds(AdcConst.MinWaitTime);
  89. var startTime = options.StartTime;
  90. options.StartTime = startTime.ClearSecond().AddSeconds(Math.Ceiling(startTime.Second * 1.0 / options.TimeLen) * options.TimeLen);
  91. var cmd = BuildDdcCommand(options, handline);
  92. var adcTsk = cmd.ExecuteAsync(token);
  93. var outTsk = Task.Run(() =>
  94. {
  95. while (!adcTsk.Task.IsCompleted)
  96. {
  97. var waitTime = options.StartTime.AddSeconds(options.TimeLen + AdcConst.DDCFindFileDelay) - DateTime.Now;
  98. if (waitTime.TotalMilliseconds > 0)
  99. Task.Delay((int)waitTime.TotalMilliseconds, token).Wait();
  100. var adcResult = AdcFileUtil.BuildDdcResult(options, _getDdcSrcFileName);
  101. resultCallback?.Invoke(adcResult);
  102. options.StartTime = options.StartTime.AddSeconds(options.TimeLen);
  103. }
  104. });
  105. StartRestartDdc(new RestartDdcOptions(options, resultCallback, handline, token));
  106. await Task.WhenAll(adcTsk, outTsk);
  107. var cmdRes = await adcTsk;
  108. return ExeResult.Create(new AdcResult(options.StartTime, options.StorePath), cmd.Arguments, cmdRes.StartTime, cmdRes.ExitTime, cmdRes.ExitCode);
  109. }
  110. /// <summary>
  111. /// 停止采集
  112. /// </summary>
  113. public async Task Stop()
  114. {
  115. _ddcOneStopTimer?.Change(Timeout.Infinite, Timeout.Infinite);
  116. _ddcRestartTimer?.Change(Timeout.Infinite, Timeout.Infinite);
  117. if (CurrentAdcOptions != null && CurrentAdcOptions.CardType == AdCardType.QFCarder)
  118. {
  119. if (File.Exists(QFStopExe))
  120. {
  121. await Cli.Wrap(QFStopExe).ExecuteAsync();
  122. }
  123. }
  124. ProcessUtil.KillProcessByName(CliFile);
  125. }
  126. /// <summary>
  127. /// 设置采集参数
  128. /// </summary>
  129. /// <param name="options"></param>
  130. private async Task SetAppCfg(AdcOptions options)
  131. {
  132. string cardTypeDesc = options.CardType.ToString("g");
  133. string cfgContent = $"DllPath={cardTypeDesc}\r\nDllName = {cardTypeDesc}.dll\r\nFilePath = {options.StorePath}";
  134. await File.WriteAllTextAsync(CliAppCfg, cfgContent);
  135. CurrentAdcOptions = options;
  136. }
  137. private void StartRestartDdc(RestartDdcOptions restartOptions)
  138. {
  139. var now = DateTime.Now;
  140. var addHour = now.Minute > 30 ? 2 : 1;
  141. var restartTime = now.AddHours(addHour).ClearMinute().AddMinutes(1);
  142. var waitTimeMs = (int)(restartTime - now).TotalMilliseconds;
  143. if (_ddcRestartTimer == null)
  144. {
  145. _ddcRestartTimer = new Timer(async obj => await RestartDdc(obj), restartOptions, waitTimeMs, Timeout.Infinite);
  146. }
  147. else
  148. {
  149. _ddcRestartTimer.Change(waitTimeMs, Timeout.Infinite);
  150. }
  151. }
  152. private async Task RestartDdc(object obj)
  153. {
  154. var options = obj as RestartDdcOptions;
  155. if (options == null) return;
  156. await Stop();
  157. await StartDdcKeep(options.AdcOptions, options.ResultCallback, options.Handline, options.Token);
  158. }
  159. private Command BuildDdcCommand(AdcOptions options, Action<string> handline)
  160. {
  161. DirectoryUtil.CreateIfNotExists(options.StorePath);
  162. var cmd = CliWrap.Cli.Wrap(CliFile)
  163. .WithWorkingDirectory(CliPath)
  164. .WithValidation(CommandResultValidation.None)
  165. .WithArguments(args =>
  166. {
  167. args.Add(2);
  168. args.Add(DateTimeUtil.To1970s(options.StartTime));
  169. args.Add(options.ClockType.ToString("D"));
  170. args.Add(options.TriggerMode.ToString("D"));
  171. args.Add(options.DdcFreq.E6m().ToString());
  172. args.Add(options.ClockFreq.E6m().ToString());
  173. args.Add(options.Mutil);
  174. args.Add(options.ChCount);
  175. args.Add(options.StorePath);
  176. args.Add(options.TimeLen);
  177. args.Add(1);
  178. args.Add(options.GetCenterFreqs().Select(m => (m * 1e-6).ToString()));
  179. foreach (var ch in options.Channels)
  180. {
  181. foreach (var sig in ch.Signals)
  182. {
  183. int mutil = SigCalcUtil.CalcMutil(options.ClockFreq / options.Mutil, sig.BandWidth, false);
  184. args.Add(ch.ChNum);
  185. args.Add(sig.FreqUp == 0 ? "0" : sig.FreqUp.E6m().ToString());
  186. args.Add(sig.FreqPoint.E6m().ToString());
  187. args.Add(mutil);
  188. args.Add(sig.SigName);
  189. }
  190. }
  191. });
  192. if (handline != null)
  193. {
  194. cmd = cmd.WithStandardErrorPipe(PipeTarget.ToDelegate(handline))
  195. .WithStandardOutputPipe(PipeTarget.ToDelegate(handline));
  196. }
  197. return cmd;
  198. }
  199. private string GetAdcSrcFileName(AdcOptions options, int chNum)
  200. {
  201. var sigTime = options.StartTime;
  202. var nameTime = sigTime.Format(SignalFile.SigTimeFileFormat);
  203. string fileName = $"{nameTime}_ch{chNum}{(options.Mutil == 1 ? "" : "_iq")}.dat";
  204. string fullName = Path.Combine(options.StorePath, fileName);
  205. return fullName;
  206. }
  207. private string GetDdcSrcFileName(AdcOptions options, AdcChOptions ch, AdcSigOptions sig)
  208. {
  209. int mutil = SigCalcUtil.CalcMutil(options.ClockFreq / options.Mutil, sig.BandWidth, false);
  210. var folderTime = options.StartTime.Format("yyyyMMdd_HH");
  211. var nameTime = options.StartTime.Format("yyyyMMddHHmmss");
  212. double downFreqMHz = sig.FreqPoint.E6m();
  213. var fs = options.ClockFreq / options.Mutil / mutil;
  214. string sourceFile = Path.Combine(options.StorePath, folderTime, $"{nameTime}_{sig.SigName}_{sig.FreqUp.E6m():F3}MHz_{downFreqMHz:F3}MHz_C{fs}_CH{ch.ChNum}.dat");
  215. return sourceFile;
  216. }
  217. }
  218. }