2025-03-23 13:09:36 +08:00
|
|
|
using System.Text.Json;
|
2025-03-16 03:17:36 +08:00
|
|
|
using MCProtocol;
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
using Seyounth.Hyosung.Data.Models;
|
|
|
|
using Seyounth.Hyosung.Data.Models.Plc;
|
|
|
|
|
|
|
|
namespace Seyounth.Hyosung.Core.Plc;
|
|
|
|
|
|
|
|
public class HyosungPlcService(ILogger<HyosungPlcService> logger) : IHyosungPlcService
|
|
|
|
{
|
|
|
|
private readonly McPlc _reader = new("192.168.3.10", 4060, Mitsubishi.McFrame.MC3E);
|
|
|
|
|
|
|
|
private readonly McPlc _writer = new("192.168.3.10", 4061, Mitsubishi.McFrame.MC3E);
|
|
|
|
|
|
|
|
private bool isLeaving = false;
|
|
|
|
|
|
|
|
public async Task StartAsync(CancellationToken token)
|
|
|
|
{
|
|
|
|
List<Task<int>> ls =
|
|
|
|
[
|
|
|
|
_reader.ConnectAsync(),
|
|
|
|
_writer.ConnectAsync()
|
|
|
|
];
|
|
|
|
var codes = await Task.WhenAll(ls);
|
|
|
|
logger.LogInformation($"plc reader connect code: {codes[0]}\r\nplc writer connect code: {codes[1]}");
|
|
|
|
ReadLoop(token);
|
|
|
|
}
|
|
|
|
|
|
|
|
public async Task StopAsync()
|
|
|
|
{
|
|
|
|
List<Task<int>> ls =
|
|
|
|
[
|
|
|
|
_reader.CloseAsync(),
|
|
|
|
_writer.CloseAsync()
|
|
|
|
];
|
|
|
|
var codes = await Task.WhenAll(ls);
|
|
|
|
logger.LogInformation($"plc reader close code: {codes[0]}\r\nplc writer close code: {codes[1]}");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public async Task WriteVarietyAsync(Variety variety)
|
|
|
|
{
|
|
|
|
var data = variety.ToVarietyPlcData();
|
|
|
|
await _writer.WriteShortsAsync(4200, data);
|
|
|
|
logger.LogInformation($"write [{string.Join(",", data)}] data to plc address[4200]");
|
|
|
|
await _writer.WriteShortsAsync(4230, (short)variety.Id);
|
|
|
|
logger.LogInformation($"write [{variety.Id}] to plc address[4230]");
|
|
|
|
}
|
|
|
|
|
2025-03-23 15:26:01 +08:00
|
|
|
public async Task WriteScanYarnResultAsync(bool result, short? varietyId = null, string? yarnCode = null)
|
2025-03-16 03:17:36 +08:00
|
|
|
{
|
|
|
|
if (result && yarnCode != null && varietyId != null)
|
|
|
|
{
|
|
|
|
await _writer.WriteShortsAsync(4009, varietyId.Value);
|
2025-03-20 19:32:49 +08:00
|
|
|
await _writer.WriteStringAsync(4010, yarnCode);
|
2025-03-16 03:17:36 +08:00
|
|
|
logger.LogInformation($"write [{yarnCode}] to plc address[4010]");
|
|
|
|
}
|
|
|
|
|
|
|
|
await _writer.WriteShortsAsync(4000, (short)(result ? 1 : 2));
|
|
|
|
logger.LogInformation($"write [{(result ? 1 : 2)}] to plc address[4000]");
|
|
|
|
}
|
|
|
|
|
|
|
|
public async Task WriteScanFixtureResultAsync(int fixtureId, bool result, short? fixtureCode = null)
|
|
|
|
{
|
|
|
|
int flagAddress = 4000 + fixtureId;
|
|
|
|
int codeAddress = 4004 + fixtureId;
|
|
|
|
if (result && fixtureCode != null)
|
|
|
|
{
|
|
|
|
await _writer.WriteShortsAsync(codeAddress, fixtureCode.Value);
|
|
|
|
logger.LogInformation($"write [{fixtureCode}] to plc address[{codeAddress}]");
|
|
|
|
}
|
|
|
|
|
|
|
|
await _writer.WriteShortsAsync(flagAddress, (short)(result ? 1 : 2));
|
|
|
|
logger.LogInformation($"write [{(result ? 1 : 2)}] to plc address[{flagAddress}]");
|
|
|
|
}
|
|
|
|
|
|
|
|
public async Task LeaveCompletedAsync()
|
2025-03-23 15:26:01 +08:00
|
|
|
{
|
2025-03-16 03:17:36 +08:00
|
|
|
await _writer.WriteShortsAsync(4020, 0);
|
|
|
|
await _writer.WriteShortsAsync(13012, 0);
|
|
|
|
await _writer.WriteShortsAsync(4520, 1);
|
|
|
|
isLeaving = false;
|
|
|
|
}
|
|
|
|
|
2025-03-20 19:32:49 +08:00
|
|
|
public async Task WriteTrayCodeAsync(int index, string trayCode)
|
2025-03-16 03:17:36 +08:00
|
|
|
{
|
|
|
|
var address = index == 1 ? 4100 : 4110;
|
2025-03-20 19:32:49 +08:00
|
|
|
await _writer.WriteStringAsync(address, trayCode);
|
2025-03-16 03:17:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
public async Task WriteReceivedYarnCountAsync(int count)
|
|
|
|
{
|
|
|
|
await _writer.WriteShortsAsync(4120, (short)count);
|
|
|
|
}
|
|
|
|
|
|
|
|
public async Task WritePackLineOptionAsync(PackLineOption option)
|
|
|
|
{
|
|
|
|
List<short> ls = new List<short>();
|
|
|
|
ls.Add((short)option.HeadCount);
|
|
|
|
ls.Add((short)(option.IsTop ? 1 : 2));
|
2025-03-19 02:42:56 +08:00
|
|
|
ls.Add(1);
|
2025-03-16 03:17:36 +08:00
|
|
|
ls.Add((short)(option.HasBox ? 1 : 2));
|
|
|
|
ls.Add((short)(option.IsPack ? 1 : 2));
|
|
|
|
ls.Add((short)(option.IsFilm ? 1 : 2));
|
|
|
|
ls.Add((short)(option.IsLam ? 1 : 2));
|
2025-03-19 02:42:56 +08:00
|
|
|
await _writer.WriteShortsAsync(12120, ls.ToArray());
|
2025-03-16 03:17:36 +08:00
|
|
|
}
|
|
|
|
|
2025-03-25 16:31:41 +08:00
|
|
|
public async Task WritePrintLableOptionsAsync(int side, int slave)
|
2025-03-16 03:17:36 +08:00
|
|
|
{
|
2025-03-25 16:31:41 +08:00
|
|
|
short masterCount = 0;
|
2025-03-23 13:09:36 +08:00
|
|
|
switch (side)
|
2025-03-20 19:32:49 +08:00
|
|
|
{
|
2025-03-23 13:09:36 +08:00
|
|
|
case 0:
|
2025-03-25 16:31:41 +08:00
|
|
|
masterCount = 1;
|
2025-03-23 13:09:36 +08:00
|
|
|
break;
|
|
|
|
case 1:
|
2025-03-25 16:31:41 +08:00
|
|
|
masterCount = 2;
|
2025-03-23 13:09:36 +08:00
|
|
|
break;
|
|
|
|
case 2:
|
2025-03-25 16:31:41 +08:00
|
|
|
masterCount = 6;
|
2025-03-23 13:09:36 +08:00
|
|
|
break;
|
|
|
|
case 3:
|
2025-03-25 16:31:41 +08:00
|
|
|
masterCount = 14;
|
2025-03-23 13:09:36 +08:00
|
|
|
break;
|
|
|
|
case 4:
|
2025-03-25 16:31:41 +08:00
|
|
|
masterCount = 30;
|
2025-03-23 13:09:36 +08:00
|
|
|
break;
|
2025-03-20 19:32:49 +08:00
|
|
|
}
|
2025-03-23 15:26:01 +08:00
|
|
|
|
2025-03-25 16:31:41 +08:00
|
|
|
short slaveCount = 0;
|
|
|
|
switch (slave)
|
|
|
|
{
|
|
|
|
case 0:
|
2025-03-26 15:02:43 +08:00
|
|
|
slaveCount = 1;
|
2025-03-25 16:31:41 +08:00
|
|
|
break;
|
|
|
|
case 1:
|
2025-03-26 15:02:43 +08:00
|
|
|
slaveCount = 2;
|
2025-03-25 16:31:41 +08:00
|
|
|
break;
|
|
|
|
case 2:
|
2025-03-26 15:02:43 +08:00
|
|
|
slaveCount = 6;
|
2025-03-25 16:31:41 +08:00
|
|
|
break;
|
|
|
|
case 3:
|
2025-03-26 15:02:43 +08:00
|
|
|
slaveCount = 14;
|
2025-03-25 16:31:41 +08:00
|
|
|
break;
|
|
|
|
case 4:
|
2025-03-26 15:02:43 +08:00
|
|
|
slaveCount = 30;
|
2025-03-25 16:31:41 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2025-03-27 09:12:16 +08:00
|
|
|
await _writer.WriteShortsAsync(13050, [1, 1, 1, 2]);
|
2025-03-23 13:09:36 +08:00
|
|
|
}
|
2025-03-23 15:26:01 +08:00
|
|
|
|
|
|
|
public async Task WritePrintLabelResultAsync(int index, bool result)
|
2025-03-23 13:09:36 +08:00
|
|
|
{
|
|
|
|
var address = index == 1 ? 13060 : 13061;
|
2025-03-20 19:32:49 +08:00
|
|
|
|
2025-03-16 03:17:36 +08:00
|
|
|
await _writer.WriteShortsAsync(address, (short)(result ? 1 : 2));
|
|
|
|
}
|
|
|
|
|
2025-03-23 15:26:01 +08:00
|
|
|
public async Task WriteScanEntryResultAsync(int index, bool result)
|
|
|
|
{
|
|
|
|
var address = index == 1 ? 4530 : 4531;
|
|
|
|
await _writer.WriteShortsAsync(address, (short)(result ? 1 : 2));
|
|
|
|
}
|
|
|
|
|
2025-03-21 09:07:39 +08:00
|
|
|
//static byte SetBit(byte value, int bitPosition)
|
|
|
|
//{
|
|
|
|
// // 创建一个掩码,该掩码只有第 bitPosition 位为 1
|
|
|
|
// byte mask = (byte)(1 << bitPosition);
|
|
|
|
// // 使用按位或操作将 value 的第 bitPosition 位置为 1
|
|
|
|
// return (byte)(value | mask);
|
|
|
|
//}
|
2025-03-16 03:17:36 +08:00
|
|
|
|
|
|
|
public event Func<int, Task>? OnPlcRequestScanProduct;
|
|
|
|
|
|
|
|
public event Func<int, Task>? OnPlcRequestScanFixture;
|
|
|
|
|
|
|
|
public event Func<PlcStackInfo, Task>? OnPlcRequestLeavingProductionLine;
|
|
|
|
|
|
|
|
public event Func<int, int, Task>? OnPlcNeedNewTrayCode;
|
|
|
|
|
|
|
|
public event Func<PlcStackingInfo, Task>? OnPlcPutCompleted;
|
|
|
|
|
2025-03-20 19:32:49 +08:00
|
|
|
public event Func<string, Task>? OnPlcRequestPackLineOption;
|
2025-03-16 03:17:36 +08:00
|
|
|
|
2025-03-23 15:26:01 +08:00
|
|
|
public event Func<int, int, Task>? OnRequestPrintLabel;
|
2025-03-21 10:19:10 +08:00
|
|
|
public event Func<string, Task> OnRequestGetPrintLableOption;
|
2025-03-23 15:26:01 +08:00
|
|
|
public event Func<int, Task>? OnRequestScanEntry;
|
2025-03-16 03:17:36 +08:00
|
|
|
|
|
|
|
private async Task ReadLoop(CancellationToken token)
|
|
|
|
{
|
|
|
|
while (!token.IsCancellationRequested)
|
|
|
|
{
|
2025-03-18 05:24:15 +08:00
|
|
|
try
|
|
|
|
{
|
2025-03-23 15:26:01 +08:00
|
|
|
await QueryScanEntry();
|
2025-03-18 05:24:15 +08:00
|
|
|
await QueryScanProductRequest();
|
|
|
|
await QueryScanFixtureRequest();
|
2025-03-23 15:26:01 +08:00
|
|
|
if (!isLeaving)
|
|
|
|
await QueryLeavingProductionLine();
|
2025-03-18 05:24:15 +08:00
|
|
|
await QueryNeedTrayCode();
|
|
|
|
await QueryPutOnceCompleted();
|
|
|
|
await QueryPackLineOption();
|
|
|
|
await QueryPrintLabel();
|
|
|
|
await Task.Delay(100, token);
|
2025-03-21 10:19:10 +08:00
|
|
|
await QueryGetPrintLabel();
|
2025-03-18 05:24:15 +08:00
|
|
|
}
|
2025-03-18 21:18:26 +08:00
|
|
|
catch (Exception e)
|
2025-03-18 05:24:15 +08:00
|
|
|
{
|
|
|
|
}
|
2025-03-16 03:17:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 查询请求扫描产品方法
|
|
|
|
/// </summary>
|
|
|
|
private async Task QueryScanProductRequest()
|
|
|
|
{
|
|
|
|
var requestScanProduct = await _reader.ReadShortsAsync(4500, 2);
|
|
|
|
if (requestScanProduct[0] == 1)
|
|
|
|
{
|
|
|
|
await _writer.WriteShortsAsync(4500, 0, 0);
|
2025-03-18 21:18:26 +08:00
|
|
|
OnPlcRequestScanProduct?.Invoke(requestScanProduct[1]);
|
2025-03-16 03:17:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 查询扫描夹具请求
|
|
|
|
/// </summary>
|
|
|
|
private async Task QueryScanFixtureRequest()
|
|
|
|
{
|
|
|
|
var requestScanFixture = await _reader.ReadShortsAsync(4505, 4);
|
|
|
|
if (requestScanFixture[0] == 1)
|
|
|
|
{
|
|
|
|
await _writer.WriteShortsAsync(4505, 0);
|
|
|
|
OnPlcRequestScanFixture?.Invoke(1);
|
|
|
|
}
|
2025-03-18 21:18:26 +08:00
|
|
|
|
2025-03-16 03:17:36 +08:00
|
|
|
if (requestScanFixture[1] == 1)
|
|
|
|
{
|
|
|
|
await _writer.WriteShortsAsync(4506, 0);
|
|
|
|
OnPlcRequestScanFixture?.Invoke(2);
|
|
|
|
}
|
2025-03-18 21:18:26 +08:00
|
|
|
|
2025-03-16 03:17:36 +08:00
|
|
|
if (requestScanFixture[2] == 1)
|
|
|
|
{
|
|
|
|
await _writer.WriteShortsAsync(4507, 0);
|
2025-03-18 21:18:26 +08:00
|
|
|
await OnPlcRequestScanFixture?.Invoke(3);
|
2025-03-16 03:17:36 +08:00
|
|
|
}
|
2025-03-18 21:18:26 +08:00
|
|
|
|
2025-03-16 03:17:36 +08:00
|
|
|
if (requestScanFixture[3] == 1)
|
|
|
|
{
|
|
|
|
await _writer.WriteShortsAsync(4508, 0);
|
|
|
|
await OnPlcRequestScanFixture?.Invoke(4);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 查询有托盘请求下线
|
|
|
|
/// </summary>
|
|
|
|
private async Task QueryLeavingProductionLine()
|
|
|
|
{
|
|
|
|
var leavingProductionLine = await _reader.ReadShortsAsync(4020, 1);
|
2025-03-18 21:18:26 +08:00
|
|
|
// var stackStatus = await _reader.ReadShortsAsync(12110, 1);
|
2025-03-16 03:17:36 +08:00
|
|
|
if (leavingProductionLine[0] == 1)
|
|
|
|
{
|
2025-03-20 19:32:49 +08:00
|
|
|
var trayCode = await _reader.ReadStringAsync(12600);
|
2025-03-23 13:09:36 +08:00
|
|
|
//if (!string.IsNullOrEmpty(trayCode))
|
|
|
|
//{
|
2025-03-23 15:26:01 +08:00
|
|
|
PlcStackInfo info = new PlcStackInfo()
|
|
|
|
{
|
|
|
|
TrayCode = trayCode
|
|
|
|
};
|
|
|
|
isLeaving = true;
|
|
|
|
OnPlcRequestLeavingProductionLine?.Invoke(info);
|
|
|
|
// }
|
2025-03-16 03:17:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 查询是否需要新的托盘号
|
|
|
|
/// </summary>
|
|
|
|
private async Task QueryNeedTrayCode()
|
|
|
|
{
|
|
|
|
var n1 = await _reader.ReadShortsAsync(4600, 2);
|
|
|
|
var n2 = await _reader.ReadShortsAsync(4610, 2);
|
|
|
|
if (n1[0] == 1)
|
|
|
|
{
|
|
|
|
await _writer.WriteShortsAsync(4600, 0);
|
2025-03-18 21:18:26 +08:00
|
|
|
OnPlcNeedNewTrayCode?.Invoke(1, n1[1]);
|
2025-03-16 03:17:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (n2[0] == 1)
|
|
|
|
{
|
|
|
|
await _writer.WriteShortsAsync(4610, 0);
|
2025-03-18 21:18:26 +08:00
|
|
|
OnPlcNeedNewTrayCode?.Invoke(2, n2[1]);
|
2025-03-16 03:17:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private async Task QueryPutOnceCompleted()
|
|
|
|
{
|
|
|
|
var status = await _reader.ReadShortsAsync(4691, 2);
|
2025-03-18 21:18:26 +08:00
|
|
|
if (status[0] > 0)
|
2025-03-16 03:17:36 +08:00
|
|
|
{
|
2025-03-23 13:09:36 +08:00
|
|
|
logger.LogInformation($"request put yarn completed");
|
2025-03-18 05:24:15 +08:00
|
|
|
await _writer.WriteShortsAsync(4690, 0, 0, 0);
|
2025-03-20 19:32:49 +08:00
|
|
|
var trayCode = await _reader.ReadStringAsync(4620);
|
|
|
|
var yarn1 = await _reader.ReadStringAsync(4630);
|
|
|
|
var yarn2 = await _reader.ReadStringAsync(4640);
|
|
|
|
var yarn3 = await _reader.ReadStringAsync(4650);
|
2025-03-16 03:17:36 +08:00
|
|
|
var info = new PlcStackingInfo()
|
|
|
|
{
|
|
|
|
TrayCode = trayCode,
|
|
|
|
YarnCount = status[0],
|
|
|
|
TotalYarnCount = status[1]
|
|
|
|
};
|
2025-03-23 13:09:36 +08:00
|
|
|
logger.LogInformation($"request put yarn get info: {JsonSerializer.Serialize(info)}");
|
2025-03-20 19:32:49 +08:00
|
|
|
if (!string.IsNullOrEmpty(yarn1))
|
2025-03-16 03:17:36 +08:00
|
|
|
info.YarnCode.Add(yarn1);
|
2025-03-20 19:32:49 +08:00
|
|
|
if (!string.IsNullOrEmpty(yarn2))
|
2025-03-16 03:17:36 +08:00
|
|
|
info.YarnCode.Add(yarn2);
|
2025-03-20 19:32:49 +08:00
|
|
|
if (!string.IsNullOrEmpty(yarn3))
|
2025-03-16 03:17:36 +08:00
|
|
|
info.YarnCode.Add(yarn3);
|
|
|
|
if (info.YarnCode.Count != info.YarnCount)
|
|
|
|
{
|
|
|
|
logger.LogWarning($"get yarn code count[{info.YarnCode.Count}]不等于YarnCount[{info.TotalYarnCount}]");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2025-03-18 21:18:26 +08:00
|
|
|
|
2025-03-16 03:17:36 +08:00
|
|
|
await _writer.WriteShortsAsync(4620, new short[40]);
|
|
|
|
OnPlcPutCompleted?.Invoke(info);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// 打包线请求获取配置
|
|
|
|
/// </summary>
|
|
|
|
private async Task QueryPackLineOption()
|
|
|
|
{
|
|
|
|
var requestPackLineOption = await _reader.ReadShortsAsync(4022, 1);
|
|
|
|
if (requestPackLineOption[0] == 1)
|
|
|
|
{
|
2025-03-20 19:32:49 +08:00
|
|
|
var trayCode = await _reader.ReadStringAsync(12100);
|
2025-03-16 03:17:36 +08:00
|
|
|
await _writer.WriteShortsAsync(4022, 0);
|
|
|
|
OnPlcRequestPackLineOption?.Invoke(trayCode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-03-23 15:26:01 +08:00
|
|
|
private async Task QueryScanEntry()
|
|
|
|
{
|
|
|
|
var requestScanEntry = await _reader.ReadShortsAsync(4030, 2);
|
|
|
|
if (requestScanEntry[0] == 1)
|
|
|
|
{
|
|
|
|
await _writer.WriteShortsAsync(4030, 0);
|
|
|
|
OnRequestScanEntry?.Invoke(1);
|
|
|
|
}
|
|
|
|
else if (requestScanEntry[1] == 1)
|
|
|
|
{
|
|
|
|
await _writer.WriteShortsAsync(4030, 0);
|
|
|
|
OnRequestScanEntry?.Invoke(2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-03-21 10:19:10 +08:00
|
|
|
private async Task QueryGetPrintLabel()
|
|
|
|
{
|
|
|
|
var trayCode = await _reader.ReadStringAsync(13000);
|
2025-03-23 15:26:01 +08:00
|
|
|
if (!string.IsNullOrEmpty(trayCode) && !trayCode.StartsWith("0000"))
|
2025-03-21 10:19:10 +08:00
|
|
|
{
|
2025-03-23 15:26:01 +08:00
|
|
|
await _reader.WriteStringAsync(13000, "00000000000000000000");
|
2025-03-21 10:19:10 +08:00
|
|
|
OnRequestGetPrintLableOption?.Invoke(trayCode);
|
|
|
|
}
|
|
|
|
}
|
2025-03-23 15:26:01 +08:00
|
|
|
|
2025-03-16 03:17:36 +08:00
|
|
|
private async Task QueryPrintLabel()
|
|
|
|
{
|
|
|
|
var requestPrintLabel = await _reader.ReadShortsAsync(13010, 3);
|
|
|
|
if (requestPrintLabel[0] == 1)
|
|
|
|
{
|
|
|
|
await _writer.WriteShortsAsync(13010, 0);
|
|
|
|
await _writer.WriteShortsAsync(13012, 0);
|
2025-03-21 10:19:10 +08:00
|
|
|
OnRequestPrintLabel?.Invoke(1, requestPrintLabel[2]);
|
2025-03-16 03:17:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (requestPrintLabel[1] == 1)
|
|
|
|
{
|
|
|
|
await _writer.WriteShortsAsync(13011, 0);
|
|
|
|
await _writer.WriteShortsAsync(13012, 0);
|
2025-03-21 10:19:10 +08:00
|
|
|
OnRequestPrintLabel?.Invoke(2, requestPrintLabel[2]);
|
2025-03-16 03:17:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|