Files
WCS/Plugins/Wcs/Plugin.Cowain.Wcs/Services/RgvTaskService.cs

637 lines
27 KiB
C#
Raw Normal View History

2026-03-02 09:13:29 +08:00
using Cowain.Base.DBContext;
using Cowain.Base.Models;
using Cowain.Base.Services;
using HslCommunication.Core;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Plugin.Cowain.Driver.Abstractions;
using Plugin.Cowain.Wcs.Actions;
using Plugin.Cowain.Wcs.IServices;
using Plugin.Cowain.Wcs.Models;
using Plugin.Cowain.Wcs.Models.Dto;
using Plugin.Cowain.Wcs.Models.Enum;
using Plugin.Cowain.Wcs.ViewModels;
using System.Text;
namespace Plugin.Cowain.Wcs.Services;
2026-03-02 10:56:30 +08:00
public class RgvToWcsData
{
public short Command { get; set; }
public short Count { get; set; }
public short Result { get; set; }
public int TaskId { get; set; }
}
2026-03-02 09:13:29 +08:00
public class WcsToRgvData
{
public short Command { get; set; }
public short Count { get; set; }
public int TaskId { get; set; }
2026-03-02 10:56:30 +08:00
public short FromStation1 { get; set; }
public short FromStation2 { get; set; }
public short ToStation1 { get; set; }
public short ToStation2 { get; set; }
public string QrCode1 { get; set; } = string.Empty;
public string QrCode2 { get; set; } = string.Empty;
2026-03-02 09:13:29 +08:00
}
2026-03-02 10:56:30 +08:00
2026-03-02 09:13:29 +08:00
public class RgvTaskService : BaseService, IRgvTaskService
{
private IServiceScopeFactory _scopeFactory;
private IDeviceMonitor _deviceMonitor;
private readonly ILogger<RgvTaskService> _logger;
2026-03-02 10:56:30 +08:00
public RgvTaskService(IDbContextFactory<SqlDbContext> dbContextFactory, IDeviceMonitor deviceMonitor, IServiceScopeFactory scopeFactory, ILogger<RgvTaskService> logger) : base(dbContextFactory)
2026-03-02 09:13:29 +08:00
{
_scopeFactory = scopeFactory;
_deviceMonitor = deviceMonitor;
_logger = logger;
}
public List<RgvActionViewModel>? ActionToList(string action)
{
try
{
var actions = JsonConvert.DeserializeObject<List<string>>(action) ?? [];
var rgvActionViewModels = actions
.Select((name, i) => new RgvActionViewModel { Id = i + 1, Name = name })
.ToList();
rgvActionViewModels.Insert(0, new RgvActionViewModel { Id = 0, Name = RgvCommandEnum.UnKnown.ToString() });
return rgvActionViewModels;
}
catch (Exception ex)
{
_logger.LogError(ex, "反序列化失败");
return null;
}
}
public RgvCommandEnum GetStepAction(List<RgvActionViewModel> actions, int step)
{
var name = actions.FirstOrDefault(x => x.Id == step)?.Name;
return Enum.TryParse(name, out RgvCommandEnum cmd) ? cmd : RgvCommandEnum.UnKnown;
}
public async Task<ResultModel> FinishTaskAsync(int id)
{
if (id <= 0)
{
return ResultModel.Error("id不能小于0");
}
2026-03-02 10:56:30 +08:00
using var dbContext = _dbContextFactory.CreateDbContext();
var DbSet = dbContext.GetDbSet<TaskDataDto>();
2026-03-02 09:13:29 +08:00
var existingModel = await DbSet.FirstOrDefaultAsync(x => x.Id == id);
if (existingModel == null)
{
return ResultModel.Error("Taskid不存在");
}
existingModel.IsFinished = true;
2026-03-02 10:56:30 +08:00
int count = await dbContext.SaveChangesAsync();
2026-03-02 09:13:29 +08:00
return count > 0 ? ResultModel.Success("Task直接更新为结束") : ResultModel.Error("Task直接更新为结束失败");
}
public async Task<List<TaskViewModel>> GetAllAsync()
{
2026-03-02 10:56:30 +08:00
using var dbContext = _dbContextFactory.CreateDbContext();
var DbSet = dbContext.GetDbSet<TaskDataDto>();
2026-03-02 09:13:29 +08:00
var data = await DbSet.ToListAsync();
return new List<TaskViewModel>(data.Select(x => new TaskViewModel
{
Id = x.Id,
ProcessId = x.ProcessId,
ProcessName = x.ProcessName,
Priority = x.Priority,
2026-03-02 10:56:30 +08:00
FromStationId1 = x.FromStationId1,
ToStationId1 = x.ToStationId1,
FromStatus1 = x.FromStatus1,
ToStatus1 = x.ToStatus1,
FromStationId2 = x.FromStationId2,
ToStationId2 = x.ToStationId2,
FromStatus2 = x.FromStatus2,
ToStatus2 = x.ToStatus2,
2026-03-02 09:13:29 +08:00
CreatTime = x.CreateTime,
IsFinished = x.IsFinished,
ExecuteAction = x.ExecuteAction,
FinishedTime = x.FinishedTime,
2026-03-02 10:56:30 +08:00
QrCode1 = x.QrCode1,
QrCode2 = x.QrCode2,
2026-03-02 09:13:29 +08:00
Action = x.Action
}));
}
public async Task<(List<TaskViewModel>, int totals)> GetAllAsync(int pageIndex, int pageSize)
{
2026-03-02 10:56:30 +08:00
using var dbContext = _dbContextFactory.CreateDbContext();
var DbSet = dbContext.GetDbSet<TaskDataDto>();
2026-03-02 09:13:29 +08:00
// 按照CreateTime倒序排列最新的任务排第一个
2026-03-02 10:56:30 +08:00
var data = await DbSet.OrderByDescending(x => x.Id).ToListAsync();
2026-03-02 09:13:29 +08:00
var list = data.Skip((pageIndex - 1) * pageSize).Take(pageSize);
var ret = new List<TaskViewModel>(list.Select(x => new TaskViewModel
{
Id = x.Id,
ProcessId = x.ProcessId,
ProcessName = x.ProcessName,
Priority = x.Priority,
2026-03-02 10:56:30 +08:00
FromStationId1 = x.FromStationId1,
ToStationId1 = x.ToStationId1,
FromStatus1 = x.FromStatus1,
ToStatus1 = x.ToStatus1,
FromStationId2 = x.FromStationId2,
ToStationId2 = x.ToStationId2,
FromStatus2 = x.FromStatus2,
ToStatus2 = x.ToStatus2,
2026-03-02 09:13:29 +08:00
CreatTime = x.CreateTime,
IsFinished = x.IsFinished,
ExecuteAction = x.ExecuteAction,
FinishedTime = x.FinishedTime,
2026-03-02 10:56:30 +08:00
QrCode1 = x.QrCode1,
QrCode2 = x.QrCode2,
Action = x.Action
2026-03-02 09:13:29 +08:00
//Actions = new(ActionToList(x.Action) ?? new List<RgvActionViewModel>())
}));
return (ret, data.Count());
}
public async Task<ResultModel<RgvCommandModel>> GetRgvCommandAsync(RgvUpdateInfoModel? infoModel)
{
RgvCommandModel? rgvCommand = null;
if (infoModel == null)
{
return ResultModel<RgvCommandModel>.Error("RgvUpdateInfoModel不能为空");
}
using var scope = _scopeFactory.CreateScope();
var dBContext = scope.ServiceProvider.GetRequiredService<SqlDbContext>();
var taskSet = dBContext.GetDbSet<TaskDataDto>();
var unfinishedTask = await taskSet.AsNoTracking().FirstOrDefaultAsync(t => !t.IsFinished);
if (unfinishedTask == null)
{
_logger.LogInformation($"没有找到在执行的任务,不需要处理");
return ResultModel<RgvCommandModel>.Error("没有找到在执行的任务,不需要处理");
}
2026-03-02 10:56:30 +08:00
var actionResult = ActionToList(unfinishedTask.Action); //转换动作列表
if (actionResult == null)
{
_logger.LogError($"工艺未配置Action请修改taskId={unfinishedTask.Id}");
return ResultModel<RgvCommandModel>.Error($"工艺未配置Action请修改taskId={unfinishedTask.Id}");
}
var actions = actionResult;
2026-03-02 09:13:29 +08:00
int step = 0;
if (infoModel.Source == RgvUpdateSourceEnum.PLC)
{
if (infoModel.RetResult == 2)
{
2026-03-02 10:56:30 +08:00
_logger.LogError($"PLC反馈结果是NG,任务id={unfinishedTask.Id}");
2026-03-02 09:13:29 +08:00
return ResultModel<RgvCommandModel>.Error($"PLC反馈结果是NG,任务id={unfinishedTask.Id}");
}
else if (infoModel.TaskId != unfinishedTask.Id)
{
2026-03-02 10:56:30 +08:00
_logger.LogError($"PLC反馈结果任务号不匹配plc任务号={infoModel.TaskId},执行任务id={unfinishedTask.Id}");
2026-03-02 09:13:29 +08:00
return ResultModel<RgvCommandModel>.Error($"PLC反馈结果任务号不匹配plc任务号={infoModel.TaskId},执行任务id={unfinishedTask.Id}");
}
step = unfinishedTask.ExecuteAction;
}
else if (infoModel.Source == RgvUpdateSourceEnum.First)
{
step = 0;
}
else if (infoModel.Source == RgvUpdateSourceEnum.User)
{
//手动下发的任务
if (infoModel.ExecuteAction > 0)
{
step = infoModel.ExecuteAction - 1;
2026-03-02 10:56:30 +08:00
_logger.LogInformation($"手动下发任务,执行任务id={unfinishedTask.Id}:{GetStepAction(actions, step).ToString()}");
2026-03-02 09:13:29 +08:00
}
else
{
2026-03-02 10:56:30 +08:00
_logger.LogError($"手动选择的动作不能为0");
2026-03-02 09:13:29 +08:00
return ResultModel<RgvCommandModel>.Error($"手动选择的动作不能为0");
}
}
try
{
var stationService = scope.ServiceProvider.GetRequiredService<IStationService>();
var stationTaskHandler = scope.ServiceProvider.GetRequiredService<IEnumerable<IHostedService>>();
var stationQueueHostedService = stationTaskHandler.OfType<StationQueueHostedService>().FirstOrDefault();
var stations = await stationService.GetAllAsync();
2026-03-02 10:56:30 +08:00
var fromStation1 = stations.FirstOrDefault(x => x.Id == unfinishedTask.FromStationId1);
if (fromStation1 == null)
{
return ResultModel<RgvCommandModel>.Error($"From1工站不存在工站Id={unfinishedTask.FromStationId1}");
}
var toStation1 = stations.FirstOrDefault(x => x.Id == unfinishedTask.ToStationId1);
if (toStation1 == null)
{
return ResultModel<RgvCommandModel>.Error($"To1工站不存在工站Id={unfinishedTask.ToStationId1}");
}
var fromStation2 = stations.FirstOrDefault(x => x.Id == unfinishedTask.FromStationId2);
if (unfinishedTask.FromStationId2 > 0 && fromStation2 == null)
2026-03-02 09:13:29 +08:00
{
2026-03-02 10:56:30 +08:00
return ResultModel<RgvCommandModel>.Error($"From2工站不存在工站Id={unfinishedTask.FromStationId2}");
2026-03-02 09:13:29 +08:00
}
2026-03-02 10:56:30 +08:00
var toStation2 = stations.FirstOrDefault(x => x.Id == unfinishedTask.ToStationId2);
if (unfinishedTask.ToStationId2 > 0 && toStation2 == null)
2026-03-02 09:13:29 +08:00
{
2026-03-02 10:56:30 +08:00
return ResultModel<RgvCommandModel>.Error($"To2站不存在工站Id={unfinishedTask.ToStationId2}");
2026-03-02 09:13:29 +08:00
}
//数据库存储的是上一步
var stepCommand = GetStepAction(actions, step); //获取上一步动作
var nextCommand = GetStepAction(actions, step + 1); //获取下一步动作
if (infoModel.Source == RgvUpdateSourceEnum.PLC)
{
if (infoModel.RetCmd != (int)stepCommand)
{
2026-03-02 10:56:30 +08:00
_logger.LogError($"PLC反馈动作不正确PLC动作{infoModel.RetCmd},实际动作{(int)stepCommand}");
2026-03-02 09:13:29 +08:00
return ResultModel<RgvCommandModel>.Error($"PLC反馈动作不正确PLC动作{infoModel.RetCmd},实际动作{(int)stepCommand}");
}
}
if (stepCommand == RgvCommandEnum.UnKnown && nextCommand == RgvCommandEnum.UnKnown)
{
2026-03-02 10:56:30 +08:00
_logger.LogError($"获取RGV命令失败配置有误");
2026-03-02 09:13:29 +08:00
return ResultModel<RgvCommandModel>.Error("获取RGV命令失败配置有误");
}
2026-03-02 10:56:30 +08:00
rgvCommand = new RgvCommandModel
2026-03-02 09:13:29 +08:00
{
2026-03-02 10:56:30 +08:00
Command = nextCommand,
TaskId = unfinishedTask.Id,
FromPos1 = fromStation1.StationPos,
FromPos2 = fromStation2?.StationPos ?? 0,
TargetPos1 = toStation1.StationPos,
TargetPos2 = toStation2?.StationPos ?? 0,
QrCode1 = unfinishedTask.QrCode1,
QrCode2 = unfinishedTask.QrCode2
};
2026-03-02 09:13:29 +08:00
var processService = scope.ServiceProvider.GetRequiredService<IProcessService>();
var getJson = await processService.GetJsonData(unfinishedTask.ProcessId);
string? rgvName = string.Empty;
if (getJson != null)
{
rgvName = getJson.Data!.RgvName;
}
//更新RGV
2026-03-02 10:56:30 +08:00
if (stepCommand == RgvCommandEnum.MoveFrom)
2026-03-02 09:13:29 +08:00
{
2026-03-02 10:56:30 +08:00
//更新rgv的目标位置
var rgvService = scope.ServiceProvider.GetRequiredService<IRgvService>();
var rgvs = await rgvService.GetAllAsync();
if (rgvs != null)
2026-03-02 09:13:29 +08:00
{
2026-03-02 10:56:30 +08:00
var rgv = rgvs.FirstOrDefault(x => x.StationName == rgvName);
if (rgv != null)
2026-03-02 09:13:29 +08:00
{
2026-03-02 10:56:30 +08:00
rgv.LayOutX = fromStation1.LayOutX;
await rgvService.UpdateAsync(rgv);
2026-03-02 09:13:29 +08:00
}
}
2026-03-02 10:56:30 +08:00
}
else if (stepCommand == RgvCommandEnum.MoveTo)
{
//更新rgv的目标位置
var rgvService = scope.ServiceProvider.GetRequiredService<IRgvService>();
var rgvs = await rgvService.GetAllAsync();
if (rgvs != null)
2026-03-02 09:13:29 +08:00
{
2026-03-02 10:56:30 +08:00
var rgv = rgvs.FirstOrDefault(x => x.StationName == rgvName);
if (rgv != null)
2026-03-02 09:13:29 +08:00
{
2026-03-02 10:56:30 +08:00
rgv.LayOutX = toStation1.LayOutX;
await rgvService.UpdateAsync(rgv);
2026-03-02 09:13:29 +08:00
}
}
}
//更新工站状态
2026-03-02 10:56:30 +08:00
if (stepCommand == RgvCommandEnum.UnKnown && nextCommand != RgvCommandEnum.UnKnown)
{
//【1】上一步未知任务刚开始
fromStation1.UpdateSource = StationUpdateSourceEnum.Task;
fromStation1.Status = StationStateEnum.Picking.ToString();
toStation1.UpdateSource = StationUpdateSourceEnum.Task;
toStation1.Status = StationStateEnum.Placing.ToString();
stationQueueHostedService?.Enqueue(fromStation1);
stationQueueHostedService?.Enqueue(toStation1);
if (fromStation2 != null)
{
fromStation2.UpdateSource = StationUpdateSourceEnum.Task;
fromStation2.Status = StationStateEnum.Picking.ToString();
stationQueueHostedService?.Enqueue(fromStation2);
}
if (toStation2 != null)
{
toStation2.UpdateSource = StationUpdateSourceEnum.Task;
toStation2.Status = StationStateEnum.Placing.ToString();
stationQueueHostedService?.Enqueue(toStation2);
}
2026-03-02 09:13:29 +08:00
//任务刚开始更新Rgv
var rgvService = scope.ServiceProvider.GetRequiredService<IRgvService>();
var rgvs = await rgvService.GetAllAsync();
if (rgvs != null)
{
var rgv = rgvs.FirstOrDefault(x => x.StationName == rgvName);
if (rgv != null)
{
2026-03-02 10:56:30 +08:00
rgv.FromStationId1 = fromStation1.Id;
rgv.ToStationId1 = toStation1.Id;
rgv.FromStationId2 = fromStation2?.Id ?? 0;
rgv.ToStationId2 = toStation2?.Id ?? 0;
2026-03-02 09:13:29 +08:00
rgv.ProcessName = unfinishedTask.ProcessName;
await rgvService.UpdateAsync(rgv);
}
}
}
2026-03-02 10:56:30 +08:00
else if (nextCommand == RgvCommandEnum.Place)
2026-03-02 09:13:29 +08:00
{
//【2】下一步要放料将源QR复制到目标QR
2026-03-02 10:56:30 +08:00
toStation1.UpdateSource = StationUpdateSourceEnum.Task;
toStation1.QrCode = fromStation1.QrCode;
stationQueueHostedService?.Enqueue(toStation1);
if (fromStation2 != null && toStation2 != null)
{
toStation2.UpdateSource = StationUpdateSourceEnum.Task;
toStation2.QrCode = fromStation2.QrCode;
stationQueueHostedService?.Enqueue(toStation2);
}
}
else if (stepCommand == RgvCommandEnum.Pick && nextCommand != RgvCommandEnum.Pick)
{
//【3】取料完成
fromStation1.UpdateSource = StationUpdateSourceEnum.Task;
fromStation1.Status = StationStateEnum.PickFinished.ToString();
stationQueueHostedService?.Enqueue(fromStation1);
2026-03-02 09:13:29 +08:00
2026-03-02 10:56:30 +08:00
if (fromStation2 != null)
{
fromStation2.UpdateSource = StationUpdateSourceEnum.Task;
fromStation2.Status = StationStateEnum.PickFinished.ToString();
stationQueueHostedService?.Enqueue(fromStation2);
}
2026-03-02 09:13:29 +08:00
}
2026-03-02 10:56:30 +08:00
else if (stepCommand == RgvCommandEnum.Place && nextCommand != RgvCommandEnum.Place)
2026-03-02 09:13:29 +08:00
{
2026-03-02 10:56:30 +08:00
//【4】放料完成任务结束
toStation1.UpdateSource = StationUpdateSourceEnum.Task;
toStation1.Status = StationStateEnum.PlaceFinished.ToString();
stationQueueHostedService?.Enqueue(toStation1);
if (toStation2 != null)
{
toStation2.UpdateSource = StationUpdateSourceEnum.Task;
toStation2.Status = StationStateEnum.PlaceFinished.ToString();
stationQueueHostedService?.Enqueue(toStation2);
}
2026-03-02 09:13:29 +08:00
var rgvService = scope.ServiceProvider.GetRequiredService<IRgvService>();
var rgvs = await rgvService.GetAllAsync();
if (rgvs != null)
{
var rgv = rgvs.FirstOrDefault(x => x.StationName == rgvName);
if (rgv != null)
{
2026-03-02 10:56:30 +08:00
rgv.FromStationId1 = 0;
rgv.ToStationId1 = 0;
rgv.FromStationId2 = 0;
rgv.ToStationId2 = 0;
2026-03-02 09:13:29 +08:00
rgv.ProcessName = "";
await rgvService.UpdateAsync(rgv);
}
}
}
int save = 0;
2026-03-02 10:56:30 +08:00
if (stepCommand == RgvCommandEnum.Place && nextCommand == RgvCommandEnum.UnKnown)
2026-03-02 09:13:29 +08:00
{
2026-03-02 10:56:30 +08:00
//任务结束
2026-03-02 09:13:29 +08:00
unfinishedTask.IsFinished = true;
unfinishedTask.FinishedTime = DateTime.Now;
// 手动将实体状态标记为Modified
dBContext.Entry(unfinishedTask).State = EntityState.Modified;
save = await dBContext.SaveChangesAsync();
if (save > 0)
{
_logger.LogInformation($"任务完成任务id={unfinishedTask.Id}");
}
}
else
{
rgvCommand.TaskId = unfinishedTask.Id;
unfinishedTask.ExecuteAction = step + 1;
// 手动将实体状态标记为Modified
dBContext.Entry(unfinishedTask).State = EntityState.Modified;
save = await dBContext.SaveChangesAsync();
if (save > 0)
{
_logger.LogInformation($"任务继续任务id={unfinishedTask.Id},动作={JsonConvert.SerializeObject(rgvCommand)}");
}
}
if (save > 0)
{
return ResultModel<RgvCommandModel>.Success(rgvCommand);
}
else
{
return ResultModel<RgvCommandModel>.Error($"任务更新异常任务id={unfinishedTask.Id}");
}
}
catch (Exception ex)
{
_logger.LogError(ex, $"任务异常任务id={unfinishedTask.Id}");
return ResultModel<RgvCommandModel>.Error($"任务异常任务id={unfinishedTask.Id}");
}
}
public async Task<ResultModel> ExecuteAsync(string? actionParam, RgvUpdateSourceEnum source, int? execute = 0)
{
if (string.IsNullOrEmpty(actionParam))
{
return ResultModel.Error("参数不能为空");
}
try
{
var _param = JsonConvert.DeserializeObject<RgvFinishedParamData>(actionParam);
if (_param == null)
{
return ResultModel.Error("参数解析失败");
}
var driver = _deviceMonitor.GetDriver(_param.PlcName);
if (!driver.IsSuccess)
{
return ResultModel.Error($"未找到名称为 {_param.PlcName} 的Driver");
}
var plc = driver.Data.GetReadWrite();
if (plc == null)
{
return ResultModel.Error($"GetReadWrite为空PLC={_param.PlcName}");
}
//读数据
var read = await ReadAsync(plc, _param.RetCmdAddress);
RgvUpdateInfoModel updateInfo = new RgvUpdateInfoModel
{
Source = source,
2026-03-02 10:56:30 +08:00
TaskId = read.IsSuccess ? read.Data.TaskId : 0,
RetResult = read.IsSuccess ? read.Data.Result : 0,
RetCmd = read.IsSuccess ? read.Data.Command : 0,
2026-03-02 09:13:29 +08:00
ExecuteAction = execute == null ? 0 : execute.Value,
};
var rgvCommand = await GetRgvCommandAsync(updateInfo);
2026-03-02 10:56:30 +08:00
if (!read.IsSuccess)
{
_logger.LogError($"从PLC读取调度数据失败{_param.PlcName}->{_param.RetCmdAddress}{read.ErrorMessage}");
return ResultModel.Error($"读命令失败:{_param.PlcName}->{_param.RetCmdAddress}{read.ErrorMessage}");
}
2026-03-02 09:13:29 +08:00
var readToRgvData = await ReadToRgvDataAsync(plc, _param.CmdAddress);
if (!readToRgvData.IsSuccess)
{
_logger.LogError($"从PLC读取命令失败{_param.PlcName}->{_param.CmdAddress}{read.ErrorMessage}");
return ResultModel.Error($"从PLC读取命令失败{_param.PlcName}->{_param.CmdAddress}{read.ErrorMessage}");
}
short count = readToRgvData.Data.Count; //计数
if (source == RgvUpdateSourceEnum.First && count != 1)
{
//新任务,且计数不为1重置计数,这个情况出现在任务生成后被手动结束了
count = 0;
}
count = count + 1 <= 100 ? (short)(count + 1) : (short)1; //最大100
if (rgvCommand.IsSuccess)
{
if (rgvCommand.Data!.Command != RgvCommandEnum.UnKnown)
{
WcsToRgvData wcsToRgv = new WcsToRgvData
{
Command = (short)rgvCommand.Data!.Command,
Count = count,
2026-03-02 10:56:30 +08:00
FromStation1 = (short)rgvCommand.Data!.FromPos1,
FromStation2 = (short)rgvCommand.Data!.FromPos2,
ToStation1 = (short)rgvCommand.Data!.TargetPos1,
ToStation2 = (short)rgvCommand.Data!.TargetPos2,
2026-03-02 09:13:29 +08:00
TaskId = rgvCommand.Data!.TaskId,
2026-03-02 10:56:30 +08:00
QrCode1 = rgvCommand.Data!.QrCode1,
QrCode2 = rgvCommand.Data!.QrCode2
2026-03-02 09:13:29 +08:00
};
var write = await WriteAsync(plc, _param.CmdAddress, wcsToRgv);
if (!write.IsSuccess) return ResultModel.Error($"写变量失败:{_param.PlcName}->{_param.CmdAddress}");
_logger.LogInformation($"调度任务下发成功TaskId={wcsToRgv.TaskId}->{JsonConvert.SerializeObject(wcsToRgv)}");
return ResultModel.Success();
2026-03-02 10:56:30 +08:00
2026-03-02 09:13:29 +08:00
}
}
return ResultModel.Error($"没有需要执行的动作TaskId={updateInfo.TaskId}");
}
catch (Exception ex)
{
return ResultModel.Error($"参数解析失败:{ex.Message}");
}
}
[LogAndSwallow]
private async Task<ResultModel<RgvToWcsData>> ReadAsync(IReadWriteDevice driver, string address)
{
var readResult = await driver.ReadAsync(address, 10);
if (!readResult.IsSuccess)
{
2026-03-02 10:56:30 +08:00
return ResultModel<RgvToWcsData>.Error(readResult.Message);
2026-03-02 09:13:29 +08:00
}
RgvToWcsData requestData = new RgvToWcsData
{
Command = driver.ByteTransform.TransInt16(readResult.Content, 0),
Count = driver.ByteTransform.TransInt16(readResult.Content, 2),
Result = driver.ByteTransform.TransInt16(readResult.Content, 4),
TaskId = driver.ByteTransform.TransInt32(readResult.Content, 6)
};
return ResultModel<RgvToWcsData>.Success(requestData);
}
[LogAndSwallow]
private async Task<ResultModel<WcsToRgvData>> ReadToRgvDataAsync(IReadWriteDevice driver, string address)
{
2026-03-02 10:56:30 +08:00
var readResult = await driver.ReadAsync(address, 60);
2026-03-02 09:13:29 +08:00
if (!readResult.IsSuccess)
{
2026-03-02 10:56:30 +08:00
return ResultModel<WcsToRgvData>.Error(readResult.Message);
2026-03-02 09:13:29 +08:00
}
WcsToRgvData requestData = new WcsToRgvData
{
Command = driver.ByteTransform.TransInt16(readResult.Content, 0),
Count = driver.ByteTransform.TransInt16(readResult.Content, 14),
TaskId = driver.ByteTransform.TransInt32(readResult.Content, 6)
};
return ResultModel<WcsToRgvData>.Success(requestData);
}
[LogAndSwallow]
private async Task<ResultModel> WriteAsync(IReadWriteDevice driver, string address, WcsToRgvData toRgvData, int retryCount = 5)
{
// 准备数据
2026-03-02 10:56:30 +08:00
byte[] data = new byte[60];
2026-03-02 09:13:29 +08:00
driver.ByteTransform.TransByte(toRgvData.Command).CopyTo(data, 0);
driver.ByteTransform.TransByte(toRgvData.TaskId).CopyTo(data, 2);
2026-03-02 10:56:30 +08:00
driver.ByteTransform.TransByte(toRgvData.FromStation1).CopyTo(data, 6);
driver.ByteTransform.TransByte(toRgvData.FromStation2).CopyTo(data, 8);
driver.ByteTransform.TransByte(toRgvData.ToStation1).CopyTo(data, 10);
driver.ByteTransform.TransByte(toRgvData.ToStation2).CopyTo(data, 12);
2026-03-02 09:13:29 +08:00
driver.ByteTransform.TransByte(toRgvData.Count).CopyTo(data, 14);
data[16] = 20;//字符串最大长度
2026-03-02 10:56:30 +08:00
data[17] = (byte)toRgvData.QrCode1.Length;//字符串实际长度
Encoding.ASCII.GetBytes(toRgvData.QrCode1).CopyTo(data, 18);
data[38] = 20;//字符串最大长度
data[39] = (byte)toRgvData.QrCode2.Length;//字符串实际长度
Encoding.ASCII.GetBytes(toRgvData.QrCode2).CopyTo(data, 40);
2026-03-02 09:13:29 +08:00
int baseDelay = 100; // 基础延迟100ms
var random = new Random();
for (int retry = 0; retry < retryCount; retry++)
{
var write = await driver.WriteAsync(address, data);
if (write.IsSuccess)
{
if (retry > 1)
{
//第一次就成功,不需要记录日志
_logger.LogInformation($"写PLC数据调度任务成功{address}->{JsonConvert.SerializeObject(toRgvData)},第{retry + 1}次尝试");
}
return ResultModel.Success();
}
else
{
_logger.LogError($"写PLC数据调度任务失败{address}->{JsonConvert.SerializeObject(toRgvData)},第{retry + 1}次尝试");
}
// 如果不是最后一次尝试,则等待后重试
if (retry < retryCount - 1)
{
// 计算指数退避+抖动
int jitter = random.Next(0, 100); // 0~100ms
int delay = baseDelay * (int)Math.Pow(2, retry) + jitter;
await Task.Delay(delay);
}
}
_logger.LogError($"写PLC数据调度任务失败{address}->{JsonConvert.SerializeObject(toRgvData)},总共{retryCount}次尝试");
return ResultModel.Error("写PLC数据失败");
}
}