HistoryTaskService.cs 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  1. using DevExpress.Internal.WinApi.Windows.UI.Notifications;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Configuration;
  5. using System.Diagnostics;
  6. using System.IO;
  7. using System.Linq;
  8. using System.Text;
  9. using System.Threading;
  10. using System.Threading.Tasks;
  11. using System.Web.Http.Results;
  12. using XdCxRhDW.Dto;
  13. namespace X3TaskServer54.Service
  14. {
  15. //业务逻辑处理类
  16. public class HistoryTaskService
  17. {
  18. private readonly string baseUrl;
  19. CancellationTokenSource cts;
  20. string DetectDir;
  21. string CapDir;
  22. string DdcDir;
  23. string PosResDir;
  24. int MainSatCode, Adja1SatCode, Adja2SatCode;
  25. double[] MainSatXYZ, Adja1SatXYZ, Adja2SatXYZ;
  26. int PosDtoFactor;
  27. bool useGpuCg = false;
  28. public HistoryTaskService()
  29. {
  30. Directory.CreateDirectory("tmp");
  31. var posPlatformAddr = ConfigurationManager.AppSettings["PosPlatformAddr"].Trim();//like http://127.0.0.1:8091 or http://127.0.0.1:8091/
  32. if (posPlatformAddr.EndsWith("/"))
  33. this.baseUrl = posPlatformAddr + "api/";
  34. else
  35. this.baseUrl = posPlatformAddr + "/api/";
  36. DetectDir = ConfigurationManager.AppSettings["DetectDir"].Trim();
  37. CapDir = ConfigurationManager.AppSettings["CapDir"].Trim();
  38. DdcDir = ConfigurationManager.AppSettings["DdcDir"].Trim();
  39. PosResDir = ConfigurationManager.AppSettings["PosResDir"].Trim();
  40. var PosDtoFactorstr = ConfigurationManager.AppSettings["PosDtoFactor"].Trim();
  41. int.TryParse(PosDtoFactorstr, out PosDtoFactor);
  42. if (PosDtoFactor == 0) PosDtoFactor = 1;
  43. string useGpuStr = ConfigurationManager.AppSettings["UseGpuCg"];
  44. if (useGpuStr != null && useGpuStr.Trim() == "1")
  45. useGpuCg = true;
  46. }
  47. public void StartAsync(X3NoRefTaskHandleDto dto)
  48. {
  49. cts = new CancellationTokenSource();
  50. Task.Run(async () =>
  51. {
  52. LogHelper.Info($"【任务{dto.ID}】开始执行...");
  53. //点击定位平台右上角查看接口可以在浏览器中查看平台提供的所有接口详细信息
  54. while (!cts.IsCancellationRequested)
  55. {
  56. try
  57. {
  58. #region 第1步,读取需要的配置信息
  59. if (!Directory.Exists(DetectDir))
  60. {
  61. StopTask(dto.ID, EnumTaskStopType.Error, $"检测结果目录[{DetectDir}]不存在");
  62. return;
  63. }
  64. if (!Directory.Exists(CapDir))
  65. {
  66. StopTask(dto.ID, EnumTaskStopType.Error, $"AD采集目录[{CapDir}]不存在");
  67. return;
  68. }
  69. Directory.CreateDirectory(DdcDir);
  70. Directory.CreateDirectory(PosResDir);
  71. LogHelper.Info($"【任务{dto.ID}】检测结果目录[{DetectDir}]");
  72. LogHelper.Info($"【任务{dto.ID}】AD采集目录[{CapDir}]");
  73. LogHelper.Info($"【任务{dto.ID}】DDC输出目录[{DdcDir}]");
  74. try
  75. {
  76. var mainInfo = ConfigurationManager.AppSettings["MainSatInfo"].Replace(",", ",").Trim();
  77. var adja1Info = ConfigurationManager.AppSettings["Adja1SatInfo"].Replace(",", ",").Trim();
  78. var adja2Info = ConfigurationManager.AppSettings["Adja2SatInfo"].Replace(",", ",").Trim();
  79. var arr1 = mainInfo.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
  80. var arr2 = adja1Info.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
  81. var arr3 = adja2Info.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
  82. MainSatCode = Convert.ToInt32(arr1[0]);
  83. Adja1SatCode = Convert.ToInt32(arr2[0]);
  84. Adja2SatCode = Convert.ToInt32(arr3[0]);
  85. MainSatXYZ = new double[3] { Convert.ToDouble(arr1[1]), Convert.ToDouble(arr1[2]), Convert.ToDouble(arr1[3]) };
  86. Adja1SatXYZ = new double[3] { Convert.ToDouble(arr2[1]), Convert.ToDouble(arr2[2]), Convert.ToDouble(arr2[3]) };
  87. Adja2SatXYZ = new double[3] { Convert.ToDouble(arr3[1]), Convert.ToDouble(arr3[2]), Convert.ToDouble(arr3[3]) };
  88. }
  89. catch
  90. {
  91. StopTask(dto.ID, EnumTaskStopType.Error, $"任务处理服务配置文件卫星信息解析出错");
  92. return;
  93. }
  94. #endregion
  95. #region 第2步,扫描检测结果目录
  96. var groupFiles = Directory.EnumerateFiles(DetectDir, "*.dat", SearchOption.TopDirectoryOnly).Select(p => StringToCheckResFile(p))
  97. .GroupBy(m => Convert.ToInt64(m.DayTime.ToString("yyyyMMdd") + m.FlagNo)).OrderBy(m => m.Key);
  98. if (!groupFiles.Any())
  99. {
  100. LogHelper.Info($"【任务{dto.ID}】等待扫描文件...");
  101. await Task.Delay(10000);
  102. }
  103. foreach (var groupFile in groupFiles)//每一组文件代表同一个时刻的
  104. {
  105. if (cts.IsCancellationRequested) break;
  106. List<SlotsInfo> listSlotsInfo = new List<SlotsInfo>();//多个频点的时隙结果
  107. foreach (var item in groupFile)
  108. {
  109. var slotsInfo = SlotHelper.GetFileSlots(item.File);//某个频点的所有时隙
  110. if (!Debugger.IsAttached)
  111. File.Delete(item.File);//检测检测结果文件
  112. if (slotsInfo.Slots.Any())
  113. listSlotsInfo.Add(slotsInfo);
  114. }
  115. if (!listSlotsInfo.Any()) continue;
  116. var adFiles = Directory.EnumerateFiles(CapDir, "*.dat", SearchOption.TopDirectoryOnly).Select(p => StringToAdFile(p))
  117. .Where(p => p.AdTime == listSlotsInfo.First().AdTime);
  118. if (!adFiles.Any())
  119. {
  120. LogHelper.Warning($"【任务{dto.ID}】{listSlotsInfo.First().AdTime:yyyyMMddHHmmss}时刻找不到原始AD文件,跳过此组文件");
  121. continue;
  122. }
  123. var first = listSlotsInfo.First();
  124. var sigs = listSlotsInfo.Select(p => new DDCSig() { FreqDownHz = (int)(p.FreqDownMHz * 1e6), Mult = (int)first.Multi, Slots = p });
  125. List<DDCFile> chDDCFiles = new List<DDCFile>();//同一个时刻多个频点多个通道的DDC数据
  126. LogHelper.Info($"【任务{dto.ID}】{listSlotsInfo.First().AdTime:yyyyMMddHHmmss}时刻DDC处理开始,共{sigs.Count()}个频点...");
  127. Stopwatch sw = new Stopwatch();
  128. sw.Start();
  129. Parallel.ForEach(adFiles, adFile =>
  130. {
  131. //227=变频器频点255-(140-112))
  132. var ddcRes = DDCHelper.DDC(adFile.File, adFile.AdTime, adFile.ChNo, (long)(first.FsampleM * 1e6), (long)(227 * 1e6), DdcDir, sigs);
  133. chDDCFiles.AddRange(StringToDDCFile(ddcRes));
  134. if (!Debugger.IsAttached)
  135. File.Delete(adFile.File);//删除AD文件
  136. });
  137. sw.Stop();
  138. LogHelper.Info($"【任务{dto.ID}】{listSlotsInfo.First().AdTime:yyyyMMddHHmmss}时刻DDC处理完成,耗时{sw.ElapsedMilliseconds}ms");
  139. if (!chDDCFiles.Any())
  140. {
  141. LogHelper.Error($"【任务{dto.ID}】{listSlotsInfo.First().AdTime:yyyyMMddHHmmss}时刻DDC处理无结果");
  142. continue;
  143. }
  144. var groupDDCFiles = chDDCFiles.GroupBy(p => p.FreqDownMHz);
  145. foreach (var group in groupDDCFiles)
  146. {
  147. //group:同一个时刻同一个频点的多个通道数据
  148. var capTime = group.First().AdTime;
  149. var ch0File = group.Where(p => p.ChNo == 0).FirstOrDefault();
  150. var ch1File = group.Where(p => p.ChNo == 1).FirstOrDefault();
  151. var ch2File = group.Where(p => p.ChNo == 2).FirstOrDefault();
  152. if (ch0File == null)
  153. {
  154. LogHelper.Warning($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-未找到主星信号ch0文件,跳过此组数据");
  155. continue;
  156. }
  157. if (ch1File == null)
  158. {
  159. LogHelper.Warning($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-未找到邻1星信号ch1文件,跳过此组数据");
  160. continue;
  161. }
  162. if (ch2File == null)
  163. {
  164. LogHelper.Warning($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-未找到邻2星信号ch2文件,跳过此组数据");
  165. continue;
  166. }
  167. var sig = sigs.FirstOrDefault(p => p.FreqDownHz == (int)(group.Key * 1e6));
  168. if (useGpuCg)
  169. {
  170. LogHelper.Info($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-GPU参估开始,共{sig.Slots.Slots.Count}个突发...");
  171. sw.Start();
  172. List<GpuCgResponseDto> data1 = new List<GpuCgResponseDto>();
  173. List<GpuCgResponseDto> data2 = new List<GpuCgResponseDto>();
  174. foreach (var item in sig.Slots.Slots)
  175. {
  176. string f1 = $"tmp\\{Path.GetFileNameWithoutExtension(ch0File.File)}_{item.StartPoint}_{item.Len}.dat";
  177. string f2 = $"tmp\\{Path.GetFileNameWithoutExtension(ch1File.File)}_{item.StartPoint}_{item.Len}.dat";
  178. string f3 = $"tmp\\{Path.GetFileNameWithoutExtension(ch2File.File)}_{item.StartPoint}_{item.Len}.dat";
  179. using (FileStream fs = new FileStream(ch0File.File, FileMode.Open))
  180. {
  181. byte[] data = new byte[item.Len * 4];
  182. fs.Position = item.StartPoint * 4;
  183. fs.Read(data, 0, data.Length);
  184. File.WriteAllBytes(f1, data);
  185. }
  186. using (FileStream fs = new FileStream(ch1File.File, FileMode.Open))
  187. {
  188. byte[] data = new byte[item.Len * 4];
  189. fs.Position = item.StartPoint * 4;
  190. fs.Read(data, 0, data.Length);
  191. File.WriteAllBytes(f2, data);
  192. }
  193. using (FileStream fs = new FileStream(ch2File.File, FileMode.Open))
  194. {
  195. byte[] data = new byte[item.Len * 4];
  196. fs.Position = item.StartPoint * 4;
  197. fs.Read(data, 0, data.Length);
  198. File.WriteAllBytes(f3, data);
  199. }
  200. string mainSlotFile = await HttpHelper.UploadFileAsync(f1, baseUrl, token: cts.Token);//主星文件
  201. string adja1SlotFile = await HttpHelper.UploadFileAsync(f2, baseUrl, token: cts.Token);//邻1星文件
  202. string adja2SlotFile = await HttpHelper.UploadFileAsync(f3, baseUrl, token: cts.Token);//邻2星文件
  203. File.Delete(f1);
  204. File.Delete(f2);
  205. File.Delete(f3);
  206. var gpudto = new GpuCgRequestDto()
  207. {
  208. dtCenter = 0,
  209. dtRange = 40000,
  210. file1 = mainSlotFile,
  211. file2 = adja1SlotFile,
  212. samplingRate = ch0File.Fs,
  213. smpCount = 0,
  214. snrThreshold = 15
  215. };
  216. var result1 = await HttpHelper.PostRequestAsync<List<GpuCgResponseDto>>(baseUrl + "DetectCg/GpuCgCalc", gpudto, token: cts.Token);
  217. if (result1.code != 200)
  218. {
  219. LogHelper.Error($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-主星邻1星GPU参估出错.{result1.msg}.突发位置{item.StartPoint}-{item.Len}");
  220. continue;
  221. }
  222. var data1First = result1.data.First();
  223. data1First.TimeSeconds = item.TimeSeconds;
  224. data1.Add(data1First);
  225. gpudto = new GpuCgRequestDto()
  226. {
  227. dtCenter = 0,
  228. dtRange = 40000,
  229. file1 = mainSlotFile,
  230. file2 = adja2SlotFile,
  231. samplingRate = ch0File.Fs,
  232. smpCount = 0,
  233. snrThreshold = 15
  234. };
  235. var result2 = await HttpHelper.PostRequestAsync<List<GpuCgResponseDto>>(baseUrl + "DetectCg/GpuCgCalc", gpudto, token: cts.Token);
  236. if (result2.code != 200)
  237. {
  238. LogHelper.Error($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-主星邻2星GPU参估出错.{result2.msg}.突发位置{item.StartPoint}-{item.Len}");
  239. continue;
  240. }
  241. var data2First = result2.data.First();
  242. data2First.TimeSeconds = item.TimeSeconds;
  243. data2.Add(data2First);
  244. }
  245. sw.Stop();
  246. LogHelper.Info($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-GPU参估完成,耗时{sw.ElapsedMilliseconds}ms");
  247. if (data1.Count != data2.Count || data1.Count != sig.Slots.Slots.Count)
  248. {
  249. LogHelper.Error($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻参估结果个数和检测结果个数不匹配");
  250. continue;
  251. }
  252. for (int i = 0; i < data1.Count; i++)
  253. {
  254. try
  255. {
  256. if (cts.IsCancellationRequested) break;
  257. X3TwoDtoNoParPosDto x3 = new X3TwoDtoNoParPosDto()
  258. {
  259. TaskID = dto.ID,
  260. //SigTime = capTime.AddSeconds(data1[i].Smpstart / (double)ch0File.Fs),
  261. SigTime = capTime.AddSeconds(data1[i].TimeSeconds),
  262. MainCode = MainSatCode,
  263. Adja1Code = Adja1SatCode,
  264. Adja2Code = Adja2SatCode,
  265. MainX = MainSatXYZ[0],
  266. MainY = MainSatXYZ[1],
  267. MainZ = MainSatXYZ[2],
  268. Adja1X = Adja1SatXYZ[0],
  269. Adja1Y = Adja1SatXYZ[1],
  270. Adja1Z = Adja1SatXYZ[2],
  271. Adja2X = Adja2SatXYZ[0],
  272. Adja2Y = Adja2SatXYZ[1],
  273. Adja2Z = Adja2SatXYZ[2],
  274. Dto1 = PosDtoFactor * data1[i].Dt,
  275. Dfo1 = data1[i].Df,
  276. Snr1 = data1[i].Snr,
  277. Dto2 = PosDtoFactor * data2[i].Dt,
  278. Dfo2 = data2[i].Df,
  279. Snr2 = data2[i].Snr,
  280. FreqUp = ch0File.FreqDownMHz * 1e6,
  281. SatTxLon = dto.CapLon,
  282. SatTxLat = dto.CapLat,
  283. FreqDown = ch0File.FreqDownMHz * 1e6,
  284. CheckRes = new CheckResDto()
  285. {
  286. FileName = Path.GetFileName(ch0File.File),
  287. SmpStart = sig.Slots.Slots[i].StartPoint,
  288. SmpCount = sig.Slots.Slots[i].Len,
  289. PosCheckType = EnumPosCheckTypeDto.DAMA,
  290. }
  291. };
  292. var result = await HttpHelper.PostRequestAsync<PosResDto>(baseUrl + "Pos/PosX3TwoDtoNoParAsync", x3);
  293. if (result.code != 200)
  294. {
  295. LogHelper.Error($"【任务{dto.ID}】-信号{group.Key}MHz-{capTime:yyyyMMddHHmmss}时刻第{i + 1}个突发定位异常.{result.msg}");
  296. }
  297. else
  298. {
  299. var posRes = result.data;
  300. double posLon = posRes.PosLon;
  301. double posLat = posRes.PosLat;
  302. if (x3.Snr1 == 0 || x3.Snr2 == 0)
  303. {
  304. posLon = 0;
  305. posLat = 0;
  306. }
  307. StringBuilder sb = new StringBuilder();
  308. sb.Append($"{x3.SigTime:yyyy}\t");
  309. sb.Append($"{x3.SigTime:MM}\t");
  310. sb.Append($"{x3.SigTime:dd}\t");
  311. sb.Append($"{x3.SigTime:HH}\t");
  312. sb.Append($"{x3.SigTime:mm}\t");
  313. sb.Append($"{x3.SigTime:ss}\t");
  314. sb.Append($"{x3.SigTime:fff}\t");
  315. sb.Append($"{x3.CheckRes.SmpCount * 1000 / ch0File.Fs:D4}\t");//信号持续时间ms
  316. sb.Append($"{Convert.ToInt64(group.First().FreqDownMHz * 1e6):D12}\t");//下行频点
  317. sb.Append($"{Convert.ToInt64((group.First().FreqDownMHz + 44) * 1e6):D12}\t");//上行频点
  318. sb.Append($"{4}\t");//信号样式(暂定有这些1:CPM,2:BPSK,4:QPSK),
  319. sb.Append($"{0:D4}\t");//目标序号
  320. sb.Append($"res\t");
  321. sb.Append($"{Convert.ToInt64(posLon * 1e6):D10}\t");
  322. sb.Append($"{Convert.ToInt64(posLat * 1e6):D10}\t");
  323. sb.Append($"{Convert.ToInt64(0 * 1e3):D8}\t");//定位误差km
  324. sb.Append($"{Convert.ToInt64(x3.Dto1 * 1e2):D10}\t");
  325. sb.Append($"{Convert.ToInt64(x3.Dfo1 * 1e2):D10}\t");
  326. sb.Append($"{Convert.ToInt64(x3.Snr1 * 1e2):D6}\t");
  327. sb.Append($"{Convert.ToInt64(x3.Dto2 * 1e2):D10}\t");
  328. sb.Append($"{Convert.ToInt64(x3.Dfo2 * 1e2):D10}\t");
  329. sb.Append($"{Convert.ToInt64(x3.Snr2 * 1e2):D6}\t");
  330. sb.Append($"{Convert.ToInt64(0 * 1e2):D10}\t");
  331. sb.Append($"{Convert.ToInt64(0 * 1e2):D10}\t");
  332. sb.Append($"{Convert.ToInt64(0 * 1e2):D6}\t");
  333. sb.Append($"{0:D8}\t");//长轴
  334. sb.Append($"{0:D8}\t");//短轴
  335. sb.Append($"{0:D7}\t");//倾角
  336. sb.Append($"{data1.Count:D2}\t");//时隙属性
  337. sb.Append($"{1}\t");//所属卫星
  338. sb.Append($"{950:D3}\t");//置信度
  339. sb.Append($"{3}\r\n");//定位体制(星地=3)
  340. string resFile = Path.Combine(PosResDir, $"定位结果_{posRes.SigTime:yyyyMMdd}.txt");
  341. File.AppendAllText(resFile, sb.ToString());
  342. }
  343. }
  344. catch (Exception ex)
  345. {
  346. LogHelper.Error($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-第{i + 1}个突发定位异常", ex);
  347. }
  348. }
  349. }
  350. else
  351. {
  352. LogHelper.Info($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-CPU参估开始,共{sig.Slots.Slots.Count}个突发...");
  353. sw.Start();
  354. string mainFile = await HttpHelper.UploadFileAsync(ch0File.File, baseUrl, token: cts.Token);//主星文件
  355. string adja1File = await HttpHelper.UploadFileAsync(ch1File.File, baseUrl, token: cts.Token);//邻1星文件
  356. string adja2File = await HttpHelper.UploadFileAsync(ch2File.File, baseUrl, token: cts.Token);//邻2星文件
  357. var cgDto = new CpuCgMultiDto()
  358. {
  359. dtCenter = 0,
  360. dtRange = 40000,
  361. file1 = mainFile,
  362. file2 = adja1File,
  363. samplingRate = ch0File.Fs,
  364. smpPositions = sig.Slots.Slots.Select(p => new SmpPosition() { TimeSeconds = p.TimeSeconds, smpStart = p.StartPoint, smpCount = p.Len }).ToList(),
  365. snrThreshold = 15,
  366. };
  367. var result1 = await HttpHelper.PostRequestAsync<List<CpuCgResDto>>(baseUrl + "DetectCg/CpuCgMultiCalc", cgDto, token: cts.Token);
  368. if (result1.code != 200)
  369. {
  370. LogHelper.Error($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-主星邻1星CPU参估出错.{result1.msg}");
  371. continue;
  372. }
  373. cgDto = new CpuCgMultiDto()
  374. {
  375. dtCenter = 0,
  376. dtRange = 40000,
  377. file1 = mainFile,
  378. file2 = adja2File,
  379. samplingRate = ch0File.Fs,
  380. smpPositions = sig.Slots.Slots.Select(p => new SmpPosition() { TimeSeconds = p.TimeSeconds, smpStart = p.StartPoint, smpCount = p.Len }).ToList(),
  381. snrThreshold = 15,
  382. };
  383. var result2 = await HttpHelper.PostRequestAsync<List<CpuCgResDto>>(baseUrl + "DetectCg/CpuCgMultiCalc", cgDto, token: cts.Token);
  384. sw.Stop();
  385. if (result2.code != 200)
  386. {
  387. LogHelper.Error($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-主星邻2星CPU参估出错.{result2.msg}");
  388. continue;
  389. }
  390. LogHelper.Info($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-CPU参估完成,耗时{sw.ElapsedMilliseconds}ms");
  391. var data1 = result1.data;
  392. var data2 = result2.data;
  393. if (data1.Count != data2.Count || data1.Count != cgDto.smpPositions.Count)
  394. {
  395. LogHelper.Error($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-参估结果个数和检测结果个数不匹配");
  396. continue;
  397. }
  398. for (int i = 0; i < data1.Count; i++)
  399. {
  400. try
  401. {
  402. if (cts.IsCancellationRequested) break;
  403. X3TwoDtoNoParPosDto x3 = new X3TwoDtoNoParPosDto()
  404. {
  405. TaskID = dto.ID,
  406. //SigTime = capTime.AddSeconds(data1[i].Smpstart / (double)ch0File.Fs),
  407. SigTime = capTime.AddSeconds(data1[i].TimeSeconds),
  408. MainCode = MainSatCode,
  409. Adja1Code = Adja1SatCode,
  410. Adja2Code = Adja2SatCode,
  411. MainX = MainSatXYZ[0],
  412. MainY = MainSatXYZ[1],
  413. MainZ = MainSatXYZ[2],
  414. Adja1X = Adja1SatXYZ[0],
  415. Adja1Y = Adja1SatXYZ[1],
  416. Adja1Z = Adja1SatXYZ[2],
  417. Adja2X = Adja2SatXYZ[0],
  418. Adja2Y = Adja2SatXYZ[1],
  419. Adja2Z = Adja2SatXYZ[2],
  420. Dto1 = PosDtoFactor * data1[i].Dt,
  421. Dfo1 = data1[i].Df,
  422. Snr1 = data1[i].Snr,
  423. Dto2 = PosDtoFactor * data2[i].Dt,
  424. Dfo2 = data2[i].Df,
  425. Snr2 = data2[i].Snr,
  426. SatTxLon = dto.CapLon,
  427. SatTxLat = dto.CapLat,
  428. FreqDown = ch0File.FreqDownMHz * 1e6,
  429. FreqUp = ch0File.FreqDownMHz * 1e6,
  430. CheckRes = new CheckResDto()
  431. {
  432. FileName = Path.GetFileName(ch0File.File),
  433. SmpStart = sig.Slots.Slots[i].StartPoint,
  434. SmpCount = sig.Slots.Slots[i].Len,
  435. PosCheckType = EnumPosCheckTypeDto.DAMA,
  436. }
  437. };
  438. var result = await HttpHelper.PostRequestAsync<PosResDto>(baseUrl + "Pos/PosX3TwoDtoNoParAsync", x3);
  439. if (result.code != 200)
  440. {
  441. LogHelper.Error($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-时隙位置{data1[i].Smpstart}定位异常.{result.msg}");
  442. }
  443. else
  444. {
  445. var posRes = result.data;
  446. double posLon = posRes.PosLon;
  447. double posLat = posRes.PosLat;
  448. if (x3.Snr1 == 0 || x3.Snr2 == 0)
  449. {
  450. posLon = 0;
  451. posLat = 0;
  452. }
  453. StringBuilder sb = new StringBuilder();
  454. sb.Append($"{x3.SigTime:yyyy}\t");
  455. sb.Append($"{x3.SigTime:MM}\t");
  456. sb.Append($"{x3.SigTime:dd}\t");
  457. sb.Append($"{x3.SigTime:HH}\t");
  458. sb.Append($"{x3.SigTime:mm}\t");
  459. sb.Append($"{x3.SigTime:ss}\t");
  460. sb.Append($"{x3.SigTime:fff}\t");
  461. sb.Append($"{x3.CheckRes.SmpCount * 1000 / ch0File.Fs:D4}\t");//信号持续时间ms
  462. sb.Append($"{Convert.ToInt64(group.First().FreqDownMHz * 1e6):D12}\t");//下行频点
  463. sb.Append($"{Convert.ToInt64((group.First().FreqDownMHz + 44) * 1e6):D12}\t");//上行频点
  464. sb.Append($"{4}\t");//信号样式(暂定有这些1:CPM,2:BPSK,4:QPSK),
  465. sb.Append($"{0:D4}\t");//目标序号
  466. sb.Append($"res\t");
  467. sb.Append($"{Convert.ToInt64(posLon * 1e6):D10}\t");
  468. sb.Append($"{Convert.ToInt64(posLat * 1e6):D10}\t");
  469. sb.Append($"{Convert.ToInt64(0 * 1e3):D8}\t");//定位误差km
  470. sb.Append($"{Convert.ToInt64(x3.Dto1 * 1e2):D10}\t");
  471. sb.Append($"{Convert.ToInt64(x3.Dfo1 * 1e2):D10}\t");
  472. sb.Append($"{Convert.ToInt64(x3.Snr1 * 1e2):D6}\t");
  473. sb.Append($"{Convert.ToInt64(x3.Dto2 * 1e2):D10}\t");
  474. sb.Append($"{Convert.ToInt64(x3.Dfo2 * 1e2):D10}\t");
  475. sb.Append($"{Convert.ToInt64(x3.Snr2 * 1e2):D6}\t");
  476. sb.Append($"{Convert.ToInt64(0 * 1e2):D10}\t");
  477. sb.Append($"{Convert.ToInt64(0 * 1e2):D10}\t");
  478. sb.Append($"{Convert.ToInt64(0 * 1e2):D6}\t");
  479. sb.Append($"{0:D8}\t");//长轴
  480. sb.Append($"{0:D8}\t");//短轴
  481. sb.Append($"{0:D7}\t");//倾角
  482. sb.Append($"{data1.Count:D2}\t");//时隙属性
  483. sb.Append($"{1}\t");//所属卫星
  484. sb.Append($"{950:D3}\t");//置信度
  485. sb.Append($"{3}");//定位体制(星地=3)
  486. sb.Append($"QPSK");//调制类型
  487. sb.Append($"1.33\r\n");//符号速率kbps
  488. string resFile = Path.Combine(PosResDir, $"定位结果_{posRes.SigTime:yyyyMMdd}.txt");
  489. File.AppendAllText(resFile, sb.ToString());
  490. }
  491. }
  492. catch (Exception ex)
  493. {
  494. LogHelper.Error($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-时隙位置{data1[i].Smpstart}定位异常", ex);
  495. }
  496. }
  497. }
  498. //删除DDC文件
  499. File.Delete(ch0File.File);
  500. File.Delete(ch1File.File);
  501. File.Delete(ch2File.File);
  502. LogHelper.Info($"【任务{dto.ID}】{capTime:yyyyMMddHHmmss}时刻-信号{group.Key}MHz-定位完成");
  503. }
  504. }
  505. #endregion
  506. }
  507. catch (TaskCanceledException ex)
  508. {
  509. LogHelper.Warning($"【任务{dto.ID}】处理结束,用户手动终止", ex.InnerException);
  510. }
  511. catch (Exception ex)
  512. {
  513. if (ex.InnerException != null && ex.InnerException.GetType() == typeof(TaskCanceledException))
  514. LogHelper.Warning($"【任务{dto.ID}】处理结束,用户手动终止", ex.InnerException);
  515. else
  516. LogHelper.Error($"【任务{dto.ID}】任务执行出错", ex);
  517. continue;
  518. }
  519. }
  520. }, cts.Token);
  521. }
  522. public void Stop()
  523. {
  524. cts?.Cancel();
  525. }
  526. private void StopTask(int taskID, EnumTaskStopType type, string stopReason)
  527. {
  528. Thread.Sleep(2000);
  529. if (type == EnumTaskStopType.Properly)
  530. {
  531. LogHelper.Info($"【任务{taskID}】{stopReason}");
  532. }
  533. else
  534. {
  535. LogHelper.Error($"【任务{taskID}】{stopReason}");
  536. }
  537. TaskStopHandleDto stopDto = new TaskStopHandleDto() { ID = taskID, StopType = type, StopReason = stopReason };
  538. var stopResp = HttpHelper.PostRequestAsync(baseUrl + "Task/StopTask", stopDto).Result;
  539. if (stopResp.code != 200)
  540. {
  541. LogHelper.Error($"【任务{taskID}】停止异常.{stopResp.msg}");
  542. }
  543. }
  544. private CheckResFile StringToCheckResFile(string file)
  545. {
  546. //YUFO_252.050MHz_20240409_1398.dat
  547. string fileName = Path.GetFileNameWithoutExtension(file).ToUpper();
  548. var arr = fileName.Split(new string[] { "_", "MHZ" }, StringSplitOptions.RemoveEmptyEntries);
  549. var dayTime = DateTime.ParseExact(arr[2], "yyyyMMdd", null);
  550. CheckResFile res = new CheckResFile()
  551. {
  552. DayTime = dayTime,
  553. File = file,
  554. FreqDownMHz = Convert.ToDouble(arr[1]),
  555. FlagNo = Convert.ToInt64(arr[3]),
  556. };
  557. return res;
  558. }
  559. private AdFile StringToAdFile(string file)
  560. {
  561. //20240409094240_ADC_ch02.dat
  562. var name = Path.GetFileNameWithoutExtension(file).ToUpper();
  563. var arr = name.Split(new string[] { "_", "CH" }, StringSplitOptions.RemoveEmptyEntries);
  564. var time = DateTime.ParseExact(arr[0], "yyyyMMddHHmmss", null);
  565. AdFile adFile = new AdFile()
  566. {
  567. File = file,
  568. AdTime = time,
  569. ChNo = Convert.ToInt32(arr[2]),
  570. };
  571. return adFile;
  572. }
  573. public DDCFile StringToDDCFile(string file)
  574. {
  575. //20240409094240_252.025_C109375_ch0.dat
  576. var name = Path.GetFileNameWithoutExtension(file).ToUpper();
  577. var arr = name.Split(new string[] { "_", "MHz", "C", "H" }, StringSplitOptions.RemoveEmptyEntries);
  578. var time = DateTime.ParseExact(arr[0], "yyyyMMddHHmmss", null);
  579. double freqDown = Convert.ToDouble(arr[1]);
  580. int fs = Convert.ToInt32(arr[2]);
  581. int chNo = Convert.ToInt32(arr[3]);
  582. return new DDCFile()
  583. {
  584. AdTime = time,
  585. ChNo = chNo,
  586. File = file,
  587. FreqDownMHz = freqDown,
  588. Fs = fs
  589. };
  590. }
  591. public List<DDCFile> StringToDDCFile(List<string> files)
  592. {
  593. List<DDCFile> list = new List<DDCFile>();
  594. foreach (var item in files)
  595. {
  596. list.Add(StringToDDCFile(item));
  597. }
  598. return list;
  599. }
  600. }
  601. }