zoulei 10 ماه پیش
والد
کامیت
acacdde66b

BIN
Database.db


+ 1 - 1
Service/X2D1TaskServer/App.config

@@ -27,7 +27,7 @@
 		<add key="AdjaSatDelay" value="0"/>
 
 		<!--检测文件类型(上行信号=0,主星下行信号=1)-->
-		<add key="CheckFileType" value="1"/>
+		<add key="CheckFileType" value="0"/>
 
 		<!--并行处理线程个数(支持0到N,0表示不限制,每个频点都在独立的线程中处理)-->
 		<add key="ThreadCount" value="0"/>

+ 11 - 6
Service/X2D1TaskServer/Controllers/X2D1TaskProcessingController.cs

@@ -22,10 +22,12 @@ namespace X2D1TaskServer.Controllers
          * !!!不要在Controller写太复杂的业务逻辑
          * Controller主要就是调用Service层的东西。Service层执行业务逻辑和调用Repository层操作数据库
          * ********************/
-        private readonly TaskService _service;
-        public X2D1TaskProcessingController(TaskService service)
+        private readonly TaskHistoryService _tskHservice;
+        private readonly TaskRealService _tskRservice;
+        public X2D1TaskProcessingController(TaskHistoryService tskHservice, TaskRealService tskRservice)
         {
-            _service = service;
+            _tskHservice = tskHservice;
+            _tskRservice = tskRservice;
         }
 
 
@@ -44,9 +46,9 @@ namespace X2D1TaskServer.Controllers
                     Thread.Sleep(2000);
                 }
                 if (dto.TaskType == EnumTaskTypeDto.History)
-                    _service.StartHistoryAsync(dto);
+                    _tskHservice.StartAsync(dto);
                 else
-                    _service.StarRealAsync(dto);
+                    _tskRservice.StartAsync(dto);
                 return Success();
             }
             catch (Exception ex)
@@ -68,7 +70,10 @@ namespace X2D1TaskServer.Controllers
             try
             {
                 await LogHelper.Warning($"用户停止了任务,ID={dto.ID}");
-                _service.Stop(dto.ID);
+                if (dto.TaskType == EnumTaskTypeDto.History)
+                    _tskHservice.Stop(dto.ID);
+                else
+                    _tskRservice.Stop(dto.ID);
                 return Success();
             }
             catch (Exception ex)

+ 42 - 0
Service/X2D1TaskServer/Service/BaseParamInfo.cs

@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XdCxRhDW.Dto;
+
+namespace X2D1TaskServer
+{
+    public class BaseParamInfo
+    {
+        public BaseParamInfo(TaskSigDto taskSig, HistoryFile dinfo, HistoryFile minfo, HistoryFile ninfo)
+        {
+            this.TaskSig = taskSig;
+            this.Dinfo = dinfo;
+            this.Minfo = minfo;
+            this.Ninfo = ninfo;
+        }
+        public TaskSigDto TaskSig { get; set; }
+        public HistoryFile Dinfo { get; set; }
+        public HistoryFile Minfo { get; set; }
+
+        public HistoryFile Ninfo { get; set; }
+
+        public double? Delay1 { get; set; }
+
+        public double? Delay2 { get; set; }
+
+
+        public void SetDelay(double? mainSatDelay, double? adjaSatDelay)
+        {
+            Delay1 = TaskSig.SigDelay.FirstOrDefault(p => p.SatInfoSatCode == Minfo.SatId)?.Delay;
+            Delay2 = TaskSig.SigDelay.FirstOrDefault(p => p.SatInfoSatCode == Ninfo.SatId)?.Delay;
+            if (Delay1 == null)
+                Delay1 = mainSatDelay;
+            if (Delay2 == null)
+                Delay2 = adjaSatDelay;
+            if (Delay1 == null) Delay1 = 0;
+            if (Delay2 == null) Delay2 = 0;
+        }
+    }
+}

+ 16 - 0
Service/X2D1TaskServer/Service/BaseTaskI.cs

@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XdCxRhDW.Dto;
+
+namespace X2D1TaskServer
+{
+    public interface BaseTaskI
+    {
+        void StartAsync(X2D1TaskHandleDto dto);
+        void Stop(int taskID);
+        Task StopTask(int taskID, EnumTaskStopType type, string stopReason);
+    }
+}

+ 194 - 0
Service/X2D1TaskServer/Service/TaskHistoryService.cs

