commit 210572ce495e3dbb27dcae57e0844ccbb07f6806 Author: zhangzhuo Date: Wed Jun 4 09:42:48 2025 +0800 初始化 代码 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..add57be --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +bin/ +obj/ +/packages/ +riderModule.iml +/_ReSharper.Caches/ \ No newline at end of file diff --git a/.idea/.idea.Seyounth.Auto.Hs/.idea/.gitignore b/.idea/.idea.Seyounth.Auto.Hs/.idea/.gitignore new file mode 100644 index 0000000..268f65e --- /dev/null +++ b/.idea/.idea.Seyounth.Auto.Hs/.idea/.gitignore @@ -0,0 +1,13 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# Rider 忽略的文件 +/projectSettingsUpdater.xml +/.idea.Seyounth.Auto.Hs.iml +/modules.xml +/contentModel.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/.idea.Seyounth.Auto.Hs/.idea/encodings.xml b/.idea/.idea.Seyounth.Auto.Hs/.idea/encodings.xml new file mode 100644 index 0000000..df87cf9 --- /dev/null +++ b/.idea/.idea.Seyounth.Auto.Hs/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/.idea.Seyounth.Auto.Hs/.idea/indexLayout.xml b/.idea/.idea.Seyounth.Auto.Hs/.idea/indexLayout.xml new file mode 100644 index 0000000..7b08163 --- /dev/null +++ b/.idea/.idea.Seyounth.Auto.Hs/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Seyounth.Auto.Hs.Runtime/Balances/BalanceService.cs b/Seyounth.Auto.Hs.Runtime/Balances/BalanceService.cs new file mode 100644 index 0000000..b8cf1b7 --- /dev/null +++ b/Seyounth.Auto.Hs.Runtime/Balances/BalanceService.cs @@ -0,0 +1,67 @@ +using Microsoft.Extensions.Logging; + +namespace Seyounth.Auto.Hs.Runtime.Balances; + +public class BalanceService : IBalanceService +{ + public IReadOnlyList Balances => _balances; + + private readonly List _balances = new List(); + + private readonly ILogger _logger; + + + public BalanceService(ILogger logger) + { + _logger = logger; + //todo:向_balances里添加Balance + } + + public async Task StartAsync() + { + await Task.WhenAll(_balances.Select(balance => balance.ConnectAsync().ContinueWith(t => + { + if (t.IsCompletedSuccessfully) + _logger.LogInformation($"Balance {balance.Id} connected successfully."); + else + _logger.LogError($"Balance {balance.Id} failed to connect, error: {t.Exception?.Message}"); + })).ToArray()); + } + + public async Task StopAsync() + { + await Task.WhenAll(_balances.Select(balance => balance.DisconnectAsync().ContinueWith(t => + { + if (t.IsCompletedSuccessfully) + _logger.LogInformation($"Balance {balance.Id} disconnected successfully."); + else + _logger.LogError($"Balance {balance.Id} failed to disconnect, error: {t.Exception?.Message}"); + })).ToArray()); + } + + public async Task WeighAsync(int id) + { + decimal rs = 0; + var balance = _balances.FirstOrDefault(b => b.Id == id); + if (balance != null) + { + Func weightChangedHandler = (weight) => + { + rs = weight; + return Task.CompletedTask; + }; + + balance.OnWeightChanged += weightChangedHandler; + while (rs == 0) + { + await Task.Delay(100); + } + + balance.OnWeightChanged -= weightChangedHandler; + return rs; + } + + _logger.LogError($"Balance {id} not found."); + return null; + } +} \ No newline at end of file diff --git a/Seyounth.Auto.Hs.Runtime/Balances/IBalance.cs b/Seyounth.Auto.Hs.Runtime/Balances/IBalance.cs new file mode 100644 index 0000000..379fe19 --- /dev/null +++ b/Seyounth.Auto.Hs.Runtime/Balances/IBalance.cs @@ -0,0 +1,12 @@ +namespace Seyounth.Auto.Hs.Runtime.Balances; + +public interface IBalance +{ + int Id { get; } + + Task ConnectAsync(); + + Task DisconnectAsync(); + + event Func OnWeightChanged; +} \ No newline at end of file diff --git a/Seyounth.Auto.Hs.Runtime/Balances/IBalanceService.cs b/Seyounth.Auto.Hs.Runtime/Balances/IBalanceService.cs new file mode 100644 index 0000000..4da7399 --- /dev/null +++ b/Seyounth.Auto.Hs.Runtime/Balances/IBalanceService.cs @@ -0,0 +1,17 @@ +namespace Seyounth.Auto.Hs.Runtime.Balances; + +public interface IBalanceService +{ + IReadOnlyList Balances { get; } + + Task StartAsync(); + + Task StopAsync(); + + /// + /// 使用指定的电子称称重 + /// + /// + /// + Task WeighAsync(int id); +} \ No newline at end of file diff --git a/Seyounth.Auto.Hs.Runtime/Handlers/OnWarningHandler.cs b/Seyounth.Auto.Hs.Runtime/Handlers/OnWarningHandler.cs new file mode 100644 index 0000000..ff267de --- /dev/null +++ b/Seyounth.Auto.Hs.Runtime/Handlers/OnWarningHandler.cs @@ -0,0 +1,15 @@ +using MediatR; + +namespace Seyounth.Auto.Hs.Runtime.Handlers; + +public class OnWarning(int first, int second) : IRequest +{ + public int First { get; } = first; + + public int Second { get; } = second; +} + +public abstract class OnWarningHandler : IRequestHandler +{ + public abstract Task Handle(OnWarning request, CancellationToken cancellationToken); +} \ No newline at end of file diff --git a/Seyounth.Auto.Hs.Runtime/Handlers/WeighBoxRequestHandler.cs b/Seyounth.Auto.Hs.Runtime/Handlers/WeighBoxRequestHandler.cs new file mode 100644 index 0000000..e534611 --- /dev/null +++ b/Seyounth.Auto.Hs.Runtime/Handlers/WeighBoxRequestHandler.cs @@ -0,0 +1,21 @@ +using MediatR; + +namespace Seyounth.Auto.Hs.Runtime.Handlers; + +public class WeighBoxRequest : IRequest +{ + public string Barcode { get; } + + public decimal? Weight { get; } + + public WeighBoxRequest(string barcode, decimal? weight) + { + Barcode = barcode; + Weight = weight; + } +} + +public abstract class WeighBoxRequestHandler : IRequestHandler +{ + public abstract Task Handle(WeighBoxRequest request, CancellationToken cancellationToken); +} \ No newline at end of file diff --git a/Seyounth.Auto.Hs.Runtime/Handlers/WeighSpindleRequestHandler.cs b/Seyounth.Auto.Hs.Runtime/Handlers/WeighSpindleRequestHandler.cs new file mode 100644 index 0000000..8091545 --- /dev/null +++ b/Seyounth.Auto.Hs.Runtime/Handlers/WeighSpindleRequestHandler.cs @@ -0,0 +1,20 @@ +using MediatR; + +namespace Seyounth.Auto.Hs.Runtime.Handlers; + +public class WeighSpindleRequest : IRequest +{ + public decimal? Weight { get; } + public string Barcode { get; } + + public WeighSpindleRequest(string barcode, decimal? weight) + { + Weight = weight; + Barcode = barcode; + } +} + +public abstract class WeighSpindleRequestHandler : IRequestHandler +{ + public abstract Task Handle(WeighSpindleRequest request, CancellationToken cancellationToken); +} \ No newline at end of file diff --git a/Seyounth.Auto.Hs.Runtime/HsAutoRuntime.cs b/Seyounth.Auto.Hs.Runtime/HsAutoRuntime.cs new file mode 100644 index 0000000..bf99cd3 --- /dev/null +++ b/Seyounth.Auto.Hs.Runtime/HsAutoRuntime.cs @@ -0,0 +1,174 @@ +using MediatR; +using Microsoft.Extensions.Logging; +using Seyounth.Auto.Hs.Runtime.Balances; +using Seyounth.Auto.Hs.Runtime.Handlers; +using Seyounth.Auto.Hs.Runtime.Plc; +using Seyounth.Auto.Hs.Runtime.Printer; +using Seyounth.Auto.Hs.Runtime.Scanner; + +namespace Seyounth.Auto.Hs.Runtime; + +public class HsAutoRuntime : IHsAutoRuntime +{ + private readonly IMediator _mediator; + private readonly IBalanceService _balance; + private readonly IScannerService _scanners; + private readonly ILogger _logger; + private readonly IPlcService _plcService; + private readonly IPrinterService _printers; + + public HsAutoRuntime(IPlcService plcService, IMediator mediator, IBalanceService balances, IScannerService scanners, + ILogger logger, IPrinterService printers) + { + _printers = printers; + _mediator = mediator; + _balance = balances; + _scanners = scanners; + _logger = logger; + _plcService = plcService; + _scanners.OnScanned += ScannersOnOnScanned; + plcService.OnWarning += PlcServiceOnOnWarning; + } + + /// + /// 获取到报警信息处理逻辑 + /// + /// + /// + /// + private Task PlcServiceOnOnWarning(Tuple warning) + { + throw new NotImplementedException(); + } + + private void ScannersOnOnScanned(IScanner scanner, string barcode) + { + if (scanner.Id == 1) + { +#pragma warning disable CS4014 // 由于此调用不会等待,因此在调用完成前将继续执行当前方法 + HandleFilmOnScanned(barcode); +#pragma warning restore CS4014 // 由于此调用不会等待,因此在调用完成前将继续执行当前方法 + } + else if (scanner.Id == 2) + { +#pragma warning disable CS4014 // 由于此调用不会等待,因此在调用完成前将继续执行当前方法 + HandleBoxOnScanned(barcode); +#pragma warning restore CS4014 // 由于此调用不会等待,因此在调用完成前将继续执行当前方法 + } + } + + private async Task HandleFilmOnScanned(string barcode) + { + try + { + _logger.LogInformation("Film Scanner: {barcode}", barcode); + var weight = await _balance.WeighAsync(1); + _logger.LogInformation($"Film Barcode:{barcode}| Weight: {weight}"); + var content = await _mediator.Send(new WeighSpindleRequest(barcode, weight)); + _logger.LogInformation($"Film Barcode:{barcode}| print content: {content}"); + await _printers.PrintAsync(1, content); + await _plcService.WriteFilmLabelPrintResult(1); + } + catch (Exception ex) + { + _logger.LogError($"Film Scanner: {barcode}| Exception: {ex.Message}"); + await _plcService.WriteFilmLabelPrintResult(2); + } + } + + private async Task HandleBoxOnScanned(string barcode) + { + try + { + _logger.LogInformation("Box Scanner: {barcode}", barcode); + int jackingFlag; + do + { + jackingFlag = await _plcService.GetJackingFlagAsync(); + } while (jackingFlag == 0); + + _logger.LogInformation($"Box Barcode:{barcode}| Jacking flag: {jackingFlag}"); + var weight = await _balance.WeighAsync(2); + _logger.LogInformation($"Box Barcode:{barcode}| Weight: {weight}"); + var content = await _mediator.Send(new WeighBoxRequest(barcode, weight)); + _logger.LogInformation($"Box Barcode:{barcode}| WeighBoxResult: {content}"); + await _printers.PrintAsync(2, content); + await _plcService.WriteBoxLabelPrintResult(1); + } + catch (Exception ex) + { + _logger.LogError(ex, "Box Scanner: {barcode}", barcode); + await _plcService.WriteBoxLabelPrintResult(2); + } + } + + public Task RunAsync() + { + var tasks = new List + { + _balance.StartAsync() + .ContinueWith(t => + { + _logger.LogInformation(t.IsCompletedSuccessfully + ? "Balance connected successfully." + : $"Balance connection failed. error: {t.Exception?.Message}"); + }), + _scanners.StartAsync() + .ContinueWith(t => + { + _logger.LogInformation(t.IsCompletedSuccessfully + ? "Scanner connected successfully." + : $"Scanner connection failed. error: {t.Exception?.Message}"); + }), + _plcService.StartAsync() + .ContinueWith(t => + { + _logger.LogInformation(t.IsCompletedSuccessfully + ? "Plc connected successfully." + : $"Plc connection failed. error: {t.Exception?.Message}"); + }), + _printers.StartAsync().ContinueWith(t => + { + _logger.LogInformation(t.IsCompletedSuccessfully + ? "Printer connected successfully." + : $"Printer connection failed. error: {t.Exception?.Message}"); + }) + }; + return Task.WhenAll(tasks); + } + + public Task StopAsync() + { + var tasks = new List + { + _balance.StopAsync() + .ContinueWith(t => + { + _logger.LogInformation(t.IsCompletedSuccessfully + ? "Balance stop successfully." + : $"Balance stop failed. error: {t.Exception?.Message}"); + }), + _scanners.StopAsync() + .ContinueWith(t => + { + _logger.LogInformation(t.IsCompletedSuccessfully + ? "Scanner stop successfully." + : $"Scanner stop failed. error: {t.Exception?.Message}"); + }), + _plcService.StopAsync() + .ContinueWith(t => + { + _logger.LogInformation(t.IsCompletedSuccessfully + ? "Plc stop successfully." + : $"Plc stop failed. error: {t.Exception?.Message}"); + }), + _printers.StopAsync().ContinueWith(t => + { + _logger.LogInformation(t.IsCompletedSuccessfully + ? "Printer stop successfully." + : $"Printer stop failed. error: {t.Exception?.Message}"); + }) + }; + return Task.WhenAll(tasks); + } +} \ No newline at end of file diff --git a/Seyounth.Auto.Hs.Runtime/HsBackgroundService.cs b/Seyounth.Auto.Hs.Runtime/HsBackgroundService.cs new file mode 100644 index 0000000..554662f --- /dev/null +++ b/Seyounth.Auto.Hs.Runtime/HsBackgroundService.cs @@ -0,0 +1,26 @@ +using Microsoft.Extensions.Hosting; + +namespace Seyounth.Auto.Hs.Runtime; + +public class HsBackgroundService(IHsAutoRuntime hs) : BackgroundService +{ + public override async Task StartAsync(CancellationToken cancellationToken) + { + await hs.RunAsync(); + await base.StartAsync(cancellationToken); + } + + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + while (!stoppingToken.IsCancellationRequested) + { + await Task.Delay(1000, stoppingToken); + } + } + + public override async Task StopAsync(CancellationToken cancellationToken) + { + await hs.StopAsync(); + await base.StopAsync(cancellationToken); + } +} \ No newline at end of file diff --git a/Seyounth.Auto.Hs.Runtime/HsExtensions.cs b/Seyounth.Auto.Hs.Runtime/HsExtensions.cs new file mode 100644 index 0000000..2136d10 --- /dev/null +++ b/Seyounth.Auto.Hs.Runtime/HsExtensions.cs @@ -0,0 +1,35 @@ +using Microsoft.Extensions.DependencyInjection; +using Seyounth.Auto.Hs.Runtime.Balances; +using Seyounth.Auto.Hs.Runtime.Handlers; +using Seyounth.Auto.Hs.Runtime.Plc; +using Seyounth.Auto.Hs.Runtime.Printer; +using Seyounth.Auto.Hs.Runtime.Scanner; + +namespace Seyounth.Auto.Hs.Runtime; + +public static class HsExtensions +{ + /// + /// 添加HS手动包装服务 + /// + /// + /// 报警信息处理器 + /// 纸箱称重处理器 + /// 丝锭称重处理器 + /// + public static IServiceCollection AddHs( + this IServiceCollection services) + where TOnWarningHandler : OnWarningHandler + where TWeighBoxRequestHandler : WeighSpindleRequestHandler + where TWeighSpindleRequestHandler : WeighSpindleRequestHandler + { + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddHostedService(); + services.AddHostedService(); + return services; + } +} \ No newline at end of file diff --git a/Seyounth.Auto.Hs.Runtime/IHsAutoRuntime.cs b/Seyounth.Auto.Hs.Runtime/IHsAutoRuntime.cs new file mode 100644 index 0000000..2d441de --- /dev/null +++ b/Seyounth.Auto.Hs.Runtime/IHsAutoRuntime.cs @@ -0,0 +1,8 @@ +namespace Seyounth.Auto.Hs.Runtime; + +public interface IHsAutoRuntime +{ + Task RunAsync(); + + Task StopAsync(); +} \ No newline at end of file diff --git a/Seyounth.Auto.Hs.Runtime/Plc/HsPlcAddressAbstract.cs b/Seyounth.Auto.Hs.Runtime/Plc/HsPlcAddressAbstract.cs new file mode 100644 index 0000000..1f7d557 --- /dev/null +++ b/Seyounth.Auto.Hs.Runtime/Plc/HsPlcAddressAbstract.cs @@ -0,0 +1,8 @@ +namespace Seyounth.Auto.Hs.Runtime.Plc; + +public abstract class HsPlcAddressAbstract +{ + public abstract string 热缩机当前温度 { get; } + + +} \ No newline at end of file diff --git a/Seyounth.Auto.Hs.Runtime/Plc/IPlcService.cs b/Seyounth.Auto.Hs.Runtime/Plc/IPlcService.cs new file mode 100644 index 0000000..ec18197 --- /dev/null +++ b/Seyounth.Auto.Hs.Runtime/Plc/IPlcService.cs @@ -0,0 +1,46 @@ +namespace Seyounth.Auto.Hs.Runtime.Plc; + +public interface IPlcService +{ + Task StartAsync(); + Task StopAsync(); + + /// + /// 查询热缩机当前温度 + /// + /// + Task GetTemperatureAsync(); + + + /// + /// 查询报警信息 + /// + /// + Task QueryWarningInfo(); + + /// + /// 触发报警信息 + /// + event Func, Task> OnWarning; + + /// + /// 获取顶升机构状态 + /// + /// + Task GetJackingFlagAsync(); + + /// + /// 写入外箱标签打印结果 + /// + /// + /// + Task WriteBoxLabelPrintResult(short rs); + + + /// + /// 写入外膜标签打印结果 + /// + /// + /// + Task WriteFilmLabelPrintResult(short rs); +} \ No newline at end of file diff --git a/Seyounth.Auto.Hs.Runtime/Plc/PlcBackgroundService.cs b/Seyounth.Auto.Hs.Runtime/Plc/PlcBackgroundService.cs new file mode 100644 index 0000000..4ceb11d --- /dev/null +++ b/Seyounth.Auto.Hs.Runtime/Plc/PlcBackgroundService.cs @@ -0,0 +1,15 @@ +using Microsoft.Extensions.Hosting; + +namespace Seyounth.Auto.Hs.Runtime.Plc; + +public class PlcBackgroundService(IPlcService plc) : BackgroundService +{ + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + while (!stoppingToken.IsCancellationRequested) + { + await plc.QueryWarningInfo(); + await Task.Delay(50, stoppingToken); + } + } +} \ No newline at end of file diff --git a/Seyounth.Auto.Hs.Runtime/Plc/PlcService.cs b/Seyounth.Auto.Hs.Runtime/Plc/PlcService.cs new file mode 100644 index 0000000..bcf6044 --- /dev/null +++ b/Seyounth.Auto.Hs.Runtime/Plc/PlcService.cs @@ -0,0 +1,56 @@ +using Microsoft.Extensions.Logging; +using Seyounth.Extensions.Plc; + +namespace Seyounth.Auto.Hs.Runtime.Plc; + +public class PlcService : IPlcService +{ + private readonly ILogger _logger; + + private readonly IPlc _plc; + + public PlcService(ILogger logger) + { + _logger = logger; + //todo:此处创建PLC对象 + } + + public async Task StartAsync() + { + await _plc.ConnectAsync(); + } + + public async Task StopAsync() + { + await _plc.DisconnectAsync(); + } + + public async Task GetTemperatureAsync() + { + return (await _plc.ReadAsync("D1000", 1))[0]; + } + + public async Task QueryWarningInfo() + { + var flags = await _plc.ReadAsync("D1003", 2); + if (flags.Any(f => f != 0)) + OnWarning?.Invoke(Tuple.Create(flags[0], flags[1])); + } + + public event Func, Task> OnWarning; + + public Task GetJackingFlagAsync() + { + throw new NotImplementedException(); + } + + public Task WriteBoxLabelPrintResult(short rs) + { + throw new NotImplementedException(); + } + + public Task WriteFilmLabelPrintResult(short rs) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/Seyounth.Auto.Hs.Runtime/Printer/IPrinter.cs b/Seyounth.Auto.Hs.Runtime/Printer/IPrinter.cs new file mode 100644 index 0000000..1daecdb --- /dev/null +++ b/Seyounth.Auto.Hs.Runtime/Printer/IPrinter.cs @@ -0,0 +1,10 @@ +namespace Seyounth.Auto.Hs.Runtime.Printer; + +public interface IPrinter +{ + int Id { get; } + Task ConnectAsync(); + Task DisconnectAsync(); + + Task PrintAsync(string content); +} \ No newline at end of file diff --git a/Seyounth.Auto.Hs.Runtime/Printer/IPrinterService.cs b/Seyounth.Auto.Hs.Runtime/Printer/IPrinterService.cs new file mode 100644 index 0000000..4d9ad35 --- /dev/null +++ b/Seyounth.Auto.Hs.Runtime/Printer/IPrinterService.cs @@ -0,0 +1,12 @@ +namespace Seyounth.Auto.Hs.Runtime.Printer; + +public interface IPrinterService +{ + IReadOnlyList Printers { get; } + + Task StartAsync(); + + Task StopAsync(); + + Task PrintAsync(int id, string content); +} \ No newline at end of file diff --git a/Seyounth.Auto.Hs.Runtime/Printer/PrinterService.cs b/Seyounth.Auto.Hs.Runtime/Printer/PrinterService.cs new file mode 100644 index 0000000..a046866 --- /dev/null +++ b/Seyounth.Auto.Hs.Runtime/Printer/PrinterService.cs @@ -0,0 +1,50 @@ +using Microsoft.Extensions.Logging; + +namespace Seyounth.Auto.Hs.Runtime.Printer; + +public class PrinterService : IPrinterService +{ + public IReadOnlyList Printers => _printers; + + private readonly ILogger _logger; + + private readonly List _printers = new List(); + + public PrinterService(ILogger logger) + { + _logger = logger; + //todo: load printers from configuration or new + } + + public async Task StartAsync() + { + await Task.WhenAll(Printers.Select(x => x.ConnectAsync() + .ContinueWith(t => + { + if (t.IsCompletedSuccessfully) + _logger.LogInformation($"Printer {x.Id} connected"); + else + _logger.LogError(t.Exception, $"Printer {x.Id} failed to connect,error: {t.Exception.Message}"); + }))); + } + + public async Task StopAsync() + { + await Task.WhenAll(Printers.Select(x => x.DisconnectAsync() + .ContinueWith(t => + { + if (t.IsCompletedSuccessfully) + _logger.LogInformation($"Printer {x.Id} disconnected"); + else + _logger.LogError(t.Exception, $"Printer {x.Id} failed to disconnect,error: {t.Exception.Message}"); + }))); + } + + public Task PrintAsync(int id, string content) + { + var printer = Printers.FirstOrDefault(x => x.Id == id); + if (printer == null) + throw new ArgumentException("Printer not found", nameof(id)); + return printer.PrintAsync(content); + } +} \ No newline at end of file diff --git a/Seyounth.Auto.Hs.Runtime/Scanner/IScanner.cs b/Seyounth.Auto.Hs.Runtime/Scanner/IScanner.cs new file mode 100644 index 0000000..a5f1c18 --- /dev/null +++ b/Seyounth.Auto.Hs.Runtime/Scanner/IScanner.cs @@ -0,0 +1,12 @@ +namespace Seyounth.Auto.Hs.Runtime.Scanner; + +public interface IScanner +{ + int Id { get; } + + Task ConnectAsync(); + + Task DisconnectAsync(); + + event Action OnScanned; +} \ No newline at end of file diff --git a/Seyounth.Auto.Hs.Runtime/Scanner/IScannerService.cs b/Seyounth.Auto.Hs.Runtime/Scanner/IScannerService.cs new file mode 100644 index 0000000..9e69e39 --- /dev/null +++ b/Seyounth.Auto.Hs.Runtime/Scanner/IScannerService.cs @@ -0,0 +1,11 @@ +namespace Seyounth.Auto.Hs.Runtime.Scanner; + +public interface IScannerService +{ + IReadOnlyList Scanners { get; } + Task StartAsync(); + + Task StopAsync(); + + event Action OnScanned; +} \ No newline at end of file diff --git a/Seyounth.Auto.Hs.Runtime/Scanner/ScannerService.cs b/Seyounth.Auto.Hs.Runtime/Scanner/ScannerService.cs new file mode 100644 index 0000000..f95814a --- /dev/null +++ b/Seyounth.Auto.Hs.Runtime/Scanner/ScannerService.cs @@ -0,0 +1,46 @@ +using Microsoft.Extensions.Logging; + +namespace Seyounth.Auto.Hs.Runtime.Scanner; + +public class ScannerService : IScannerService +{ + public ScannerService(ILogger logger) + { + _logger = logger; + //todo:向_scanners里添加HikScanner + + _scanners.ForEach(x => x.OnScanned += (barcode) => OnScanned?.Invoke(x, barcode)); + } + + public IReadOnlyList Scanners => _scanners; + + private readonly ILogger _logger; + + private readonly List _scanners = new List(); + + public async Task StartAsync() + { + await Task.WhenAll(_scanners.Select(x => x.ConnectAsync() + .ContinueWith(t => + { + if (t.IsCompletedSuccessfully) + _logger.LogInformation($"Scanner {x.Id} connected successfully."); + else + _logger.LogError($"Scanner {x.Id} failed to connect, error: {t.Exception?.Message}"); + }))); + } + + public async Task StopAsync() + { + await Task.WhenAll(_scanners.Select(x => x.DisconnectAsync() + .ContinueWith(t => + { + if (t.IsCompletedSuccessfully) + _logger.LogInformation($"Scanner {x.Id} disconnected."); + else + _logger.LogError($"Scanner {x.Id} failed to disconnect, error: {t.Exception?.Message}"); + }))); + } + + public event Action? OnScanned; +} \ No newline at end of file diff --git a/Seyounth.Auto.Hs.Runtime/Seyounth.Auto.Hs.Runtime.csproj b/Seyounth.Auto.Hs.Runtime/Seyounth.Auto.Hs.Runtime.csproj new file mode 100644 index 0000000..7a4dfd8 --- /dev/null +++ b/Seyounth.Auto.Hs.Runtime/Seyounth.Auto.Hs.Runtime.csproj @@ -0,0 +1,15 @@ + + + + net8.0 + enable + enable + + + + + + + + + diff --git a/Seyounth.Auto.Hs.sln b/Seyounth.Auto.Hs.sln new file mode 100644 index 0000000..eea76c4 --- /dev/null +++ b/Seyounth.Auto.Hs.sln @@ -0,0 +1,16 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Seyounth.Auto.Hs.Runtime", "Seyounth.Auto.Hs.Runtime\Seyounth.Auto.Hs.Runtime.csproj", "{6966BCFD-A22C-4C83-8171-96BB005F38D4}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6966BCFD-A22C-4C83-8171-96BB005F38D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6966BCFD-A22C-4C83-8171-96BB005F38D4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6966BCFD-A22C-4C83-8171-96BB005F38D4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6966BCFD-A22C-4C83-8171-96BB005F38D4}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/nuget.config b/nuget.config new file mode 100644 index 0000000..205006e --- /dev/null +++ b/nuget.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file