AdsCommunicator.cs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. using Log;
  2. using ProtocalGeneral;
  3. using System.Collections.Concurrent;
  4. using TwinCAT.Ads.SumCommand;
  5. using TwinCAT.TypeSystem;
  6. namespace AdsCommunicatorNet8;
  7. //this Implementation has removed notification function, only get value and set value available
  8. public class AdsCommunicator(ILog? log) : IDisposable
  9. {
  10. private bool _isConnected;
  11. private bool _isInitialized;
  12. private string? _netID = null;
  13. private int _port = 0;
  14. private AdsClient? _adsClient;
  15. private List<string[]>? _adsCsvInfo;
  16. private ITcpConnectNority? _connectionNotify;
  17. private bool disposedValue;
  18. private readonly ConcurrentDictionary<string, IAdsSymbol> _symbols = [];
  19. public bool IsConnected => _isConnected;
  20. public bool IsInitialized => _isInitialized;
  21. public bool Initialize(ITcpConnectNority connectionNotify)
  22. {
  23. if (this._adsClient is not null)
  24. return false;
  25. this._adsClient = new AdsClient();
  26. this._adsClient.ConnectionStateChanged += AdsClient_ConnectionStateChanged;
  27. this._adsCsvInfo = [];
  28. this._connectionNotify = connectionNotify;
  29. _isInitialized = true;
  30. disposedValue = false;
  31. return true;
  32. }
  33. public bool Open(string netID, int port, int retry=10)
  34. {
  35. log?.Info($"Try Open {netID} {port}");
  36. if (this._adsClient is null)
  37. {
  38. log?.Warning("Not initialized before Open");
  39. return false;
  40. }
  41. if (this._adsClient.IsConnected)
  42. {
  43. log?.Warning($"Ads {netID} {port} already connected");
  44. return false;
  45. }
  46. for (int i = 1; i <= retry; i++)
  47. {
  48. log?.Info($"Try Connected {i}");
  49. try
  50. {
  51. this._adsClient.Connect(netID, port);
  52. if (this._adsClient.TryReadState(out _) == AdsErrorCode.NoError)
  53. break;
  54. }
  55. catch
  56. {
  57. }
  58. if (i == retry)
  59. {
  60. log?.Error($"Reach Max Retry {i}, connect failed");
  61. return false;
  62. }
  63. Thread.Sleep(300);
  64. }
  65. this._netID = netID;
  66. this._port = port;
  67. log?.Info($"Connect success");
  68. return true;
  69. }
  70. public bool ReConnect()
  71. {
  72. if (string.IsNullOrEmpty(this._netID) || this._port == 0)
  73. return false;
  74. this._adsClient ??= new();
  75. if (this._adsClient.IsConnected)
  76. return true;
  77. for (; ; )
  78. {
  79. log?.Info($"Try ReConnected");
  80. try
  81. {
  82. this._adsClient.Connect(_netID, _port);
  83. if (this._adsClient.TryReadState(out _) == AdsErrorCode.NoError)
  84. break;
  85. }
  86. catch
  87. {
  88. Thread.Sleep(300);
  89. }
  90. }
  91. return true;
  92. }
  93. public bool GetValue<T>(string symbolName, out T? value)
  94. {
  95. value = default;
  96. if (string.IsNullOrEmpty(symbolName))
  97. {
  98. log?.Warning("Symbol Empty");
  99. return false;
  100. }
  101. log?.Info($"Try get value {symbolName}");
  102. if (this._adsClient is null)
  103. {
  104. log?.Error("PLC not connected");
  105. return false;
  106. }
  107. if (!this._symbols.TryGetValue(symbolName, out IAdsSymbol? adsSymbol) || adsSymbol is null)
  108. {
  109. log?.Info($"{symbolName} not Created before try create symbol");
  110. if (this._adsClient.TryReadSymbol(symbolName, out adsSymbol) != AdsErrorCode.NoError || adsSymbol is null)
  111. {
  112. log?.Error($"{symbolName} not exist in PLC");
  113. return false;
  114. }
  115. this._symbols[symbolName] = adsSymbol;
  116. }
  117. try
  118. {
  119. value = (T)this._adsClient.ReadValue(adsSymbol);
  120. log?.Info($"{symbolName} value {value}");
  121. }
  122. catch (Exception ex)
  123. {
  124. log?.Error($"{symbolName} Read failed: {ex.Message}");
  125. return false;
  126. }
  127. return true;
  128. }
  129. public bool SetValue<T>(string symbolName, T value) where T : notnull
  130. {
  131. if (string.IsNullOrEmpty(symbolName))
  132. {
  133. log?.Warning("Set Value Symbol empty");
  134. return false;
  135. }
  136. log?.Info($"Try set value {symbolName}");
  137. if (this._adsClient is null)
  138. {
  139. log?.Error("PLC not connected");
  140. return false;
  141. }
  142. if (value is null)
  143. {
  144. log?.Warning("Value Empty");
  145. return false;
  146. }
  147. log?.Info($"Value {value}");
  148. if (!this._symbols.TryGetValue(symbolName, out IAdsSymbol? adsSymbol) || adsSymbol is null)
  149. {
  150. log?.Info($"{symbolName} not Created before try create symbol");
  151. if (this._adsClient.TryReadSymbol(symbolName, out adsSymbol) != AdsErrorCode.NoError || adsSymbol is null)
  152. {
  153. log?.Error($"{symbolName} not exist in PLC");
  154. return false;
  155. }
  156. this._symbols[symbolName] = adsSymbol;
  157. }
  158. try
  159. {
  160. this._adsClient.WriteValue(adsSymbol, value);
  161. log?.Info($"Set {symbolName} value {value} succeeded");
  162. }
  163. catch (Exception ex)
  164. {
  165. log?.Error($"{symbolName} Set failed: {ex.Message}");
  166. return false;
  167. }
  168. return true;
  169. }
  170. public bool SetBatchValue(IEnumerable<string> symbolCollection, IList<object> valueCollection)
  171. {
  172. if (this._adsClient is null)
  173. return false;
  174. if (symbolCollection is null || valueCollection is null)
  175. return false;
  176. if (symbolCollection.Count() != symbolCollection.Count())
  177. return false;
  178. List<ISymbol> symbols = [];
  179. foreach (var item in symbolCollection)
  180. {
  181. if (!this._symbols.TryGetValue(item, out IAdsSymbol? symbol) || symbol is null)
  182. {
  183. log?.Warning($"BatchSend: {item} not Registered before");
  184. return false;
  185. }
  186. symbols.Add(symbol);
  187. }
  188. SumSymbolWrite writes = new(this._adsClient, symbols);
  189. try
  190. {
  191. writes.Write([.. valueCollection]);
  192. }
  193. catch (Exception ex)
  194. {
  195. log?.Warning(ex.Message);
  196. return false;
  197. }
  198. return true;
  199. }
  200. private void AdsClient_ConnectionStateChanged(object? sender, TwinCAT.ConnectionStateChangedEventArgs e)
  201. {
  202. if (this._adsClient is null)
  203. return;
  204. log?.Info($"{e.NewState} {this._adsClient.Address.NetId} {this._adsClient.Address.Port}");
  205. switch (e.NewState)
  206. {
  207. case TwinCAT.ConnectionState.Connected:
  208. this._isConnected = true;
  209. this._connectionNotify?.Connect(this._adsClient.Address.NetId.ToString(), this._adsClient.Address.Port);
  210. break;
  211. case TwinCAT.ConnectionState.Disconnected:
  212. case TwinCAT.ConnectionState.Lost:
  213. default:
  214. this._isConnected = false;
  215. this._connectionNotify?.DisConnect(this._adsClient.Address.NetId.ToString(), this._adsClient.Address.Port);
  216. break;
  217. }
  218. }
  219. #region Dispose
  220. protected virtual void Dispose(bool disposing)
  221. {
  222. log?.Info("Disposing AdsCommunication");
  223. if (!disposedValue)
  224. {
  225. if (disposing)
  226. {
  227. if (this._adsClient is not null)
  228. {
  229. this._adsClient.Dispose();
  230. this._adsClient.ConnectionStateChanged -= AdsClient_ConnectionStateChanged;
  231. this._adsClient = null;
  232. _isInitialized = false;
  233. }
  234. this._adsCsvInfo?.Clear();
  235. }
  236. disposedValue = true;
  237. }
  238. }
  239. public void Dispose()
  240. {
  241. Dispose(disposing: true);
  242. GC.SuppressFinalize(this);
  243. }
  244. #endregion
  245. }