@@ -0,0 +1,194 @@
+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.Dto;
+
+namespace X2D1TaskServer.Service
+{
+    /// <summary>
+    /// 历史任务服务
+    /// </summary>
+
+    public class TaskHistoryService : TaskService, BaseTaskI
+    {
+        Dictionary<int, CancellationTokenSource> dicCts = new Dictionary<int, CancellationTokenSource>();
+        public TaskHistoryService()
+        {
+        }
+        /// <summary>
+        /// 启动历史任务
+        /// </summary>
+        /// <param name="dto"></param>
+        public void StartAsync(X2D1TaskHandleDto dto)
+        {
+            var cts = new CancellationTokenSource();
+            if (dicCts.ContainsKey(dto.ID))
+                dicCts[dto.ID] = cts;
+            else
+                dicCts.Add(dto.ID, cts);
+
+            Task.Run(async () =>
+            {
+                if (!Directory.Exists(dto.CapDir))
+                {
+                    await StopTask(dto.ID, EnumTaskStopType.Error, $"文件路径[{dto.CapDir}]不存在,任务结束");
+                    return;
+                }
+                if (dto.DateDirFormat.Contains("\\"))
+                {
+                    await StopTask(dto.ID, EnumTaskStopType.Error, $"子目录日期格式不能包含多级目录格式");
+                    return;
+                }
+                await LogHelper.Info($"【任务{dto.ID}】开始执行...");
+
+                await LogHelper.Info($"【任务{dto.ID}】定位时差系数={_config.posDtoFactor}");
+
+                await LogHelper.Info($"【任务{dto.ID}】检测类型={_config.checkFileTypeStr}");
+                string threadStr = _config.threadCount == 0 ? "不限制" : _config.threadCount.ToString();
+                await LogHelper.Info($"【任务{dto.ID}】线程个数={threadStr}");
+                bool canConnected = CanGetSatIdFromMySql(dto.ID);
+                foreach (var taskSig in dto.Sigs)
+                {
+                    double? delay1 = taskSig.SigDelay.FirstOrDefault(p => p.SatInfoSatCode == dto.MainSatCode)?.Delay;
+                    double? delay2 = taskSig.SigDelay.FirstOrDefault(p => p.SatInfoSatCode == dto.AdjaSatCode)?.Delay;
+                    if (delay1 == null)
+                        delay1 = _config.mainSatDelay;
+                    if (delay2 == null)
+                        delay2 = _config.adjaSatDelay;
+                    if (delay1 == null) delay1 = 0;
+                    if (delay2 == null) delay2 = 0;
+
+                    await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],主星{dto.MainSatCode}转发时延{delay1}us");
+                    await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],邻星{dto.AdjaSatCode}转发时延{delay2}us");
+                }
+
+                DateTime preTime = dto.StartTime.AddSeconds(-1);
+                int formatFlag;
+                if (string.IsNullOrWhiteSpace(dto.DateDirFormat))
+                {
+                    //没有日期目录,处理完目录中的数据后停止任务
+                    formatFlag = 0;
+                }
+                else if (dto.DateDirFormat.ToLower().EndsWith("dd"))
+                {
+                    //处理完一个目录后跳转到第二天的目录
+                    formatFlag = 1;
+                }
+                else if (dto.DateDirFormat.ToUpper().EndsWith("HH"))
+                {
+                    //处理完一个目录后跳转到下一个小时的目录
+                    formatFlag = 2;
+                }
+                else
+                {
+                    await StopTask(dto.ID, EnumTaskStopType.Error, $"执行异常,不支持的日期目录格式");
+                    return;
+                }
+
+                while (!cts.IsCancellationRequested && preTime <= dto.EndTime)
+                {
+                    if (!dicCts.Values.Contains(cts)) return;
+                    string filesDir = dto.CapDir;
+                    try
+                    {
+                        if (formatFlag != 0)
+                        {
+                            filesDir = Path.Combine(dto.CapDir, $"{preTime.ToString(dto.DateDirFormat)}");//yyyyMMdd
+                        }
+
+                        if (!Directory.Exists(filesDir))
+                        {
+                            await LogHelper.Info($"【任务{dto.ID}】目录[{filesDir}]不存在,跳过此目录");
+                            ResetTime(formatFlag, ref preTime);
+                            continue;
+                        }
+
+
+                        await LogHelper.Info($"【任务{dto.ID}】正在扫描[{filesDir}]目录...");
+                        Stopwatch sw = new Stopwatch();
+                        sw.Start();
+                        List<string> files = Directory.GetFiles(filesDir, "*.dat").ToList();
+                        sw.Stop();
+                        await LogHelper.Info($"【任务{dto.ID}】扫描[{filesDir}]目录完成,耗时{sw.ElapsedMilliseconds}ms");
+                        if (!files.Any())
+                        {
+                            await LogHelper.Info($"【任务{dto.ID}】目录[{filesDir}]中没有文件,跳过此目录");
+                            ResetTime(formatFlag, ref preTime);
+                            continue;
+                        }
+                        bool isLocal = IsLocal(filesDir);
+                        List<IGrouping<DateTime, HistoryFile>> groups = null;
+                        groups = files.Select(f => FileToHistoryFile(dto, f, preTime, canConnected, cts.Token))
+                            .Where(p => p != null)
+                            .GroupBy(m => m.CapTime)
+                            .OrderBy(m => m.Key).ToList();
+                        if (cts.IsCancellationRequested) break;
+                        foreach (var sameTimeFiles in groups)
+                        {
+                            if (cts.IsCancellationRequested) break;
+                            var xdgbInfos = sameTimeFiles.GroupBy(m => m.XdIndex);
+
+                            var splitXdgbInfos = SplitFreqFiles( xdgbInfos);
+                            List<Task> listTask = new List<Task>();
+                            foreach (var item in splitXdgbInfos)//splitXdgbInfos中的数据并行处理
+                            {
+                                if (cts.IsCancellationRequested) return;
+                                var task = GetPosTask(dto, item, isLocal, cts);
+                                listTask.Add(task);
+                            }
+                            await Task.WhenAll(listTask);
+                            preTime = sameTimeFiles.First().CapTime;
+                        }
+                        ResetTime(formatFlag, ref preTime);
+                        await LogHelper.Info($"【任务{dto.ID}】目录[{filesDir}]本次扫描的数据处理完成");
+                    }
+                    catch (TaskCanceledException ex)
+                    {
+                        await LogHelper.Warning($"【任务{dto.ID}】目录[{filesDir}]中的数据处理结束,用户手动终止", ex);
+                        ResetTime(formatFlag, ref preTime);
+                    }
+                    catch (Exception ex)
+                    {
+                        await LogHelper.Error($"【任务{dto.ID}】目录[{filesDir}]中的数据处理出错,跳过此目录", ex);
+                        ResetTime(formatFlag, ref preTime);
+                    }
+                }
+                await StopTask(dto.ID, EnumTaskStopType.Properly, "数据处理完成,任务结束");
+            }, cts.Token);
+        }
+
+
+        public void Stop(int taskID)
+        {
+            if (!dicCts.ContainsKey(taskID)) return;
+            dicCts[taskID]?.Cancel();
+            dicCts.Remove(taskID);
+        }
+        public async Task StopTask(int taskID, EnumTaskStopType type, string stopReason)
+        {
+            await Task.Delay(2000);
+            if (type == EnumTaskStopType.Properly)
+            {
+                await LogHelper.Info($"【任务{taskID}】{stopReason}");
+            }
+            else
+            {
+                await LogHelper.Error($"【任务{taskID}】{stopReason}");
+            }
+            TaskStopHandleDto stopDto = new TaskStopHandleDto() { ID = taskID, StopType = type, TaskType = EnumTaskTypeDto.History, StopReason = stopReason };
+            var stopResp = await HttpHelper.PostRequestAsync(_config.baseUrl + "Task/StopTask", stopDto);
+            if (stopResp.code != 200)
+            {
+                await LogHelper.Error($"【任务{taskID}】停止异常.{stopResp.msg}");
+            }
+            if (dicCts.ContainsKey(taskID))
+                dicCts.Remove(taskID);
+        }
+    }
+}

