任务服务优化与接口扩展,日志与配置调整
本次提交包括以下主要更新:
- 优化任务服务可用巷道查询逻辑,增加EnalbeStatus判断,跳过无可用数量巷道,并新增异步接口GetRoadWayAsync。
- 简化库存查询流程,去除部分物料明细遍历,提升效率。
- 托盘入库校验增加产线与巷道匹配校验,提升数据准确性。
- 调整输送线任务相关日志输出,减少无用日志,优化异常信息过滤,避免重复记录“存在任务”类异常。
- 路由查询方法中性能日志输出被注释,减少日志干扰。
- TaskController扩展依赖注入,新增GetRoadWayAsync接口,支持前端异步获取可用巷道。
- 配置文件格式化,主库连接字符串调整为本地数据库,结构更规范。
- 程序集信息及数据库文件同步更新。
| | |
| | | [assembly: System.Reflection.AssemblyCompanyAttribute("WIDESEAWCS_ProcessService")] |
| | | [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] |
| | | [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] |
| | | [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+29aa484d06b2d4839536034bb1033d0e60334ec2")] |
| | | [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+02a4fdd78cef9c7d2a26bfb9aa187179cf0baac3")] |
| | | [assembly: System.Reflection.AssemblyProductAttribute("WIDESEAWCS_ProcessService")] |
| | | [assembly: System.Reflection.AssemblyTitleAttribute("WIDESEAWCS_ProcessService")] |
| | | [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] |
| | |
| | | { |
| | | // 用于记录已经访问过的起点和终点组合,避免重复访问进入死循环 |
| | | HashSet<string> visitedRoutes = new HashSet<string>(); |
| | | var stopwatch = Stopwatch.StartNew(); |
| | | //var stopwatch = Stopwatch.StartNew(); |
| | | var rasult = QueryNextRoutesInternal(startPosi, endPosi, visitedRoutes); |
| | | |
| | | stopwatch.Stop(); |
| | | var elapsed = stopwatch.ElapsedMilliseconds; |
| | | QuartzLogger.WriteLogToFile("路由查询", $"时长{elapsed},起点:{startPosi},终点{endPosi}"); |
| | | //stopwatch.Stop(); |
| | | //var elapsed = stopwatch.ElapsedMilliseconds; |
| | | //QuartzLogger.WriteLogToFile("路由查询", $"时长{elapsed},起点:{startPosi},终点{endPosi}"); |
| | | return rasult; |
| | | } |
| | | |
| | |
| | | |
| | | if (childDeviceCode == "1670" || childDeviceCode == "1666" || childDeviceCode == "1548" || childDeviceCode == "1448") |
| | | { |
| | | if (lastUpdateTime > DateTime.Now.AddMinutes(1)) |
| | | { |
| | | lastUpdateTime = DateTime.Now; |
| | | //if (lastUpdateTime > DateTime.Now.AddMinutes(1)) |
| | | //{ |
| | | // lastUpdateTime = DateTime.Now; |
| | | Platform platform = _platFormRepository.QueryFirst(x => x.DeviceCode == conveyorLine.DeviceCode && x.PlatCode == childDeviceCode && x.Status == "Active"); |
| | | if (platform != null) |
| | | { |
| | |
| | | } |
| | | } |
| | | } |
| | | } |
| | | //} |
| | | } |
| | | |
| | | #region 调用事件总线通知前端 |
| | |
| | | List<string> strings = platform.Location.Split(',').ToList(); |
| | | |
| | | var result = await HttpHelper.PostAsync(wmsIpAddress, new { Position = childDeviceCode, Tag = (int)taskType, AreaCdoe = platform.Stacker, AreaCdoes = strings, platform.ProductionLine }.Serialize()); |
| | | WriteInfo("OCV请求返回参数", $"时间:【{DateTime.Now}】请求点位【{childDeviceCode}】返回参数【{JsonConvert.SerializeObject(result)}】"); |
| | | |
| | | WebResponseContent content = JsonConvert.DeserializeObject<WebResponseContent>(result); |
| | | |
| | | ConsoleHelper.WriteSuccessLine($"时间:【{DateTime.Now}】请求WMS出库任务返回结果:【{content.Serialize()}】"); |
| | | |
| | | // 检查状态并返回 |
| | | if (!content.Status) |
| | | return; |
| | |
| | | } |
| | | else |
| | | { |
| | | if (content.Message != "请求过于频繁,请稍后再试" && content.Message != "无法获取目标地址") |
| | | if (content.Message != "请求过于频繁,请稍后再试" && content.Message != "无法获取目标地址" && !content.Message.Contains("存在任务")) |
| | | { |
| | | WriteInfo(conveyorLine.DeviceName, content.Message); |
| | | conveyorLine.SetValue(ConveyorLineDBName_After.ConveyorLineTargetAddress, stationManager.stationNGChildCode, childDeviceCode); |
| | |
| | | List<string> strings = platform.Location.Split(',').ToList(); |
| | | |
| | | var result = await HttpHelper.PostAsync(wmsIpAddress, new { Position = childDeviceCode, Tag = (int)taskType, AreaCdoe = platform.Stacker, AreaCdoes = strings, platform.ProductionLine }.Serialize()); |
| | | WriteInfo("OCV请求返回参数", $"时间:【{DateTime.Now}】请求点位【{childDeviceCode}】返回参数【{JsonConvert.SerializeObject(result)}】"); |
| | | |
| | | WebResponseContent content = JsonConvert.DeserializeObject<WebResponseContent>(result); |
| | | |
| | |
| | | /// </summary> |
| | | /// <returns></returns> |
| | | WebResponseContent GetLocationStatus(); |
| | | |
| | | Task<string> GetRoadWayAsync(List<string> process); |
| | | } |
| | |
| | | } |
| | | |
| | | //var outBoundMateriel = AppSettings.app<OutBoundMateriel>("OutBoundMateriel"); |
| | | var outBoundMateriel = _dt_ChangeoversRepository.QueryData(x => x.Status == "1").ToList(); |
| | | //var outBoundMateriel = _dt_ChangeoversRepository.QueryData(x => x.Status == "1").ToList(); |
| | | |
| | | List<string>? materielCodes = outBoundMateriel.Count != 0 |
| | | ? outBoundMateriel.Where(x => x.ProductionLine == productionLine && x.ProcessCode == area.AreaCode) |
| | | .Select(x => x.MaterielCode) |
| | | .ToList() |
| | | : null; |
| | | //List<string>? materielCodes = outBoundMateriel.Count != 0 |
| | | // ? outBoundMateriel.Where(x => x.ProductionLine == productionLine && x.ProcessCode == area.AreaCode) |
| | | // .Select(x => x.MaterielCode) |
| | | // .ToList() |
| | | // : null; |
| | | |
| | | var result = new DtStockInfo(); |
| | | //DtStockInfo result = null; |
| | | |
| | | var stockInfoList = await _stockInfoRepository.Db.Queryable<DtStockInfo>() |
| | | var result = await _stockInfoRepository.Db.Queryable<DtStockInfo>() |
| | | .Includes(x => x.LocationInfo) |
| | | //.Includes(x => x.StockInfoDetails) |
| | | .Where(x => x.AreaCode == areaCode && x.OutboundTime < DateTime.Now && x.IsFull) |
| | |
| | | .Where(x => x.LocationInfo.LocationStatus == (int)LocationEnum.InStock && x.LocationInfo.AreaId == area.AreaID && x.LocationInfo.EnalbeStatus == (int)EnableEnum.Enable) |
| | | //.WhereIF(!materielCodes.IsNullOrEmpty(), x => x.StockInfoDetails.Any(y => materielCodes.Contains(y.MaterielCode))) |
| | | .OrderBy(x => x.OutboundTime) |
| | | .ToListAsync(); |
| | | foreach (var stock in stockInfoList) |
| | | { |
| | | var hasMatchingDetail = await _stockInfoRepository.Db.Queryable<DtStockInfoDetail>() |
| | | .Where(d => d.StockId == stock.Id && materielCodes.Contains(d.MaterielCode)) |
| | | .AnyAsync(); |
| | | .FirstAsync(); |
| | | //foreach (var stock in stockInfoList) |
| | | //{ |
| | | // var hasMatchingDetail = await _stockInfoRepository.Db.Queryable<DtStockInfoDetail>() |
| | | // .Where(d => d.StockId == stock.Id && materielCodes.Contains(d.MaterielCode)) |
| | | // .AnyAsync(); |
| | | |
| | | if (hasMatchingDetail) |
| | | { |
| | | result = stock; |
| | | break; |
| | | } |
| | | } |
| | | // if (hasMatchingDetail) |
| | | // { |
| | | // result = stock; |
| | | // break; |
| | | // } |
| | | //} |
| | | |
| | | if (result.IsNullOrEmpty()) |
| | | ConsoleHelper.WriteErrorLine($"{area.AreaName}-{productionLine}查询实盘库存信息失败:未找到符合条件的数据"); |
| | |
| | | ConsoleHelper.WriteErrorLine(content.ToJsonString()); |
| | | var result = JsonConvert.DeserializeObject<ResultTrayCellsStatus>(content.Data.ToString()); |
| | | if (result == null || !result.Success) return content.Error(result?.MOMMessage ?? "Deserialization error"); |
| | | |
| | | List<string> strings = station.productLine.Split(",").ToList(); |
| | | if (!result.ProductionLine.Contains(strings)) |
| | | { |
| | | ConsoleHelper.WriteErrorLine($"托盘号【{palletCode}】请求产线【{result.ProductionLine}】不允许入【{station.Roadway}】"); |
| | | return content.Error($"托盘号【{palletCode}】请求产线【{result.ProductionLine}】不允许入【{station.Roadway}】"); |
| | | } |
| | | |
| | | if (result.SerialNos.Count > 0) |
| | | { |
| | |
| | | .Where(x => x.DeviceStatus == 1.ToString() && process.Contains(x.DeviceCode)) |
| | | .Select(x => x.DeviceCode).ToListAsync(); |
| | | |
| | | var minGroup = _locationRepository.QueryData(x => deviceCode.Contains(x.RoadwayNo) && x.LocationStatus == (int)LocationEnum.Free) |
| | | var minGroup = _locationRepository.QueryData(x => deviceCode.Contains(x.RoadwayNo) && x.LocationStatus == (int)LocationEnum.Free && x.EnalbeStatus == (int)EnableEnum.Enable) |
| | | .GroupBy(x => x.RoadwayNo) |
| | | .OrderByDescending(g => g.Count()) // 根据每个组的元素数量排序 |
| | | .ToList(); // 取出数量最多的组 |
| | |
| | | foreach (var item in minGroup) |
| | | { |
| | | var number = BaseDal.QueryData(x => x.TargetAddress == item.Key).Count(); |
| | | if (item.Count() - number <= 0) |
| | | { |
| | | continue; |
| | | } |
| | | result.Add(item.Key, item.Count() - number); |
| | | } |
| | | |
| | |
| | | using WIDESEA_DTO; |
| | | using WIDESEA_Core.BaseRepository; |
| | | using WIDESEA_DTO; |
| | | using WIDESEA_IStorageBasicRepository; |
| | | using WIDESEA_IStorageTaskRepository; |
| | | using WIDESEAWCS_QuartzJob.Models; |
| | | |
| | | namespace WIDESEA_WMSServer.Controllers; |
| | | |
| | |
| | | private readonly IHttpContextAccessor _httpContextAccessor; |
| | | private readonly IDt_TaskService _taskService; |
| | | private readonly ILocationInfoService _locationService; |
| | | private readonly ILocationInfoRepository _locationRepository; |
| | | private readonly IDt_TaskRepository BaseDal; |
| | | |
| | | public TaskController(IDt_TaskService taskService, |
| | | IHttpContextAccessor httpContextAccessor, |
| | | ILocationInfoService locationService) : base(taskService) |
| | | ILocationInfoService locationService, ILocationInfoRepository locationInfoRepository,IDt_TaskRepository repository) : base(taskService) |
| | | { |
| | | _httpContextAccessor = httpContextAccessor; |
| | | _taskService = taskService; |
| | | _locationService = locationService; |
| | | _locationRepository = locationInfoRepository; |
| | | BaseDal = repository; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | { |
| | | return Service.GetLocationStatus(); |
| | | } |
| | | |
| | | [HttpPost, AllowAnonymous, Route("GetRoadWayAsync")] |
| | | public async Task<string> GetRoadWayAsync(List<string> process) |
| | | { |
| | | return await Service.GetRoadWayAsync(process); |
| | | } |
| | | } |
| | |
| | | { |
| | | "Logging": { |
| | | "LogLevel": { |
| | | "Default": "Information", |
| | | "Microsoft.AspNetCore": "Warning" |
| | | } |
| | | }, |
| | | "AllowedHosts": "*", |
| | | "urls": "http://*:5000", |
| | | "MainDB": "DB_WIDESEA", //当前项目的主库,所对应的连接字符串的Enabled必须为true |
| | | //连接字符串 |
| | | //"ConnectionString": "HTI6FB1H05Krd07mNm9yBCNhofW6edA5zLs9TY~MNthRYW3kn0qKbMIsGp~3yyPDF1YZUCPBQx8U0Jfk4PH~ajNFXVIwlH85M3F~v_qKYQ3CeAz3q1mLVDn8O5uWt1~3Ut2V3KRkEwYHvW2oMDN~QIDXPxDgXN0R2oTIhc9dNu7QNaLEknblqmHhjaNSSpERdDVZIgHnMKejU_SL49tralBkZmDNi0hmkbL~837j1NWe37u9fJKmv91QPb~16JsuI9uu0EvNZ06g6PuZfOSAeFH9GMMIZiketdcJG3tHelo=", |
| | | //"ConnectionString": "Data Source=192.168.15.253;Initial Catalog=WIDESEA_WMSDB_BBMain;User ID=sa;Password=P@ssw0rd;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False", |
| | | "ConnectionString": "Data Source=192.168.20.253;Initial Catalog=WIDESEA_WMSDB;User ID=sa;Password=P@ssw0rd;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False", |
| | | //"ConnectionString": "Data Source=.\\LIULEI;Initial Catalog=WIDESEA_WMSDB_BBMain;User ID=sa;Password=123456;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False", |
| | | //"ConnectionString": "Data Source=192.168.20.251;Initial Catalog=WIDESEA_WMSDB;User ID=sa;Password=123456@gy;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False", |
| | | //"ConnectionStringWCS": "Data Source=192.168.15.253;Initial Catalog=WIDESEA_WCSDB_BBMain;User ID=sa;Password=P@ssw0rd;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False", |
| | | "ConnectionStringWCS": "Data Source=192.168.20.253;Initial Catalog=WIDESEA_WCSDB;User ID=sa;Password=P@ssw0rd;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False", |
| | | //跨域 |
| | | "Cors": { |
| | | "PolicyName": "CorsIpAccess", //策略名称 |
| | | "EnableAllIPs": true, //当为true时,开放所有IP均可访问。 |
| | | // 支持多个域名端口,注意端口号后不要带/斜杆:比如localhost:8000/,是错的 |
| | | // 注意,http://127.0.0.1:1818 和 http://localhost:1818 是不一样的 |
| | | "IPs": "http://127.0.0.1:8080,http://localhost:8080,http://127.0.0.1:8081,http://localhost:8081" |
| | | }, |
| | | "ApiName": "WIDESEA", |
| | | "ExpMinutes": 120, |
| | | "Logging": { |
| | | "LogLevel": { |
| | | "Default": "Information", |
| | | "Microsoft.AspNetCore": "Warning" |
| | | } |
| | | }, |
| | | "AllowedHosts": "*", |
| | | "urls": "http://*:5000", |
| | | "MainDB": "DB_WIDESEA", //当前项目的主库,所对应的连接字符串的Enabled必须为true |
| | | //连接字符串 |
| | | //"ConnectionString": "HTI6FB1H05Krd07mNm9yBCNhofW6edA5zLs9TY~MNthRYW3kn0qKbMIsGp~3yyPDF1YZUCPBQx8U0Jfk4PH~ajNFXVIwlH85M3F~v_qKYQ3CeAz3q1mLVDn8O5uWt1~3Ut2V3KRkEwYHvW2oMDN~QIDXPxDgXN0R2oTIhc9dNu7QNaLEknblqmHhjaNSSpERdDVZIgHnMKejU_SL49tralBkZmDNi0hmkbL~837j1NWe37u9fJKmv91QPb~16JsuI9uu0EvNZ06g6PuZfOSAeFH9GMMIZiketdcJG3tHelo=", |
| | | "ConnectionString": "Data Source=.;Initial Catalog=WIDESEA_WMSDB_BBMain;User ID=sa;Password=P@ssw0rd;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False", |
| | | "ConnectionStringWCS": "Data Source=192.168.20.253;Initial Catalog=WIDESEA_WCSDB;User ID=sa;Password=P@ssw0rd;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False", |
| | | //跨域 |
| | | "Cors": { |
| | | "PolicyName": "CorsIpAccess", //策略名称 |
| | | "EnableAllIPs": true, //当为true时,开放所有IP均可访问。 |
| | | // 支持多个域名端口,注意端口号后不要带/斜杆:比如localhost:8000/,是错的 |
| | | // 注意,http://127.0.0.1:1818 和 http://localhost:1818 是不一样的 |
| | | "IPs": "http://127.0.0.1:8080,http://localhost:8080,http://127.0.0.1:8081,http://localhost:8081" |
| | | }, |
| | | "ApiName": "WIDESEA", |
| | | "ExpMinutes": 120, |
| | | |
| | | // 需要移库的行 |
| | | "TransfertRows": "1,4,5,8", |
| | | "CacheSettings": { |
| | | "UseRedis": false, |
| | | "RedisSettings": { |
| | | "Address": "127.0.0.1:6379", |
| | | "Password": "123456", |
| | | "Db": 9, |
| | | "ClearRedis": true |
| | | } |
| | | }, |
| | | // 允许出库的编码 |
| | | "OutBoundMateriel": [ |
| | | //{ |
| | | // "MaterielCode": "CC01050001348", |
| | | // "ProductionLine": "ZJ-8", |
| | | // "ProcessCode": "CH001" |
| | | //} |
| | | ] |
| | | // 需要移库的行 |
| | | "TransfertRows": "1,4,5,8", |
| | | "CacheSettings": { |
| | | "UseRedis": false, |
| | | "RedisSettings": { |
| | | "Address": "127.0.0.1:6379", |
| | | "Password": "123456", |
| | | "Db": 9, |
| | | "ClearRedis": true |
| | | } |
| | | }, |
| | | // 允许出库的编码 |
| | | "OutBoundMateriel": [ |
| | | //{ |
| | | // "MaterielCode": "CC01050001348", |
| | | // "ProductionLine": "ZJ-8", |
| | | // "ProcessCode": "CH001" |
| | | //} |
| | | ] |
| | | } |