添加项目文件。
This commit is contained in:
parent
47d3aca9e9
commit
34014ed142
13
.idea/.idea.Seyounth.Hyosung/.idea/.gitignore
generated
vendored
Normal file
13
.idea/.idea.Seyounth.Hyosung/.idea/.gitignore
generated
vendored
Normal file
@ -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
|
12
.idea/.idea.Seyounth.Hyosung/.idea/dataSources.xml
generated
Normal file
12
.idea/.idea.Seyounth.Hyosung/.idea/dataSources.xml
generated
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||
<data-source source="LOCAL" name="hyosung.test" uuid="8700df22-a043-445e-8381-da146d36a9c8">
|
||||
<driver-ref>sqlite.xerial</driver-ref>
|
||||
<synchronize>true</synchronize>
|
||||
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
|
||||
<jdbc-url>jdbc:sqlite:$PROJECT_DIR$/Seyounth.Hyosung/bin/Debug/net8.0-windows/hyosung.test</jdbc-url>
|
||||
<working-dir>$ProjectFileDir$</working-dir>
|
||||
</data-source>
|
||||
</component>
|
||||
</project>
|
8
.idea/.idea.Seyounth.Hyosung/.idea/indexLayout.xml
generated
Normal file
8
.idea/.idea.Seyounth.Hyosung/.idea/indexLayout.xml
generated
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="UserContentModel">
|
||||
<attachedFolders />
|
||||
<explicitIncludes />
|
||||
<explicitExcludes />
|
||||
</component>
|
||||
</project>
|
1
HyosungDataTester/GlobalUsings.cs
Normal file
1
HyosungDataTester/GlobalUsings.cs
Normal file
@ -0,0 +1 @@
|
||||
global using NUnit.Framework;
|
24
HyosungDataTester/HyosungDataTester.csproj
Normal file
24
HyosungDataTester/HyosungDataTester.csproj
Normal file
@ -0,0 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0"/>
|
||||
<PackageReference Include="NUnit" Version="3.13.3"/>
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1"/>
|
||||
<PackageReference Include="NUnit.Analyzers" Version="3.6.1"/>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.0"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Seyounth.Hyosung.Data\Seyounth.Hyosung.Data.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
21
HyosungDataTester/UnitTest1.cs
Normal file
21
HyosungDataTester/UnitTest1.cs
Normal file
@ -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));
|
||||
}
|
||||
}
|
14
HyosungTester/HyosungTester.csproj
Normal file
14
HyosungTester/HyosungTester.csproj
Normal file
@ -0,0 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Seyounth.Hyosung.Data\Seyounth.Hyosung.Data.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
10
HyosungTester/Program.cs
Normal file
10
HyosungTester/Program.cs
Normal file
@ -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();
|
9
Seyounth.Core/Extensions/DateTimeExtensions.cs
Normal file
9
Seyounth.Core/Extensions/DateTimeExtensions.cs
Normal file
@ -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();
|
||||
}
|
||||
}
|
22
Seyounth.Core/Extensions/EnumHelper.cs
Normal file
22
Seyounth.Core/Extensions/EnumHelper.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Seyounth.Core.Extensions;
|
||||
|
||||
public static class EnumHelper
|
||||
{
|
||||
public static IEnumerable<T> GetValues<T>()
|
||||
{
|
||||
return Enum.GetValues(typeof(T)).Cast<T>();
|
||||
}
|
||||
|
||||
// 获取枚举值的描述信息
|
||||
public static string GetDescription<T>(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();
|
||||
}
|
||||
}
|
9
Seyounth.Core/Seyounth.Core.csproj
Normal file
9
Seyounth.Core/Seyounth.Core.csproj
Normal file
@ -0,0 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
146
Seyounth.Hyosung.Core/Agv/HikAgv.cs
Normal file
146
Seyounth.Hyosung.Core/Agv/HikAgv.cs
Normal file
@ -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<HikAgv> 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}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 取消任务
|
||||
/// </summary>
|
||||
/// <param name="taskCode"></param>
|
||||
public async Task CancelTaskAsync(string taskCode)
|
||||
{
|
||||
var url = Url + CancelTaskUri;
|
||||
var input = new
|
||||
{
|
||||
reqCode = GetRequestCode(),
|
||||
taskCode
|
||||
};
|
||||
var result = await PostAsync<string>(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<string>(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<string>(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<AgvStatusInfo?> 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<List<AgvStatusInfo>>(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<HikApiResult<T>?> PostAsync<T>(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<HikApiResult<T>>();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.LogError(e, $"post error");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
8
Seyounth.Hyosung.Core/Agv/HikModels/AgvPosition.cs
Normal file
8
Seyounth.Hyosung.Core/Agv/HikModels/AgvPosition.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace Seyounth.Hyosung.Core.Agv.HikModels;
|
||||
|
||||
public class AgvPosition
|
||||
{
|
||||
public string PositionCode { get; set; }
|
||||
|
||||
public string Type { get; set; }
|
||||
}
|
27
Seyounth.Hyosung.Core/Agv/HikModels/AgvStatusInfo.cs
Normal file
27
Seyounth.Hyosung.Core/Agv/HikModels/AgvStatusInfo.cs
Normal file
@ -0,0 +1,27 @@
|
||||
namespace Seyounth.Hyosung.Core.Agv.HikModels;
|
||||
|
||||
public class AgvStatusInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 机器人编号
|
||||
/// </summary>
|
||||
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; }
|
||||
/// <summary>
|
||||
/// 电量值
|
||||
/// </summary>
|
||||
public string Battery { get; set; }
|
||||
public string Status { get; set; }
|
||||
/// <summary>
|
||||
/// 是否已被排除,被排除后不接受新任务( 1-排除, 0-正常)
|
||||
public string exclType { get; set; }
|
||||
/// <summary>
|
||||
/// 是否暂停 0-否 1-是
|
||||
/// </summary>
|
||||
public string Stop { get; set; }
|
||||
|
||||
}
|
24
Seyounth.Hyosung.Core/Agv/HikModels/HikApiResult.cs
Normal file
24
Seyounth.Hyosung.Core/Agv/HikModels/HikApiResult.cs
Normal file
@ -0,0 +1,24 @@
|
||||
namespace Seyounth.Hyosung.Core.Agv.HikModels;
|
||||
|
||||
public class HikApiResult<TData>
|
||||
{
|
||||
/// <summary>
|
||||
/// 返回码
|
||||
/// </summary>
|
||||
public string Code { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 返回消息
|
||||
/// </summary>
|
||||
public string Message { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 请求编号
|
||||
/// </summary>
|
||||
public string ReqCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义返回
|
||||
/// </summary>
|
||||
public TData Data { get; set; }
|
||||
}
|
42
Seyounth.Hyosung.Core/Agv/HyosungAgvService.cs
Normal file
42
Seyounth.Hyosung.Core/Agv/HyosungAgvService.cs
Normal file
@ -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<HikAgv>());
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
11
Seyounth.Hyosung.Core/Agv/IHyosungAgvService.cs
Normal file
11
Seyounth.Hyosung.Core/Agv/IHyosungAgvService.cs
Normal file
@ -0,0 +1,11 @@
|
||||
namespace Seyounth.Hyosung.Core.Agv;
|
||||
|
||||
public interface IHyosungAgvService
|
||||
{
|
||||
/// <summary>
|
||||
/// 入库
|
||||
/// </summary>
|
||||
/// <param name="trayCode"></param>
|
||||
/// <returns></returns>
|
||||
Task StorageAsync(string trayCode);
|
||||
}
|
301
Seyounth.Hyosung.Core/Plc/HyosungPlcService.cs
Normal file
301
Seyounth.Hyosung.Core/Plc/HyosungPlcService.cs
Normal file
@ -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<HyosungPlcService> logger) : IHyosungPlcService
|
||||
{
|
||||
private readonly McPlc _reader = new("192.168.3.10", 4060, Mitsubishi.McFrame.MC3E);
|
||||
|
||||
private readonly McPlc _writer = new("192.168.3.10", 4061, Mitsubishi.McFrame.MC3E);
|
||||
|
||||
private bool isLeaving = false;
|
||||
|
||||
public async Task StartAsync(CancellationToken token)
|
||||
{
|
||||
token = token;
|
||||
List<Task<int>> ls =
|
||||
[
|
||||
_reader.ConnectAsync(),
|
||||
_writer.ConnectAsync()
|
||||
];
|
||||
var codes = await Task.WhenAll(ls);
|
||||
logger.LogInformation($"plc reader connect code: {codes[0]}\r\nplc writer connect code: {codes[1]}");
|
||||
ReadLoop(token);
|
||||
}
|
||||
|
||||
public async Task StopAsync()
|
||||
{
|
||||
List<Task<int>> ls =
|
||||
[
|
||||
_reader.CloseAsync(),
|
||||
_writer.CloseAsync()
|
||||
];
|
||||
var codes = await Task.WhenAll(ls);
|
||||
logger.LogInformation($"plc reader close code: {codes[0]}\r\nplc writer close code: {codes[1]}");
|
||||
}
|
||||
|
||||
|
||||
public async Task WriteVarietyAsync(Variety variety)
|
||||
{
|
||||
var data = variety.ToVarietyPlcData();
|
||||
await _writer.WriteShortsAsync(4200, data);
|
||||
logger.LogInformation($"write [{string.Join(",", data)}] data to plc address[4200]");
|
||||
await _writer.WriteShortsAsync(4230, (short)variety.Id);
|
||||
logger.LogInformation($"write [{variety.Id}] to plc address[4230]");
|
||||
}
|
||||
|
||||
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<short> ls = new List<short>();
|
||||
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<int, Task>? OnPlcRequestScanProduct;
|
||||
|
||||
public event Func<int, Task>? OnPlcRequestScanFixture;
|
||||
|
||||
public event Func<PlcStackInfo, Task>? OnPlcRequestLeavingProductionLine;
|
||||
|
||||
public event Func<int, int, Task>? OnPlcNeedNewTrayCode;
|
||||
|
||||
public event Func<PlcStackingInfo, Task>? OnPlcPutCompleted;
|
||||
|
||||
public event Func<string, Task>? OnPlcRequestPackLineOption;
|
||||
|
||||
public event Func<int, string, int, Task>? 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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询请求扫描产品方法
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询扫描夹具请求
|
||||
/// </summary>
|
||||
private async Task QueryScanFixtureRequest()
|
||||
{
|
||||
var requestScanFixture = await _reader.ReadShortsAsync(4505, 4);
|
||||
if (requestScanFixture[0] == 1)
|
||||
{
|
||||
await _writer.WriteShortsAsync(4505, 0);
|
||||
OnPlcRequestScanFixture?.Invoke(1);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询有托盘请求下线
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询是否需要新的托盘号
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 打包线请求获取配置
|
||||
/// </summary>
|
||||
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]);
|
||||
}
|
||||
}
|
||||
}
|
97
Seyounth.Hyosung.Core/Plc/IHyosungPlcService.cs
Normal file
97
Seyounth.Hyosung.Core/Plc/IHyosungPlcService.cs
Normal file
@ -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();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 写入品种到PLC
|
||||
/// </summary>
|
||||
/// <param name="variety"></param>
|
||||
/// <returns></returns>
|
||||
Task WriteVarietyAsync(Variety variety);
|
||||
|
||||
/// <summary>
|
||||
/// 写入扫码结果
|
||||
/// </summary>
|
||||
/// <param name="result">结果</param>
|
||||
/// <param name="varietyId">品类ID</param>
|
||||
/// <param name="yarnCode">纱码</param>
|
||||
/// <returns></returns>
|
||||
Task WriteScanYarnResultAsync(bool result, short? varietyId = null, string? yarnCode = null);
|
||||
|
||||
/// <summary>
|
||||
/// 写入治具扫码结果
|
||||
/// </summary>
|
||||
/// <param name="fixtureId"></param>
|
||||
/// <param name="result"></param>
|
||||
/// <param name="fixtureCode"></param>
|
||||
/// <returns></returns>
|
||||
Task WriteScanFixtureResultAsync(int fixtureId, bool result, short? fixtureCode = null);
|
||||
|
||||
/// <summary>
|
||||
/// 下线完成
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task LeaveCompletedAsync();
|
||||
|
||||
/// <summary>
|
||||
/// 写入托盘号
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
/// <param name="trayCode"></param>
|
||||
/// <returns></returns>
|
||||
Task WriteTrayCodeAsync(int index, string trayCode);
|
||||
|
||||
/// <summary>
|
||||
/// 写入收到的纱数量
|
||||
/// </summary>
|
||||
/// <param name="count"></param>
|
||||
/// <returns></returns>
|
||||
Task WriteReceivedYarnCountAsync(int count);
|
||||
|
||||
Task WritePackLineOptionAsync(PackLineOption option);
|
||||
|
||||
Task WritePrintLabelResultAsync(int index, bool result);
|
||||
|
||||
/// <summary>
|
||||
/// Plc请求扫描产品
|
||||
/// </summary>
|
||||
event Func<int, Task> OnPlcRequestScanProduct;
|
||||
|
||||
/// <summary>
|
||||
/// Plc请求扫描治具
|
||||
/// </summary>
|
||||
event Func<int, Task> OnPlcRequestScanFixture;
|
||||
|
||||
/// <summary>
|
||||
/// Plc请求下线
|
||||
/// </summary>
|
||||
event Func<PlcStackInfo, Task> OnPlcRequestLeavingProductionLine;
|
||||
|
||||
/// <summary>
|
||||
/// Plc需要新的托盘号
|
||||
/// </summary>
|
||||
event Func<int, int, Task> OnPlcNeedNewTrayCode;
|
||||
|
||||
/// <summary>
|
||||
/// Plc放入一次完成
|
||||
/// </summary>
|
||||
event Func<PlcStackingInfo, Task> OnPlcPutCompleted;
|
||||
|
||||
/// <summary>
|
||||
/// Plc请求打包线选项
|
||||
/// </summary>
|
||||
event Func<string, Task> OnPlcRequestPackLineOption;
|
||||
|
||||
/// <summary>
|
||||
/// 贴标站请求贴标
|
||||
/// </summary>
|
||||
event Func<int, string, int, Task> OnRequestPrintLabel;
|
||||
}
|
74
Seyounth.Hyosung.Core/Plc/McPlc.cs
Normal file
74
Seyounth.Hyosung.Core/Plc/McPlc.cs
Normal file
@ -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<int> ConnectAsync()
|
||||
{
|
||||
_mc.HostName = host;
|
||||
_mc.PortNumber = port;
|
||||
_mc.CommandFrame = type;
|
||||
return await _mc.Open();
|
||||
}
|
||||
|
||||
public Task<int> CloseAsync()
|
||||
{
|
||||
var code = _mc.Close();
|
||||
_mc.Dispose();
|
||||
return Task.FromResult(code);
|
||||
}
|
||||
|
||||
public async Task<byte[]> ReadBytesAsync(int address, int length)
|
||||
{
|
||||
var code = await _mc.ReadDeviceBlock(Mitsubishi.PlcDeviceType.D, address, length / 2);
|
||||
return code;
|
||||
}
|
||||
|
||||
public async Task<short[]> 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<string> 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);
|
||||
}
|
||||
}
|
103
Seyounth.Hyosung.Core/PrintTemp.json
Normal file
103
Seyounth.Hyosung.Core/PrintTemp.json
Normal file
File diff suppressed because one or more lines are too long
47
Seyounth.Hyosung.Core/Printer/AveryPrinter.cs
Normal file
47
Seyounth.Hyosung.Core/Printer/AveryPrinter.cs
Normal file
@ -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));
|
||||
}
|
||||
}
|
132
Seyounth.Hyosung.Core/Printer/HyosungPrinter.cs
Normal file
132
Seyounth.Hyosung.Core/Printer/HyosungPrinter.cs
Normal file
@ -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<HyosungPrinter> logger,
|
||||
IVarietyService varietyService,
|
||||
ITrayService trayService,
|
||||
IDictService dictService,
|
||||
IYarnService yarnService,
|
||||
IHyosungWmsService hyosungWmsService,
|
||||
IOptions<PrintTemp> 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<Task> ls = new List<Task>();
|
||||
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<string> GetPrint1Content(Tray tray)
|
||||
{
|
||||
var variety = await varietyService.GetById(tray.VarietyId);
|
||||
var yarns = await yarnService.GetYarnsByTrayIdAsync(tray.VarietyId);
|
||||
var dic = new Dictionary<string, string>();
|
||||
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<string> 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<string, string>
|
||||
{
|
||||
{ "$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;
|
||||
}
|
||||
}
|
15
Seyounth.Hyosung.Core/Printer/IHyosungPrinter.cs
Normal file
15
Seyounth.Hyosung.Core/Printer/IHyosungPrinter.cs
Normal file
@ -0,0 +1,15 @@
|
||||
namespace Seyounth.Hyosung.Core.Printer;
|
||||
|
||||
public interface IHyosungPrinter
|
||||
{
|
||||
Task StartAsync(CancellationToken token);
|
||||
|
||||
Task StopAsync(CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// 打印指定垛的标签
|
||||
/// </summary>
|
||||
/// <param name="trayCode"></param>
|
||||
/// <returns></returns>
|
||||
Task PrintAsync(int index,string trayCode);
|
||||
}
|
26
Seyounth.Hyosung.Core/Printer/PrintTemp.cs
Normal file
26
Seyounth.Hyosung.Core/Printer/PrintTemp.cs
Normal file
@ -0,0 +1,26 @@
|
||||
namespace Seyounth.Hyosung.Core.Printer;
|
||||
|
||||
public class PrintTemp
|
||||
{
|
||||
public string DefaultTemp { get; set; }
|
||||
|
||||
public string Partition { get; set; }
|
||||
|
||||
public List<Side> Sides { get; set; }
|
||||
|
||||
public List<TempData> 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; }
|
||||
}
|
49
Seyounth.Hyosung.Core/Scanner/HikScanner.cs
Normal file
49
Seyounth.Hyosung.Core/Scanner/HikScanner.cs
Normal file
@ -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<string> 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;
|
||||
}
|
||||
// 清空缓冲区 防止收到之前的数据
|
||||
}
|
||||
}
|
135
Seyounth.Hyosung.Core/Scanner/HyosungScannerService.cs
Normal file
135
Seyounth.Hyosung.Core/Scanner/HyosungScannerService.cs
Normal file
@ -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<HikScanner> _yarnScanners = new();
|
||||
|
||||
private readonly ILogger<HyosungScannerService> _logger;
|
||||
|
||||
private readonly ConcurrentDictionary<int, HikScanner> _fixtureScanners = new();
|
||||
|
||||
|
||||
public HyosungScannerService(ILogger<HyosungScannerService> 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<Task>();
|
||||
allTasks.AddRange(yarnScannerTasks);
|
||||
allTasks.AddRange(fixtureScannerTasks);
|
||||
|
||||
// 等待所有任务完成
|
||||
await Task.WhenAll(allTasks);
|
||||
|
||||
// 检查每个任务是否超时
|
||||
foreach (var task in yarnScannerTasks)
|
||||
{
|
||||
var innerTask = task as Task<Task>;
|
||||
if (innerTask.Result == timeoutTask)
|
||||
{
|
||||
// 处理纱线扫描器连接超时的情况
|
||||
Console.WriteLine($"纱线扫描器连接超时");
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var task in fixtureScannerTasks)
|
||||
{
|
||||
var innerTask = task as Task<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<Task> 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<Yarn?> ScanYarnAsync(int varietyId)
|
||||
{
|
||||
List<Task<Yarn?>> 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<Yarn?> 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<string> ScanFixtureAsync(int fixtureId)
|
||||
{
|
||||
return await _fixtureScanners[fixtureId].ScanAsync();
|
||||
}
|
||||
}
|
24
Seyounth.Hyosung.Core/Scanner/IHyosungScannerService.cs
Normal file
24
Seyounth.Hyosung.Core/Scanner/IHyosungScannerService.cs
Normal file
@ -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);
|
||||
|
||||
/// <summary>
|
||||
/// 扫描纱
|
||||
/// </summary>
|
||||
/// <param name="varietyId"></param>
|
||||
/// <returns></returns>
|
||||
Task<Yarn?> ScanYarnAsync(int varietyId);
|
||||
|
||||
/// <summary>
|
||||
/// 扫描治具
|
||||
/// </summary>
|
||||
/// <param name="fixtureId"></param>
|
||||
/// <returns></returns>
|
||||
Task<string> ScanFixtureAsync(int fixtureId);
|
||||
}
|
20
Seyounth.Hyosung.Core/ServiceExtensions.cs
Normal file
20
Seyounth.Hyosung.Core/ServiceExtensions.cs
Normal file
@ -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<IHyosungPlcService, HyosungPlcService>();
|
||||
services.AddSingleton<IHyosungScannerService, HyosungScannerService>();
|
||||
services.AddSingleton<IHyosungAgvService, HyosungAgvService>();
|
||||
services.AddSingleton<IHyosungPrinter, HyosungPrinter>();
|
||||
return services;
|
||||
}
|
||||
}
|
24
Seyounth.Hyosung.Core/Seyounth.Hyosung.Core.csproj
Normal file
24
Seyounth.Hyosung.Core/Seyounth.Hyosung.Core.csproj
Normal file
@ -0,0 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="McProtocol" Version="1.2.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Seyounth.Hyosung.Data\Seyounth.Hyosung.Data.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="PrintTemp.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
34
Seyounth.Hyosung.Data/Entities/AgvBinEntity.cs
Normal file
34
Seyounth.Hyosung.Data/Entities/AgvBinEntity.cs
Normal file
@ -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; }
|
||||
}
|
15
Seyounth.Hyosung.Data/Entities/DictEntity.cs
Normal file
15
Seyounth.Hyosung.Data/Entities/DictEntity.cs
Normal file
@ -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; }
|
||||
}
|
26
Seyounth.Hyosung.Data/Entities/PalletEntity.cs
Normal file
26
Seyounth.Hyosung.Data/Entities/PalletEntity.cs
Normal file
@ -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; }
|
||||
}
|
52
Seyounth.Hyosung.Data/Entities/ScannedYarnEntity.cs
Normal file
52
Seyounth.Hyosung.Data/Entities/ScannedYarnEntity.cs
Normal file
@ -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; }
|
||||
}
|
43
Seyounth.Hyosung.Data/Entities/TrayEntity.cs
Normal file
43
Seyounth.Hyosung.Data/Entities/TrayEntity.cs
Normal file
@ -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; }
|
||||
}
|
87
Seyounth.Hyosung.Data/Entities/VarietyEntity.cs
Normal file
87
Seyounth.Hyosung.Data/Entities/VarietyEntity.cs
Normal file
@ -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; }
|
||||
|
||||
}
|
17
Seyounth.Hyosung.Data/Models/NeedType.cs
Normal file
17
Seyounth.Hyosung.Data/Models/NeedType.cs
Normal file
@ -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; }
|
||||
}
|
5
Seyounth.Hyosung.Data/Models/Pallet.cs
Normal file
5
Seyounth.Hyosung.Data/Models/Pallet.cs
Normal file
@ -0,0 +1,5 @@
|
||||
using Seyounth.Hyosung.Data.Entities;
|
||||
|
||||
namespace Seyounth.Hyosung.Data.Models;
|
||||
|
||||
public class Pallet : PalletEntity;
|
19
Seyounth.Hyosung.Data/Models/PalletType.cs
Normal file
19
Seyounth.Hyosung.Data/Models/PalletType.cs
Normal file
@ -0,0 +1,19 @@
|
||||
namespace Seyounth.Hyosung.Data.Models;
|
||||
|
||||
public enum PalletType
|
||||
{
|
||||
/// <summary>
|
||||
/// 纸板托盘
|
||||
/// </summary>
|
||||
Paper=0,
|
||||
|
||||
/// <summary>
|
||||
/// 胶合板托盘
|
||||
/// </summary>
|
||||
Plywood = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 木板托盘
|
||||
/// </summary>
|
||||
Wood = 2
|
||||
}
|
18
Seyounth.Hyosung.Data/Models/Plc/PackLineOption.cs
Normal file
18
Seyounth.Hyosung.Data/Models/Plc/PackLineOption.cs
Normal file
@ -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; }
|
||||
|
||||
|
||||
}
|
10
Seyounth.Hyosung.Data/Models/Plc/PlcStackInfo.cs
Normal file
10
Seyounth.Hyosung.Data/Models/Plc/PlcStackInfo.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace Seyounth.Hyosung.Data.Models.Plc;
|
||||
|
||||
/// <summary>
|
||||
/// Plc侧整垛信息
|
||||
/// </summary>
|
||||
public class PlcStackInfo
|
||||
{
|
||||
public string TrayCode { get; set; }
|
||||
|
||||
}
|
12
Seyounth.Hyosung.Data/Models/Plc/PlcStackingInfo.cs
Normal file
12
Seyounth.Hyosung.Data/Models/Plc/PlcStackingInfo.cs
Normal file
@ -0,0 +1,12 @@
|
||||
namespace Seyounth.Hyosung.Data.Models.Plc;
|
||||
|
||||
public class PlcStackingInfo
|
||||
{
|
||||
public string TrayCode { get; set; }
|
||||
|
||||
public List<string> YarnCode { get; set; } = new List<string>();
|
||||
|
||||
public int YarnCount { get; set; }
|
||||
|
||||
public int TotalYarnCount { get; set; }
|
||||
}
|
84
Seyounth.Hyosung.Data/Models/Tray.cs
Normal file
84
Seyounth.Hyosung.Data/Models/Tray.cs
Normal file
@ -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
|
||||
};
|
||||
}
|
||||
}
|
179
Seyounth.Hyosung.Data/Models/Variety.cs
Normal file
179
Seyounth.Hyosung.Data/Models/Variety.cs
Normal file
@ -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<PalletEntity> 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<short> ls = new List<short>();
|
||||
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();
|
||||
}
|
||||
}
|
143
Seyounth.Hyosung.Data/Models/Yarn.cs
Normal file
143
Seyounth.Hyosung.Data/Models/Yarn.cs
Normal file
@ -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
|
||||
};
|
||||
}
|
||||
}
|
7
Seyounth.Hyosung.Data/Repositories/IRepository.cs
Normal file
7
Seyounth.Hyosung.Data/Repositories/IRepository.cs
Normal file
@ -0,0 +1,7 @@
|
||||
using SqlSugar;
|
||||
|
||||
namespace Seyounth.Hyosung.Data.Repositories;
|
||||
|
||||
public interface IRepository<T> : ISimpleClient<T> where T : class, new()
|
||||
{
|
||||
}
|
11
Seyounth.Hyosung.Data/Repositories/Repository.cs
Normal file
11
Seyounth.Hyosung.Data/Repositories/Repository.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using SqlSugar;
|
||||
|
||||
namespace Seyounth.Hyosung.Data.Repositories;
|
||||
|
||||
public class Repository<T> : SimpleClient<T>, IRepository<T> where T : class, new()
|
||||
{
|
||||
public Repository(ISqlSugarClient db)
|
||||
{
|
||||
base.Context = db;
|
||||
}
|
||||
}
|
49
Seyounth.Hyosung.Data/ServiceExtensions.cs
Normal file
49
Seyounth.Hyosung.Data/ServiceExtensions.cs
Normal file
@ -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<ISqlSugarClient>(s =>
|
||||
{
|
||||
SqlSugarScope sqlSugar = new SqlSugarScope(new ConnectionConfig()
|
||||
{
|
||||
DbType = DbType.SqlServer,
|
||||
ConnectionString = connectionString,
|
||||
IsAutoCloseConnection = true,
|
||||
}
|
||||
);
|
||||
return sqlSugar;
|
||||
});
|
||||
services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
|
||||
services.AddSingleton<IVarietyService, VarietyService>();
|
||||
services.AddSingleton<IYarnService, YarnService>();
|
||||
services.AddSingleton<ITrayService, TrayService>();
|
||||
services.AddSingleton<IAgvBinService, AgvBinService>();
|
||||
services.AddSingleton<IDictService, DictService>();
|
||||
services.AddSingleton<IHyosungWmsService, HyosungWmsService>();
|
||||
return services;
|
||||
}
|
||||
|
||||
public static void UseHyosungData(this IServiceProvider provider)
|
||||
{
|
||||
var db = provider.GetRequiredService<ISqlSugarClient>();
|
||||
db.DbMaintenance.CreateDatabase();
|
||||
db.CodeFirst.InitTables(typeof(VarietyEntity),
|
||||
typeof(PalletEntity),
|
||||
typeof(ScannedYarnEntity),
|
||||
typeof(TrayEntity),
|
||||
typeof(AgvBinEntity),
|
||||
typeof(DictEntity));
|
||||
}
|
||||
}
|
45
Seyounth.Hyosung.Data/Services/AgvBinService.cs
Normal file
45
Seyounth.Hyosung.Data/Services/AgvBinService.cs
Normal file
@ -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<AgvBinEntity> _cache;
|
||||
|
||||
private readonly IRepository<AgvBinEntity> repository;
|
||||
|
||||
public AgvBinService(IServiceProvider provider)
|
||||
{
|
||||
repository = provider.CreateScope().ServiceProvider.GetRequiredService<IRepository<AgvBinEntity>>();
|
||||
_cache = repository.GetList();
|
||||
}
|
||||
|
||||
public async Task<AgvBinEntity> 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);
|
||||
}
|
||||
}
|
31
Seyounth.Hyosung.Data/Services/DictService.cs
Normal file
31
Seyounth.Hyosung.Data/Services/DictService.cs
Normal file
@ -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<DictEntity> _repository;
|
||||
|
||||
private readonly List<DictEntity> _cache;
|
||||
|
||||
public DictService(IServiceProvider provider)
|
||||
{
|
||||
_repository = provider.CreateScope()
|
||||
.ServiceProvider.GetRequiredService<IRepository<DictEntity>>();
|
||||
_cache = _repository.GetList();
|
||||
}
|
||||
|
||||
|
||||
public async Task<string> GetKeyAsync(string type, string name)
|
||||
{
|
||||
return _cache.FirstOrDefault(d => d.Type == type && d.Value == name)?.Value ?? "";
|
||||
}
|
||||
|
||||
public async Task<List<DictEntity>> GetDictsByTypeAsync(string type)
|
||||
{
|
||||
return _cache.Where(d => d.Type == type).ToList();
|
||||
}
|
||||
}
|
@ -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; }
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
using SqlSugar;
|
||||
|
||||
namespace Seyounth.Hyosung.Data.Services.Hyosung.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// 晓星 控制号表
|
||||
/// </summary>
|
||||
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; }
|
||||
}
|
@ -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; }
|
||||
}
|
77
Seyounth.Hyosung.Data/Services/Hyosung/HyosungWmsService.cs
Normal file
77
Seyounth.Hyosung.Data/Services/Hyosung/HyosungWmsService.cs
Normal file
@ -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<int> GetControlNo(Variety variety, string grade)
|
||||
{
|
||||
var checkCode = $"02025{grade}{variety.Lot.ToString().Substring(1, 3)}";
|
||||
var x = await _db.Queryable<MST_BOXNO_SEQ_NON_DATE>().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<MST_ITEM_2240_V> GetItemInfoByItemCode(string itemCode)
|
||||
{
|
||||
return await _db.Queryable<MST_ITEM_2240_V>()
|
||||
.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<MST_BOXNO_SEQ_NON_DATE>()
|
||||
.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<LabelResult> 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<LabelResult>()
|
||||
.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();
|
||||
}
|
||||
}
|
15
Seyounth.Hyosung.Data/Services/Hyosung/IHyosungWmsService.cs
Normal file
15
Seyounth.Hyosung.Data/Services/Hyosung/IHyosungWmsService.cs
Normal file
@ -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<int> GetControlNo(Variety variety, string grade);
|
||||
|
||||
Task<MST_ITEM_2240_V> GetItemInfoByItemCode(string itemCode);
|
||||
|
||||
Task UpdateControlNo(Variety variety, int controlNo);
|
||||
|
||||
Task<LabelResult> GetLabelResult(string itemCode,string lot,int controlNo);
|
||||
}
|
21
Seyounth.Hyosung.Data/Services/IAgvBinService.cs
Normal file
21
Seyounth.Hyosung.Data/Services/IAgvBinService.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using Seyounth.Hyosung.Data.Entities;
|
||||
using Seyounth.Hyosung.Data.Models;
|
||||
|
||||
namespace Seyounth.Hyosung.Data.Services;
|
||||
|
||||
public interface IAgvBinService
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取可用的库位信息
|
||||
/// </summary>
|
||||
/// <param name="height"></param>
|
||||
/// <returns></returns>
|
||||
Task<AgvBinEntity> GetAvailableBin(int height);
|
||||
|
||||
/// <summary>
|
||||
/// 绑定相应的库
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <returns></returns>
|
||||
Task BindAsync(AgvBinEntity entity);
|
||||
}
|
10
Seyounth.Hyosung.Data/Services/IDictService.cs
Normal file
10
Seyounth.Hyosung.Data/Services/IDictService.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using Seyounth.Hyosung.Data.Entities;
|
||||
|
||||
namespace Seyounth.Hyosung.Data.Services;
|
||||
|
||||
public interface IDictService
|
||||
{
|
||||
Task<string> GetKeyAsync(string type, string value);
|
||||
|
||||
Task<List<DictEntity>> GetDictsByTypeAsync(string type);
|
||||
}
|
45
Seyounth.Hyosung.Data/Services/ITrayService.cs
Normal file
45
Seyounth.Hyosung.Data/Services/ITrayService.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using Seyounth.Hyosung.Data.Models;
|
||||
using Seyounth.Hyosung.Data.Services.Hyosung.Entities;
|
||||
|
||||
namespace Seyounth.Hyosung.Data.Services;
|
||||
|
||||
public interface ITrayService
|
||||
{
|
||||
/// <summary>
|
||||
/// 生成一个新的托盘
|
||||
/// </summary>
|
||||
/// <param name="varietyId">品类ID</param>
|
||||
/// <returns></returns>
|
||||
Task<Tray> GeneraNewTray(int varietyId);
|
||||
|
||||
/// <summary>
|
||||
/// 通过Code查找ID
|
||||
/// </summary>
|
||||
/// <param name="code"></param>
|
||||
/// <returns></returns>
|
||||
Task<int> GetIdByCode(string code);
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="code"></param>
|
||||
/// <returns></returns>
|
||||
Task<Tray> GetByCode(string code);
|
||||
|
||||
/// <summary>
|
||||
/// 生成控制号
|
||||
/// </summary>
|
||||
/// <param name="trayCode"></param>
|
||||
/// <returns></returns>
|
||||
Task StorageAsync(string trayCode);
|
||||
|
||||
/// <summary>
|
||||
/// 打印托盘
|
||||
/// </summary>
|
||||
/// <param name="trayCode"></param>
|
||||
/// <param name="stackHeight"></param>
|
||||
/// <param name="controlNo"></param>
|
||||
/// <param name="itemInfo"></param>
|
||||
/// <returns></returns>
|
||||
Task PrintTrayAsync(string trayCode, int stackHeight, int controlNo, MST_ITEM_2240_V itemInfo);
|
||||
}
|
36
Seyounth.Hyosung.Data/Services/IVarietyService.cs
Normal file
36
Seyounth.Hyosung.Data/Services/IVarietyService.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using Seyounth.Hyosung.Data.Models;
|
||||
|
||||
namespace Seyounth.Hyosung.Data.Services;
|
||||
|
||||
public interface IVarietyService
|
||||
{
|
||||
/// <summary>
|
||||
/// 通过品种代码获取品种信息
|
||||
/// </summary>
|
||||
/// <param name="code">品种代码</param>
|
||||
/// <param name="layers">码垛层数</param>
|
||||
/// <returns></returns>
|
||||
Task<Variety?> GetVarietyByCodeAsync(string code, int? layers = null);
|
||||
|
||||
Task<Variety> GetById(int id);
|
||||
|
||||
/// <summary>
|
||||
/// 添加品种信息
|
||||
/// </summary>
|
||||
/// <param name="variety"></param>
|
||||
/// <returns></returns>
|
||||
Task AddVarietyAsync(Variety variety);
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有托盘信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<List<Pallet>> GetPalletsAsync();
|
||||
|
||||
/// <summary>
|
||||
/// 添加托盘信息
|
||||
/// </summary>
|
||||
/// <param name="pallet"></param>
|
||||
/// <returns></returns>
|
||||
Task AddPalletAsync(Pallet pallet);
|
||||
}
|
31
Seyounth.Hyosung.Data/Services/IYarnService.cs
Normal file
31
Seyounth.Hyosung.Data/Services/IYarnService.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using System.Collections.Concurrent;
|
||||
using Seyounth.Hyosung.Data.Models;
|
||||
|
||||
namespace Seyounth.Hyosung.Data.Services;
|
||||
|
||||
public interface IYarnService
|
||||
{
|
||||
ConcurrentDictionary<string, Yarn> NoFinished { get; }
|
||||
|
||||
Task<Yarn?> AddYarnAsync(Yarn yarn);
|
||||
|
||||
|
||||
Task<List<Yarn>> GetYarnsByTrayIdAsync(int trayId);
|
||||
|
||||
Task<Yarn> GetYarnByCodeAsync(string code);
|
||||
|
||||
/// <summary>
|
||||
/// 完成指定纱
|
||||
/// </summary>
|
||||
/// <param name="yarnCode"></param>
|
||||
/// <returns></returns>
|
||||
Task FinishYarnAsync(string yarnCode);
|
||||
|
||||
/// <summary>
|
||||
/// 绑定托盘号
|
||||
/// </summary>
|
||||
/// <param name="yarnCode"></param>
|
||||
/// <param name="trayId"></param>
|
||||
/// <returns></returns>
|
||||
Task BindTrayAsync(string yarnCode, int trayId);
|
||||
}
|
79
Seyounth.Hyosung.Data/Services/TrayService.cs
Normal file
79
Seyounth.Hyosung.Data/Services/TrayService.cs
Normal file
@ -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<string, Tray> _cache = new();
|
||||
private readonly IRepository<TrayEntity> _repository;
|
||||
private readonly IHyosungWmsService _hyosungWmsService;
|
||||
|
||||
public TrayService(IServiceProvider provider, IHyosungWmsService hyosungWmsService)
|
||||
{
|
||||
_repository = provider.CreateScope().ServiceProvider.GetRequiredService<IRepository<TrayEntity>>();
|
||||
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<Tray> 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<int> GetIdByCode(string code)
|
||||
{
|
||||
return _cache[code].Id;
|
||||
}
|
||||
|
||||
public async Task<Tray> 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)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
61
Seyounth.Hyosung.Data/Services/VarietyService.cs
Normal file
61
Seyounth.Hyosung.Data/Services/VarietyService.cs
Normal file
@ -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<VarietyEntity> _varietyRepository;
|
||||
private readonly IRepository<PalletEntity> _palletRepository;
|
||||
private readonly ConcurrentBag<VarietyEntity> _varietiesCache;
|
||||
private readonly ConcurrentBag<PalletEntity> _palletsCache;
|
||||
|
||||
public VarietyService(IServiceProvider provider)
|
||||
{
|
||||
try
|
||||
{
|
||||
_varietyRepository = provider.CreateScope().ServiceProvider.GetRequiredService<IRepository<VarietyEntity>>();
|
||||
_palletRepository = provider.CreateScope().ServiceProvider.GetRequiredService<IRepository<PalletEntity>>();
|
||||
_varietiesCache = new ConcurrentBag<VarietyEntity>(_varietyRepository.GetList());
|
||||
_palletsCache = new ConcurrentBag<PalletEntity>(_palletRepository.GetList());
|
||||
}catch(Exception e)
|
||||
{
|
||||
Console.WriteLine(e.Message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public async Task<Variety?> 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<Variety> 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<List<Pallet>> GetPalletsAsync()
|
||||
{
|
||||
return _palletsCache.Select(p => (Pallet)p).ToList();
|
||||
}
|
||||
|
||||
public async Task AddPalletAsync(Pallet pallet)
|
||||
{
|
||||
var entity = await _palletRepository.InsertReturnEntityAsync(pallet);
|
||||
_palletsCache.Add(entity);
|
||||
}
|
||||
}
|
63
Seyounth.Hyosung.Data/Services/YarnService.cs
Normal file
63
Seyounth.Hyosung.Data/Services/YarnService.cs
Normal file
@ -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<ScannedYarnEntity> _yarnRepository;
|
||||
|
||||
public YarnService(IServiceProvider provider)
|
||||
{
|
||||
_yarnRepository = provider.CreateScope().ServiceProvider.GetRequiredService<IRepository<ScannedYarnEntity>>();
|
||||
NoFinished = new ConcurrentDictionary<string, Yarn>();
|
||||
var yarns = _yarnRepository.GetList(y => !y.IsFinished);
|
||||
foreach (var yarn in yarns)
|
||||
{
|
||||
NoFinished.TryAdd(yarn.ScanCode, Yarn.FromEntity(yarn));
|
||||
}
|
||||
}
|
||||
|
||||
public ConcurrentDictionary<string, Yarn> NoFinished { get; }
|
||||
|
||||
public async Task<Yarn?> AddYarnAsync(Yarn yarn)
|
||||
{
|
||||
var id = await _yarnRepository.InsertReturnIdentityAsync(yarn.ToEntity());
|
||||
yarn.Id = id;
|
||||
NoFinished.TryAdd(yarn.ScanCode, yarn);
|
||||
return yarn;
|
||||
}
|
||||
|
||||
public async Task<List<Yarn>> GetYarnsByTrayIdAsync(int trayId)
|
||||
{
|
||||
return (await _yarnRepository.GetListAsync(y => y.TrayId == trayId))
|
||||
.Select(Yarn.FromEntity).ToList();
|
||||
}
|
||||
|
||||
public async Task<Yarn> 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 _);
|
||||
}
|
||||
}
|
20
Seyounth.Hyosung.Data/Seyounth.Hyosung.Data.csproj
Normal file
20
Seyounth.Hyosung.Data/Seyounth.Hyosung.Data.csproj
Normal file
@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="McProtocol" Version="1.2.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.3" />
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.182" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Seyounth.Core\Seyounth.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
212
Seyounth.Hyosung.Runtime/HyosungRuntime.cs
Normal file
212
Seyounth.Hyosung.Runtime/HyosungRuntime.cs
Normal file
@ -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<HyosungRuntime> 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}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理PLC请求扫描治具事件
|
||||
/// </summary>
|
||||
/// <param name="fixtureId">治具ID</param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
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}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理PLC请求扫描纱事件
|
||||
/// </summary>
|
||||
/// <param name="varietyId"></param>
|
||||
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}]");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理PLC请求下线事件
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
private async Task OnPlcRequestLeavingProductionLine(PlcStackInfo info)
|
||||
{
|
||||
//使托盘完成
|
||||
await trayService.StorageAsync(info.TrayCode);
|
||||
await hyosungAgvService.StorageAsync(info.TrayCode);
|
||||
//标志下线已完成
|
||||
await hyosungPlcService.LeaveCompletedAsync();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 处理Plc需要新的托盘号事件
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
/// <param name="varietyId"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
private async Task OnPlcNeedNewTrayCode(int index, int varietyId)
|
||||
{
|
||||
var tray = await trayService.GeneraNewTray(varietyId);
|
||||
await hyosungPlcService.WriteTrayCodeAsync(index, tray.TrayCode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// PLC码垛一次完成
|
||||
/// </summary>
|
||||
/// <param name="arg"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理PLC请求打包线配置事件
|
||||
/// </summary>
|
||||
/// <param name="arg"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理贴标站请求贴标事件
|
||||
/// </summary>
|
||||
/// <param name="arg1"></param>
|
||||
/// <param name="arg2"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotImplementedException"></exception>
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
26
Seyounth.Hyosung.Runtime/HyosungWorker.cs
Normal file
26
Seyounth.Hyosung.Runtime/HyosungWorker.cs
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
29
Seyounth.Hyosung.Runtime/IHyosungRuntime.cs
Normal file
29
Seyounth.Hyosung.Runtime/IHyosungRuntime.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using System.Collections.Concurrent;
|
||||
using Seyounth.Hyosung.Data.Models;
|
||||
|
||||
namespace Seyounth.Hyosung.Runtime;
|
||||
|
||||
public interface IHyosungRuntime
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 启动运行
|
||||
/// </summary>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task StartAsync(CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// 停止运行
|
||||
/// </summary>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task StopAsync(CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// 发布品类信息到PLC
|
||||
/// </summary>
|
||||
/// <param name="variety"></param>
|
||||
/// <returns></returns>
|
||||
Task SendVarietyToPlcAsync(Variety variety);
|
||||
}
|
23
Seyounth.Hyosung.Runtime/ServiceExtensions.cs
Normal file
23
Seyounth.Hyosung.Runtime/ServiceExtensions.cs
Normal file
@ -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<HyosungWorker>();
|
||||
services.AddSingleton<IHyosungRuntime, HyosungRuntime>();
|
||||
return services;
|
||||
}
|
||||
|
||||
public static void UseHyosung(this IServiceProvider provider)
|
||||
{
|
||||
provider.UseHyosungData();
|
||||
}
|
||||
}
|
19
Seyounth.Hyosung.Runtime/Seyounth.Hyosung.Runtime.csproj
Normal file
19
Seyounth.Hyosung.Runtime/Seyounth.Hyosung.Runtime.csproj
Normal file
@ -0,0 +1,19 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Seyounth.Hyosung.Core\Seyounth.Hyosung.Core.csproj" />
|
||||
<ProjectReference Include="..\Seyounth.Hyosung.Data\Seyounth.Hyosung.Data.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.3" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
58
Seyounth.Hyosung.sln
Normal file
58
Seyounth.Hyosung.sln
Normal file
@ -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
|
22
Seyounth.Hyosung/App.xaml
Normal file
22
Seyounth.Hyosung/App.xaml
Normal file
@ -0,0 +1,22 @@
|
||||
<Application x:Class="Seyounth.Hyosung.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:Seyounth.Hyosung"
|
||||
DispatcherUnhandledException="OnDispatcherUnhandledException"
|
||||
Exit="OnExit"
|
||||
Startup="OnStartup">
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary
|
||||
Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/materialdesigntheme.dark.xaml" />
|
||||
<ResourceDictionary
|
||||
Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml" />
|
||||
<ResourceDictionary
|
||||
Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Primary/MaterialDesignColor.DeepPurple.xaml" />
|
||||
<ResourceDictionary
|
||||
Source="pack://application:,,,/MaterialDesignColors;component/Themes/Recommended/Accent/MaterialDesignColor.Lime.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
68
Seyounth.Hyosung/App.xaml.cs
Normal file
68
Seyounth.Hyosung/App.xaml.cs
Normal file
@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
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<PrintTemp>(builder.Configuration.GetSection("Print"));
|
||||
builder.Services.AddHostedService<ApplicationHostService>();
|
||||
builder.Services.AddSingleton<MainWindow>();
|
||||
builder.Services.AddSingleton<MainWindowViewModel>();
|
||||
builder.Services.AddSingleton<VarietyPage>();
|
||||
builder.Services.AddSingleton<VarietyViewModel>();
|
||||
builder.Services.AddHyosung(builder.Configuration);
|
||||
_host = builder.Build();
|
||||
}
|
||||
|
||||
|
||||
private void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
|
||||
{
|
||||
var logger = _host.Services.GetRequiredService<ILogger<App>>();
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
10
Seyounth.Hyosung/AssemblyInfo.cs
Normal file
10
Seyounth.Hyosung/AssemblyInfo.cs
Normal file
@ -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)
|
||||
)]
|
40
Seyounth.Hyosung/Services/ApplicationHostService.cs
Normal file
40
Seyounth.Hyosung/Services/ApplicationHostService.cs
Normal file
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Triggered when the application host is ready to start the service.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">Indicates that the start process has been aborted.</param>
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await HandleActivationAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when the application host is performing a graceful shutdown.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">Indicates that the shutdown process should no longer be graceful.</param>
|
||||
public async Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates main window during activation.
|
||||
/// </summary>
|
||||
private async Task HandleActivationAsync()
|
||||
{
|
||||
if (!Application.Current.Windows.OfType<MainWindow>().Any())
|
||||
{
|
||||
Application.Current.MainWindow = serviceProvider.GetService(typeof(MainWindow)) as MainWindow;
|
||||
Application.Current.MainWindow.Show();
|
||||
}
|
||||
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
}
|
35
Seyounth.Hyosung/Seyounth.Hyosung.csproj
Normal file
35
Seyounth.Hyosung/Seyounth.Hyosung.csproj
Normal file
@ -0,0 +1,35 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<UseWPF>true</UseWPF>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
|
||||
<PackageReference Include="MaterialDesignThemes" Version="4.9.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Seyounth.Hyosung.Runtime\Seyounth.Hyosung.Runtime.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="appsettings.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="Views\MainWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<XamlRuntime>Wpf</XamlRuntime>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
23
Seyounth.Hyosung/ViewModels/MainWindowViewModel.cs
Normal file
23
Seyounth.Hyosung/ViewModels/MainWindowViewModel.cs
Normal file
@ -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;
|
||||
}
|
||||
}
|
25
Seyounth.Hyosung/ViewModels/VarietyViewModel.cs
Normal file
25
Seyounth.Hyosung/ViewModels/VarietyViewModel.cs
Normal file
@ -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<VarietyEntity> _varieties;
|
||||
|
||||
public IEnumerable<NeedTypeEnumItem> NeedTypeItems { get; }
|
||||
public VarietyViewModel()
|
||||
{
|
||||
_varieties = new List<VarietyEntity>();
|
||||
var needTypes = EnumHelper.GetValues<NeedType>();
|
||||
NeedTypeItems = needTypes.Select(nt => new NeedTypeEnumItem
|
||||
{
|
||||
Value = nt,
|
||||
Description = nt.GetDescription()
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
62
Seyounth.Hyosung/Views/Controls/AddVarietyControl.xaml
Normal file
62
Seyounth.Hyosung/Views/Controls/AddVarietyControl.xaml
Normal file
@ -0,0 +1,62 @@
|
||||
<UserControl x:Class="Seyounth.Hyosung.Views.Controls.AddVarietyControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Seyounth.Hyosung.Views.Controls"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="300" d:DesignWidth="300">
|
||||
<StackPanel
|
||||
Margin="16">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="3*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="产品编号:" VerticalAlignment="Center" Margin="0,0,10,0"/>
|
||||
<TextBox Grid.Column="1"
|
||||
x:Name="VarietyCodeTextBox">
|
||||
</TextBox>
|
||||
</Grid>
|
||||
|
||||
<TextBox Grid.Row="1"
|
||||
x:Name="LotTextBox"
|
||||
materialDesign:HintAssist.Hint="Lot">
|
||||
</TextBox>
|
||||
</Grid>
|
||||
<StackPanel
|
||||
HorizontalAlignment="Right"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
Margin="0,8,8,0"
|
||||
Content="ACCEPT"
|
||||
IsDefault="True"
|
||||
Style="{StaticResource MaterialDesignFlatButton}">
|
||||
<Button.CommandParameter>
|
||||
<system:Boolean
|
||||
xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
True
|
||||
</system:Boolean>
|
||||
</Button.CommandParameter>
|
||||
</Button>
|
||||
<Button
|
||||
Margin="0,8,8,0"
|
||||
Content="CANCEL"
|
||||
IsCancel="True"
|
||||
Style="{StaticResource MaterialDesignFlatButton}">
|
||||
<Button.CommandParameter>
|
||||
<system:Boolean
|
||||
xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
False
|
||||
</system:Boolean>
|
||||
</Button.CommandParameter>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</UserControl>
|
22
Seyounth.Hyosung/Views/Controls/AddVarietyControl.xaml.cs
Normal file
22
Seyounth.Hyosung/Views/Controls/AddVarietyControl.xaml.cs
Normal file
@ -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();
|
||||
}
|
||||
}
|
129
Seyounth.Hyosung/Views/MainWindow.xaml
Normal file
129
Seyounth.Hyosung/Views/MainWindow.xaml
Normal file
@ -0,0 +1,129 @@
|
||||
<Window x:Class="Seyounth.Hyosung.Views.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:Seyounth.Hyosung"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:views="clr-namespace:Seyounth.Hyosung.Views"
|
||||
mc:Ignorable="d"
|
||||
d:DataContext="{d:DesignInstance views:MainWindow,
|
||||
IsDesignTimeCreatable=True}"
|
||||
Title="{Binding ViewModel.ApplicationTitle, Mode=OneWay}"
|
||||
Height="1080" Width="1920"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
WindowStyle="None"
|
||||
AllowsTransparency="True"
|
||||
WindowState="Maximized"
|
||||
Background="Transparent">
|
||||
<Border Background="{DynamicResource MaterialDesignPaper}"
|
||||
CornerRadius="4"
|
||||
Margin="10"
|
||||
materialDesign:ElevationAssist.Elevation="Dp2">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<materialDesign:ColorZone Padding="16"
|
||||
materialDesign:ElevationAssist.Elevation="Dp4"
|
||||
DockPanel.Dock="Top"
|
||||
Mode="PrimaryMid">
|
||||
<DockPanel>
|
||||
|
||||
<StackPanel DockPanel.Dock="Right" Orientation="Horizontal">
|
||||
<Button x:Name="One" Margin="-20,-20,10,-20"
|
||||
Content="_"
|
||||
Command="{Binding ViewModel.MinimizeCommand}" />
|
||||
<Button x:Name="Exit"
|
||||
Content="X"
|
||||
Command="{Binding ViewModel.ExitCommand}" />
|
||||
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="22"
|
||||
Text="Hyosung -- Seyounth Auto" />
|
||||
</DockPanel>
|
||||
</materialDesign:ColorZone>
|
||||
<materialDesign:Card Grid.Row="1">
|
||||
<TabControl
|
||||
x:Name="MenuTab"
|
||||
materialDesign:ColorZoneAssist.Mode="Standard"
|
||||
materialDesign:ElevationAssist.Elevation="Dp8"
|
||||
Style="{StaticResource MaterialDesignNavigationRailTabControl}">
|
||||
<TabItem x:Name="Home">
|
||||
<TabItem.Header>
|
||||
<StackPanel
|
||||
Width="auto"
|
||||
Height="auto">
|
||||
<materialDesign:PackIcon
|
||||
Width="24"
|
||||
Height="24"
|
||||
HorizontalAlignment="Center"
|
||||
Kind="Home" />
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
Text="仪表盘" />
|
||||
</StackPanel>
|
||||
</TabItem.Header>
|
||||
<Grid
|
||||
Width="100" />
|
||||
</TabItem>
|
||||
<TabItem x:Name="VarietyTabItem">
|
||||
<TabItem.Header>
|
||||
<StackPanel
|
||||
Width="auto"
|
||||
Height="auto">
|
||||
<materialDesign:PackIcon
|
||||
Width="24"
|
||||
Height="24"
|
||||
HorizontalAlignment="Center"
|
||||
Kind="ListBox" />
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
Text="产品信息" />
|
||||
</StackPanel>
|
||||
</TabItem.Header>
|
||||
<Frame Padding="16" HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch" x:Name="VarietyFrame" />
|
||||
</TabItem>
|
||||
<TabItem>
|
||||
<TabItem.Header>
|
||||
<StackPanel
|
||||
Width="auto"
|
||||
Height="auto">
|
||||
<materialDesign:PackIcon
|
||||
Width="24"
|
||||
Height="24"
|
||||
HorizontalAlignment="Center"
|
||||
Kind="Info" />
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
Text="运行状态" />
|
||||
</StackPanel>
|
||||
</TabItem.Header>
|
||||
</TabItem>
|
||||
<TabItem>
|
||||
<TabItem.Header>
|
||||
<StackPanel
|
||||
Width="auto"
|
||||
Height="auto">
|
||||
<materialDesign:PackIcon
|
||||
Width="24"
|
||||
Height="24"
|
||||
HorizontalAlignment="Center"
|
||||
Kind="Settings" />
|
||||
<TextBlock
|
||||
HorizontalAlignment="Center"
|
||||
Text="系统设置" />
|
||||
</StackPanel>
|
||||
</TabItem.Header>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
</materialDesign:Card>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Window>
|
21
Seyounth.Hyosung/Views/MainWindow.xaml.cs
Normal file
21
Seyounth.Hyosung/Views/MainWindow.xaml.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using System.Windows;
|
||||
using Seyounth.Hyosung.ViewModels;
|
||||
using Seyounth.Hyosung.Views.Pages;
|
||||
|
||||
namespace Seyounth.Hyosung.Views;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
public partial class MainWindow
|
||||
{
|
||||
public MainWindowViewModel ViewModel { get; }
|
||||
|
||||
public MainWindow(MainWindowViewModel viewModel, VarietyPage varietyPage)
|
||||
{
|
||||
ViewModel = viewModel;
|
||||
DataContext = this;
|
||||
InitializeComponent();
|
||||
VarietyFrame.Content = varietyPage;
|
||||
}
|
||||
}
|
142
Seyounth.Hyosung/Views/Pages/VarietyPage.xaml
Normal file
142
Seyounth.Hyosung/Views/Pages/VarietyPage.xaml
Normal file
@ -0,0 +1,142 @@
|
||||
<Page x:Class="Seyounth.Hyosung.Views.Pages.VarietyPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Seyounth.Hyosung.Views.Pages"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
mc:Ignorable="d"
|
||||
Width="Auto"
|
||||
Height="Auto"
|
||||
d:DataContext="{d:DesignInstance local:VarietyPage,
|
||||
IsDesignTimeCreatable=True}">
|
||||
<materialDesign:DialogHost x:Name="Root"
|
||||
DialogMargin="8"
|
||||
Style="{StaticResource MaterialDesignEmbeddedDialogHost}" >
|
||||
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="Auto" Height="Auto">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<ToolBarTray>
|
||||
<ToolBar ClipToBounds="False"
|
||||
Style="{StaticResource MaterialDesignToolBar}">
|
||||
<Button
|
||||
Content="{materialDesign:PackIcon Kind=Add}"
|
||||
Click="ButtonBase_OnClick"
|
||||
ToolTip="新增" />
|
||||
<Button
|
||||
Content="{materialDesign:PackIcon Kind=Edit}"
|
||||
ToolTip="编辑" />
|
||||
<Button
|
||||
Content="{materialDesign:PackIcon Kind=Delete}"
|
||||
ToolTip="删除" />
|
||||
<Separator />
|
||||
<ComboBox Margin="8"
|
||||
Width="400"
|
||||
materialDesign:HintAssist.Hint="品类编号"
|
||||
materialDesign:TextFieldAssist.HasClearButton="False"
|
||||
IsEditable="False"
|
||||
ItemsSource="{Binding ViewModel.Varieties}"
|
||||
DisplayMemberPath="Code"
|
||||
Style="{StaticResource MaterialDesignFilledComboBox}">
|
||||
</ComboBox>
|
||||
<Button
|
||||
Content="{materialDesign:PackIcon Kind=Search}"
|
||||
ToolTip="搜索" />
|
||||
</ToolBar>
|
||||
</ToolBarTray>
|
||||
<materialDesign:Card Margin="0,10,0,0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
|
||||
Width="Auto"
|
||||
Height="Auto"
|
||||
Grid.Row="1">
|
||||
<DataGrid x:Name="VarietyDataGrid"
|
||||
CanUserAddRows="True"
|
||||
AutoGenerateColumns="False"
|
||||
HeadersVisibility="All"
|
||||
ItemsSource="{Binding ViewModel.Varieties, Mode=OneWay}"
|
||||
SelectionUnit="{Binding ElementName=selectionUnitComboBox, Path=SelectedValue}">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn
|
||||
Binding="{Binding Code}"
|
||||
Header="代码"
|
||||
Width="Auto" />
|
||||
<DataGridTextColumn
|
||||
Binding="{Binding Lot }"
|
||||
Header="LOT"
|
||||
Width="Auto" />
|
||||
<DataGridTextColumn
|
||||
Binding="{Binding Specifications }"
|
||||
Header="规格"
|
||||
Width="Auto" />
|
||||
<DataGridTextColumn
|
||||
Binding="{Binding InnerDiameter }"
|
||||
Header="内径(D1)"
|
||||
Width="Auto" />
|
||||
<DataGridTextColumn
|
||||
Binding="{Binding OuterDiameter }"
|
||||
Header="外径(D2)"
|
||||
Width="Auto" />
|
||||
<DataGridTextColumn
|
||||
Binding="{Binding YarnDiameter }"
|
||||
Header="直径(D3)"
|
||||
Width="Auto" />
|
||||
<DataGridTextColumn
|
||||
Binding="{Binding PaperTubeHeight }"
|
||||
Header="纸管高(H1)"
|
||||
Width="Auto" />
|
||||
<DataGridTextColumn
|
||||
Binding="{Binding YarnThickness }"
|
||||
Header="纱线厚(H2)"
|
||||
Width="Auto" />
|
||||
<DataGridTextColumn
|
||||
Binding="{Binding SingleWeight }"
|
||||
Header="单筒重"
|
||||
Width="Auto" />
|
||||
<DataGridTextColumn
|
||||
Binding="{Binding StackingLayers }"
|
||||
Header="码层数"
|
||||
Width="Auto" />
|
||||
<DataGridTextColumn
|
||||
Binding="{Binding TotalCount }"
|
||||
Header="个/托"
|
||||
Width="Auto" />
|
||||
<DataGridTextColumn
|
||||
Binding="{Binding StackHeadSpec }"
|
||||
Header="垛头尺寸"
|
||||
Width="Auto" />
|
||||
<DataGridTextColumn
|
||||
Binding="{Binding StackHeadCount }"
|
||||
Header="垛头数量"
|
||||
Width="Auto" />
|
||||
<DataGridComboBoxColumn
|
||||
TextBinding="{Binding NeedTopBoard }"
|
||||
ItemsSource="{Binding }"
|
||||
Header="顶板"
|
||||
Width="Auto" />
|
||||
<DataGridComboBoxColumn
|
||||
TextBinding="{Binding NeedAngleBeam }"
|
||||
Header="护角"
|
||||
Width="Auto" />
|
||||
<DataGridComboBoxColumn
|
||||
TextBinding="{Binding NeedFilmWrapping }"
|
||||
Header="缠膜"
|
||||
Width="Auto" />
|
||||
<DataGridComboBoxColumn
|
||||
TextBinding="{Binding NeedFilmCoating }"
|
||||
Header="覆膜"
|
||||
Width="Auto" />
|
||||
<DataGridTextColumn
|
||||
Binding="{Binding MasterLabelCount }"
|
||||
Header="主标签数量"
|
||||
Width="Auto" />
|
||||
<DataGridTextColumn
|
||||
Binding="{Binding SubLabelCount }"
|
||||
Header="副标签数量"
|
||||
Width="Auto" />
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</materialDesign:Card>
|
||||
</Grid>
|
||||
</materialDesign:DialogHost>
|
||||
</Page>
|
36
Seyounth.Hyosung/Views/Pages/VarietyPage.xaml.cs
Normal file
36
Seyounth.Hyosung/Views/Pages/VarietyPage.xaml.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using MaterialDesignThemes.Wpf;
|
||||
using Seyounth.Hyosung.Data.Entities;
|
||||
using Seyounth.Hyosung.Data.Models;
|
||||
using Seyounth.Hyosung.ViewModels;
|
||||
using Seyounth.Hyosung.Views.Controls;
|
||||
|
||||
namespace Seyounth.Hyosung.Views.Pages;
|
||||
|
||||
public partial class VarietyPage : Page
|
||||
{
|
||||
public VarietyViewModel ViewModel { get; set; }
|
||||
|
||||
|
||||
public VarietyPage(VarietyViewModel viewModel)
|
||||
{
|
||||
ViewModel = viewModel;
|
||||
DataContext = this;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
|
||||
private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var blankVariety = new VarietyEntity()
|
||||
;
|
||||
// 将空白对象添加到数据源中
|
||||
ViewModel.Varieties.Add(blankVariety);
|
||||
// 滚动到新添加的行并使其进入编辑状态
|
||||
VarietyDataGrid.ScrollIntoView(blankVariety);
|
||||
var index = ViewModel.Varieties.IndexOf(blankVariety);
|
||||
VarietyDataGrid.SelectedIndex = index;
|
||||
VarietyDataGrid.BeginEdit();
|
||||
}
|
||||
}
|
5
Seyounth.Hyosung/appsettings.json
Normal file
5
Seyounth.Hyosung/appsettings.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "server=DESKTOP-AJ6K895;database=seyounth.hyosung;Trusted_Connection=SSPI;Encrypt=True;TrustServerCertificate=True;"
|
||||
}
|
||||
}
|
7
global.json
Normal file
7
global.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"sdk": {
|
||||
"version": "8.0.0",
|
||||
"rollForward": "latestMinor",
|
||||
"allowPrerelease": false
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user