+ 253 - 0
Service/X2D1TaskServer/Service/TaskRealService.cs

@@ -0,0 +1,253 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using static Org.BouncyCastle.Math.EC.ECCurve;
+using XdCxRhDW.Dto;
+using System.Configuration;
+using System.Diagnostics;
+using System.IO;
+
+namespace X2D1TaskServer.Service
+{
+    /// <summary>
+    /// 实时任务服务
+    /// </summary>
+
+    public class TaskRealService : TaskService, BaseTaskI
+    {
+        Dictionary<int, CancellationTokenSource> dicCts = new Dictionary<int, CancellationTokenSource>();
+
+        public TaskRealService()
+        {
+        }
+        /// <summary>
+        /// 启动实时任务
+        /// </summary>
+        /// <param name="dto"></param>
+        public void StartAsync(X2D1TaskHandleDto dto)
+        {
+            var cts = new CancellationTokenSource();
+            if (dicCts.ContainsKey(dto.ID))
+                dicCts[dto.ID] = cts;
+            else
+                dicCts.Add(dto.ID, cts);
+
+            Task.Run(async () =>
+            {
+                if (!Directory.Exists(dto.CapDir))
+                {
+                    await StopTask(dto.ID, EnumTaskStopType.Error, $"文件路径[{dto.CapDir}]不存在,任务结束");
+                    return;
+                }
+                if (dto.DateDirFormat.Contains("\\"))
+                {
+                    await StopTask(dto.ID, EnumTaskStopType.Error, $"子目录日期格式不能包含多级目录格式");
+                    return;
+                }
+
+                await LogHelper.Info($"【任务{dto.ID}】开始执行...");
+
+                await LogHelper.Info($"【任务{dto.ID}】定位时差系数={_config.posDtoFactor}");
+                string checkFileTypeStr = "上行信号";
+                if (_config.checkFileType != 0)
+                    checkFileTypeStr = "主星下行信号";
+                await LogHelper.Info($"【任务{dto.ID}】检测类型={checkFileTypeStr}");
+                string threadStr = _config.threadCount == 0 ? "不限制" : _config.threadCount.ToString();
+                await LogHelper.Info($"【任务{dto.ID}】线程个数={threadStr}");
+                bool canConnected = CanGetSatIdFromMySql(dto.ID);
+                foreach (var taskSig in dto.Sigs)
+                {
+                    double? delay1 = taskSig.SigDelay.FirstOrDefault(p => p.SatInfoSatCode == dto.MainSatCode)?.Delay;
+                    double? delay2 = taskSig.SigDelay.FirstOrDefault(p => p.SatInfoSatCode == dto.AdjaSatCode)?.Delay;
+                    if (delay1 == null)
+                        delay1 = _config.mainSatDelay;
+                    if (delay2 == null)
+                        delay2 = _config.adjaSatDelay;
+                    if (delay1 == null) delay1 = 0;
+                    if (delay2 == null) delay2 = 0;
+
+                    await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],主星{dto.MainSatCode}转发时延{delay1}us");
+                    await LogHelper.Info($"【任务{dto.ID}】信号[{taskSig.FreqUp / 1e6:f3}MHz],邻星{dto.AdjaSatCode}转发时延{delay2}us");
+                }
+
+                DateTime preTime = DateTime.Now.AddSeconds(-_config.capSeconds * 2);
+                int formatFlag;
+                if (string.IsNullOrWhiteSpace(dto.DateDirFormat))
+                {
+                    //没有日期目录,处理完目录中的数据后停止任务
+                    formatFlag = 0;
+                }
+                else if (dto.DateDirFormat.ToLower().EndsWith("dd"))
+                {
+                    //处理完一个目录后跳转到第二天的目录
+                    formatFlag = 1;
+                }
+                else if (dto.DateDirFormat.ToUpper().EndsWith("HH"))
+                {
+                    //处理完一个目录后跳转到下一个小时的目录
+                    formatFlag = 2;
+                }
+                else
+                {
+                    await StopTask(dto.ID, EnumTaskStopType.Error, $"执行异常,不支持的日期目录格式");
+                    return;
+                }
+
+                while (!cts.IsCancellationRequested)
+                {
+                    string filesDir = dto.CapDir;
+                    try
+                    {
+                        if (formatFlag != 0)
+                        {
+                            filesDir = Path.Combine(dto.CapDir, $"{preTime.ToString(dto.DateDirFormat)}");//yyyy_MM_dd_HH
+                        }
+                        bool doNextHour = false;
+                        while (!Directory.Exists(filesDir))
+                        {
+                            if (cts.IsCancellationRequested) return;
+                            if (!dicCts.Values.Contains(cts)) return;
+                            await LogHelper.Info($"【任务{dto.ID}】目录[{filesDir}]不存在,等待5秒...");
+                            await Task.Delay(5000, cts.Token);
+                            if (DateTime.Now.Hour != preTime.Hour)
+                            {
+                                ResetTime(formatFlag, ref preTime);
+                                doNextHour = true;
+                                break;
+                            }
+                        }
+                        if (cts.IsCancellationRequested) return;
+                        if (doNextHour)
+                        {
+                            continue;
+                        }
+                        await LogHelper.Info($"【任务{dto.ID}】正在扫描[{filesDir}]目录...");
+                        Stopwatch sw = new Stopwatch();
+                        sw.Start();
+                        List<string> files = Directory.GetFiles(filesDir, "*.dat").ToList();
+                        sw.Stop();
+                        await LogHelper.Info($"【任务{dto.ID}】扫描[{filesDir}]目录完成,耗时{sw.ElapsedMilliseconds}ms");
+                        while (true)
+                        {
+                            if (cts.IsCancellationRequested) return;
+                            if (!files.Any())
+                            {
+                                await LogHelper.Info($"【任务{dto.ID}】目录[{filesDir}]中没有文件,等待10秒...");
+                                if (DateTime.Now.Hour != preTime.Hour)
+                                {
+                                    ResetTime(formatFlag, ref preTime);
+                                    doNextHour = true;
+                                    break;
+                                }
+                                await Task.Delay(10000, cts.Token);
+                                files = Directory.GetFiles(filesDir, "*.dat").ToList();
+                                continue;
+                            }
+                            break;
+                        }
+                        if (cts.IsCancellationRequested) return;
+                        List<IGrouping<DateTime, HistoryFile>> groups = null;
+                        bool isLocal = IsLocal(filesDir);
+                        groups = files.Select(f => FileToHistoryFile(dto, f, preTime, canConnected, cts.Token))
+                            .Where(p => p != null)
+                            .GroupBy(m => m.CapTime)
+                            .OrderBy(m => m.Key).ToList();
+                        if (cts.IsCancellationRequested) break;
+                        bool hasFile = false;
+                        if (groups.Any())
+                        {
+                            var lastTime = groups.Last().Key;
+                            foreach (var sameTimeFiles in groups)
+                            {
+                                if (cts.IsCancellationRequested) return;
+                                var capTime = sameTimeFiles.First().CapTime;
+                                if ((DateTime.Now - capTime).TotalMinutes > 10)
+                                {
+                                    preTime = capTime;
+                                    await LogHelper.Warning($"【任务{dto.ID}】处理速度过慢,丢弃数据");
+                                    continue;
+                                }
+                                if (capTime == lastTime)
+                                {
+                                    await WaitFileEnd(dto.ID, sameTimeFiles.First(), _config.capSeconds, cts);
+                                }
+                                await LogHelper.Info($"【任务{dto.ID}】[{capTime:yyyyMMddHHmmss}]时刻文件采集完成");
+                                if (!CanOpenFile(dto.ID, sameTimeFiles.First()))
+                                    continue;//文件无法打开
+                                hasFile = true;
+                                var xdgbInfos = sameTimeFiles.GroupBy(m => m.XdIndex);
+                                var splitXdgbInfos = SplitFreqFiles(xdgbInfos);
+                                List<Task> listTask = new List<Task>();
+                                foreach (var item in splitXdgbInfos)//splitXdgbInfos中的数据并行处理
+                                {
+                                    if (cts.IsCancellationRequested) return;
+                                    var task = GetPosTask(dto, item, isLocal, cts);
+                                    listTask.Add(task);
+                                }
+                                await Task.WhenAll(listTask);
+                                preTime = capTime;
+                            }
+                        }
+                        if (!hasFile || preTime.Minute == 59)
+                        {
+                            await LogHelper.Info($"【任务{dto.ID}】缺少{preTime:yyyyMMddHHmmss}时刻之后的采集文件,等待5秒...");
+                            //实时任务没有文件需要考虑跳转到下一个小时的目录
+                            var time = new DateTime(preTime.Year, preTime.Month, preTime.Day, preTime.Hour, 0, 0);
+                            var now = DateTime.Now;
+                            if ((int)(now - time).TotalHours != 0)
+                            {
+                                preTime = new DateTime(now.Year, now.Month, now.Day, now.Hour, 0, 0);
+                            }
+                            await Task.Delay(5000, cts.Token);
+                        }
+                        else
+                        {
+                            await LogHelper.Info($"【任务{dto.ID}】目录[{filesDir}]本次扫描的数据处理完成");
+                        }
+                    }
+                    catch (TaskCanceledException ex)
+                    {
+                        await LogHelper.Warning($"【任务{dto.ID}】目录[{filesDir}]中的数据处理结束,用户手动终止", ex);
+                        ResetTime(formatFlag, ref preTime);
+                    }
+                    catch (Exception ex)
+                    {
+                        await LogHelper.Error($"【任务{dto.ID}】目录[{filesDir}]中的数据处理出错,跳过此目录", ex);
+                        ResetTime(formatFlag, ref preTime);
+                    }
+                }
+                await StopTask(dto.ID, EnumTaskStopType.Properly, "数据处理完成,任务结束");
+            }, cts.Token);
+        }
+
+        public void Stop(int taskID)
+        {
+            if (!dicCts.ContainsKey(taskID)) return;
+            dicCts[taskID]?.Cancel();
+            dicCts.Remove(taskID);
+        }
+        public async Task StopTask(int taskID, EnumTaskStopType type, string stopReason)
+        {
+            await Task.Delay(2000);
+            if (type == EnumTaskStopType.Properly)
+            {
+                await LogHelper.Info($"【任务{taskID}】{stopReason}");
+            }
+            else
+            {
+                await LogHelper.Error($"【任务{taskID}】{stopReason}");
+            }
+            TaskStopHandleDto stopDto = new TaskStopHandleDto() { ID = taskID, StopType = type, TaskType = EnumTaskTypeDto.Real, StopReason = stopReason };
+            var stopResp = await HttpHelper.PostRequestAsync(_config.baseUrl + "Task/StopTask", stopDto);
+            if (stopResp.code != 200)
+            {
+                await LogHelper.Error($"【任务{taskID}】停止异常.{stopResp.msg}");
+            }
+            if (dicCts.ContainsKey(taskID))
+                dicCts.Remove(taskID);
+        }
+    }
+}

