Code/.omc/state/last-tool-error.json
@@ -1,7 +1,7 @@ { "tool_name": "Read", "tool_input_preview": "{\"file_path\":\"D:\\\\Git\\\\ShanMeiXinNengYuan\\\\Code\\\\WCS\\\\WIDESEAWCS_Server\\\\WIDESEA_DTO\\\\Stock\\\\StockDTO.cs\"}", "error": "File does not exist. Note: your current working directory is D:\\Git\\ShanMeiXinNengYuan\\Code.", "timestamp": "2026-04-16T15:04:27.059Z", "retry_count": 2 "tool_name": "Bash", "tool_input_preview": "{\"command\":\"node -e \\\"\\nconst f=require('fs'),p=require('path'),h=require('os').homedir();\\nconst d=process.env.CLAUDE_CONFIG_DIR||p.join(h,'.claude');\\nconst cf=p.join(d,'.omc-config.json');\\nconst e...", "error": "Exit code 1\n<anonymous_script>:1\r\n\r\n\r\nSyntaxError: Unexpected end of JSON input\r\n at JSON.parse (<anonymous>)\r\n at [eval]:5:38\r\n at runScriptInThisContext (node:internal/vm:219:10)\r\n at node:internal/process/execution:451:12\r\n at [eval]-wrapper:6:24\r\n at runScriptInContext (node:internal/process/execution:449:60)\r\n at evalFunction (node:internal/process/execution:283:30)\r\n at evalTypeScript (node:internal/process/execution:295:3)\r\n at node:internal/main/eval_string:71:...", "timestamp": "2026-04-18T06:15:45.665Z", "retry_count": 1 } Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/HostedService/ApiRouteCacheWarmupHostedService.cs
@@ -46,8 +46,16 @@ public Task StartAsync(CancellationToken cancellationToken) { const string cacheKey = $"{RedisPrefix.Code}"; _cache.RemoveByPrefix($"{cacheKey}"); const string cacheKeyPrefix = $"{RedisPrefix.Code}:{RedisName.API}:"; int warmedCount = 0; foreach ((string configKey, string routePath) in ApiRouteMappings) { @@ -55,7 +63,7 @@ warmedCount++; } _logger.LogInformation("��API·�ɻ���Ԥ����ɡ�����={Count}", warmedCount); _logger.LogInformation("API路由缓存预热完成,共加载={Count}个路由映射", warmedCount); return Task.CompletedTask; } Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/appsettings.json
@@ -88,11 +88,11 @@ "110681": "Split" }, "AddressRoadwayMap": { // 对应设备地址映射 "11001": "换盘机械手", "11010": "换盘机械手", "11068": "注液组盘机械手", "10010": "换盘机械手", "10030": "换盘机械手" "11001": "HCSC1", "11010": "HCSC1", "11068": "GWSC1", "10010": "GWSC1", "10030": "GWSC1" }, "AddressSourceLineNoMap": { // 对应输送线编号地址映射 "11001": "10010", Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_TaskInfoService/Flows/OutboundTaskFlowService.cs
@@ -93,12 +93,12 @@ if (task.TaskStatus == (int)TaskOutStatusEnum.Line_OutFinish && task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty) { WebResponseContent content = _robotTaskService.GetWMSRobotTask(task); if (!content.Status) { return content; } return OutboundFinishTaskTray(task); return _robotTaskService.GetWMSRobotTask(task); //if (!content.Status) //{ // return content; //} //return OutboundFinishTaskTray(task); } if (task.TaskStatus == (int)TaskOutStatusEnum.Line_OutExecuting) Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotBarcodeGenerator.cs
@@ -1,4 +1,5 @@ using Masuit.Tools; using WIDESEAWCS_Communicator; using WIDESEAWCS_QuartzJob; namespace WIDESEAWCS_Tasks @@ -18,7 +19,11 @@ var device = Storage.Devices.Where(d => d.DeviceName == "A区_一注输送线").FirstOrDefault(); if (!device.IsNullOrEmpty() && device != null && device.Communicator.IsConnected) { var trayBarcode = device.Communicator.Read<string>(prefix); var trayBarcode = device.Communicator.Read<string>(prefix).Trim().Replace("\u0018", "").Replace("\u0006", ""); if(trayBarcode == "NoRead") { trayBarcode = ""; } return trayBarcode; } return ""; Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotSocketState.cs
@@ -211,5 +211,15 @@ /// 拉带线上电芯扫码是否NG。 /// </remarks> public bool IsScanNG { get; set; } = false; /// <summary> /// 是否电芯到位 /// </summary> /// <remarks> /// 拉带线上电芯是否到位。 /// </remarks> public bool BatteryArrived { get; set; } = false; } } Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/RobotTaskProcessor.cs
@@ -165,7 +165,7 @@ /// <param name="task">要下发的任务对象</param> /// <param name="state">机器人当前状态</param> /// <param name="isScanNG">是否扫码NG</param> public async Task SendSocketRobotPickAsync(Dt_RobotTask task, RobotSocketState state, bool isScanNG) public async Task SendSocketRobotPickAsync(Dt_RobotTask task, RobotSocketState state, bool isScanNG = false) { // 构建取货指令,格式:Pickbattery,{源地址} string taskString = $"Pickbattery,{task.RobotSourceAddress}"; @@ -600,7 +600,8 @@ Channel = x, // 电池条码:如果状态中有条码列表,取对应位置的条码;否则为空 CellBarcode = state.CellBarcode?.Count > 0 ? state.CellBarcode[x - 1] : "" //CellBarcode = state.CellBarcode?.Count > 0 ? state.CellBarcode[x - 1] : "" CellBarcode = state.CellBarcode[idx].ToString() }) .ToList() }; Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotSimpleCommandHandler.cs
@@ -119,6 +119,11 @@ state.CurrentAction = "Putting"; return true; // 手臂无物料(手臂空闲) case "batteryarrived": state.BatteryArrived = true; return true; // ==================== 全部完成命令 ==================== // 全部取货完成 @@ -251,12 +256,12 @@ if (robotTaskType == RobotTaskTypeEnum.GroupPallet) { // 调用批量组盘确认接口 var targetPallet = state.CurrentTask.RobotTargetAddressPalletCode; var confirmResult = _taskProcessor.PostGroupPalletConfirmAsync(targetPallet); if (!confirmResult.IsSuccess) { QuartzLogger.Error($"批量组盘确认失败: {confirmResult.ErrorMessage}", state.RobotCrane?.DeviceName ?? "Unknown"); } //var targetPallet = state.CurrentTask.RobotTargetAddressPalletCode; //var confirmResult = _taskProcessor.PostGroupPalletConfirmAsync(targetPallet); //if (!confirmResult.IsSuccess) //{ // QuartzLogger.Error($"批量组盘确认失败: {confirmResult.ErrorMessage}", state.RobotCrane?.DeviceName ?? "Unknown"); //} // 处理入库任务回传 // useSourceAddress: false 表示使用目标地址(组盘场景) Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/RobotJob/Workflow/RobotWorkflowOrchestrator.cs
@@ -112,7 +112,7 @@ // 1. 运行模式为自动(2) // 2. 控制模式为客户端控制(1) // 3. 运行状态是 Running if (latestState.RobotRunMode == 2 /*&& latestState.RobotControlMode == 1*/ && latestState.OperStatus == "Running" && latestState.Homed == "Homed") if (latestState.RobotRunMode == 2 /*&& latestState.RobotControlMode == 1*/ && latestState.OperStatus == "Running" && (latestState.Homed == "Homed" || latestState.Homed.IsNullOrEmpty())) { // ========== 取货完成后的放货处理 ========== // 条件: @@ -120,11 +120,11 @@ // - 手臂上有物料(RobotArmObject == 1) // - 任务状态为 RobotPickFinish(已记录取货完成) if ((latestState.CurrentAction == "PickFinished" || latestState.CurrentAction == "AllPickFinished") && latestState.RobotArmObject == 1 && (latestState.RobotArmObject.IsNullOrEmpty() || latestState.RobotArmObject == 1) && task.RobotTaskState == TaskRobotStatusEnum.RobotPickFinish.GetHashCode()) { _logger.LogInformation("ExecuteAsync:满足放货条件,开始处理取货完成,任务号: {TaskNum}", task.RobotTaskNum); QuartzLogger.Info($"ExecuteAsync:满足放货条件,开始处理取货完成", latestState.RobotCrane?.DeviceName ?? ipAddress); _logger.LogInformation("ExecuteAsync:满足放货条件,开始下发放货任务,任务号: {TaskNum}", task.RobotTaskNum); QuartzLogger.Info($"ExecuteAsync:满足放货条件,开始下发放货任务", latestState.RobotCrane?.DeviceName ?? ipAddress); // 发送放货指令 await HandlePickFinishedStateAsync(task, ipAddress); } @@ -136,12 +136,12 @@ // - 手臂上无物料(RobotArmObject == 0) // - 任务状态为 RobotPutFinish 或不是 RobotExecuting else if ((latestState.CurrentAction == "PutFinished" || latestState.CurrentAction == "AllPutFinished" || latestState.CurrentAction.IsNullOrEmpty()) && latestState.RobotArmObject == 0 && (latestState.RobotArmObject.IsNullOrEmpty() || latestState.RobotArmObject == 0) && (task.RobotTaskState == TaskRobotStatusEnum.RobotPutFinish.GetHashCode() || task.RobotTaskState != TaskRobotStatusEnum.RobotExecuting.GetHashCode())) { _logger.LogInformation("ExecuteAsync:满足取货条件,开始处理放货完成,任务号: {TaskNum}", task.RobotTaskNum); QuartzLogger.Info($"ExecuteAsync:满足取货条件,开始处理放货完成", latestState.RobotCrane?.DeviceName ?? ipAddress); _logger.LogInformation("ExecuteAsync:满足取货条件,开始下发取货任务,任务号: {TaskNum}", task.RobotTaskNum); QuartzLogger.Info($"ExecuteAsync:满足取货条件,开始下发取货任务", latestState.RobotCrane?.DeviceName ?? ipAddress); // 发送取货指令 await HandlePutFinishedStateAsync(task, ipAddress); } @@ -236,7 +236,7 @@ // 组盘任务:放货需判断是否NG,如果NG则放到NG口 if (state.IsScanNG) { taskString = $"Putbattery,NG"; taskString = $"Putbattery,4"; } else { @@ -316,6 +316,11 @@ // 如果是组盘任务 if (task.RobotTaskType == RobotTaskTypeEnum.GroupPallet.GetHashCode()) { //if (!stateForUpdate.BatteryArrived) //{ // return; //} // 读取线体电芯条码 string trayBarcode1 = RobotBarcodeGenerator.GenerateTrayBarcode("DB40.990"); string trayBarcode2 = RobotBarcodeGenerator.GenerateTrayBarcode("DB40.1020"); @@ -331,15 +336,21 @@ // 条码重复,记录错误日志并停止后续操作(后续放货时会用到这些条码信息,供后续放货时使用,调试后可能会取消此逻辑) // 发送取货指令 标记扫码NG,放货时不使用这些条码,并放入NG口 await _taskProcessor.SendSocketRobotPickAsync(task, stateForUpdate, true); //await _taskProcessor.SendSocketRobotPickAsync(task, stateForUpdate, true); return; } else { _logger.LogInformation("HandlePutFinishedStateAsync:读取的托盘条码唯一,继续执行,任务号: {TaskNum}", task.RobotTaskNum); QuartzLogger.Info($"读取的托盘条码唯一,继续执行", stateForUpdate.RobotCrane.DeviceName); stateForUpdate.CellBarcode = new List<string>() { trayBarcode1,trayBarcode2 }; // 将条码添加到状态中,供后续放货时使用 stateForUpdate.CellBarcode.Add(trayBarcode1); stateForUpdate.CellBarcode.Add(trayBarcode2); //stateForUpdate.CellBarcode.Add(trayBarcode1); //stateForUpdate.CellBarcode.Add(trayBarcode2); } @@ -348,7 +359,7 @@ QuartzLogger.Info($"读取托盘条码成功: {trayBarcode1}+{trayBarcode2}", stateForUpdate.RobotCrane.DeviceName); // 发送取货指令 await _taskProcessor.SendSocketRobotPickAsync(task, stateForUpdate, false); await _taskProcessor.SendSocketRobotPickAsync(task, stateForUpdate); } else { @@ -358,7 +369,8 @@ // 发送取货指令 标记扫码NG,放货时不使用这些条码,并放入NG口 await _taskProcessor.SendSocketRobotPickAsync(task, stateForUpdate, true); //await _taskProcessor.SendSocketRobotPickAsync(task, stateForUpdate, true); return; } } else if (task.RobotTaskType == RobotTaskTypeEnum.ChangePallet.GetHashCode()) @@ -373,7 +385,7 @@ // 目标数量为48:直接走原有逻辑,不进入批次模式 if (targetNormalCount == targetTotal) { await _taskProcessor.SendSocketRobotPickAsync(task, stateForUpdate, false); await _taskProcessor.SendSocketRobotPickAsync(task, stateForUpdate); return; } @@ -542,7 +554,7 @@ else { // 非组盘任务,直接发送取货指令 await _taskProcessor.SendSocketRobotPickAsync(task, stateForUpdate, false); await _taskProcessor.SendSocketRobotPickAsync(task, stateForUpdate); } } } Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.Messaging.cs
@@ -59,6 +59,12 @@ break; } if(message == lastMessage) { // 重复消息,忽略 continue; } // 更新客户端状态 UpdateClientStatus(clientId, message); Code/WCS/WIDESEAWCS_Server/WIDESEAWCS_Tasks/SocketServer/TcpSocketServer.cs
@@ -136,6 +136,11 @@ public bool IsRunning { get; private set; } /// <summary> /// 上次接收消息源 /// </summary> public string lastMessage; /// <summary> /// 消息接收事件 /// </summary> /// <remarks> Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/WCS/TaskService_Inbound.cs
@@ -151,18 +151,18 @@ if (!updateLocationResult || !updateStockResult) return WebResponseContent.Instance.Error("任务完成失败"); // 调用MES托盘进站 var inboundRequest = new InboundInContainerRequest { EquipmentCode = "STK-GROUP-001", ResourceCode = "STK-GROUP-001", LocalTime = DateTime.Now, ContainerCode = taskDto.PalletCode }; var inboundResult = _mesService.InboundInContainer(inboundRequest); if (inboundResult == null || inboundResult.Data == null || !inboundResult.Data.IsSuccess) { return content.Error($"任务完成失败:MES进站失败: {inboundResult?.Data?.Msg ?? inboundResult?.ErrorMessage ?? "未知错误"}"); } //var inboundRequest = new InboundInContainerRequest //{ // EquipmentCode = "STK-GROUP-001", // ResourceCode = "STK-GROUP-001", // LocalTime = DateTime.Now, // ContainerCode = taskDto.PalletCode //}; //var inboundResult = _mesService.InboundInContainer(inboundRequest); //if (inboundResult == null || inboundResult.Data == null || !inboundResult.Data.IsSuccess) //{ // return content.Error($"任务完成失败:MES进站失败: {inboundResult?.Data?.Msg ?? inboundResult?.ErrorMessage ?? "未知错误"}"); //} return await CompleteTaskAsync(task, "入库完成"); }); } Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/WCS/TaskService_Robot.cs
@@ -129,9 +129,9 @@ Creater = "system" }; var result = await Repository.AddDataAsync(task) > 0; if (!result) return WebResponseContent.Instance.Error($"机械手{taskName}任务创建失败"); //var result = await Repository.AddDataAsync(task) > 0; //if (!result) // return WebResponseContent.Instance.Error($"机械手{taskName}任务创建失败"); var wmstaskDto = _mapper.Map<WMSTaskDTO>(task) ?? new WMSTaskDTO(); wmstaskDto.TaskQuantity = stock.Details?.Sum(d => d.Quantity) ?? 0;