前言
工业自动化领域,可编程逻辑控制器(PLC)是实现复杂控制系统的核心组件。西门子 S7 系列 PLC 以其卓越的性能和可靠性,广泛应用于各种工业场景中。
然而,管理和维护这些 PLC 的数据往往是一项复杂且耗时的任务,尤其是在面对多个设备和大量数据的情况下。
推荐一款基于 .NET 平台的西门子 S7 系列 PLC 数据管理工具。该工具帮助大家更方便地读取、写入和管理 PLC 中的数据,从而减少手动操作的时间和错误率。
项目介绍
西门子S7系列PLC数据简单管理工具。
使用s7netplus库进行数据操作。
GitHub:github.com/S7NetPlus/s...
该项目使用了S7netplus v0.9.0版本,其IsAvailable属性调用了Connect方法,这就相当于重新建立了连接,使得原来的连接失效。
在对PLC在线检测的时候,可能会用到IsAvailable属性,但是这个属性在S7netplus v0.9.0版本中并不能让人放心使用。
1、问题所在
通过查看S7netplus v0.9.0的源码,可以得知在IsAvailable属性中调用了Connect方法,这就相当于重新建立了连接,使得原来的连接失效。在代码中含有"TODO: Fix This"的注释,可见源码也认为这样写代码不妥。
csharp
/// <summary>
/// Returns true if a connection to the PLC can be established
/// </summary>
publicbool IsAvailable
{
//TODO: Fix This
get
{
try
{
OpenAsync().GetAwaiter().GetResult();
returntrue;
}
catch
{
returnfalse;
}
}
}
2、问题解决
在旧版本(S7netplus v0.1.9 2018/5/14)的源码中,是通过Socket连接来验证PLC是否可用的,如下所示。
csharp
/// <summary>
/// Returns true if a connection to the plc can be established
/// </summary>
publicbool IsAvailable
{
get
{
#if NETFX_CORE
return (!string.IsNullOrWhiteSpace(IP));
#else
using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
return Connect(socket) == ErrorCode.NoError;
}
#endif
}
}
根据这个版本的IsAvailable属性的实现代码,可以在S7netplus v0.9.0的基础上自己封装相同作用的IsAvailable属性代码,以解决当前版本的问题。
csharp
/// <summary>
/// PLC连接是否可用
/// <remarks>PLC初始化以后才有连接意义,返回ping结果</remarks>
/// <remarks>该版本中Plc的IsAvailable属性等价于Open,因此不能在连接后使用该属性</remarks>
/// </summary>
publicbool IsAvailable
{
get
{
if (_plc == null || string.IsNullOrWhiteSpace(_plc.IP))
{
returnfalse;
}
using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
string errorMessage;
var ret = Connect(socket, _plc.IP, _plc.Port, out errorMessage) == ErrorCode.NoError;
if (!ret)
{
LastErrorMsg = errorMessage;
}
return ret;
}
}
}
ini
/// <summary>
/// 连接Socket
/// </summary>
/// <param name="socket">socket对象</param>
/// <param name="ip">IP地址</param>
/// <param name="port">端口</param>
/// <param name="errorMessage">错误信息</param>
/// <returns>连接状态码</returns>
private static ErrorCode Connect(Socket socket, string ip, int port, out string errorMessage)
{
var errorCode = ErrorCode.NoError;
errorMessage = string.Empty;
try
{
var server = new IPEndPoint(IPAddress.Parse(ip), port);
socket.Connect(server);
return errorCode;
}
catch (SocketException sex)
{
// see https://msdn.microsoft.com/en-us/library/windows/desktop/ms740668(v=vs.85).aspx
errorCode = sex.SocketErrorCode == SocketError.TimedOut
? ErrorCode.IPAddressNotAvailable
: ErrorCode.ConnectionError;
errorMessage = sex.Message;
}
catch (Exception ex)
{
errorCode = ErrorCode.ConnectionError;
errorMessage = ex.Message;
}
return errorCode;
}
3、问题延申
在上面实现的IsAvailable属性代码中,使用Socket连接的方法固然能够实现PLC的连接测试,但是要想控制连接超时时间就不容易了,这里主要解决超时时间的问题。
C#中有Ping对象,可以直接通过IP来和目标机器进行连接,也能够设置超时时间,因此是个不错的选择。需要注意的是,这个方法并不能判断指定端口是否打开,因此只能在PLC建立连接之后使用。
csharp
/// <summary>
/// 使用ping判断PLC是否在线
/// <remarks>这个方法不能测试端口是否开放</remarks>
/// </summary>
publicbool IsPlcOnline
{
get
{
if (_plc == null || string.IsNullOrWhiteSpace(_plc.IP))
{
returnfalse;
}
return PingPlc(_plc.IP);
}
}
/// <summary>
/// 对PLC进行ping操作
/// </summary>
/// <param name="ip">IP地址</param>
/// <returns>是否可以ping通</returns>
private static bool PingPlc(string ip)
{
var ping = new Ping();
var reply = ping.Send(ip, 1000);
return reply != null && reply.Status == IPStatus.Success;
}
项目架构
1、S7PlcDataManager
西门子S7系列数据管理工具(Winform)
2、S7PlcDataCollector.Client
西门子S7系列数据采集工具(Winform)
3、S7NetPlusNetCoreSample
S7netplus .NET Core Sample(.NET Core控制台程序)
项目效果
项目地址
Gitee:gitee.com/xhubobo/S7P...
总结
以上仅展示了PLC数据管理工具的部分功能。更多实用特性和详细信息,请大家访问项目地址。
希望通过本文能为C#实现工业设备数据采集开发方面提供有价值的参考。欢迎在评论区留言交流,分享您的宝贵经验和建议。
最后
如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。
也可以加入微信公众号 [DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!
优秀是一种习惯,欢迎大家留言学习!