+ 50 - 0
Service/X2D1TaskServer/Service/TaskSvrConfig.cs

@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace X2D1TaskServer.Service
+{
+    public class TaskSvrConfig
+    {
+        /// <summary>
+        /// Http地址
+        /// </summary>
+        public string baseUrl { get; set; }
+        /// <summary>
+        /// 实时任务采集时长(秒)
+        /// </summary>
+
+        public int capSeconds { get; set; }
+        /// <summary>
+        /// //配置文件中配置的主星转发延迟
+        /// </summary>
+        public double? mainSatDelay { get; set; }
+        /// <summary>
+        /// 配置文件中配置的邻星转发延迟
+        /// </summary>
+        public double? adjaSatDelay { get; set; }
+        /// <summary>
+        /// 检测文件类型(上行信号= 0, 主星下行信号= 1
+        /// </summary>
+        public int checkFileType { get; set; }
+        /// <summary>
+        /// 线程个数
+        /// </summary>
+        public int threadCount { get; set; } = 0;
+
+        /// <summary>
+        /// //定位时时差系数
+        /// </summary>
+        public int posDtoFactor { get; set; }
+
+        public string checkFileTypeStr
+        {
+            get
+            {
+                return checkFileType == 0 ? "上行信号" : "主星下行信号";
+            }
+        }
+    }
+}

