TaskService.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Configuration;
  4. using System.Diagnostics;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading;
  9. using System.Threading.Tasks;
  10. using XdCxRhDW.Dto;
  11. namespace X1LeoTaskServer54.Service
  12. {
  13. //业务逻辑处理类
  14. public class TaskService
  15. {
  16. private readonly string baseUrl;
  17. CancellationTokenSource cts;
  18. string CapDir;
  19. int MainSatCode;
  20. double[] Time1XYZ, Time2XYZ, Time3XYZ;
  21. int PosDtoFactor;
  22. double DfoErrHz;
  23. double EphPosErrM;
  24. double EphVelErr;
  25. public TaskService()
  26. {
  27. Directory.CreateDirectory("tmp");
  28. var posPlatformAddr = ConfigurationManager.AppSettings["PosPlatformAddr"].Trim();//like http://127.0.0.1:8091 or http://127.0.0.1:8091/
  29. if (posPlatformAddr.EndsWith("/"))
  30. this.baseUrl = posPlatformAddr + "api/";
  31. else
  32. this.baseUrl = posPlatformAddr + "/api/";
  33. CapDir = ConfigurationManager.AppSettings["CapDir"].Trim();
  34. var PosDtoFactorstr = ConfigurationManager.AppSettings["PosDtoFactor"].Trim();
  35. int.TryParse(PosDtoFactorstr, out PosDtoFactor);
  36. if (PosDtoFactor == 0) PosDtoFactor = 1;
  37. var DfoErrusstr = ConfigurationManager.AppSettings["DfoErr"].Trim();
  38. double.TryParse(DfoErrusstr, out DfoErrHz);
  39. var EphPosErrstr = ConfigurationManager.AppSettings["EphPosErr"].Trim();
  40. double.TryParse(EphPosErrstr, out EphPosErrM);
  41. var EphVelErrstr = ConfigurationManager.AppSettings["EphVelErr"].Trim();
  42. double.TryParse(EphVelErrstr, out EphVelErr);
  43. }
  44. /// <summary>
  45. /// 扫描 检测 参估 定位
  46. /// </summary>
  47. /// <param name="dto"></param>
  48. public void StartAsync(LeoSat1TaskHandleDto dto)
  49. {
  50. cts = new CancellationTokenSource();
  51. Task.Run(async () =>
  52. {
  53. await LogHelper.Info($"【任务{dto.ID}】开始执行...");
  54. await LogHelper.Info($"【任务{dto.ID}】AD采集目录[{CapDir}]");
  55. await LogHelper.Info($"【任务{dto.ID}】状态上报输出目录[{dto.StateDir}]");
  56. //点击定位平台右上角查看接口可以在浏览器中查看平台提供的所有接口详细信息
  57. while (!cts.IsCancellationRequested)
  58. {
  59. try
  60. {
  61. #region 第1步,读取需要的配置信息
  62. if (!Directory.Exists(CapDir))
  63. {
  64. await StopTask(dto.ID, EnumTaskStopType.Error, $"AD采集目录[{CapDir}]不存在");
  65. return;
  66. }
  67. Directory.CreateDirectory(dto.PosDir);
  68. try
  69. {
  70. var mainInfo = ConfigurationManager.AppSettings["Time1SatInfo"].Replace(",", ",").Trim();
  71. var adja1Info = ConfigurationManager.AppSettings["Time2SatInfo"].Replace(",", ",").Trim();
  72. var adja2Info = ConfigurationManager.AppSettings["Time3SatInfo"].Replace(",", ",").Trim();
  73. var arr1 = mainInfo.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
  74. var arr2 = adja1Info.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
  75. var arr3 = adja2Info.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
  76. MainSatCode = Convert.ToInt32(arr1[0]);
  77. Time1XYZ = GetEph(arr1);
  78. Time2XYZ = GetEph(arr2);
  79. Time3XYZ = GetEph(arr3);
  80. }
  81. catch
  82. {
  83. await StopTask(dto.ID, EnumTaskStopType.Error, $"任务处理服务配置文件卫星信息解析出错");
  84. return;
  85. }
  86. #endregion
  87. #region 第2步,扫描采集文件
  88. var groupFiles = Directory.EnumerateFiles(CapDir, "*.dat", SearchOption.TopDirectoryOnly).Select(p => StringToAdFile(p))
  89. .GroupBy(p => p.FreqDownMHz);
  90. bool matched = false;
  91. var listTask = new List<Task>();
  92. foreach (var groupFile in groupFiles)//按频点分组
  93. {
  94. var task = Task.Run(async () =>
  95. {
  96. var oneFreqItems = groupFile.OrderBy(p => p.AdTime).ToList();//按时间排序
  97. int idx = 0;
  98. while (oneFreqItems.Count > idx + 2)//表示能取到3个文件
  99. {
  100. var adFile1 = oneFreqItems[idx];
  101. var adFile2 = oneFreqItems[idx + 1];
  102. var adFile3 = oneFreqItems[idx + 2];
  103. var adTime = adFile1.AdTime;
  104. var freq = adFile1.FreqDownMHz;
  105. matched = true;
  106. if (cts.IsCancellationRequested) return;
  107. Stopwatch sw = new Stopwatch();
  108. sw.Start();
  109. string mainFile = await HttpHelper.UploadFileAsync(adFile1.File, baseUrl, token: cts.Token);//主星文件
  110. string adja1File = await HttpHelper.UploadFileAsync(adFile2.File, baseUrl, token: cts.Token);//邻1星文件
  111. string adja2File = await HttpHelper.UploadFileAsync(adFile3.File, baseUrl, token: cts.Token);//邻2星文件
  112. DetectDto detectDto = new DetectDto()
  113. {
  114. file1 = mainFile,
  115. dmcType = EnumSigCheckTypeDto.Ky5758,
  116. fsHz = adFile1.Fs,
  117. mergeRes = true,
  118. SigProc = true,
  119. };
  120. var deteResp = await HttpHelper.PostRequestAsync<List<DetectResDto>>(baseUrl + "DetectCg/DetectCalc", detectDto, token: cts.Token);
  121. if (deteResp.code != 200)
  122. {
  123. await LogHelper.Error($"【任务{dto.ID}】{adTime:yyyyMMddHHmmss}时刻-信号{freq}MHz信号检测出错.{deteResp.msg}");
  124. return;
  125. }
  126. var smps = deteResp.data.Select(m => new SmpPosition(m.Start, m.Length)).ToList();//怎么补0?
  127. await LogHelper.Info($"【任务{dto.ID}】{adTime:yyyyMMddHHmmss}时刻-信号{freq}MHz-CPU参估开始,共{smps.Count}个突发...");
  128. var cgDto = new CpuCgMultiDto()
  129. {
  130. dtCenter = 0,
  131. dtRange = 60000,
  132. file1 = mainFile,
  133. file2 = adja1File,
  134. samplingRate = adFile1.Fs,
  135. smpPositions = smps,
  136. snrThreshold = 15,
  137. };
  138. var result1 = await HttpHelper.PostRequestAsync<List<CpuCgResDto>>(baseUrl + "DetectCg/CpuCgMultiCalc", cgDto, token: cts.Token);
  139. if (result1.code != 200)
  140. {
  141. await LogHelper.Error($"【任务{dto.ID}】{adTime:yyyyMMddHHmmss}时刻-信号{freq}MHz-主星邻1星CPU参估出错.{result1.msg}");
  142. return;
  143. }
  144. cgDto = new CpuCgMultiDto()
  145. {
  146. dtCenter = 0,
  147. dtRange = 60000,
  148. file1 = mainFile,
  149. file2 = adja2File,
  150. samplingRate = adFile1.Fs,
  151. smpPositions = smps,
  152. snrThreshold = 15,
  153. };
  154. var result2 = await HttpHelper.PostRequestAsync<List<CpuCgResDto>>(baseUrl + "DetectCg/CpuCgMultiCalc", cgDto, token: cts.Token);
  155. sw.Stop();
  156. if (result2.code != 200)
  157. {
  158. await LogHelper.Error($"【任务{dto.ID}】{adTime:yyyyMMddHHmmss}时刻-信号{freq}MHz-主星邻2星CPU参估出错.{result2.msg}");
  159. return;
  160. }
  161. await LogHelper.Info($"【任务{dto.ID}】{adTime:yyyyMMddHHmmss}时刻-信号{freq}MHz-CPU参估完成,耗时{sw.ElapsedMilliseconds}ms");
  162. var data1 = result1.data;
  163. var data2 = result2.data;
  164. if (data1.Count != data2.Count || data1.Count != cgDto.smpPositions.Count)
  165. {
  166. await LogHelper.Error($"【任务{dto.ID}】{adTime:yyyyMMddHHmmss}时刻-信号{freq}MHz-参估结果个数和检测结果个数不匹配");
  167. return;
  168. }
  169. sw.Restart();
  170. for (int i = 0; i < data1.Count; i++)
  171. {
  172. try
  173. {
  174. if (cts.IsCancellationRequested) return;
  175. LeoX1ParPosDto posDto = new LeoX1ParPosDto()
  176. {
  177. TaskID = dto.ID,
  178. SigTime = adTime.AddSeconds(data1[i].Smpstart / (double)adFile1.Fs),
  179. MainCode = MainSatCode,
  180. Adja1Code = MainSatCode,
  181. Adja2Code = MainSatCode,
  182. MainX = Time1XYZ[0],
  183. MainY = Time1XYZ[1],
  184. MainZ = Time1XYZ[2],
  185. MainVX = Time1XYZ[3],
  186. MainVY = Time1XYZ[4],
  187. MainVZ = Time1XYZ[5],
  188. Adja1X = Time2XYZ[0],
  189. Adja1Y = Time2XYZ[1],
  190. Adja1Z = Time2XYZ[2],
  191. Adja1VX = Time2XYZ[3],
  192. Adja1VY = Time2XYZ[4],
  193. Adja1VZ = Time2XYZ[5],
  194. Adja2X = Time3XYZ[0],
  195. Adja2Y = Time3XYZ[1],
  196. Adja2Z = Time3XYZ[2],
  197. Adja2VX = Time3XYZ[3],
  198. Adja2VY = Time3XYZ[4],
  199. Adja2VZ = Time3XYZ[5],
  200. Dto1 = PosDtoFactor * data1[i].Dt,
  201. Dfo1 = data1[i].Df,
  202. Snr1 = data1[i].Snr,
  203. Dto2 = PosDtoFactor * data2[i].Dt,
  204. Dfo2 = data2[i].Df,
  205. Snr2 = data2[i].Snr,
  206. FreqUp = (adFile1.FreqDownMHz + 44) * 1e6,
  207. SatTxLon = dto.CapLon,
  208. SatTxLat = dto.CapLat,
  209. FreqDown = adFile1.FreqDownMHz * 1e6,
  210. CheckRes = new CheckResDto()
  211. {
  212. FileName = Path.GetFileName(adFile1.File),
  213. SmpStart = cgDto.smpPositions[i].smpStart,
  214. SmpCount = cgDto.smpPositions[i].smpCount,
  215. PosCheckType = EnumPosCheckTypeDto.Ky5758,
  216. }
  217. };
  218. var result = await HttpHelper.PostRequestAsync<PosResDto>(baseUrl + "Pos/PosLeX1ParAsync", posDto);
  219. if (result.code != 200)
  220. {
  221. await LogHelper.Error($"【任务{dto.ID}】{adTime:yyyyMMddHHmmss}时刻-信号{freq}MHz 第{i + 1}个突发定位异常.{result.msg}");
  222. }
  223. else
  224. {
  225. var posRes = result.data;
  226. double posLon = posRes.PosLon;
  227. double posLat = posRes.PosLat;
  228. if (posDto.Snr1 == 0 || posDto.Snr2 == 0)
  229. {
  230. posLon = 0;
  231. posLat = 0;
  232. }
  233. ErrorEllipseLeoX1Dto errdto = new ErrorEllipseLeoX1Dto()
  234. {
  235. MsEph = Time1XYZ,
  236. NsEph1 = Time2XYZ,
  237. NsEph2 = Time3XYZ,
  238. SelectPoint = new double[3] { posLon, posLat, 0 },
  239. DfoErr = DfoErrHz,
  240. EphPosErr = EphPosErrM,
  241. EphVelErr = EphVelErr,
  242. fu = posDto.FreqUp,
  243. Pe = 0.5,
  244. OutputErrPoint = false
  245. };
  246. var errRes = await GetErrEllipseResDto(errdto, posLon, posLat);
  247. PosResWriteDto wDto = new PosResWriteDto()
  248. {
  249. PosTypeDto = EnumPosTypeDto.X1Leo,
  250. SigTime = posDto.SigTime,
  251. SigTimeLenMs = posDto.CheckRes.SmpCount * 1000 / adFile1.Fs,
  252. FreqDownMHz = adFile1.FreqDownMHz,
  253. FreqUpMHz = adFile1.FreqDownMHz + 44,
  254. SigModType = deteResp.data[i].ModType,
  255. PosLon = posLon,
  256. PosLat = posLat,
  257. Dto1 = posDto.Dto1,
  258. Dfo1 = posDto.Dfo1,
  259. Snr1 = posDto.Snr1,
  260. Dto2 = posDto.Dto2,
  261. Dfo2 = posDto.Dfo2,
  262. Snr2 = posDto.Snr2,
  263. LongRadius = errRes.LongRadius,
  264. ShortRadius = errRes.ShortRadius,
  265. DipAngle = errRes.DipAngle,
  266. TsCount = data1.Count,
  267. PosType = 4,
  268. ModRate = deteResp.data[i].ModRate.Value,
  269. };
  270. await HttpHelper.PostRequestAsync(baseUrl + "Result/WritePosResToFile", wDto);
  271. }
  272. }
  273. catch (Exception ex)
  274. {
  275. await LogHelper.Error($"【任务{dto.ID}】{adTime:yyyyMMddHHmmss}时刻-信号{freq}MHz-时隙位置{data1[i].Smpstart}定位异常", ex);
  276. }
  277. }
  278. sw.Stop();
  279. await LogHelper.Info($"【任务{dto.ID}】{adTime:yyyyMMddHHmmss}时刻-信号{freq}MHz-定位完成,耗时{sw.ElapsedMilliseconds}ms");
  280. idx++;
  281. }
  282. });
  283. listTask.Add(task);
  284. }
  285. await Task.WhenAll(listTask);
  286. if (!matched)
  287. {
  288. await LogHelper.Info($"【任务{dto.ID}】等待扫描文件...");
  289. await Task.Delay(10000, cts.Token);
  290. }
  291. #endregion
  292. }
  293. catch (TaskCanceledException ex)
  294. {
  295. await LogHelper.Warning($"【任务{dto.ID}】处理结束,用户手动终止", ex.InnerException);
  296. }
  297. catch (Exception ex)
  298. {
  299. if (ex.InnerException != null && ex.InnerException.GetType() == typeof(TaskCanceledException))
  300. await LogHelper.Warning($"【任务{dto.ID}】处理结束,用户手动终止", ex.InnerException);
  301. else
  302. await LogHelper.Error($"【任务{dto.ID}】任务执行出错", ex);
  303. continue;
  304. }
  305. }
  306. }, cts.Token);
  307. }
  308. private double[] GetEph(string[] strs)
  309. {
  310. var TimeXYZ = new double[6] { Convert.ToDouble(strs[1]),
  311. Convert.ToDouble(strs[2]),
  312. Convert.ToDouble(strs[3]),
  313. Convert.ToDouble(strs[4]),
  314. Convert.ToDouble(strs[5]),
  315. Convert.ToDouble(strs[6]),
  316. };
  317. return TimeXYZ;
  318. }
  319. private int GetSignalType(string modTypestr)
  320. {
  321. EnumSignalTypeDto modType = modTypestr.GetEnumByDisplayName<EnumSignalTypeDto>();
  322. //1:CPM,2:BPSK,4:QPSK,9:其他
  323. int signalType = 9;
  324. if (modType == EnumSignalTypeDto.BPSK)
  325. {
  326. signalType = 2;
  327. }
  328. else if (modType == EnumSignalTypeDto.QPSK)
  329. {
  330. signalType = 4;
  331. }
  332. return signalType;
  333. }
  334. private async Task<ErrEllipseResDto> GetErrEllipseResDto(ErrorEllipseLeoX1Dto dto, double posLon, double posLat)
  335. {
  336. ErrEllipseResDto errRes = new ErrEllipseResDto();
  337. if (posLon != 0 && posLat != 0 && posLon != 999 && posLat != 999)
  338. {
  339. var errResRsp = await HttpHelper.PostRequestAsync<ErrEllipseResDto>(baseUrl + "Ellipse/X1Leo", dto);
  340. if (errResRsp.code != 200)
  341. {
  342. await LogHelper.Error(errResRsp.msg);
  343. }
  344. else
  345. {
  346. errRes = errResRsp.data;
  347. }
  348. }
  349. return errRes;
  350. }
  351. public void Stop()
  352. {
  353. cts?.Cancel();
  354. }
  355. private async Task StopTask(int taskID, EnumTaskStopType type, string stopReason)
  356. {
  357. cts?.Cancel();
  358. await Task.Delay(2000);
  359. if (type == EnumTaskStopType.Properly)
  360. {
  361. await LogHelper.Info($"【任务{taskID}】{stopReason}");
  362. }
  363. else
  364. {
  365. await LogHelper.Error($"【任务{taskID}】{stopReason}");
  366. }
  367. TaskStopHandleDto stopDto = new TaskStopHandleDto() { ID = taskID, StopType = type, StopReason = stopReason };
  368. var stopResp = await HttpHelper.PostRequestAsync(baseUrl + "Task/StopTask", stopDto);
  369. if (stopResp.code != 200)
  370. {
  371. await LogHelper.Error($"【任务{taskID}】停止异常.{stopResp.msg}");
  372. }
  373. }
  374. private AdFile StringToAdFile(string file)
  375. {
  376. //20240625184555_D261_FS96000_ch1.dat
  377. var name = Path.GetFileNameWithoutExtension(file).ToUpper();
  378. var arr = name.Split(new string[] { "_", "D", "FS" }, StringSplitOptions.RemoveEmptyEntries);
  379. var time = DateTime.ParseExact(arr[0], "yyyyMMddHHmmss", null);
  380. AdFile adFile = new AdFile()
  381. {
  382. File = file,
  383. AdTime = time,
  384. FreqDownMHz = Convert.ToDouble(arr[1]),
  385. Fs = Convert.ToInt32(arr[2]),
  386. };
  387. return adFile;
  388. }
  389. }
  390. }