fix(WCS): 修复输送线任务处理逻辑并更新设备映射
修复输送线任务处理中的目标地址选择逻辑,改为直接检查CV_State状态并设置Target值
更新入库站台设备映射列表,添加新地址2125
修改RobotSelect.vue中的参数名从robotCode改为DeviceName
优化日志记录格式,移除冗余信息
更新HttpResponseResult.cs添加JsonIgnore属性避免序列化异常
修改开发环境API基础URL配置
| | |
| | | "total_spawned": 144, |
| | | "total_completed": 166, |
| | | "total_failed": 0, |
| | | "last_updated": "2026-04-21T11:39:09.704Z" |
| | | "last_updated": "2026-04-21T13:08:04.028Z" |
| | | } |
| | |
| | | using System.Linq; |
| | | using System.Net; |
| | | using System.Text; |
| | | using System.Text.Json.Serialization; |
| | | using System.Threading.Tasks; |
| | | |
| | | namespace WIDESEA_Core |
| | |
| | | public string ErrorMessage { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 异常信息 |
| | | /// 异常信息(不参与JSON序列化,因Exception.TargetSite类型无法被System.Text.Json序列化) |
| | | /// </summary> |
| | | [JsonIgnore] |
| | | public Exception Exception { get; set; } |
| | | |
| | | /// <summary> |
| | |
| | | private readonly ILogger _logger; |
| | | |
| | | /// <summary> |
| | | /// 目标地址到设备类型的映射 |
| | | /// 目标地址到设备类型的映射(入库站台) |
| | | /// </summary> |
| | | /// <remarks> |
| | | /// </remarks> |
| | | private static List<string> AddressToDeviceType = new List<string> { "11020", "11028" }; |
| | | private static List<string> AddressToDeviceType = new List<string> { "11020", "11028", "2125" }; |
| | | |
| | | /// <summary> |
| | | /// 托盘检查位置的最近执行时间(用于30秒间隔限制) |
| | |
| | | using WIDESEAWCS_ITaskInfoService; |
| | | using WIDESEAWCS_Model.Models; |
| | | using WIDESEAWCS_QuartzJob; |
| | | using WIDESEAWCS_QuartzJob.Models; |
| | | using WIDESEAWCS_QuartzJob.Service; |
| | | |
| | | namespace WIDESEAWCS_Tasks |
| | |
| | | { |
| | | // 清除任务号,表示当前空闲 |
| | | conveyorLine.SetValue(ConveyorLineDBNameNew.TaskNo, 0, childDeviceCode); |
| | | QuartzLogHelper.LogDebug(_logger, "HeartBeat:子设备 {ChildDeviceCode} 心跳", $"HeartBeat:子设备 {childDeviceCode} 心跳", conveyorLine.DeviceCode, childDeviceCode); |
| | | QuartzLogHelper.LogDebug(_logger, $"HeartBeat:子设备 {childDeviceCode} 心跳", conveyorLine.DeviceCode); |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | /// <param name="childDeviceCode">子设备编码</param> |
| | | public void RequestInbound(CommonConveyorLine conveyorLine, ConveyorLineTaskCommandNew command, string childDeviceCode) |
| | | { |
| | | QuartzLogHelper.LogInfo(_logger, "RequestInbound:子设备 {ChildDeviceCode} 请求入库", $"请求入库,子设备: {childDeviceCode}", conveyorLine.DeviceCode, childDeviceCode); |
| | | QuartzLogHelper.LogInfo(_logger, $"请求入库,子设备: {childDeviceCode}", conveyorLine.DeviceCode); |
| | | |
| | | // 向 WMS 请求新任务(基于条码) |
| | | if (_taskFilter.RequestWmsTask(command.Barcode, childDeviceCode)) |
| | |
| | | // 更新任务状态到下一阶段 |
| | | _taskService.UpdateTaskStatusToNext(task); |
| | | |
| | | QuartzLogHelper.LogInfo(_logger, "RequestInbound:入库任务已下发,任务号: {TaskNum},子设备: {ChildDeviceCode}", $"入库任务已下发,任务号: {task.TaskNum},子设备: {childDeviceCode}", conveyorLine.DeviceCode, task.TaskNum, childDeviceCode); |
| | | QuartzLogHelper.LogInfo(_logger, $"入库任务已下发,任务号: {task.TaskNum},子设备: {childDeviceCode}", conveyorLine.DeviceCode); |
| | | } |
| | | } |
| | | } |
| | |
| | | Dt_Task? task = _taskFilter.QueryExecutingTask(command.TaskNo, childDeviceCode); |
| | | if (task == null) |
| | | { |
| | | QuartzLogHelper.LogDebug(_logger, "RequestInNextAddress:任务 {TaskNo} 不存在", $"RequestInNextAddress:任务 {command.TaskNo} 不存在", conveyorLine.DeviceCode, command.TaskNo); |
| | | QuartzLogHelper.LogDebug(_logger, $"RequestInNextAddress:任务 {command.TaskNo} 不存在", conveyorLine.DeviceCode); |
| | | return; |
| | | } |
| | | |
| | | QuartzLogHelper.LogInfo(_logger, "RequestInNextAddress:入库下一地址,任务号: {TaskNum},子设备: {ChildDeviceCode}", $"RequestInNextAddress:入库下一地址,任务号: {task.TaskNum},子设备: {childDeviceCode}", conveyorLine.DeviceCode, task.TaskNum, childDeviceCode); |
| | | QuartzLogHelper.LogInfo(_logger, $"RequestInNextAddress:入库下一地址,任务号: {task.TaskNum},子设备: {childDeviceCode}", conveyorLine.DeviceCode); |
| | | |
| | | // 如果不是空托盘任务,处理目标地址(与拘束机/插拔钉机交互) |
| | | if (task.TaskType != (int)TaskOutboundTypeEnum.OutEmpty) |
| | | { |
| | | _targetAddressSelector.HandleInboundNextAddress(conveyorLine, task.NextAddress, childDeviceCode); |
| | | } |
| | | //// 如果不是空托盘任务,处理目标地址 |
| | | //if (task.TaskType != (int)TaskOutboundTypeEnum.OutEmpty) |
| | | //{ |
| | | |
| | | Dt_Router routers = _routerService.QueryNextRoute(task.NextAddress, task.TargetAddress); |
| | | if (routers == null) throw new Exception($"未找到设备路由信息"); |
| | | |
| | | _targetAddressSelector.HandleInboundNextAddress(conveyorLine, routers.ChildPosi, childDeviceCode); |
| | | //} |
| | | |
| | | // 更新任务当前位置 |
| | | _ = _taskService.UpdatePosition(task.TaskNum, task.CurrentAddress); |
| | |
| | | { |
| | | // 回复 ACK 确认 |
| | | conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)1, childDeviceCode); |
| | | QuartzLogHelper.LogInfo(_logger, "ConveyorLineInFinish:入库完成,任务号: {TaskNum},子设备: {ChildDeviceCode}", $"入库完成,任务号: {task.TaskNum}", conveyorLine.DeviceCode, task.TaskNum, childDeviceCode); |
| | | QuartzLogHelper.LogInfo(_logger, $"入库完成,任务号: {task.TaskNum},子设备:{childDeviceCode}", conveyorLine.DeviceCode); |
| | | } |
| | | } |
| | | } |
| | |
| | | Dt_Task? task = _taskFilter.QueryExecutingTask(command.TaskNo, childDeviceCode); |
| | | if (task == null) |
| | | { |
| | | QuartzLogHelper.LogDebug(_logger, "RequestOutNextAddress:任务 {TaskNo} 不存在", $"RequestOutNextAddress:任务 {command.TaskNo} 不存在", conveyorLine.DeviceCode, command.TaskNo); |
| | | QuartzLogHelper.LogDebug(_logger, $"RequestOutNextAddress:任务 {command.TaskNo} 不存在", conveyorLine.DeviceCode); |
| | | return; |
| | | } |
| | | |
| | | QuartzLogHelper.LogInfo(_logger, "RequestOutNextAddress:出库下一地址,任务号: {TaskNum},子设备: {ChildDeviceCode}", $"RequestOutNextAddress:出库下一地址,任务号: {task.TaskNum},子设备: {childDeviceCode}", conveyorLine.DeviceCode, task.TaskNum, childDeviceCode); |
| | | QuartzLogHelper.LogInfo(_logger, $"RequestOutNextAddress:出库下一地址,任务号: {task.TaskNum},子设备: {childDeviceCode}", conveyorLine.DeviceCode); |
| | | |
| | | // 如果不是空托盘任务,处理目标地址 |
| | | if (task.TaskType != (int)TaskOutboundTypeEnum.OutEmpty) |
| | | { |
| | | _targetAddressSelector.HandleOutboundNextAddress(conveyorLine, task.NextAddress, childDeviceCode); |
| | | } |
| | | //if (task.TaskType != (int)TaskOutboundTypeEnum.OutEmpty) |
| | | //{ |
| | | Dt_Router routers = _routerService.QueryNextRoute(task.NextAddress, task.TargetAddress); |
| | | if (routers == null) throw new Exception($"未找到设备路由信息"); |
| | | |
| | | _targetAddressSelector.HandleOutboundNextAddress(conveyorLine, routers.ChildPosi, childDeviceCode); |
| | | //} |
| | | |
| | | // 更新任务当前位置 |
| | | _ = _taskService.UpdatePosition(task.TaskNum, task.CurrentAddress); |
| | |
| | | conveyorLine.SetValue(ConveyorLineDBNameNew.WCS_ACK, (short)1, childDeviceCode); |
| | | } |
| | | |
| | | QuartzLogHelper.LogInfo(_logger, "ConveyorLineOutFinish:出库完成,完成结果:{Status},任务号: {TaskNum},子设备: {ChildDeviceCode},错误消息: {Message}", $"出库完成,完成结果:{content.Status},任务号: {task.TaskNum},错误消息:{content.Message}", conveyorLine.DeviceCode, content.Status, task.TaskNum, childDeviceCode, content.Message); |
| | | QuartzLogHelper.LogInfo(_logger, $"出库完成,完成结果:{content.Status},任务号: {task.TaskNum},错误消息:{content.Message}", conveyorLine.DeviceCode); |
| | | } |
| | | } |
| | | } |
| | |
| | | // 记录入库场景的调试日志,包含子设备和目标地址信息 |
| | | WriteDebug(conveyorLine, "入库下一地址", childDeviceCode, nextAddress); |
| | | // 委托通用处理方法,入库对应上层(isUpper: true) |
| | | HandleDeviceRequest(conveyorLine, nextAddress, childDeviceCode, Layer.Upper); |
| | | //HandleDeviceRequest(conveyorLine, nextAddress, childDeviceCode, Layer.Upper); |
| | | |
| | | var cvState = conveyorLine.GetValue<ConveyorLineDBNameNew, byte>(ConveyorLineDBNameNew.CV_State, nextAddress); |
| | | bool isAvailable = cvState == 2; |
| | | if (isAvailable) |
| | | { |
| | | conveyorLine.SetValue(ConveyorLineDBNameNew.Target, Convert.ToInt16(nextAddress), childDeviceCode); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | // 记录出库场景的调试日志,包含子设备和目标地址信息 |
| | | WriteDebug(conveyorLine, "出库下一地址", childDeviceCode, nextAddress); |
| | | // 委托通用处理方法,出库对应下层(isUpper: false) |
| | | HandleDeviceRequest(conveyorLine, nextAddress, childDeviceCode, Layer.Lower); |
| | | //HandleDeviceRequest(conveyorLine, nextAddress, childDeviceCode, Layer.Lower); |
| | | |
| | | var cvState = conveyorLine.GetValue<ConveyorLineDBNameNew, byte>(ConveyorLineDBNameNew.CV_State, nextAddress); |
| | | bool isAvailable = cvState == 2; |
| | | if (isAvailable) |
| | | { |
| | | conveyorLine.SetValue(ConveyorLineDBNameNew.Target, Convert.ToInt16(nextAddress), childDeviceCode); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | CommonConveyorLine conveyorLine = (CommonConveyorLine)device; |
| | | |
| | | // 读取 CV_State,CV_State == 2 表示空闲 |
| | | byte cvState = conveyorLine.GetValue<ConveyorLineStatus, byte>(ConveyorLineStatus.CV_State, task.TargetAddress); |
| | | byte cvState = conveyorLine.GetValue<ConveyorLineDBNameNew, byte>(ConveyorLineDBNameNew.CV_State, task.TargetAddress); |
| | | bool isAvailable = cvState == 2; |
| | | QuartzLogHelper.LogInfo(_logger, "IsTargetAddressConveyorStationAvailable:TargetAddress: {TargetAddress},CV_State: {CV_State},是否空闲: {IsAvailable},任务号: {TaskNum}", |
| | | $"IsTargetAddressConveyorStationAvailable:TargetAddress: {task.TargetAddress},CV_State: {cvState},是否空闲: {isAvailable}", task.Roadway, task.TargetAddress, cvState, isAvailable, task.TaskNum); |
| | |
| | | let loadingInstance; |
| | | let loadingStatus = false; |
| | | if (process.env.NODE_ENV == 'development') { |
| | | axios.defaults.baseURL = window.webConfig.webApiProduction; |
| | | axios.defaults.baseURL = window.webConfig.webApiBaseUrl; |
| | | } |
| | | else if (process.env.NODE_ENV == 'debug') { |
| | | axios.defaults.baseURL = window.webConfig.webApiBaseUrl; |
| | |
| | | |
| | | const result = await this.http.post("/api/StockInfoDetail/BindContainer", { |
| | | palletCode: this.currentRow.palletCode, |
| | | robotCode: this.selectedRobot |
| | | DeviceName: this.selectedRobot |
| | | }, "正在调用MES接口..."); |
| | | |
| | | if (result.status) { |
| | |
| | | |
| | | const result = await this.http.post("/api/StockInfoDetail/UnbindContainer", { |
| | | palletCode: this.currentRow.palletCode, |
| | | robotCode: this.selectedRobot |
| | | DeviceName: this.selectedRobot |
| | | }, "正在调用MES接口..."); |
| | | |
| | | if (result.status) { |
| | |
| | | using System.Linq; |
| | | using System.Net; |
| | | using System.Text; |
| | | using System.Text.Json.Serialization; |
| | | using System.Threading.Tasks; |
| | | |
| | | namespace WIDESEA_Core |
| | |
| | | public string ErrorMessage { get; set; } |
| | | |
| | | /// <summary> |
| | | /// 异常信息 |
| | | /// 异常信息(不参与JSON序列化,因Exception.TargetSite类型无法被System.Text.Json序列化) |
| | | /// </summary> |
| | | [JsonIgnore] |
| | | public Exception Exception { get; set; } |
| | | |
| | | /// <summary> |
| | |
| | | "MainDB": "DB_WIDESEA", //当前项目的主库,所对应的连接字符串的Enabled必须为true |
| | | //连接字符串 |
| | | //"ConnectionString": "HTI6FB1H05Krd07mNm9yBCNhofW6edA5zLs9TY~MNthRYW3kn0qKbMIsGp~3yyPDF1YZUCPBQx8U0Jfk4PH~ajNFXVIwlH85M3F~v_qKYQ3CeAz3q1mLVDn8O5uWt1~3Ut2V3KRkEwYHvW2oMDN~QIDXPxDgXN0R2oTIhc9dNu7QNaLEknblqmHhjaNSSpERdDVZIgHnMKejU_SL49tralBkZmDNi0hmkbL~837j1NWe37u9fJKmv91QPb~16JsuI9uu0EvNZ06g6PuZfOSAeFH9GMMIZiketdcJG3tHelo=", |
| | | "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=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数据库连接 |