using System; using System.Net.Sockets; namespace S7.Net { /// /// Creates an instance of S7.Net driver /// public partial class Plc : IDisposable { private const int CONNECTION_TIMED_OUT_ERROR_CODE = 10060; //TCP connection to device private TcpClient tcpClient; private NetworkStream stream; /// /// IP address of the PLC /// public string IP { get; private set; } /// /// CPU type of the PLC /// public CpuType CPU { get; private set; } /// /// Rack of the PLC /// public Int16 Rack { get; private set; } /// /// Slot of the CPU of the PLC /// public Int16 Slot { get; private set; } /// /// Max PDU size this cpu supports /// public Int16 MaxPDUSize { get; set; } /// /// Returns true if a connection to the PLC can be established /// public bool IsAvailable { //TODO: Fix This get { try { Connect(); return true; } catch { return false; } } } /// /// Checks if the socket is connected and polls the other peer (the PLC) to see if it's connected. /// This is the variable that you should continously check to see if the communication is working /// See also: http://stackoverflow.com/questions/2661764/how-to-check-if-a-socket-is-connected-disconnected-in-c /// public bool IsConnected { get { try { if (tcpClient == null) return false; //TODO: Actually check communication by sending an empty TPDU return tcpClient.Connected; } catch { return false; } } } /// /// Creates a PLC object with all the parameters needed for connections. /// For S7-1200 and S7-1500, the default is rack = 0 and slot = 0. /// You need slot > 0 if you are connecting to external ethernet card (CP). /// For S7-300 and S7-400 the default is rack = 0 and slot = 2. /// /// CpuType of the PLC (select from the enum) /// Ip address of the PLC /// rack of the PLC, usually it's 0, but check in the hardware configuration of Step7 or TIA portal /// slot of the CPU of the PLC, usually it's 2 for S7300-S7400, 0 for S7-1200 and S7-1500. /// If you use an external ethernet card, this must be set accordingly. public Plc(CpuType cpu, string ip, Int16 rack, Int16 slot) { if (!Enum.IsDefined(typeof(CpuType), cpu)) throw new ArgumentException($"The value of argument '{nameof(cpu)}' ({cpu}) is invalid for Enum type '{typeof(CpuType).Name}'.", nameof(cpu)); if (string.IsNullOrEmpty(ip)) throw new ArgumentException("IP address must valid.", nameof(ip)); CPU = cpu; IP = ip; Rack = rack; Slot = slot; MaxPDUSize = 240; } /// /// Close connection to PLC /// public void Close() { if (tcpClient != null) { if (tcpClient.Connected) tcpClient.Close(); } } #region IDisposable Support private bool disposedValue = false; // To detect redundant calls /// /// Dispose Plc Object /// /// protected virtual void Dispose(bool disposing) { if (!disposedValue) { if (disposing) { Close(); } // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below. // TODO: set large fields to null. disposedValue = true; } } // TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources. // ~Plc() { // // Do not change this code. Put cleanup code in Dispose(bool disposing) above. // Dispose(false); // } // This code added to correctly implement the disposable pattern. void IDisposable.Dispose() { // Do not change this code. Put cleanup code in Dispose(bool disposing) above. Dispose(true); // TODO: uncomment the following line if the finalizer is overridden above. // GC.SuppressFinalize(this); } #endregion } }