using AdsCommunicatorNet8; using Log; using ProtocalGeneral; namespace PLCIOPointTool.Services; public class PLCCommunicator : ICommunicator, ITcpConnectNority, IDisposable { private readonly ILog? _log; private readonly AdsCommunicator _adsCommunicator; private const int _retryCount = 10; private bool _isConnected; private bool disposedValue; public PLCCommunicator(ILog? log) { _log = log; _adsCommunicator = new(_log); } public event EventHandler? ConnectionStatusChanged; public void Open(string netID, int port) { if (netID is null || port < 0) { _log?.Error("Invalid connection parameters"); return; } if (!_adsCommunicator.IsInitialized && !_adsCommunicator.Initialize(this)) { _log?.Error("Failed to initialize Tcp Client"); return; } if (!_adsCommunicator.Open(netID, port, _retryCount)) { _log?.Error("Failed to open Tcp Client"); return; } _log?.Info("Communicator started"); } public void Close() { _adsCommunicator.Dispose(); _log?.Info("Communicator Closed"); } public void GetValue(string symbolName, ValueType valueType) { if (string.IsNullOrWhiteSpace(symbolName)) { _log?.Error("Symbol name can not be null"); return; } if (!_isConnected) { _log?.Error("Client is in disconnected"); return; } try { if (_adsCommunicator.GetValue(symbolName, out object? value) && value is not null) { bool rst = false; switch (valueType) { case ValueType.Boolean: if (value is bool) rst = true; break; case ValueType.Int32: if (value is Int32) rst = true; break; case ValueType.Int64: if (value is Int64) rst = true; break; case ValueType.Float: if (value is float) rst = true; break; case ValueType.Double: if (value is double) rst = true; break; default: break; } if (rst) { _log?.Info($"Get value of {symbolName} [{valueType.ToString()} {value}]"); return; } } } catch (Exception ex) { _log?.Error(ex.Message); } _log?.Info($"Failed to get value of {symbolName}"); } public void SetValue(string symbolName, string inputValue, ValueType valueType) { if (string.IsNullOrWhiteSpace(symbolName) || string.IsNullOrWhiteSpace(inputValue)) { _log?.Error("Symbol name or input value can not be null"); return; } if (!_isConnected) { _log?.Error("Client is in disconnected"); return; } try { bool rst = false; switch (valueType) { case ValueType.Boolean: rst = bool.TryParse(inputValue, out bool boolRst) && _adsCommunicator.SetValue(symbolName, boolRst); break; case ValueType.Int32: rst = Int32.TryParse(inputValue, out int int32Rst) && _adsCommunicator.SetValue(symbolName, int32Rst); break; case ValueType.Int64: rst = Int64.TryParse(inputValue, out long int64Rst) && _adsCommunicator.SetValue(symbolName, int64Rst); break; case ValueType.Float: rst = float.TryParse(inputValue, out float floatRst) && _adsCommunicator.SetValue(symbolName, floatRst); break; case ValueType.Double: rst = double.TryParse(inputValue, out double doubleRst) && _adsCommunicator.SetValue(symbolName, doubleRst); break; default: break; } if (rst) { _log?.Info($"Set value of {symbolName} [{valueType.ToString()} {inputValue}]"); return; } } catch (Exception ex) { _log?.Error(ex.Message); } _log?.Info($"Failed to set value of {symbolName}"); } public void Connect(string ip, int port) { _log?.Info($"Connect to {ip}:{port}"); _isConnected = true; ConnectionStatusChanged?.Invoke(null, true); } public void DisConnect(string ip, int port) { _log?.Info($"Disconnect from {ip}:{port}"); _isConnected = false; ConnectionStatusChanged?.Invoke(null, false); } protected virtual void Dispose(bool disposing) { if (!disposedValue) { if (disposing) { // TODO: dispose managed state (managed objects) _adsCommunicator.Dispose(); } // TODO: free unmanaged resources (unmanaged objects) and override finalizer // TODO: set large fields to null disposedValue = true; } } // // TODO: override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources // ~PLCCommunicator() // { // // 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); } }