+ 5 - 0
Service/X2D1TaskServer/X2D1TaskServer.csproj

@@ -131,8 +131,13 @@
     <Compile Include="MainForm.Designer.cs">
       <DependentUpon>MainForm.cs</DependentUpon>
     </Compile>
+    <Compile Include="Service\BaseParamInfo.cs" />
+    <Compile Include="Service\BaseTaskI.cs" />
+    <Compile Include="Service\TaskHistoryService.cs" />
+    <Compile Include="Service\TaskRealService.cs" />
     <Compile Include="Service\TaskService.cs" />
     <Compile Include="HistoryFile.cs" />
+    <Compile Include="Service\TaskSvrConfig.cs" />
     <None Include="packages.config" />
     <EmbeddedResource Include="Properties\Resources.resx">
       <Generator>ResXFileCodeGenerator</Generator>

+ 23 - 0
XdCxRhDW.App/X2D1PosRef/LinearInterpolation.cs

@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace XdCxRhDW.App
+{
+    public class LinearInterpolation
+    {
+        public static double CalSigTimeDto(DateTime x, DateTime x0, DateTime x1, double y0, double y1)
+        {
+            // 线性插值公式: y = y0 + (x - x0) * ((y1 - y0) / (x1 - x0))
+            double y= y0 + (x - x0).TotalSeconds * ((y1 - y0) / (x1 - x0).TotalSeconds);
+            if (y == double.NaN)
+            {
+                y = 0;
+            }
+            return y;
+        }
+
+    }
+}

