Merge branch 'xiaoyang' 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);
|
| | |
| | | /// <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 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)
|
| | |
| | | //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); |
| | | } |
| | | |
| | |
| | | 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) |
| | | //{ |
| | |
| | | |
| | | 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 |
| | |
| | | |
| | | 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; |
| | |
| | | // è§£æ 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)
|
| | |
| | | // è°ç¨æ¹éæç确认æ¥å£ |
| | | 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; |
| | |
| | | // è°ç¨æ¹éç»ç确认æ¥å£ |
| | | 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; |
| | |
| | | // ç®æ æ°é为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)) |
| | | { |
| | |
| | | $"TrySelectOutboundTaskï¼TargetAddress: {outboundTask.TargetAddress} å·²ææ£å¨æ§è¡çè¾é线任å¡", outboundTask.Roadway, outboundTask.TargetAddress, outboundTask.TaskNum); |
| | | return null; |
| | | } |
| | | } |
| | | //} |
| | | |
| | | if(outboundTask.Roadway != "GWSC1") |
| | | { |
| | |
| | | && x.LocationType == locationType) |
| | | .CountAsync(); |
| | | |
| | | if(roadwayNo != "CWSC1") |
| | | { |
| | | // 空é²è´§ä½ä¸è¶³æä½ä¿çæ°éæ¶è¿ånullï¼é¿å
å°å··éåé
èå°½ |
| | | const int minFreeLocationThreshold = 5; |
| | | 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> |
| | | /// å容åºåºåºå°å |
| | |
| | | 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, "å
¥åºå®æ"); |
| | |
| | | |
| | | stockInfo.StockStatus = StockStatusEmun.å
¥åºå®æ.GetHashCode(); |
| | | |
| | | stockInfo.CreateDate = DateTime.Now; |
| | | |
| | | location.LocationStatus = LocationStatusEnum.InStock.GetHashCode(); |
| | | |
| | | var updateLocationResult = await _locationInfoService.UpdateLocationInfoAsync(location); |
| | |
| | | "MainDB": "DB_WIDESEA", //å½å项ç®ç主åºï¼æå¯¹åºçè¿æ¥å符串çEnabledå¿
须为true |
| | | //è¿æ¥å符串 |
| | | //"ConnectionString": "HTI6FB1H05Krd07mNm9yBCNhofW6edA5zLs9TY~MNthRYW3kn0qKbMIsGp~3yyPDF1YZUCPBQx8U0Jfk4PH~ajNFXVIwlH85M3F~v_qKYQ3CeAz3q1mLVDn8O5uWt1~3Ut2V3KRkEwYHvW2oMDN~QIDXPxDgXN0R2oTIhc9dNu7QNaLEknblqmHhjaNSSpERdDVZIgHnMKejU_SL49tralBkZmDNi0hmkbL~837j1NWe37u9fJKmv91QPb~16JsuI9uu0EvNZ06g6PuZfOSAeFH9GMMIZiketdcJG3tHelo=", |
| | | "ConnectionString": "Data Source=.;Initial Catalog=WIDESEAWMS_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=WIDESEAWMS_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=WIDESEAWMS_ShanMei;User ID=sa;Password=123456;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False", |
| | | //"ConnectionString": "Data Source=10.30.4.92;Initial Catalog=WMS_TC;User ID=sa;Password=duo123456;Integrated Security=False;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False", |
| | | //æ§WMSæ°æ®åºè¿æ¥ |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # 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 è·å |