using System;
|
using System.Diagnostics;
|
using System.Net.Sockets;
|
using System.Text;
|
using System.Threading;
|
using System.Threading.Tasks;
|
using Aging.Infrastructure.Contracts;
|
using ConnectionUtil;
|
using log4net;
|
|
namespace Aging.Infrastructure.Drivers
|
{
|
/// <summary>
|
/// TCP 原始通信驱动适配器。
|
/// 封装 ConnectionUtil.TcpClientWrapper,实现统一的 IDeviceDriver 接口。
|
/// </summary>
|
public sealed class TcpRawDriverAdapter : IDeviceDriver
|
{
|
private static readonly ILog Log = LogManager.GetLogger(typeof(TcpRawDriverAdapter));
|
|
private readonly string _ip;
|
private readonly int _port;
|
private TcpClientWrapper? _client;
|
private bool _disposed;
|
private readonly Stopwatch _latencyStopwatch = new Stopwatch();
|
private double _lastLatencyMs;
|
private string _lastError = string.Empty;
|
private DateTime? _lastErrorTime;
|
private int _reconnectCount;
|
|
/// <inheritdoc/>
|
public string DeviceId { get; }
|
|
/// <inheritdoc/>
|
public bool IsConnected => _client?.IsConnected ?? false;
|
|
/// <inheritdoc/>
|
public event EventHandler<DeviceConnectionEventArgs>? ConnectionChanged;
|
|
/// <summary>
|
/// 初始化 TCP 原始通信驱动适配器
|
/// </summary>
|
/// <param name="deviceId">设备唯一标识符</param>
|
/// <param name="ip">目标 IP 地址</param>
|
/// <param name="port">目标端口号</param>
|
public TcpRawDriverAdapter(string deviceId, string ip, int port)
|
{
|
DeviceId = deviceId ?? throw new ArgumentNullException(nameof(deviceId));
|
_ip = ip ?? throw new ArgumentNullException(nameof(ip));
|
_port = port;
|
}
|
|
/// <inheritdoc/>
|
public async Task ConnectAsync(CancellationToken ct)
|
{
|
ThrowIfDisposed();
|
Log.Info($"[TCP] 设备 {DeviceId} 正在连接 {_ip}:{_port}...");
|
|
try
|
{
|
_client = new TcpClientWrapper(_ip, _port);
|
bool success = await _client.ConnectAsync();
|
|
if (!success)
|
{
|
_lastError = "连接失败";
|
_lastErrorTime = DateTime.Now;
|
throw new InvalidOperationException($"[TCP] 设备 {DeviceId} 连接 {_ip}:{_port} 失败");
|
}
|
|
_lastError = string.Empty;
|
Log.Info($"[TCP] 设备 {DeviceId} 已成功连接到 {_ip}:{_port}");
|
OnConnectionChanged(true, "连接成功");
|
}
|
catch (Exception ex)
|
{
|
_lastError = ex.Message;
|
_lastErrorTime = DateTime.Now;
|
Log.Error($"[TCP] 设备 {DeviceId} 连接异常: {ex.Message}", ex);
|
throw;
|
}
|
}
|
|
/// <inheritdoc/>
|
public Task DisconnectAsync()
|
{
|
ThrowIfDisposed();
|
Log.Info($"[TCP] 设备 {DeviceId} 正在断开连接...");
|
|
try
|
{
|
if (_client != null)
|
{
|
_client?.Close();
|
_client = null;
|
}
|
|
Log.Info($"[TCP] 设备 {DeviceId} 已断开连接");
|
OnConnectionChanged(false, "主动断开");
|
}
|
catch (Exception ex)
|
{
|
_lastError = ex.Message;
|
_lastErrorTime = DateTime.Now;
|
Log.Error($"[TCP] 设备 {DeviceId} 断开连接异常: {ex.Message}", ex);
|
}
|
|
return Task.CompletedTask;
|
}
|
|
/// <inheritdoc/>
|
public async Task<string> SendCommandAsync(string command, CancellationToken ct)
|
{
|
ThrowIfDisposed();
|
if (!IsConnected) throw new InvalidOperationException("[TCP] 设备未连接");
|
|
_latencyStopwatch.Restart();
|
try
|
{
|
Log.Debug($"[TCP] 设备 {DeviceId} 发送命令: {command}");
|
string response = await _client.SendMessageAsync(command);
|
_latencyStopwatch.Stop();
|
_lastLatencyMs = _latencyStopwatch.Elapsed.TotalMilliseconds;
|
Log.Debug($"[TCP] 设备 {DeviceId} 收到响应: {response} (延迟 {_lastLatencyMs:F2}ms)");
|
return response;
|
}
|
catch (Exception ex)
|
{
|
_latencyStopwatch.Stop();
|
_lastLatencyMs = _latencyStopwatch.Elapsed.TotalMilliseconds;
|
_lastError = ex.Message;
|
_lastErrorTime = DateTime.Now;
|
Log.Error($"[TCP] 设备 {DeviceId} 发送命令失败: {ex.Message}", ex);
|
throw;
|
}
|
}
|
|
/// <inheritdoc/>
|
public async Task<string> QueryAsync(string query, CancellationToken ct)
|
{
|
ThrowIfDisposed();
|
if (!IsConnected) throw new InvalidOperationException("[TCP] 设备未连接");
|
|
_latencyStopwatch.Restart();
|
try
|
{
|
Log.Debug($"[TCP] 设备 {DeviceId} 发送查询: {query}");
|
// 使用较短超时进行查询操作
|
string response = await _client.SendMessageAsync(query, TimeSpan.FromSeconds(5));
|
_latencyStopwatch.Stop();
|
_lastLatencyMs = _latencyStopwatch.Elapsed.TotalMilliseconds;
|
Log.Debug($"[TCP] 设备 {DeviceId} 查询响应: {response} (延迟 {_lastLatencyMs:F2}ms)");
|
return response;
|
}
|
catch (Exception ex)
|
{
|
_latencyStopwatch.Stop();
|
_lastLatencyMs = _latencyStopwatch.Elapsed.TotalMilliseconds;
|
_lastError = ex.Message;
|
_lastErrorTime = DateTime.Now;
|
Log.Error($"[TCP] 设备 {DeviceId} 查询失败: {ex.Message}", ex);
|
throw;
|
}
|
}
|
|
/// <inheritdoc/>
|
public DeviceDriverStatus GetStatus()
|
{
|
return new DeviceDriverStatus
|
{
|
IsConnected = IsConnected,
|
IsHealthy = IsConnected && string.IsNullOrEmpty(_lastError),
|
LastError = _lastError,
|
LastErrorTime = _lastErrorTime,
|
LatencyMs = _lastLatencyMs,
|
ReconnectCount = _reconnectCount
|
};
|
}
|
|
/// <inheritdoc/>
|
public void Dispose()
|
{
|
if (_disposed) return;
|
_disposed = true;
|
|
try
|
{
|
_client?.Dispose();
|
}
|
catch (Exception ex)
|
{
|
Log.Error($"[TCP] 设备 {DeviceId} 释放资源异常: {ex.Message}", ex);
|
}
|
}
|
|
/// <summary>
|
/// 触发连接状态变化事件
|
/// </summary>
|
private void OnConnectionChanged(bool isConnected, string reason)
|
{
|
ConnectionChanged?.Invoke(this, new DeviceConnectionEventArgs
|
{
|
DeviceId = DeviceId,
|
IsConnected = isConnected,
|
Reason = reason
|
});
|
|
if (!isConnected)
|
{
|
_reconnectCount++;
|
}
|
}
|
|
/// <summary>
|
/// 检查是否已释放
|
/// </summary>
|
private void ThrowIfDisposed()
|
{
|
if (_disposed) throw new ObjectDisposedException(nameof(TcpRawDriverAdapter));
|
}
|
}
|
}
|