123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300 |
- using Log;
- using ProtocalGeneral;
- using System.Collections.Concurrent;
- using TwinCAT.Ads.SumCommand;
- using TwinCAT.TypeSystem;
- namespace AdsCommunicatorNet8;
- //this Implementation has removed notification function, only get value and set value available
- public class AdsCommunicator(ILog? log) : IDisposable
- {
- private bool _isConnected;
- private bool _isInitialized;
- private string? _netID = null;
- private int _port = 0;
- private AdsClient? _adsClient;
- private List<string[]>? _adsCsvInfo;
- private ITcpConnectNority? _connectionNotify;
- private bool disposedValue;
- private readonly ConcurrentDictionary<string, IAdsSymbol> _symbols = [];
- public bool IsConnected => _isConnected;
- public bool IsInitialized => _isInitialized;
- public bool Initialize(ITcpConnectNority connectionNotify)
- {
- if (this._adsClient is not null)
- return false;
- this._adsClient = new AdsClient();
- this._adsClient.ConnectionStateChanged += AdsClient_ConnectionStateChanged;
- this._adsCsvInfo = [];
- this._connectionNotify = connectionNotify;
- _isInitialized = true;
- disposedValue = false;
- return true;
- }
- public bool Open(string netID, int port, int retry=10)
- {
- log?.Info($"Try Open {netID} {port}");
- if (this._adsClient is null)
- {
- log?.Warning("Not initialized before Open");
- return false;
- }
- if (this._adsClient.IsConnected)
- {
- log?.Warning($"Ads {netID} {port} already connected");
- return false;
- }
- for (int i = 1; i <= retry; i++)
- {
- log?.Info($"Try Connected {i}");
- try
- {
- this._adsClient.Connect(netID, port);
- if (this._adsClient.TryReadState(out _) == AdsErrorCode.NoError)
- break;
- }
- catch
- {
- }
- if (i == retry)
- {
- log?.Error($"Reach Max Retry {i}, connect failed");
- return false;
- }
- Thread.Sleep(300);
- }
- this._netID = netID;
- this._port = port;
- log?.Info($"Connect success");
- return true;
- }
- public bool ReConnect()
- {
- if (string.IsNullOrEmpty(this._netID) || this._port == 0)
- return false;
- this._adsClient ??= new();
- if (this._adsClient.IsConnected)
- return true;
- for (; ; )
- {
- log?.Info($"Try ReConnected");
- try
- {
- this._adsClient.Connect(_netID, _port);
- if (this._adsClient.TryReadState(out _) == AdsErrorCode.NoError)
- break;
- }
- catch
- {
- Thread.Sleep(300);
- }
- }
- return true;
- }
- public bool GetValue<T>(string symbolName, out T? value)
- {
- value = default;
- if (string.IsNullOrEmpty(symbolName))
- {
- log?.Warning("Symbol Empty");
- return false;
- }
- log?.Info($"Try get value {symbolName}");
- if (this._adsClient is null)
- {
- log?.Error("PLC not connected");
- return false;
- }
- if (!this._symbols.TryGetValue(symbolName, out IAdsSymbol? adsSymbol) || adsSymbol is null)
- {
- log?.Info($"{symbolName} not Created before try create symbol");
- if (this._adsClient.TryReadSymbol(symbolName, out adsSymbol) != AdsErrorCode.NoError || adsSymbol is null)
- {
- log?.Error($"{symbolName} not exist in PLC");
- return false;
- }
- this._symbols[symbolName] = adsSymbol;
- }
- try
- {
- value = (T)this._adsClient.ReadValue(adsSymbol);
- log?.Info($"{symbolName} value {value}");
- }
- catch (Exception ex)
- {
- log?.Error($"{symbolName} Read failed: {ex.Message}");
- return false;
- }
- return true;
- }
- public bool SetValue<T>(string symbolName, T value) where T : notnull
- {
- if (string.IsNullOrEmpty(symbolName))
- {
- log?.Warning("Set Value Symbol empty");
- return false;
- }
- log?.Info($"Try set value {symbolName}");
- if (this._adsClient is null)
- {
- log?.Error("PLC not connected");
- return false;
- }
- if (value is null)
- {
- log?.Warning("Value Empty");
- return false;
- }
- log?.Info($"Value {value}");
- if (!this._symbols.TryGetValue(symbolName, out IAdsSymbol? adsSymbol) || adsSymbol is null)
- {
- log?.Info($"{symbolName} not Created before try create symbol");
- if (this._adsClient.TryReadSymbol(symbolName, out adsSymbol) != AdsErrorCode.NoError || adsSymbol is null)
- {
- log?.Error($"{symbolName} not exist in PLC");
- return false;
- }
- this._symbols[symbolName] = adsSymbol;
- }
- try
- {
- this._adsClient.WriteValue(adsSymbol, value);
- log?.Info($"Set {symbolName} value {value} succeeded");
- }
- catch (Exception ex)
- {
- log?.Error($"{symbolName} Set failed: {ex.Message}");
- return false;
- }
- return true;
- }
- public bool SetBatchValue(IEnumerable<string> symbolCollection, IList<object> valueCollection)
- {
- if (this._adsClient is null)
- return false;
- if (symbolCollection is null || valueCollection is null)
- return false;
- if (symbolCollection.Count() != symbolCollection.Count())
- return false;
- List<ISymbol> symbols = [];
- foreach (var item in symbolCollection)
- {
- if (!this._symbols.TryGetValue(item, out IAdsSymbol? symbol) || symbol is null)
- {
- log?.Warning($"BatchSend: {item} not Registered before");
- return false;
- }
- symbols.Add(symbol);
- }
- SumSymbolWrite writes = new(this._adsClient, symbols);
- try
- {
- writes.Write([.. valueCollection]);
- }
- catch (Exception ex)
- {
- log?.Warning(ex.Message);
- return false;
- }
- return true;
- }
- private void AdsClient_ConnectionStateChanged(object? sender, TwinCAT.ConnectionStateChangedEventArgs e)
- {
- if (this._adsClient is null)
- return;
- log?.Info($"{e.NewState} {this._adsClient.Address.NetId} {this._adsClient.Address.Port}");
- switch (e.NewState)
- {
- case TwinCAT.ConnectionState.Connected:
- this._isConnected = true;
- this._connectionNotify?.Connect(this._adsClient.Address.NetId.ToString(), this._adsClient.Address.Port);
- break;
- case TwinCAT.ConnectionState.Disconnected:
- case TwinCAT.ConnectionState.Lost:
- default:
- this._isConnected = false;
- this._connectionNotify?.DisConnect(this._adsClient.Address.NetId.ToString(), this._adsClient.Address.Port);
- break;
- }
- }
- #region Dispose
- protected virtual void Dispose(bool disposing)
- {
- log?.Info("Disposing AdsCommunication");
- if (!disposedValue)
- {
- if (disposing)
- {
- if (this._adsClient is not null)
- {
- this._adsClient.Dispose();
- this._adsClient.ConnectionStateChanged -= AdsClient_ConnectionStateChanged;
- this._adsClient = null;
- _isInitialized = false;
- }
- this._adsCsvInfo?.Clear();
- }
- disposedValue = true;
- }
- }
- public void Dispose()
- {
- Dispose(disposing: true);
- GC.SuppressFinalize(this);
- }
- #endregion
- }
|