diff --git a/share/Seyounth.Auto.Hs.Runtime/Scanner/BoxScanner.cs b/share/Seyounth.Auto.Hs.Runtime/Scanner/BoxScanner.cs
new file mode 100644
index 0000000..ebb6055
--- /dev/null
+++ b/share/Seyounth.Auto.Hs.Runtime/Scanner/BoxScanner.cs
@@ -0,0 +1,119 @@
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Logging;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Sockets;
+using System.Net;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Seyounth.Auto.Hs.Runtime.Scanner
+{
+
+ ///
+ /// 料箱扫码枪
+ ///
+ public class BoxScanner : IScanner
+ {
+ public int Id => 2;
+
+
+ //扫到码后的业务逻辑
+ public event Action OnScanned;
+ private DeviceConnectConfig DeviceConnectConfig;
+ private TcpClient _tcp;
+ //字节流、可以理解为后端与扫码枪之间的一条管道,扫码枪的数据就是通过这条管道发送给我们的
+ private NetworkStream _stream;
+ private readonly ILogger logger;
+ private CancellationTokenSource _receiveDataCancellationToken;
+
+ public BoxScanner(IConfiguration configuration, 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.logger = logger;
+ }
+
+ ///
+ /// 连接扫码枪
+ ///
+ ///
+ public async Task ConnectAsync()
+ {
+ 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))
+ .ContinueWith((task, obj) =>
+ {
+ if (task.IsCompletedSuccessfully)
+ {
+ if (_stream is not null)
+ _stream.Dispose();
+ _stream = _tcp.GetStream();
+ logger.LogInformation("箱扫码枪连接成功,开始接收数据");
+ _receiveDataCancellationToken = new CancellationTokenSource();
+ Task.Factory.StartNew(() => ReceiveData(_receiveDataCancellationToken.Token), _receiveDataCancellationToken.Token);
+ }
+ }, null);
+ }
+ catch (Exception ex)
+ {
+ logger.LogError(ex, "箱扫码枪连接失败");
+ }
+ }
+
+ ///
+ /// 接收扫码枪数据
+ ///
+ ///
+ private void ReceiveData(CancellationToken cancellationToken)
+ {
+ while (!cancellationToken.IsCancellationRequested)
+ {
+ //一次最大读取1M
+ byte[] buffer = new byte[1024];
+ /* readCount :实际读取字节数*/
+ var readCount = _stream.Read(buffer, 0, buffer.Length);
+ /* UTF-8 编码获取字符串*/
+ var result = Encoding.UTF8.GetString(buffer, 0, readCount);
+ logger.LogInformation($"箱扫码枪接收数据:{result},字节数:{readCount}");
+ /* 异步执行所有事件避免事件中报错未能执行完成所有事件而阻塞下次接收 */
+ Task.Run(() => OnScanned?.Invoke(result));
+ }
+ }
+
+ ///
+ /// 断开连接
+ ///
+ ///
+ public Task DisconnectAsync()
+ {
+ _receiveDataCancellationToken.Cancel();
+ _tcp?.Dispose();
+ return Task.CompletedTask;
+ }
+ }
+}
diff --git a/share/Seyounth.Auto.Hs.Runtime/Scanner/YarnScanner.cs b/share/Seyounth.Auto.Hs.Runtime/Scanner/YarnScanner.cs
new file mode 100644
index 0000000..ef64670
--- /dev/null
+++ b/share/Seyounth.Auto.Hs.Runtime/Scanner/YarnScanner.cs
@@ -0,0 +1,128 @@
+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 ILogger logger;
+ private CancellationTokenSource _receiveDataCancellationToken;
+
+ public YarnScanner(IConfiguration configuration,ILogger logger)
+ {
+ /*
+ * 从配置文件获取扫码枪IP/端口
+ */
+ var configs = configuration.GetSection("Scanner").Get();
+ if (configs is not null && configs.Length > 0)
+ {
+ DeviceConnectConfig = configs.FirstOrDefault(e => e.Id == Id);
+ }
+
+ OnScanned += 每次扫到码后的业务逻辑;
+ this.logger = logger;
+ }
+
+ ///
+ /// 连接扫码枪
+ ///
+ ///
+ public async Task ConnectAsync()
+ {
+ 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))
+ .ContinueWith((task,obj) =>
+ {
+ if (task.IsCompletedSuccessfully)
+ {
+ if(_stream is not null)
+ _stream.Dispose();
+ _stream = _tcp.GetStream();
+ logger.LogInformation("人工扫码枪连接成功,开始接收数据");
+ _receiveDataCancellationToken = new CancellationTokenSource();
+ Task.Factory.StartNew(() => ReceiveData(_receiveDataCancellationToken.Token), _receiveDataCancellationToken.Token);
+ }
+ },null);
+ }
+ catch (Exception ex)
+ {
+ logger.LogError(ex, "人工扫纱扫码枪连接失败");
+ }
+ }
+
+ ///
+ /// 接收扫码枪数据
+ ///
+ ///
+ private void ReceiveData(CancellationToken cancellationToken)
+ {
+ while (!cancellationToken.IsCancellationRequested)
+ {
+ //一次最大读取1M
+ byte[] buffer = new byte[1024];
+ /* readCount :实际读取字节数*/
+ var readCount = _stream.Read(buffer,0,buffer.Length);
+ /* UTF-8 编码获取字符串*/
+ var result = Encoding.UTF8.GetString(buffer,0,readCount);
+ logger.LogInformation($"人工扫纱扫码枪接收数据:{result},字节数:{readCount}");
+ /* 异步执行所有事件避免事件中报错未能执行完成所有事件而阻塞下次接收 */
+ Task.Run(() => OnScanned?.Invoke(result));
+ }
+ }
+
+
+ ///
+ /// 把人工扫码的逻辑写这里,在这里将码返回给前端
+ ///
+ ///
+ private void 每次扫到码后的业务逻辑(string code)
+ {
+
+ }
+
+ ///
+ /// 断开连接
+ ///
+ ///
+ public Task DisconnectAsync()
+ {
+ _receiveDataCancellationToken.Cancel();
+ _tcp?.Dispose();
+ return Task.CompletedTask;
+ }
+ }
+}