From 34014ed142c7edc8ce325938c0cd2ae511825eb8 Mon Sep 17 00:00:00 2001 From: admin Date: Sun, 16 Mar 2025 03:17:36 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=A1=B9=E7=9B=AE=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/.idea.Seyounth.Hyosung/.idea/.gitignore | 13 + .../.idea/dataSources.xml | 12 + .../.idea/indexLayout.xml | 8 + HyosungDataTester/GlobalUsings.cs | 1 + HyosungDataTester/HyosungDataTester.csproj | 24 ++ HyosungDataTester/UnitTest1.cs | 21 ++ HyosungTester/HyosungTester.csproj | 14 + HyosungTester/Program.cs | 10 + .../Extensions/DateTimeExtensions.cs | 9 + Seyounth.Core/Extensions/EnumHelper.cs | 22 ++ Seyounth.Core/Seyounth.Core.csproj | 9 + Seyounth.Hyosung.Core/Agv/HikAgv.cs | 146 +++++++++ .../Agv/HikModels/AgvPosition.cs | 8 + .../Agv/HikModels/AgvStatusInfo.cs | 27 ++ .../Agv/HikModels/HikApiResult.cs | 24 ++ .../Agv/HyosungAgvService.cs | 42 +++ .../Agv/IHyosungAgvService.cs | 11 + .../Plc/HyosungPlcService.cs | 301 ++++++++++++++++++ .../Plc/IHyosungPlcService.cs | 97 ++++++ Seyounth.Hyosung.Core/Plc/McPlc.cs | 74 +++++ Seyounth.Hyosung.Core/PrintTemp.json | 103 ++++++ Seyounth.Hyosung.Core/Printer/AveryPrinter.cs | 47 +++ .../Printer/HyosungPrinter.cs | 132 ++++++++ .../Printer/IHyosungPrinter.cs | 15 + Seyounth.Hyosung.Core/Printer/PrintTemp.cs | 26 ++ Seyounth.Hyosung.Core/Scanner/HikScanner.cs | 49 +++ .../Scanner/HyosungScannerService.cs | 135 ++++++++ .../Scanner/IHyosungScannerService.cs | 24 ++ Seyounth.Hyosung.Core/ServiceExtensions.cs | 20 ++ .../Seyounth.Hyosung.Core.csproj | 24 ++ .../Entities/AgvBinEntity.cs | 34 ++ Seyounth.Hyosung.Data/Entities/DictEntity.cs | 15 + .../Entities/PalletEntity.cs | 26 ++ .../Entities/ScannedYarnEntity.cs | 52 +++ Seyounth.Hyosung.Data/Entities/TrayEntity.cs | 43 +++ .../Entities/VarietyEntity.cs | 87 +++++ Seyounth.Hyosung.Data/Models/NeedType.cs | 17 + Seyounth.Hyosung.Data/Models/Pallet.cs | 5 + Seyounth.Hyosung.Data/Models/PalletType.cs | 19 ++ .../Models/Plc/PackLineOption.cs | 18 ++ .../Models/Plc/PlcStackInfo.cs | 10 + .../Models/Plc/PlcStackingInfo.cs | 12 + Seyounth.Hyosung.Data/Models/Tray.cs | 84 +++++ Seyounth.Hyosung.Data/Models/Variety.cs | 179 +++++++++++ Seyounth.Hyosung.Data/Models/Yarn.cs | 143 +++++++++ .../Repositories/IRepository.cs | 7 + .../Repositories/Repository.cs | 11 + Seyounth.Hyosung.Data/ServiceExtensions.cs | 49 +++ .../Services/AgvBinService.cs | 45 +++ Seyounth.Hyosung.Data/Services/DictService.cs | 31 ++ .../Services/Hyosung/Entities/LabelResult.cs | 38 +++ .../Entities/MST_BOXNO_SEQ_NON_DATE.cs | 32 ++ .../Hyosung/Entities/MST_ITEM_2240_V.cs | 24 ++ .../Services/Hyosung/HyosungWmsService.cs | 77 +++++ .../Services/Hyosung/IHyosungWmsService.cs | 15 + .../Services/IAgvBinService.cs | 21 ++ .../Services/IDictService.cs | 10 + .../Services/ITrayService.cs | 45 +++ .../Services/IVarietyService.cs | 36 +++ .../Services/IYarnService.cs | 31 ++ Seyounth.Hyosung.Data/Services/TrayService.cs | 79 +++++ .../Services/VarietyService.cs | 61 ++++ Seyounth.Hyosung.Data/Services/YarnService.cs | 63 ++++ .../Seyounth.Hyosung.Data.csproj | 20 ++ Seyounth.Hyosung.Runtime/HyosungRuntime.cs | 212 ++++++++++++ Seyounth.Hyosung.Runtime/HyosungWorker.cs | 26 ++ Seyounth.Hyosung.Runtime/IHyosungRuntime.cs | 29 ++ Seyounth.Hyosung.Runtime/ServiceExtensions.cs | 23 ++ .../Seyounth.Hyosung.Runtime.csproj | 19 ++ Seyounth.Hyosung.sln | 58 ++++ Seyounth.Hyosung/App.xaml | 22 ++ Seyounth.Hyosung/App.xaml.cs | 68 ++++ Seyounth.Hyosung/AssemblyInfo.cs | 10 + .../Services/ApplicationHostService.cs | 40 +++ Seyounth.Hyosung/Seyounth.Hyosung.csproj | 35 ++ .../ViewModels/MainWindowViewModel.cs | 23 ++ .../ViewModels/VarietyViewModel.cs | 25 ++ .../Views/Controls/AddVarietyControl.xaml | 62 ++++ .../Views/Controls/AddVarietyControl.xaml.cs | 22 ++ Seyounth.Hyosung/Views/MainWindow.xaml | 129 ++++++++ Seyounth.Hyosung/Views/MainWindow.xaml.cs | 21 ++ Seyounth.Hyosung/Views/Pages/VarietyPage.xaml | 142 +++++++++ .../Views/Pages/VarietyPage.xaml.cs | 36 +++ Seyounth.Hyosung/appsettings.json | 5 + global.json | 7 + 85 files changed, 3901 insertions(+) create mode 100644 .idea/.idea.Seyounth.Hyosung/.idea/.gitignore create mode 100644 .idea/.idea.Seyounth.Hyosung/.idea/dataSources.xml create mode 100644 .idea/.idea.Seyounth.Hyosung/.idea/indexLayout.xml create mode 100644 HyosungDataTester/GlobalUsings.cs create mode 100644 HyosungDataTester/HyosungDataTester.csproj create mode 100644 HyosungDataTester/UnitTest1.cs create mode 100644 HyosungTester/HyosungTester.csproj create mode 100644 HyosungTester/Program.cs create mode 100644 Seyounth.Core/Extensions/DateTimeExtensions.cs create mode 100644 Seyounth.Core/Extensions/EnumHelper.cs create mode 100644 Seyounth.Core/Seyounth.Core.csproj create mode 100644 Seyounth.Hyosung.Core/Agv/HikAgv.cs create mode 100644 Seyounth.Hyosung.Core/Agv/HikModels/AgvPosition.cs create mode 100644 Seyounth.Hyosung.Core/Agv/HikModels/AgvStatusInfo.cs create mode 100644 Seyounth.Hyosung.Core/Agv/HikModels/HikApiResult.cs create mode 100644 Seyounth.Hyosung.Core/Agv/HyosungAgvService.cs create mode 100644 Seyounth.Hyosung.Core/Agv/IHyosungAgvService.cs create mode 100644 Seyounth.Hyosung.Core/Plc/HyosungPlcService.cs create mode 100644 Seyounth.Hyosung.Core/Plc/IHyosungPlcService.cs create mode 100644 Seyounth.Hyosung.Core/Plc/McPlc.cs create mode 100644 Seyounth.Hyosung.Core/PrintTemp.json create mode 100644 Seyounth.Hyosung.Core/Printer/AveryPrinter.cs create mode 100644 Seyounth.Hyosung.Core/Printer/HyosungPrinter.cs create mode 100644 Seyounth.Hyosung.Core/Printer/IHyosungPrinter.cs create mode 100644 Seyounth.Hyosung.Core/Printer/PrintTemp.cs create mode 100644 Seyounth.Hyosung.Core/Scanner/HikScanner.cs create mode 100644 Seyounth.Hyosung.Core/Scanner/HyosungScannerService.cs create mode 100644 Seyounth.Hyosung.Core/Scanner/IHyosungScannerService.cs create mode 100644 Seyounth.Hyosung.Core/ServiceExtensions.cs create mode 100644 Seyounth.Hyosung.Core/Seyounth.Hyosung.Core.csproj create mode 100644 Seyounth.Hyosung.Data/Entities/AgvBinEntity.cs create mode 100644 Seyounth.Hyosung.Data/Entities/DictEntity.cs create mode 100644 Seyounth.Hyosung.Data/Entities/PalletEntity.cs create mode 100644 Seyounth.Hyosung.Data/Entities/ScannedYarnEntity.cs create mode 100644 Seyounth.Hyosung.Data/Entities/TrayEntity.cs create mode 100644 Seyounth.Hyosung.Data/Entities/VarietyEntity.cs create mode 100644 Seyounth.Hyosung.Data/Models/NeedType.cs create mode 100644 Seyounth.Hyosung.Data/Models/Pallet.cs create mode 100644 Seyounth.Hyosung.Data/Models/PalletType.cs create mode 100644 Seyounth.Hyosung.Data/Models/Plc/PackLineOption.cs create mode 100644 Seyounth.Hyosung.Data/Models/Plc/PlcStackInfo.cs create mode 100644 Seyounth.Hyosung.Data/Models/Plc/PlcStackingInfo.cs create mode 100644 Seyounth.Hyosung.Data/Models/Tray.cs create mode 100644 Seyounth.Hyosung.Data/Models/Variety.cs create mode 100644 Seyounth.Hyosung.Data/Models/Yarn.cs create mode 100644 Seyounth.Hyosung.Data/Repositories/IRepository.cs create mode 100644 Seyounth.Hyosung.Data/Repositories/Repository.cs create mode 100644 Seyounth.Hyosung.Data/ServiceExtensions.cs create mode 100644 Seyounth.Hyosung.Data/Services/AgvBinService.cs create mode 100644 Seyounth.Hyosung.Data/Services/DictService.cs create mode 100644 Seyounth.Hyosung.Data/Services/Hyosung/Entities/LabelResult.cs create mode 100644 Seyounth.Hyosung.Data/Services/Hyosung/Entities/MST_BOXNO_SEQ_NON_DATE.cs create mode 100644 Seyounth.Hyosung.Data/Services/Hyosung/Entities/MST_ITEM_2240_V.cs create mode 100644 Seyounth.Hyosung.Data/Services/Hyosung/HyosungWmsService.cs create mode 100644 Seyounth.Hyosung.Data/Services/Hyosung/IHyosungWmsService.cs create mode 100644 Seyounth.Hyosung.Data/Services/IAgvBinService.cs create mode 100644 Seyounth.Hyosung.Data/Services/IDictService.cs create mode 100644 Seyounth.Hyosung.Data/Services/ITrayService.cs create mode 100644 Seyounth.Hyosung.Data/Services/IVarietyService.cs create mode 100644 Seyounth.Hyosung.Data/Services/IYarnService.cs create mode 100644 Seyounth.Hyosung.Data/Services/TrayService.cs create mode 100644 Seyounth.Hyosung.Data/Services/VarietyService.cs create mode 100644 Seyounth.Hyosung.Data/Services/YarnService.cs create mode 100644 Seyounth.Hyosung.Data/Seyounth.Hyosung.Data.csproj create mode 100644 Seyounth.Hyosung.Runtime/HyosungRuntime.cs create mode 100644 Seyounth.Hyosung.Runtime/HyosungWorker.cs create mode 100644 Seyounth.Hyosung.Runtime/IHyosungRuntime.cs create mode 100644 Seyounth.Hyosung.Runtime/ServiceExtensions.cs create mode 100644 Seyounth.Hyosung.Runtime/Seyounth.Hyosung.Runtime.csproj create mode 100644 Seyounth.Hyosung.sln create mode 100644 Seyounth.Hyosung/App.xaml create mode 100644 Seyounth.Hyosung/App.xaml.cs create mode 100644 Seyounth.Hyosung/AssemblyInfo.cs create mode 100644 Seyounth.Hyosung/Services/ApplicationHostService.cs create mode 100644 Seyounth.Hyosung/Seyounth.Hyosung.csproj create mode 100644 Seyounth.Hyosung/ViewModels/MainWindowViewModel.cs create mode 100644 Seyounth.Hyosung/ViewModels/VarietyViewModel.cs create mode 100644 Seyounth.Hyosung/Views/Controls/AddVarietyControl.xaml create mode 100644 Seyounth.Hyosung/Views/Controls/AddVarietyControl.xaml.cs create mode 100644 Seyounth.Hyosung/Views/MainWindow.xaml create mode 100644 Seyounth.Hyosung/Views/MainWindow.xaml.cs create mode 100644 Seyounth.Hyosung/Views/Pages/VarietyPage.xaml create mode 100644 Seyounth.Hyosung/Views/Pages/VarietyPage.xaml.cs create mode 100644 Seyounth.Hyosung/appsettings.json create mode 100644 global.json 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 @@ + + + + + + + + + + + +