From 63b59cca10c503ef3803cff078ec4c66adaf114b Mon Sep 17 00:00:00 2001 From: CaesarBao <445720029@qq.com> Date: Sat, 7 Sep 2024 00:58:36 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=8E=B7=E5=8F=96=E7=AD=89?= =?UTF-8?q?=E5=BE=85=E4=BB=BB=E5=8A=A1=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../base/BaseTaskInfoBusiness.cs | 98 +++++++++++++++++-- .../Templates/Service/IServices.vm | 2 +- .../Templates/Service/Impl/ServiceCreate.cs | 2 +- SlnMesnac.Model/domain/AGVState.cs | 75 ++++++++++++++ SlnMesnac.Quartz/Job/GetAgvState_Job.cs | 27 +++++ SlnMesnac.Quartz/Job/GetTaskInfo_Job.cs | 43 ++++++++ SlnMesnac.Quartz/Job/MyJob.cs | 2 +- SlnMesnac.Quartz/QuartzSetUp.cs | 13 ++- SlnMesnac.Quartz/SlnMesnac.Quartz.csproj | 5 + .../service/IAGVStateService.cs | 26 +++++ .../service/IAirportTaskService.cs | 15 ++- .../service/Impl/AGVStateServiceImpl.cs | 42 ++++++++ .../service/Impl/AirportTaskServiceImpl.cs | 29 +++++- SlnMesnac.WPF/Startup.cs | 4 + .../IndexPage/IndexContentViewModel.cs | 21 +++- .../ViewModel/MainWindowViewModel.cs | 10 ++ SlnMesnac.WPF/appsettings.json | 20 ++-- 17 files changed, 400 insertions(+), 34 deletions(-) create mode 100644 SlnMesnac.Model/domain/AGVState.cs create mode 100644 SlnMesnac.Quartz/Job/GetAgvState_Job.cs create mode 100644 SlnMesnac.Quartz/Job/GetTaskInfo_Job.cs create mode 100644 SlnMesnac.Repository/service/IAGVStateService.cs create mode 100644 SlnMesnac.Repository/service/Impl/AGVStateServiceImpl.cs diff --git a/SlnMesnac.Business/base/BaseTaskInfoBusiness.cs b/SlnMesnac.Business/base/BaseTaskInfoBusiness.cs index 605f4cb..28d822c 100644 --- a/SlnMesnac.Business/base/BaseTaskInfoBusiness.cs +++ b/SlnMesnac.Business/base/BaseTaskInfoBusiness.cs @@ -3,27 +3,95 @@ using SlnMesnac.Repository.service; using System; using System.Collections.Generic; using SlnMesnac.Repository; +using SlnMesnac.Repository.service.Impl; using TouchSocket.Sockets; +using SlnMesnac.Model.domain; +using SlnMesnac.TouchSocket; +using System.Timers; namespace SlnMesnac.Business.@base { public class BaseTaskInfoBusiness { - public Action> AirportTaskEvent; + public Action _Taskaction; + private static BaseTaskInfoBusiness instance; private ILogger _logger; - - private IAirportTaskService _service; - public BaseTaskInfoBusiness(ILogger logger, IAirportTaskService service) + private IAirportTaskService _Taskservice; + private IAGVStateService _AGVStateService; + public BaseTaskInfoBusiness(ILogger logger, IAirportTaskService Taskservice, IAGVStateService agvService) { _logger = logger; - _service = service; + _Taskservice = Taskservice; + _AGVStateService = agvService; + InitClearTimer(); + } + public static BaseTaskInfoBusiness GetInstance(ILogger logger, IAirportTaskService Taskservice, IAGVStateService agvService) + { + if (instance == null) + { + instance = new BaseTaskInfoBusiness(logger, Taskservice,agvService); + } + return instance; } + private void InitClearTimer() + { + System.Timers.Timer timer = new System.Timers.Timer + { + Interval = 1000, // 每天执行一次 + AutoReset = false, + + }; + timer.Elapsed += GetAGVTaskInfo; + timer.Start(); - public void GetTaskInfos() + } + /// + /// 获取任务列表 + /// + private void GetAGVTaskInfo(object source, ElapsedEventArgs e) { try { - List TaskInfos = _service.GetTaskInfos(); + List Task = _Taskservice.GetAGVTaskInfos(); + if (Task.Count > 0 && Task != null) + { + foreach (var TaskItem in Task) + { + _logger.LogInformation($"获取任务信息列表"); + //查询AGV设备状态及AMR设备状态 + //这里要看AGV是否会立刻更新状态 + List State = GetAgvState(); + if (State != null && State.Count > 0) + { + foreach (var AgvItem in State) + { + //根据规则筛选最优AGV + if (AgvItem.agvworkstate == "任务空闲") + { + _logger.LogInformation($"获取空闲AGV列表"); + //调用派发任务接口,向任务状态为任务空闲的AGV派发任务 + AgvItem.taskno = TaskItem.taskno; + AgvItem.agvworkstate = "任务执行中"; + AgvItem.refreshtime = DateTime.Now; + _AGVStateService.UpdateAsync(AgvItem); + + //更新任务信息表状态为执行中 + TaskItem.agvno = AgvItem.agvno; + TaskItem.taskstate = "执行中"; + _Taskservice.UpdateAsync(TaskItem); + _Taskaction?.Invoke(TaskItem); + + } + } + + + } + } + + } + + + } catch (Exception ex) { @@ -31,5 +99,21 @@ namespace SlnMesnac.Business.@base } } + private List GetAgvState() + { + List State = null; + try + { + State = _AGVStateService.GetAgvState(); + return State; + } + catch (Exception ex) + { + return State; + } + + } + + } } \ No newline at end of file diff --git a/SlnMesnac.Generate/Templates/Service/IServices.vm b/SlnMesnac.Generate/Templates/Service/IServices.vm index a5b8992..c868c30 100644 --- a/SlnMesnac.Generate/Templates/Service/IServices.vm +++ b/SlnMesnac.Generate/Templates/Service/IServices.vm @@ -6,7 +6,7 @@ using System.Text; namespace ${NameSpace}.service { - public interface I${tableName}Services: IBaseService<${tableName}> + public interface I${tableName}Service: IBaseService<${tableName}> { } diff --git a/SlnMesnac.Generate/Templates/Service/Impl/ServiceCreate.cs b/SlnMesnac.Generate/Templates/Service/Impl/ServiceCreate.cs index 14830ea..1514359 100644 --- a/SlnMesnac.Generate/Templates/Service/Impl/ServiceCreate.cs +++ b/SlnMesnac.Generate/Templates/Service/Impl/ServiceCreate.cs @@ -33,7 +33,7 @@ namespace SlnMesnac.Generate.Templates.Service.Impl { public class ServiceCreate { - private static readonly string templateDir = @"E:\桌面\SlnMesnac\SlnMesnac.Generate\Templates\Service\Impl\"; + private static readonly string templateDir = @"F:\Mesnac\2023部门项目\机场AGV调度\HightWay_AirPot_WCS\SlnMesnac.Generate\Templates\Service\Impl\"; public bool Create(string tableName, string NameSpace, string outdir) { diff --git a/SlnMesnac.Model/domain/AGVState.cs b/SlnMesnac.Model/domain/AGVState.cs new file mode 100644 index 0000000..3b130b9 --- /dev/null +++ b/SlnMesnac.Model/domain/AGVState.cs @@ -0,0 +1,75 @@ +using System; +using System.Linq; +using System.Text; +using SqlSugar; + +namespace SlnMesnac.Repository +{ + /// + /// + /// + [SugarTable("AGVState")] + public partial class AGVState + { + public AGVState(){ + + + } + /// + /// Desc: + /// Default: + /// Nullable:False + /// + [SugarColumn(IsPrimaryKey=true,IsIdentity=true,ColumnName="ID")] + public int id {get;set;} + + /// + /// Desc: + /// Default: + /// Nullable:False + /// + [SugarColumn(ColumnName="AGVNo")] + public string agvno {get;set;} + + /// + /// Desc: + /// Default: + /// Nullable:False + /// + [SugarColumn(ColumnName="AGVType")] + public string agvtype {get;set;} + + /// + /// Desc: + /// Default: + /// Nullable:False + /// + [SugarColumn(ColumnName="TaskNo")] + public string taskno {get;set;} + + /// + /// Desc: + /// Default: + /// Nullable:False + /// + [SugarColumn(ColumnName="AGVAlarmState")] + public string agvalarmstate {get;set;} + + /// + /// Desc: + /// Default: + /// Nullable:False + /// + [SugarColumn(ColumnName="AGVWorkState")] + public string agvworkstate {get;set;} + + /// + /// Desc: + /// Default: + /// Nullable:False + /// + [SugarColumn(ColumnName="RefreshTime")] + public DateTime refreshtime {get;set;} + + } +} diff --git a/SlnMesnac.Quartz/Job/GetAgvState_Job.cs b/SlnMesnac.Quartz/Job/GetAgvState_Job.cs new file mode 100644 index 0000000..a421b57 --- /dev/null +++ b/SlnMesnac.Quartz/Job/GetAgvState_Job.cs @@ -0,0 +1,27 @@ +using Microsoft.Extensions.Logging; +using Quartz; +using System; +using System.Threading.Tasks; + +namespace SlnMesnac.Quartz.Job +{ + /// + /// 定时获取设备状态 + /// + public class GetAgvState_Job : IJob + { + private readonly ILogger _logger; + + public GetAgvState_Job(ILogger logger) + { + _logger = logger; + } + + public Task Execute(IJobExecutionContext context) + { + _logger.LogInformation($"获取AGV状态:{DateTime.Now.ToString("HH:mm:ss")}"); + return Task.CompletedTask; + } + + } +} \ No newline at end of file diff --git a/SlnMesnac.Quartz/Job/GetTaskInfo_Job.cs b/SlnMesnac.Quartz/Job/GetTaskInfo_Job.cs new file mode 100644 index 0000000..e06050c --- /dev/null +++ b/SlnMesnac.Quartz/Job/GetTaskInfo_Job.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Quartz; +using SlnMesnac.Business.@base; +using SlnMesnac.Repository; +using SlnMesnac.Repository.service; + +namespace SlnMesnac.Quartz.Job +{ + public class GetTaskInfo_Job : IJob + { + private readonly ILogger _logger; + private IAirportTaskService _service; + private BaseTaskInfoBusiness _taskInfoBusiness; + public GetTaskInfo_Job(ILogger logger, IAirportTaskService service) + { + _logger = logger; + _service = service; + } + public Task Execute(IJobExecutionContext context) + { + + return Task.CompletedTask; + } + + /// + /// 获取任务列表 + /// + private void GetAGVTaskInfo() + { + try + { + List Task = _service.GetTaskInfos(); + } + catch (Exception ex) + { + + } + } + } +} \ No newline at end of file diff --git a/SlnMesnac.Quartz/Job/MyJob.cs b/SlnMesnac.Quartz/Job/MyJob.cs index 735f08c..0dd123c 100644 --- a/SlnMesnac.Quartz/Job/MyJob.cs +++ b/SlnMesnac.Quartz/Job/MyJob.cs @@ -40,7 +40,7 @@ namespace SlnMesnac.Quartz.Job public Task Execute(IJobExecutionContext context) { - _logger.LogInformation($"执行MyJob:{DateTime.Now.ToString("HH:mm:ss")}"); + _logger.LogInformation($"获取机械臂状态:{DateTime.Now.ToString("HH:mm:ss")}"); return Task.CompletedTask; } } diff --git a/SlnMesnac.Quartz/QuartzSetUp.cs b/SlnMesnac.Quartz/QuartzSetUp.cs index 1a6bb23..c1da80f 100644 --- a/SlnMesnac.Quartz/QuartzSetUp.cs +++ b/SlnMesnac.Quartz/QuartzSetUp.cs @@ -36,12 +36,15 @@ namespace SlnMesnac.Quartz { q.UseMicrosoftDependencyInjectionJobFactory(); - q.ScheduleJob(trigger => - trigger.WithCronSchedule("*/3 * * * * ?").WithIdentity("MyJob", "MyJobGroup") // 示例:每3s执行一次 - ); + //q.ScheduleJob(trigger => + // trigger.WithCronSchedule("*/3 * * * * ?").WithIdentity("MyJob", "MyJobGroup") // 示例:每3s执行一次 + //); - q.ScheduleJob(trigger => - trigger.WithCronSchedule("*/5 * * * * ?").WithIdentity("Job2", "Job2Group") // 示例:每5s执行一次 + q.ScheduleJob(trigger => + trigger.WithCronSchedule("*/5 * * * * ?").WithIdentity("GetAgvState_Job", "GetAgvState_JobGroup") // 示例:每5s执行一次 + ); + q.ScheduleJob(trigger => + trigger.WithCronSchedule("*/5 * * * * ?").WithIdentity("MyJob", "GetAgvState_JobGroup") // 示例:每5s执行一次 ); }); diff --git a/SlnMesnac.Quartz/SlnMesnac.Quartz.csproj b/SlnMesnac.Quartz/SlnMesnac.Quartz.csproj index 1040f6c..71fb50e 100644 --- a/SlnMesnac.Quartz/SlnMesnac.Quartz.csproj +++ b/SlnMesnac.Quartz/SlnMesnac.Quartz.csproj @@ -10,4 +10,9 @@ + + + + + diff --git a/SlnMesnac.Repository/service/IAGVStateService.cs b/SlnMesnac.Repository/service/IAGVStateService.cs new file mode 100644 index 0000000..446a2ba --- /dev/null +++ b/SlnMesnac.Repository/service/IAGVStateService.cs @@ -0,0 +1,26 @@ +using SlnMesnac.Model.domain; +using SlnMesnac.Repository.service.@base; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; + +namespace SlnMesnac.Repository.service +{ + public interface IAGVStateService: IBaseService + { + /// + /// ѯAGV״̬ + /// + /// + List GetAgvState(); + + /// + /// AGV豸״̬Ϣ + /// + /// + /// + Task UpdateAsync(AGVState record); + + } +} \ No newline at end of file diff --git a/SlnMesnac.Repository/service/IAirportTaskService.cs b/SlnMesnac.Repository/service/IAirportTaskService.cs index d2a7974..6a3d70d 100644 --- a/SlnMesnac.Repository/service/IAirportTaskService.cs +++ b/SlnMesnac.Repository/service/IAirportTaskService.cs @@ -3,15 +3,28 @@ using SlnMesnac.Repository.service.@base; using System; using System.Collections.Generic; using System.Text; +using System.Threading.Tasks; namespace SlnMesnac.Repository.service { public interface IAirportTaskService : IBaseService { /// - /// ȡб + /// ȡվ̨б /// /// List GetTaskInfos(); + /// + /// ȡִб + /// + /// + List GetAGVTaskInfos(); + + /// + /// б + /// + /// + /// + Task UpdateAsync(AirportTask record); } } \ No newline at end of file diff --git a/SlnMesnac.Repository/service/Impl/AGVStateServiceImpl.cs b/SlnMesnac.Repository/service/Impl/AGVStateServiceImpl.cs new file mode 100644 index 0000000..aeadc34 --- /dev/null +++ b/SlnMesnac.Repository/service/Impl/AGVStateServiceImpl.cs @@ -0,0 +1,42 @@ +using Microsoft.Extensions.Logging; +using SlnMesnac.Common; +using SlnMesnac.Model.domain; +using SlnMesnac.Repository.service.@base; +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Threading.Tasks; + +namespace SlnMesnac.Repository.service.Impl +{ + public class AGVStateServiceImpl : BaseServiceImpl, IAGVStateService + { + private ILogger _logger; + public AGVStateServiceImpl(Repository repository, ILogger logger) :base(repository) + { + _logger = logger; + } + public List GetAgvState() + { + List agvStateInfoList = null; + try + { + Expression> exp = x => true; + exp = exp.And(x => x.agvno != "" && (x.taskno == null || x.taskno == "") && x.agvworkstate == ""); + + agvStateInfoList = base._rep.GetList(exp); + } + catch (Exception ex) + { + _logger.LogError($"ͨͻȡϢ쳣:{ex.Message}"); + } + return agvStateInfoList; + } + + public async Task UpdateAsync(AGVState record) + { + bool result = await _rep.UpdateAsync(record); + return result; + } + } +} \ No newline at end of file diff --git a/SlnMesnac.Repository/service/Impl/AirportTaskServiceImpl.cs b/SlnMesnac.Repository/service/Impl/AirportTaskServiceImpl.cs index c1a9979..f8f7c6c 100644 --- a/SlnMesnac.Repository/service/Impl/AirportTaskServiceImpl.cs +++ b/SlnMesnac.Repository/service/Impl/AirportTaskServiceImpl.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq.Expressions; using System.Text; using SlnMesnac.Repository.service.@base; +using System.Threading.Tasks; #region << 版 本 注 释 >> /*-------------------------------------------------------------------- @@ -50,8 +51,7 @@ namespace SlnMesnac.Repository.service.Impl List taskInfos = null; try { - - String sql = "SELECT ConveyorNo,TaskNo ,MAX(StartTime),TaskState FROM AirportTask group by ConveyorNo "; + String sql = "SELECT ConveyorNo,TaskNo,FlightNo,AGVNo,MAX(StartTime) as StartTime,TaskState, TotalCount ,LoadCount FROM AirportTask group by ConveyorNo "; taskInfos = base._rep.AsTenant().GetConnection("AGV").Ado.SqlQuery(sql); } catch (Exception ex) @@ -61,7 +61,30 @@ namespace SlnMesnac.Repository.service.Impl return taskInfos; } - + /// + /// 获取AGV任务信息 + /// + /// + public List GetAGVTaskInfos() + { + List taskInfos = null; + try + { + String sql = "SELECT id, ConveyorNo,TaskNo,FlightNo,AGVNo,MAX(StartTime) as StartTime,TaskState, TotalCount ,LoadCount FROM AirportTask WHERE AGVNo IS NULL and TaskState = '等待' group by ConveyorNo "; + taskInfos = base._rep.AsTenant().GetConnection("AGV").Ado.SqlQuery(sql); + } + catch (Exception ex) + { + _logger.LogError($"获取AGV任务信息异常:{ex.Message}"); + } + return taskInfos; + } + + public async Task UpdateAsync(AirportTask record) + { + bool result = await _rep.UpdateAsync(record); + return result; + } } } diff --git a/SlnMesnac.WPF/Startup.cs b/SlnMesnac.WPF/Startup.cs index abe8f06..3eb2dee 100644 --- a/SlnMesnac.WPF/Startup.cs +++ b/SlnMesnac.WPF/Startup.cs @@ -12,6 +12,7 @@ using SlnMesnac.Rfid; using SlnMesnac.Ioc; using SlnMesnac.Plc; using SlnMesnac.Extensions; +using SlnMesnac.Quartz; using SlnMesnac.TouchSocket; namespace SlnMesnac.WPF @@ -46,6 +47,9 @@ namespace SlnMesnac.WPF //注册RFID工厂 //services.AddRfidFactorySetup(); + + //注册任务调度 + //services.AddQuartzSetUp(); } /// diff --git a/SlnMesnac.WPF/ViewModel/IndexPage/IndexContentViewModel.cs b/SlnMesnac.WPF/ViewModel/IndexPage/IndexContentViewModel.cs index 11568b3..51d78e3 100644 --- a/SlnMesnac.WPF/ViewModel/IndexPage/IndexContentViewModel.cs +++ b/SlnMesnac.WPF/ViewModel/IndexPage/IndexContentViewModel.cs @@ -42,8 +42,10 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage public partial class IndexContentViewModel: ObservableObject { private ILogger _logger; - private IAirportTaskService _service; - + private ILogger _taskBusinessLogger; + private IAirportTaskService _taskservice; + private IAGVStateService _agvstateService; + private BaseTaskInfoBusiness _taskInfoBusiness; private DispatcherTimer _timer; @@ -51,7 +53,17 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage { LogMessages = new ObservableCollection(); - _service = App.ServiceProvider.GetService(); + _taskBusinessLogger = App.ServiceProvider.GetService>(); + _taskservice = App.ServiceProvider.GetService(); + _agvstateService = App.ServiceProvider.GetService(); + _taskInfoBusiness = BaseTaskInfoBusiness.GetInstance(_taskBusinessLogger, _taskservice, _agvstateService); + _taskInfoBusiness._Taskaction += task => + { + TaskItems = new ObservableCollection + { + task + }; + }; this.Init(); } @@ -59,9 +71,8 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage { #region 测试数据 - List AirportTaskItem = _service.GetTaskInfos(); + List AirportTaskItem = _taskservice.GetTaskInfos(); TaskItems = new ObservableCollection(AirportTaskItem); - // TaskItems = new ObservableCollection // { // new AirportTask { TaskCode = "1", StationName = "1#站台", TaskDetails = "入库:P04->C01", Status = "任务状态:执行中" }, diff --git a/SlnMesnac.WPF/ViewModel/MainWindowViewModel.cs b/SlnMesnac.WPF/ViewModel/MainWindowViewModel.cs index dc851e3..68dec19 100644 --- a/SlnMesnac.WPF/ViewModel/MainWindowViewModel.cs +++ b/SlnMesnac.WPF/ViewModel/MainWindowViewModel.cs @@ -2,6 +2,9 @@ using GalaSoft.MvvmLight.Command; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using SlnMesnac.Business.@base; +using SlnMesnac.Repository.service; +using SlnMesnac.TouchSocket; using SlnMesnac.WPF.Page.Generate; using SlnMesnac.WPF.Page.IndexPage; using System; @@ -12,6 +15,9 @@ namespace SlnMesnac.WPF.ViewModel public class MainWindowViewModel: ViewModelBase { private readonly ILogger _logger; + private readonly ILogger _BaseTaskInfoBusinesslogger; + private IAirportTaskService _Taskservice; + private IAGVStateService _AGVStateService; //代码生成 private readonly GenerateControl generateControl = new GenerateControl(); @@ -82,7 +88,11 @@ namespace SlnMesnac.WPF.ViewModel { _logger = App.ServiceProvider.GetService>(); + _Taskservice = App.ServiceProvider.GetService(); + _AGVStateService = App.ServiceProvider.GetService(); + _BaseTaskInfoBusinesslogger = App.ServiceProvider.GetService>(); + BaseTaskInfoBusiness.GetInstance(_BaseTaskInfoBusinesslogger, _Taskservice, _AGVStateService); ControlOnClickCommand = new RelayCommand(obj => ControlOnClick(obj)); FormControlCommand = new RelayCommand(x => FormControl(x)); diff --git a/SlnMesnac.WPF/appsettings.json b/SlnMesnac.WPF/appsettings.json index e5d344d..1c30f52 100644 --- a/SlnMesnac.WPF/appsettings.json +++ b/SlnMesnac.WPF/appsettings.json @@ -10,16 +10,16 @@ "AppConfig": { "logPath": "F:\\Mesnac\\2023部门项目\\机场AGV调度\\HightWay_AirPot_WCS\\SlnMesnac.WPF\\bin\\Debug\\net6.0-windows\\log", "SqlConfig": [ - { - "configId": "mes", - "dbType": 1, - "connStr": "server=.;uid=sa;pwd=123456;database=JiangYinMENS" - }, - { - "configId": "mcs", - "dbType": 3, - "connStr": "Data Source=175.27.215.92/helowin;User ID=aucma_scada;Password=aucma" - }, + //{ + // "configId": "mes", + // "dbType": 1, + // "connStr": "server=.;uid=sa;pwd=123456;database=JiangYinMENS" + //}, + //{ + // "configId": "mcs", + // "dbType": 3, + // "connStr": "Data Source=175.27.215.92/helowin;User ID=aucma_scada;Password=aucma" + //}, { "configId": "AGV", "dbType": 2,