diff --git a/.idea/.idea.Seyounth.Hyosung/.idea/.gitignore b/.idea/.idea.Seyounth.Hyosung/.idea/.gitignore
new file mode 100644
index 0000000..361a05a
--- /dev/null
+++ b/.idea/.idea.Seyounth.Hyosung/.idea/.gitignore
@@ -0,0 +1,13 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# Rider 忽略的文件
+/projectSettingsUpdater.xml
+/modules.xml
+/contentModel.xml
+/.idea.Seyounth.Hyosung.iml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/.idea.Seyounth.Hyosung/.idea/dataSources.xml b/.idea/.idea.Seyounth.Hyosung/.idea/dataSources.xml
new file mode 100644
index 0000000..90c00e8
--- /dev/null
+++ b/.idea/.idea.Seyounth.Hyosung/.idea/dataSources.xml
@@ -0,0 +1,12 @@
+
+
+
+
+ sqlite.xerial
+ true
+ org.sqlite.JDBC
+ jdbc:sqlite:$PROJECT_DIR$/Seyounth.Hyosung/bin/Debug/net8.0-windows/hyosung.test
+ $ProjectFileDir$
+
+
+
\ No newline at end of file
diff --git a/.idea/.idea.Seyounth.Hyosung/.idea/indexLayout.xml b/.idea/.idea.Seyounth.Hyosung/.idea/indexLayout.xml
new file mode 100644
index 0000000..7b08163
--- /dev/null
+++ b/.idea/.idea.Seyounth.Hyosung/.idea/indexLayout.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HyosungDataTester/GlobalUsings.cs b/HyosungDataTester/GlobalUsings.cs
new file mode 100644
index 0000000..cefced4
--- /dev/null
+++ b/HyosungDataTester/GlobalUsings.cs
@@ -0,0 +1 @@
+global using NUnit.Framework;
\ No newline at end of file
diff --git a/HyosungDataTester/HyosungDataTester.csproj b/HyosungDataTester/HyosungDataTester.csproj
new file mode 100644
index 0000000..681442a
--- /dev/null
+++ b/HyosungDataTester/HyosungDataTester.csproj
@@ -0,0 +1,24 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/HyosungDataTester/UnitTest1.cs b/HyosungDataTester/UnitTest1.cs
new file mode 100644
index 0000000..ed99aa4
--- /dev/null
+++ b/HyosungDataTester/UnitTest1.cs
@@ -0,0 +1,21 @@
+using System.Text.Json;
+using Seyounth.Hyosung.Data.Services.Hyosung;
+
+namespace HyosungDataTester;
+
+public class Tests
+{
+ private IHyosungWmsService _wmsService = new HyosungWmsService();
+
+ [SetUp]
+ public void Setup()
+ {
+ }
+
+ [Test]
+ public void Test1()
+ {
+ var result = _wmsService.GetItemInfoByItemCode("TYY-JPS1843018G").Result;
+ Assert.Pass(JsonSerializer.Serialize(result));
+ }
+}
\ No newline at end of file
diff --git a/HyosungTester/HyosungTester.csproj b/HyosungTester/HyosungTester.csproj
new file mode 100644
index 0000000..55d519a
--- /dev/null
+++ b/HyosungTester/HyosungTester.csproj
@@ -0,0 +1,14 @@
+
+
+
+ Exe
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/HyosungTester/Program.cs b/HyosungTester/Program.cs
new file mode 100644
index 0000000..ceb8e42
--- /dev/null
+++ b/HyosungTester/Program.cs
@@ -0,0 +1,10 @@
+// See https://aka.ms/new-console-template for more information
+
+using System.Text.Json;
+using Seyounth.Hyosung.Data.Services.Hyosung;
+
+Console.WriteLine("Hello, World!");
+IHyosungWmsService wmsService=new HyosungWmsService();
+var data= wmsService.GetItemInfoByItemCode("TYY-JPS1843018G").Result;
+Console.WriteLine(JsonSerializer.Serialize(data));
+Console.ReadLine();
\ No newline at end of file
diff --git a/Seyounth.Core/Extensions/DateTimeExtensions.cs b/Seyounth.Core/Extensions/DateTimeExtensions.cs
new file mode 100644
index 0000000..326190b
--- /dev/null
+++ b/Seyounth.Core/Extensions/DateTimeExtensions.cs
@@ -0,0 +1,9 @@
+namespace Seyounth.Core.Extensions;
+
+public static class DateTimeExtensions
+{
+ public static int ToTimestamp(this DateTime dateTime)
+ {
+ return (int)new DateTimeOffset(dateTime).ToUnixTimeSeconds();
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Core/Extensions/EnumHelper.cs b/Seyounth.Core/Extensions/EnumHelper.cs
new file mode 100644
index 0000000..0ae23f2
--- /dev/null
+++ b/Seyounth.Core/Extensions/EnumHelper.cs
@@ -0,0 +1,22 @@
+using System.ComponentModel;
+
+namespace Seyounth.Core.Extensions;
+
+public static class EnumHelper
+{
+ public static IEnumerable GetValues()
+ {
+ return Enum.GetValues(typeof(T)).Cast();
+ }
+
+ // 获取枚举值的描述信息
+ public static string GetDescription(this T enumValue) where T : Enum
+ {
+ var fieldInfo = enumValue.GetType().GetField(enumValue.ToString());
+ var descriptionAttributes =
+ fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false) as DescriptionAttribute[];
+ return descriptionAttributes is { Length: > 0 }
+ ? descriptionAttributes[0].Description
+ : enumValue.ToString();
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Core/Seyounth.Core.csproj b/Seyounth.Core/Seyounth.Core.csproj
new file mode 100644
index 0000000..3a63532
--- /dev/null
+++ b/Seyounth.Core/Seyounth.Core.csproj
@@ -0,0 +1,9 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
diff --git a/Seyounth.Hyosung.Core/Agv/HikAgv.cs b/Seyounth.Hyosung.Core/Agv/HikAgv.cs
new file mode 100644
index 0000000..5807b9f
--- /dev/null
+++ b/Seyounth.Hyosung.Core/Agv/HikAgv.cs
@@ -0,0 +1,146 @@
+using System.Net.Http.Json;
+using Microsoft.Extensions.Logging;
+using Seyounth.Hyosung.Core.Agv.HikModels;
+
+namespace Seyounth.Hyosung.Core.Agv;
+
+public class HikAgv(ILogger logger)
+{
+ private const string Url = "http://192.168.30.161:8181/rcms/services/rest/hikRpcService/";
+
+ private const string CancelTaskUri = "cancelTask";
+
+ private const string SchedulingTaskUri = "genAgvSchedulingTask";
+
+ private string GetRequestCode()
+ {
+ return $"Syc_{DateTimeOffset.Now.Ticks}";
+ }
+
+ ///
+ /// 取消任务
+ ///
+ ///
+ public async Task CancelTaskAsync(string taskCode)
+ {
+ var url = Url + CancelTaskUri;
+ var input = new
+ {
+ reqCode = GetRequestCode(),
+ taskCode
+ };
+ var result = await PostAsync(url, input);
+ if (result is null)
+ {
+ logger.LogWarning($"task {taskCode} cancel error: result is null");
+ return;
+ }
+
+ if (result.Code != "0")
+ {
+ logger.LogWarning($"task {taskCode} cancel error: code is {result.Code}");
+ return;
+ }
+
+ logger.LogInformation($"task {taskCode} cancel succeed.");
+ }
+
+ public async Task CarryToAsync(AgvPosition start, AgvPosition end, string ctnrType, int priority, string taskType)
+ {
+ var url = Url + SchedulingTaskUri;
+ var input = new
+ {
+ reqCode = GetRequestCode(),
+ ctnrType,
+ taskType,
+ priority,
+ agvCode = "4083",
+ positionCodePath = new object[]
+ {
+ new { positionCode = start.PositionCode, type = start.Type },
+ new { positionCode = end.PositionCode, type = end.Type }
+ }
+ };
+ var rs = await PostAsync(url, input);
+ if (rs is null)
+ {
+ logger.LogWarning($"{start.PositionCode} carry to {end.PositionCode} error: result is null");
+ return;
+ }
+
+ if (rs.Code != "0")
+ {
+ logger.LogWarning($"{start.PositionCode} carry to {end.PositionCode} error: code is {rs.Code}");
+ return;
+ }
+
+ logger.LogInformation($"{start.PositionCode} carry to {end.PositionCode} succeed");
+ }
+
+ public async Task MovingToAsync(AgvPosition des, string taskType)
+ {
+ var url = Url + SchedulingTaskUri;
+ var input = new
+ {
+ reqCode = GetRequestCode(),
+ taskType,
+ priority = 1,
+ positionCodePath =
+ new object[]
+ {
+ new { positionCode = des.PositionCode, type = des.Type }
+ }
+ };
+ var rs = await PostAsync(url, input);
+ if (rs is null)
+ {
+ logger.LogWarning($"agv move to {des.PositionCode} error: result is null");
+ return;
+ }
+
+ if (rs.Code != "0")
+ {
+ logger.LogWarning($"agv move to {des.PositionCode} error: code is {rs.Code}");
+ return;
+ }
+
+ logger.LogInformation($"agv move to {des.PositionCode} succeed");
+ }
+
+ public async Task GetAgvStatus(string mapCode, string agvCode)
+ {
+ var url = "http://192.168.30.161:8181/rcms-dps/rest/queryAgvStatus";
+ var q = new
+ {
+ reqCode = GetRequestCode(),
+ mapCode
+ };
+ var rs = await PostAsync>(url, q);
+ if (rs is null)
+ {
+ logger.LogWarning($"get agv {agvCode} from map {mapCode} error: result is null");
+ return null;
+ }
+
+ if (rs.Code == "0") return rs.Data.First(t => t.RobotCode == agvCode);
+ logger.LogWarning($"get agv {agvCode} from map {mapCode} error: code is {rs.Code}");
+ return null;
+ }
+
+ private async Task?> PostAsync(string url, object content)
+ {
+ try
+ {
+ using var client = new HttpClient();
+ var json = JsonContent.Create(content);
+ var response = await client.PostAsync(url, json);
+ response.EnsureSuccessStatusCode();
+ return await response.Content.ReadFromJsonAsync>();
+ }
+ catch (Exception e)
+ {
+ logger.LogError(e, $"post error");
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Core/Agv/HikModels/AgvPosition.cs b/Seyounth.Hyosung.Core/Agv/HikModels/AgvPosition.cs
new file mode 100644
index 0000000..f6d828b
--- /dev/null
+++ b/Seyounth.Hyosung.Core/Agv/HikModels/AgvPosition.cs
@@ -0,0 +1,8 @@
+namespace Seyounth.Hyosung.Core.Agv.HikModels;
+
+public class AgvPosition
+{
+ public string PositionCode { get; set; }
+
+ public string Type { get; set; }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Core/Agv/HikModels/AgvStatusInfo.cs b/Seyounth.Hyosung.Core/Agv/HikModels/AgvStatusInfo.cs
new file mode 100644
index 0000000..6f16c67
--- /dev/null
+++ b/Seyounth.Hyosung.Core/Agv/HikModels/AgvStatusInfo.cs
@@ -0,0 +1,27 @@
+namespace Seyounth.Hyosung.Core.Agv.HikModels;
+
+public class AgvStatusInfo
+{
+ ///
+ /// 机器人编号
+ ///
+ public string RobotCode { get; set; }
+ public string RobotDir { get; set; }
+ public string RobotIp { get; set; }
+ public string MapCode { get; set; }
+ public string posX { get; set; }
+ public string posY { get; set; }
+ ///
+ /// 电量值
+ ///
+ public string Battery { get; set; }
+ public string Status { get; set; }
+ ///
+ /// 是否已被排除,被排除后不接受新任务( 1-排除, 0-正常)
+ public string exclType { get; set; }
+ ///
+ /// 是否暂停 0-否 1-是
+ ///
+ public string Stop { get; set; }
+
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Core/Agv/HikModels/HikApiResult.cs b/Seyounth.Hyosung.Core/Agv/HikModels/HikApiResult.cs
new file mode 100644
index 0000000..edba9fd
--- /dev/null
+++ b/Seyounth.Hyosung.Core/Agv/HikModels/HikApiResult.cs
@@ -0,0 +1,24 @@
+namespace Seyounth.Hyosung.Core.Agv.HikModels;
+
+public class HikApiResult
+{
+ ///
+ /// 返回码
+ ///
+ public string Code { get; set; }
+
+ ///
+ /// 返回消息
+ ///
+ public string Message { get; set; }
+
+ ///
+ /// 请求编号
+ ///
+ public string ReqCode { get; set; }
+
+ ///
+ /// 自定义返回
+ ///
+ public TData Data { get; set; }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Core/Agv/HyosungAgvService.cs b/Seyounth.Hyosung.Core/Agv/HyosungAgvService.cs
new file mode 100644
index 0000000..68212a8
--- /dev/null
+++ b/Seyounth.Hyosung.Core/Agv/HyosungAgvService.cs
@@ -0,0 +1,42 @@
+using Microsoft.Extensions.Logging;
+using Seyounth.Hyosung.Core.Agv.HikModels;
+using Seyounth.Hyosung.Data.Services;
+
+namespace Seyounth.Hyosung.Core.Agv;
+
+public class HyosungAgvService(
+ ILoggerFactory loggerFactory,
+ IAgvBinService agvBinService,
+ ITrayService trayService,
+ IDictService dictService) : IHyosungAgvService
+{
+ private readonly HikAgv _agv = new HikAgv(loggerFactory.CreateLogger());
+
+
+ public async Task StorageAsync(string trayCode)
+ {
+ AgvStatusInfo? status;
+ do
+ {
+ status = await _agv.GetAgvStatus("BB", "4083");
+ await Task.Delay(1000);
+ } while (status is null);
+
+ var tray = await trayService.GetByCode(trayCode);
+ var height = (int)Math.Ceiling((double)(tray.StackHeight / 10.0)!);
+ var bin = await agvBinService.GetAvailableBin(height);
+ AgvPosition start = new AgvPosition()
+ {
+ PositionCode = "A1",
+ Type = "00"
+ };
+ var stop = new AgvPosition()
+ {
+ PositionCode = bin.CtnrCode,
+ Type = "05"
+ };
+ var ctnrType = await dictService.GetKeyAsync("AgvRackType", height.ToString());
+ await _agv.CarryToAsync(start, stop, ctnrType, 120, "1");
+ await agvBinService.BindAsync(bin);
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Core/Agv/IHyosungAgvService.cs b/Seyounth.Hyosung.Core/Agv/IHyosungAgvService.cs
new file mode 100644
index 0000000..a94d7a0
--- /dev/null
+++ b/Seyounth.Hyosung.Core/Agv/IHyosungAgvService.cs
@@ -0,0 +1,11 @@
+namespace Seyounth.Hyosung.Core.Agv;
+
+public interface IHyosungAgvService
+{
+ ///
+ /// 入库
+ ///
+ ///
+ ///
+ Task StorageAsync(string trayCode);
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Core/Plc/HyosungPlcService.cs b/Seyounth.Hyosung.Core/Plc/HyosungPlcService.cs
new file mode 100644
index 0000000..c4c9d2e
--- /dev/null
+++ b/Seyounth.Hyosung.Core/Plc/HyosungPlcService.cs
@@ -0,0 +1,301 @@
+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 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)
+ {
+ token = token;
+ List> 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> 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]");
+ }
+
+ public async Task WriteScanYarnResultAsync(bool result, short? varietyId = null, string? yarnCode = null)
+ {
+ if (result && yarnCode != null && varietyId != null)
+ {
+ await _writer.WriteShortsAsync(4009, varietyId.Value);
+ await _writer.WriteStringAsync(4010, yarnCode);
+ 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()
+ {
+ await _writer.WriteShortsAsync(4020, 0);
+ await _writer.WriteShortsAsync(13012, 0);
+ await _writer.WriteShortsAsync(4520, 1);
+ isLeaving = false;
+ }
+
+ public async Task WriteTrayCodeAsync(int index, string trayCode)
+ {
+ var address = index == 1 ? 4100 : 4110;
+ await _writer.WriteStringAsync(address, trayCode);
+ }
+
+ public async Task WriteReceivedYarnCountAsync(int count)
+ {
+ await _writer.WriteShortsAsync(4120, (short)count);
+ }
+
+ public async Task WritePackLineOptionAsync(PackLineOption option)
+ {
+ List ls = new List();
+ ls.Add((short)option.HeadCount);
+ ls.Add((short)(option.IsTop ? 1 : 2));
+ await _writer.WriteShortsAsync(12120, ls.ToArray());
+ ls.Clear();
+ 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));
+ await _writer.WriteShortsAsync(12123, ls.ToArray());
+ }
+
+ public async Task WritePrintLabelResultAsync(int index, bool result)
+ {
+ var address = index == 1 ? 13060 : 13061;
+ await _writer.WriteShortsAsync(address, (short)(result ? 1 : 2));
+ }
+
+
+ public event Func? OnPlcRequestScanProduct;
+
+ public event Func? OnPlcRequestScanFixture;
+
+ public event Func? OnPlcRequestLeavingProductionLine;
+
+ public event Func? OnPlcNeedNewTrayCode;
+
+ public event Func? OnPlcPutCompleted;
+
+ public event Func? OnPlcRequestPackLineOption;
+
+ public event Func? OnRequestPrintLabel;
+
+
+ private async Task ReadLoop(CancellationToken token)
+ {
+ while (!token.IsCancellationRequested)
+ {
+ await QueryScanProductRequest();
+ await QueryScanFixtureRequest();
+ if (!isLeaving)
+ await QueryLeavingProductionLine();
+ await QueryNeedTrayCode();
+ await QueryPutOnceCompleted();
+ await QueryPackLineOption();
+ await QueryPrintLabel();
+ await Task.Delay(100, token);
+ }
+ }
+
+ ///
+ /// 查询请求扫描产品方法
+ ///
+ private async Task QueryScanProductRequest()
+ {
+ var requestScanProduct = await _reader.ReadShortsAsync(4500, 2);
+ if (requestScanProduct[0] == 1)
+ {
+ OnPlcRequestScanProduct?.Invoke(requestScanProduct[1]);
+ //清空请求标志位
+ await _writer.WriteShortsAsync(4500, 0, 0);
+ }
+ }
+
+ ///
+ /// 查询扫描夹具请求
+ ///
+ private async Task QueryScanFixtureRequest()
+ {
+ var requestScanFixture = await _reader.ReadShortsAsync(4505, 4);
+ if (requestScanFixture[0] == 1)
+ {
+ await _writer.WriteShortsAsync(4505, 0);
+ OnPlcRequestScanFixture?.Invoke(1);
+ }
+
+ if (requestScanFixture[1] == 1)
+ {
+ await _writer.WriteShortsAsync(4506, 0);
+ OnPlcRequestScanFixture?.Invoke(2);
+ }
+
+ if (requestScanFixture[2] == 1)
+ {
+ await _writer.WriteShortsAsync(4507, 0);
+ await OnPlcRequestScanFixture?.Invoke(3);
+ }
+ if (requestScanFixture[3] == 1)
+ {
+ await _writer.WriteShortsAsync(4508, 0);
+ await OnPlcRequestScanFixture?.Invoke(4);
+ }
+
+ }
+
+ ///
+ /// 查询有托盘请求下线
+ ///
+ private async Task QueryLeavingProductionLine()
+ {
+ var leavingProductionLine = await _reader.ReadShortsAsync(4020, 1);
+ // var stackStatus = await _reader.ReadShortsAsync(12110, 1);
+ if (leavingProductionLine[0] == 1)
+ {
+ var trayCode = await _reader.ReadStringAsync(12600);
+ if (!string.IsNullOrEmpty(trayCode))
+ {
+ PlcStackInfo info = new PlcStackInfo()
+ {
+ TrayCode = trayCode
+ };
+ isLeaving = true;
+ OnPlcRequestLeavingProductionLine?.Invoke(info);
+ }
+ }
+ }
+
+ ///
+ /// 查询是否需要新的托盘号
+ ///
+ private async Task QueryNeedTrayCode()
+ {
+ var n1 = await _reader.ReadShortsAsync(4600, 2);
+ var n2 = await _reader.ReadShortsAsync(4610, 2);
+ if (n1[0] == 1)
+ {
+ OnPlcNeedNewTrayCode?.Invoke(1, n1[1]);
+ await _writer.WriteShortsAsync(4600, 0);
+ }
+
+ if (n2[0] == 1)
+ {
+ OnPlcNeedNewTrayCode?.Invoke(2, n2[1]);
+ await _writer.WriteShortsAsync(4610, 0);
+ }
+ }
+
+ private async Task QueryPutOnceCompleted()
+ {
+ var status = await _reader.ReadShortsAsync(4691, 2);
+ if (status[0] == 1)
+ {
+ var trayCode = await _reader.ReadStringAsync(4620);
+ var yarn1 = await _reader.ReadStringAsync(4630);
+ var yarn2 = await _reader.ReadStringAsync(4640);
+ var yarn3 = await _reader.ReadStringAsync(4650);
+ var info = new PlcStackingInfo()
+ {
+ TrayCode = trayCode,
+ YarnCount = status[0],
+ TotalYarnCount = status[1]
+ };
+ if (!string.IsNullOrEmpty(yarn1))
+ info.YarnCode.Add(yarn1);
+ if (!string.IsNullOrEmpty(yarn2))
+ info.YarnCode.Add(yarn2);
+ if (!string.IsNullOrEmpty(yarn3))
+ info.YarnCode.Add(yarn3);
+ if (info.YarnCode.Count != info.YarnCount)
+ {
+ logger.LogWarning($"get yarn code count[{info.YarnCode.Count}]不等于YarnCount[{info.TotalYarnCount}]");
+ return;
+ }
+
+ await _writer.WriteShortsAsync(4690, 0, 0, 0);
+ await _writer.WriteShortsAsync(4620, new short[40]);
+ OnPlcPutCompleted?.Invoke(info);
+ }
+ }
+
+ ///
+ /// 打包线请求获取配置
+ ///
+ private async Task QueryPackLineOption()
+ {
+ var requestPackLineOption = await _reader.ReadShortsAsync(4022, 1);
+ if (requestPackLineOption[0] == 1)
+ {
+ var trayCode = await _reader.ReadStringAsync(12100);
+ await _writer.WriteShortsAsync(4022, 0);
+ OnPlcRequestPackLineOption?.Invoke(trayCode);
+ }
+ }
+
+ private async Task QueryPrintLabel()
+ {
+ var requestPrintLabel = await _reader.ReadShortsAsync(13010, 3);
+ if (requestPrintLabel[0] == 1)
+ {
+ var trayCode = await _reader.ReadStringAsync(13000);
+ await _writer.WriteShortsAsync(13010, 0);
+ await _writer.WriteShortsAsync(13012, 0);
+ OnRequestPrintLabel?.Invoke(1, trayCode, requestPrintLabel[2]);
+ }
+
+ if (requestPrintLabel[1] == 1)
+ {
+ var trayCode = await _reader.ReadStringAsync(13001);
+ await _writer.WriteShortsAsync(13011, 0);
+ await _writer.WriteShortsAsync(13012, 0);
+ OnRequestPrintLabel?.Invoke(2, trayCode, requestPrintLabel[2]);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Core/Plc/IHyosungPlcService.cs b/Seyounth.Hyosung.Core/Plc/IHyosungPlcService.cs
new file mode 100644
index 0000000..ed87387
--- /dev/null
+++ b/Seyounth.Hyosung.Core/Plc/IHyosungPlcService.cs
@@ -0,0 +1,97 @@
+using Seyounth.Hyosung.Data.Models;
+using Seyounth.Hyosung.Data.Models.Plc;
+
+namespace Seyounth.Hyosung.Core.Plc;
+
+public interface IHyosungPlcService
+{
+ Task StartAsync(CancellationToken token);
+
+ Task StopAsync();
+
+
+ ///
+ /// 写入品种到PLC
+ ///
+ ///
+ ///
+ Task WriteVarietyAsync(Variety variety);
+
+ ///
+ /// 写入扫码结果
+ ///
+ /// 结果
+ /// 品类ID
+ /// 纱码
+ ///
+ Task WriteScanYarnResultAsync(bool result, short? varietyId = null, string? yarnCode = null);
+
+ ///
+ /// 写入治具扫码结果
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task WriteScanFixtureResultAsync(int fixtureId, bool result, short? fixtureCode = null);
+
+ ///
+ /// 下线完成
+ ///
+ ///
+ Task LeaveCompletedAsync();
+
+ ///
+ /// 写入托盘号
+ ///
+ ///
+ ///
+ ///
+ Task WriteTrayCodeAsync(int index, string trayCode);
+
+ ///
+ /// 写入收到的纱数量
+ ///
+ ///
+ ///
+ Task WriteReceivedYarnCountAsync(int count);
+
+ Task WritePackLineOptionAsync(PackLineOption option);
+
+ Task WritePrintLabelResultAsync(int index, bool result);
+
+ ///
+ /// Plc请求扫描产品
+ ///
+ event Func OnPlcRequestScanProduct;
+
+ ///
+ /// Plc请求扫描治具
+ ///
+ event Func OnPlcRequestScanFixture;
+
+ ///
+ /// Plc请求下线
+ ///
+ event Func OnPlcRequestLeavingProductionLine;
+
+ ///
+ /// Plc需要新的托盘号
+ ///
+ event Func OnPlcNeedNewTrayCode;
+
+ ///
+ /// Plc放入一次完成
+ ///
+ event Func OnPlcPutCompleted;
+
+ ///
+ /// Plc请求打包线选项
+ ///
+ event Func OnPlcRequestPackLineOption;
+
+ ///
+ /// 贴标站请求贴标
+ ///
+ event Func OnRequestPrintLabel;
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Core/Plc/McPlc.cs b/Seyounth.Hyosung.Core/Plc/McPlc.cs
new file mode 100644
index 0000000..96ddb77
--- /dev/null
+++ b/Seyounth.Hyosung.Core/Plc/McPlc.cs
@@ -0,0 +1,74 @@
+using MCProtocol;
+
+namespace Seyounth.Hyosung.Core.Plc;
+
+public class McPlc(string host, int port, Mitsubishi.McFrame type)
+{
+ private readonly Mitsubishi.McProtocolTcp _mc = new();
+
+
+ public async Task ConnectAsync()
+ {
+ _mc.HostName = host;
+ _mc.PortNumber = port;
+ _mc.CommandFrame = type;
+ return await _mc.Open();
+ }
+
+ public Task CloseAsync()
+ {
+ var code = _mc.Close();
+ _mc.Dispose();
+ return Task.FromResult(code);
+ }
+
+ public async Task ReadBytesAsync(int address, int length)
+ {
+ var code = await _mc.ReadDeviceBlock(Mitsubishi.PlcDeviceType.D, address, length / 2);
+ return code;
+ }
+
+ public async Task ReadShortsAsync(int address, int length)
+ {
+ var code = await _mc.ReadDeviceBlock(Mitsubishi.PlcDeviceType.D, address, length);
+ if (code is null || code.Length < length * 2)
+ throw new Exception("read short error");
+ var shorts = new short[length];
+ Buffer.BlockCopy(code, 0, shorts, 0, code.Length);
+ return shorts;
+ }
+
+ public async Task WriteShortsAsync(int address, params short[] values)
+ {
+ var code = await _mc.WriteDeviceBlock(Mitsubishi.PlcDeviceType.D, address, values.Length,
+ values.SelectMany(BitConverter.GetBytes).ToArray());
+ }
+
+ public async Task WriteBytesAsync(int address, byte[] data)
+ {
+ var code = await _mc.WriteDeviceBlock(Mitsubishi.PlcDeviceType.D, address, data.Length / 2, data);
+ }
+
+ public async Task ReadStringAsync(int address)
+ {
+ const int fixedLength = 20;
+ // 调用 ReadBytesAsync 方法读取字节数据,固定长度为 10
+ byte[] bytes = await ReadBytesAsync(address, fixedLength);
+ // 将字节数组使用 ASCII 编码转换为字符串
+ string result = System.Text.Encoding.ASCII.GetString(bytes);
+ // 去除字符串末尾可能存在的空字符
+ return result.TrimEnd('\0');
+ }
+
+ public async Task WriteStringAsync(int address, string value)
+ {
+ const int fixedLength = 10;
+ // 将字符串使用 ASCII 编码转换为字节数组
+ byte[] bytes = System.Text.Encoding.ASCII.GetBytes(value);
+ // 确保字节数组长度为 10
+ byte[] fixedLengthBytes = new byte[fixedLength];
+ Array.Copy(bytes, fixedLengthBytes, Math.Min(bytes.Length, fixedLength));
+ // 调用 WriteBytesAsync 方法写入字节数组
+ await WriteBytesAsync(address, fixedLengthBytes);
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Core/PrintTemp.json b/Seyounth.Hyosung.Core/PrintTemp.json
new file mode 100644
index 0000000..55bc61c
--- /dev/null
+++ b/Seyounth.Hyosung.Core/PrintTemp.json
@@ -0,0 +1,103 @@
+{
+ "Print": {
+ "DefaultTemp": "#!A1\n#N13\n#PC1017/0\n#IMR137/136.60\n#HV50\n#PR6//\n#PO0\n#ERNC/1//0.00\n#R0/0\n#T86 #J43 #FD/0/L #SS903/BVUN/180X73/0 #VW/L/\"250101J068\"#G\n#T62 #J43 #FD/0/L #SS903/BVUN/180X90/0 #VW/L/\"$965\"#G\n#T86 #J67 #FD/0/L #SS903/BVUN/180X100/0 #VW/L/\"25-01-01\"#G\n#T45 #J43 #FD/0/L #SS903/BVUN/180X85/0 #VW/L/\"$90\"#G\n#T7 #J46 #FD/0/L #SS903/BVUN/400X131/0 #VW/L/\"$1153\"#G\n#T62 #J67 #FD/0/L #SS903/BVUN/180X90/0 #VW/L/\"$900\"#G\n#T45 #J67 #FD/0/L #SS903/BVUN/180X90/0 #VW/L/\"$SA\"#G\n#T45 #J102 #FD/0/L #SS903/BVUN/138X84/0 #VW/L/\"1670dtex -144F\"#G\n#T50 #J92 #FD/0/L #SS903/BVUN/138X84/0 #VW/L/\"1500D - 144F\"#G\n#T17#J7 #FD/0/L #SB3/MNKP2.0/11.00/3 #VW/L/\"DTYY-JPA11530SFG250101000900115305480\"#G\n#Q1#G\n#!P1",
+ "Partition": "#!A1\n#N13\n#PC1017/0\n#IMR120/100\n#HV50\n#PR6//\n#PO0\n#ERNC/1//0.00\n#R0/0\n#T7.19 #J42.16 #YR0/0/0.84/97.62/32.93#G\n#T7.19 #J59.52 #YL0/0/1.01/97.02#G\n#T12.86 #J65.19 #FD/0/L #SS101/OVUN/75X75/0 #VW/L/\"Lot No\"#G\n#T36.23 #J43.01 #YL0/0/32.08/1.01#G\n#T16.25 #J48.68 #FD/0/L #SS101/OVUN/75X75/0 #VW/L/\"POS\"#G\n#T61.55 #J65.19 #FD/0/L #SS101/OVUN/75X75/0 #VW/L/\"1569\"#G\n#T49.86 #J48.68 #FD/0/L #SS101/OVUN/75X75/0 #VW/L/\"T1 T2 T3 T4 T5\"#G\n#Q1#G\n#!P1",
+ "Sides": [
+ {
+ "ItemCode": "TYY-JPA11530SFG",
+ "TempName": "SAAAYarn"
+ },{
+ "ItemCode": "TYY-JPA115301HG",
+ "TempName": "AAYarn"
+ },{
+ "ItemCode": "TYY-JPE147101DI",
+ "TempName": "Coats"
+ },{
+ "ItemCode": "TYY-JPE158501DI",
+ "TempName": "Coats"
+ },{
+ "ItemCode": "TYY-JPE158301DI",
+ "TempName": "Coats"
+ },{
+ "ItemCode": "TYY-JWE804101QI",
+ "TempName": "Coats"
+ },{
+ "ItemCode": "TYY-JWE802501E1",
+ "TempName": "GRSInternational"
+ },{
+ "ItemCode": "TYY-JWD802101EL",
+ "TempName": "GRSInternational"
+ },{
+ "ItemCode": "TYY-JWD801001EL",
+ "TempName": "GRSInternational"
+ },{
+ "ItemCode": "TYY-JWD807001EL",
+ "TempName": "GRSInternational"
+ },{
+ "ItemCode": "TYY-JWD801101EL",
+ "TempName": "GRSInternational"
+ },{
+ "ItemCode": "TYY-JWD802101EL",
+ "TempName": "Address"
+ },{
+ "ItemCode": "TYY-JWD802201EL",
+ "TempName": "Address"
+ },{
+ "ItemCode": "JWD801101EL",
+ "TempName": "Address"
+ },{
+ "ItemCode": "JWD805001EL",
+ "TempName": "Address"
+ },{
+ "ItemCode": "JWD802001EL",
+ "TempName": "Address"
+ },{
+ "ItemCode": "JWD801001EL",
+ "TempName": "Address"
+ },{
+ "ItemCode": "JWD807001EL",
+ "TempName": "Address"
+ },{
+ "ItemCode": "JWD808001EL",
+ "TempName": "Address"
+ },{
+ "ItemCode": "TYY-JPA11530SFG",
+ "TempName": "SA"
+ },{
+ "ItemCode": "TYY-JPA115301HG",
+ "TempName": "Weft"
+ }
+
+ ],
+ "Temps": [
+ {
+ "Name": "AAYarn",
+ "Code": "#!A1\n#N13\n#PC1017/0\n#IMR120/100\n#HV50\n#PR6//\n#PO0\n#ERNC/1//0.00\n#R0/0\n#T7.02 #J8.21 #YR0/0/1.01/106.08/84.75#G\n#T7.02 #J78.99 #YL0/0/1.01/106.00#G\n#T7.02 #J65.95 #YL0/0/1.01/106.00#G\n#T7.02 #J53.00 #YL0/0/1.01/106.00#G\n#T7.02 #J19.98 #YL0/0/1.01/106.00#G\n#T39.96 #J8.04 #YL0/0/83.98/1.01#G\n#T13.97 #J86.61 #FD/0/L #SS101/OVUN/41X41/4 #VW/L/\"Part Name\"#G\n#T16.00 #J82.38 #FD/0/L #SS903/OVUN/41X41/4 #VW/L/\"产品名称\"#G\n#T9.99 #J73.57 #FD/0/L #SS101/OVUN/41X41/4 #VW/L/\"Supplier Name\"#G\n#T14.22 #J69.34 #FD/0/L #SS903/OVUN/41X41/4 #VW/L/\"供应商名称\"#G\n#T13.03 #J60.62 #FD/0/L #SS101/OVUN/41X41/4 #VW/L/\"Material No.\"#G\n#T20.48 #J56.38 #FD/0/L #SS903/OVUN/41X41/4 #VW/L/\"料号\"#G\n#T18.03 #J36.57 #FD/0/L #SS101/OVUN/41X41/4 #VW/L/\"Lot No.\"#G\n#T20.99 #J32.34 #FD/0/L #SS903/OVUN/41X41/4 #VW/L/\"批次\"#G\n#T20.48 #J15.57 #FD/0/L #SS101/OVUN/41X41/4 #VW/L/\"Qty.\"#G\n#T18.03 #J11.34 #FD/0/L #SS903/OVUN/41X41/4 #VW/L/\"数量Kg\"#G\n#T49.02 #J84.58 #FD/0/L #SS903/OVUN/41X41/4 #VW/L/\"1153, 550dtex/144f, (AA纬丝)\"#G\n#T59.01 #J71.62 #FD/0/L #SS903/OVUN/41X41/4 #VW/L/\"晓星化纤(嘉兴)#G\n#T57.99 #J59.60 #FD/0/L #SS101/OVUN/41X41/4 #VW/L/\"TYY-JPA115301HG\"#G\n#T72.98 #J13.63 #FD/0/L #SS101/OVUN/41X41/4 #VW/L/\"900\"#G\n#Q1#G\n#!P1\n"
+ },
+ {
+ "Name": "Address",
+ "Code": "#!A1\n#N13\n#PC1017/0\n#IMR120/100\n#HV50\n#PR6//\n#PO0\n#ERNC/1//0.00\n#R0/0\n#T3.81 #J4.40 #YR0/0/1.01/112.01/91.52#G\n#T4.40 #J82.04 #YL0/0/1.01/110.65#G\n#T4.82 #J69.00 #YL0/0/1.01/109.98#G\n#T4.82 #J41.06 #YL0/0/1.01/110.15#G\n#T3.81 #J28.53 #YL0/0/1.01/110.91#G\n#T4.57 #J16.25 #YL0/0/1.01/110.15#G\n#T50.37 #J4.99 #YL0/0/90.00/1.01#G\n#T6.35 #J87.03 #FD/0/L #SS903/OVUN/38X38/4 #VW/L/\"生产单位/Product\"#G\n#T54.35 #J87.03 #FD/0/L #SS903/OVUN/38X38/0 #VW/L/\"晓星化纤(嘉兴)有限公司\"#G\n#T6.68 #J74.59 #FD/0/L #SS903/OVUN/38X38/4 #VW/L/\"生产地址/Address\"#G\n#T6.43 #J53.67 #FD/0/L #SS903/OVUN/38X38/4 #VW/L/\"认证编号/Certifation No\"#G\n#T53.59 #J73.00 #YG/0///GREEN.jpg#G\n#T6.01 #J34.12 #FD/0/L #SS903/OVUN/38X38/4 #VW/L/\"品名/Narne of Product\"#G\n#T6.18 #J21.75 #FD/0/L #SS903/OVUN/38X38/4 #VW/L/\"净重/Suttle\"#G\n#T6.18 #J9.73 #FD/0/L #SS903/OVUN/38X38/4 #VW/L/\"毛重/Gross Weight\"#G\n#T51.39 #J54.18 #YL0/0/1.01/63.66#G\n#T53.59 #J9.73 #FD/0/L #SS101/OVUN/38X38/4 #VW/L/\"630.0KG\"#G\n#T53.59 #J21.75 #FD/0/L #SS101/OVUN/38X38/4 #VW/L/\"563.5KG\"#G\n#T53.59 #J32.60 #YG/0///ADRESS.jpg#G\n#T53.59 #J47.07 #FD/0/L #SS101/OVUN/38X38/0 #VW/L/\"100% post-consumer polyester\"#G\n#T53.59 #J60.70 #FD/0/L #SS101/OVUN/38X38/4 #VW/L/\"CU 1041627\"#G\n#Q1#G\n#!P1\n"
+ },
+ {
+ "Name": "Coats",
+ "Code": "#!A1\n#N13\n#PC1017/0\n#IMR120/100\n#HV50\n#PR6//\n#PO0\n#ERNC/1//0.00\n#R0/0\n#T4.31 #J3.72 #YR0/0/1.01/111.33/91.94#G\n#T4.31 #J80.34 #YL0/0/1.01/111.25#G\n#T4.31 #J64.43 #YL0/0/1.01/108.79#G\n#T4.31 #J48.17 #YL0/0/1.01/110.65#G\n#T4.31 #J32.68 #YL0/0/1.01/110.74#G\n#T4.31 #J17.44 #YIB13/168/\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\u20ac \uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5? \uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5? \uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5? \uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5? \uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5? \uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5? \uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5? \uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5? \uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5? \uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5? \uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5? \uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5\uf8f5? \n#T61.04 #J4.65 #YL0/0/90.00/1.01#G\n#T27.00 #J85.76 #FD/0/L #SS101/OVUN/66X66/4 #VW/L/\"Site\"#G\n#T78.82 #J86.27 #FD/0/L #SS101/OVUN/66X66/4 #VW/L/\"JiaXing\"#G\n#T24.21 #J71.12 #FD/0/L #SS101/OVUN/66X66/4 #VW/L/\"Denier\"#G\n#T83.65 #J70.61 #FD/0/L #SS101/OVUN/66X66/4 #VW/L/\"70d\"#G\n#T21.33 #J54.94 #FD/0/L #SS101/OVUN/66X66/4 #VW/L/\"Filament\"#G\n#T84.32 #J54.77 #FD/0/L #SS101/OVUN/66X66/4 #VW/L/\"24f\"#G\n#T28.53 #J38.86 #FD/0/L #SS101/OVUN/66X66/4 #VW/L/\"Lot\"#G\n#T81.95 #J39.20 #FD/0/L #SS101/OVUN/66X66/4 #VW/L/\"1471\"#G\n#T18.71 #J27.17 #FD/0/L #SS101/OVUN/66X66/4 #VW/L/\"Sap Code\"#G\n#T22.69 #J20.32 #FD/0/L #SS101/OVUN/66X66/4 #VW/L/\"(coats)\"#G\n#T75.43 #J23.19 #FD/0/L #SS101/OVUN/66X66/4 #VW/L/\"86300005\"#G\n#T16.00 #J12.36 #FD/0/L #SS101/OVUN/66X66/4 #VW/L/\"Merge Code\"#G\n#T23.28 #J5.50 #FD/0/L #SS101/OVUN/66X66/4 #VW/L/\"(coats)\"#G\n#T76.62 #J8.89 #FD/0/L #SS101/OVUN/66X66/4 #VW/L/\"R000836\"#G\n#Q1#G\n#!P1\n"
+ },
+ {
+ "Name": "GRSInternational",
+ "Code": "#!A1\n#N13\n#PC1017/0\n#IMR120/100\n#HV50\n#PR6//\n#PO0\n#ERNC/1//0.00\n#R0/0\n#T19 #J20 #FD/0/L #SS903/OVUN/100X100/0 #VW/L/\"GRS国际回收认证\"#G\n#T23 #J28#YG/0///GRS.jpg#G\n#Q1#G\n#!P1\n"
+ },
+ {
+ "Name": "GRSTemp",
+ "Code": "#!A1\n#N13\n#PC1017/0\n#IMR137/136.60\n#HV50\n#PR6//\n#PO0\n#ERNC/1//0.00\n#R0/0\n#T87 #J45 #FD/0/L #SS903/BVUN/63X80/0 #VW/L/\"250101J068\"#G\n#T62 #J45 #FD/0/L #SS903/BVUN/72X117/0 #VW/L/\"$965\"#G\n#T87 #J70 #FD/0/L #SS903/BVUN/72X117/0 #VW/L/\"25-01-01\"#G\n#T45 #J45 #FD/0/L #SS903/BVUN/72X125/0 #VW/L/\"$90\"#G\n#T5 #J50 #FD/0/L #SS903/BVUN/342X171/0 #VW/L/\"$1153\"#G\n#T62 #J70 #FD/0/L #SS903/BVUN/72X117/0 #VW/L/\"$900\"#G\n#T45 #J70 #FD/0/L #SS903/BVUN/60X125/0 #VW/L/\"$SA\"#G\n#T45 #J102 #FD/0/L #SS903/BVUN/84X138/0 #VW/L/\"1670dtex -144F\"#G\n#T47 #J94 #FD/0/L #SS903/BVUN/84X138/0 #VW/L/\"1500D - 144F\"#G\n#T7#J7 #FD/0/L #SB3/MNKP2.0/11.00/4 #VW/L/\"DTYY-JPA11530SFG250101000900115305480\"#G\n#Q1#G\n#!P1"
+ },
+ {
+ "Name": "Welf",
+ "Code": "#!A1\n#N13\n#PC1017/0\n#IMR120/100\n#HV50\n#PR6//\n#PO0\n#ERNC/1//0.00\n#R0/0\n#T36.99 #J57.23 #FD/0/L #SS101/OVUN/266X266/0 #VW/L/\"Weft\"#G\n#T36.99 #J30.14 #FD/0/L #SS101/OVUN/266X266/0 #VW/L/\"Only\"#G\n#Q1#G\n#!P1\n"
+ },
+ {
+ "Name": "SA",
+ "Code": "#!A1\n#N13\n#PC1017/0\n#IMR120/100\n#HV50\n#PR6//\n#PO0\n#ERNC/1//0.00\n#R0/0\n#T7.78 #J6.01 #YR0/0/1.01/110.49/90.93#G\n#T19.21 #J55.62 #FD/0/L #SS101/OVUN/229X204/4 #VW/L/\"SA Grade\"#G\n#T23.70 #J32.34 #FD/0/L #SS101/OVUN/229X204/4 #VW/L/\"for Warp\"#G\n#T6.26 #J6.01 #YL0/0/1.01/3.38#G\n#Q1#G\n#!P1\n"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Core/Printer/AveryPrinter.cs b/Seyounth.Hyosung.Core/Printer/AveryPrinter.cs
new file mode 100644
index 0000000..b3a0ac8
--- /dev/null
+++ b/Seyounth.Hyosung.Core/Printer/AveryPrinter.cs
@@ -0,0 +1,47 @@
+using System.Net.Sockets;
+using System.Text;
+
+namespace Seyounth.Hyosung.Core.Printer;
+
+public class AveryPrinter(string host, int port)
+{
+ public string Host => host;
+ public int Port => port;
+ private readonly Socket _socket = new(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
+
+ public async Task ConnectAsync(CancellationToken token)
+ {
+ try
+ {
+ await _socket.ConnectAsync(Host, Convert.ToInt32(port), token);
+ }catch(Exception e)
+ {
+ Console.WriteLine($"Host[{Host}:{port}] error:{e.Message}");
+ }
+
+ }
+
+ public async Task CloseAsync(CancellationToken token)
+ {
+ await _socket.DisconnectAsync(true, token);
+ _socket.Dispose();
+ }
+
+ public async Task SendContentAsync(string context)
+ {
+ await _socket.SendAsync(Encoding.UTF8.GetBytes(context));
+ }
+
+ private const string CleanCmd = "#!A1#!CA#!P1";
+ private const string PrintCmd = "#!A1#!D#!P1";
+
+ public async Task CleanContextAsync()
+ {
+ await _socket.SendAsync(Encoding.UTF8.GetBytes(CleanCmd));
+ }
+
+ public async Task PrintAsync()
+ {
+ await _socket.SendAsync(Encoding.UTF8.GetBytes(PrintCmd));
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Core/Printer/HyosungPrinter.cs b/Seyounth.Hyosung.Core/Printer/HyosungPrinter.cs
new file mode 100644
index 0000000..c35e2b3
--- /dev/null
+++ b/Seyounth.Hyosung.Core/Printer/HyosungPrinter.cs
@@ -0,0 +1,132 @@
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using Seyounth.Hyosung.Data.Models;
+using Seyounth.Hyosung.Data.Services;
+using Seyounth.Hyosung.Data.Services.Hyosung;
+
+namespace Seyounth.Hyosung.Core.Printer;
+
+public class HyosungPrinter(
+ ILogger logger,
+ IVarietyService varietyService,
+ ITrayService trayService,
+ IDictService dictService,
+ IYarnService yarnService,
+ IHyosungWmsService hyosungWmsService,
+ IOptions options) : IHyosungPrinter
+{
+ private readonly AveryPrinter _masterPrinter = new("192.168.3.60", 9100);
+ private readonly AveryPrinter _slavePrinter = new("192.168.3.61", 9100);
+
+ public async Task StartAsync(CancellationToken token)
+ {
+ List ls = new List();
+ ls.Add(_masterPrinter.ConnectAsync(token)) ;
+ ls.Add(_slavePrinter.ConnectAsync(token)) ;
+ await Task.WhenAll(ls);
+ logger.LogInformation("printer connected");
+ }
+
+ public async Task StopAsync(CancellationToken token)
+ {
+ await _masterPrinter.CloseAsync(token);
+ await _slavePrinter.CloseAsync(token);
+ logger.LogInformation("printer disconnected");
+ }
+
+ public async Task PrintAsync(int index, string trayCode)
+ {
+ var tray = await trayService.GetByCode(trayCode);
+ if (index == 1)
+ {
+ await PrintLabel1Async(tray);
+ }
+ else
+ {
+ await PrintLabel2Async(tray);
+ }
+ }
+
+ private async Task PrintLabel1Async(Tray tray)
+ {
+ await _masterPrinter.CleanContextAsync();
+ var content = await GetPrint1Content(tray);
+ await _masterPrinter.SendContentAsync(content);
+ await _masterPrinter.PrintAsync();
+ }
+
+ private async Task PrintLabel2Async(Tray tray)
+ {
+ await _slavePrinter.CleanContextAsync();
+ var content = await GetPrint2Content(tray);
+ await _slavePrinter.SendContentAsync(content);
+ await _slavePrinter.PrintAsync();
+ }
+
+ private async Task GetPrint1Content(Tray tray)
+ {
+ var variety = await varietyService.GetById(tray.VarietyId);
+ var yarns = await yarnService.GetYarnsByTrayIdAsync(tray.VarietyId);
+ var dic = new Dictionary();
+ if (yarns.Count > 0)
+ {
+ var machineNoList = yarns
+ .Where(item => item.Machine.Contains('-'))
+ .Select(item => item.Machine.Split('-')[0])
+ .Distinct()
+ .ToList();
+
+ var machineStr = string.Join(" ", machineNoList);
+
+
+ dic.Add("1569", yarns[0].Lot.ToString());
+ dic.Add("T1 T2 T3 T4 T5", machineStr);
+ }
+
+ string temp;
+ if (variety.MasterLabelCount == 1)
+ temp = options.Value.Partition;
+ else
+ {
+ var tempName = options.Value.Sides.First(t => t.ItemCode == variety.Code).TempName;
+ temp = options.Value.Temps.First(t => t.Name == tempName).Code;
+ }
+
+ foreach (var (key, value) in dic)
+ {
+ temp = temp.Replace(key, value);
+ }
+
+ return temp;
+ }
+
+ private async Task GetPrint2Content(Tray tray)
+ {
+ var variety = await varietyService.GetById(tray.VarietyId);
+ var labelResult =
+ await hyosungWmsService.GetLabelResult(variety.Code, variety.Lot.ToString(), tray.ControlNo!.Value);
+ var dic = new Dictionary
+ {
+ { "$1153", $"\"{variety.Lot}\"" },
+ { "1670dtex -144F", $"\"{tray.DtexFila}\"" },
+ { "1500D - 144F", $"\"{tray.DenFila}\"" },
+ { "$SA", $"\"{tray.Grade}\"" },
+ { "$900", $"\"{labelResult.NET_WEIGHT}\"" },
+ { "25-01-01", $"\"{DateTime.Now:yy-MM-dd}\"" },
+ { "$90", $"\"{variety.TotalCount}\"" },
+ { "$965", $"\"{labelResult.GROSS_WEIGHT}\"" },
+ {
+ "250101J068",
+ $"\"{DateTime.Now.ToString("yyMMdd" + "J") + tray.ControlNo.ToString()?.PadLeft(3, '0')}\""
+ },
+ { "DTYY-JPA11530SFG250101000900115305480", $"\"{labelResult.BAR_CODE}\"" }
+ };
+ string content = options.Value.DefaultTemp;
+ foreach (var (key, value) in dic)
+ {
+ content = content.Replace(key, value);
+ }
+
+ return content;
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Core/Printer/IHyosungPrinter.cs b/Seyounth.Hyosung.Core/Printer/IHyosungPrinter.cs
new file mode 100644
index 0000000..4a2cbac
--- /dev/null
+++ b/Seyounth.Hyosung.Core/Printer/IHyosungPrinter.cs
@@ -0,0 +1,15 @@
+namespace Seyounth.Hyosung.Core.Printer;
+
+public interface IHyosungPrinter
+{
+ Task StartAsync(CancellationToken token);
+
+ Task StopAsync(CancellationToken token);
+
+ ///
+ /// 打印指定垛的标签
+ ///
+ ///
+ ///
+ Task PrintAsync(int index,string trayCode);
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Core/Printer/PrintTemp.cs b/Seyounth.Hyosung.Core/Printer/PrintTemp.cs
new file mode 100644
index 0000000..0b4e646
--- /dev/null
+++ b/Seyounth.Hyosung.Core/Printer/PrintTemp.cs
@@ -0,0 +1,26 @@
+namespace Seyounth.Hyosung.Core.Printer;
+
+public class PrintTemp
+{
+ public string DefaultTemp { get; set; }
+
+ public string Partition { get; set; }
+
+ public List Sides { get; set; }
+
+ public List Temps { get; set; }
+}
+
+public class Side
+{
+ public string ItemCode { get; set; }
+
+ public string TempName { get; set; }
+}
+
+public class TempData
+{
+ public string Name { get; set; }
+
+ public string Code { get; set; }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Core/Scanner/HikScanner.cs b/Seyounth.Hyosung.Core/Scanner/HikScanner.cs
new file mode 100644
index 0000000..5f0f473
--- /dev/null
+++ b/Seyounth.Hyosung.Core/Scanner/HikScanner.cs
@@ -0,0 +1,49 @@
+using System.Net.Sockets;
+using System.Text;
+using NetTaste;
+using Newtonsoft.Json.Linq;
+
+namespace Seyounth.Hyosung.Core.Scanner;
+
+public class HikScanner(string host, int port)
+{
+ public string Host => host;
+ public int Port => port;
+ private Socket _socket = new(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
+
+ public async Task ConnectAsync(CancellationToken token)
+ {
+ await _socket.ConnectAsync(Host, Port, token);
+ Console.WriteLine($"scanner[{Host}:{Port}] connected");
+ }
+
+ public async Task CloseAsync(CancellationToken token)
+ {
+ await _socket.DisconnectAsync(true, token);
+ _socket.Dispose();
+ }
+
+ public async Task ScanAsync()
+ {
+ try
+ {
+ byte[] cmd = "start"u8.ToArray();
+ await _socket.SendAsync(cmd);
+ byte[] buffer = new byte[1024];
+ int len = await _socket.ReceiveAsync(buffer).WaitAsync(TimeSpan.FromMilliseconds(2000));
+ cmd = "stop"u8.ToArray();
+ await _socket.SendAsync(cmd);
+ byte[] _ = new byte[1024];
+ while (_socket.Available > 0)
+ {
+ await _socket.ReceiveAsync(_, SocketFlags.None);
+ }
+ return Encoding.ASCII.GetString(buffer, 0, len);
+ }
+ catch (Exception e)
+ {
+ return string.Empty;
+ }
+ // 清空缓冲区 防止收到之前的数据
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Core/Scanner/HyosungScannerService.cs b/Seyounth.Hyosung.Core/Scanner/HyosungScannerService.cs
new file mode 100644
index 0000000..cee0d26
--- /dev/null
+++ b/Seyounth.Hyosung.Core/Scanner/HyosungScannerService.cs
@@ -0,0 +1,135 @@
+using System.Collections.Concurrent;
+using Microsoft.Extensions.Logging;
+using Seyounth.Hyosung.Data.Models;
+
+namespace Seyounth.Hyosung.Core.Scanner;
+
+public class HyosungScannerService : IHyosungScannerService
+{
+ private readonly List _yarnScanners = new();
+
+ private readonly ILogger _logger;
+
+ private readonly ConcurrentDictionary _fixtureScanners = new();
+
+
+ public HyosungScannerService(ILogger logger)
+ {
+ _yarnScanners.Add(new HikScanner("192.168.3.35", 2001));
+ _yarnScanners.Add(new HikScanner("192.168.3.36", 2001));
+ _yarnScanners.Add(new HikScanner("192.168.3.37", 2001));
+ _yarnScanners.Add(new HikScanner("192.168.3.38", 2001));
+ _yarnScanners.Add(new HikScanner("192.168.3.39", 2001));
+ _fixtureScanners.TryAdd(1, new HikScanner("192.168.3.31", 2001));
+ _fixtureScanners.TryAdd(2, new HikScanner("192.168.3.32", 2001));
+ _fixtureScanners.TryAdd(3, new HikScanner("192.168.3.33", 2001));
+ _fixtureScanners.TryAdd(4, new HikScanner("192.168.3.30", 2001));
+ _logger = logger;
+ }
+
+ public async Task StartAsync(CancellationToken token)
+ {
+
+ // 创建一个超时任务
+ var timeoutTask = Task.Delay(2000, token);
+
+ // 为每个纱线扫描器创建一个带有超时的连接任务
+ var yarnScannerTasks = _yarnScanners.Select(scanner =>
+ {
+ var connectTask = scanner.ConnectAsync(token);
+ return Task.WhenAny(connectTask, timeoutTask);
+ }).ToList();
+
+ // 为每个夹具扫描器创建一个带有超时的连接任务
+ var fixtureScannerTasks = _fixtureScanners.Values.Select(scanner =>
+ {
+ var connectTask = scanner.ConnectAsync(token);
+ return Task.WhenAny(connectTask, timeoutTask);
+ }).ToList();
+
+ // 合并所有任务
+ var allTasks = new List();
+ allTasks.AddRange(yarnScannerTasks);
+ allTasks.AddRange(fixtureScannerTasks);
+
+ // 等待所有任务完成
+ await Task.WhenAll(allTasks);
+
+ // 检查每个任务是否超时
+ foreach (var task in yarnScannerTasks)
+ {
+ var innerTask = task as Task;
+ if (innerTask.Result == timeoutTask)
+ {
+ // 处理纱线扫描器连接超时的情况
+ Console.WriteLine($"纱线扫描器连接超时");
+ }
+ }
+
+ foreach (var task in fixtureScannerTasks)
+ {
+ var innerTask = task as Task;
+ if (innerTask.Result == timeoutTask)
+ {
+ // 处理夹具扫描器连接超时的情况
+ Console.WriteLine($"夹具扫描器连接超时");
+ }
+ }
+ // foreach (var scanner in _yarnScanners)
+ // {
+ // await scanner.ConnectAsync(token);
+ // }
+ //
+ // foreach (var fixtureScanner in _fixtureScanners)
+ // {
+ // await fixtureScanner.Value.ConnectAsync(token);
+ // }
+ }
+
+ public async Task StopAsync(CancellationToken token)
+ {
+ List ls = _yarnScanners.Select(scanner => scanner.CloseAsync(token)).ToList();
+ ls.AddRange(_fixtureScanners.Values.Select(scanner => scanner.CloseAsync(token)).ToList());
+ await Task.WhenAll(ls);
+ }
+
+ public async Task ScanYarnAsync(int varietyId)
+ {
+ List> ls = _yarnScanners.Select(scanner => scanner.ScanAsync()
+ .ContinueWith(task =>
+ {
+ if (task.IsCompletedSuccessfully && !string.IsNullOrEmpty(task.Result))
+ {
+ _logger.LogInformation($"scanner[{scanner.Host}:{scanner.Port}] scan yarn {task.Result}");
+ return Yarn.Create(task.Result, varietyId);
+ }
+
+ return null;
+ }))
+ .ToList();
+
+ while (ls.Count > 0)
+ {
+ // 使用 Task.WhenAny 方法等待任意一个任务完成
+ Task completedTask = await Task.WhenAny(ls);
+ // 移除已经完成的任务
+ ls.Remove(completedTask);
+ // 获取完成任务的结果
+ Yarn? result = await completedTask;
+ // 如果结果不为空,立即返回结果
+ if (result != null)
+ {
+ return result;
+ }
+ }
+
+ _logger.LogWarning($"all scanner no scan yarn");
+ // 如果所有任务都完成且没有找到非空结果,返回 null
+ return null;
+ }
+
+ public async Task ScanFixtureAsync(int fixtureId)
+ {
+ return await _fixtureScanners[fixtureId].ScanAsync();
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Core/Scanner/IHyosungScannerService.cs b/Seyounth.Hyosung.Core/Scanner/IHyosungScannerService.cs
new file mode 100644
index 0000000..e136916
--- /dev/null
+++ b/Seyounth.Hyosung.Core/Scanner/IHyosungScannerService.cs
@@ -0,0 +1,24 @@
+using Seyounth.Hyosung.Data.Models;
+
+namespace Seyounth.Hyosung.Core.Scanner;
+
+public interface IHyosungScannerService
+{
+ Task StartAsync(CancellationToken token);
+
+ Task StopAsync(CancellationToken token);
+
+ ///
+ /// 扫描纱
+ ///
+ ///
+ ///
+ Task ScanYarnAsync(int varietyId);
+
+ ///
+ /// 扫描治具
+ ///
+ ///
+ ///
+ Task ScanFixtureAsync(int fixtureId);
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Core/ServiceExtensions.cs b/Seyounth.Hyosung.Core/ServiceExtensions.cs
new file mode 100644
index 0000000..7b9e7e3
--- /dev/null
+++ b/Seyounth.Hyosung.Core/ServiceExtensions.cs
@@ -0,0 +1,20 @@
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Seyounth.Hyosung.Core.Agv;
+using Seyounth.Hyosung.Core.Plc;
+using Seyounth.Hyosung.Core.Printer;
+using Seyounth.Hyosung.Core.Scanner;
+
+namespace Seyounth.Hyosung.Core;
+
+public static class ServiceExtensions
+{
+ public static IServiceCollection AddHyosungServices(this IServiceCollection services,ConfigurationManager configuration)
+ {
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
+ return services;
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Core/Seyounth.Hyosung.Core.csproj b/Seyounth.Hyosung.Core/Seyounth.Hyosung.Core.csproj
new file mode 100644
index 0000000..4a42d67
--- /dev/null
+++ b/Seyounth.Hyosung.Core/Seyounth.Hyosung.Core.csproj
@@ -0,0 +1,24 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+
+
diff --git a/Seyounth.Hyosung.Data/Entities/AgvBinEntity.cs b/Seyounth.Hyosung.Data/Entities/AgvBinEntity.cs
new file mode 100644
index 0000000..e6143bd
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Entities/AgvBinEntity.cs
@@ -0,0 +1,34 @@
+using SqlSugar;
+
+namespace Seyounth.Hyosung.Data.Entities;
+
+[SugarTable("system_agv_bin", TableDescription = "AGV库位")]
+public class AgvBinEntity
+{
+ [SugarColumn(IsPrimaryKey = true, IsIdentity = true, ColumnDescription = "主键")]
+ public int Id { get; set; }
+
+ [SugarColumn(ColumnDescription = "库位编码")]
+ public string BinCode { get; set; }
+
+ [SugarColumn(ColumnDescription = "控制编码")]
+ public string CtnrCode { get; set; }
+
+ [SugarColumn(ColumnDescription = "控制类型")]
+ public int CtnrType { get; set; }
+
+ [SugarColumn(ColumnDescription = "库位类型")]
+ public int RackType { get; set; }
+
+ [SugarColumn(ColumnDescription = "是否空闲")]
+ public bool IsFree { get; set; }
+
+ [SugarColumn(ColumnDescription = "库位高度")]
+ public int Height { get; set; }
+
+ [SugarColumn(ColumnDescription = "上次使用时间")]
+ public DateTime? LastBindTime { get; set; }
+
+ [SugarColumn(ColumnDescription = "排序")]
+ public int Sort { get; set; }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Entities/DictEntity.cs b/Seyounth.Hyosung.Data/Entities/DictEntity.cs
new file mode 100644
index 0000000..75fbbef
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Entities/DictEntity.cs
@@ -0,0 +1,15 @@
+using SqlSugar;
+
+namespace Seyounth.Hyosung.Data.Entities;
+
+[SugarTable("system_dict", TableDescription = "字典表")]
+public class DictEntity
+{
+ public int Id { get; set; }
+
+ public string Key { get; set; }
+
+ public string Type { get; set; }
+
+ public string Value { get; set; }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Entities/PalletEntity.cs b/Seyounth.Hyosung.Data/Entities/PalletEntity.cs
new file mode 100644
index 0000000..82f5de3
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Entities/PalletEntity.cs
@@ -0,0 +1,26 @@
+using Seyounth.Hyosung.Data.Models;
+using SqlSugar;
+
+namespace Seyounth.Hyosung.Data.Entities;
+
+[SugarTable("system_pallet", "托盘纸盘规格表")]
+public class PalletEntity
+{
+ [SugarColumn(IsIdentity = true, IsPrimaryKey = true)]
+ public int Id { get; set; }
+
+ [SugarColumn(ColumnDescription = "板类型")]
+ public PalletType Type { get; set; }
+
+ [SugarColumn(ColumnDescription = "长")] public int Length { get; set; }
+
+ [SugarColumn(ColumnDescription = "宽")] public int Width { get; set; }
+
+ [SugarColumn(ColumnDescription = "高")] public int Height { get; set; }
+
+ [SugarColumn(ColumnDescription = "孔数量", IsNullable = true)]
+ public int? HoleCount { get; set; }
+
+ [SugarColumn(ColumnDescription = "是否是大孔", IsNullable = true)]
+ public bool? IsBigHole { get; set; }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Entities/ScannedYarnEntity.cs b/Seyounth.Hyosung.Data/Entities/ScannedYarnEntity.cs
new file mode 100644
index 0000000..cc731c2
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Entities/ScannedYarnEntity.cs
@@ -0,0 +1,52 @@
+using SqlSugar;
+
+namespace Seyounth.Hyosung.Data.Entities;
+
+[SugarTable("product_scanned_yarn", "扫描到的纱线信息")]
+public class ScannedYarnEntity
+{
+ [SugarColumn(IsIdentity = true, IsPrimaryKey = true, ColumnDescription = "ID")]
+ public int Id { get; set; }
+
+ [SugarColumn(ColumnDescription = "条码", Length = 255)]
+ public string QrCode { get; set; }
+
+ [SugarColumn(ColumnDescription = "纱线代码", Length = 20)]
+ public string ScanCode { get; set; }
+
+ [SugarColumn(ColumnDescription = "Lot")]
+ public int Lot { get; set; }
+
+ [SugarColumn(ColumnDescription = "DEN_FILA", IsNullable = true)]
+ public string? DenFila { get; set; }
+
+ [SugarColumn(ColumnDescription = "DTEX_FILA", IsNullable = true)]
+ public string? DtexFila { get; set; }
+
+ [SugarColumn(ColumnDescription = "生产班次")]
+ public string WorkShift { get; set; } = "NoData";
+
+ [SugarColumn(ColumnDescription = "生产机台")]
+ public string Machine { get; set; } = "NoData";
+
+ [SugarColumn(ColumnDescription = "所属品类信息")]
+ public int VarietyId { get; set; }
+
+ [SugarColumn(ColumnDescription = "扫描时间")]
+ public DateTime ScanTime { get; set; }
+
+ [SugarColumn(ColumnDescription = "生产时间")]
+ public string ProduceTime { get; set; }
+
+ [SugarColumn(ColumnDescription = "是否完成码垛")]
+ public bool IsFinished { get; set; } = false;
+
+ [SugarColumn(ColumnDescription = "所属托盘Id", IsNullable = true)]
+ public int? TrayId { get; set; }
+
+ [SugarColumn(ColumnDescription = "码垛时间", IsNullable = true)]
+ public DateTime? StackTime { get; set; }
+
+ [SugarColumn(ColumnDescription = "入库时间", IsNullable = true)]
+ public DateTime? StorageTime { get; set; }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Entities/TrayEntity.cs b/Seyounth.Hyosung.Data/Entities/TrayEntity.cs
new file mode 100644
index 0000000..a2f8a63
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Entities/TrayEntity.cs
@@ -0,0 +1,43 @@
+using SqlSugar;
+
+namespace Seyounth.Hyosung.Data.Entities;
+
+[SugarTable("product_tray", "生产托盘数据")]
+public class TrayEntity
+{
+ [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
+ public int Id { get; set; }
+
+ [SugarColumn(ColumnDescription = "托盘唯一号")]
+ public string TrayCode { get; set; }
+
+ [SugarColumn(ColumnDescription = "所属的品类信息")]
+ public int VarietyId { get; set; }
+
+ [SugarColumn(ColumnDescription = "垛高")]
+ public int? StackHeight { get; set; }
+
+ [SugarColumn(ColumnDescription = "是否为双号")]
+ public bool IsEven { get; set; }
+
+ [SugarColumn(ColumnDescription = "控制号 为空时说明尚未入库", IsNullable = true,
+ IndexGroupNameList = ["idx_ControlNo_CreateTime"])]
+ public int? ControlNo { get; set; }
+
+ [SugarColumn(ColumnDescription = "生成时间", IndexGroupNameList = ["idx_ControlNo_CreateTime"])]
+ public DateTime CreateTime { get; set; }
+
+ [SugarColumn(ColumnDescription = "入库时间", IsNullable = true)]
+ public DateTime? FinishTime { get; set; }
+
+
+ [SugarColumn(IsNullable = true)] public string? Grade { get; set; }
+ [SugarColumn(IsNullable = true)] public string? Type { get; set; }
+ [SugarColumn(IsNullable = true)] public string? DenFila { get; set; }
+ [SugarColumn(IsNullable = true)] public string? DtexFila { get; set; }
+ [SugarColumn(IsNullable = true)] public int? Unit { get; set; }
+ [SugarColumn(IsNullable = true)] public double NetWeight { get; set; }
+ [SugarColumn(IsNullable = true)] public double GrossWeight { get; set; }
+
+ [SugarColumn(IsNullable = true)] public int? AgvBinId { get; set; }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Entities/VarietyEntity.cs b/Seyounth.Hyosung.Data/Entities/VarietyEntity.cs
new file mode 100644
index 0000000..de232f9
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Entities/VarietyEntity.cs
@@ -0,0 +1,87 @@
+using Seyounth.Hyosung.Data.Models;
+using SqlSugar;
+
+namespace Seyounth.Hyosung.Data.Entities;
+
+[SugarTable("system_variety", TableDescription = "品种表")]
+public class VarietyEntity
+{
+ [SugarColumn(IsPrimaryKey = true, IsIdentity = true, ColumnDescription = "主键")]
+ public int Id { get; set; }
+
+ [SugarColumn(ColumnDescription = "品种代码")]
+ public string Code { get; set; }
+
+ [SugarColumn(ColumnDescription = "Lot")]
+ public int Lot { get; set; }
+
+ [SugarColumn(ColumnDescription = "规格")]
+ public string Specifications { get; set; }
+
+ [SugarColumn(ColumnDescription = "纸管内径")]
+ public int InnerDiameter { get; set; }
+
+ [SugarColumn(ColumnDescription = "纸管外径")]
+ public int OuterDiameter { get; set; }
+
+ [SugarColumn(ColumnDescription = "纱直径")]
+ public int YarnDiameter { get; set; }
+
+ [SugarColumn(ColumnDescription = "纸筒高度")]
+ public int PaperTubeHeight { get; set; }
+
+ [SugarColumn(ColumnDescription = "纱丝厚度")]
+ public int YarnThickness { get; set; }
+
+ [SugarColumn(ColumnDescription = "单筒重量")]
+ public double SingleWeight { get; set; }
+
+ [SugarColumn(ColumnDescription = "码垛层数")]
+ public int StackingLayers { get; set; }
+
+ [SugarColumn(ColumnDescription = "总数量")]
+ public int TotalCount { get; set; }
+
+ [SugarColumn(ColumnDescription = "中间蜂窝板ID")]
+ public int MiddlePalletId { get; set; }
+
+ [SugarColumn(ColumnDescription = "上下蜂窝板ID")]
+ public int TopAndBottomPalletId { get; set; }
+
+ [SugarColumn(ColumnDescription = "托盘ID")]
+ public int TrayId { get; set; }
+
+ [SugarColumn(ColumnDescription = "垛头尺寸")]
+ public string? StackHeadSpec { get; set; }
+
+ [SugarColumn(ColumnDescription = "垛头数量")]
+ public int? StackHeadCount { get; set; }
+
+ [SugarColumn(ColumnDescription = "纸托Id")]
+ public int? PaperTrayId { get; set; }
+
+ [SugarColumn(ColumnDescription = "是否需要纸箱")]
+ public bool HasBox { get; set; }
+
+ [SugarColumn(ColumnDescription = "是否需要顶板")]
+ public NeedType NeedTopBoard { get; set; }
+
+ [SugarColumn(ColumnDescription = "是否需要护角")]
+ public NeedType NeedAngleBeam { get; set; }
+
+ [SugarColumn(ColumnDescription = "是否需要打包带")]
+ public NeedType NeedPackStrap { get; set; }
+
+ [SugarColumn(ColumnDescription = "是否需要缠膜")]
+ public NeedType NeedFilmWrapping { get; set; }
+
+ [SugarColumn(ColumnDescription = "是否需要覆膜")]
+ public NeedType NeedFilmCoating { get; set; }
+
+ [SugarColumn(ColumnDescription = "主标签数量")]
+ public int MasterLabelCount { get; set; }
+
+ [SugarColumn(ColumnDescription = "副标签数量")]
+ public int SubLabelCount { get; set; }
+
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Models/NeedType.cs b/Seyounth.Hyosung.Data/Models/NeedType.cs
new file mode 100644
index 0000000..0693061
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Models/NeedType.cs
@@ -0,0 +1,17 @@
+using System.ComponentModel;
+
+namespace Seyounth.Hyosung.Data.Models;
+
+public enum NeedType
+{
+ [Description("需要")] Need,
+ [Description("不需要")] NotNeed,
+ [Description("单号需要")] OddNeed,
+ [Description("双号需要")] EvenNeed
+}
+
+public class NeedTypeEnumItem
+{
+ public NeedType Value { get; set; }
+ public string Description { get; set; }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Models/Pallet.cs b/Seyounth.Hyosung.Data/Models/Pallet.cs
new file mode 100644
index 0000000..2baef86
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Models/Pallet.cs
@@ -0,0 +1,5 @@
+using Seyounth.Hyosung.Data.Entities;
+
+namespace Seyounth.Hyosung.Data.Models;
+
+public class Pallet : PalletEntity;
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Models/PalletType.cs b/Seyounth.Hyosung.Data/Models/PalletType.cs
new file mode 100644
index 0000000..b9e6f54
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Models/PalletType.cs
@@ -0,0 +1,19 @@
+namespace Seyounth.Hyosung.Data.Models;
+
+public enum PalletType
+{
+ ///
+ /// 纸板托盘
+ ///
+ Paper=0,
+
+ ///
+ /// 胶合板托盘
+ ///
+ Plywood = 1,
+
+ ///
+ /// 木板托盘
+ ///
+ Wood = 2
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Models/Plc/PackLineOption.cs b/Seyounth.Hyosung.Data/Models/Plc/PackLineOption.cs
new file mode 100644
index 0000000..243e641
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Models/Plc/PackLineOption.cs
@@ -0,0 +1,18 @@
+namespace Seyounth.Hyosung.Data.Models.Plc;
+
+public class PackLineOption
+{
+ public int HeadCount { get; set; }
+
+ public bool HasBox { get; set; }
+
+ public bool IsTop { get; set; }
+
+ public bool IsPack { get; set; }
+
+ public bool IsFilm { get; set; }
+
+ public bool IsLam { get; set; }
+
+
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Models/Plc/PlcStackInfo.cs b/Seyounth.Hyosung.Data/Models/Plc/PlcStackInfo.cs
new file mode 100644
index 0000000..4899f27
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Models/Plc/PlcStackInfo.cs
@@ -0,0 +1,10 @@
+namespace Seyounth.Hyosung.Data.Models.Plc;
+
+///
+/// Plc侧整垛信息
+///
+public class PlcStackInfo
+{
+ public string TrayCode { get; set; }
+
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Models/Plc/PlcStackingInfo.cs b/Seyounth.Hyosung.Data/Models/Plc/PlcStackingInfo.cs
new file mode 100644
index 0000000..0975857
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Models/Plc/PlcStackingInfo.cs
@@ -0,0 +1,12 @@
+namespace Seyounth.Hyosung.Data.Models.Plc;
+
+public class PlcStackingInfo
+{
+ public string TrayCode { get; set; }
+
+ public List YarnCode { get; set; } = new List();
+
+ public int YarnCount { get; set; }
+
+ public int TotalYarnCount { get; set; }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Models/Tray.cs b/Seyounth.Hyosung.Data/Models/Tray.cs
new file mode 100644
index 0000000..dbb07df
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Models/Tray.cs
@@ -0,0 +1,84 @@
+using Seyounth.Hyosung.Data.Entities;
+
+namespace Seyounth.Hyosung.Data.Models;
+
+public class Tray
+{
+ public int Id { get; set; }
+
+ public string TrayCode { get; set; }
+
+ public int VarietyId { get; set; }
+
+ public int? ControlNo { get; set; } = null;
+
+ public DateTime CreateTime { get; set; }
+
+ public DateTime? FinishTime { get; set; }
+
+ public bool IsEven { get; set; }
+
+
+ public string? Grade { get; set; }
+
+ public string? Type { get; set; }
+
+ public string? DenFila { get; set; }
+
+ public string? DtexFila { get; set; }
+
+ public int? Unit { get; set; }
+
+ public double NetWeight { get; set; }
+
+ public double GrossWeight { get; set; }
+ public int? StackHeight { get; set; }
+
+ public int? AgvBinId { get; set; }
+
+ public TrayEntity ToEntity()
+ {
+ return new TrayEntity()
+ {
+ Id = Id,
+ TrayCode = TrayCode,
+ VarietyId = VarietyId,
+ ControlNo = ControlNo,
+ FinishTime = FinishTime,
+ StackHeight = StackHeight,
+ IsEven = IsEven,
+ GrossWeight = GrossWeight,
+ NetWeight = NetWeight,
+ CreateTime = CreateTime,
+ DenFila = DenFila,
+ DtexFila = DtexFila,
+ Grade = Grade,
+ Type = Type,
+ Unit = Unit,
+ AgvBinId = AgvBinId
+ };
+ }
+
+ public static Tray FromEntity(TrayEntity entity)
+ {
+ return new Tray()
+ {
+ Id = entity.Id,
+ TrayCode = entity.TrayCode,
+ VarietyId = entity.VarietyId,
+ ControlNo = entity.ControlNo,
+ StackHeight = entity.StackHeight,
+ FinishTime = entity.FinishTime,
+ IsEven = entity.IsEven,
+ GrossWeight = entity.GrossWeight,
+ NetWeight = entity.NetWeight,
+ CreateTime = entity.CreateTime,
+ DenFila = entity.DenFila,
+ DtexFila = entity.DtexFila,
+ Grade = entity.Grade,
+ Type = entity.Type,
+ Unit = entity.Unit,
+ AgvBinId = entity.AgvBinId
+ };
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Models/Variety.cs b/Seyounth.Hyosung.Data/Models/Variety.cs
new file mode 100644
index 0000000..026888b
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Models/Variety.cs
@@ -0,0 +1,179 @@
+using Seyounth.Hyosung.Data.Entities;
+
+namespace Seyounth.Hyosung.Data.Models;
+
+public class Variety
+{
+ public int Id { get; set; }
+
+ public string Code { get; set; }
+
+ public int Lot { get; set; }
+
+ public int YarnCarType { get; set; }
+
+ public int YarnCarSide { get; set; }
+
+ public string Specifications { get; set; }
+
+ public int InnerDiameter { get; set; }
+
+ public int OuterDiameter { get; set; }
+
+ public int YarnDiameter { get; set; }
+
+ public int PaperTubeHeight { get; set; }
+
+ public int YarnThickness { get; set; }
+
+ public double SingleWeight { get; set; }
+
+ public int StackingLayers { get; set; }
+
+ public int TotalCount { get; set; }
+
+ public Pallet MiddlePallet { get; set; }
+
+ public Pallet TopAndBottomPallet { get; set; }
+
+ public Pallet Tray { get; set; }
+
+ public string? StackHeadSpec { get; set; }
+
+ public int? StackHeadCount { get; set; }
+
+ public Pallet? PaperTray { get; set; }
+
+ public bool HasBox { get; set; }
+
+ public NeedType NeedTopBoard { get; set; }
+
+ public NeedType NeedAngleBeam { get; set; }
+
+ public NeedType NeedPackStrap { get; set; }
+
+ public NeedType NeedFilmWrapping { get; set; }
+
+ public NeedType NeedFilmCoating { get; set; }
+
+ public int MasterLabelCount { get; set; }
+
+ public int SubLabelCount { get; set; }
+
+ public bool IsTurn { get; set; }
+
+ public static Variety Create(VarietyEntity entity, List pallets)
+ {
+ var variety = new Variety()
+ {
+ Id = entity.Id,
+ Code = entity.Code,
+ Lot = entity.Lot,
+ Specifications = entity.Specifications,
+ InnerDiameter = entity.InnerDiameter,
+ OuterDiameter = entity.OuterDiameter,
+ YarnDiameter = entity.YarnDiameter,
+ PaperTubeHeight = entity.PaperTubeHeight,
+ YarnThickness = entity.YarnThickness,
+ SingleWeight = entity.SingleWeight,
+ StackingLayers = entity.StackingLayers,
+ TotalCount = entity.TotalCount,
+ StackHeadSpec = entity.StackHeadSpec,
+ StackHeadCount = entity.StackHeadCount,
+ NeedTopBoard = entity.NeedTopBoard,
+ NeedAngleBeam = entity.NeedAngleBeam,
+ NeedPackStrap = entity.NeedPackStrap,
+ NeedFilmWrapping = entity.NeedFilmWrapping,
+ NeedFilmCoating = entity.NeedFilmCoating,
+ MasterLabelCount = entity.MasterLabelCount,
+ SubLabelCount = entity.SubLabelCount,
+ MiddlePallet = (Pallet)pallets.First(x => x.Id == entity.MiddlePalletId),
+ TopAndBottomPallet = (Pallet)pallets.First(x => x.Id == entity.TopAndBottomPalletId),
+ Tray = (Pallet)pallets.First(x => x.Id == entity.TrayId),
+ HasBox = entity.HasBox
+ };
+ if (entity.PaperTrayId != null && entity.PaperTrayId != 0)
+ variety.PaperTray = (Pallet)pallets.First(x => x.Id == entity.PaperTrayId);
+
+ return variety;
+ }
+
+ public VarietyEntity ToEntity()
+ {
+ var entity = new VarietyEntity()
+ {
+ Id = Id,
+ Code = Code,
+ Lot = Lot,
+ Specifications = Specifications,
+ InnerDiameter = InnerDiameter,
+ OuterDiameter = OuterDiameter,
+ YarnDiameter = YarnDiameter,
+ PaperTubeHeight = PaperTubeHeight,
+ YarnThickness = YarnThickness,
+ SingleWeight = SingleWeight,
+ StackingLayers = StackingLayers,
+ TotalCount = TotalCount,
+ StackHeadSpec = StackHeadSpec,
+ StackHeadCount = StackHeadCount,
+ PaperTrayId = PaperTray?.Id,
+ NeedTopBoard = NeedTopBoard,
+ NeedAngleBeam = NeedAngleBeam,
+ NeedPackStrap = NeedPackStrap,
+ NeedFilmWrapping = NeedFilmWrapping,
+ NeedFilmCoating = NeedFilmCoating,
+ MasterLabelCount = MasterLabelCount,
+ SubLabelCount = SubLabelCount,
+ MiddlePalletId = MiddlePallet.Id,
+ TopAndBottomPalletId = TopAndBottomPallet.Id,
+ TrayId = Tray.Id,
+ HasBox = HasBox,
+ };
+ return entity;
+ }
+
+ public short[] ToVarietyPlcData()
+ {
+ List ls = new List();
+ ls.Add((short)YarnCarSide);
+ ls.Add((short)YarnCarType);
+ ls.Add((short)InnerDiameter);
+ ls.Add((short)OuterDiameter);
+ ls.Add((short)YarnDiameter);
+ ls.Add((short)PaperTubeHeight);
+ ls.Add((short)YarnThickness);
+ ls.Add((short)Tray.Type);
+ ls.Add((short)Tray.Length);
+ ls.Add((short)Tray.Width);
+ ls.Add((short)Tray.Height);
+ if (PaperTray is null)
+ {
+ ls.Add(0);
+ ls.Add(0);
+ ls.Add(0);
+ ls.Add(0);
+ }
+ else
+ {
+ ls.Add(1);
+ ls.Add((short)PaperTray.Length);
+ ls.Add((short)PaperTray.Width);
+ ls.Add((short)PaperTray.Height);
+ }
+
+ ls.Add((short)TopAndBottomPallet.HoleCount);
+ ls.Add((short)(TopAndBottomPallet.IsBigHole.Value ? 1 : 2));
+ ls.Add((short)TopAndBottomPallet.Length);
+ ls.Add((short)TopAndBottomPallet.Width);
+ ls.Add((short)TopAndBottomPallet.Height);
+ ls.Add((short)MiddlePallet.HoleCount);
+ ls.Add((short)(MiddlePallet.IsBigHole.Value ? 1 : 2));
+ ls.Add((short)MiddlePallet.Length);
+ ls.Add((short)MiddlePallet.Width);
+ ls.Add((short)MiddlePallet.Height);
+ ls.Add((short)(IsTurn ? 1 : 2));
+ ls.Add((short)TotalCount);
+ ls.Add((short)StackingLayers);
+ return ls.ToArray();
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Models/Yarn.cs b/Seyounth.Hyosung.Data/Models/Yarn.cs
new file mode 100644
index 0000000..3a19b26
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Models/Yarn.cs
@@ -0,0 +1,143 @@
+using Seyounth.Core.Extensions;
+using Seyounth.Hyosung.Data.Entities;
+
+namespace Seyounth.Hyosung.Data.Models;
+
+public class Yarn
+{
+ public int Id { get; set; }
+
+ public string QrCode { get; set; }
+
+ public string ScanCode { get; set; }
+
+ public int Lot { get; set; }
+
+ public string? DenFila { get; set; }
+
+ public string? DtexFila { get; set; }
+
+ public string WorkShift { get; set; } = "NoData";
+
+ public string Machine { get; set; } = "NoData";
+
+ public int VarietyId { get; set; }
+
+ public DateTime ScanTime { get; set; }
+
+ public string ProduceTime { get; set; }
+
+ public bool IsFinished { get; set; } = false;
+
+ public int? TrayId { get; set; }
+
+ public DateTime? StackTime { get; set; }
+
+ public DateTime? StorageTime { get; set; }
+
+
+ public static Yarn? Create(string qrCode, int varietyId)
+ {
+ try
+ {
+ Yarn yarn;
+ if (!qrCode.Contains('\n'))
+ {
+ var parts = qrCode.Split(' ');
+
+ yarn = new Yarn()
+ {
+ QrCode = qrCode,
+ Lot = int.Parse(parts[0].Replace("Lot:", "")),
+ Machine = parts[2],
+ ProduceTime = parts[3],
+ ScanTime = DateTime.Now,
+ VarietyId = varietyId,
+ ScanCode = DateTime.Now.ToTimestamp().ToString(),
+ TrayId = null
+ };
+ yarn.WorkShift = parts[1] switch
+ {
+ "0" => "早班",
+ "1" => "中班",
+ "2" => "晚班",
+ _ => yarn.WorkShift
+ };
+ return yarn;
+ }
+ else
+ {
+ var parts = qrCode.Split('\n');
+ yarn = new Yarn()
+ {
+ QrCode = qrCode,
+ Lot = int.Parse(parts[0].Replace("Lot:", "")),
+ DenFila = parts[1],
+ DtexFila = parts[2],
+ ProduceTime = parts[3],
+ Machine = parts[4],
+ ScanTime = DateTime.Now,
+ VarietyId = varietyId,
+ TrayId = null,
+ ScanCode = DateTime.Now.ToTimestamp().ToString().PadLeft(10, '0'),
+ };
+ yarn.WorkShift = parts[5] switch
+ {
+ "0" => "早班",
+ "1" => "中班",
+ "2" => "晚班",
+ _ => yarn.WorkShift
+ };
+ return yarn;
+ }
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ public static Yarn FromEntity(ScannedYarnEntity entity)
+ {
+ return new Yarn
+ {
+ Id = entity.Id,
+ ScanCode = entity.ScanCode,
+ DenFila = entity.DenFila,
+ DtexFila = entity.DtexFila,
+ IsFinished = entity.IsFinished,
+ Lot = entity.Lot,
+ Machine = entity.Machine,
+ ProduceTime = entity.ProduceTime,
+ QrCode = entity.QrCode,
+ ScanTime = entity.ScanTime,
+ VarietyId = entity.VarietyId,
+ WorkShift = entity.WorkShift,
+ TrayId = entity.TrayId,
+ StorageTime = entity.StorageTime,
+ StackTime = entity.StackTime
+ };
+ }
+
+ public ScannedYarnEntity ToEntity()
+ {
+ return new ScannedYarnEntity
+ {
+ Id = Id,
+ ScanCode = ScanCode,
+ DenFila = DenFila,
+ DtexFila = DtexFila,
+ IsFinished = IsFinished,
+ Lot = Lot,
+ Machine = Machine,
+ ProduceTime = ProduceTime,
+ QrCode = QrCode,
+ ScanTime = ScanTime,
+ VarietyId = VarietyId,
+ WorkShift = WorkShift,
+ TrayId = TrayId,
+ StackTime = StackTime,
+ StorageTime = StorageTime
+ };
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Repositories/IRepository.cs b/Seyounth.Hyosung.Data/Repositories/IRepository.cs
new file mode 100644
index 0000000..4b6f279
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Repositories/IRepository.cs
@@ -0,0 +1,7 @@
+using SqlSugar;
+
+namespace Seyounth.Hyosung.Data.Repositories;
+
+public interface IRepository : ISimpleClient where T : class, new()
+{
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Repositories/Repository.cs b/Seyounth.Hyosung.Data/Repositories/Repository.cs
new file mode 100644
index 0000000..a238983
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Repositories/Repository.cs
@@ -0,0 +1,11 @@
+using SqlSugar;
+
+namespace Seyounth.Hyosung.Data.Repositories;
+
+public class Repository : SimpleClient, IRepository where T : class, new()
+{
+ public Repository(ISqlSugarClient db)
+ {
+ base.Context = db;
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/ServiceExtensions.cs b/Seyounth.Hyosung.Data/ServiceExtensions.cs
new file mode 100644
index 0000000..d5f39cf
--- /dev/null
+++ b/Seyounth.Hyosung.Data/ServiceExtensions.cs
@@ -0,0 +1,49 @@
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Seyounth.Hyosung.Data.Entities;
+using Seyounth.Hyosung.Data.Repositories;
+using Seyounth.Hyosung.Data.Services;
+using Seyounth.Hyosung.Data.Services.Hyosung;
+using SqlSugar;
+
+namespace Seyounth.Hyosung.Data;
+
+public static class ServiceExtensions
+{
+ public static IServiceCollection AddHyosungData(this IServiceCollection services,
+ ConfigurationManager configuration)
+ {
+ var connectionString = configuration.GetConnectionString("DefaultConnection");
+ services.AddSingleton(s =>
+ {
+ SqlSugarScope sqlSugar = new SqlSugarScope(new ConnectionConfig()
+ {
+ DbType = DbType.SqlServer,
+ ConnectionString = connectionString,
+ IsAutoCloseConnection = true,
+ }
+ );
+ return sqlSugar;
+ });
+ services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
+ return services;
+ }
+
+ public static void UseHyosungData(this IServiceProvider provider)
+ {
+ var db = provider.GetRequiredService();
+ db.DbMaintenance.CreateDatabase();
+ db.CodeFirst.InitTables(typeof(VarietyEntity),
+ typeof(PalletEntity),
+ typeof(ScannedYarnEntity),
+ typeof(TrayEntity),
+ typeof(AgvBinEntity),
+ typeof(DictEntity));
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Services/AgvBinService.cs b/Seyounth.Hyosung.Data/Services/AgvBinService.cs
new file mode 100644
index 0000000..e31dc87
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Services/AgvBinService.cs
@@ -0,0 +1,45 @@
+using Microsoft.Extensions.DependencyInjection;
+using Seyounth.Hyosung.Data.Entities;
+using Seyounth.Hyosung.Data.Repositories;
+
+namespace Seyounth.Hyosung.Data.Services;
+
+public class AgvBinService : IAgvBinService
+{
+ private readonly List _cache;
+
+ private readonly IRepository repository;
+
+ public AgvBinService(IServiceProvider provider)
+ {
+ repository = provider.CreateScope().ServiceProvider.GetRequiredService>();
+ _cache = repository.GetList();
+ }
+
+ public async Task GetAvailableBin(int height)
+ {
+ if (height < 180)
+ {
+ return _cache
+ .Where(x =>
+ x is { CtnrType: 1, IsFree: true } ||
+ x is { CtnrType: 2, IsFree: true } &&
+ _cache.Any(y =>
+ y is { CtnrType: 1, IsFree: false } && y.BinCode == x.BinCode &&
+ y is { Height: < 180 })
+ )
+ .OrderByDescending(x => x.CtnrType)
+ .ThenBy(x => x.Sort)
+ .First();
+ }
+
+ return _cache.Where(a => a is { IsFree: true }).OrderBy(a => a.CtnrType).First();
+ }
+
+ public Task BindAsync(AgvBinEntity entity)
+ {
+ entity.IsFree = false;
+ _cache.First(e => e.Id == entity.Id).IsFree = false;
+ return repository.UpdateAsync(entity);
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Services/DictService.cs b/Seyounth.Hyosung.Data/Services/DictService.cs
new file mode 100644
index 0000000..8b6c40e
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Services/DictService.cs
@@ -0,0 +1,31 @@
+using Microsoft.Extensions.DependencyInjection;
+using Seyounth.Hyosung.Data.Entities;
+using Seyounth.Hyosung.Data.Repositories;
+using SqlSugar;
+
+namespace Seyounth.Hyosung.Data.Services;
+
+public class DictService : IDictService
+{
+ private readonly IRepository _repository;
+
+ private readonly List _cache;
+
+ public DictService(IServiceProvider provider)
+ {
+ _repository = provider.CreateScope()
+ .ServiceProvider.GetRequiredService>();
+ _cache = _repository.GetList();
+ }
+
+
+ public async Task GetKeyAsync(string type, string name)
+ {
+ return _cache.FirstOrDefault(d => d.Type == type && d.Value == name)?.Value ?? "";
+ }
+
+ public async Task> GetDictsByTypeAsync(string type)
+ {
+ return _cache.Where(d => d.Type == type).ToList();
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Services/Hyosung/Entities/LabelResult.cs b/Seyounth.Hyosung.Data/Services/Hyosung/Entities/LabelResult.cs
new file mode 100644
index 0000000..670df31
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Services/Hyosung/Entities/LabelResult.cs
@@ -0,0 +1,38 @@
+using SqlSugar;
+
+namespace Seyounth.Hyosung.Data.Services.Hyosung.Entities;
+
+[SugarTable("LABEL_RESULT")]
+public class LabelResult
+{
+ public int BE_ID { get; set; }
+ public string BAR_CODE { get; set; }
+ public string ITEM_CODE { get; set; }
+ public string LABEL_ID { get; set; }
+ public string WMS_UOM { get; set; }
+ public string ERP_UOM { get; set; }
+ public string MFG_DATE { get; set; }
+ public decimal NET_WEIGHT { get; set; }
+ public double GROSS_WEIGHT { get; set; }
+ public string MFG_LINE { get; set; }
+ public string GRADE { get; set; }
+ public string LOT { get; set; }
+ public string BOX_NO { get; set; }
+ public string DENIER { get; set; }
+ public string FILA { get; set; }
+ public string CUSTOMER_NAME { get; set; }
+ public string REMARKS { get; set; }
+ public string TRI_INTERFACE_YN { get; set; }
+ public string TRI_TYPE { get; set; }
+ public string COMMON_S1 { get; set; }
+ public string COMMON_S2 { get; set; }
+ public string COMMON_S3 { get; set; }
+ public string COMMON_S4 { get; set; }
+ public string COMMON_S5 { get; set; }
+ public string COMMON_N1 { get; set; }
+ public string TRI_YN { get; set; }
+ public string CREATED_BY { get; set; }
+ public string CREATED_ON { get; set; }
+ public string MODIFIED_BY { get; set; }
+ public string MODIFIED_ON { get; set; }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Services/Hyosung/Entities/MST_BOXNO_SEQ_NON_DATE.cs b/Seyounth.Hyosung.Data/Services/Hyosung/Entities/MST_BOXNO_SEQ_NON_DATE.cs
new file mode 100644
index 0000000..dde3257
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Services/Hyosung/Entities/MST_BOXNO_SEQ_NON_DATE.cs
@@ -0,0 +1,32 @@
+using SqlSugar;
+
+namespace Seyounth.Hyosung.Data.Services.Hyosung.Entities;
+
+///
+/// 晓星 控制号表
+///
+public class MST_BOXNO_SEQ_NON_DATE
+{
+ [SugarColumn(ColumnName = "LAST_NO", IsNullable = true)]
+ public int? LastNo { get; set; }
+
+ [SugarColumn(ColumnName = "BE_ID")] public string BeId { get; set; }
+
+ [SugarColumn(ColumnName = "ITEM_CODE")]
+ public string ItemCode { get; set; }
+
+ [SugarColumn(ColumnName = "CHECK_CHAR")]
+ public string CheckCode { get; set; }
+
+ [SugarColumn(ColumnName = "CREATED_ON", IsNullable = true)]
+ public DateTime CreatedTime { get; set; }
+
+ [SugarColumn(ColumnName = "MODIFIED_ON", IsNullable = true)]
+ public DateTime ModifiedTime { get; set; }
+
+ [SugarColumn(ColumnName = "CREATED_BY", IsNullable = true)]
+ public string CreatedBy { get; set; }
+
+ [SugarColumn(ColumnName = "MODIFIED_BY", IsNullable = true)]
+ public string ModifiedBy { get; set; }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Services/Hyosung/Entities/MST_ITEM_2240_V.cs b/Seyounth.Hyosung.Data/Services/Hyosung/Entities/MST_ITEM_2240_V.cs
new file mode 100644
index 0000000..5bcca81
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Services/Hyosung/Entities/MST_ITEM_2240_V.cs
@@ -0,0 +1,24 @@
+namespace Seyounth.Hyosung.Data.Services.Hyosung.Entities;
+
+public class MST_ITEM_2240_V
+{
+ public string BE_ID { get; set; }
+
+ public string ITEM_CODE { get; set; }
+
+ public string TYPE { get; set; }
+
+ public string DEN_FILA { get; set; }
+
+ public string DTEX_FILA { get; set; }
+
+ public string LOTNO { get; set; }
+
+ public string GRADE { get; set; }
+
+ public int UNIT { get; set; }
+
+ public double NET_WEIGHT { get; set; }
+
+ public double GROSS_WEIGHT { get; set; }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Services/Hyosung/HyosungWmsService.cs b/Seyounth.Hyosung.Data/Services/Hyosung/HyosungWmsService.cs
new file mode 100644
index 0000000..3774b92
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Services/Hyosung/HyosungWmsService.cs
@@ -0,0 +1,77 @@
+using Seyounth.Hyosung.Data.Models;
+using Seyounth.Hyosung.Data.Services.Hyosung.Entities;
+using SqlSugar;
+
+namespace Seyounth.Hyosung.Data.Services.Hyosung;
+
+public class HyosungWmsService : IHyosungWmsService
+{
+ private ISqlSugarClient _db = new SqlSugarClient(new ConnectionConfig
+ {
+ DbType = DbType.SqlServer,
+ ConnectionString =
+ $"Data Source=192.168.2.11;User Id=TY_ACP;Password=ty@_acp20y;database=HSWMS;Encrypt=True;TrustServerCertificate=True;Pooling=true;Min Pool Size=1",
+ IsAutoCloseConnection = true,
+ });
+
+ public async Task GetControlNo(Variety variety, string grade)
+ {
+ var checkCode = $"02025{grade}{variety.Lot.ToString().Substring(1, 3)}";
+ var x = await _db.Queryable().Where(x =>
+ x.BeId == "2240" && x.ItemCode == variety.Code && x.CheckCode == checkCode).FirstAsync();
+ if (x?.LastNo is null)
+ return 1;
+ return x.LastNo.Value + 1;
+ }
+
+ public async Task GetItemInfoByItemCode(string itemCode)
+ {
+ return await _db.Queryable()
+ .FirstAsync(t => t.ITEM_CODE == itemCode);
+ }
+
+ public async Task UpdateControlNo(Variety variety, int controlNo)
+ {
+ var checkCode = $"02025{variety.Lot}";
+ if (controlNo is 1)
+ {
+ var entity = new MST_BOXNO_SEQ_NON_DATE()
+ {
+ BeId = "2240",
+ CheckCode = checkCode,
+ LastNo = 1,
+ CreatedBy = "seyounth",
+ CreatedTime = DateTime.Now,
+ ModifiedBy = "seyounth",
+ ModifiedTime = DateTime.Now,
+ ItemCode = variety.Code
+ };
+ await _db.Insertable(entity).ExecuteCommandAsync();
+ }
+ else
+ {
+ await _db.Updateable()
+ .SetColumns(i => i.LastNo == controlNo
+ && i.ModifiedTime == DateTime.Now
+ && i.ModifiedBy == "seyounth")
+ .Where(i => i.BeId == "2240" &&
+ i.ItemCode == variety.Code &&
+ i.CheckCode == checkCode).ExecuteCommandAsync();
+ }
+ }
+
+ public async Task GetLabelResult(string itemCode, string lot, int controlNo)
+ {
+ string code = $"{itemCode.Trim()} {DateTime.Now.AddDays(0):yyMMdd}";
+ string code2 = $"{lot.Trim()}{controlNo.ToString().PadLeft(4, '0')}0";
+
+ // 使用 SqlSugar 进行查询
+ return await _db.Queryable()
+ .Where(x =>
+ x.BAR_CODE.Substring(0, 24) == code &&
+ x.BAR_CODE.Substring(x.BAR_CODE.Length - 9, 9) == code2 &&
+ x.BE_ID == 2240
+ )
+ .FirstAsync();
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Services/Hyosung/IHyosungWmsService.cs b/Seyounth.Hyosung.Data/Services/Hyosung/IHyosungWmsService.cs
new file mode 100644
index 0000000..ca619b5
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Services/Hyosung/IHyosungWmsService.cs
@@ -0,0 +1,15 @@
+using Seyounth.Hyosung.Data.Models;
+using Seyounth.Hyosung.Data.Services.Hyosung.Entities;
+
+namespace Seyounth.Hyosung.Data.Services.Hyosung;
+
+public interface IHyosungWmsService
+{
+ Task GetControlNo(Variety variety, string grade);
+
+ Task GetItemInfoByItemCode(string itemCode);
+
+ Task UpdateControlNo(Variety variety, int controlNo);
+
+ Task GetLabelResult(string itemCode,string lot,int controlNo);
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Services/IAgvBinService.cs b/Seyounth.Hyosung.Data/Services/IAgvBinService.cs
new file mode 100644
index 0000000..b9e8021
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Services/IAgvBinService.cs
@@ -0,0 +1,21 @@
+using Seyounth.Hyosung.Data.Entities;
+using Seyounth.Hyosung.Data.Models;
+
+namespace Seyounth.Hyosung.Data.Services;
+
+public interface IAgvBinService
+{
+ ///
+ /// 获取可用的库位信息
+ ///
+ ///
+ ///
+ Task GetAvailableBin(int height);
+
+ ///
+ /// 绑定相应的库
+ ///
+ ///
+ ///
+ Task BindAsync(AgvBinEntity entity);
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Services/IDictService.cs b/Seyounth.Hyosung.Data/Services/IDictService.cs
new file mode 100644
index 0000000..8d7dd5c
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Services/IDictService.cs
@@ -0,0 +1,10 @@
+using Seyounth.Hyosung.Data.Entities;
+
+namespace Seyounth.Hyosung.Data.Services;
+
+public interface IDictService
+{
+ Task GetKeyAsync(string type, string value);
+
+ Task> GetDictsByTypeAsync(string type);
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Services/ITrayService.cs b/Seyounth.Hyosung.Data/Services/ITrayService.cs
new file mode 100644
index 0000000..bc574f9
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Services/ITrayService.cs
@@ -0,0 +1,45 @@
+using Seyounth.Hyosung.Data.Models;
+using Seyounth.Hyosung.Data.Services.Hyosung.Entities;
+
+namespace Seyounth.Hyosung.Data.Services;
+
+public interface ITrayService
+{
+ ///
+ /// 生成一个新的托盘
+ ///
+ /// 品类ID
+ ///
+ Task GeneraNewTray(int varietyId);
+
+ ///
+ /// 通过Code查找ID
+ ///
+ ///
+ ///
+ Task GetIdByCode(string code);
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task GetByCode(string code);
+
+ ///
+ /// 生成控制号
+ ///
+ ///
+ ///
+ Task StorageAsync(string trayCode);
+
+ ///
+ /// 打印托盘
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task PrintTrayAsync(string trayCode, int stackHeight, int controlNo, MST_ITEM_2240_V itemInfo);
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Services/IVarietyService.cs b/Seyounth.Hyosung.Data/Services/IVarietyService.cs
new file mode 100644
index 0000000..2debae0
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Services/IVarietyService.cs
@@ -0,0 +1,36 @@
+using Seyounth.Hyosung.Data.Models;
+
+namespace Seyounth.Hyosung.Data.Services;
+
+public interface IVarietyService
+{
+ ///
+ /// 通过品种代码获取品种信息
+ ///
+ /// 品种代码
+ /// 码垛层数
+ ///
+ Task GetVarietyByCodeAsync(string code, int? layers = null);
+
+ Task GetById(int id);
+
+ ///
+ /// 添加品种信息
+ ///
+ ///
+ ///
+ Task AddVarietyAsync(Variety variety);
+
+ ///
+ /// 获取所有托盘信息
+ ///
+ ///
+ Task> GetPalletsAsync();
+
+ ///
+ /// 添加托盘信息
+ ///
+ ///
+ ///
+ Task AddPalletAsync(Pallet pallet);
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Services/IYarnService.cs b/Seyounth.Hyosung.Data/Services/IYarnService.cs
new file mode 100644
index 0000000..3a90579
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Services/IYarnService.cs
@@ -0,0 +1,31 @@
+using System.Collections.Concurrent;
+using Seyounth.Hyosung.Data.Models;
+
+namespace Seyounth.Hyosung.Data.Services;
+
+public interface IYarnService
+{
+ ConcurrentDictionary NoFinished { get; }
+
+ Task AddYarnAsync(Yarn yarn);
+
+
+ Task> GetYarnsByTrayIdAsync(int trayId);
+
+ Task GetYarnByCodeAsync(string code);
+
+ ///
+ /// 完成指定纱
+ ///
+ ///
+ ///
+ Task FinishYarnAsync(string yarnCode);
+
+ ///
+ /// 绑定托盘号
+ ///
+ ///
+ ///
+ ///
+ Task BindTrayAsync(string yarnCode, int trayId);
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Services/TrayService.cs b/Seyounth.Hyosung.Data/Services/TrayService.cs
new file mode 100644
index 0000000..d605857
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Services/TrayService.cs
@@ -0,0 +1,79 @@
+using System.Collections.Concurrent;
+using Microsoft.Extensions.DependencyInjection;
+using Seyounth.Hyosung.Data.Entities;
+using Seyounth.Hyosung.Data.Models;
+using Seyounth.Hyosung.Data.Repositories;
+using Seyounth.Hyosung.Data.Services.Hyosung;
+using Seyounth.Hyosung.Data.Services.Hyosung.Entities;
+
+namespace Seyounth.Hyosung.Data.Services;
+
+public class TrayService : ITrayService
+{
+ private readonly ConcurrentDictionary _cache = new();
+ private readonly IRepository _repository;
+ private readonly IHyosungWmsService _hyosungWmsService;
+
+ public TrayService(IServiceProvider provider, IHyosungWmsService hyosungWmsService)
+ {
+ _repository = provider.CreateScope().ServiceProvider.GetRequiredService>();
+ var trays = _repository.GetList(t => t.ControlNo == null);
+ _hyosungWmsService = hyosungWmsService;
+ foreach (var tray in trays)
+ {
+ _cache.TryAdd(tray.TrayCode, Tray.FromEntity(tray));
+ }
+ }
+
+ public async Task GeneraNewTray(int varietyId)
+ {
+ var tray = new Tray()
+ {
+ TrayCode = DateTime.Now.ToString("yyMMddHHmmss"),
+ VarietyId = varietyId,
+ CreateTime = DateTime.Now
+ };
+ var count = await _repository.CountAsync(t => t.VarietyId == tray.VarietyId);
+ tray.IsEven = count % 2 == 0;
+ var identity = await _repository.InsertReturnIdentityAsync(tray.ToEntity());
+ tray.Id = identity;
+ _cache.TryAdd(tray.TrayCode, tray);
+ return tray;
+ }
+
+ public async Task GetIdByCode(string code)
+ {
+ return _cache[code].Id;
+ }
+
+ public async Task GetByCode(string code)
+ {
+ return Tray.FromEntity(await _repository.GetSingleAsync(t => t.TrayCode == code));
+ }
+
+ public Task StorageAsync(string trayCode, int stackHeight, int controlNo, MST_ITEM_2240_V itemInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ public async Task PrintTrayAsync(string trayCode, int stackHeight, int controlNo, MST_ITEM_2240_V itemInfo)
+ {
+ var tray = _cache[trayCode];
+ tray.ControlNo = controlNo;
+ tray.StackHeight = stackHeight;
+ tray.Grade = itemInfo.GRADE;
+ tray.Type = itemInfo.TYPE;
+ tray.DenFila = itemInfo.DEN_FILA;
+ tray.DtexFila = itemInfo.DTEX_FILA;
+ tray.Unit = itemInfo.UNIT;
+ tray.NetWeight = itemInfo.NET_WEIGHT;
+ tray.GrossWeight = itemInfo.GROSS_WEIGHT;
+ await _repository.UpdateAsync(tray.ToEntity());
+ _cache.Remove(tray.TrayCode, out _);
+ }
+
+ public async Task StorageAsync(string trayCode)
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Services/VarietyService.cs b/Seyounth.Hyosung.Data/Services/VarietyService.cs
new file mode 100644
index 0000000..02b56bb
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Services/VarietyService.cs
@@ -0,0 +1,61 @@
+using System.Collections.Concurrent;
+using Microsoft.Extensions.DependencyInjection;
+using Seyounth.Hyosung.Data.Entities;
+using Seyounth.Hyosung.Data.Models;
+using Seyounth.Hyosung.Data.Repositories;
+
+namespace Seyounth.Hyosung.Data.Services;
+
+public class VarietyService : IVarietyService
+{
+ private readonly IRepository _varietyRepository;
+ private readonly IRepository _palletRepository;
+ private readonly ConcurrentBag _varietiesCache;
+ private readonly ConcurrentBag _palletsCache;
+
+ public VarietyService(IServiceProvider provider)
+ {
+ try
+ {
+ _varietyRepository = provider.CreateScope().ServiceProvider.GetRequiredService>();
+ _palletRepository = provider.CreateScope().ServiceProvider.GetRequiredService>();
+ _varietiesCache = new ConcurrentBag(_varietyRepository.GetList());
+ _palletsCache = new ConcurrentBag(_palletRepository.GetList());
+ }catch(Exception e)
+ {
+ Console.WriteLine(e.Message);
+ }
+
+ }
+
+ public async Task GetVarietyByCodeAsync(string code, int? layers = null)
+ {
+ var entity = layers != null
+ ? _varietiesCache.FirstOrDefault(p => p.Code == code && p.StackingLayers == layers)
+ : _varietiesCache.FirstOrDefault(v => v.Code == code);
+ return entity is null ? null : Variety.Create(entity, _palletsCache.ToList());
+ }
+
+ public Task GetById(int id)
+ {
+ var entity = _varietiesCache.FirstOrDefault(p => p.Id == id);
+ return Task.FromResult(Variety.Create(entity, _palletsCache.ToList()));
+ }
+
+ public async Task AddVarietyAsync(Variety variety)
+ {
+ var entity = await _varietyRepository.InsertReturnEntityAsync(variety.ToEntity());
+ _varietiesCache.Add(entity);
+ }
+
+ public async Task> GetPalletsAsync()
+ {
+ return _palletsCache.Select(p => (Pallet)p).ToList();
+ }
+
+ public async Task AddPalletAsync(Pallet pallet)
+ {
+ var entity = await _palletRepository.InsertReturnEntityAsync(pallet);
+ _palletsCache.Add(entity);
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Services/YarnService.cs b/Seyounth.Hyosung.Data/Services/YarnService.cs
new file mode 100644
index 0000000..66f04a5
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Services/YarnService.cs
@@ -0,0 +1,63 @@
+using System.Collections.Concurrent;
+using Microsoft.Extensions.DependencyInjection;
+using Seyounth.Hyosung.Data.Entities;
+using Seyounth.Hyosung.Data.Models;
+using Seyounth.Hyosung.Data.Repositories;
+
+namespace Seyounth.Hyosung.Data.Services;
+
+public class YarnService : IYarnService
+{
+ private readonly IRepository _yarnRepository;
+
+ public YarnService(IServiceProvider provider)
+ {
+ _yarnRepository = provider.CreateScope().ServiceProvider.GetRequiredService>();
+ NoFinished = new ConcurrentDictionary();
+ var yarns = _yarnRepository.GetList(y => !y.IsFinished);
+ foreach (var yarn in yarns)
+ {
+ NoFinished.TryAdd(yarn.ScanCode, Yarn.FromEntity(yarn));
+ }
+ }
+
+ public ConcurrentDictionary NoFinished { get; }
+
+ public async Task AddYarnAsync(Yarn yarn)
+ {
+ var id = await _yarnRepository.InsertReturnIdentityAsync(yarn.ToEntity());
+ yarn.Id = id;
+ NoFinished.TryAdd(yarn.ScanCode, yarn);
+ return yarn;
+ }
+
+ public async Task> GetYarnsByTrayIdAsync(int trayId)
+ {
+ return (await _yarnRepository.GetListAsync(y => y.TrayId == trayId))
+ .Select(Yarn.FromEntity).ToList();
+ }
+
+ public async Task GetYarnByCodeAsync(string code)
+ {
+ return NoFinished[code];
+ }
+
+ public async Task FinishYarnAsync(string yarnCode)
+ {
+ var yarn = NoFinished[yarnCode];
+ yarn.IsFinished = true;
+ await _yarnRepository.UpdateAsync(yarn.ToEntity());
+ NoFinished.TryRemove(yarnCode, out _);
+ }
+
+ public async Task BindTrayAsync(string yarnCode, int trayId)
+ {
+ var yarn = NoFinished[yarnCode];
+ yarn.TrayId = trayId;
+ yarn.StackTime = DateTime.Now;
+ yarn.IsFinished = true;
+ yarn.IsFinished = true;
+ await _yarnRepository.UpdateAsync(yarn.ToEntity());
+ NoFinished.TryRemove(yarnCode, out _);
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Seyounth.Hyosung.Data.csproj b/Seyounth.Hyosung.Data/Seyounth.Hyosung.Data.csproj
new file mode 100644
index 0000000..19f45ee
--- /dev/null
+++ b/Seyounth.Hyosung.Data/Seyounth.Hyosung.Data.csproj
@@ -0,0 +1,20 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Seyounth.Hyosung.Runtime/HyosungRuntime.cs b/Seyounth.Hyosung.Runtime/HyosungRuntime.cs
new file mode 100644
index 0000000..fb5dd6c
--- /dev/null
+++ b/Seyounth.Hyosung.Runtime/HyosungRuntime.cs
@@ -0,0 +1,212 @@
+using System.Collections.Concurrent;
+using Microsoft.Extensions.Logging;
+using Seyounth.Hyosung.Core.Agv;
+using Seyounth.Hyosung.Core.Plc;
+using Seyounth.Hyosung.Core.Printer;
+using Seyounth.Hyosung.Core.Scanner;
+using Seyounth.Hyosung.Data.Models;
+using Seyounth.Hyosung.Data.Models.Plc;
+using Seyounth.Hyosung.Data.Services;
+using Seyounth.Hyosung.Data.Services.Hyosung;
+
+namespace Seyounth.Hyosung.Runtime;
+
+public class HyosungRuntime(
+ ILogger logger,
+ IHyosungPlcService hyosungPlcService,
+ IHyosungScannerService hyosungScannerService,
+ IHyosungPrinter printer,
+ IYarnService yarnService,
+ ITrayService trayService,
+ IVarietyService varietyService,
+ IHyosungAgvService hyosungAgvService,
+ IHyosungWmsService hyosungWmsService) : IHyosungRuntime
+{
+ public async Task StartAsync(CancellationToken token)
+ {
+ //启动扫码服务
+ await hyosungScannerService.StartAsync(token);
+ await printer.StartAsync(token);
+ //最后启动PLC服务
+ hyosungPlcService.OnPlcRequestScanProduct += OnPlcRequestScanProduct;
+ hyosungPlcService.OnPlcRequestScanFixture += OnPlcRequestScanFixture;
+ hyosungPlcService.OnPlcRequestLeavingProductionLine += OnPlcRequestLeavingProductionLine;
+ hyosungPlcService.OnPlcNeedNewTrayCode += OnPlcNeedNewTrayCode;
+ hyosungPlcService.OnPlcPutCompleted += OnPlcPutCompleted;
+ hyosungPlcService.OnPlcRequestPackLineOption += OnPlcRequestPackLineOption;
+ hyosungPlcService.OnRequestPrintLabel += OnPlcRequestPrintLabel;
+ await hyosungPlcService.StartAsync(token);
+ }
+
+ public async Task StopAsync(CancellationToken token)
+ {
+ //先停止扫码服务
+ // await hyosungScannerService.StopAsync(token);
+ await printer.StopAsync(token);
+ //先停止PLC服务
+ //解绑相关事件
+ hyosungPlcService.OnPlcRequestScanProduct -= OnPlcRequestScanProduct;
+ hyosungPlcService.OnPlcRequestScanFixture -= OnPlcRequestScanFixture;
+ hyosungPlcService.OnPlcRequestLeavingProductionLine -= OnPlcRequestLeavingProductionLine;
+ hyosungPlcService.OnPlcNeedNewTrayCode -= OnPlcNeedNewTrayCode;
+ hyosungPlcService.OnPlcPutCompleted -= OnPlcPutCompleted;
+ await hyosungPlcService.StopAsync();
+ }
+
+
+ public async Task SendVarietyToPlcAsync(Variety variety)
+ {
+ await hyosungPlcService.WriteVarietyAsync(variety);
+ logger.LogInformation($"send variety to plc success: {variety.Id}");
+ }
+
+ ///
+ /// 处理PLC请求扫描治具事件
+ ///
+ /// 治具ID
+ ///
+ ///
+ private async Task OnPlcRequestScanFixture(int fixtureId)
+ {
+ var fix = await hyosungScannerService.ScanFixtureAsync(fixtureId);
+ if (string.IsNullOrEmpty(fix))
+ {
+ await hyosungPlcService.WriteScanFixtureResultAsync(fixtureId, false);
+ logger.LogInformation($"scan fixture{fixtureId} fail");
+ }
+ else
+ {
+ await hyosungPlcService.WriteScanFixtureResultAsync(fixtureId, true, (short)Convert.ToInt32(fix));
+ logger.LogInformation($"scan fixture{fixtureId} success: {fix}");
+ }
+ }
+
+ ///
+ /// 处理PLC请求扫描纱事件
+ ///
+ ///
+ private async Task OnPlcRequestScanProduct(int varietyId)
+ {
+ logger.LogInformation($"plc request scan yarn qrcode");
+ var yarn = await hyosungScannerService.ScanYarnAsync(varietyId);
+ if (yarn is null)
+ {
+ await hyosungPlcService.WriteScanYarnResultAsync(false);
+ logger.LogInformation($"scan yarn fail");
+ return;
+ }
+
+ await yarnService.AddYarnAsync(yarn);
+ await hyosungPlcService.WriteScanYarnResultAsync(true, (short)varietyId, yarn.ScanCode);
+ logger.LogInformation($"scan yarn {yarn.ScanCode} success: qrcode[{yarn.QrCode}]");
+ }
+
+ ///
+ /// 处理PLC请求下线事件
+ ///
+ ///
+ ///
+ private async Task OnPlcRequestLeavingProductionLine(PlcStackInfo info)
+ {
+ //使托盘完成
+ await trayService.StorageAsync(info.TrayCode);
+ await hyosungAgvService.StorageAsync(info.TrayCode);
+ //标志下线已完成
+ await hyosungPlcService.LeaveCompletedAsync();
+ }
+
+
+ ///
+ /// 处理Plc需要新的托盘号事件
+ ///
+ ///
+ ///
+ ///
+ ///
+ private async Task OnPlcNeedNewTrayCode(int index, int varietyId)
+ {
+ var tray = await trayService.GeneraNewTray(varietyId);
+ await hyosungPlcService.WriteTrayCodeAsync(index, tray.TrayCode);
+ }
+
+ ///
+ /// PLC码垛一次完成
+ ///
+ ///
+ ///
+ ///
+ private async Task OnPlcPutCompleted(PlcStackingInfo arg)
+ {
+ foreach (var yarnCode in arg.YarnCode)
+ {
+ await yarnService.BindTrayAsync(yarnCode, await trayService.GetIdByCode(arg.TrayCode));
+ }
+
+ await hyosungPlcService.WriteReceivedYarnCountAsync(arg.YarnCode.Count);
+ }
+
+ ///
+ /// 处理PLC请求打包线配置事件
+ ///
+ ///
+ ///
+ ///
+ private async Task OnPlcRequestPackLineOption(string arg)
+ {
+ var tray = await trayService.GetByCode(arg);
+ var variety = await varietyService.GetById(tray.VarietyId);
+ var option = new PackLineOption()
+ {
+ HeadCount = variety.StackHeadCount ?? 0,
+ HasBox = variety.HasBox,
+ IsTop = variety.NeedTopBoard is NeedType.Need or NeedType.NotNeed
+ ? variety.NeedTopBoard == NeedType.Need
+ : tray.IsEven && variety.NeedTopBoard == NeedType.EvenNeed,
+ IsPack = variety.NeedPackStrap is NeedType.Need or NeedType.NotNeed
+ ? variety.NeedPackStrap == NeedType.Need
+ : tray.IsEven && variety.NeedPackStrap == NeedType.EvenNeed,
+ IsFilm = variety.NeedFilmWrapping is NeedType.Need or NeedType.NotNeed
+ ? variety.NeedFilmWrapping == NeedType.Need
+ : tray.IsEven && variety.NeedFilmWrapping == NeedType.EvenNeed,
+ IsLam = variety.NeedFilmCoating is NeedType.Need or NeedType.NotNeed
+ ? variety.NeedFilmCoating == NeedType.Need
+ : tray.IsEven && variety.NeedFilmCoating == NeedType.EvenNeed,
+ };
+ await hyosungPlcService.WritePackLineOptionAsync(option);
+ }
+
+ ///
+ /// 处理贴标站请求贴标事件
+ ///
+ ///
+ ///
+ ///
+ ///
+ private async Task OnPlcRequestPrintLabel(int arg1, string trayCode, int height)
+ {
+ try
+ {
+ if (arg1 == 1)
+ {
+ var tray = await trayService.GetByCode(trayCode);
+ var variety = await varietyService.GetById(tray.VarietyId);
+ var mod = await hyosungWmsService.GetItemInfoByItemCode(variety.Code);
+ var grade = "1";
+ if (mod.GRADE != "AA") grade = mod.GRADE;
+ var controlNo = await hyosungWmsService.GetControlNo(variety, grade);
+ await trayService.PrintTrayAsync(trayCode, height, controlNo, mod);
+ await printer.PrintAsync(1, trayCode);
+ await hyosungWmsService.UpdateControlNo(variety, controlNo);
+ }
+ else
+ await printer.PrintAsync(1, trayCode);
+
+ await hyosungPlcService.WritePrintLabelResultAsync(arg1, true);
+ }
+ catch (Exception e)
+ {
+ await hyosungPlcService.WritePrintLabelResultAsync(arg1, false);
+ logger.LogError(e, "print label fail");
+ }
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Runtime/HyosungWorker.cs b/Seyounth.Hyosung.Runtime/HyosungWorker.cs
new file mode 100644
index 0000000..c315f6c
--- /dev/null
+++ b/Seyounth.Hyosung.Runtime/HyosungWorker.cs
@@ -0,0 +1,26 @@
+using Microsoft.Extensions.Hosting;
+
+namespace Seyounth.Hyosung.Runtime;
+
+public class HyosungWorker(IHyosungRuntime runtime) : BackgroundService
+{
+ public override async Task StopAsync(CancellationToken cancellationToken)
+ {
+ await runtime.StopAsync(cancellationToken);
+ await base.StopAsync(cancellationToken);
+ }
+
+ public override async Task StartAsync(CancellationToken cancellationToken)
+ {
+ await runtime.StartAsync(cancellationToken);
+ await base.StartAsync(cancellationToken);
+ }
+
+ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
+ {
+ while (stoppingToken.IsCancellationRequested)
+ {
+ await Task.Delay(1000, stoppingToken);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Runtime/IHyosungRuntime.cs b/Seyounth.Hyosung.Runtime/IHyosungRuntime.cs
new file mode 100644
index 0000000..3dfb334
--- /dev/null
+++ b/Seyounth.Hyosung.Runtime/IHyosungRuntime.cs
@@ -0,0 +1,29 @@
+using System.Collections.Concurrent;
+using Seyounth.Hyosung.Data.Models;
+
+namespace Seyounth.Hyosung.Runtime;
+
+public interface IHyosungRuntime
+{
+
+ ///
+ /// 启动运行
+ ///
+ ///
+ ///
+ Task StartAsync(CancellationToken token);
+
+ ///
+ /// 停止运行
+ ///
+ ///
+ ///
+ Task StopAsync(CancellationToken token);
+
+ ///
+ /// 发布品类信息到PLC
+ ///
+ ///
+ ///
+ Task SendVarietyToPlcAsync(Variety variety);
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Runtime/ServiceExtensions.cs b/Seyounth.Hyosung.Runtime/ServiceExtensions.cs
new file mode 100644
index 0000000..11f5451
--- /dev/null
+++ b/Seyounth.Hyosung.Runtime/ServiceExtensions.cs
@@ -0,0 +1,23 @@
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Seyounth.Hyosung.Core;
+using Seyounth.Hyosung.Data;
+
+namespace Seyounth.Hyosung.Runtime;
+
+public static class ServiceExtensions
+{
+ public static IServiceCollection AddHyosung(this IServiceCollection services, ConfigurationManager configuration)
+ {
+ services.AddHyosungData(configuration);
+ services.AddHyosungServices(configuration);
+ services.AddHostedService();
+ services.AddSingleton();
+ return services;
+ }
+
+ public static void UseHyosung(this IServiceProvider provider)
+ {
+ provider.UseHyosungData();
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Runtime/Seyounth.Hyosung.Runtime.csproj b/Seyounth.Hyosung.Runtime/Seyounth.Hyosung.Runtime.csproj
new file mode 100644
index 0000000..339a0b5
--- /dev/null
+++ b/Seyounth.Hyosung.Runtime/Seyounth.Hyosung.Runtime.csproj
@@ -0,0 +1,19 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Seyounth.Hyosung.sln b/Seyounth.Hyosung.sln
new file mode 100644
index 0000000..9fdec85
--- /dev/null
+++ b/Seyounth.Hyosung.sln
@@ -0,0 +1,58 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Seyounth.Hyosung.Core", "Seyounth.Hyosung.Core\Seyounth.Hyosung.Core.csproj", "{B6FCBC79-2C82-4915-BE52-16F4F22F2650}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Seyounth.Hyosung.Data", "Seyounth.Hyosung.Data\Seyounth.Hyosung.Data.csproj", "{BC51516E-38D1-482C-913B-CE8F514CF978}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Seyounth.Hyosung.Runtime", "Seyounth.Hyosung.Runtime\Seyounth.Hyosung.Runtime.csproj", "{CB32CBA4-8760-490A-8E48-91CB10AD3965}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Seyounth.Core", "Seyounth.Core\Seyounth.Core.csproj", "{BC139001-2C26-4E95-982F-DA90DC0CFB4A}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tester", "Tester", "{F94CF5F9-01E3-4159-BC91-1EC9D8112837}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HyosungDataTester", "HyosungDataTester\HyosungDataTester.csproj", "{6D6BC0D1-1460-42A7-8A47-81B22B2C7A07}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HyosungTester", "HyosungTester\HyosungTester.csproj", "{95193F01-653D-4664-84F3-1956994703D6}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Seyounth.Hyosung", "Seyounth.Hyosung\Seyounth.Hyosung.csproj", "{16C5CC9B-FEA9-4B1E-805F-C6DBF5865DC0}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B6FCBC79-2C82-4915-BE52-16F4F22F2650}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B6FCBC79-2C82-4915-BE52-16F4F22F2650}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B6FCBC79-2C82-4915-BE52-16F4F22F2650}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B6FCBC79-2C82-4915-BE52-16F4F22F2650}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BC51516E-38D1-482C-913B-CE8F514CF978}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BC51516E-38D1-482C-913B-CE8F514CF978}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BC51516E-38D1-482C-913B-CE8F514CF978}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BC51516E-38D1-482C-913B-CE8F514CF978}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CB32CBA4-8760-490A-8E48-91CB10AD3965}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CB32CBA4-8760-490A-8E48-91CB10AD3965}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CB32CBA4-8760-490A-8E48-91CB10AD3965}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CB32CBA4-8760-490A-8E48-91CB10AD3965}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BC139001-2C26-4E95-982F-DA90DC0CFB4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BC139001-2C26-4E95-982F-DA90DC0CFB4A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BC139001-2C26-4E95-982F-DA90DC0CFB4A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BC139001-2C26-4E95-982F-DA90DC0CFB4A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6D6BC0D1-1460-42A7-8A47-81B22B2C7A07}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6D6BC0D1-1460-42A7-8A47-81B22B2C7A07}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6D6BC0D1-1460-42A7-8A47-81B22B2C7A07}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6D6BC0D1-1460-42A7-8A47-81B22B2C7A07}.Release|Any CPU.Build.0 = Release|Any CPU
+ {95193F01-653D-4664-84F3-1956994703D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {95193F01-653D-4664-84F3-1956994703D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {95193F01-653D-4664-84F3-1956994703D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {95193F01-653D-4664-84F3-1956994703D6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {16C5CC9B-FEA9-4B1E-805F-C6DBF5865DC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {16C5CC9B-FEA9-4B1E-805F-C6DBF5865DC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {16C5CC9B-FEA9-4B1E-805F-C6DBF5865DC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {16C5CC9B-FEA9-4B1E-805F-C6DBF5865DC0}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {6D6BC0D1-1460-42A7-8A47-81B22B2C7A07} = {F94CF5F9-01E3-4159-BC91-1EC9D8112837}
+ {95193F01-653D-4664-84F3-1956994703D6} = {F94CF5F9-01E3-4159-BC91-1EC9D8112837}
+ EndGlobalSection
+EndGlobal
diff --git a/Seyounth.Hyosung/App.xaml b/Seyounth.Hyosung/App.xaml
new file mode 100644
index 0000000..d0b97b3
--- /dev/null
+++ b/Seyounth.Hyosung/App.xaml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Seyounth.Hyosung/App.xaml.cs b/Seyounth.Hyosung/App.xaml.cs
new file mode 100644
index 0000000..2ea052d
--- /dev/null
+++ b/Seyounth.Hyosung/App.xaml.cs
@@ -0,0 +1,68 @@
+using System.Configuration;
+using System.Data;
+using System.IO;
+using System.Reflection;
+using System.Windows;
+using System.Windows.Threading;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+using Seyounth.Hyosung.Core.Printer;
+using Seyounth.Hyosung.Runtime;
+using Seyounth.Hyosung.Services;
+using Seyounth.Hyosung.ViewModels;
+using Seyounth.Hyosung.Views;
+using Seyounth.Hyosung.Views.Pages;
+
+namespace Seyounth.Hyosung;
+
+///
+/// Interaction logic for App.xaml
+///
+public partial class App : Application
+{
+ private static IHost _host;
+
+ public App()
+ {
+ var builder = Host
+ .CreateApplicationBuilder();
+ builder.Configuration.AddJsonFile("PrintTemp.json", true, true);
+ builder.Configuration.AddJsonFile("appsettings.json", true, true);
+ builder.Services.Configure(builder.Configuration.GetSection("Print"));
+ builder.Services.AddHostedService();
+ builder.Services.AddSingleton();
+ builder.Services.AddSingleton();
+ builder.Services.AddSingleton();
+ builder.Services.AddSingleton();
+ builder.Services.AddHyosung(builder.Configuration);
+ _host = builder.Build();
+ }
+
+
+ private void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
+ {
+ var logger = _host.Services.GetRequiredService>();
+ logger.LogError(e.Exception, "Unhandled exception");
+ }
+
+ private async void OnExit(object sender, ExitEventArgs e)
+ {
+ await _host.StopAsync();
+ _host.Dispose();
+ }
+
+ private void OnStartup(object sender, StartupEventArgs e)
+ {
+ try
+ {
+ _host.Services.UseHyosung();
+ _host.StartAsync();
+ }catch(Exception ex)
+ {
+ Console.WriteLine(ex.Message);
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung/AssemblyInfo.cs b/Seyounth.Hyosung/AssemblyInfo.cs
new file mode 100644
index 0000000..4a05c7d
--- /dev/null
+++ b/Seyounth.Hyosung/AssemblyInfo.cs
@@ -0,0 +1,10 @@
+using System.Windows;
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
\ No newline at end of file
diff --git a/Seyounth.Hyosung/Services/ApplicationHostService.cs b/Seyounth.Hyosung/Services/ApplicationHostService.cs
new file mode 100644
index 0000000..1bc43fc
--- /dev/null
+++ b/Seyounth.Hyosung/Services/ApplicationHostService.cs
@@ -0,0 +1,40 @@
+using System.Windows;
+using Microsoft.Extensions.Hosting;
+using Seyounth.Hyosung.Views;
+
+namespace Seyounth.Hyosung.Services;
+
+public class ApplicationHostService(IServiceProvider serviceProvider) : IHostedService
+{
+ ///
+ /// Triggered when the application host is ready to start the service.
+ ///
+ /// Indicates that the start process has been aborted.
+ public async Task StartAsync(CancellationToken cancellationToken)
+ {
+ await HandleActivationAsync();
+ }
+
+ ///
+ /// Triggered when the application host is performing a graceful shutdown.
+ ///
+ /// Indicates that the shutdown process should no longer be graceful.
+ public async Task StopAsync(CancellationToken cancellationToken)
+ {
+ await Task.CompletedTask;
+ }
+
+ ///
+ /// Creates main window during activation.
+ ///
+ private async Task HandleActivationAsync()
+ {
+ if (!Application.Current.Windows.OfType().Any())
+ {
+ Application.Current.MainWindow = serviceProvider.GetService(typeof(MainWindow)) as MainWindow;
+ Application.Current.MainWindow.Show();
+ }
+
+ await Task.CompletedTask;
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung/Seyounth.Hyosung.csproj b/Seyounth.Hyosung/Seyounth.Hyosung.csproj
new file mode 100644
index 0000000..eedaf4b
--- /dev/null
+++ b/Seyounth.Hyosung/Seyounth.Hyosung.csproj
@@ -0,0 +1,35 @@
+
+
+
+ WinExe
+ net8.0-windows
+ enable
+ enable
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+
+
+
+ MSBuild:Compile
+ Wpf
+ Designer
+
+
+
+
diff --git a/Seyounth.Hyosung/ViewModels/MainWindowViewModel.cs b/Seyounth.Hyosung/ViewModels/MainWindowViewModel.cs
new file mode 100644
index 0000000..769be17
--- /dev/null
+++ b/Seyounth.Hyosung/ViewModels/MainWindowViewModel.cs
@@ -0,0 +1,23 @@
+using System.Diagnostics.Metrics;
+using System.Windows;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+
+namespace Seyounth.Hyosung.ViewModels;
+
+public partial class MainWindowViewModel : ObservableObject
+{
+ [ObservableProperty] private string _applicationTitle = "Hyosung - Seyounth Auto";
+
+ [RelayCommand]
+ private void OnExit()
+ {
+ Application.Current.Shutdown();
+ }
+
+ [RelayCommand]
+ private void OnMinimize()
+ {
+ Application.Current.MainWindow.WindowState = WindowState.Minimized;
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung/ViewModels/VarietyViewModel.cs b/Seyounth.Hyosung/ViewModels/VarietyViewModel.cs
new file mode 100644
index 0000000..94ba22d
--- /dev/null
+++ b/Seyounth.Hyosung/ViewModels/VarietyViewModel.cs
@@ -0,0 +1,25 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using Seyounth.Core.Extensions;
+using Seyounth.Hyosung.Data.Entities;
+using Seyounth.Hyosung.Data.Models;
+
+namespace Seyounth.Hyosung.ViewModels;
+
+public partial class VarietyViewModel : ObservableObject
+{
+ [ObservableProperty] private List _varieties;
+
+ public IEnumerable NeedTypeItems { get; }
+ public VarietyViewModel()
+ {
+ _varieties = new List();
+ var needTypes = EnumHelper.GetValues();
+ NeedTypeItems = needTypes.Select(nt => new NeedTypeEnumItem
+ {
+ Value = nt,
+ Description = nt.GetDescription()
+ });
+ }
+
+
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung/Views/Controls/AddVarietyControl.xaml b/Seyounth.Hyosung/Views/Controls/AddVarietyControl.xaml
new file mode 100644
index 0000000..c6b2c33
--- /dev/null
+++ b/Seyounth.Hyosung/Views/Controls/AddVarietyControl.xaml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Seyounth.Hyosung/Views/Controls/AddVarietyControl.xaml.cs b/Seyounth.Hyosung/Views/Controls/AddVarietyControl.xaml.cs
new file mode 100644
index 0000000..885dc10
--- /dev/null
+++ b/Seyounth.Hyosung/Views/Controls/AddVarietyControl.xaml.cs
@@ -0,0 +1,22 @@
+using System.Windows;
+using System.Windows.Controls;
+
+namespace Seyounth.Hyosung.Views.Controls;
+
+public partial class AddVarietyControl : UserControl
+{
+ public AddVarietyControl()
+ {
+ InitializeComponent();
+ }
+
+ private void CancelButton_Click(object sender, RoutedEventArgs e)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void OkButton_Click(object sender, RoutedEventArgs e)
+ {
+ throw new NotImplementedException();
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung/Views/MainWindow.xaml b/Seyounth.Hyosung/Views/MainWindow.xaml
new file mode 100644
index 0000000..95113cf
--- /dev/null
+++ b/Seyounth.Hyosung/Views/MainWindow.xaml
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Seyounth.Hyosung/Views/MainWindow.xaml.cs b/Seyounth.Hyosung/Views/MainWindow.xaml.cs
new file mode 100644
index 0000000..03d0a05
--- /dev/null
+++ b/Seyounth.Hyosung/Views/MainWindow.xaml.cs
@@ -0,0 +1,21 @@
+using System.Windows;
+using Seyounth.Hyosung.ViewModels;
+using Seyounth.Hyosung.Views.Pages;
+
+namespace Seyounth.Hyosung.Views;
+
+///
+/// Interaction logic for MainWindow.xaml
+///
+public partial class MainWindow
+{
+ public MainWindowViewModel ViewModel { get; }
+
+ public MainWindow(MainWindowViewModel viewModel, VarietyPage varietyPage)
+ {
+ ViewModel = viewModel;
+ DataContext = this;
+ InitializeComponent();
+ VarietyFrame.Content = varietyPage;
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung/Views/Pages/VarietyPage.xaml b/Seyounth.Hyosung/Views/Pages/VarietyPage.xaml
new file mode 100644
index 0000000..2e67ae7
--- /dev/null
+++ b/Seyounth.Hyosung/Views/Pages/VarietyPage.xaml
@@ -0,0 +1,142 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Seyounth.Hyosung/Views/Pages/VarietyPage.xaml.cs b/Seyounth.Hyosung/Views/Pages/VarietyPage.xaml.cs
new file mode 100644
index 0000000..0b7899e
--- /dev/null
+++ b/Seyounth.Hyosung/Views/Pages/VarietyPage.xaml.cs
@@ -0,0 +1,36 @@
+using System.Windows;
+using System.Windows.Controls;
+using MaterialDesignThemes.Wpf;
+using Seyounth.Hyosung.Data.Entities;
+using Seyounth.Hyosung.Data.Models;
+using Seyounth.Hyosung.ViewModels;
+using Seyounth.Hyosung.Views.Controls;
+
+namespace Seyounth.Hyosung.Views.Pages;
+
+public partial class VarietyPage : Page
+{
+ public VarietyViewModel ViewModel { get; set; }
+
+
+ public VarietyPage(VarietyViewModel viewModel)
+ {
+ ViewModel = viewModel;
+ DataContext = this;
+ InitializeComponent();
+ }
+
+
+ private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
+ {
+ var blankVariety = new VarietyEntity()
+ ;
+ // 将空白对象添加到数据源中
+ ViewModel.Varieties.Add(blankVariety);
+ // 滚动到新添加的行并使其进入编辑状态
+ VarietyDataGrid.ScrollIntoView(blankVariety);
+ var index = ViewModel.Varieties.IndexOf(blankVariety);
+ VarietyDataGrid.SelectedIndex = index;
+ VarietyDataGrid.BeginEdit();
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung/appsettings.json b/Seyounth.Hyosung/appsettings.json
new file mode 100644
index 0000000..d1dea65
--- /dev/null
+++ b/Seyounth.Hyosung/appsettings.json
@@ -0,0 +1,5 @@
+{
+ "ConnectionStrings": {
+ "DefaultConnection": "server=DESKTOP-AJ6K895;database=seyounth.hyosung;Trusted_Connection=SSPI;Encrypt=True;TrustServerCertificate=True;"
+ }
+}
\ No newline at end of file
diff --git a/global.json b/global.json
new file mode 100644
index 0000000..2ddda36
--- /dev/null
+++ b/global.json
@@ -0,0 +1,7 @@
+{
+ "sdk": {
+ "version": "8.0.0",
+ "rollForward": "latestMinor",
+ "allowPrerelease": false
+ }
+}
\ No newline at end of file