Code/WCS/DataDictionary.pdfBinary files differ
Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Common/RobotEnum/RobotConst.cs
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,14 @@ namespace WIDESEAWCS_Common { public class RobotConst { /// <summary> /// 任塿»æ°ä¸é /// </summary> /// <remarks> /// 彿ºå¨äººå¤ççè´§ç©æ°éè¾¾å°æ¤ä¸éæ¶ï¼ä¸åä¸åæ°ä»»å¡ã /// 鲿¢æºå¨äººè¿åº¦å³ç´¯æç³»ç»è¿è½½ã /// </remarks> public const int MaxTaskTotalNum = 48; } } Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Core/Http/HTTP/HttpClientHelper.cs
@@ -121,7 +121,7 @@ public HttpResponseResult<TResponse> Get<TResponse>(string url, HttpRequestConfig? config = null) { url = BaseAPI.WMSBaseUrl + _cache.Get(url); url = BaseAPI.WMSBaseUrl + _cache.Get($"{RedisPrefix.Code}:{RedisName.API}:{url}"); HttpResponseResult httpResponseResult = Get(url, config); HttpResponseResult<TResponse> result = new HttpResponseResult<TResponse> Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITaskInfoService/IRobotTaskService.cs
@@ -57,6 +57,13 @@ public Dt_RobotTask? QueryRobotCraneTask(string deviceCode); /// <summary> /// æ ¹æ®è®¾å¤ç¼ç è·åæ§è¡ä¸çæºæ¢°æä»»å¡ /// </summary> /// <param name="deviceCode">设å¤ç¼ç </param> /// <returns>æ§è¡ä¸çä»»å¡å¯¹è±¡ï¼å¦ææ²¡æåè¿å null</returns> public Dt_RobotTask? QueryRobotCraneExecutingTask(string deviceCode); Task<bool> UpdateRobotTaskAsync(Dt_RobotTask robotTask); /// <summary> Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/RobotTaskService.cs
@@ -111,6 +111,11 @@ return BaseDal.QueryFirst(x => x.RobotRoadway == deviceCode && x.RobotTaskState != (int)TaskRobotStatusEnum.RobotExecuting, TaskOrderBy); } public Dt_RobotTask? QueryRobotCraneExecutingTask(string deviceCode) { return BaseDal.QueryFirst(x => x.RobotRoadway == deviceCode && x.RobotTaskState == (int)TaskRobotStatusEnum.RobotExecuting, TaskOrderBy); } public async Task<bool> UpdateRobotTaskAsync(Dt_RobotTask robotTask) { return await BaseDal.UpdateDataAsync(robotTask); Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/TaskService.cs
@@ -101,10 +101,13 @@ try { List<Dt_Task> tasks = new List<Dt_Task>(); List<Dt_Task> duplicates = new List<Dt_Task>(); foreach (var item in taskDTOs) { if (BaseDal.QueryFirst(x => x.TaskNum == item.TaskNum || x.PalletCode == item.PalletCode) != null) Dt_Task existingTask = BaseDal.QueryFirst(x => x.TaskNum == item.TaskNum || x.PalletCode == item.PalletCode); if (existingTask != null) { duplicates.Add(existingTask); continue; } Dt_Task task = _mapper.Map<Dt_Task>(item); @@ -117,7 +120,10 @@ _taskExecuteDetailService.AddTaskExecuteDetail(tasks.Select(x => x.TaskNum).ToList(), "æ¥æ¶WMSä»»å¡"); content = WebResponseContent.Instance.OK("æå", tasks); // å°éå¤ä»»å¡ä¿¡æ¯ä¹ä¸å¹¶è¿å tasks.AddRange(duplicates); var result = tasks; content = WebResponseContent.Instance.OK("æå", result); } catch (Exception ex) { Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotJob.cs
@@ -1,7 +1,7 @@ using Microsoft.Extensions.Logging; using Quartz; using System.Net; using WIDESEA_Core; using WIDESEAWCS_Common; using WIDESEAWCS_Core.Caches; using WIDESEAWCS_Core.Helper; using WIDESEAWCS_Core.LogHelper; @@ -29,15 +29,6 @@ [DisallowConcurrentExecution] public class RobotJob : IJob { /// <summary> /// 任塿»æ°ä¸é /// </summary> /// <remarks> /// 彿ºå¨äººå¤ççè´§ç©æ°éè¾¾å°æ¤ä¸éæ¶ï¼ä¸åä¸åæ°ä»»å¡ã /// 鲿¢æºå¨äººè¿åº¦å³ç´¯æç³»ç»è¿è½½ã /// </remarks> private const int MaxTaskTotalNum = 48; /// <summary> /// æ¶æ¯äºä»¶è®¢é æ å¿ /// </summary> @@ -131,7 +122,7 @@ // åå§åå½ä»¤å¤çå¨ // ç®åå½ä»¤å¤çå¨ï¼å¤çç¶ææ´æ°çç®åå½ä»¤ var simpleCommandHandler = new RobotSimpleCommandHandler(_taskProcessor); var simpleCommandHandler = new RobotSimpleCommandHandler(_taskProcessor, socketGateway); // åç¼å½ä»¤å¤çå¨ï¼å¤ç pickfinishedãputfinished ç另忰çå½ä»¤ var prefixCommandHandler = new RobotPrefixCommandHandler(robotTaskService, _taskProcessor, _stateManager, socketGateway); @@ -214,8 +205,19 @@ return; } if (state.CurrentAction == "Picking" || state.CurrentAction == "Puting") { return; } // 轮询è·å该设å¤çå¾ å¤çä»»å¡ var task = _taskProcessor.GetTask(robotCrane); // å¦ææ²¡æè·åå°å¾ å¤çä»»å¡ï¼ä¸RobotArmObject为1ï¼æç©æï¼ï¼åè·åè¯¥è®¾å¤æ§è¡ä¸çä»»å¡ if (task == null && state.RobotArmObject == 1) { task = _taskProcessor.GetExecutingTask(robotCrane); } // 妿æå¾ å¤çä»»å¡ if (task != null) @@ -229,12 +231,12 @@ } // æ£æ¥ä»»å¡æ»æ°æ¯å¦æªè¾¾å°ä¸é //if (latestState.RobotTaskTotalNum < MaxTaskTotalNum) //{ if (latestState.RobotTaskTotalNum < RobotConst.MaxTaskTotalNum) { // è°ç¨å·¥ä½æµç¼æå¨æ§è¡ä»»å¡ // ç¼æå¨ä¼æ ¹æ®å½åç¶æå³å®ä¸ä¸æ¥å¨ä½ await _workflowOrchestrator.ExecuteAsync(latestState, task, ipAddress); //} } } } catch (Exception ex) @@ -246,4 +248,4 @@ } } } } } Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotMessageHandler.cs
@@ -1,5 +1,4 @@ using Microsoft.Extensions.Logging; using System.Net; using System.Net.Sockets; using WIDESEAWCS_Common; using WIDESEAWCS_Core.Caches; @@ -119,6 +118,17 @@ _logger.LogInformation($"æ¥æ¶å°å®¢æ·ç«¯ã{state.RobotCrane.DeviceName}ãåéæ¶æ¯ã{message}ã"); QuartzLogger.Info($"æ¥æ¶å°å®¢æ·ç«¯æ¶æ¯ã{message}ã", state.RobotCrane.DeviceName); // æ£æ¥ä»»å¡æ»æ°æ¯å¦æªè¾¾å°ä¸é if (state.RobotTaskTotalNum > RobotConst.MaxTaskTotalNum) { // è®°å½æ¥æ¶å°çæ¶æ¯æ¥å¿ _logger.LogInformation($"æ¥æ¶å°å®¢æ·ç«¯ã{state.RobotCrane.DeviceName}ãåéæ¶æ¯ã{message}ã"); QuartzLogger.Info($"æ¥æ¶å°å®¢æ·ç«¯æ¶æ¯ã{message}ã", state.RobotCrane.DeviceName); // å¤çæååï¼å°åæ¶æ¯ååå°å®¢æ·ç«¯ï¼ä¿æåæè¡ä¸ºï¼ await _socketClientGateway.SendMessageAsync(client, message); return null; } // æå»ºç¼åé®ï¼æ£æ¥ Redis 䏿¯å¦åå¨è¯¥è®¾å¤çç¶æ var cacheKey = $"{RedisPrefix.Code}:{RedisName.SocketDevices}:{client.Client.RemoteEndPoint}"; @@ -161,4 +171,4 @@ return null; } } } } Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotSocketState.cs
@@ -74,6 +74,16 @@ public RobotCraneDevice? RobotCrane { get; set; } /// <summary> /// æºæ¢°æåå§å宿åå°å¾ æºä½ /// </summary> /// <remarks> /// å¯è½çå¼ï¼ /// - "Homed": å·²åé¶ /// - "Homing": åé¶ä¸ /// </remarks> public string? Homed { get; set; } /// <summary> /// æºæ¢°æå½åæ£å¨æ§è¡çå¨ä½ /// </summary> /// <remarks> Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotTaskProcessor.cs
@@ -113,6 +113,20 @@ } /// <summary> /// æè®¾å¤ç¼ç è·åå½åæºå¨äººçæ§è¡ä¸ä»»å¡ /// </summary> /// <remarks> /// 仿°æ®åºä¸æ¥è¯¢æå®è®¾å¤ç¼ç çæ§è¡ä¸æºå¨äººä»»å¡ã /// å½RobotArmObject为1ï¼æç©æï¼ä¸æ²¡æå¾ å¤ç任塿¶è°ç¨ã /// </remarks> /// <param name="robotCrane">æºå¨äººè®¾å¤ä¿¡æ¯ï¼å å«è®¾å¤ç¼ç </param> /// <returns>æ§è¡ä¸çä»»å¡å¯¹è±¡ï¼å¦ææ²¡æåè¿å null</returns> public Dt_RobotTask? GetExecutingTask(RobotCraneDevice robotCrane) { return _robotTaskService.QueryRobotCraneExecutingTask(robotCrane.DeviceCode); } /// <summary> /// å 餿ºå¨äººä»»å¡ /// </summary> /// <remarks> @@ -208,7 +222,7 @@ // æ ¹æ®å··éåç§°å¤æä»åº ID // ZYRB1 -> 1, HPRB001 -> 2, å ¶ä» -> 3 int warehouseId = currentTask.RobotRoadway == "ZYRB1" ? 1 : currentTask.RobotRoadway == "HPRB001" ? 2 : 3; int warehouseId = currentTask.RobotRoadway == "注液ç»çæºæ¢°æ" ? 1 : currentTask.RobotRoadway == "HPRB001" ? 2 : 3; // ä»»å¡ç±»åï¼0 表示æªå®ä¹ï¼ç¨åæ ¹æ®ä»»å¡ç±»åè®¾ç½®ï¼ int taskType = 0; @@ -303,7 +317,8 @@ } // è§£æè¿åçä»»å¡ä¿¡æ¯ var taskInfo = JsonConvert.DeserializeObject<Dt_Task>(content.Data.ToJson() ?? string.Empty) ?? new Dt_Task(); var taskInfos = JsonConvert.DeserializeObject<List<Dt_Task>>(content.Data.ToJson() ?? string.Empty) ?? new List<Dt_Task>(); var taskInfo = taskInfos.FirstOrDefault(); // è·åæºå°å string sourceAddress = taskDTO.SourceAddress; @@ -363,6 +378,9 @@ // ç®æ è¾é线ç¼å· TargetLineNo = state.CurrentTask.RobotTargetAddressLineCode, // å··éç¼å·(æºå¨äººåç§°) Roadway = state.CurrentTask.RobotRoadway, // çµæ± ä½ç½®è¯¦æ å表 // è¿æ»¤æä½ç½®ä¸º 0 æè´æ°çæ ææ°æ® // æä½ç½®ç¼å·æåº @@ -373,7 +391,7 @@ .Select((x, idx) => new StockDetailDTO { // æ°éï¼å¦æå·²æä»»å¡æ»æ°ï¼ä½¿ç¨ä»»å¡æ»æ°+å½åä½ç½®æ°ï¼å¦ååªä½¿ç¨å½åä½ç½®æ° Quantity = state.RobotTaskTotalNum > 0 ? state.RobotTaskTotalNum + positions.Length : positions.Length, Quantity = 1, // éé/ä½ç½®ç¼å· Channel = x, Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotSimpleCommandHandler.cs
@@ -1,4 +1,5 @@ using WIDESEAWCS_Common.TaskEnum; using WIDESEAWCS_Core.LogHelper; using WIDESEAWCS_Tasks.Workflow.Abstractions; namespace WIDESEAWCS_Tasks.Workflow @@ -26,12 +27,21 @@ private readonly RobotTaskProcessor _taskProcessor; /// <summary> /// Socket ç½å ³ /// </summary> /// <remarks> /// ç¨äºå客æ·ç«¯åéååºæ¶æ¯ã /// </remarks> private readonly ISocketClientGateway _socketClientGateway; /// <summary> /// æé 彿° /// </summary> /// <param name="taskProcessor">ä»»å¡å¤çå¨å®ä¾</param> public RobotSimpleCommandHandler(RobotTaskProcessor taskProcessor) public RobotSimpleCommandHandler(RobotTaskProcessor taskProcessor, ISocketClientGateway socketClientGateway) { _taskProcessor = taskProcessor; _socketClientGateway = socketClientGateway; } /// <summary> @@ -71,12 +81,12 @@ // æºå¨äººæ£å¨åé¶ case "homing": state.OperStatus = "Homing"; state.Homed = "Homing"; return true; // æºå¨äººå·²å®æåé¶ case "homed": state.OperStatus = "Homed"; state.Homed = "Homed"; return true; // æºå¨äººæ£å¨è¿è¡ @@ -113,71 +123,76 @@ // å ¨é¨åè´§å®æ case "allpickfinished": { // æ´æ°å½åå¨ä½ä¸º"å ¨é¨åè´§å®æ" state.CurrentAction = "AllPickFinished"; // è·åå½åå ³èçä»»å¡ var currentTask = state.CurrentTask; if (currentTask == null) { // 没æä»»å¡å ³èï¼è¿å false // æ´æ°å½åå¨ä½ä¸º"å ¨é¨åè´§å®æ" state.CurrentAction = "AllPickFinished"; // è·åå½åå ³èçä»»å¡ var currentTask = state.CurrentTask; if (currentTask == null) { // 没æä»»å¡å ³èï¼è¿å false return false; } // 夿任å¡ç±»å var robotTaskType = (RobotTaskTypeEnum)currentTask.RobotTaskType; // åªææçææ¢çä»»å¡éè¦å¤çå ¥åº if (robotTaskType == RobotTaskTypeEnum.SplitPallet || robotTaskType == RobotTaskTypeEnum.ChangePallet) { // å¤çå ¥åºä»»å¡åä¼ // useSourceAddress: true è¡¨ç¤ºä½¿ç¨æºå°åï¼æç/æ¢çåºæ¯ï¼ if (await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: true)) { // å ¥åºæåï¼å é¤ä»»å¡è®°å½ _taskProcessor.DeleteTask(currentTask.RobotTaskId); await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Swap,diskFinished"); QuartzLogger.Info($"åéæ¶æ¯ï¼ãSwap,diskFinishedã", state.RobotCrane.DeviceName); return true; } } return false; } // 夿任å¡ç±»å var robotTaskType = (RobotTaskTypeEnum)currentTask.RobotTaskType; // åªææçææ¢çä»»å¡éè¦å¤çå ¥åº if (robotTaskType == RobotTaskTypeEnum.SplitPallet || robotTaskType == RobotTaskTypeEnum.ChangePallet) { // å¤çå ¥åºä»»å¡åä¼ // useSourceAddress: true è¡¨ç¤ºä½¿ç¨æºå°åï¼æç/æ¢çåºæ¯ï¼ if (await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: true)) { // å ¥åºæåï¼å é¤ä»»å¡è®°å½ _taskProcessor.DeleteTask(currentTask.RobotTaskId); return true; } } return false; } // å ¨é¨æ¾è´§å®æ case "allputfinished": { // æ´æ°å½åå¨ä½ä¸º"å ¨é¨æ¾è´§å®æ" state.CurrentAction = "AllPutFinished"; // è·åå½åå ³èçä»»å¡ var currentTask = state.CurrentTask; if (currentTask == null) { // æ´æ°å½åå¨ä½ä¸º"å ¨é¨æ¾è´§å®æ" state.CurrentAction = "AllPutFinished"; // è·åå½åå ³èçä»»å¡ var currentTask = state.CurrentTask; if (currentTask == null) { return false; } // 夿任å¡ç±»å var robotTaskType = (RobotTaskTypeEnum)currentTask.RobotTaskType; // åªæç»çææ¢çä»»å¡éè¦å¤çå ¥åº if (robotTaskType == RobotTaskTypeEnum.GroupPallet || robotTaskType == RobotTaskTypeEnum.ChangePallet) { // å¤çå ¥åºä»»å¡åä¼ // useSourceAddress: false 表示使ç¨ç®æ å°åï¼ç»ç/æ¢çåºæ¯ï¼ if (await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: false)) { // å ¥åºæåï¼å é¤ä»»å¡è®°å½ _taskProcessor.DeleteTask(currentTask.RobotTaskId); // æ¸ çç¶æï¼ä¸ºä¸ä¸ä¸ªä»»å¡ååå¤ state.CurrentTask = null; // æ¸ é¤å½åä»»å¡ state.RobotTaskTotalNum = 0; // é置任å¡è®¡æ° state.CellBarcode = new List<string>(); // æ¸ ç©ºæ¡ç å表 await _socketClientGateway.SendToClientAsync(state.IPAddress, $"Group,diskFinished"); QuartzLogger.Info($"åéæ¶æ¯ï¼ãGroup,diskFinishedã", state.RobotCrane.DeviceName); return true; } } return false; } // 夿任å¡ç±»å var robotTaskType = (RobotTaskTypeEnum)currentTask.RobotTaskType; // åªæç»çææ¢çä»»å¡éè¦å¤çå ¥åº if (robotTaskType == RobotTaskTypeEnum.GroupPallet || robotTaskType == RobotTaskTypeEnum.ChangePallet) { // å¤çå ¥åºä»»å¡åä¼ // useSourceAddress: false 表示使ç¨ç®æ å°åï¼ç»ç/æ¢çåºæ¯ï¼ if (await _taskProcessor.HandleInboundTaskAsync(state, useSourceAddress: false)) { // å ¥åºæåï¼å é¤ä»»å¡è®°å½ _taskProcessor.DeleteTask(currentTask.RobotTaskId); // æ¸ çç¶æï¼ä¸ºä¸ä¸ä¸ªä»»å¡ååå¤ state.CurrentTask = null; // æ¸ é¤å½åä»»å¡ state.RobotTaskTotalNum = 0; // é置任å¡è®¡æ° state.CellBarcode = new List<string>(); // æ¸ ç©ºæ¡ç å表 return true; } } return false; } // ==================== 模å¼åæ¢å½ä»¤ ==================== @@ -221,4 +236,4 @@ } } } } } Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs
@@ -111,13 +111,8 @@ // 1. è¿è¡æ¨¡å¼ä¸ºèªå¨ï¼2ï¼ // 2. æ§å¶æ¨¡å¼ä¸ºå®¢æ·ç«¯æ§å¶ï¼1ï¼ // 3. è¿è¡ç¶ææ¯ Running if (latestState.RobotRunMode == 2 /*&& latestState.RobotControlMode == 1*/ && latestState.OperStatus == "Running") if (latestState.RobotRunMode == 2 /*&& latestState.RobotControlMode == 1*/ && latestState.OperStatus == "Running" && latestState.Homed == "Homed") { if(latestState.CurrentAction == "Picking" || latestState.CurrentAction == "Puting") { return; } // ========== åè´§å®æåçæ¾è´§å¤ç ========== // æ¡ä»¶ï¼ // - å½åå¨ä½æ¯ PickFinished æ AllPickFinishedï¼åè´§å®æï¼ @@ -255,9 +250,23 @@ // 妿æ¡ç çææå if (!string.IsNullOrEmpty(trayBarcode1) && !string.IsNullOrEmpty(trayBarcode2)) { // å°æ¡ç æ·»å å°ç¶æä¸ï¼ä¾åç»æ¾è´§æ¶ä½¿ç¨ stateForUpdate.CellBarcode.Add(trayBarcode1); stateForUpdate.CellBarcode.Add(trayBarcode2); if(stateForUpdate.CellBarcode.Contains(trayBarcode1)|| stateForUpdate.CellBarcode.Contains(trayBarcode2)) { _logger.LogError("HandlePutFinishedStateAsyncï¼çæçæçæ¡ç å·²åå¨ï¼å¯è½åå¨éå¤ï¼ä»»å¡å·: {TaskNum}", task.RobotTaskNum); QuartzLogger.Error($"çæçæçæ¡ç å·²åå¨ï¼å¯è½åå¨éå¤", stateForUpdate.RobotCrane.DeviceName); // æ¡ç éå¤ï¼è®°å½é误æ¥å¿å¹¶åæ¢åç»æä½(åç»æ¾è´§æ¶ä¼ç¨å°è¿äºæ¡ç ä¿¡æ¯ï¼ä¾åç»æ¾è´§æ¶ä½¿ç¨ï¼è°è¯åå¯è½ä¼åæ¶æ¤é»è¾) return; } else { _logger.LogInformation("HandlePutFinishedStateAsyncï¼çæçæçæ¡ç å¯ä¸ï¼ç»§ç»æ§è¡ï¼ä»»å¡å·: {TaskNum}", task.RobotTaskNum); QuartzLogger.Info($"çæçæçæ¡ç å¯ä¸ï¼ç»§ç»æ§è¡", stateForUpdate.RobotCrane.DeviceName); // å°æ¡ç æ·»å å°ç¶æä¸ï¼ä¾åç»æ¾è´§æ¶ä½¿ç¨ stateForUpdate.CellBarcode.Add(trayBarcode1); stateForUpdate.CellBarcode.Add(trayBarcode2); } // è®°å½æ¥å¿ï¼çææçæ¡ç æå _logger.LogInformation("HandlePutFinishedStateAsyncï¼çææçæ¡ç æå: {Barcode1}+{Barcode2}ï¼ä»»å¡å·: {TaskNum}", trayBarcode1, trayBarcode2, task.RobotTaskNum); Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Server.cs
@@ -19,11 +19,11 @@ /// </remarks> /// <param name="cancellationToken">忶令ç</param> /// <returns>å¯å¨ä»»å¡</returns> public Task StartAsync(CancellationToken cancellationToken) public async Task StartAsync(CancellationToken cancellationToken) { if (IsRunning || !_options.Enabled) { return Task.CompletedTask; return; } // è§£æçå¬å°å @@ -32,6 +32,8 @@ { ipAddress = parsedAddress; } await Task.Delay(5000); // å建çå¬å¨ _listener = new TcpListener(ipAddress, _options.Port); @@ -45,7 +47,7 @@ // å¯å¨å®¢æ·ç«¯çæ§ä»»å¡ï¼æ£æ¥ç©ºé²è¶ æ¶ï¼ _monitorTask = Task.Run(() => MonitorClientsAsync(_cts.Token)); return Task.CompletedTask; return; } /// <summary>