176 lines
7.0 KiB
C#
176 lines
7.0 KiB
C#
|
|
using Cowain.Base.Models;
|
|||
|
|
using HslCommunication;
|
|||
|
|
using HslCommunication.Core;
|
|||
|
|
using Microsoft.Extensions.DependencyInjection;
|
|||
|
|
using Microsoft.Extensions.Hosting;
|
|||
|
|
using Microsoft.Extensions.Logging;
|
|||
|
|
using Plugin.Cowain.Driver;
|
|||
|
|
using Plugin.Cowain.Driver.Abstractions;
|
|||
|
|
using Plugin.Cowain.Driver.Attributes;
|
|||
|
|
using Plugin.Cowain.Driver.Models;
|
|||
|
|
using Plugin.Cowain.Wcs.IServices;
|
|||
|
|
using Plugin.Cowain.Wcs.Models.Enum;
|
|||
|
|
using Plugin.Cowain.Wcs.Services;
|
|||
|
|
using System.Text.Json;
|
|||
|
|
|
|||
|
|
namespace Plugin.Cowain.Wcs.Actions;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 20250812简化,批量写
|
|||
|
|
/// </summary>
|
|||
|
|
[Action("Station6180", "上下料请求6180")]
|
|||
|
|
public class Station6180Action : IVariableAction
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
private class ParamData
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// PLC名称
|
|||
|
|
/// </summary>
|
|||
|
|
public string StationCode { get; set; } = string.Empty;
|
|||
|
|
/// <summary>
|
|||
|
|
/// PLC名称
|
|||
|
|
/// </summary>
|
|||
|
|
public string PlcName { get; set; } = string.Empty;
|
|||
|
|
/// <summary>
|
|||
|
|
/// 命令地址
|
|||
|
|
/// </summary>
|
|||
|
|
public string CmdAddress { get; set; } = string.Empty;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 反馈命令地址
|
|||
|
|
/// </summary>
|
|||
|
|
public string RetCmdAddress { get; set; } = string.Empty;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private readonly IDeviceMonitor _deviceMonitor;
|
|||
|
|
private IServiceScopeFactory _scopeFactory;
|
|||
|
|
private readonly ILogger<Station6180Action> _logger;
|
|||
|
|
public Station6180Action(IDeviceMonitor deviceMonitor, IServiceScopeFactory scopeFactory, ILogger<Station6180Action> logger)
|
|||
|
|
{
|
|||
|
|
_deviceMonitor = deviceMonitor;
|
|||
|
|
_scopeFactory = scopeFactory;
|
|||
|
|
_logger = logger;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
public async Task<ResultModel> ExecuteAsync(VariableAction variableAction, CancellationToken cancellationToken)
|
|||
|
|
{
|
|||
|
|
_logger.LogInformation($"执行测试事件:{variableAction.Variable.Name}-{variableAction.Variable.Address},参数:{variableAction.Param},旧值:{variableAction.Variable.OldValue},新值:{variableAction.Variable.Value}");
|
|||
|
|
|
|||
|
|
var _param = JsonSerializer.Deserialize<ParamData>(variableAction.Param);
|
|||
|
|
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.CmdAddress);
|
|||
|
|
if (!read.IsSuccess)
|
|||
|
|
{
|
|||
|
|
_logger.LogError($"从PLC读取工站数据失败:{_param.PlcName}->{_param.CmdAddress},{read.ErrorMessage}");
|
|||
|
|
return ResultModel.Error($"读命令失败:{_param.PlcName}->{_param.CmdAddress},{read.ErrorMessage}");
|
|||
|
|
}
|
|||
|
|
using var scope = _scopeFactory.CreateScope();
|
|||
|
|
var stationService = scope.ServiceProvider.GetRequiredService<IStationService>();
|
|||
|
|
var stations = await stationService.GetAllAsync();
|
|||
|
|
var station = stations.FirstOrDefault(x => x.StationCode == _param.StationCode);
|
|||
|
|
if (station == null)
|
|||
|
|
{
|
|||
|
|
_logger.LogError($"工站不存在,请检查:{_param.StationCode}");
|
|||
|
|
return ResultModel.Error($"工站不存在,请检查:{_param.StationCode}");
|
|||
|
|
}
|
|||
|
|
station.UpdateSource = StationUpdateSourceEnum.PLC;
|
|||
|
|
if (read.Data.Command == (short)StationStateEnum.RequestPick)
|
|||
|
|
{
|
|||
|
|
station.Status = StationStateEnum.RequestPick.ToString();
|
|||
|
|
station.QrCode = read.Data.QrCode;
|
|||
|
|
}
|
|||
|
|
else if (read.Data.Command == (short)StationStateEnum.RequestPlace)
|
|||
|
|
{
|
|||
|
|
station.Status = StationStateEnum.RequestPlace.ToString();
|
|||
|
|
}
|
|||
|
|
else if (read.Data.Command == (short)StationStateEnum.NgPick)
|
|||
|
|
{
|
|||
|
|
station.Status = StationStateEnum.NgPick.ToString();
|
|||
|
|
station.QrCode = read.Data.QrCode;
|
|||
|
|
}
|
|||
|
|
else if (read.Data.Command == 1)
|
|||
|
|
{
|
|||
|
|
//清除工站信息
|
|||
|
|
station.QrCode = "";
|
|||
|
|
station.ProcessName = "";
|
|||
|
|
station.Status = StationStateEnum.UnKnown.ToString();
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
_logger.LogError($"命令不正确,请检查:{_param.StationCode},{read.Data.Command}");
|
|||
|
|
return ResultModel.Error($"命令不正确,请检查:{_param.StationCode},{read.Data.Command}");
|
|||
|
|
}
|
|||
|
|
station.ProcessName = read.Data.ProcessName;
|
|||
|
|
//这里没有判断产品名称是否正确,如果不正确需要返回PLC NG,待完善
|
|||
|
|
_logger.LogInformation($"工站更新开始:{_param.StationCode},{read.Data.Command}");
|
|||
|
|
var stationTaskHandler = scope.ServiceProvider.GetRequiredService<IEnumerable<IHostedService>>();
|
|||
|
|
var stationQueueHostedService = stationTaskHandler.OfType<StationQueueHostedService>().FirstOrDefault();
|
|||
|
|
var tcs = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
|
|||
|
|
station.UpdatedAction = result => tcs.TrySetResult(result);
|
|||
|
|
stationQueueHostedService?.Enqueue(station);
|
|||
|
|
var ret = await tcs.Task;
|
|||
|
|
_logger.LogInformation($"工站更新结束:{_param.StationCode},{read.Data.Command}");
|
|||
|
|
|
|||
|
|
//使用批量写入,保证PLC数据一致性,避免出现部分数据未写成功的情况,要么都没写成功
|
|||
|
|
if (ret)
|
|||
|
|
{
|
|||
|
|
//工站更新OK
|
|||
|
|
var writeResult = await plc.WriteValuesAysnc(_param.RetCmdAddress, new short[] { read.Data.Command, (short)1, read.Data.Count });
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
//工站更新NG
|
|||
|
|
var writeResult = await plc.WriteValuesAysnc(_param.RetCmdAddress, new short[] { read.Data.Command, (short)2, read.Data.Count });
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
return ResultModel.Success();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
private async Task<ResultModel<StationRequestData>> ReadAsync(IReadWriteDevice driver, string address)
|
|||
|
|
{
|
|||
|
|
var readResult = await driver.ReadAsync(address, 70);
|
|||
|
|
if (!readResult.IsSuccess)
|
|||
|
|
{
|
|||
|
|
ResultModel<StationRequestData>.Error(readResult.Message);
|
|||
|
|
}
|
|||
|
|
StationRequestData requestData = new StationRequestData
|
|||
|
|
{
|
|||
|
|
Command = driver.ByteTransform.TransInt16(readResult.Content, 0),
|
|||
|
|
Count = driver.ByteTransform.TransInt16(readResult.Content, 2),
|
|||
|
|
ProcessName = readResult.Content.RemoveBegin(4).GetS7String(),
|
|||
|
|
NgStationName = readResult.Content.RemoveBegin(26).GetS7String(),
|
|||
|
|
QrCode = readResult.Content.RemoveBegin(48).GetS7String()
|
|||
|
|
};
|
|||
|
|
return ResultModel<StationRequestData>.Success(requestData);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
public class StationRequestData
|
|||
|
|
{
|
|||
|
|
public string QrCode { get; set; } = string.Empty;
|
|||
|
|
public string ProcessName { get; set; } = string.Empty;
|
|||
|
|
public string NgStationName { get; set; } = string.Empty;
|
|||
|
|
public short Command { get; set; }
|
|||
|
|
public short Count { get; set; }
|
|||
|
|
}
|