using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; namespace Seyounth.Auto.Hs.Runtime.Scanner { /// /// 人工扫纱扫码枪 /// public class YarnScanner : IScanner { public int Id => 1; //扫到码后的业务逻辑 public event Action OnScanned; private DeviceConnectConfig DeviceConnectConfig; private TcpClient _tcp; private NetworkStream _stream; private readonly IEnumerable scannerEventHandles; private readonly ILogger logger; private CancellationTokenSource _receiveDataCancellationToken; public YarnScanner(IConfiguration configuration, IEnumerable scannerEventHandles, ILogger logger) { /* * 从配置文件获取扫码枪IP/端口 */ var configs = configuration.GetSection("Scanner").Get(); if (configs is not null && configs.Length > 0) { DeviceConnectConfig = configs.FirstOrDefault(e => e.Id == Id); } this.scannerEventHandles = scannerEventHandles; this.logger = logger; } /// /// 连接扫码枪 /// /// public async Task ConnectAsync() { while (true) { if (_tcp is not null) { try { _tcp.Dispose(); } catch (Exception ex) { /* * 忽略释放异常 */ } } _tcp = new TcpClient(); try { await _tcp.ConnectAsync(new IPEndPoint(IPAddress.Parse(DeviceConnectConfig.IP), DeviceConnectConfig.Port)); if (_stream is not null) _stream.Dispose(); _stream = _tcp.GetStream(); logger.LogInformation("人工扫码枪连接成功,开始接收数据"); _receiveDataCancellationToken?.Cancel(); _receiveDataCancellationToken = new CancellationTokenSource(); ReceiveData(_receiveDataCancellationToken.Token); break; } catch (Exception ex) when (ex.GetBaseException() is OperationCanceledException oce || ex.GetBaseException() is SocketException socketException) { await Task.Delay(1000 * 5); logger.LogError(ex.GetBaseException(), "人工扫码枪连接失败,尝试重连中"); continue; } catch (Exception ex) { logger.LogError(ex, "人工扫码枪连接失败"); } } } /// /// 接收扫码枪数据 /// /// private async Task ReceiveData(CancellationToken cancellationToken) { try { while (!cancellationToken.IsCancellationRequested) { //一次最大读取1M byte[] buffer = new byte[1024]; /* readCount :实际读取字节数*/ var readCount = _stream.Read(buffer, 0, buffer.Length); if (readCount == 0) throw new SocketException(); /* UTF-8 编码获取字符串*/ var result = Encoding.UTF8.GetString(buffer, 0, readCount); if (string.IsNullOrWhiteSpace(result)) continue; logger.LogInformation($"人工扫纱扫码枪接收数据:{result},字节数:{readCount}"); /* 异步执行所有事件避免事件中报错未能执行完成所有事件而阻塞下次接收 */ foreach (var item in scannerEventHandles) { await item.ExecAsync(result, Id); } } } catch (Exception ex) when (ex.GetBaseException() is OperationCanceledException oce || ex.GetBaseException() is SocketException socketException) { logger.LogError(ex.GetBaseException(), "人工扫码枪连接失败,尝试重连中"); await ConnectAsync(); } catch (Exception ex) { logger.LogError(ex, "人工扫码枪连接失败"); } } /// /// 断开连接 /// /// public Task DisconnectAsync() { _receiveDataCancellationToken?.Cancel(); _tcp?.Dispose(); return Task.CompletedTask; } } }