|
@@ -0,0 +1,698 @@
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Configuration;
|
|
|
+using System.Diagnostics;
|
|
|
+using System.IO;
|
|
|
+using System.Linq;
|
|
|
+using System.Text;
|
|
|
+using System.Threading;
|
|
|
+using System.Threading.Tasks;
|
|
|
+using XdCxRhDW.Api;
|
|
|
+using XdCxRhDW.Dto;
|
|
|
+
|
|
|
+namespace X2D1NoRefTaskServer54.Service
|
|
|
+{
|
|
|
+ //业务逻辑处理类
|
|
|
+ public class TaskService
|
|
|
+ {
|
|
|
+ private readonly string baseUrl;
|
|
|
+ CancellationTokenSource cts;
|
|
|
+
|
|
|
+ string DetectDir;
|
|
|
+ string CapDir;
|
|
|
+ string DdcDir;
|
|
|
+ string PosResDir;
|
|
|
+ int MainSatCode, Adja1SatCode;
|
|
|
+ double[] MainSatXYZ, Adja1SatXYZ;
|
|
|
+ int PosDtoFactor;
|
|
|
+ bool useGpuCg = false;
|
|
|
+ double DtoErrus;
|
|
|
+ double EphErrm;
|
|
|
+
|
|
|
+ public TaskService()
|
|
|
+ {
|
|
|
+ Directory.CreateDirectory("tmp");
|
|
|
+ var posPlatformAddr = ConfigurationManager.AppSettings["PosPlatformAddr"].Trim();//like http://127.0.0.1:8091 or http://127.0.0.1:8091/
|
|
|
+ if (posPlatformAddr.EndsWith("/"))
|
|
|
+ this.baseUrl = posPlatformAddr + "api/";
|
|
|
+ else
|
|
|
+ this.baseUrl = posPlatformAddr + "/api/";
|
|
|
+
|
|
|
+ DetectDir = ConfigurationManager.AppSettings["DetectDir"].Trim();
|
|
|
+ CapDir = ConfigurationManager.AppSettings["CapDir"].Trim();
|
|
|
+ DdcDir = ConfigurationManager.AppSettings["DdcDir"].Trim();
|
|
|
+ PosResDir = ConfigurationManager.AppSettings["PosResDir"].Trim();
|
|
|
+ var PosDtoFactorstr = ConfigurationManager.AppSettings["PosDtoFactor"].Trim();
|
|
|
+ int.TryParse(PosDtoFactorstr, out PosDtoFactor);
|
|
|
+ if (PosDtoFactor == 0) PosDtoFactor = 1;
|
|
|
+ var DtoErrusstr = ConfigurationManager.AppSettings["DtoErrus"].Trim();
|
|
|
+ double.TryParse(DtoErrusstr, out DtoErrus);
|
|
|
+ var EphErrmstr = ConfigurationManager.AppSettings["EphErrm"].Trim();
|
|
|
+ double.TryParse(EphErrmstr, out EphErrm);
|
|
|
+
|
|
|
+ string useGpuStr = ConfigurationManager.AppSettings["UseGpuCg"];
|
|
|
+ if (useGpuStr != null && useGpuStr.Trim() == "1")
|
|
|
+ useGpuCg = true;
|
|
|
+ }
|
|
|
+ public void StartAsync(X2D1NoRefTaskHandleDto dto)
|
|
|
+ {
|
|
|
+ cts = new CancellationTokenSource();
|
|
|
+ Task.Run(async () =>
|
|
|
+ {
|
|
|
+ LogHelper.Info($"【任务{dto.ID}】开始执行...");
|
|
|
+ LogHelper.Info($"【任务{dto.ID}】检测结果目录[{DetectDir}]");
|
|
|
+ LogHelper.Info($"【任务{dto.ID}】AD采集目录[{CapDir}]");
|
|
|
+ LogHelper.Info($"【任务{dto.ID}】DDC输出目录[{DdcDir}]");
|
|
|
+ //点击定位平台右上角查看接口可以在浏览器中查看平台提供的所有接口详细信息
|
|
|
+ while (!cts.IsCancellationRequested)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ #region 第1步,读取需要的配置信息
|
|
|
+ if (!Directory.Exists(DetectDir))
|
|
|
+ {
|
|
|
+ await StopTask(dto.ID, EnumTaskStopType.Error, $"检测结果目录[{DetectDir}]不存在");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (!Directory.Exists(CapDir))
|
|
|
+ {
|
|
|
+ await StopTask(dto.ID, EnumTaskStopType.Error, $"AD采集目录[{CapDir}]不存在");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ Directory.CreateDirectory(DdcDir);
|
|
|
+ Directory.CreateDirectory(PosResDir);
|
|
|
+
|
|
|
+ try
|
|
|
+ {
|
|
|
+ var mainInfo = ConfigurationManager.AppSettings["MainSatInfo"].Replace(",", ",").Trim();
|
|
|
+ var adja1Info = ConfigurationManager.AppSettings["Adja1SatInfo"].Replace(",", ",").Trim();
|
|
|
+ var arr1 = mainInfo.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
|
|
|
+ var arr2 = adja1Info.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
|
|
|
+ MainSatCode = Convert.ToInt32(arr1[0]);
|
|
|
+ Adja1SatCode = Convert.ToInt32(arr2[0]);
|
|
|
+ MainSatXYZ = new double[3] { Convert.ToDouble(arr1[1]), Convert.ToDouble(arr1[2]), Convert.ToDouble(arr1[3]) };
|
|
|
+ Adja1SatXYZ = new double[3] { Convert.ToDouble(arr2[1]), Convert.ToDouble(arr2[2]), Convert.ToDouble(arr2[3]) };
|
|
|
+ }
|
|
|
+ catch
|
|
|
+ {
|
|
|
+ await StopTask(dto.ID, EnumTaskStopType.Error, $"任务处理服务配置文件卫星信息解析出错");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region 第2步,扫描检测结果目录
|
|
|
+ var groupFiles = Directory.EnumerateFiles(DetectDir, "*.dat", SearchOption.TopDirectoryOnly).Select(p => StringToCheckResFile(p))
|
|
|
+ .GroupBy(m => Convert.ToInt64(m.DayTime.ToString("yyyyMMdd") + m.FlagNo)).OrderBy(m => m.Key);
|
|
|
+ if (!groupFiles.Any())
|
|
|
+ {
|
|
|
+ LogHelper.Info($"【任务{dto.ID}】等待扫描文件...");
|
|
|
+ await Task.Delay(10000);
|
|
|
+ }
|
|
|
+ foreach (var groupFile in groupFiles)//每一组文件代表同一个时刻的
|
|
|
+ {
|
|
|
+ if (cts.IsCancellationRequested) break;
|
|
|
+ List<SlotsInfo> listSlotsInfo = new List<SlotsInfo>();//多个频点的时隙结果
|
|
|
+ foreach (var item in groupFile)
|
|
|
+ {
|
|
|
+ var slotsInfo = SlotHelper.GetFileSlots(item.File);//某个频点的所有时隙
|
|
|
+ if (!Debugger.IsAttached)
|
|
|
+ File.Delete(item.File);//检测检测结果文件
|
|
|
+ if (slotsInfo.Slots.Any())
|
|
|
+ listSlotsInfo.Add(slotsInfo);
|
|
|
+ }
|
|
|
+ if (!listSlotsInfo.Any()) continue;
|
|
|
+ var adFiles = Directory.EnumerateFiles(CapDir, "*.dat", SearchOption.TopDirectoryOnly).Select(p => StringToAdFile(p))
|
|
|
+ .Where(p => p.AdTime == listSlotsInfo.First().AdTime);
|
|
|
+ if (!adFiles.Any())
|
|
|
+ {
|
|
|
+ LogHelper.Warning($"【任务{dto.ID}】{listSlotsInfo.First().AdTime:yyyyMMddHHmmss}时刻找不到原始AD文件,跳过此组文件");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ var first = listSlotsInfo.First();
|
|
|
+ var sigs = listSlotsInfo.Select(p => new DDCSig() { FreqDownHz = (int)(p.FreqDownMHz * 1e6), Mult = (int)first.Multi, Slots = p });
|
|
|
+ List<DDCFile> chDDCFiles = new List<DDCFile>();//同一个时刻多个频点多个通道的DDC数据
|
|
|
+ LogHelper.Info($"【任务{dto.ID}】{listSlotsInfo.First().AdTime:yyyyMMddHHmmss}时刻DDC处理开始,共{sigs.Count()}个频点...");
|
|
|
+ Stopwatch sw = new Stopwatch();
|
|
|
+ sw.Start();
|
|
|
+ var listTask = new List<Task>();
|
|
|
+ foreach (var adFile in adFiles)
|
|
|
+ {
|
|
|
+ var task = Task.Run(() =>
|
|
|
+ {
|
|
|
+ var ddcRes = DDCHelper.DDC(adFile.File, adFile.AdTime, adFile.ChNo, (long)(first.FsampleM * 1e6), (long)(227 * 1e6), DdcDir, sigs);
|
|
|
+ chDDCFiles.AddRange(StringToDDCFile(ddcRes));
|
|
|
+ if (!Debugger.IsAttached)
|
|
|
+ File.Delete(adFile.File);//删除AD文件
|
|
|
+ }, cts.Token);
|
|
|
+ listTask.Add(task);
|
|
|
+ }
|
|
|
+ await Task.WhenAll(listTask);
|
|
|
+ sw.Stop();
|
|
|
+ LogHelper.Info($"【任务{dto.ID}】{listSlotsInfo.First().AdTime:yyyyMMddHHmmss}时刻DDC处理完成,耗时{sw.ElapsedMilliseconds}ms");
|
|
|
+ if (!chDDCFiles.Any())
|
|
|
+ {
|
|
|
+ LogHelper.Error($"【任务{dto.ID}】{listSlotsInfo.First().AdTime:yyyyMMddHHmmss}时刻DDC处理无结果");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ var groupDDCFiles = chDDCFiles.GroupBy(p => p.FreqDownMHz);
|
|
|
+ listTask.Clear();
|
|
|
+ foreach (var group in groupDDCFiles)
|
|
|
+ {
|
|
|
+ //group:同一个时刻同一个频点的多个通道数据
|
|
|
+ var task = Task.Run(async () =>
|
|
|
+ {
|
|
|
+ var capTime = group.First().AdTime;
|
|
|
+ var ch0File = group.Where(p => p.ChNo == 0).FirstOrDefault();
|
|
|
+ var ch1File = group.Where(p => p.ChNo == 1).FirstOrDefault();
|
|
|
+ var ch2File = group.Where(p => p.ChNo == 2).FirstOrDefault();
|
|
|
+ if (ch0File == null)
|
|
|
+ {
|
|
|
+ LogHelper.Warning($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-未找到主星信号ch0文件,跳过此组数据");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (ch1File == null)
|
|
|
+ {
|
|
|
+ LogHelper.Warning($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-未找到邻星信号ch1文件,跳过此组数据");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (ch2File == null)
|
|
|
+ {
|
|
|
+ LogHelper.Warning($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-未找到超短信号ch2文件,跳过此组数据");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ var sig = sigs.FirstOrDefault(p => p.FreqDownHz == (int)(group.Key * 1e6));
|
|
|
+
|
|
|
+ if (cts.IsCancellationRequested) return;
|
|
|
+ if (useGpuCg)
|
|
|
+ {
|
|
|
+ LogHelper.Info($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-GPU参估开始,共{sig.Slots.Slots.Count}个突发...");
|
|
|
+ sw.Start();
|
|
|
+ List<GpuCgResponseDto> data1 = new List<GpuCgResponseDto>();
|
|
|
+ List<GpuCgResponseDto> data2 = new List<GpuCgResponseDto>();
|
|
|
+ foreach (var item in sig.Slots.Slots)
|
|
|
+ {
|
|
|
+ string f1 = $"tmp\\{Path.GetFileNameWithoutExtension(ch0File.File)}_{item.StartPoint}_{item.Len}.dat";
|
|
|
+ string f2 = $"tmp\\{Path.GetFileNameWithoutExtension(ch1File.File)}_{item.StartPoint}_{item.Len}.dat";
|
|
|
+ string f3 = $"tmp\\{Path.GetFileNameWithoutExtension(ch2File.File)}_{item.StartPoint}_{item.Len}.dat";
|
|
|
+ using (FileStream fs = new FileStream(ch0File.File, FileMode.Open))
|
|
|
+ {
|
|
|
+ byte[] data = new byte[item.Len * 4];
|
|
|
+ fs.Position = item.StartPoint * 4;
|
|
|
+ fs.Read(data, 0, data.Length);
|
|
|
+ File.WriteAllBytes(f1, data);
|
|
|
+ }
|
|
|
+ using (FileStream fs = new FileStream(ch1File.File, FileMode.Open))
|
|
|
+ {
|
|
|
+ byte[] data = new byte[item.Len * 4];
|
|
|
+ fs.Position = item.StartPoint * 4;
|
|
|
+ fs.Read(data, 0, data.Length);
|
|
|
+ File.WriteAllBytes(f2, data);
|
|
|
+ }
|
|
|
+ using (FileStream fs = new FileStream(ch2File.File, FileMode.Open))
|
|
|
+ {
|
|
|
+ byte[] data = new byte[item.Len * 4];
|
|
|
+ fs.Position = item.StartPoint * 4;
|
|
|
+ fs.Read(data, 0, data.Length);
|
|
|
+ File.WriteAllBytes(f3, data);
|
|
|
+ }
|
|
|
+ string mainSlotFile = await HttpHelper.UploadFileAsync(f1, baseUrl, token: cts.Token);//主星文件
|
|
|
+ string adja1SlotFile = await HttpHelper.UploadFileAsync(f2, baseUrl, token: cts.Token);//邻1星文件
|
|
|
+ string adja2SlotFile = await HttpHelper.UploadFileAsync(f3, baseUrl, token: cts.Token);//邻2星文件
|
|
|
+ File.Delete(f1);
|
|
|
+ File.Delete(f2);
|
|
|
+ File.Delete(f3);
|
|
|
+ var gpudto = new GpuCgRequestDto()
|
|
|
+ {
|
|
|
+ dtCenter = 0,
|
|
|
+ dtRange = 40000,
|
|
|
+ file1 = mainSlotFile,
|
|
|
+ file2 = adja1SlotFile,
|
|
|
+ samplingRate = ch0File.Fs,
|
|
|
+ smpCount = 0,
|
|
|
+ snrThreshold = 15
|
|
|
+ };
|
|
|
+ var result1 = await HttpHelper.PostRequestAsync<List<GpuCgResponseDto>>(baseUrl + "DetectCg/GpuCgCalc", gpudto, token: cts.Token);
|
|
|
+ if (result1.code != 200)
|
|
|
+ {
|
|
|
+ LogHelper.Error($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-主星邻1星GPU参估出错.{result1.msg}.突发位置{item.StartPoint}-{item.Len}");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ var data1First = result1.data.First();
|
|
|
+ data1First.TimeSeconds = item.TimeSeconds;
|
|
|
+ data1.Add(data1First);
|
|
|
+ gpudto = new GpuCgRequestDto()
|
|
|
+ {
|
|
|
+ dtCenter = 0,
|
|
|
+ dtRange = 40000,
|
|
|
+ file1 = mainSlotFile,
|
|
|
+ file2 = adja2SlotFile,
|
|
|
+ samplingRate = ch0File.Fs,
|
|
|
+ smpCount = 0,
|
|
|
+ snrThreshold = 15
|
|
|
+ };
|
|
|
+ var result2 = await HttpHelper.PostRequestAsync<List<GpuCgResponseDto>>(baseUrl + "DetectCg/GpuCgCalc", gpudto, token: cts.Token);
|
|
|
+ if (result2.code != 200)
|
|
|
+ {
|
|
|
+ LogHelper.Error($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-主星邻2星GPU参估出错.{result2.msg}.突发位置{item.StartPoint}-{item.Len}");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ var data2First = result2.data.First();
|
|
|
+ data2First.TimeSeconds = item.TimeSeconds;
|
|
|
+ data2.Add(data2First);
|
|
|
+ }
|
|
|
+ sw.Stop();
|
|
|
+ LogHelper.Info($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-GPU参估完成,耗时{sw.ElapsedMilliseconds}ms");
|
|
|
+
|
|
|
+ string mainFile = await HttpHelper.UploadFileAsync(ch0File.File, baseUrl, token: cts.Token);//主星文件
|
|
|
+ var smpPositions = sig.Slots.Slots.Select(p => new SmpPosition() { TimeSeconds = p.TimeSeconds, smpStart = p.StartPoint, smpCount = p.Len }).ToList();
|
|
|
+ var signaldto = new SignalProcDto()
|
|
|
+ {
|
|
|
+ File = mainFile,
|
|
|
+ Fs = ch0File.Fs,
|
|
|
+ Smps = smpPositions,
|
|
|
+ };
|
|
|
+ var signalResult = await HttpHelper.PostRequestAsync<List<SignalProcResDto>>(baseUrl + "DetectCg/SignalProc", signaldto);
|
|
|
+ if (signalResult.code != 200)
|
|
|
+ {
|
|
|
+ LogHelper.Error($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-主星信号识别出错.{signalResult.msg}");
|
|
|
+ return;
|
|
|
+
|
|
|
+ }
|
|
|
+ LogHelper.Info($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-GPU参估完成,耗时{sw.ElapsedMilliseconds}ms");
|
|
|
+ if (data1.Count != data2.Count || data1.Count != sig.Slots.Slots.Count)
|
|
|
+ {
|
|
|
+ LogHelper.Error($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-参估结果个数和检测结果个数不匹配");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (data1.Count != data2.Count || data1.Count != signalResult.data.Count)
|
|
|
+ {
|
|
|
+ LogHelper.Error($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-信号识别结果个数和检测结果个数不匹配");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ for (int i = 0; i < data1.Count; i++)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ if (cts.IsCancellationRequested) break;
|
|
|
+ X2D1NoParPosDto x21d = new X2D1NoParPosDto()
|
|
|
+ {
|
|
|
+ TaskID = dto.ID,
|
|
|
+ //SigTime = capTime.AddSeconds(data1[i].Smpstart / (double)ch0File.Fs),
|
|
|
+ SigTime = capTime.AddSeconds(data1[i].TimeSeconds),
|
|
|
+ MainCode = MainSatCode,
|
|
|
+ AdjaCode = Adja1SatCode,
|
|
|
+ MainX = MainSatXYZ[0],
|
|
|
+ MainY = MainSatXYZ[1],
|
|
|
+ MainZ = MainSatXYZ[2],
|
|
|
+ AdjaX = Adja1SatXYZ[0],
|
|
|
+ AdjaY = Adja1SatXYZ[1],
|
|
|
+ AdjaZ = Adja1SatXYZ[2],
|
|
|
+ SxDto = PosDtoFactor * data1[i].Dt,
|
|
|
+ SxDfo = data1[i].Df,
|
|
|
+ SxSnr = data1[i].Snr,
|
|
|
+ XdDto = PosDtoFactor * data2[i].Dt,
|
|
|
+ XdDfo = data2[i].Df,
|
|
|
+ XdSnr = data2[i].Snr,
|
|
|
+ SatTxLon = dto.CapLon,
|
|
|
+ SatTxLat = dto.CapLat,
|
|
|
+ CdbTxLon = dto.CdbLon,
|
|
|
+ CdbTxLat = dto.CdbLat,
|
|
|
+ FreqDown = ch0File.FreqDownMHz * 1e6,
|
|
|
+ FreqUp = ch0File.FreqDownMHz * 1e6,
|
|
|
+ CheckRes = new CheckResDto()
|
|
|
+ {
|
|
|
+ FileName = Path.GetFileName(ch0File.File),
|
|
|
+ SmpStart = sig.Slots.Slots[i].StartPoint,
|
|
|
+ SmpCount = sig.Slots.Slots[i].Len,
|
|
|
+ PosCheckType = EnumPosCheckTypeDto.DAMA,
|
|
|
+ }
|
|
|
+ };
|
|
|
+ var result = await HttpHelper.PostRequestAsync<PosResDto>(baseUrl + "Pos/PosX2D1NoParAsync", x21d);
|
|
|
+ if (result.code != 200)
|
|
|
+ {
|
|
|
+ LogHelper.Error($"【任务{dto.ID}】-信号{group.Key}MHz-{capTime:yyyyMMddHHmmss}时刻第{i + 1}个突发定位异常.{result.msg}");
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ var posRes = result.data;
|
|
|
+ double posLon = posRes.PosLon;
|
|
|
+ double posLat = posRes.PosLat;
|
|
|
+ if (x21d.SxSnr == 0 || x21d.XdSnr == 0)
|
|
|
+ {
|
|
|
+ posLon = 0;
|
|
|
+ posLat = 0;
|
|
|
+ }
|
|
|
+ double longAxis = 0, shortAxis = 0, dipAngle = 0;
|
|
|
+ if (posLon != 0 && posLat != 0 && posLon != 999 && posLat != 999)
|
|
|
+ {
|
|
|
+ double[] cdbPos = new double[] { dto.CdbLon, dto.CdbLat, 0 };
|
|
|
+ double[] refGeod = new double[] { 0, 0, 0 };
|
|
|
+#warning 误差椭圆没有提供无参算法 暂时使用有参
|
|
|
+ double[] errorEllipse = GdopHelper.ErrorEllipse2X1D(posLon, posLat, MainSatXYZ, Adja1SatXYZ, cdbPos, refGeod, DtoErrus, EphErrm);
|
|
|
+ if (errorEllipse.Length == 3)
|
|
|
+ {
|
|
|
+ longAxis = errorEllipse[0];
|
|
|
+ shortAxis = errorEllipse[1];
|
|
|
+ dipAngle = errorEllipse[2];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
+ sb.Append($"{x21d.SigTime:yyyy}\t");
|
|
|
+ sb.Append($"{x21d.SigTime:MM}\t");
|
|
|
+ sb.Append($"{x21d.SigTime:dd}\t");
|
|
|
+ sb.Append($"{x21d.SigTime:HH}\t");
|
|
|
+ sb.Append($"{x21d.SigTime:mm}\t");
|
|
|
+ sb.Append($"{x21d.SigTime:ss}\t");
|
|
|
+ sb.Append($"{x21d.SigTime:fff}\t");
|
|
|
+ sb.Append($"{x21d.CheckRes.SmpCount * 1000 / ch0File.Fs:D4}\t");//信号持续时间ms
|
|
|
+ sb.Append($"{Convert.ToInt64(group.First().FreqDownMHz * 1e6):D12}\t");//下行频点
|
|
|
+ sb.Append($"{Convert.ToInt64((group.First().FreqDownMHz + 44) * 1e6):D12}\t");//上行频点
|
|
|
+ sb.Append($"{4}\t");//信号样式(暂定有这些1:CPM,2:BPSK,4:QPSK),
|
|
|
+ sb.Append($"{0:D4}\t");//目标序号
|
|
|
+ sb.Append($"res\t");
|
|
|
+ sb.Append($"{Convert.ToInt64(posLon * 1e6):D10}\t");
|
|
|
+ sb.Append($"{Convert.ToInt64(posLat * 1e6):D10}\t");
|
|
|
+ sb.Append($"{Convert.ToInt64(0 * 1e3):D8}\t");//定位误差km
|
|
|
+ sb.Append($"{Convert.ToInt64(x21d.SxDto * 1e2):D10}\t");
|
|
|
+ sb.Append($"{Convert.ToInt64(x21d.SxDfo * 1e2):D10}\t");
|
|
|
+ sb.Append($"{Convert.ToInt64(x21d.SxSnr * 1e2):D6}\t");
|
|
|
+ sb.Append($"{Convert.ToInt64(x21d.XdDto * 1e2):D10}\t");
|
|
|
+ sb.Append($"{Convert.ToInt64(x21d.XdDfo * 1e2):D10}\t");
|
|
|
+ sb.Append($"{Convert.ToInt64(x21d.XdSnr * 1e2):D6}\t");
|
|
|
+ sb.Append($"{Convert.ToInt64(0 * 1e2):D10}\t");
|
|
|
+ sb.Append($"{Convert.ToInt64(0 * 1e2):D10}\t");
|
|
|
+ sb.Append($"{Convert.ToInt64(0 * 1e2):D6}\t");
|
|
|
+ sb.Append($"{longAxis:F8}\t");//长轴
|
|
|
+ sb.Append($"{shortAxis:F8}\t");//短轴
|
|
|
+ sb.Append($"{dipAngle:F7}\t");//倾角
|
|
|
+ sb.Append($"{data1.Count:D2}\t");//时隙属性
|
|
|
+ sb.Append($"{1}\t");//所属卫星
|
|
|
+ sb.Append($"{950:D3}\t");//置信度
|
|
|
+ sb.Append($"{3}");//定位体制(星地=3)
|
|
|
+ sb.Append($"{signalResult.data[i].ModType.GetEnumDisplayName()}");//调制类型
|
|
|
+ sb.Append($"{signalResult.data[i].Rate * 1e-3:F3}\r\n");//符号速率kbps
|
|
|
+ string resFile = Path.Combine(PosResDir, $"定位结果_{posRes.SigTime:yyyyMMdd}.txt");
|
|
|
+ File.AppendAllText(resFile, sb.ToString());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ LogHelper.Error($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-第{i + 1}个突发定位异常", ex);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+ LogHelper.Info($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-CPU参估开始,共{sig.Slots.Slots.Count}个突发...");
|
|
|
+ sw.Start();
|
|
|
+ string mainFile = await HttpHelper.UploadFileAsync(ch0File.File, baseUrl, token: cts.Token);//主星文件
|
|
|
+ string adja1File = await HttpHelper.UploadFileAsync(ch1File.File, baseUrl, token: cts.Token);//邻1星文件
|
|
|
+ string cdbFile = await HttpHelper.UploadFileAsync(ch2File.File, baseUrl, token: cts.Token);//地面信号文件
|
|
|
+
|
|
|
+ var smpPositions = sig.Slots.Slots.Select(p => new SmpPosition() { TimeSeconds = p.TimeSeconds, smpStart = p.StartPoint, smpCount = p.Len }).ToList();
|
|
|
+ var cgDto = new CpuCgMultiDto()
|
|
|
+ {
|
|
|
+ dtCenter = 0,
|
|
|
+ dtRange = 40000,
|
|
|
+ file1 = mainFile,
|
|
|
+ file2 = adja1File,
|
|
|
+ samplingRate = ch0File.Fs,
|
|
|
+ smpPositions = smpPositions,
|
|
|
+ snrThreshold = 15,
|
|
|
+ };
|
|
|
+ var result1 = await HttpHelper.PostRequestAsync<List<CpuCgResDto>>(baseUrl + "DetectCg/CpuCgMultiCalc", cgDto, token: cts.Token);
|
|
|
+ if (result1.code != 200)
|
|
|
+ {
|
|
|
+ LogHelper.Error($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻主星邻星CPU参估出错.{result1.msg}");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ cgDto = new CpuCgMultiDto()
|
|
|
+ {
|
|
|
+ dtCenter = 260000,
|
|
|
+ dtRange = 50000,
|
|
|
+ file1 = mainFile,
|
|
|
+ file2 = cdbFile,
|
|
|
+ samplingRate = ch0File.Fs,
|
|
|
+ smpPositions = smpPositions,
|
|
|
+ snrThreshold = 15,
|
|
|
+ };
|
|
|
+ var result2 = await HttpHelper.PostRequestAsync<List<CpuCgResDto>>(baseUrl + "DetectCg/CpuCgMultiCalc", cgDto, token: cts.Token);
|
|
|
+ if (result2.code != 200)
|
|
|
+ {
|
|
|
+ LogHelper.Error($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-主星超短CPU参估出错.{result2.msg}");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ sw.Stop();
|
|
|
+ LogHelper.Info($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-CPU参估完成,耗时{sw.ElapsedMilliseconds}ms");
|
|
|
+ var signaldto = new SignalProcDto()
|
|
|
+ {
|
|
|
+ File = mainFile,
|
|
|
+ Fs = ch0File.Fs,
|
|
|
+ Smps = smpPositions,
|
|
|
+ };
|
|
|
+ var signalResult = await HttpHelper.PostRequestAsync<List<SignalProcResDto>>(baseUrl + "DetectCg/SignalProc", signaldto);
|
|
|
+ if (signalResult.code != 200)
|
|
|
+ {
|
|
|
+ LogHelper.Error($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-主星信号识别出错.{signalResult.msg}");
|
|
|
+ return;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ LogHelper.Info($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-主星超短CPU参估完成");
|
|
|
+ var data1 = result1.data;
|
|
|
+ var data2 = result2.data;
|
|
|
+ if (data1.Count != data2.Count || data1.Count != cgDto.smpPositions.Count)
|
|
|
+ {
|
|
|
+ LogHelper.Error($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-参估结果个数和检测结果个数不匹配");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (data1.Count != signalResult.data.Count)
|
|
|
+ {
|
|
|
+ LogHelper.Error($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-信号识别结果个数和检测结果个数不匹配");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ for (int i = 0; i < data1.Count; i++)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ if (cts.IsCancellationRequested) break;
|
|
|
+ X2D1NoParPosDto x21d = new X2D1NoParPosDto()
|
|
|
+ {
|
|
|
+ TaskID = dto.ID,
|
|
|
+ //SigTime = capTime.AddSeconds(data1[i].Smpstart / (double)ch0File.Fs),
|
|
|
+ SigTime = capTime.AddSeconds(data1[i].TimeSeconds),
|
|
|
+ MainCode = MainSatCode,
|
|
|
+ AdjaCode = Adja1SatCode,
|
|
|
+ MainX = MainSatXYZ[0],
|
|
|
+ MainY = MainSatXYZ[1],
|
|
|
+ MainZ = MainSatXYZ[2],
|
|
|
+ AdjaX = Adja1SatXYZ[0],
|
|
|
+ AdjaY = Adja1SatXYZ[1],
|
|
|
+ AdjaZ = Adja1SatXYZ[2],
|
|
|
+ SxDto = PosDtoFactor * data1[i].Dt,
|
|
|
+ SxDfo = data1[i].Df,
|
|
|
+ SxSnr = data1[i].Snr,
|
|
|
+ XdDto = PosDtoFactor * data2[i].Dt,
|
|
|
+ XdDfo = data2[i].Df,
|
|
|
+ XdSnr = data2[i].Snr,
|
|
|
+ SatTxLon = dto.CapLon,
|
|
|
+ SatTxLat = dto.CapLat,
|
|
|
+ CdbTxLon = dto.CdbLon,
|
|
|
+ CdbTxLat = dto.CdbLat,
|
|
|
+ FreqDown = ch0File.FreqDownMHz * 1e6,
|
|
|
+ FreqUp = ch0File.FreqDownMHz * 1e6,
|
|
|
+ CheckRes = new CheckResDto()
|
|
|
+ {
|
|
|
+ FileName = Path.GetFileName(ch0File.File),
|
|
|
+ SmpStart = sig.Slots.Slots[i].StartPoint,
|
|
|
+ SmpCount = sig.Slots.Slots[i].Len,
|
|
|
+ PosCheckType = EnumPosCheckTypeDto.DAMA,
|
|
|
+ }
|
|
|
+ };
|
|
|
+ var result = await HttpHelper.PostRequestAsync<PosResDto>(baseUrl + "Pos/PosX2D1NoParAsync", x21d);
|
|
|
+ if (result.code != 200)
|
|
|
+ {
|
|
|
+ LogHelper.Error($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-时隙位置{data1[i].Smpstart}定位异常.{result.msg}");
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ var posRes = result.data;
|
|
|
+ double posLon = posRes.PosLon;
|
|
|
+ double posLat = posRes.PosLat;
|
|
|
+ if (x21d.SxSnr == 0 || x21d.XdSnr == 0)
|
|
|
+ {
|
|
|
+ posLon = 0;
|
|
|
+ posLat = 0;
|
|
|
+ }
|
|
|
+ double longAxis = 0, shortAxis = 0, dipAngle = 0;
|
|
|
+ if (posLon != 0 && posLat != 0 && posLon != 999 && posLat != 999)
|
|
|
+ {
|
|
|
+ double[] cdbPos = new double[] { dto.CdbLon, dto.CdbLat, 0 };
|
|
|
+ double[] refGeod = new double[] { 0, 0, 0 };
|
|
|
+#warning 误差椭圆没有提供无参算法 暂时使用有参
|
|
|
+ double[] errorEllipse = GdopHelper.ErrorEllipse2X1D(posLon, posLat, MainSatXYZ, Adja1SatXYZ, cdbPos, refGeod, DtoErrus, EphErrm);
|
|
|
+ if (errorEllipse.Length == 3)
|
|
|
+ {
|
|
|
+ longAxis = errorEllipse[0];
|
|
|
+ shortAxis = errorEllipse[1];
|
|
|
+ dipAngle = errorEllipse[2];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
+ sb.Append($"{x21d.SigTime:yyyy}\t");
|
|
|
+ sb.Append($"{x21d.SigTime:MM}\t");
|
|
|
+ sb.Append($"{x21d.SigTime:dd}\t");
|
|
|
+ sb.Append($"{x21d.SigTime:HH}\t");
|
|
|
+ sb.Append($"{x21d.SigTime:mm}\t");
|
|
|
+ sb.Append($"{x21d.SigTime:ss}\t");
|
|
|
+ sb.Append($"{x21d.SigTime:fff}\t");
|
|
|
+ sb.Append($"{x21d.CheckRes.SmpCount * 1000 / ch0File.Fs:D4}\t");//信号持续时间ms
|
|
|
+ sb.Append($"{Convert.ToInt64(group.First().FreqDownMHz * 1e6):D12}\t");//下行频点
|
|
|
+ sb.Append($"{Convert.ToInt64((group.First().FreqDownMHz + 44) * 1e6):D12}\t");//上行频点
|
|
|
+ sb.Append($"{4}\t");//信号样式(暂定有这些1:CPM,2:BPSK,4:QPSK),
|
|
|
+ sb.Append($"{0:D4}\t");//目标序号
|
|
|
+ sb.Append($"res\t");
|
|
|
+ sb.Append($"{Convert.ToInt64(posLon * 1e6):D10}\t");
|
|
|
+ sb.Append($"{Convert.ToInt64(posLat * 1e6):D10}\t");
|
|
|
+ sb.Append($"{Convert.ToInt64(0 * 1e3):D8}\t");//定位误差km
|
|
|
+ sb.Append($"{Convert.ToInt64(x21d.SxDto * 1e2):D10}\t");
|
|
|
+ sb.Append($"{Convert.ToInt64(x21d.SxDfo * 1e2):D10}\t");
|
|
|
+ sb.Append($"{Convert.ToInt64(x21d.SxSnr * 1e2):D6}\t");
|
|
|
+ sb.Append($"{Convert.ToInt64(x21d.XdDto * 1e2):D10}\t");
|
|
|
+ sb.Append($"{Convert.ToInt64(x21d.XdDfo * 1e2):D10}\t");
|
|
|
+ sb.Append($"{Convert.ToInt64(x21d.XdSnr * 1e2):D6}\t");
|
|
|
+ sb.Append($"{Convert.ToInt64(0 * 1e2):D10}\t");
|
|
|
+ sb.Append($"{Convert.ToInt64(0 * 1e2):D10}\t");
|
|
|
+ sb.Append($"{Convert.ToInt64(0 * 1e2):D6}\t");
|
|
|
+ sb.Append($"{longAxis:F8}\t");//长轴
|
|
|
+ sb.Append($"{shortAxis:F8}\t");//短轴
|
|
|
+ sb.Append($"{dipAngle:F7}\t");//倾角
|
|
|
+ sb.Append($"{data1.Count:D2}\t");//时隙属性
|
|
|
+ sb.Append($"{1}\t");//所属卫星
|
|
|
+ sb.Append($"{950:D3}\t");//置信度
|
|
|
+ sb.Append($"{3}");//定位体制(星地=3)
|
|
|
+ sb.Append($"{signalResult.data[i].ModType.GetEnumDisplayName()}");//调制类型
|
|
|
+ sb.Append($"{signalResult.data[i].Rate * 1e-3:F3}\r\n");//符号速率kbps
|
|
|
+ string resFile = Path.Combine(PosResDir, $"定位结果_{posRes.SigTime:yyyyMMdd}.txt");
|
|
|
+ File.AppendAllText(resFile, sb.ToString());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ LogHelper.Error($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-时隙位置{data1[i].Smpstart}定位异常", ex);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ //删除DDC文件
|
|
|
+ File.Delete(ch0File.File);
|
|
|
+ File.Delete(ch1File.File);
|
|
|
+ File.Delete(ch2File.File);
|
|
|
+ LogHelper.Info($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-定位完成");
|
|
|
+ }, cts.Token);
|
|
|
+ listTask.Add(task);
|
|
|
+ }
|
|
|
+ await Task.WhenAll(listTask);
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+ }
|
|
|
+ catch (TaskCanceledException ex)
|
|
|
+ {
|
|
|
+ LogHelper.Warning($"【任务{dto.ID}】处理结束,用户手动终止", ex.InnerException);
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ if (ex.InnerException != null && ex.InnerException.GetType() == typeof(TaskCanceledException))
|
|
|
+ LogHelper.Warning($"【任务{dto.ID}】处理结束,用户手动终止", ex.InnerException);
|
|
|
+ else
|
|
|
+ LogHelper.Error($"【任务{dto.ID}】任务执行出错", ex);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }, cts.Token);
|
|
|
+ }
|
|
|
+ public void Stop()
|
|
|
+ {
|
|
|
+ cts?.Cancel();
|
|
|
+ }
|
|
|
+ private async Task StopTask(int taskID, EnumTaskStopType type, string stopReason)
|
|
|
+ {
|
|
|
+ await Task.Delay(2000);
|
|
|
+ if (type == EnumTaskStopType.Properly)
|
|
|
+ {
|
|
|
+ LogHelper.Info($"【任务{taskID}】{stopReason}");
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ LogHelper.Error($"【任务{taskID}】{stopReason}");
|
|
|
+ }
|
|
|
+ TaskStopHandleDto stopDto = new TaskStopHandleDto() { ID = taskID, StopType = type, StopReason = stopReason };
|
|
|
+ var stopResp = await HttpHelper.PostRequestAsync(baseUrl + "Task/StopTask", stopDto);
|
|
|
+ if (stopResp.code != 200)
|
|
|
+ {
|
|
|
+ LogHelper.Error($"【任务{taskID}】停止异常.{stopResp.msg}");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private CheckResFile StringToCheckResFile(string file)
|
|
|
+ {
|
|
|
+ //YUFO_252.050MHz_20240409_1398.dat
|
|
|
+ string fileName = Path.GetFileNameWithoutExtension(file).ToUpper();
|
|
|
+ var arr = fileName.Split(new string[] { "_", "MHZ" }, StringSplitOptions.RemoveEmptyEntries);
|
|
|
+ var dayTime = DateTime.ParseExact(arr[2], "yyyyMMdd", null);
|
|
|
+ CheckResFile res = new CheckResFile()
|
|
|
+ {
|
|
|
+ DayTime = dayTime,
|
|
|
+ File = file,
|
|
|
+ FreqDownMHz = Convert.ToDouble(arr[1]),
|
|
|
+ FlagNo = Convert.ToInt64(arr[3]),
|
|
|
+ };
|
|
|
+ return res;
|
|
|
+ }
|
|
|
+ private AdFile StringToAdFile(string file)
|
|
|
+ {
|
|
|
+ //20240409094240_ADC_ch02.dat
|
|
|
+ var name = Path.GetFileNameWithoutExtension(file).ToUpper();
|
|
|
+ var arr = name.Split(new string[] { "_", "CH" }, StringSplitOptions.RemoveEmptyEntries);
|
|
|
+ var time = DateTime.ParseExact(arr[0], "yyyyMMddHHmmss", null);
|
|
|
+ AdFile adFile = new AdFile()
|
|
|
+ {
|
|
|
+ File = file,
|
|
|
+ AdTime = time,
|
|
|
+ ChNo = Convert.ToInt32(arr[2]),
|
|
|
+ };
|
|
|
+ return adFile;
|
|
|
+ }
|
|
|
+ public DDCFile StringToDDCFile(string file)
|
|
|
+ {
|
|
|
+ //20240409094240_252.025_C109375_ch0.dat
|
|
|
+ var name = Path.GetFileNameWithoutExtension(file).ToUpper();
|
|
|
+ var arr = name.Split(new string[] { "_", "MHz", "C", "H" }, StringSplitOptions.RemoveEmptyEntries);
|
|
|
+ var time = DateTime.ParseExact(arr[0], "yyyyMMddHHmmss", null);
|
|
|
+ double freqDown = Convert.ToDouble(arr[1]);
|
|
|
+ int fs = Convert.ToInt32(arr[2]);
|
|
|
+ int chNo = Convert.ToInt32(arr[3]);
|
|
|
+ return new DDCFile()
|
|
|
+ {
|
|
|
+ AdTime = time,
|
|
|
+ ChNo = chNo,
|
|
|
+ File = file,
|
|
|
+ FreqDownMHz = freqDown,
|
|
|
+ Fs = fs
|
|
|
+ };
|
|
|
+ }
|
|
|
+ public List<DDCFile> StringToDDCFile(List<string> files)
|
|
|
+ {
|
|
|
+ List<DDCFile> list = new List<DDCFile>();
|
|
|
+ foreach (var item in files)
|
|
|
+ {
|
|
|
+ list.Add(StringToDDCFile(item));
|
|
|
+ }
|
|
|
+ return list;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|