using CliWrap; using CliWrap.Buffered; using Ips.Library.Basic; using Ips.Library.Entity; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection.Metadata; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; namespace Ips.AdcAlgorithm { public static class AdgUtil { static AdgUtil() { DirectoryUtil.CreateIfNotExists(ParamsPath); } static readonly string CliPath = PathUtil.GetBasePath("ipscli", "adg"); static readonly string CliFile = Path.Combine(CliPath, "adg.exe"); static readonly string CliAppCfg = Path.Combine(CliPath, "app.cfg"); static readonly string ParamsPath = PathUtil.GetBasePath("AdParams"); static readonly string AdArgFile = Path.Combine(ParamsPath, "adarg.json"); static readonly string DdcArgFile = Path.Combine(ParamsPath, "ddcarg.json"); static readonly string QFStopExe = Path.Combine(CliPath, "stop.exe"); static CommandTask DDCTsk; static Timer DDCOneStopTimer = new Timer(AutoStopAdDdc, null, Timeout.Infinite, Timeout.Infinite); static Timer DDCRestartTimer = new Timer(RestartDdc, null, Timeout.Infinite, Timeout.Infinite); static AdcOptions lastAdArg; static Dictionary _adArgs = new Dictionary(); static Dictionary _ddcArgs = new Dictionary(); public static event EventHandler AdLogNotify; public static async Task> StartAdc(AdcOptions options, Action handline = null, CancellationToken token = default) { //停止采集 await StopAdc(); //修改配置 SetAppCfg(options); if (options.StartTime < DateTime.Now.AddSeconds(AdcConst.MinWaitTime)) options.StartTime = DateTime.Now.AddSeconds(AdcConst.MinWaitTime); DirectoryUtil.CreateIfNotExists(options.StorePath); var cmd = CliWrap.Cli.Wrap(CliFile) .WithWorkingDirectory(CliPath) .WithValidation(CommandResultValidation.None) .WithArguments(args => { args.Add(1); args.Add(DateTimeUtil.To1970s(options.StartTime)); args.Add(options.ClockType.ToString("D")); args.Add(options.TriggerMode.ToString("D")); args.Add(options.DdcFreq.E6m().ToString()); args.Add(options.ClockFreq.E6m().ToString()); args.Add(options.Mutil == 1 ? 0 : options.Mutil); args.Add(options.ChCount); args.Add(options.StorePath, true); args.Add(options.TimeLen); }); if (handline != null) { cmd = cmd.WithStandardErrorPipe(PipeTarget.ToDelegate(handline)) .WithStandardOutputPipe(PipeTarget.ToDelegate(handline)); } var result = await cmd.ExecuteAsync(token); var adcResult = AdcFileUtil.BuildAdcResult(options, AdMode.ADC); return ExeResult.Create(adcResult, cmd.Arguments, result.StartTime, result.ExitTime, result.ExitCode); } /// /// DDC采集 /// public static async Task> StartDdcOne(AdcOptions options, Action handline = null, CancellationToken token = default) { await StopAdc(); SetAppCfg(options); if (options.StartTime < DateTime.Now.AddSeconds(AdcConst.MinWaitTime)) options.StartTime = DateTime.Now.AddSeconds(AdcConst.MinWaitTime); var cmd = BuildDdcCommand(options, handline); //由于DDC采集不会停止,到时间后结束进程 var stopTimeSpan = options.StartTime.AddSeconds(options.TimeLen + AdcConst.DDCFindFileDelay) - DateTime.Now; DDCOneStopTimer.Change(stopTimeSpan, Timeout.InfiniteTimeSpan); var cmdRes = await cmd.ExecuteAsync(token); var adcResult = BuildDdcResult(options); return ExeResult.Create(adcResult, cmd.Arguments, cmdRes.StartTime, cmdRes.ExitTime, cmdRes.ExitCode); } /// /// DDC持续采集 /// /// 采集参数 /// DDC参数 /// public static async Task> StartDdcKeep(AdcOptions options, Action resultCallback, Action handline = null, CancellationToken token = default) { //停止原有采集 await StopAdc(); //设置配置文件 SetAppCfg(options); if (options.StartTime < DateTime.Now.AddSeconds(AdcConst.MinWaitTime)) options.StartTime = DateTime.Now.AddSeconds(AdcConst.MinWaitTime); var startTime = options.StartTime; options.StartTime = startTime.ClearSecond().AddSeconds(Math.Ceiling(startTime.Second * 1.0 / options.TimeLen) * options.TimeLen); var cmd = BuildDdcCommand(options, handline); var adcTsk = cmd.ExecuteAsync(token); var outTsk = Task.Run(async () => { while (!adcTsk.Task.IsCompleted) { await Task.Delay(options.StartTime.AddSeconds(options.TimeLen + AdcConst.DDCFindFileDelay) - DateTime.Now, token); var adcResult = BuildDdcResult(options); resultCallback?.Invoke(adcResult); options.StartTime = options.StartTime.AddSeconds(options.TimeLen); } }); await Task.WhenAll(adcTsk, outTsk); var cmdRes = await adcTsk; return ExeResult.Create(new AdcResult(options.StartTime, options.StorePath), cmd.Arguments, cmdRes.StartTime, cmdRes.ExitTime, cmdRes.ExitCode); } /// /// DDC持续采集,共享采集 /// /// 共享编号 /// 采集参数 /// DDC参数 /// public static Task> StartDdcShared(string sharedId, AdcOptions adArg, DdcOptions ddcArg, CancellationToken token) { lastAdArg = adArg; _adArgs[sharedId] = adArg; _ddcArgs[sharedId] = ddcArg; SaveAdParams(); var result = StartDdcKeepInternal(token); return result; } private static Task> StartDdcKeepInternal(CancellationToken token = default) { //StopAdc(); var adDdcArg = GetAdDdcArg(); AdcOptions adArg = adDdcArg.adArg; DdcOptions ddcArg = adDdcArg.ddcArg; SetAppCfg(adArg); var startTime = DateTime.Now.AddSeconds(30); adArg.StartTime = startTime.ClearSecond().AddSeconds(Math.Ceiling(startTime.Second * 1.0 / 15) * 15); DirectoryUtil.CreateIfNotExists(adArg.StorePath); var cmd = CliWrap.Cli.Wrap(CliFile) .WithWorkingDirectory(CliPath) .WithValidation(CommandResultValidation.None) .WithArguments(args => { args.Add(2); args.Add(DateTimeUtil.To1970s(adArg.StartTime)); args.Add(adArg.ClockType.ToString("D")); args.Add(adArg.TriggerMode.ToString("D")); args.Add(adArg.DdcFreq.E6m().ToString()); args.Add(adArg.ClockFreq.E6m().ToString()); args.Add(adArg.Mutil); args.Add(adArg.ChCount); args.Add(adArg.StorePath); args.Add(adArg.TimeLen); args.Add(1); args.Add(ddcArg.CenterFreqs.Select(m => m.ToString())); foreach (var freqItem in ddcArg.DdcSigList) { int mutil = SigCalcUtil.CalcMutil(adArg.ClockFreq / adArg.Mutil, freqItem.BandWidth); args.Add(freqItem.ChNo); args.Add(freqItem.UpFreq.E6m().ToString()); args.Add(freqItem.DownFreq.E6m().ToString()); args.Add(mutil); args.Add(freqItem.SigName); } }); if (AdLogNotify != null) { cmd = cmd.WithStandardErrorPipe(PipeTarget.ToDelegate(OnAdLog)) .WithStandardOutputPipe(PipeTarget.ToDelegate(OnAdLog)); } DDCTsk = cmd.ExecuteAsync(token); var adResult = new AdcResult(); var folderTime = adArg.StartTime.Format("yyyyMMdd_HH"); var nameTime = adArg.StartTime.Format("yyyyMMddHHmmss"); foreach (var freqItem in ddcArg.DdcSigList) { int mutil = SigCalcUtil.CalcMutil(adArg.ClockFreq / adArg.Mutil, freqItem.BandWidth); double upFreqMHz = freqItem.UpFreq.E6m(); double downFreqMHz = freqItem.DownFreq.E6m(); var fs = adArg.ClockFreq / adArg.Mutil / mutil; var foldername = "{0:yyyyMMdd_HH}"; var filename = Path.Combine(adArg.StorePath, "{0:yyyyMMdd_HH}", $"{{0:yyyyMMddHHmmss}}_{freqItem.SigName}_{upFreqMHz}MHz_{downFreqMHz}MHz_C{fs}_CH{freqItem.ChNo}.dat"); var fileItem = new AdcFile() { //StartTime = adArg.StartTime, //ChNum = freqItem.ChNo, //SatCode = freqItem.SigName, //UpFreq = freqItem.UpFreq, //DownFreq = freqItem.DownFreq, //BandWidth = freqItem.BandWidth, //Mutil = mutil * adArg.Mutil, //DDCMutil = mutil, //Fs = (int)(adArg.ClockFreq * 1e6 / adArg.Mutil / mutil), //FolderName = foldername, //FileName = filename }; adResult.FileList.Add(fileItem); } StartRestartDdc(); var result = ExeResult.Create(adResult, cmd.Arguments, DateTime.Now, DateTime.MaxValue, 0, ""); return Task.FromResult(result); } /// /// 停止采集 /// public static async Task StopAdc() { DDCOneStopTimer?.Change(Timeout.Infinite, Timeout.Infinite); DDCRestartTimer?.Change(Timeout.Infinite, Timeout.Infinite); if (lastAdArg != null && lastAdArg.CardType == AdCardType.QFCarder) { if (File.Exists(QFStopExe)) { await Cli.Wrap(QFStopExe).ExecuteAsync(); } } ProcessUtil.KillProcessByName(CliFile); } /// /// 设置采集参数 /// /// private static void SetAppCfg(AdcOptions options) { string cardTypeDesc = options.CardType.ToString("g"); string cfgContent = $"DllPath={cardTypeDesc}\r\nDllName = {cardTypeDesc}.dll\r\nFilePath = {options.StorePath}"; File.WriteAllText(CliAppCfg, cfgContent); } public static void StartLastTask() { DirectoryUtil.CreateIfNotExists(ParamsPath); if (File.Exists(AdArgFile)) { _adArgs = JsonSerializer.Deserialize>(AdArgFile); } if (File.Exists(DdcArgFile)) { _ddcArgs = JsonSerializer.Deserialize>(DdcArgFile); } if (_adArgs.IsNullOrEmpty() || _ddcArgs.IsNullOrEmpty()) return; StartDdcKeepInternal(); } private static void AutoStopAdDdc(object obj) { StopAdc(); } private static void StartRestartDdc() { var now = DateTime.Now; var addHour = now.Minute > 30 ? 2 : 1; var restartTime = now.AddHours(addHour).ClearMinute().AddMinutes(2); DDCRestartTimer.Change((int)(restartTime - now).TotalMilliseconds, Timeout.Infinite); } private static void RestartDdc(object obj) { StartDdcKeepInternal(); } private static void InitAdcConfig(AdcOptions adArg) { lastAdArg = adArg; DeleteAdParams(); SetAppCfg(adArg); } private static Command BuildDdcCommand(AdcOptions options, Action handline) { DirectoryUtil.CreateIfNotExists(options.StorePath); var cmd = CliWrap.Cli.Wrap(CliFile) .WithWorkingDirectory(CliPath) .WithValidation(CommandResultValidation.None) .WithArguments(args => { args.Add(2); args.Add(DateTimeUtil.To1970s(options.StartTime)); args.Add(options.ClockType.ToString("D")); args.Add(options.TriggerMode.ToString("D")); args.Add(options.DdcFreq.E6m().ToString()); args.Add(options.ClockFreq.E6m().ToString()); args.Add(options.Mutil); args.Add(options.ChCount); args.Add(options.StorePath); args.Add(options.TimeLen); args.Add(1); args.Add(options.GetCenterFreqs().Select(m => m.ToString())); foreach (var ch in options.Channels) { foreach (var sigGroup in ch.Signals.GroupBy(m => new { m.DownFreq, m.BandWidth })) { var sig = sigGroup.Key; int mutil = SigCalcUtil.CalcMutil(options.ClockFreq / options.Mutil, sig.BandWidth); args.Add(ch.ChNum); args.Add("0"); args.Add(sig.DownFreq.E6m().ToString()); args.Add(mutil); args.Add("0"); } } }); if (handline != null) { cmd = cmd.WithStandardErrorPipe(PipeTarget.ToDelegate(handline)) .WithStandardOutputPipe(PipeTarget.ToDelegate(handline)); } return cmd; } private static AdcResult BuildDdcResult(AdcOptions options) { var adcResult = new AdcResult(options.StartTime, options.StorePath); var folderTime = options.StartTime.Format("yyyyMMdd_HH"); var nameTime = options.StartTime.Format("yyyyMMddHHmmss"); foreach (var ch in options.Channels) { foreach (var sigGroup in ch.Signals.GroupBy(m => new { m.DownFreq, m.BandWidth })) { var sigKey = sigGroup.Key; int mutil = SigCalcUtil.CalcMutil(options.ClockFreq / options.Mutil, sigKey.BandWidth); double downFreqMHz = sigKey.DownFreq.E6m(); var fs = options.ClockFreq / options.Mutil / mutil; string sourceFile = Path.Combine(options.StorePath, folderTime, $"{nameTime}_0_0MHz_{downFreqMHz}MHz_C{fs}_CH{ch.ChNum}.dat"); foreach (var sig in sigGroup) { AdcFile fileItem = new AdcFile( options.StartTime, sig.SatCode, ch.RecCode, sig.FreqPoint, sig.BandWidth, SigCalcUtil.CalcFs(options.ClockFreq, sig.BandWidth, options.Mutil), ch.ChNum, options.StorePath, sig.UpFreq, sig.DownFreq ); string targetFile = fileItem.GetFullName(); DirectoryUtil.CreateIfNotExists(Path.GetDirectoryName(targetFile)); File.Move(sourceFile, targetFile, true); adcResult.FileList.Add(fileItem); } } } return adcResult; } private static void SaveAdParams() { if (_adArgs != null) { var adArgContent = JsonSerializer.Serialize(_adArgs, new JsonSerializerOptions() { WriteIndented = true }); File.WriteAllText(AdArgFile, adArgContent); } if (_ddcArgs != null) { var ddcArgContent = JsonSerializer.Serialize(_ddcArgs, new JsonSerializerOptions() { WriteIndented = true }); File.WriteAllText(DdcArgFile, ddcArgContent); } } private static void DeleteAdParams() { FileUtil.DeleteIfExists(AdArgFile); FileUtil.DeleteIfExists(DdcArgFile); } private static (AdcOptions adArg, DdcOptions ddcArg) GetAdDdcArg() { AdcOptions adArg = lastAdArg; DdcOptions ddcArg = null; if (_ddcArgs.Count == 1) { ddcArg = _ddcArgs.First().Value; } else { adArg.Mutil = _adArgs.Min(m => m.Value.Mutil); adArg.ChCount = _adArgs.Max(m => m.Value.ChCount); ddcArg = new DdcOptions(); List freqItems = new List(); foreach (var item in _ddcArgs) { if (ddcArg.CenterFreqs == null || ddcArg.CenterFreqs.Length < item.Value.CenterFreqs.Length) { ddcArg.CenterFreqs = item.Value.CenterFreqs; } foreach (var freqItem in item.Value.DdcSigList) { if (freqItems.Any(m => m.ChNo == freqItem.ChNo && m.UpFreq == freqItem.UpFreq && m.DownFreq == freqItem.DownFreq && m.BandWidth == freqItem.BandWidth && m.SigName == freqItem.SigName)) continue; freqItems.Add(freqItem); } ddcArg.DdcSigList = freqItems; } } return (adArg, ddcArg); } private static void OnAdLog(string message) { AdLogNotify.InvokeSafely(null, new AdcMessageEventArgs(message)); } } }