297 lines
9.5 KiB
C#
Raw Normal View History

2025-11-20 14:44:46 +08:00
using Microsoft.Extensions.Logging;
using RIZO.Model.Mes.Scanner;
using RIZO.Service.Mes.IMesService.Scanner;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RIZO.Service.Mes.Scanner
{
public class ScannerService : IScannerService, IDisposable
{
private readonly ILogger<ScannerService> _logger;
private SerialPort? _serialPort;
private ScannerConfig _config = new();
private bool _isInitialized = false;
public bool IsConnected => _serialPort?.IsOpen == true;
// 事件定义
public event EventHandler<ScanData>? OnScanDataReceived;
public event EventHandler<string>? OnScannerError;
public ScannerService(ILogger<ScannerService> logger)
{
_logger = logger;
}
public async Task<bool> InitializeAsync(ScannerConfig config)
{
try
{
_config = config;
await Task.Run(() =>
{
_serialPort = new SerialPort(
_config.PortName,
_config.BaudRate,
ParseParity(_config.Parity),
_config.DataBits,
ParseStopBits(_config.StopBits))
{
Encoding = System.Text.Encoding.UTF8,
ReadTimeout = 1000,
WriteTimeout = 1000
};
_serialPort.DataReceived += SerialPort_DataReceived;
});
_isInitialized = true;
_logger.LogInformation($"扫码服务初始化成功 - 端口:{_config.PortName} 波特率:{_config.BaudRate}");
return true;
}
catch (Exception ex)
{
_logger.LogError(ex, "扫码服务初始化失败");
OnScannerError?.Invoke(this, $"初始化失败: {ex.Message}");
return false;
}
}
public async Task<bool> StartAsync()
{
if (!_isInitialized || _serialPort == null)
{
OnScannerError?.Invoke(this, "扫码服务未初始化");
return false;
}
try
{
if (!_serialPort.IsOpen)
{
await Task.Run(() => _serialPort.Open());
_logger.LogInformation("串口扫码枪启动成功");
}
return true;
}
catch (Exception ex)
{
_logger.LogError(ex, "启动串口扫码枪失败");
OnScannerError?.Invoke(this, $"启动失败: {ex.Message}");
return false;
}
}
public async Task<bool> StopAsync()
{
if (_serialPort?.IsOpen == true)
{
await Task.Run(() => _serialPort.Close());
_logger.LogInformation("串口扫码枪已停止");
}
return true;
}
/// <summary>
/// 串口数据接收事件处理
/// </summary>
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
if (sender is SerialPort sp)
{
string scannedData = sp.ReadExisting().Trim();
if (!string.IsNullOrEmpty(scannedData))
{
_logger.LogInformation($"接收到扫码数据: {scannedData}");
// 异步处理扫码数据
_ = Task.Run(async () =>
{
var result = await ProcessScanCodeAsync(scannedData);
if (result.Success && result.Data != null)
{
OnScanDataReceived?.Invoke(this, result.Data);
}
});
}
}
}
catch (Exception ex)
{
_logger.LogError(ex, "处理扫码数据时发生错误");
OnScannerError?.Invoke(this, $"数据处理错误: {ex.Message}");
}
}
/// <summary>
/// 处理扫码数据业务逻辑
/// </summary>
public async Task<ScanResult> ProcessScanCodeAsync(string scanCode)
{
try
{
_logger.LogInformation($"开始处理扫码数据: {scanCode}");
var scanData = new ScanData
{
Code = scanCode.ToUpper(),
ScanTime = DateTime.Now
};
// ============ 业务逻辑判断 ============
// 判断是否为产品条码(根据你的业务规则修改)
if (IsProductCode(scanCode))
{
scanData.CodeType = "Product";
await ProcessProductCodeAsync(scanData);
}
// 判断是否为物料条码
else if (IsMaterialCode(scanCode))
{
scanData.CodeType = "Material";
await ProcessMaterialCodeAsync(scanData);
}
// 判断是否为追溯码
else if (IsTraceCode(scanCode))
{
scanData.CodeType = "Trace";
await ProcessTraceCodeAsync(scanData);
}
else
{
scanData.CodeType = "Unknown";
scanData.IsValid = false;
scanData.ErrorMessage = "未知条码类型";
await ProcessUnknownCodeAsync(scanData);
}
return new ScanResult
{
Success = scanData.IsValid,
Message = scanData.IsValid ? "处理成功" : scanData.ErrorMessage,
Data = scanData
};
}
catch (Exception ex)
{
_logger.LogError(ex, $"处理扫码数据时发生错误: {scanCode}");
return new ScanResult
{
Success = false,
Message = $"处理失败: {ex.Message}"
};
}
}
#region -
private bool IsProductCode(string code)
{
// 根据你的业务规则判断是否为产品条码
return code.Length == 20 || code.StartsWith("P") || code.StartsWith("PROD");
}
private bool IsMaterialCode(string code)
{
// 根据你的业务规则判断是否为物料条码
return code.Length == 15 || code.StartsWith("M") || code.StartsWith("MAT");
}
private bool IsTraceCode(string code)
{
// 根据你的业务规则判断是否为追溯码
return code.Contains("TRACE") || code.Contains(GetCurrentLineName());
}
private async Task ProcessProductCodeAsync(ScanData scanData)
{
_logger.LogInformation($"处理产品条码: {scanData.Code}");
// 这里实现产品条码处理逻辑
// 例如更新数据库、与PLC通信、更新界面等
// 模拟异步处理
await Task.Delay(10);
// 示例:更新全局状态
// global.ScanCode = scanData.Code;
}
private async Task ProcessMaterialCodeAsync(ScanData scanData)
{
_logger.LogInformation($"处理物料条码: {scanData.Code}");
// 这里实现物料条码处理逻辑
await Task.Delay(10);
}
private async Task ProcessTraceCodeAsync(ScanData scanData)
{
_logger.LogInformation($"处理追溯码: {scanData.Code}");
// 这里实现追溯码处理逻辑
await Task.Delay(10);
}
private async Task ProcessUnknownCodeAsync(ScanData scanData)
{
_logger.LogWarning($"未知条码类型: {scanData.Code}");
// 处理未知条码
await Task.Delay(10);
}
private string GetCurrentLineName()
{
// 返回当前生产线名称,根据你的业务逻辑实现
return "LINE001";
}
#endregion
#region
private Parity ParseParity(string parity)
{
return parity.ToUpper() switch
{
"N" or "NONE" => Parity.None,
"E" or "EVEN" => Parity.Even,
"O" or "ODD" => Parity.Odd,
"M" or "MARK" => Parity.Mark,
"S" or "SPACE" => Parity.Space,
_ => Parity.None
};
}
private StopBits ParseStopBits(string stopBits)
{
return stopBits.ToUpper() switch
{
"1" or "ONE" => StopBits.One,
"1.5" or "ONEPOINTFIVE" => StopBits.OnePointFive,
"2" or "TWO" => StopBits.Two,
_ => StopBits.One
};
}
public void Dispose()
{
_serialPort?.Close();
_serialPort?.Dispose();
_logger.LogInformation("扫码服务资源已释放");
}
#endregion
}
}