123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- using TwinCAT;
- using TwinCAT.Ads;
- using TwinCAT.Ads.TypeSystem;
- namespace PLCIOPointTool.Services;
- public class AdsClientService : IClientService
- {
- private readonly ILogService _logService;
- private readonly AdsClient _adsClient;
- private readonly Timer _timer;
- private bool _previousCheckState = false;
- private bool disposedValue;
- public AdsClientService(ILogService logService)
- {
- _logService = logService;
- _adsClient = new AdsClient();
- _adsClient.ConnectionStateChanged += OnAdsClientConnectionStateChanged;
- _timer = new Timer(OnHealthCheck, null, Timeout.Infinite, Timeout.Infinite);
- }
- public event EventHandler<ConnectionState>? ConnectionStateChanged;
- public event EventHandler<bool>? HealthCheckingChanged;
- public async Task ConnectAsync(string netId, int port)
- {
- if (string.IsNullOrWhiteSpace(netId) || port < 0)
- {
- _logService.Warning("Invalid connection parameters");
- return;
- }
- try
- {
- await _adsClient.ConnectAsync(new AmsAddress(netId, port), new CancellationToken());
- if (_adsClient.TryReadState(out _) != AdsErrorCode.NoError)
- {
- OnAdsClientConnectionStateChanged(
- null,
- new ConnectionStateChangedEventArgs(
- ConnectionStateChangedReason.Established,
- ConnectionState.Disconnected,
- ConnectionState.Disconnected));
- _logService.Warning("Failed to connect ADS server, please try later");
- return;
- }
- _logService.Info("Succeeded to connect ADS server");
- _timer.Change(3000, 3000);
- }
- catch (Exception ex)
- {
- _logService.Error($"Got an exception while connecting; {ex}");
- }
- }
- public async Task DisconnectAsync()
- {
- try
- {
- await _adsClient.DisconnectAsync(new CancellationToken());
- _logService.Info("Succeeded to disconnect ADS server");
- }
- catch (Exception ex)
- {
- _logService.Error($"Got an exception while disconnecting; {ex}");
- }
- finally
- {
- _timer.Change(Timeout.Infinite, Timeout.Infinite);
- }
- }
- public async Task<object?> ReadValue(string symbolName)
- {
- if (string.IsNullOrWhiteSpace(symbolName))
- {
- _logService.Warning("Invalid variable path");
- return null;
- }
- try
- {
- var symbol = await _adsClient.ReadSymbolAsync(symbolName, new CancellationToken());
- if (symbol is null || symbol.Value is null || symbol.Succeeded == false)
- {
- _logService.Warning($"Failed to get symbol of {symbolName}");
- return null;
- }
- var symbolValue = await _adsClient.ReadValueAsync(symbol.Value, new CancellationToken());
- if (symbolValue is null || symbolValue.Value is null || symbolValue.Succeeded == false)
- {
- _logService.Warning($"Failed to get value of {symbolName}");
- return null;
- }
- _logService.Info($"Succeeded to get value of {symbolName}");
- return symbolValue.Value;
- }
- catch (Exception ex)
- {
- _logService.Error($"Got an exception while reading; {ex}");
- return null;
- }
- }
- public async Task WriteValue(string symbolName, object value)
- {
- if (string.IsNullOrWhiteSpace(symbolName) || value is null)
- {
- _logService.Warning("Invalid variable path or value");
- return;
- }
- try
- {
- var resultValue = await _adsClient.WriteSymbolAsync(symbolName, value, new CancellationToken());
- if (resultValue is null || resultValue.Succeeded == false)
- {
- _logService.Warning($"Failed to set value of {symbolName}");
- return;
- }
- _logService.Info($"Succeeded to set value of {symbolName}");
- }
- catch (Exception ex)
- {
- _logService.Error($"Got an exception while reading; {ex}");
- }
- }
- private void OnAdsClientConnectionStateChanged(object? sender, TwinCAT.ConnectionStateChangedEventArgs e)
- {
- try
- {
- ConnectionStateChanged?.Invoke(null, e.NewState);
- }
- catch (Exception ex)
- {
- _logService.Error($"Got an exception; {ex}");
- }
- }
- private void OnHealthCheck(object? state)
- {
- var errorCode = _adsClient.TryReadState(out _);
- if (errorCode != AdsErrorCode.NoError)
- {
- _logService.Warning("Health Checking Failed");
- if (_previousCheckState == true)
- {
- _previousCheckState = false;
- HealthCheckingChanged?.Invoke(null, false);
- }
- return;
- }
- if (_previousCheckState == false)
- {
- _previousCheckState = true;
- HealthCheckingChanged?.Invoke(null, true);
- }
- //_logService.Info("Health Checking succeeded");
- }
- #region Dispose
- protected virtual void Dispose(bool disposing)
- {
- if (!disposedValue)
- {
- if (disposing)
- {
- // TODO: dispose managed state (managed objects)
- }
- // TODO: free unmanaged resources (unmanaged objects) and override finalizer
- // TODO: set large fields to null
- _timer.Change(Timeout.Infinite, Timeout.Infinite);
- _timer.Dispose();
- _adsClient.Dispose();
- _adsClient.ConnectionStateChanged -= OnAdsClientConnectionStateChanged;
- disposedValue = true;
- }
- }
- // // TODO: override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources
- // ~AdsClientService()
- // {
- // // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
- // Dispose(disposing: false);
- // }
- public void Dispose()
- {
- // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
- Dispose(disposing: true);
- GC.SuppressFinalize(this);
- }
- #endregion
- }
|