Merge branch 'dev' of http://115.159.85.185:8098/r/SuZhouGuanHong/ShanMeiXinNengYuan into dev
| | |
| | | /// <summary> |
| | | /// WMSæ¥å£åºç¡URL |
| | | /// </summary> |
| | | public const string WMSBaseUrl = "http://localhost:9291/api/"; |
| | | public const string WMSBaseUrl = "http://192.168.60.30:9291/api/"; |
| | | |
| | | /// <summary> |
| | | /// WCSæ¥å£åºç¡URL |
| | |
| | | DataType_Char => TypeCode.Char, |
| | | DataType_UInt => TypeCode.UInt16, |
| | | DataType_UDInt => TypeCode.UInt32, |
| | | DataType_ByteArray => TypeCode.SByte, |
| | | _ => throw new CommunicationException($"æ°æ®ç±»åé误:ã{dataType}ã", CommunicationErrorType.TypeError), |
| | | }; |
| | | } |
| | |
| | | return Encoding.Default.GetString((byte[])GetContent(plc.Read(address, length), address)).ToArray(); |
| | | return (char)GetContent(plc.ReadByte(address), address); |
| | | |
| | | case TypeCode.SByte: |
| | | return Encoding.Default.GetString((byte[])GetContent(plc.Read(address, 20), address)).ToArray(); |
| | | |
| | | default: |
| | | throw new CommunicationException(string.Format(CommunicationExceptionMessage.DataTypeErrorException, typeCode.ToString(), address), CommunicationErrorType.TypeError); |
| | | } |
| | |
| | | WebResponseContent GetWMSRobotTask(Dt_Task task); |
| | | |
| | | /// <summary> |
| | | /// |
| | | /// </summary> |
| | | /// <param name="taskType"></param> |
| | | /// <param name="palletCode"></param> |
| | | /// <returns></returns> |
| | | int GetRobotTaskTotalNum(int taskType, string? palletCode); |
| | | |
| | | /// <summary> |
| | | /// 卿¬å°ç´æ¥åå»ºæºæ¢°æä»»å¡ï¼ä¸è°ç¨WMSæ¥å£ |
| | | /// </summary> |
| | | /// <param name="task">åºåºä»»å¡</param> |
| | | /// <returns>æä½ç»æ</returns> |
| | | WebResponseContent CreateLocalRobotTask(Dt_Task task); |
| | | |
| | | /// <summary> |
| | | /// æ£æ¥æºçº¿ä½æ¯å¦ææçå·ï¼å¹¶æ ¹æ®ç»æåå»ºæºæ¢°æä»»å¡ã |
| | | /// ææçå·æ¶è°ç¨ CreateLocalRobotTaskï¼æ æçå·æ¶ä» WMS è·åä»»å¡ã |
| | | /// </summary> |
| | | /// <param name="task">åºåºä»»å¡å®ä½</param> |
| | | /// <returns>æä½ç»æ</returns> |
| | | WebResponseContent CheckSourceLineAndCreateRobotTask(Dt_Task task); |
| | | |
| | | int MapWarehouseIdConfigKey(string? targetAddress); |
| | | string ResolveRobotRuleValue(string? targetAddress, string addressSectionName, string? fallback);
|
| | | WebResponseContent CreateRobotTaskManually(ManualRobotTaskDto request);
|
| | |
| | | public int[]? LastPutPositions { get; set; } |
| | | |
| | | /// <summary> |
| | | /// çµæ± /è´§ä½æ¡ç å表 |
| | | /// çµæ± /è´§ä½æ¡ç å表ï¼ç´¯ç§¯æææ¹æ¬¡ï¼ä¸éå¤ï¼ |
| | | /// </summary> |
| | | /// <remarks> |
| | | /// å¨ç»çæä½æ¶ç¨äºè®°å½çæçæçæ¡ç ã |
| | | /// å¨ç»çæä½æ¶ç¨äºç´¯ç§¯è®°å½ææçµè¯æ¡ç ï¼æ¯æ¬¡è¯»åæ°æ¡ç æ¶è¿½å ï¼å»éï¼ã |
| | | /// ä»
卿¶å° allputfinishedï¼å
¨é¨æ¾è´§å®æï¼æ¶æ¸
空ã |
| | | /// æ¯ä¸ªæ¡ç æ ¼å¼ä¸º "TRAY" + æ¥æ + æ¶é´ + éæºæ°ã |
| | | /// </remarks> |
| | | public List<string> CellBarcode { get; set; } = new List<string>(); |
| | | |
| | | /// <summary> |
| | | /// å½åæ¹æ¬¡ççµè¯æ¡ç å表 |
| | | /// </summary> |
| | | /// <remarks> |
| | | /// æ¯æ¬¡è¯»åæ°æ¡ç æ¶è®¾ç½®ä¸ºæ¬æ¹æ¬¡çæ¡ç ï¼ä»
ç¨äº WMS æäº¤æ¶ææ¹æ¬¡æäº¤ã |
| | | /// æ¯æ¬¡æ°æ¹æ¬¡è¯»åæ¶è¦çï¼å¨ allputfinished æ¶æ¸
空ã |
| | | /// </remarks> |
| | | public List<string> CurrentBatchBarcodes { get; set; } = new List<string>(); |
| | | |
| | | /// <summary> |
| | | /// æºæ¢°æå½åæ£å¨æ§è¡çä»»å¡ |
| | |
| | | /// æå¸¦çº¿ä¸çµè¯æ¯å¦å°ä½ã |
| | | /// </remarks> |
| | | public bool BatteryArrived { get; set; } = false; |
| | | |
| | | /// <summary> |
| | | /// å½åæ§è¡ä¸çæºå¨äººä»»å¡ç¼å· |
| | | /// </summary> |
| | | /// <remarks> |
| | | /// ä¸å任塿¶ç¼åä»»å¡ç¼å·ï¼ç¨äº RobotJob å¿«éæ¥æ¾æ§è¡ä¸çä»»å¡ï¼ |
| | | /// é¿å
æ¯æ¬¡è½®è¯¢å
¨è¡¨æ«æãä»»å¡å®ææ¶æ¸
空为 nullã |
| | | /// </remarks> |
| | | public int? CurrentTaskNum { get; set; } |
| | | } |
| | | } |
| | |
| | | /// <returns></returns> |
| | | private ITrigger CreateSimpleTrigger(DispatchInfoDTO sysSchedule) |
| | | { |
| | | // Quartzè¦æ±é´éè³å°1ç§ï¼é²æ¢æ°æ®åºä¸IntervalSecond为0æè´å¼å¯¼è´ArgumentOutOfRangeException |
| | | var intervalSeconds = sysSchedule.IntervalSecond <= 0 ? 1 : sysSchedule.IntervalSecond; |
| | | |
| | | ITrigger trigger = TriggerBuilder.Create() |
| | | .WithIdentity(sysSchedule.Id.ToString(), sysSchedule.JobGroup) |
| | | .StartAt(sysSchedule.BeginTime.GetValueOrDefault()) |
| | | .WithSimpleSchedule(x => x |
| | | .WithIntervalInSeconds(sysSchedule.IntervalSecond) |
| | | .WithIntervalInSeconds(intervalSeconds) |
| | | .RepeatForever() |
| | | ) |
| | | .EndAt(sysSchedule.EndTime.GetValueOrDefault()) |
| | |
| | | public IServer GetServer() |
| | | { |
| | | var endpoints = _connection.Value.GetEndPoints(); |
| | | if (endpoints == null || endpoints.Length == 0) |
| | | throw new InvalidOperationException("Redis没æå¯ç¨çç»ç»ç¹ï¼è¯·æ£æ¥è¿æ¥é
ç½®"); |
| | | return _connection.Value.GetServer(endpoints[0]); |
| | | } |
| | | |
| | |
| | | using Autofac.Core;
|
| | | using Masuit.Tools;
|
| | | using Microsoft.AspNetCore.Authorization;
|
| | | using Microsoft.AspNetCore.Mvc;
|
| | | using System.Threading.Tasks;
|
| | | using WIDESEAWCS_Common.TaskEnum;
|
| | | using WIDESEAWCS_Core;
|
| | | using WIDESEAWCS_Core.BaseController;
|
| | | using WIDESEAWCS_Core.Enums;
|
| | | using WIDESEAWCS_DTO.TaskInfo;
|
| | | using WIDESEAWCS_ISystemServices;
|
| | | using WIDESEAWCS_ITaskInfoService;
|
| | | using WIDESEAWCS_Model.Models;
|
| | |
|
| | |
| | | {
|
| | | public RobotTaskController(IRobotTaskService service) : base(service)
|
| | | {
|
| | | |
| | | }
|
| | |
|
| | | [HttpGet, HttpPost, Route("DeleteRobotTask"), AllowAnonymous]
|
| | | public WebResponseContent DeleteRobotTask(int id)
|
| | | {
|
| | | if (Service.DeleteRobotTask(id)){
|
| | | if (Service.DeleteRobotTask(id))
|
| | | {
|
| | | return WebResponseContent.Instance.OK();
|
| | | }
|
| | | return WebResponseContent.Instance.Error();
|
| | | }
|
| | |
|
| | | [HttpGet, HttpPost, Route("GetRobotTaskTotalNum"), AllowAnonymous]
|
| | | public int GetRobotTaskTotalNum(int taskType, string? palletCode)
|
| | | {
|
| | | return Service.GetRobotTaskTotalNum(taskType, palletCode);
|
| | | }
|
| | |
|
| | | // æå¨æºæ¢°æä»»å¡
|
| | | [HttpGet, HttpPost, Route("CreateRobotTaskManually"), AllowAnonymous]
|
| | | public WebResponseContent CreateRobotTaskManually([FromBody] ManualRobotTaskDto request) |
| | | public WebResponseContent CreateRobotTaskManually([FromBody] ManualRobotTaskDto request)
|
| | | {
|
| | | return Service.CreateRobotTaskManually(request);
|
| | | }
|
| | | }
|
| | | }
|
| | | } |
| | |
| | | //5.PostgreSQL |
| | | "DBType": "SqlServer", |
| | | //è¿æ¥å符串 |
| | | "ConnectionString": "Data Source=.;Initial Catalog=WIDESEAWCS_ShanMei;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.60.30;Initial Catalog=WIDESEAWCS_ShanMei;User ID=sa;Password=P@ssw0rd;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False", |
| | | //"ConnectionString": "Data Source=.;Initial Catalog=WIDESEAWCS_ShanMei;User ID=sa;Password=123456;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False", |
| | | |
| | | //è·¨å |
| | |
| | | |
| | | if (task.TaskStatus == (int)TaskOutStatusEnum.Line_OutFinish && task.TaskType == (int)TaskOutboundTypeEnum.Outbound) |
| | | { |
| | | return WebResponseContent.Instance.OK(); |
| | | //return WebResponseContent.Instance.OK(); |
| | | |
| | | //return _robotTaskService.CheckSourceLineAndCreateRobotTask(task); |
| | | // Todo:è·å对åçº¿ä½æ¯å¦ææçå·ï¼å¦æææçå·ç´æ¥çææºæ¢°æä»»å¡ |
| | | |
| | | return GetWMSOutboundTrayTask(task); |
| | | } |
| | | |
| | | if (task.TaskStatus == (int)TaskOutStatusEnum.Line_OutFinish && task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty) |
| | | { |
| | | return _robotTaskService.CreateLocalRobotTask(task); |
| | | return _robotTaskService.CreateLocalRobotTask(task); |
| | | //if (!content.Status) |
| | | //{ |
| | | // return content; |
| | |
| | | using Masuit.Tools;
|
| | | using Microsoft.Extensions.Configuration;
|
| | | using Newtonsoft.Json;
|
| | | using Newtonsoft.Json.Linq;
|
| | | using Serilog;
|
| | | using SqlSugar;
|
| | | using System.Diagnostics;
|
| | | using System.Diagnostics.CodeAnalysis;
|
| | | using System.Text;
|
| | | using WIDESEA_Core;
|
| | | using WIDESEAWCS_Common;
|
| | | using WIDESEAWCS_Common.HttpEnum;
|
| | |
| | | _taskExecuteDetailService = taskExecuteDetailService;
|
| | | _logger = logger;
|
| | | }
|
| | |
|
| | | public override WebResponseContent DeleteData(object[] keys)
|
| | | {
|
| | | List<int> taskKeys = new List<int>();
|
| | |
| | | List<Dt_RobotTask> tasks = BaseDal.QueryData(x => taskKeys.Contains(x.RobotTaskId));
|
| | | BaseDal.DeleteAndMoveIntoHty(tasks, OperateTypeEnum.人工å é¤);
|
| | | return WebResponseContent.Instance.OK($"æåå é¤{tasks.Count}æ¡æ°æ®");
|
| | |
|
| | | }
|
| | |
|
| | | public bool DeleteRobotTask(int id)
|
| | | {
|
| | | Dt_RobotTask task = BaseDal.QueryFirst(x => x.RobotTaskId == id);
|
| | |
| | |
|
| | | public Dt_RobotTask? QueryRobotCraneTask(string deviceCode)
|
| | | {
|
| | | return BaseDal.QueryFirst(x => x.RobotRoadway == deviceCode && x.RobotTaskState != (int)TaskRobotStatusEnum.RobotExecuting, TaskOrderBy);
|
| | | return BaseDal.QueryFirst(x => x.RobotRoadway == deviceCode, TaskOrderBy);
|
| | | }
|
| | |
|
| | | public Dt_RobotTask? QueryRobotCraneExecutingTask(string deviceCode)
|
| | |
| | | }
|
| | |
|
| | | /// <summary>
|
| | | /// æ£æ¥æºçº¿ä½æ¯å¦ææçå·ï¼å¹¶æ ¹æ®ç»æåå»ºæºæ¢°æä»»å¡ã
|
| | | /// </summary>
|
| | | /// <param name="task">åºåºä»»å¡å®ä½</param>
|
| | | /// <returns>
|
| | | /// ææçå·æ¶è¿å CreateLocalRobotTask ç»æï¼
|
| | | /// æ æçå·æ¶è¿å GetWMSOutboundTrayTask ç»æã
|
| | | /// </returns>
|
| | | public WebResponseContent CheckSourceLineAndCreateRobotTask(Dt_Task task)
|
| | | {
|
| | | // 1. è·åæºçº¿ä½ç¼å·ï¼å¤ç¨å·²æé»è¾ï¼
|
| | | string configKey = ResolveRobotTaskConfigKey(task.TargetAddress);
|
| | | StockDTO stock = BuildRobotTaskStock(task, configKey);
|
| | | string sourceLineNo = stock.SourceLineNo;
|
| | |
|
| | | if (string.IsNullOrWhiteSpace(sourceLineNo))
|
| | | {
|
| | | return GetWMSOutboundTrayTaskFromWMS(task);
|
| | | }
|
| | |
|
| | | // 2. éè¿è®¾å¤é信读åçº¿ä½æçå·
|
| | | string? palletCode = ReadLineBarcode(sourceLineNo);
|
| | |
|
| | | if (!string.IsNullOrWhiteSpace(palletCode))
|
| | | {
|
| | | // ææçå·ï¼æ¬å°åå»ºæºæ¢°æä»»å¡
|
| | | return CreateLocalRobotTask(task);
|
| | | }
|
| | |
|
| | | // æ æçå·ï¼ä» WMS è·åä»»å¡
|
| | | return GetWMSOutboundTrayTaskFromWMS(task);
|
| | | }
|
| | |
|
| | | /// <summary>
|
| | | /// ä»WMSè·å空æçåºåºä»»å¡ã
|
| | | /// </summary>
|
| | | /// <param name="task">ä»»å¡å®ä½ã</param>
|
| | | /// <returns>è°ç¨ç»æã</returns>
|
| | | private WebResponseContent GetWMSOutboundTrayTaskFromWMS(Dt_Task task)
|
| | | {
|
| | | int warehouseId = MapWarehouseIdConfigKey(task.TargetAddress);
|
| | | string sourceLineNo = ResolveRobotRuleValue(task.TargetAddress, "AddressSourceLineNoMap", task.TargetAddress);
|
| | | string configKey = nameof(ConfigKey.GetOutBoundTrayTaskAsync);
|
| | | string requestParam = new CreateTaskDto { WarehouseId = warehouseId, TargetAddress = sourceLineNo }.ToJson();
|
| | | DateTime startTime = DateTime.Now;
|
| | |
|
| | | var result = _httpClientHelper.Post<WebResponseContent>(configKey, requestParam);
|
| | |
|
| | | if (!result.IsSuccess || !result.Data.Status)
|
| | | {
|
| | | QuartzLogHelper.LogError(_logger, $"è°ç¨WMSæ¥å£å¤±è´¥,æ¥å£:ã{configKey}ã,请æ±åæ°:ã{requestParam}ã,é误信æ¯:ã{result.Data?.Message}ã", "RobotTaskService");
|
| | | return WebResponseContent.Instance.Error($"è·åWMSç³»ç»ç©ºæçåºåºä»»å¡å¤±è´¥,ä»»å¡å·:ã{task.TaskNum}ã,æçå·:ã{task.PalletCode}ã,é误信æ¯:ã{result.Data?.Message}ã");
|
| | | }
|
| | |
|
| | | QuartzLogHelper.LogInfo(_logger, $"è°ç¨WMSæ¥å£æå,æ¥å£:ã{configKey}ã,ååºæ°æ®:ã{result.Data?.Data}ã,èæ¶:{(DateTime.Now - startTime).TotalMilliseconds}ms", "RobotTaskService");
|
| | |
|
| | | WMSTaskDTO? wMSTask = JsonConvert.DeserializeObject<WMSTaskDTO>(result.Data.Data?.ToString() ?? string.Empty);
|
| | | if (wMSTask == null)
|
| | | return WebResponseContent.Instance.Error($"è·åWMSç³»ç»ç©ºæçåºåºä»»å¡å¤±è´¥,ä»»å¡å·:ã{task.TaskNum}ã,æçå·:ã{task.PalletCode}ã,é误信æ¯:ãWMSæªè¿åææä»»å¡æ°æ®ã");
|
| | |
|
| | | // æå»ºStockDTOå¹¶è°ç¨ReceiveWMSTaskå建æ¬å°å
¥åºä»»å¡
|
| | | var stockDto = new StockDTO
|
| | | {
|
| | | Roadway = task.Roadway,
|
| | | SourceLineNo = sourceLineNo,
|
| | | TargetLineNo = task.TargetAddress,
|
| | | SourcePalletNo = string.Empty,
|
| | | TargetPalletNo = string.Empty
|
| | | };
|
| | | return ReceiveWMSTask(wMSTask, stockDto);
|
| | | }
|
| | |
|
| | | /// <summary>
|
| | | /// 读åæå®çº¿ä½çæçå·ã
|
| | | /// </summary>
|
| | | /// <param name="sourceLineNo">æºçº¿ä½ç¼å·</param>
|
| | | /// <returns>æçå·ï¼å¦æå¼å¸¸è¿å null</returns>
|
| | | private string? ReadLineBarcode(string sourceLineNo)
|
| | | {
|
| | | try
|
| | | {
|
| | | IDevice? device = Storage.Devices.FirstOrDefault(x =>
|
| | | x.DeviceProDTOs.Any(d => d.DeviceChildCode == sourceLineNo));
|
| | |
|
| | | if (device == null)
|
| | | return null;
|
| | |
|
| | | CommonConveyorLine conveyorLine = (CommonConveyorLine)device;
|
| | | return conveyorLine.GetValue<ConveyorLineDBNameNew, string>(
|
| | | ConveyorLineDBNameNew.Barcode, sourceLineNo);
|
| | | }
|
| | | catch (Exception ex)
|
| | | {
|
| | | _logger.Error(ex, $"读å线ä½[{sourceLineNo}]æçå·å¼å¸¸");
|
| | | return null;
|
| | | }
|
| | | }
|
| | |
|
| | | /// <summary>
|
| | | /// è·åæºæ¢°æä»»å¡æ»æ°éã
|
| | | /// ç»çä»»å¡åºå®48ï¼æ¢çåæçä»»å¡éè¿æçå·æ¥è¯¢WMSåºåæç»æ°éã
|
| | | /// </summary>
|
| | | private int GetRobotTaskTotalNum(int taskType, string? palletCode)
|
| | | public int GetRobotTaskTotalNum(int taskType, string? palletCode)
|
| | | {
|
| | | if (taskType == (int)RobotTaskTypeEnum.GroupPallet)
|
| | | return 48;
|
| | |
| | |
|
| | | try
|
| | | {
|
| | | QuartzLogHelper.LogInfo(_logger, $"å¼å§è°ç¨WMSæ¥å£è·ååºåæç»æ°é,æçå·:ã{palletCode}ã", "RobotTaskService");
|
| | | string url = $"{BaseAPI.WMSBaseUrl}Stock/GetStockDetailCount?palletCode={Uri.EscapeDataString(palletCode)}";
|
| | | var result = _httpClientHelper.Get(url);
|
| | | QuartzLogHelper.LogInfo(_logger, $"è°ç¨WMSè·ååºåæç»æ°éæ¥å£,请æ±URL:ã{url}ã,ååºæ°æ®:ã{result.Content}ã,èæ¶:{result.Duration}ms", "RobotTaskService");
|
| | | if (!result.IsSuccess || string.IsNullOrEmpty(result.Content))
|
| | | return 1;
|
| | |
|
| | |
| | | if (response == null || !response.Status)
|
| | | return 1;
|
| | |
|
| | | var detailCount = response.Data?.GetType().GetProperty("DetailCount")?.GetValue(response.Data);
|
| | | return detailCount is int count and > 0 ? count : 1;
|
| | | var detailCount = (response.Data as JObject)?["detailCount"]?.Value<int>();
|
| | | return detailCount.HasValue && detailCount.Value > 0 ? detailCount.Value : 1;
|
| | | }
|
| | | catch
|
| | | {
|
| | |
| | | CommonConveyorLine conveyorLine = (CommonConveyorLine)device;
|
| | |
|
| | | DeviceProDTO? devicePro = conveyorLine.DeviceProDTOs.FirstOrDefault(x => x.DeviceProParamName == nameof(ConveyorLineDBNameNew.Barcode) && x.DeviceChildCode == sourceLineNo);
|
| | | //conveyorLine.Communicator.Read(devicePro.DeviceProAddress, 20);
|
| | | //ConveyorLineTaskCommandNew command = conveyorLine.ReadCustomer<ConveyorLineTaskCommandNew>(sourceLineNo); // æµè¯ç¨
|
| | | var barcode = conveyorLine.GetValue<ConveyorLineDBNameNew, string>(ConveyorLineDBNameNew.Barcode, sourceLineNo);
|
| | | var bytes = conveyorLine.Communicator.Read(devicePro.DeviceProAddress, 20);
|
| | | var barcode = Encoding.Default.GetString(bytes).Trim();
|
| | | stock.SourcePalletNo = string.IsNullOrEmpty(barcode) ? string.Empty : barcode;
|
| | | }
|
| | | }
|
| | |
| | | using MapsterMapper; |
| | | using Masuit.Tools; |
| | | using Microsoft.Extensions.Configuration; |
| | | using Newtonsoft.Json; |
| | | using Quartz; |
| | | using Serilog; |
| | | using SqlSugar; |
| | | using WIDESEA_Core; |
| | | using WIDESEAWCS_Common.HttpEnum; |
| | | using WIDESEAWCS_Common.TaskEnum; |
| | | using WIDESEAWCS_Core; |
| | | using WIDESEAWCS_Core.Helper; |
| | | using WIDESEAWCS_DTO.TaskInfo; |
| | | using WIDESEAWCS_ITaskInfoService; |
| | | using WIDESEAWCS_Model.Models; |
| | | using WIDESEAWCS_QuartzJob; |
| | |
| | | { |
| | | // 妿 WCS_ACK 为 1ï¼å
æ¸
é¤ï¼è¡¨ç¤ºå¤çè¿ä¸ä¸æ¬¡è¯·æ±ï¼ |
| | | if (command.WCS_ACK == 1) |
| | | conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)0, childDeviceCode); |
| | | { |
| | | conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (byte)0, childDeviceCode); |
| | | //Thread.Sleep(300); |
| | | //conveyorLine.SetValue(ConveyorLineDBNameNew.Target, (short)0, childDeviceCode); |
| | | } |
| | | |
| | | // å¤çæå¨å
¥åºä»»å¡ï¼èµ·ç¹ä¸ºçº¿ä½ç¹ä½çä»»å¡ï¼ |
| | | try |
| | |
| | | } |
| | | continue; |
| | | } |
| | | else |
| | | { |
| | | if (childDeviceCode == "2103" || childDeviceCode == "2101") |
| | | { |
| | | try |
| | | { |
| | | var task = _taskService.QueryManualInboundTask(childDeviceCode); |
| | | if (task != null) |
| | | { |
| | | QuartzLogHelper.LogInfo(_logger, $"è·åå°è¾é线å¼å§ä»»å¡ï¼ä»»å¡å·ï¼{task.TaskNum}ï¼ç¶æ: {task.TaskStatus},å½åå°åï¼{conveyorLine.DeviceCode}", conveyorLine.DeviceCode); |
| | | var handler = new ManualInboundTaskHandler(_taskService, _logger); |
| | | handler.WriteTaskToPlc(conveyorLine, childDeviceCode, task); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | QuartzLogHelper.LogError(_logger, ex, "å¤çæå¨å
¥åºä»»å¡å¼å¸¸", $"å¤çæå¨å
¥åºä»»å¡å¼å¸¸: {ex.Message}", "CommonConveyorLineNewJob"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // ========== å¤çæ æçæ¡ç çæ
åµ ========== |
| | | // æ æçæ¡ç æ¶ï¼è¯·æ±åºåºä»»å¡ |
| | | if (command.Barcode.IsNullOrEmpty() || command.Barcode.Replace("\0", "") == "") |
| | | // 妿 PLC_STB 为 1ï¼ä½æ²¡æä»»å¡å·ï¼å¯è½æ¯æ°ä»»å¡çå¼å§ï¼å
请æ±åºåºä»»å¡ï¼éç¨äºæ æ¡ç çæ
åµï¼ |
| | | if (command.TaskNo == 1000) |
| | | { |
| | | _conveyorLineDispatch.RequestOutbound(conveyorLine, command, childDeviceCode); |
| | | continue; |
| | | } |
| | | |
| | | // ========== å¤çå·²æä»»å¡å·çæ
åµ ========== |
| | | if (command.TaskNo > 0 && !command.Barcode.IsNullOrEmpty()) |
| | | if (command.TaskNo > 0) |
| | | { |
| | | // æ¥è¯¢æ£å¨æ§è¡çä»»å¡ |
| | | Dt_Task task = _taskService.QueryExecutingConveyorLineTask(command.TaskNo, childDeviceCode); |
| | |
| | | conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)1, childDeviceCode); |
| | | } |
| | | } |
| | | //else if (!command.Barcode.IsNullOrEmpty() && (childDeviceCode == "11001" || childDeviceCode == "11010")) |
| | | //{ |
| | | // var isWcsTask = _taskService.Db.Queryable<Dt_Task>().Any(x => x.PalletCode == command.Barcode && (x.TaskStatus == (int)TaskOutStatusEnum.OutNew || x.TaskStatus == (int)TaskInStatusEnum.InNew)); |
| | | // var isRobotTask = _robotTaskService.Db.Queryable<Dt_RobotTask>().Any(x => x.RobotTargetAddressPalletCode == command.Barcode); |
| | | // if (isWcsTask || isRobotTask) |
| | | // { |
| | | // continue; |
| | | // } |
| | | |
| | | // // è°ç¨ WMS å建空æçå
¥åºä»»å¡ |
| | | // string configKey = nameof(ConfigKey.CreateTaskInboundAsync); |
| | | // string requestParam = new CreateTaskDto() |
| | | // { |
| | | // PalletCode = command.Barcode, |
| | | // SourceAddress = childDeviceCode, |
| | | // TargetAddress = "GWSC1", // ç®æ å°å |
| | | // Roadway = "GWSC1", // å··é |
| | | // WarehouseId = 1, // ä»åº ID |
| | | // PalletType = 1, // æçç±»åï¼é»è®¤ä¸º1ï¼ |
| | | // TaskType = TaskTypeEnum.InEmpty.GetHashCode() // ä»»å¡ç±»åï¼å
¥åº/空æçå
¥åºï¼ |
| | | // }.Serialize(); |
| | | // DateTime startTime = DateTime.Now; |
| | | |
| | | // var responseResult = _httpClientHelper.Post<WebResponseContent>(configKey, requestParam); |
| | | |
| | | // if (responseResult.IsSuccess && responseResult.Data.Status) |
| | | // { |
| | | // QuartzLogHelper.LogInfo(_logger, $"è°ç¨WMSæ¥å£æå,æ¥å£:ã{configKey}ã,请æ±åæ°:ã{requestParam}ã,ååºæ°æ®:ã{responseResult.Data?.Data}ã,èæ¶:{(DateTime.Now - startTime).TotalMilliseconds}ms", conveyorLine.DeviceCode); |
| | | // var wmsTask = JsonConvert.DeserializeObject<WMSTaskDTO>(responseResult?.Data?.Data?.ToString()); |
| | | // List<WMSTaskDTO> taskDTOs = new List<WMSTaskDTO> { wmsTask }; |
| | | // if (wmsTask == null) continue; |
| | | |
| | | // if (_taskService.ReceiveWMSTask(taskDTOs).Status) |
| | | // { |
| | | // conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)1, childDeviceCode); |
| | | // } |
| | | // } |
| | | // else |
| | | // { |
| | | // QuartzLogHelper.LogError(_logger, $"è°ç¨WMSæ¥å£å¤±è´¥,æ¥å£:ã{configKey}ã,请æ±åæ°:ã{requestParam}ã,é误信æ¯:ã{responseResult.Data?.Message}ã", conveyorLine.DeviceCode); |
| | | // } |
| | | //} |
| | | } |
| | | } |
| | | catch (Exception innerEx) |
| | |
| | | |
| | | // ç¡®å®ç®æ å°åï¼ç©ºæçä»»å¡ä½¿ç¨ "2201"ï¼å
¶ä»ä»»å¡ä½¿ç¨ NextAddress |
| | | var isEmptyTask = task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty; |
| | | var targetAddress = task.CurrentAddress == "2217" ? (isEmptyTask ? "2201" : task.NextAddress) : task.NextAddress; |
| | | var targetAddress = task.CurrentAddress == "2217" ? (isEmptyTask ? task.TargetAddress : task.NextAddress) : task.NextAddress; |
| | | |
| | | // å¤çç¹æ®å°å 2217ï¼éè¦è°ç¨ç®æ å°åéæ©å¨ |
| | | if (task.CurrentAddress == "2217" && !_targetAddressSelector.HandleOutboundNextAddress(conveyorLine, targetAddress, childDeviceCode)) |
| | | { |
| | | return Task.CompletedTask; ; |
| | | } |
| | | //if (task.CurrentAddress == "2217" && !_targetAddressSelector.HandleOutboundNextAddress(conveyorLine, targetAddress, childDeviceCode)) |
| | | //{ |
| | | // return Task.CompletedTask; ; |
| | | //} |
| | | |
| | | // 设置任å¡å·ãæçæ¡ç ãç®æ å°åãWCS_ACK |
| | | var isTaskNoSet = conveyorLine.SetValue(ConveyorLineDBNameNew.TaskNo, task.TaskNum, childDeviceCode); |
| | | |
| | | Thread.Sleep(100); // ç¡®ä¿ PLC è½æ£ç¡®è¯»åä»»å¡å·åååå
¥æ¡ç |
| | | Thread.Sleep(300); // ç¡®ä¿ PLC è½æ£ç¡®è¯»åä»»å¡å·åååå
¥æ¡ç |
| | | var isPalletSet = conveyorLine.SetValue(ConveyorLineDBNameNew.Barcode, task.PalletCode, childDeviceCode); |
| | | |
| | | Thread.Sleep(100); // ç¡®ä¿ PLC è½æ£ç¡®è¯»åä»»å¡å·åååå
¥æ¡ç |
| | | Thread.Sleep(300); // ç¡®ä¿ PLC è½æ£ç¡®è¯»åä»»å¡å·åååå
¥æ¡ç |
| | | bool isTargetSet = conveyorLine.SetValue(ConveyorLineDBNameNew.Target, targetAddress, childDeviceCode); |
| | | //if (targetAddress == "2217" && !isEmptyTask) |
| | | //{ |
| | |
| | | //} |
| | | //if (!isTargetSet || !isTaskNoSet || !isPalletSet) |
| | | //{ |
| | | // QuartzLogHelper.LogError(_logger, $"RequestOutboundï¼ä¸ååºåºä»»å¡å¤±è´¥ï¼ä»»å¡å·: {task.TaskNum}ï¼å设å¤: {childDeviceCode}", conveyorLine.DeviceCode); |
| | | // QuartzLogHelper.LogError(_logger, $"RequestOutboundï¼ä¸ååºåºä»»å¡å¤±è´¥ï¼ä»»å¡å·: {task.TaskNum}ï¼å设å¤: {childDeviceCode}", conveyorLine.DeviceCode); |
| | | // return Task.CompletedTask; |
| | | //} |
| | | |
| | | bool isWmsResult = false; |
| | | // æ´æ°ä»»å¡ç¶ææä½ç½® |
| | | if (isEmptyTask && task.NextAddress == "2217") |
| | | if (isEmptyTask && (task.TargetAddress == "2103" || task.TargetAddress == "2101")) |
| | | { |
| | | task.TaskStatus = task.TaskStatus.GetNextNotCompletedStatus<TaskOutStatusEnum>(); |
| | | task.NextAddress = "2201"; |
| | | task.NextAddress = "2103"; |
| | | isWmsResult = _taskService.Repository.UpdateData(task); |
| | | } |
| | | else |
| | |
| | | isWmsResult = _taskService.UpdateTaskStatusToNext(task).Status; |
| | | } |
| | | |
| | | if(!isWmsResult) |
| | | if (!isWmsResult) |
| | | { |
| | | QuartzLogHelper.LogError(_logger, $"RequestOutboundï¼æ´æ°ä»»å¡ç¶æå¤±è´¥ï¼ä»»å¡å·: {task.TaskNum}ï¼å设å¤: {childDeviceCode}", conveyorLine.DeviceCode); |
| | | return Task.CompletedTask; |
| | |
| | | |
| | | var cvState = conveyorLine.GetValue<ConveyorLineDBNameNew, byte>(ConveyorLineDBNameNew.CV_State, nextAddress); |
| | | bool isAvailable = cvState == 2; |
| | | WriteDebug(conveyorLine, "åºåºä¸ä¸å°åç¶æ", childDeviceCode, $"CV_State={cvState}ï¼å¯ç¨={isAvailable}"); |
| | | if (isAvailable) |
| | | { |
| | | WriteDebug(conveyorLine, "åºåºä¸ä¸å°åå¯ç¨ï¼åå
¥ç®æ å°å", childDeviceCode, nextAddress); |
| | | Thread.Sleep(300); // çæçå¾
ï¼ç¡®ä¿è®¾å¤ç¶æç¨³å®åååå
¥ç®æ å°å |
| | | return conveyorLine.SetValue(ConveyorLineDBNameNew.Target, Convert.ToInt16(nextAddress), childDeviceCode); |
| | | } |
| | | return false; |
| | |
| | | } |
| | | |
| | | // 轮询è·å该设å¤çå¾
å¤çä»»å¡ |
| | | var task = _taskProcessor.GetTask(robotCrane); |
| | | // ä¼å
éè¿ç¶æä¸ç¼åçä»»å¡ç¼å·æ¥æ¾æ§è¡ä¸çä»»å¡ |
| | | Dt_RobotTask? task = null; |
| | | if (state.CurrentTaskNum.HasValue) |
| | | { |
| | | task = _taskProcessor.GetTaskByNum(state.CurrentTaskNum.Value); |
| | | } |
| | | |
| | | // ç¼åçä»»å¡å·æªæ¾å°å¯¹åºä»»å¡æ¶ï¼æè®¾å¤ç¼ç è·åæ°ä»»å¡ |
| | | task ??= _taskProcessor.GetTask(robotCrane); |
| | | |
| | | // å¦ææ²¡æè·åå°å¾
å¤çä»»å¡ï¼ä¸RobotArmObject为1ï¼æç©æï¼ï¼åè·åè¯¥è®¾å¤æ§è¡ä¸çä»»å¡ |
| | | //if (task == null && state.RobotArmObject == 1) |
| | |
| | | }
|
| | |
|
| | | /// <summary>
|
| | | /// æä»»å¡ç¼å·è·åæºå¨äººä»»å¡
|
| | | /// </summary>
|
| | | /// <remarks>
|
| | | /// ç¨äº RobotJob å¿«éæ¥æ¾æ§è¡ä¸çä»»å¡ï¼é¿å
å
¨è¡¨æ«æã
|
| | | /// ä¼å
éè¿ç¶æä¸ç¼åç CurrentTaskNum å®ä½ä»»å¡ã
|
| | | /// </remarks>
|
| | | /// <param name="taskNum">æºå¨äººä»»å¡ç¼å·</param>
|
| | | /// <returns>å¹é
çä»»å¡å¯¹è±¡ï¼å¦ææ²¡æåè¿å null</returns>
|
| | | public Dt_RobotTask? GetTaskByNum(int taskNum)
|
| | | {
|
| | | return _robotTaskService.Repository.QueryFirst(x => x.RobotTaskNum == taskNum);
|
| | | }
|
| | |
|
| | | /// <summary>
|
| | | /// æè®¾å¤ç¼ç è·åå½åæºå¨äººçæ§è¡ä¸ä»»å¡
|
| | | /// </summary>
|
| | | /// <remarks>
|
| | |
| | |
|
| | | // å°ä»»å¡å
³èå°ç¶æå¯¹è±¡
|
| | | state.CurrentTask = task;
|
| | | state.CurrentTaskNum = task.RobotTaskNum;
|
| | |
|
| | | if (isScanNG)
|
| | | {
|
| | |
| | |
|
| | | // å°ä»»å¡å
³èå°ç¶æå¯¹è±¡
|
| | | state.CurrentTask = task;
|
| | | state.CurrentTaskNum = task.RobotTaskNum;
|
| | |
|
| | | if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
|
| | | {
|
| | |
| | |
|
| | | task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
|
| | | state.CurrentTask = task;
|
| | | state.CurrentTaskNum = task.RobotTaskNum;
|
| | |
|
| | | if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
|
| | | {
|
| | |
| | | {
|
| | | task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
|
| | | state.CurrentTask = task;
|
| | | state.CurrentTaskNum = task.RobotTaskNum;
|
| | |
|
| | | if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
|
| | | {
|
| | |
| | | {
|
| | | task.RobotTaskState = TaskRobotStatusEnum.RobotExecuting.GetHashCode();
|
| | | state.CurrentTask = task;
|
| | | state.CurrentTaskNum = task.RobotTaskNum;
|
| | |
|
| | | if (_stateManager.TryUpdateStateSafely(state.IPAddress, state))
|
| | | {
|
| | |
| | | // è§£æ WMS è¿åçä»»å¡ä¿¡æ¯
|
| | | WMSTaskDTO taskDTO = JsonConvert.DeserializeObject<WMSTaskDTO>(result.Data.Data.ToJson() ?? string.Empty) ?? new WMSTaskDTO();
|
| | |
|
| | | var task = await _taskService.Repository.QueryFirstAsync(x => x.PalletCode == taskDTO.PalletCode);
|
| | | if(task != null)
|
| | | {
|
| | | await _taskService.Repository.DeleteDataAsync(task);
|
| | | }
|
| | |
|
| | | // è°ç¨ä»»å¡æå¡æ¥æ¶ WMS ä»»å¡
|
| | | var content = _taskService.ReceiveWMSTask(new List<WMSTaskDTO> { taskDTO });
|
| | | if (!content.Status)
|
| | |
| | | // éé/ä½ç½®ç¼å·
|
| | | Channel = x,
|
| | |
|
| | | // çµæ± æ¡ç ï¼å¦æç¶æä¸ææ¡ç å表ï¼å对åºä½ç½®çæ¡ç ï¼å¦å为空
|
| | | // çµæ± æ¡ç ï¼ä½¿ç¨å½åæ¹æ¬¡æ¡ç å表ï¼å对åºä½ç½®çæ¡ç ï¼å¦å为空
|
| | | //CellBarcode = state.CellBarcode?.Count > 0 ? state.CellBarcode[x - 1] : ""
|
| | | CellBarcode = !state.CellBarcode.IsNullOrEmpty() ? state.CellBarcode[idx].ToString() ?? string.Empty : string.Empty
|
| | | CellBarcode = !state.CurrentBatchBarcodes.IsNullOrEmpty() ? state.CurrentBatchBarcodes[idx].ToString() ?? string.Empty : string.Empty
|
| | | })
|
| | | .ToList()
|
| | | };
|
| | |
| | | // è°ç¨æ¹éæç确认æ¥å£ |
| | | var sourcePallet = state.CurrentTask.RobotSourceAddressPalletCode; |
| | | var confirmResult = _taskProcessor.PostSplitPalletConfirmAsync(sourcePallet, state.RobotCrane?.DeviceName); |
| | | if (!confirmResult.IsSuccess) |
| | | if (!confirmResult.IsSuccess && !confirmResult.Data.Status) |
| | | { |
| | | QuartzLogHelper.LogError(_logger, $"æ¹éæç确认失败: {confirmResult.ErrorMessage}", state.RobotCrane?.DeviceName ?? "Unknown"); |
| | | return false; |
| | |
| | | QuartzLogHelper.LogInfo(_logger, $"åéæ¶æ¯ï¼ãGroup,diskFinishedã", state.RobotCrane.DeviceName); |
| | | |
| | | state.CurrentTask = null; |
| | | state.CurrentTaskNum = null; |
| | | state.RobotTaskTotalNum = 0; |
| | | state.CellBarcode = new List<string>(); |
| | | state.CurrentBatchBarcodes = new List<string>(); |
| | | state.ChangePalletPhase = 0; |
| | | state.CurrentBatchIndex = 1; |
| | | state.IsInFakeBatteryMode = false; |
| | |
| | | // è°ç¨æ¹éç»ç确认æ¥å£ |
| | | var targetPallet = state.CurrentTask.RobotTargetAddressPalletCode; |
| | | var confirmResult = _taskProcessor.PostGroupPalletConfirmAsync(targetPallet, state.RobotCrane?.DeviceName); |
| | | if (!confirmResult.IsSuccess) |
| | | if (!confirmResult.IsSuccess && !confirmResult.Data.Status) |
| | | { |
| | | QuartzLogHelper.LogError(_logger, $"æ¹éç»ç确认失败: {confirmResult.ErrorMessage}", state.RobotCrane?.DeviceName ?? "Unknown"); |
| | | return false; |
| | |
| | | } |
| | | |
| | | state.CurrentTask = null; |
| | | state.CurrentTaskNum = null; |
| | | state.RobotTaskTotalNum = 0; |
| | | state.CellBarcode = new List<string>(); |
| | | state.CurrentBatchBarcodes = new List<string>(); |
| | | |
| | | await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Group,diskFinished"); |
| | | QuartzLogHelper.LogInfo(_logger, $"åéæ¶æ¯ï¼ãGroup,diskFinishedã", state.RobotCrane.DeviceName); |
| | |
| | | } |
| | | |
| | | state.CurrentTask = null; |
| | | state.CurrentTaskNum = null; |
| | | state.RobotTaskTotalNum = 0; |
| | | state.CellBarcode = new List<string>(); |
| | | state.CurrentBatchBarcodes = new List<string>(); |
| | | |
| | | await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Group,diskFinished"); |
| | | QuartzLogHelper.LogInfo(_logger, $"åéæ¶æ¯ï¼ãGroup,diskFinishedã", state.RobotCrane.DeviceName); |
| | |
| | | |
| | | // æ¸
çç¶æï¼ä¸ºä¸ä¸ä¸ªä»»å¡ååå¤ |
| | | state.CurrentTask = null; // æ¸
é¤å½åä»»å¡ |
| | | state.CurrentTaskNum = null; // æ¸
é¤å½åä»»å¡ç¼å· |
| | | state.RobotTaskTotalNum = 0; // é置任å¡è®¡æ° |
| | | state.CellBarcode = new List<string>(); // æ¸
空æ¡ç å表 |
| | | state.CurrentBatchBarcodes = new List<string>(); // æ¸
空å½åæ¹æ¬¡æ¡ç |
| | | |
| | | await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Group,diskFinished"); |
| | | QuartzLogHelper.LogInfo(_logger, $"åéæ¶æ¯ï¼ãGroup,diskFinishedã", state.RobotCrane.DeviceName); |
| | |
| | | if (stateToUpdate != null) |
| | | { |
| | | stateToUpdate.CurrentTask = task; |
| | | stateToUpdate.CurrentTaskNum = task.RobotTaskNum; |
| | | |
| | | if (_stateManager.TryUpdateStateSafely(ipAddress, stateToUpdate)) |
| | | { |
| | |
| | | |
| | | QuartzLogHelper.LogInfo(_logger, $"HandlePutFinishedStateAsyncï¼è¯»åççµè¯æ¡ç å¯ä¸ï¼ç»§ç»æ§è¡ï¼ä»»å¡å·: {task.RobotTaskNum}", stateForUpdate?.RobotCrane?.DeviceName ?? ipAddress); |
| | | |
| | | // å°æ¡ç æ·»å å°ç¶æä¸ï¼ä¾åç»æ¾è´§æ¶ä½¿ç¨ |
| | | stateForUpdate.CellBarcode = new List<string>() |
| | | // å°æ¡ç ç´¯ç§¯å° CellBarcodeï¼å»éï¼ï¼å¹¶è®¾ç½®å½åæ¹æ¬¡æ¡ç |
| | | if (!stateForUpdate.CellBarcode.Contains(trayBarcode1)) |
| | | stateForUpdate.CellBarcode.Add(trayBarcode1); |
| | | if (!stateForUpdate.CellBarcode.Contains(trayBarcode2)) |
| | | stateForUpdate.CellBarcode.Add(trayBarcode2); |
| | | |
| | | // 设置å½åæ¹æ¬¡æ¡ç ï¼ç¨äº WMS æäº¤ |
| | | stateForUpdate.CurrentBatchBarcodes = new List<string>() |
| | | { |
| | | trayBarcode1,trayBarcode2 |
| | | trayBarcode1, trayBarcode2 |
| | | }; |
| | | } |
| | | |
| | |
| | | // ç®æ æ°é为48ï¼ç´æ¥èµ°åæé»è¾ï¼ä¸è¿å
¥æ¹æ¬¡æ¨¡å¼ |
| | | if (targetNormalCount + currentCompletedCount == targetTotal) |
| | | { |
| | | QuartzLogHelper.LogInfo(_logger, $"HandlePutFinishedStateAsyncï¼ç®æ æ°é已达48ï¼ç´æ¥ä¸ååè´§æä»¤ï¼ä»»å¡å·: {task.RobotTaskNum}", stateForUpdate?.RobotCrane?.DeviceName ?? ipAddress); |
| | | await _taskProcessor.SendSocketRobotPickAsync(task, stateForUpdate); |
| | | return; |
| | | } |
| | | |
| | | QuartzLogHelper.LogDebug(_logger,$"HandlePutFinishedStateAsyncï¼æ¢çä»»å¡ç®æ æ°é: {targetNormalCount}ï¼å½å已宿æ°é: {currentCompletedCount}ï¼æµå: {(isFlowA ? "A" : "B")}ï¼ä»»å¡å·: {task.RobotTaskNum}", stateForUpdate?.RobotCrane?.DeviceName ?? ipAddress); |
| | | |
| | | // åå§åæ¹æ¬¡æ¨¡å¼ |
| | | if (stateForUpdate.ChangePalletPhase == 0) |
| | | { |
| | |
| | | using System.Text.Json; |
| | | using System.IO; |
| | | using WIDESEAWCS_Model.Models; |
| | | using Serilog.Core; |
| | | |
| | | namespace WIDESEAWCS_Tasks.SocketServer |
| | | { |
| | |
| | | //{ |
| | | // if (_clientLastMessage.TryGetValue(clientId, out var prev) && message == prev) |
| | | // { |
| | | // QuartzLogHelper.LogInfo(Logger.None, $"æ¥èªå®¢æ·ç«¯ {clientId} çé夿¶æ¯ï¼å
容: {message}", clientId); |
| | | // continue; |
| | | // } |
| | | // _clientLastMessage[clientId] = message; |
| | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// å è½½é
ç½®æä»¶ï¼ä¼å
级ï¼é
ç½®æä»¶ > é»è®¤é
ç½®ï¼ |
| | | /// </summary> |
| | | /// <remarks> |
| | | /// ä»åºç¨ç¨åºç®å½ä¸ç StackerCraneJob/stackercrane-command-config.json 读åé
ç½®ã |
| | | /// 妿æä»¶ä¸åå¨æè§£æå¤±è´¥ï¼ä½¿ç¨é»è®¤é
ç½®ã |
| | | /// </remarks> |
| | | /// <returns>å åæºå½ä»¤é
ç½®</returns> |
| | | private static StackerCraneCommandConfig LoadConfig() |
| | | { |
| | | try |
| | | { |
| | | // æé é
ç½®æä»¶è·¯å¾ |
| | | string configPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "StackerCraneJob", "stackercrane-command-config.json"); |
| | | if (File.Exists(configPath)) |
| | | { |
| | | // 读åå¹¶è§£æ JSON é
ç½® |
| | | string json = File.ReadAllText(configPath); |
| | | return System.Text.Json.JsonSerializer.Deserialize<StackerCraneCommandConfig>(json) ?? new StackerCraneCommandConfig(); |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | // é
ç½®å 载失败ï¼ä½¿ç¨é»è®¤é
ç½® |
| | | Console.WriteLine($"é
ç½®å 载失败: {ex.Message}ï¼ä½¿ç¨é»è®¤é
ç½®"); |
| | | } |
| | | |
| | | return new StackerCraneCommandConfig(); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// Quartz Job çæ§è¡å
¥å£ |
| | | /// </summary> |
| | | /// <remarks> |
| | |
| | | using Newtonsoft.Json; |
| | | using Serilog; |
| | | using System.Diagnostics.CodeAnalysis; |
| | | using System.Threading.Tasks; |
| | | using WIDESEA_Core; |
| | | using WIDESEAWCS_Common.Constants; |
| | | using WIDESEAWCS_Common.HttpEnum; |
| | |
| | | using WIDESEAWCS_ITaskInfoService; |
| | | using WIDESEAWCS_Model.Models; |
| | | using WIDESEAWCS_QuartzJob; |
| | | using WIDESEAWCS_QuartzJob.ConveyorLine.Enum; |
| | | using WIDESEAWCS_QuartzJob.Models; |
| | | using WIDESEAWCS_QuartzJob.Service; |
| | | |
| | |
| | | { |
| | | // å
è¿è¡æ¬å°ç«å°æ£æ¥ï¼PLC 读åï¼å¿«éï¼ï¼é¿å
ä¸å¿
è¦ç WMS HTTP è°ç¨ |
| | | |
| | | if (outboundTask.TaskType != (int)TaskOutboundTypeEnum.OutEmpty && outboundTask.Roadway != "GWSC1" && outboundTask.TargetAddress != "CWSC1") |
| | | if (outboundTask.TaskType != (int)TaskOutboundTypeEnum.OutEmpty && outboundTask.TargetAddress != "CWSC1") |
| | | { |
| | | // 夿 TargetAddress è¾é线ç«å°æ¯å¦ç©ºé² |
| | | if (!IsTargetAddressConveyorStationAvailable(outboundTask)) |
| | |
| | | return null; |
| | | } |
| | | |
| | | if (outboundTask.TargetAddress != "CWSC1") |
| | | //if (outboundTask.TargetAddress != "CWSC1") |
| | | //{ |
| | | // æ£æ¥æ¯å¦ææ£å¨æ§è¡çè¾é线任å¡å»å¾åä¸ TargetAddress |
| | | if (_taskService.HasExecutingTaskToTarget(outboundTask.Roadway, outboundTask.TargetAddress)) |
| | | { |
| | | // æ£æ¥æ¯å¦ææ£å¨æ§è¡çè¾é线任å¡å»å¾åä¸ TargetAddress |
| | | if (_taskService.HasExecutingTaskToTarget(outboundTask.Roadway, outboundTask.TargetAddress)) |
| | | { |
| | | QuartzLogHelper.LogInfo(_logger, "TrySelectOutboundTaskï¼TargetAddress: {TargetAddress} å·²ææ£å¨æ§è¡çè¾é线任å¡ï¼ä»»å¡å·: {TaskNum}", |
| | | $"TrySelectOutboundTaskï¼TargetAddress: {outboundTask.TargetAddress} å·²ææ£å¨æ§è¡çè¾é线任å¡", outboundTask.Roadway, outboundTask.TargetAddress, outboundTask.TaskNum); |
| | | return null; |
| | | } |
| | | QuartzLogHelper.LogInfo(_logger, "TrySelectOutboundTaskï¼TargetAddress: {TargetAddress} å·²ææ£å¨æ§è¡çè¾é线任å¡ï¼ä»»å¡å·: {TaskNum}", |
| | | $"TrySelectOutboundTaskï¼TargetAddress: {outboundTask.TargetAddress} å·²ææ£å¨æ§è¡çè¾é线任å¡", outboundTask.Roadway, outboundTask.TargetAddress, outboundTask.TaskNum); |
| | | return null; |
| | | } |
| | | //} |
| | | |
| | | if(outboundTask.Roadway != "GWSC1") |
| | | if (outboundTask.Roadway != "GWSC1") |
| | | { |
| | | return outboundTask; |
| | | } |
| | |
| | | name: 'PDA', |
| | | component: () => import('@/views/system/PDA.vue') |
| | | } |
| | | , { |
| | | path: '/outboundTimeConfig', |
| | | name: 'outboundTimeConfig', |
| | | component: () => import('@/views/system/outboundTimeConfig.vue') |
| | | } |
| | | ] |
| | | |
| | | export default viewgird |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="config-container"> |
| | | <el-card class="config-card"> |
| | | <template #header> |
| | | <span>åºåºæ¶æé
ç½®</span> |
| | | </template> |
| | | <el-form :model="form" label-width="180px" v-loading="loading"> |
| | | <el-form-item label="GW馿¾å
¥åºæ¶æï¼å°æ¶ï¼"> |
| | | <el-input-number |
| | | v-model="form.gw1FirstHours" |
| | | :min="0.01" |
| | | :max="999" |
| | | :precision="2" |
| | | :step="1" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="GWäºæ¾å
¥åºæ¶æï¼å°æ¶ï¼"> |
| | | <el-input-number |
| | | v-model="form.gw1SecondHours" |
| | | :min="0.01" |
| | | :max="999" |
| | | :precision="2" |
| | | :step="0.01" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="CWåºåºæ¶æï¼å°æ¶ï¼"> |
| | | <el-input-number |
| | | v-model="form.cw1Hours" |
| | | :min="0.01" |
| | | :max="999" |
| | | :precision="2" |
| | | :step="1" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleSave" :loading="saving"> |
| | | ä¿å |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </el-card> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import { ref, onMounted } from "vue"; |
| | | import { ElMessage } from "element-plus"; |
| | | import http from "@/api/http"; |
| | | |
| | | export default { |
| | | name: "outboundTimeConfig", |
| | | setup() { |
| | | const loading = ref(false); |
| | | const saving = ref(false); |
| | | const form = ref({ |
| | | gw1FirstHours: 24, |
| | | gw1SecondHours: 0.05, |
| | | cw1Hours: 3, |
| | | }); |
| | | |
| | | /// å è½½å½åé
ç½® |
| | | const loadConfig = async () => { |
| | | loading.value = true; |
| | | try { |
| | | const res = await http.post("/api/OutboundTimeConfig/get", {}, false); |
| | | if (res.status) { |
| | | form.value = { |
| | | gw1FirstHours: res.data.gw1FirstHours, |
| | | gw1SecondHours: res.data.gw1SecondHours, |
| | | cw1Hours: res.data.cw1Hours, |
| | | }; |
| | | } |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | |
| | | /// ä¿åé
ç½® |
| | | const handleSave = async () => { |
| | | saving.value = true; |
| | | try { |
| | | const res = await http.post("/api/OutboundTimeConfig/update", form.value, false); |
| | | if (res.status) { |
| | | ElMessage.success("ä¿åæå"); |
| | | } else { |
| | | ElMessage.error(res.message || "ä¿å失败"); |
| | | } |
| | | } finally { |
| | | saving.value = false; |
| | | } |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | loadConfig(); |
| | | }); |
| | | |
| | | return { form, loading, saving, handleSave }; |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .config-container { |
| | | padding: 20px; |
| | | } |
| | | .config-card { |
| | | max-width: 600px; |
| | | } |
| | | </style> |
| | |
| | | && x.LocationType == locationType) |
| | | .CountAsync(); |
| | | |
| | | // 空é²è´§ä½ä¸è¶³æä½ä¿çæ°éæ¶è¿ånullï¼é¿å
å°å··éåé
èå°½ |
| | | const int minFreeLocationThreshold = 5; |
| | | if (freeCount < minFreeLocationThreshold) return null; |
| | | if(roadwayNo != "CWSC1") |
| | | { |
| | | // 空é²è´§ä½ä¸è¶³æä½ä¿çæ°éæ¶è¿ånullï¼é¿å
å°å··éåé
èå°½ |
| | | const int minFreeLocationThreshold = 1; |
| | | if (freeCount < minFreeLocationThreshold) return null; |
| | | } |
| | | |
| | | // æ°æ®åºç«¯æåºåç¬¬ä¸æ¡ï¼åªä¼ è¾åè¡æ°æ®ï¼ |
| | | return await BaseDal.Db.Queryable<Dt_LocationInfo>() |
| | |
| | | /// <summary> |
| | | /// GW_1馿¾å
¥åºæ¶æï¼24å°æ¶ï¼ |
| | | /// </summary> |
| | | public const int OUTBOUND_HOURS_GW1_FIRST = 24; |
| | | public const double OUTBOUND_HOURS_GW1_FIRST = 24; |
| | | |
| | | /// <summary> |
| | | /// GW_1äºæ¾å
¥åºæ¶æï¼24å°æ¶ï¼ |
| | | /// GW_1äºæ¾å
¥åºæ¶æï¼5åéï¼ |
| | | /// </summary> |
| | | public const int OUTBOUND_HOURS_GW1_SECOND = 24; |
| | | public const double OUTBOUND_HOURS_GW1_SECOND = 0.05; |
| | | |
| | | /// <summary> |
| | | /// CW_1åºåºæ¶æï¼12å°æ¶ï¼ |
| | | /// CW_1åºåºæ¶æï¼3å°æ¶ï¼ |
| | | /// </summary> |
| | | public const int OUTBOUND_HOURS_CW1 = 12; |
| | | public const double OUTBOUND_HOURS_CW1 = 3; |
| | | } |
| | | } |
| | |
| | | /// <summary> |
| | | /// 髿¸©1å·åºåºå°åå表ï¼è½®è¯¢ï¼ |
| | | /// </summary> |
| | | public static readonly string[] GW1_ADDRESSES = { "11001" }; |
| | | public static readonly string[] GW1_ADDRESSES = { "11010" }; |
| | | |
| | | /// <summary> |
| | | /// 髿¸©2å·åºåºå°å |
| | |
| | | /// <summary> |
| | | /// å容åºåºåºå°å |
| | | /// </summary> |
| | | public const string GRADING_OUTBOUND_ADDRESS = "2103"; |
| | | public const string GRADING_OUTBOUND_ADDRESS = "2101"; |
| | | |
| | | /// <summary> |
| | | /// å容åºåºåºå°å |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | namespace WIDESEA_Core.Core |
| | | { |
| | | /// <summary> |
| | | /// åºåºæ¶æé
ç½®é项ï¼ç»å® appsettings.json ä¸ç OutboundTimeConfig è |
| | | /// </summary> |
| | | public class OutboundTimeConfigOptions |
| | | { |
| | | /// <summary> |
| | | /// é
ç½®èåç§° |
| | | /// </summary> |
| | | public const string SectionName = "OutboundTimeConfig"; |
| | | |
| | | /// <summary> |
| | | /// GW馿¾å
¥åºæ¶æï¼å°æ¶ï¼ï¼é»è®¤24å°æ¶ |
| | | /// </summary> |
| | | public double Gw1FirstHours { get; set; } = 24; |
| | | |
| | | /// <summary> |
| | | /// GWäºæ¾å
¥åºæ¶æï¼å°æ¶ï¼ï¼é»è®¤0.05å°æ¶ï¼çº¦3åéï¼ |
| | | /// </summary> |
| | | public double Gw1SecondHours { get; set; } = 0.05; |
| | | |
| | | /// <summary> |
| | | /// CWåºåºæ¶æï¼å°æ¶ï¼ï¼é»è®¤3å°æ¶ |
| | | /// </summary> |
| | | public double Cw1Hours { get; set; } = 3; |
| | | } |
| | | } |
| | |
| | | using WIDESEA_Common.StockEnum; |
| | | using WIDESEA_Common.TaskEnum; |
| | | using WIDESEA_Common.WareHouseEnum; |
| | | using Microsoft.Extensions.Options; |
| | | using WIDESEA_Core; |
| | | using WIDESEA_Core.BaseRepository; |
| | | using WIDESEA_Core.BaseServices; |
| | |
| | | private readonly IMesLogService _mesLogService; |
| | | private readonly IMesUploadHelper _mesUploadHelper; |
| | | private readonly ISqlSugarClient _sqlSugarClient; |
| | | private readonly IOptionsMonitor<OutboundTimeConfigOptions> _outboundTimeOptions; |
| | | |
| | | public IRepository<Dt_Task> Repository => BaseDal; |
| | | |
| | |
| | | IMESDeviceConfigService mesDeviceConfigService, |
| | | IMesLogService mesLogService, |
| | | IMesUploadHelper mesUploadHelper, |
| | | ISqlSugarClient sqlSugarClient) : base(BaseDal) |
| | | ISqlSugarClient sqlSugarClient, |
| | | IOptionsMonitor<OutboundTimeConfigOptions> outboundTimeOptions) : base(BaseDal) |
| | | { |
| | | _mapper = mapper; |
| | | _stockInfoService = stockInfoService; |
| | |
| | | _mesLogService = mesLogService; |
| | | _mesUploadHelper = mesUploadHelper; |
| | | _sqlSugarClient = sqlSugarClient; |
| | | _outboundTimeOptions = outboundTimeOptions; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | Creater = StockConstants.SYSTEM_USER, |
| | | Details = null, |
| | | LocationCode = location.LocationCode, |
| | | LocationId = location.Id |
| | | LocationId = location.Id, |
| | | OutboundDate = DateTime.Now |
| | | }; |
| | | location.LocationStatus = LocationStatusEnum.InStock.GetHashCode(); |
| | | var updateLocationResult = await _locationInfoService.UpdateLocationInfoAsync(location); |
| | | var updateStockResult = await _stockInfoService.Repository.AddDataAsync(stockInfo); |
| | | return await CompleteTaskAsync(task, "å
¥åºå®æ"); |
| | |
| | | SetOutboundDateByRoadway(task, stockInfo); |
| | | |
| | | stockInfo.StockStatus = StockStatusEmun.å
¥åºå®æ.GetHashCode(); |
| | | |
| | | stockInfo.CreateDate = DateTime.Now; |
| | | |
| | | location.LocationStatus = LocationStatusEnum.InStock.GetHashCode(); |
| | | |
| | |
| | | /// <param name="stockInfo">åºåä¿¡æ¯</param> |
| | | private void SetOutboundDateByRoadway(Dt_Task task, Dt_StockInfo stockInfo) |
| | | { |
| | | var config = _outboundTimeOptions.CurrentValue; |
| | | var now = DateTime.Now; |
| | | if (task.Roadway.Contains("GW")) |
| | | { |
| | | stockInfo.OutboundDate = string.IsNullOrEmpty(stockInfo.Remark) |
| | | ? now.AddHours(OutboundTimeConstants.OUTBOUND_HOURS_GW1_FIRST) |
| | | ? now.AddHours(config.Gw1FirstHours) |
| | | : stockInfo.Remark == StockRemarkConstants.GW1 |
| | | ? now.AddHours(OutboundTimeConstants.OUTBOUND_HOURS_GW1_SECOND) |
| | | : now.AddHours(OutboundTimeConstants.OUTBOUND_HOURS_GW1_FIRST); |
| | | ? now.AddHours(config.Gw1SecondHours) |
| | | : now.AddHours(config.Gw1FirstHours); |
| | | |
| | | stockInfo.Remark = string.IsNullOrEmpty(stockInfo.Remark) |
| | | ? StockRemarkConstants.GW1 |
| | |
| | | } |
| | | else if (task.Roadway.Contains("CW")) |
| | | { |
| | | stockInfo.OutboundDate = now.AddHours(OutboundTimeConstants.OUTBOUND_HOURS_CW1); |
| | | stockInfo.OutboundDate = now.AddHours(config.Cw1Hours); |
| | | if (stockInfo.Remark == StockRemarkConstants.GW2) |
| | | stockInfo.Remark = StockRemarkConstants.CW1; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using Microsoft.AspNetCore.Authorization; |
| | | using Microsoft.AspNetCore.Mvc; |
| | | using Microsoft.Extensions.Options; |
| | | using Newtonsoft.Json; |
| | | using Newtonsoft.Json.Linq; |
| | | using WIDESEA_Core; |
| | | using WIDESEA_Core.Core; |
| | | |
| | | namespace WIDESEA_WMSServer.Controllers |
| | | { |
| | | /// <summary> |
| | | /// åºåºæ¶æé
ç½®æ§å¶å¨ï¼è¯»åç¬ç«ç outbound_time_config.json é
ç½®æä»¶ |
| | | /// </summary> |
| | | [Route("api/[controller]")] |
| | | [ApiController] |
| | | [Authorize] |
| | | public class OutboundTimeConfigController : ControllerBase |
| | | { |
| | | private readonly IOptionsMonitor<OutboundTimeConfigOptions> _optionsMonitor; |
| | | private readonly IWebHostEnvironment _env; |
| | | |
| | | /// <summary> |
| | | /// é
ç½®æä»¶å |
| | | /// </summary> |
| | | private const string ConfigFileName = "outbound_time_config.json"; |
| | | |
| | | /// <summary> |
| | | /// æé 彿° |
| | | /// </summary> |
| | | /// <param name="optionsMonitor">åºåºæ¶æé
ç½® Options çæ§å¨</param> |
| | | /// <param name="env">Web 宿主ç¯å¢ï¼ç¨äºå®ä½é
ç½®æä»¶è·¯å¾</param> |
| | | public OutboundTimeConfigController(IOptionsMonitor<OutboundTimeConfigOptions> optionsMonitor, IWebHostEnvironment env) |
| | | { |
| | | _optionsMonitor = optionsMonitor; |
| | | _env = env; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è·åå½ååºåºæ¶æé
ç½® |
| | | /// </summary> |
| | | /// <returns>å½åé
ç½®å¼</returns> |
| | | [HttpPost("get")] |
| | | public IActionResult Get() |
| | | { |
| | | var config = _optionsMonitor.CurrentValue; |
| | | return Ok(WebResponseContent.Instance.OK("è·åæå", new |
| | | { |
| | | config.Gw1FirstHours, |
| | | config.Gw1SecondHours, |
| | | config.Cw1Hours |
| | | })); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ´æ°åºåºæ¶æé
ç½®ï¼åå
¥ç¬ç«ç outbound_time_config.json æä»¶ |
| | | /// </summary> |
| | | /// <param name="config">æ°çé
ç½®å¼</param> |
| | | /// <returns>æä½ç»æ</returns> |
| | | [HttpPost("update")] |
| | | public IActionResult Update([FromBody] OutboundTimeConfigOptions config) |
| | | { |
| | | if (config.Gw1FirstHours <= 0 || config.Gw1SecondHours <= 0 || config.Cw1Hours <= 0) |
| | | { |
| | | return Ok(WebResponseContent.Instance.Error("é
ç½®å¼å¿
须大äº0")); |
| | | } |
| | | |
| | | try |
| | | { |
| | | var filePath = Path.Combine(_env.ContentRootPath, ConfigFileName); |
| | | |
| | | // æå»ºé
ç½® JSONï¼å
è£¹å¨ OutboundTimeConfig èä¸ä»¥å¹é
Options ç»å® |
| | | var configSection = new JObject |
| | | { |
| | | ["Gw1FirstHours"] = config.Gw1FirstHours, |
| | | ["Gw1SecondHours"] = config.Gw1SecondHours, |
| | | ["Cw1Hours"] = config.Cw1Hours |
| | | }; |
| | | var jsonObj = new JObject |
| | | { |
| | | [OutboundTimeConfigOptions.SectionName] = configSection |
| | | }; |
| | | |
| | | // åå
¥æä»¶ï¼æ ¼å¼åè¾åº |
| | | System.IO.File.WriteAllText(filePath, jsonObj.ToString(Formatting.Indented)); |
| | | |
| | | return Ok(WebResponseContent.Instance.OK("é
ç½®æ´æ°æå")); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | return Ok(WebResponseContent.Instance.Error($"é
ç½®æ´æ°å¤±è´¥: {ex.Message}")); |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | hostingContext.Configuration.ConfigureApplication(); |
| | | config.Sources.Clear(); |
| | | config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true); |
| | | config.AddJsonFile("outbound_time_config.json", optional: true, reloadOnChange: true); |
| | | }); |
| | | |
| | | builder.Host.UseSerilog((context, services, loggerConfiguration) => |
| | |
| | | builder.Services.AddSingleton<RoundRobinService>(); |
| | | builder.Services.Configure<AutoOutboundTaskOptions>( |
| | | builder.Configuration.GetSection("AutoOutboundTask")); |
| | | builder.Services.Configure<OutboundTimeConfigOptions>( |
| | | builder.Configuration.GetSection(OutboundTimeConfigOptions.SectionName)); |
| | | builder.Services.AddMemoryCacheSetup(); // ç¼åæå¡ |
| | | builder.Services.AddWebSocketSetup(); |
| | | builder.Services.AddSqlsugarSetup(); // SqlSugar æ°æ®åºé
ç½® |
| | |
| | | </ItemGroup> |
| | | |
| | | <ItemGroup> |
| | | <Content Update="outbound_time_config.json"> |
| | | <CopyToOutputDirectory>Always</CopyToOutputDirectory> |
| | | </Content> |
| | | </ItemGroup> |
| | | |
| | | <ItemGroup> |
| | | <Content Update="wwwroot\swg-login.html"> |
| | | <CopyToOutputDirectory>Never</CopyToOutputDirectory> |
| | | </Content> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | { |
| | | "OutboundTimeConfig": { |
| | | "Gw1FirstHours": 24.0, |
| | | "Gw1SecondHours": 0.05, |
| | | "Cw1Hours": 3.0 |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # OutboundTaskFlowService.MoveToNextStatus TODO å®ç°è®¡å |
| | | |
| | | > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. |
| | | |
| | | **Goal:** è¡¥å
¨ `OutboundTaskFlowService.MoveToNextStatus` æ¹æ³ä¸ç TODOï¼å®ç°å¨åºåºä»»å¡å°è¾¾ `Line_OutFinish` ç¶ææ¶æ£æ¥å¯¹åçº¿ä½æçå·ï¼ææçå·åæ¬å°åå»ºæºæ¢°æä»»å¡ï¼æ æçå·åä» WMS è·åä»»å¡ã |
| | | |
| | | **Architecture:** å¨ `RobotTaskService` 䏿°å¢ `CheckSourceLineAndCreateRobotTask` æ¹æ³ï¼å¤ç¨å·²æç `BuildRobotTaskStock` è·åæºçº¿ä½ç¼å·ï¼éè¿è®¾å¤é信读åçº¿ä½æçå·ï¼æ ¹æ®ç»æå³å®è°ç¨ `CreateLocalRobotTask` æ `GetWMSOutboundTrayTask`ã |
| | | |
| | | **Tech Stack:** C# / .NET 6, ASP.NET Core, SqlSugar ORM |
| | | |
| | | --- |
| | | |
| | | ## æ¶åæä»¶ |
| | | |
| | | | æä»¶ | æ¹å¨ | |
| | | |------|------| |
| | | | `WIDESEAWCS_TaskInfoService/RobotTaskService.cs` | æ°å¢ `CheckSourceLineAndCreateRobotTask` æ¹æ³ | |
| | | | `WIDESEAWCS_TaskInfoService/Flows/OutboundTaskFlowService.cs` | æ¿æ¢ TODO ä»£ç æ®µä¸ºå§æè°ç¨ | |
| | | |
| | | --- |
| | | |
| | | ## Task 1: å¨ RobotTaskService æ°å¢ CheckSourceLineAndCreateRobotTask æ¹æ³ |
| | | |
| | | **Files:** |
| | | - Modify: `WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs:241`ï¼å¨ `CreateLocalRobotTask` æ¹æ³ä¹åï¼ |
| | | |
| | | - [ ] **Step 1: å¨ `CreateLocalRobotTask` æ¹æ³åæ·»å æ°æ¹æ³** |
| | | |
| | | å¨ `RobotTaskService.cs` 第 240 è¡ï¼`CreateLocalRobotTask` æ¹æ³ç»æåçä½ç½®ï¼æ·»å 以䏿¹æ³ï¼ |
| | | |
| | | ```csharp |
| | | /// <summary> |
| | | /// æ£æ¥æºçº¿ä½æ¯å¦ææçå·ï¼å¹¶æ ¹æ®ç»æåå»ºæºæ¢°æä»»å¡ã |
| | | /// </summary> |
| | | /// <param name="task">åºåºä»»å¡å®ä½</param> |
| | | /// <returns> |
| | | /// ææçå·æ¶è¿å CreateLocalRobotTask ç»æï¼ |
| | | /// æ æçå·æ¶è¿å GetWMSOutboundTrayTask ç»æã |
| | | /// </returns> |
| | | public WebResponseContent CheckSourceLineAndCreateRobotTask(Dt_Task task) |
| | | { |
| | | // 1. è·åæºçº¿ä½ç¼å·ï¼å¤ç¨å·²æé»è¾ï¼ |
| | | string configKey = ResolveRobotTaskConfigKey(task.TargetAddress); |
| | | StockDTO stock = BuildRobotTaskStock(task, configKey); |
| | | string sourceLineNo = stock.SourceLineNo; |
| | | |
| | | if (string.IsNullOrWhiteSpace(sourceLineNo)) |
| | | { |
| | | return GetWMSOutboundTrayTask(task); |
| | | } |
| | | |
| | | // 2. éè¿è®¾å¤é信读åçº¿ä½æçå· |
| | | string? palletCode = ReadLineBarcode(sourceLineNo); |
| | | |
| | | if (!string.IsNullOrWhiteSpace(palletCode)) |
| | | { |
| | | // ææçå·ï¼æ¬å°åå»ºæºæ¢°æä»»å¡ |
| | | return CreateLocalRobotTask(task); |
| | | } |
| | | |
| | | // æ æçå·ï¼ä» WMS è·åä»»å¡ |
| | | return GetWMSOutboundTrayTask(task); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 读åæå®çº¿ä½çæçå·ã |
| | | /// </summary> |
| | | /// <param name="sourceLineNo">æºçº¿ä½ç¼å·</param> |
| | | /// <returns>æçå·ï¼å¦æå¼å¸¸è¿å null</returns> |
| | | private string? ReadLineBarcode(string sourceLineNo) |
| | | { |
| | | try |
| | | { |
| | | IDevice? device = Storage.Devices.FirstOrDefault(x => |
| | | x.DeviceProDTOs.Any(d => d.DeviceChildCode == sourceLineNo)); |
| | | |
| | | if (device == null) |
| | | return null; |
| | | |
| | | CommonConveyorLine conveyorLine = (CommonConveyorLine)device; |
| | | return conveyorLine.GetValue<ConveyorLineDBNameNew, string>( |
| | | ConveyorLineDBNameNew.Barcode, sourceLineNo); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _logger.Error(ex, $"读å线ä½[{sourceLineNo}]æçå·å¼å¸¸"); |
| | | return null; |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | - [ ] **Step 2: éªè¯ç¼è¯** |
| | | |
| | | Run: `dotnet build WIDESEAWCS_Server/WIDESEAWCS_Server.sln --no-restore` |
| | | Expected: BUILD SUCCEEDEDï¼æ ç¼è¯éè¯¯ï¼ |
| | | |
| | | - [ ] **Step 3: æäº¤** |
| | | |
| | | ```bash |
| | | git add WIDESEAWCS_TaskInfoService/RobotTaskService.cs |
| | | git commit -m "feat(æºæ¢°æä»»å¡): æ°å¢CheckSourceLineAndCreateRobotTaskæ¹æ³æ¯ææ£æ¥çº¿ä½æçå·å³ç |
| | | |
| | | - æ°å¢CheckSourceLineAndCreateRobotTaskæ¹æ³ï¼æ ¹æ®æºçº¿ä½æçå·å³å®åå»ºæºæ¢°æä»»å¡æ¹å¼ |
| | | - æ°å¢ReadLineBarcodeç§ææ¹æ³ï¼è¯»åæå®çº¿ä½çæçå· |
| | | - ææçå·æ¶è°ç¨CreateLocalRobotTaskï¼æ æçå·æ¶è°ç¨GetWMSOutboundTrayTask |
| | | - å¼å¸¸æ¶é级为ä»WMSè·åä»»å¡" |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## Task 2: ä¿®æ¹ OutboundTaskFlowService.MoveToNextStatus è°ç¨æ°æ¹æ³ |
| | | |
| | | **Files:** |
| | | - Modify: `WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/OutboundTaskFlowService.cs:107-114` |
| | | |
| | | - [ ] **Step 1: æ¿æ¢ TODO ä»£ç æ®µ** |
| | | |
| | | å° `OutboundTaskFlowService.cs` 第 107-114 è¡ï¼ |
| | | |
| | | ```csharp |
| | | if (task.TaskStatus == (int)TaskOutStatusEnum.Line_OutFinish && task.TaskType == (int)TaskOutboundTypeEnum.Outbound) |
| | | { |
| | | return WebResponseContent.Instance.OK(); |
| | | |
| | | // Todo:è·å对åçº¿ä½æ¯å¦ææçå·ï¼å¦æææçå·ç´æ¥çææºæ¢°æä»»å¡ |
| | | |
| | | return GetWMSOutboundTrayTask(task); |
| | | } |
| | | ``` |
| | | |
| | | æ¿æ¢ä¸ºï¼ |
| | | |
| | | ```csharp |
| | | if (task.TaskStatus == (int)TaskOutStatusEnum.Line_OutFinish && task.TaskType == (int)TaskOutboundTypeEnum.Outbound) |
| | | { |
| | | // è·å对åçº¿ä½æ¯å¦ææçå·ï¼å¦æææçå·ç´æ¥çææºæ¢°æä»»å¡ |
| | | return _robotTaskService.CheckSourceLineAndCreateRobotTask(task); |
| | | } |
| | | ``` |
| | | |
| | | - [ ] **Step 2: éªè¯ç¼è¯** |
| | | |
| | | Run: `dotnet build WIDESEAWCS_Server/WIDESEAWCS_Server.sln --no-restore` |
| | | Expected: BUILD SUCCEEDEDï¼æ ç¼è¯éè¯¯ï¼ |
| | | |
| | | - [ ] **Step 3: æäº¤** |
| | | |
| | | ```bash |
| | | git add WIDESEAWCS_TaskInfoService/Flows/OutboundTaskFlowService.cs |
| | | git commit -m "feat(åºåºä»»å¡): MoveToNextStatusè°ç¨CheckSourceLineAndCreateRobotTaskå³çæºæ¢°æä»»å¡å建æ¹å¼ |
| | | |
| | | - æ¿æ¢TODOä»£ç æ®µä¸º_robotTaskService.CheckSourceLineAndCreateRobotTaskè°ç¨ |
| | | - ææçå·æ¶æ¬å°åå»ºæºæ¢°æä»»å¡ï¼æ æçå·æ¶ä»WMSè·å" |
| | | ``` |
| | | |
| | | --- |
| | | |
| | | ## éªè¯è¦ç¹ |
| | | |
| | | 1. å½è¾éçº¿æææ¶ï¼å¯¹åçº¿ä½ Barcode æå¼ï¼ï¼æºæ¢°æä»»å¡ç´æ¥æ¬å°å建ï¼ä¸è°ç¨ WMS æ¥å£ |
| | | 2. å½è¾éçº¿æ ææ¶ï¼å¯¹åçº¿ä½ Barcode 为空ï¼ï¼é级è°ç¨ WMS è·å空æçä»»å¡ |
| | | 3. å¼å¸¸åºæ¯ä¸é»å¡ä¸»æµç¨ï¼éçº§å° WMS è·å |
| | | |
| | | --- |
| | | |
| | | ## 注æäºé¡¹ |
| | | |
| | | - `ReadLineBarcode` æ¹æ³å¤ç¨äº `BuildRobotTaskStock` ä¸è¯»å Barcode çè®¾å¤æ¥è¯¢é»è¾ï¼è§ `RobotTaskService.cs:365-374`ï¼ |
| | | - å¼å¸¸å¤çè¿å nullï¼è§¦åé级é»è¾è°ç¨ `GetWMSOutboundTrayTask` |
| | | - è®¾è®¡ææ¡£ä½ç½®ï¼`docs/superpowers/specs/2026-04-29-outbound-task-flow-todo-design.md` |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # OutboundTaskFlowService.MoveToNextStatus TODO è®¾è®¡æ¹æ¡ |
| | | |
| | | ## èæ¯ |
| | | |
| | | `OutboundTaskFlowService.MoveToNextStatus` æ¹æ³ä¸åå¨ä¸ä¸ª TODOï¼ |
| | | |
| | | ```csharp |
| | | if (task.TaskStatus == (int)TaskOutStatusEnum.Line_OutFinish && task.TaskType == (int)TaskOutboundTypeEnum.Outbound) |
| | | { |
| | | return WebResponseContent.Instance.OK(); |
| | | |
| | | // Todo:è·å对åçº¿ä½æ¯å¦ææçå·ï¼å¦æææçå·ç´æ¥çææºæ¢°æä»»å¡ |
| | | |
| | | return GetWMSOutboundTrayTask(task); |
| | | } |
| | | ``` |
| | | |
| | | 该 TODO éè¦å¨åºåºä»»å¡å°è¾¾ `Line_OutFinish` ç¶ææ¶ï¼æ£æ¥å¯¹åçº¿ä½æ¯å¦ææçå·ï¼ä»¥å³å®åç»æºæ¢°æä»»å¡çå建æ¹å¼ã |
| | | |
| | | ## ä¸å¡é»è¾ |
| | | |
| | | åºåºä»»å¡æµç¨ä¸ï¼å½ç©æéè¿è¾é线å°è¾¾ç®æ ä½ç½®åï¼ |
| | | |
| | | - **对åçº¿ä½ææçå·** â æçä¸æè´§ï¼ç´æ¥å¨æ¬å°åå»ºæºæ¢°æä»»å¡æ§è¡æ¢ç/ç»ç/æç |
| | | - **对åçº¿ä½æ æçå·** â éè¦ä» WMS è·å空æçåºåºä»»å¡ |
| | | |
| | | ## æ¹æ¡éæ© |
| | | |
| | | **éç¨æ¹æ¡ B**ï¼å¨ `RobotTaskService` ä¸å°è£
æ£æ¥é»è¾ï¼å¤ç¨å·²æç `BuildRobotTaskStock` åºç¡è®¾æ½ã |
| | | |
| | | ### åå |
| | | - `RobotTaskService.BuildRobotTaskStock` å·²å®ç°éè¿ `AddressSourceLineNoMap` è§£ææºçº¿ä½ç¼å·ï¼å¹¶éè¿è®¾å¤é信读å `Barcode` ç宿´é»è¾ |
| | | - æ°å¢æ¹æ³èè´£åä¸ï¼æ£æ¥ â å³çï¼ä»
å夿䏿§è¡å¯ä½ç¨ |
| | | - `OutboundTaskFlowService` ä¿æç®æ´ï¼åªéè°ç¨å³å¯ |
| | | |
| | | ## å®ç°è®¾è®¡ |
| | | |
| | | ### 1. RobotTaskService æ°å¢æ¹æ³ |
| | | |
| | | ```csharp |
| | | /// <summary> |
| | | /// æ£æ¥æºçº¿ä½æ¯å¦ææçå·ï¼å¹¶æ ¹æ®ç»æåå»ºæºæ¢°æä»»å¡ã |
| | | /// </summary> |
| | | /// <param name="task">åºåºä»»å¡å®ä½</param> |
| | | /// <returns> |
| | | /// ææçå·æ¶è¿å CreateLocalRobotTask ç»æï¼ |
| | | /// æ æçå·æ¶è¿å GetWMSOutboundTrayTask ç»æã |
| | | /// </returns> |
| | | public WebResponseContent CheckSourceLineAndCreateRobotTask(Dt_Task task) |
| | | { |
| | | // 1. è·åæºçº¿ä½ç¼å·ï¼å¤ç¨å·²æé»è¾ï¼ |
| | | string configKey = ResolveRobotTaskConfigKey(task.TargetAddress); |
| | | StockDTO stock = BuildRobotTaskStock(task, configKey); |
| | | string sourceLineNo = stock.SourceLineNo; |
| | | |
| | | if (string.IsNullOrWhiteSpace(sourceLineNo)) |
| | | { |
| | | return GetWMSOutboundTrayTask(task); |
| | | } |
| | | |
| | | // 2. éè¿è®¾å¤é信读åçº¿ä½æçå· |
| | | string? palletCode = ReadLineBarcode(sourceLineNo); |
| | | |
| | | if (!string.IsNullOrWhiteSpace(palletCode)) |
| | | { |
| | | // ææçå·ï¼æ¬å°åå»ºæºæ¢°æä»»å¡ |
| | | return CreateLocalRobotTask(task); |
| | | } |
| | | |
| | | // æ æçå·ï¼ä» WMS è·åä»»å¡ |
| | | return GetWMSOutboundTrayTask(task); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 读åæå®çº¿ä½çæçå·ã |
| | | /// </summary> |
| | | private string? ReadLineBarcode(string sourceLineNo) |
| | | { |
| | | try |
| | | { |
| | | IDevice? device = Storage.Devices.FirstOrDefault(x => |
| | | x.DeviceProDTOs.Any(d => d.DeviceChildCode == sourceLineNo)); |
| | | |
| | | if (device == null) |
| | | return null; |
| | | |
| | | CommonConveyorLine conveyorLine = (CommonConveyorLine)device; |
| | | return conveyorLine.GetValue<ConveyorLineDBNameNew, string>( |
| | | ConveyorLineDBNameNew.Barcode, sourceLineNo); |
| | | } |
| | | catch |
| | | { |
| | | return null; |
| | | } |
| | | } |
| | | ``` |
| | | |
| | | ### 2. OutboundTaskFlowService ä¿®æ¹ |
| | | |
| | | ```csharp |
| | | if (task.TaskStatus == (int)TaskOutStatusEnum.Line_OutFinish && task.TaskType == (int)TaskOutboundTypeEnum.Outbound) |
| | | { |
| | | // è·å对åçº¿ä½æ¯å¦ææçå·ï¼å¦æææçå·ç´æ¥çææºæ¢°æä»»å¡ |
| | | return _robotTaskService.CheckSourceLineAndCreateRobotTask(task); |
| | | } |
| | | ``` |
| | | |
| | | ## æ°æ®æµ |
| | | |
| | | ``` |
| | | MoveToNextStatus (OutboundTaskFlowService) |
| | | â |
| | | â¼ |
| | | CheckSourceLineAndCreateRobotTask (RobotTaskService) |
| | | â |
| | | ââââ⺠BuildRobotTaskStock ââ⺠ResolveRobotTaskConfigKey |
| | | â âââ⺠AddressSourceLineNoMap è·å sourceLineNo |
| | | â |
| | | â¼ |
| | | ReadLineBarcode(sourceLineNo) |
| | | â |
| | | ââââ⺠Storage.Devices æ¥æ¾è®¾å¤ |
| | | ââââ⺠CommonConveyorLine.GetValue(Barcode) |
| | | â |
| | | â¼ |
| | | âââââââââ´ââââââââ |
| | | â æçå·æå¼ â æçå·ä¸ºç©º |
| | | â¼ â¼ |
| | | CreateLocalRobotTask GetWMSOutboundTrayTask |
| | | ``` |
| | | |
| | | ## é误å¤ç |
| | | |
| | | - è®¾å¤æ¥æ¾å¤±è´¥æè¯»åå¼å¸¸ â é级为è°ç¨ `GetWMSOutboundTrayTask`ï¼ä» WMS è·åä»»å¡ï¼ |
| | | - ä¸é»å¡ä¸»æµç¨ï¼å¼å¸¸ä»
è®°å½æ¥å¿ |
| | | |
| | | ## æ¶åæä»¶ |
| | | |
| | | | æä»¶ | æ¹å¨ | |
| | | |------|------| |
| | | | `WIDESEAWCS_TaskInfoService/RobotTaskService.cs` | æ°å¢ `CheckSourceLineAndCreateRobotTask` å `ReadLineBarcode` æ¹æ³ | |
| | | | `WIDESEAWCS_TaskInfoService/Flows/OutboundTaskFlowService.cs` | æ¿æ¢ TODO ä»£ç æ®µä¸ºå§æè°ç¨ | |
| | | |
| | | ## éªè¯è¦ç¹ |
| | | |
| | | 1. å½è¾éçº¿æææ¶ï¼æºæ¢°æä»»å¡ç´æ¥æ¬å°å建ï¼ä¸è°ç¨ WMS æ¥å£ |
| | | 2. å½è¾éçº¿æ ææ¶ï¼é级è°ç¨ WMS è·å空æçä»»å¡ |
| | | 3. å¼å¸¸åºæ¯ä¸é»å¡ä¸»æµç¨ï¼éçº§å° WMS è·å |