+ 161 - 0
XdCxRhDW.App/X2D1PosRef/X2D1PosHandle.cs

@@ -0,0 +1,161 @@
+using DevExpress.Utils.About;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Data.Entity;
+using System.Linq;
+using System.Security.Policy;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Documents;
+using XdCxRhDW.Dto;
+using XdCxRhDW.Entity;
+using XdCxRhDW.Repostory;
+
+namespace XdCxRhDW.App
+{
+    /// <summary>
+    /// 两星一地定位取参考
+    /// </summary>
+    public class X2D1PosHandle
+    {
+        
+        public int TaskId;
+        //十分钟时间内的数据
+        private int TimeSeconds = 10 * 60;//十分钟
+        private bool isRuning = true;
+
+        BlockingCollection<X2D1NoXlNoParlPosDto> posDtos = new BlockingCollection<X2D1NoXlNoParlPosDto>();
+        public X2D1PosHandle(int taskId)
+        {
+            TaskId = taskId;
+            StartMonitor();
+        }
+
+        public void StartMonitor()
+        {
+            Task.Run(async () =>
+            {
+
+                while (isRuning)
+                {
+                    try
+                    {
+                        var dto = posDtos.Take();
+
+                        FixedStation fixedStation;
+                        using (RHDWContext db = new RHDWContext())
+                        {
+                            fixedStation = await db.FixedStation.FirstAsync(f => f.ID == dto.FixedStationId.Value);
+                        }
+                        
+                        DateTime min = dto.SigTime.AddSeconds(-TimeSeconds);
+                        DateTime max = dto.SigTime.AddSeconds(TimeSeconds);
+                        using (RHDWPartContext db = RHDWPartContext.GetContext(dto.SigTime, true))
+                        {
+                            //获取十分钟之内的固定站数据
+                            var cgRess = await db.CgRes.Where(m => m.FixedStationResID == dto.FixedStationId && dto.SigTime >= min && dto.SigTime <= max).OrderBy(d => d.SigTime).ToListAsync();
+
+                            List<CgRes> matchCgList = new List<CgRes>();
+                            cgRess.ForEach(c =>
+                            {
+                                if ((dto.SigTime - c.SigTime).TotalSeconds <= TimeSeconds)
+                                {
+                                    matchCgList.Add(c);
+                                }
+                            });
+#warning 获取最近时间的时差值,若没找到参考信号就做无参 是否要等待?
+                            var point1 = matchCgList.Where(c => c.SigTime <= dto.SigTime).FirstOrDefault();
+                            var point2 = matchCgList.Where(c => c.SigTime >= dto.SigTime).FirstOrDefault();
+                            bool isSucces = false;
+                            if (point1 != null && point2 != null)
+                            {
+                                //通过双星时差及超短波时差怎么计算参考信息的时差
+                                double refDto = LinearInterpolation.CalSigTimeDto(dto.SigTime, point1.SigTime, point2.SigTime, point1.Dto1.Value, point2.Dto1.Value);
+                                double refDtoCdb = LinearInterpolation.CalSigTimeDto(dto.SigTime, point1.SigTime, point2.SigTime, point1.DtoCdb.Value, point2.DtoCdb.Value);
+
+                                //执行两星一地有参定位
+                                X2D1NoXlPosDto X2D1NoXlPosDto = new X2D1NoXlPosDto()
+                                {
+                                    SigTime = dto.SigTime,
+                                    MainCode = dto.MainCode,
+                                    AdjaCode = dto.AdjaCode,
+                                    SxDto = dto.SxDto,
+                                    XdDto = dto.XdDto,
+                                    MainYbDto = refDto,
+                                    AdjaYbDto = refDtoCdb,
+                                    SatTxLon = dto.SatTxLon,
+                                    SatTxLat = dto.SatTxLat,
+                                    CdbTxLon = dto.CdbTxLon,
+                                    CdbTxLat = dto.CdbTxLat,
+                                    RefLon = fixedStation.Lon,
+                                    RefLat = fixedStation.Lat,
+                                    FreqDown = dto.FreqDown,
+                                    FreqUp = dto.FreqUp,
+                                    XdDfo = dto.XdDfo,
+                                    XdSnr = dto.XdSnr,
+                                    SxDfo = dto.SxDfo,
+                                    SxSnr = dto.SxSnr,
+                                    CalcConfidence = true,
+                                    TheoryDfoCalc = true,
+                                };
+                                var result = await HttpHelper.PostRequestAsync<PosResDto>(SysConfig.GetUrl("Pos/PosX2D1NoXlAsync"), X2D1NoXlPosDto);
+                                if (result.code != 200)
+                                {
+                                    isSucces = false;
+                                    Serilog.Log.Error($"{dto.SigTime:yyyy-MM-dd HH:mm:ss}两星一地有参定位失败{result.msg}");
+                                }
+                                else
+                                {
+                                    isSucces = true;
+                                    Serilog.Log.Error($"{dto.SigTime:yyyy-MM-dd HH:mm:ss}两星一地有参定位完成{result.msg}");
+                                }
+                                if (isSucces && result.data.PosLon == 999)
+                                {
+                                    isSucces = false;
+                                }
+
+                            }
+                            if (!isSucces)
+                            {
+                                dto.BeFindRef = false;
+                                dto.FixedStationId = null;
+                                var result = await HttpHelper.PostRequestAsync<PosResDto>(SysConfig.GetUrl("Pos/PosX2D1NoXlNoParAsync"), dto);
+                                if (result.code != 200)
+                                {
+                                    Serilog.Log.Error($"{dto.SigTime:yyyy-MM-dd HH:mm:ss}两星一地无参定位失败{result.msg}");
+
+                                }
+                                else
+                                {
+                                    Serilog.Log.Error($"{dto.SigTime:yyyy-MM-dd HH:mm:ss}两星一地无参定位完成{result.msg}");
+                                }
+
+                            }
+
+                        }
+                    }
+                    catch (Exception ex)
+                    {
+                        Serilog.Log.Error(ex, $"【取参考信号流程异常{ex.Message}");
+                    }
+
+                }
+            });
+        }
+        public void Append(X2D1NoXlNoParlPosDto dto)
+        {
+            bool ret = posDtos.TryAdd(dto);
+            if (!ret)
+            {
+                Serilog.Log.Error($"【任务{dto.TaskID}】添加取参考Dto");
+            }
+        }
+
+        public void Stop()
+        {
+            //当前任务停止处理
+            isRuning = false;
+        }
+    }
+}

