S7协议是西门子S7系列PLC内置的通信协议。我们使用C#、C++或者Python等高级编程语言开发的上位机如果想访问S7系列PLC的数据,那S7协议是最方便的。目前市面上也有很多开源或者闭源的基于S7的通信驱动,比如S7Net、NodeS7、Snap7等等。但是自S7-1200/1500开始,西门子将其内置的协议升级到了S7CommPlus。该协议支持以符号名访问PLC数据,并且全面支持通信过程的认证和数据加密,使其安全性得到了很大的提高。
S7CommPlus并非开放的协议。网上也有一些针对该协议的研究文章。但是S7CommPlus认证过程比较复杂,没有很扎实的网络通信基础很难分析出来,更别说基于它开发一个通信驱动了。幸运的是前一段时间无意中在网上发现了一个德国人封装的S7CommPlus通信驱动。前几天下载后抽空研究了下。本来没抱太大希望,但是运行起来连接到PLCSIM Advanced后发现竟然可以批量获取到PLC里面所有的标签名。
string HostIp;
int res;
List<ItemAddress> readlist = new List<ItemAddress>();
Console.WriteLine("程序启动......");
//设定目标PLC的IP
if (args.Length == 1)
{
HostIp = args[0];
}
else
{
HostIp = "192.168.0.10";
}
Console.WriteLine("连接至PLC: " + HostIp);
S7CommPlusConnection conn = new S7CommPlusConnection();
res = conn.Connect(HostIp);
if (res == 0)
{
Console.WriteLine("连接成功!");
Console.WriteLine("浏览标签......");
// Variablenhaushalt auslesen
List<VarInfo> vars = new List<VarInfo>();
res = conn.Browse(out vars);
}
看来所言非虚,不过连续运行一段时间后,发现通信非常不稳定,短则几十秒,长则3-5分钟就会掉一次线。
为了排除PLCSIM Advanced或者系统的问题,我又找了一台S7-1200PLC来测试。发现可以连接到CPU,但是无法获取标签名。想着是不是固件版本问题。将CPU的固件版本从4.4升级到4.5后终于可以获取到标签名称了。通过驱动的读标签值方法也可以获取到变量的值。
Console.WriteLine("读标签值......");foreach (var v in vars){ readlist.Add(new ItemAddress(v.AccessSequence));} List<object> values = new List<object>(); List<UInt64> errors = new List<UInt64>(); //调用读标签值方法 res = conn.ReadValues(readlist, out values, out errors);
既然读写没问题,那么连续运行试下稳定性如何。一晚上没关机,第二天起来发现通信依然正常。检查应用程序的各项参数也都没啥问题,看来稳定性应该还行。不过经过对比,在数据刷新速度上,S7CommPlus比之前的S7明显慢了一些,不知道是否和中间的通信认证有关系。后面有时间再观察看看。