204 lines
7.6 KiB
C#
Raw Normal View History

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace Seyounth.Auto.Hs.Runtime.Balances
{
public class SilkBalance : IBalance
{
public int Id => 1;
//扫到码后的业务逻辑
//扫到码后的业务逻辑
private readonly static object _lock = new object();
private List<decimal> _weights = new List<decimal>();
public event Action<string> OnScanned;
private DeviceConnectConfig DeviceConnectConfig;
private TcpClient _tcp;
private NetworkStream _stream;
private readonly IServiceProvider serviceProvider;
private readonly IEnumerable<IBalanceEventHandle> balanceEventHandles;
private readonly ILogger<SilkBalance> logger;
private CancellationTokenSource _receiveDataCancellationToken;
private bool tag;
public SilkBalance(IConfiguration configuration, IServiceProvider serviceProvider, IEnumerable<IBalanceEventHandle> balanceEventHandles, ILogger<SilkBalance> logger)
{
/*
* IP/
*/
var configs = configuration.GetSection("Balance").Get<DeviceConnectConfig[]>();
if (configs is not null && configs.Length > 0)
{
DeviceConnectConfig = configs.FirstOrDefault(e => e.Id == Id);
}
this.serviceProvider = serviceProvider;
this.balanceEventHandles = balanceEventHandles;
this.logger = logger;
}
public event Func<decimal, Task> OnWeightChanged;
/// <summary>
/// 连接体重秤
/// </summary>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
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, "体重秤连接失败");
}
}
}
/// <summary>
/// 接收扫码枪数据
/// </summary>
/// <returns></returns>
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);
/* 异步执行所有事件避免事件中报错未能执行完成所有事件而阻塞下次接收 */
var matchs = Regex.Match(result, "-?\\d+(.?\\d+)?");
var weight = 0m;
if (!string.IsNullOrWhiteSpace(matchs.Value))
weight = Convert.ToDecimal(matchs.Value);
;
//logger.LogInformation("YYYYYYYYYYYYYYYYYYYY");
//1.刚开机,重量为 0
if (weight <= 0)
{
tag = true;
continue;
}
;
if (MonitorWeightStability(_weights, weight))
{
if (tag)
{
//logger.LogInformation($"丝锭称接收数据:{result},字节数:{readCount}");
using (var scope = serviceProvider.CreateAsyncScope())
{
var handles = scope.ServiceProvider.GetService<IEnumerable<IBalanceEventHandle>>();
foreach (var item in handles)
{
await item.ExecAsync(weight, Id);
}
}
tag = false;
}
}
}
}
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, "体重秤连接失败");
}
}
/// <summary>
/// 断开连接
/// </summary>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public Task DisconnectAsync()
{
_receiveDataCancellationToken?.Cancel();
_tcp?.Dispose();
return Task.CompletedTask;
}
/// <summary>
/// 由于物体刚上称时重量浮动的原因体重称上传10次的重量一样视为稳定
/// </summary>
/// <param name="weightList"></param>
/// <param name="weight"></param>
/// <returns></returns>
public bool MonitorWeightStability(List<decimal> weightList, decimal weight)
{
//由于电子秤上传重量频率较高故加锁保证
lock (_lock)
{
weightList.Add(weight);
if (weightList.Count > 10)
{
for (int i = weightList.Count - 1; i > 9; i--)
weightList.RemoveAt(i);
}
if (weightList.Count == 10)
{
var result = weightList.Distinct().Count() == 1;
weightList.Clear();
return result;
}
return false;
}
}
}
}