+ 112 - 0
XdCxRhDW.App/X2D1PosRef/X2D1PosRefService.cs

@@ -0,0 +1,112 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Data.Entity;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using XdCxRhDW.Dto;
+using XdCxRhDW.Entity;
+using XdCxRhDW.Repostory;
+namespace XdCxRhDW.App
+{
+    /// <summary>
+    /// 两星一地定位取参考服务 
+    /// </summary>
+    public class X2D1PosRefService
+    {
+        public static X2D1PosRefService Instance { get; private set; } = new X2D1PosRefService();
+
+        readonly List<X2D1PosHandle> handles = new List<X2D1PosHandle>();
+
+        public X2D1PosRefService()
+        {
+            StartMonitor();
+        }
+        public void StartMonitor()
+        {
+            Task.Run(() =>
+            {
+                while (true)
+                {
+                    if (handles.Count == 0)
+                    {
+                        Thread.Sleep(5000);
+                    }
+                    try
+                    {
+                        lock (this)
+                        {
+                            List<X2D1PosHandle> deletes = new List<X2D1PosHandle>();
+                            using (RHDWContext db = new RHDWContext())
+                            {
+                                for (int i = 0; i < handles.Count; i++)
+                                {
+                                    var handle = handles[i];
+                                    var runTask = db.TaskInfos.FirstOrDefault(p => p.ID == handle.TaskId && p.TaskState == EnumTaskState.Running);
+                                    if (runTask == null)
+                                    {
+                                        handle.Stop();
+                                        deletes.Add(handle);
+                                    }
+                                }
+
+                            }
+                            //删除未运行的任务
+                            handles.RemoveAll(r => deletes.Any(d => d.TaskId == r.TaskId));
+                        }
+                        Thread.Sleep(5000);
+                    }
+                    catch (Exception ex)
+                    {
+                        Serilog.Log.Error(ex, $"【监视取参考任务运行状态异常,{ex.Message}");
+
+                    }
+
+                }
+            });
+        }
+        public void AddPosDto(X2D1NoXlNoParlPosDto dto)
+        {
+            try
+            {
+                lock (this)
+                {
+                    var firstDto = handles.FirstOrDefault(m => m.TaskId == dto.TaskID);
+                    if (firstDto == null)
+                    {
+                        firstDto = new X2D1PosHandle(dto.TaskID.Value);
+                        handles.Add(firstDto);
+                    }
+                    firstDto.Append(dto);
+                }
+            }
+            catch (Exception ex)
+            {
+                Serilog.Log.Error(ex, $"【任务{dto.TaskID}】添加取参考信号流程异常,{ex.Message}");
+
+            }
+        }
+        public void Stop(int taskID)
+        {
+            try
+            {
+                lock (this)
+                {
+                    var firstDto = handles.FirstOrDefault(m => m.TaskId == taskID);
+                    if (firstDto != null)
+                    {
+                        firstDto.Stop();
+                        handles.Remove(firstDto);
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                Serilog.Log.Error(ex, $"停止【任务{taskID}】取参考信号流程异常,{ex.Message}");
+
+            }
+        }
+
+    }
+}

+ 3 - 1
XdCxRhDW.App/XdCxRhDW.App.csproj

@@ -334,6 +334,8 @@
     <Compile Include="Model\ModelCgXgf.cs" />
     <Compile Include="Model\RePosRes.cs" />
     <Compile Include="CpuMonitor.cs" />
+    <Compile Include="X2D1PosRef\LinearInterpolation.cs" />
+    <Compile Include="X2D1PosRef\X2D1PosRefService.cs" />
     <Compile Include="PopupControl\ShowCgCtrl.cs">
       <SubType>UserControl</SubType>
     </Compile>
@@ -469,6 +471,7 @@
     <Compile Include="UserControl\X2D1GDOPParam.Designer.cs">
       <DependentUpon>X2D1GDOPParam.cs</DependentUpon>
     </Compile>
+    <Compile Include="X2D1PosRef\X2D1PosHandle.cs" />
     <EmbeddedResource Include="CorTools\GpuCalcForm.resx">
       <DependentUpon>GpuCalcForm.cs</DependentUpon>
     </EmbeddedResource>
@@ -555,7 +558,6 @@
     <EmbeddedResource Include="PopupControl\ShowCxCtrl.resx">
       <DependentUpon>ShowCxCtrl.cs</DependentUpon>
     </EmbeddedResource>
-    <None Include="Properties\licenses.licx" />
     <EmbeddedResource Include="Properties\Resources.resx">
       <Generator>ResXFileCodeGenerator</Generator>
       <LastGenOutput>Resources.Designer.cs</LastGenOutput>

+ 10 - 0
XdCxRhDw.Dto/PosDto/X2D1NoXlNoParlPosDto.cs

@@ -118,6 +118,16 @@ namespace XdCxRhDW.Dto
         [Obsolete]
         public bool CalcConfidence { get; set; } = false;
 
+        /// <summary>
+        /// 固定站ID
+        /// </summary>
+        public int? FixedStationId { get; set; }
+
+        /// <summary>
+        /// 获取参考信号
+        /// </summary>
+        public bool BeFindRef { get; set; }
+
     }
 
 }

+ 4 - 0
XdCxRhDw.Dto/TaskHandleDto/TaskStopHandleDto.cs

@@ -16,6 +16,10 @@ namespace XdCxRhDW.Dto
         /// </summary>
         public int ID { get; set; }
 
+        /// <summary>
+        /// 任务类型
+        /// </summary>
+        public EnumTaskTypeDto TaskType { get; set; }
 
         /// <summary>
         /// 任务停止类型

+ 4 - 0
XdCxRhDw.Dto/TaskHandleDto/X2D1TaskHandleDto.cs

@@ -93,6 +93,10 @@ namespace XdCxRhDW.Dto
     /// </summary>
     public class X2D1FixedStationDto
     {
+        /// <summary>
+        /// 固定站ID
+        /// </summary>
+        public int FixedStationId { get; set; }
         /// <summary>
         /// 名称
         /// </summary>