PlcConntectHepler
This commit is contained in:
parent
794221fbc6
commit
59856db96e
133
RIZO.Service/PLCBackground/PlcConntectHepler.cs
Normal file
133
RIZO.Service/PLCBackground/PlcConntectHepler.cs
Normal file
@ -0,0 +1,133 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using S7.Net; // 确保引用 S7.Net 库
|
||||
|
||||
namespace RIZO.Service.PLC
|
||||
{
|
||||
|
||||
|
||||
|
||||
public class PlcConntectHepler : IDisposable
|
||||
{
|
||||
private Plc _plc;
|
||||
private readonly string _ipAddress;
|
||||
private readonly CpuType _cpuType;
|
||||
private readonly short _rack;
|
||||
private readonly short _slot;
|
||||
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
|
||||
private bool _disposed;
|
||||
|
||||
public PlcConntectHepler(string ipAddress, CpuType cpuType = CpuType.S71200, short rack = 0, short slot = 1)
|
||||
{
|
||||
_ipAddress = ipAddress;
|
||||
_cpuType = cpuType;
|
||||
_rack = rack;
|
||||
_slot = slot;
|
||||
}
|
||||
|
||||
private async Task ConnectAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
int maxRetries = 3;
|
||||
int retryDelayMs = 2000;
|
||||
int attempt = 0;
|
||||
|
||||
while (attempt < maxRetries)
|
||||
{
|
||||
attempt++;
|
||||
try
|
||||
{
|
||||
_plc = new Plc(_cpuType, _ipAddress, _rack, _slot);
|
||||
await Task.Run(() => _plc.Open(), cancellationToken); // 在线程池中执行同步Open
|
||||
Console.WriteLine($"成功连接到PLC: {_ipAddress} (尝试{attempt}/{maxRetries})");
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"连接尝试 {attempt}/{maxRetries} 失败: {ex.Message}");
|
||||
|
||||
if (attempt < maxRetries)
|
||||
{
|
||||
Console.WriteLine($"{retryDelayMs / 1000}秒后重试...");
|
||||
await Task.Delay(retryDelayMs, cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("无法建立PLC连接,请检查网络和设备状态");
|
||||
_plc?.Close();
|
||||
_plc = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<object> ReadAsync(string address, CancellationToken cancellationToken = default)
|
||||
{
|
||||
await _semaphore.WaitAsync(cancellationToken);
|
||||
try
|
||||
{
|
||||
if (_plc == null || !_plc.IsConnected)
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
if (_plc == null || !_plc.IsConnected)
|
||||
throw new InvalidOperationException("PLC未连接");
|
||||
}
|
||||
|
||||
return await Task.Run(() => _plc.Read(address), cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Read error: {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_semaphore.Release();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task WriteAsync(string address, object value, CancellationToken cancellationToken = default)
|
||||
{
|
||||
await _semaphore.WaitAsync(cancellationToken);
|
||||
try
|
||||
{
|
||||
if (_plc == null || !_plc.IsConnected)
|
||||
{
|
||||
await ConnectAsync(cancellationToken);
|
||||
if (_plc == null || !_plc.IsConnected)
|
||||
throw new InvalidOperationException("PLC未连接");
|
||||
}
|
||||
|
||||
await Task.Run(() => _plc.Write(address, value), cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Write error: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
_semaphore.Release();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (_disposed) return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
_semaphore.Dispose();
|
||||
_plc?.Close();
|
||||
(_plc as IDisposable)?.Dispose();
|
||||
}
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
70
RIZO.Service/PLCBackground/PlcPollingServiceOP72.cs
Normal file
70
RIZO.Service/PLCBackground/PlcPollingServiceOP72.cs
Normal file
@ -0,0 +1,70 @@
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using RIZO.Service.PLC;
|
||||
using S7.Net;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace RIZO.Service.PLCBackground
|
||||
{
|
||||
|
||||
|
||||
public class PlcPollingServiceOP72 : BackgroundService
|
||||
{
|
||||
private readonly ILogger<PlcPollingServiceOP72> _logger;
|
||||
private PlcConntectHepler _plcService;
|
||||
private readonly TimeSpan _pollingInterval = TimeSpan.FromSeconds(5);
|
||||
private readonly string _ipAddress = "192.168.0.1";
|
||||
private readonly CpuType _cpuType = CpuType.S71500;
|
||||
|
||||
public PlcPollingServiceOP72(ILogger<PlcPollingServiceOP72> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
_logger.LogInformation("PLC Polling Service started");
|
||||
|
||||
// 使用工厂方法创建服务实例
|
||||
using (_plcService = new PlcConntectHepler(_ipAddress, _cpuType))
|
||||
{
|
||||
while (!stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 使用异步读写方法
|
||||
var data1 = await _plcService.ReadAsync("DB1.DBW0");
|
||||
var data2 = await _plcService.ReadAsync("DB1.DBD4");
|
||||
var flag = await _plcService.ReadAsync("M10.0");
|
||||
|
||||
_logger.LogInformation($"DB1.DBW0: {data1}, DB1.DBD4: {data2}, M10.0: {flag}");
|
||||
|
||||
await _plcService.WriteAsync("DB1.DBW10", (short)123);
|
||||
await _plcService.WriteAsync("DB1.DBD20", 45.67d);
|
||||
|
||||
await Task.Delay(_pollingInterval, stoppingToken);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
_logger.LogInformation("PLC Polling Service is stopping");
|
||||
break;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "PLC polling error");
|
||||
await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_logger.LogInformation("PLC Polling Service stopped");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user