176 lines
6.9 KiB
C#
176 lines
6.9 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>
|
||
/// 工站需要上下料请求
|
||
/// </summary>
|
||
[Action("Station", "工站请求命令")]
|
||
public class StationAction : 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<StationAction> _logger;
|
||
public StationAction(IDeviceMonitor deviceMonitor, IServiceScopeFactory scopeFactory, ILogger<StationAction> 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; }
|
||
}
|