Java通过HslCommunication快速实现PLC数据采集

本来是想直接实战的,但是写着写着发现:

如果对PLC的基础知识,尤其存储区、数据结构不先了解的话,在对PLC的地址进行读写操作时,会觉得莫名其妙,所以,就先补写了一片PLC的基础介绍:

PLC基础知识 + 西门子S7-200Smart型号存储区、数据类型

一、什么是HslCommunication?

官网:http://www.hslcommunication.cn/

官网Doc文档:http://www.hsltechnology.cn/Doc/HslCommunication

官网API文档:http://api.hslcommunication.cn/html/c136d3de-eab7-9b0f-4bdf-d891297c8018.htm

Github地址:https://github.com/newtopp/HslCommunication/

1、HSL的介绍:

        这是一个基于工业物联网,计算机通讯的架构实现,集成了工业软件开发的大部分的基础功能实现,比如三菱PLC通讯,西门子PLC通讯,欧姆龙PLC通讯,modbus通讯,AB PLC,基恩士PLC,台达PLC,松下PLC,GE PLC通讯等等,这些通讯全部进行了多语言的实现,当然,主打的 .net 库的功能集成还更加的强大,除此之外,还实现了跨程序,跨语言,跨平台的通讯,让你不再纠结于使用windows还是 linux系统,实现了日志功能,流水号生成功能,邮件发送功能,傅立叶变换功能,等等,将来会集成更多的工业环境常见功能的实现。 

2、HSL的版权问题:

  • 个人用户可免费用于学术研究,测试。

  •  如果,个人所有依赖组件的项目年总值小于3000元以下的,只需要一次性付费240rmb,加入普通vip即可获得永久使用的权利,永久发放激活码。

  • 个人商业使用及企业商业使用需要进行授权,授权费用参考官网:http://www.hslcommunication.cn/ 

所以:作为个人入门、学习、调试等使用,还是很不错的选择,但是如果有商业用途,建议获取官方授权,或者另寻它法!


二、使用Java通过HSLCommunication快速实现对S7-200Smart的读写操作

1、引入HSLCommunication的依赖:

<!-- https://mvnrepository.com/artifact/com.github.dathlin/HslCommunication -->
<dependency>
    <groupId>com.github.dathlin</groupId>
    <artifactId>HslCommunication</artifactId>
    <version>3.3.1</version>
</dependency>

2、以短连接的方式对本地PLC进行读写操作:

// 测试了多种数据类型,以及中文
public class SiemensShortConnect {
    public static void main(String[] args) {
        SiemensS7Net siemensS7 = new SiemensS7Net(SiemensPLCS.S200Smart, "127.0.0.1");
        siemensS7.setPort(102);

        siemensS7.Write("M10.0", Boolean.TRUE); // BOOL型占 1 Bit,可以存在小空间的M区(位存储区)
        siemensS7.Write("V100",100); // 整形 int = 4Byte
        siemensS7.Write("V104",(long) 10000); // 整形 long = 4Byte
        siemensS7.Write("V112", (float) 4.44); // 浮点型(实数), float = 4Byte
        siemensS7.Write("V116", (double) 8.88); // 浮点型(实数), double = 8Byte
        siemensS7.Write("V124", "zidan"); // UTF-8编码下,一个英文字母为一个字符,一个英文字符 = 1Byte;但是VW起始位必须要偶数
        siemensS7.Write("VW130", "jiguiquan"); // UTF-8编码下,一个英文字母为一个字符,一个英文字符 = 1Byte;一个中文汉字 = 3字节;但是VW起始位必须要偶数
        siemensS7.Write("VW140", "吉桂权", Charset.forName("UTF-8")); // UTF-8编码下,一个英文字母为一个字符,一个英文字符 = 1Byte;一个中文汉字 = 3字节;但是VW起始位必须要偶数

        Boolean m10 = siemensS7.ReadBool("M10.0").Content;
        Integer v100 = siemensS7.ReadInt32( "VB100" ).Content;  // V100 = VB100
        Long v104 = siemensS7.ReadInt64( "VB104" ).Content; // V104 = VB104
        Float v112 = siemensS7.ReadFloat("V112").Content;
        Double v116 = siemensS7.ReadDouble("V116").Content;
        String vw124 = siemensS7.ReadString("VW124").Content; // V124 = VW124
        String vw130 = siemensS7.ReadString("V130").Content;  // VW130 = V130
        String vw140 = siemensS7.ReadString("V140", Charset.forName("UTF-8")).Content;
        // 底层会自己判断,我们只需要根据JAVA中的数据类型,区判断字节数即可;

        System.out.println("M10.0: " + m10);
        System.out.println("V100: " + v100);
        System.out.println("V104: " + v104);
        System.out.println("V112: " + v112);
        System.out.println("V116: " + v116);
        System.out.println("VW124: " + vw124);
        System.out.println("VW130: " + vw130);
        System.out.println("VW140: " + vw140);
    }
}

运行结果如下:

M10.0: true
V100: 100
V104: 10000
V112: 4.44
V116: 8.88
VW124: zidan
VW130: jiguiquan
VW140: 吉桂权

问:何为短连接?

答:如下图,每一次读或写操作,都会伴随一次 连接~断开,这种显然是很不友好且耗资源的;如果有很多操作时,我们肯定希望能够通过长连接完成;

1692156208739584.png

3、通过长连接的方式对本地PLC进行读写操作:

public class SiemensLongConnect {
    public static void main(String[] args) {
        SiemensS7Net siemensS7 = new SiemensS7Net( SiemensPLCS.S200Smart, "127.0.0.1" );
        siemensS7.setPort(102);
        OperateResult connect  = siemensS7.ConnectServer();  // 建立长连接
        if (!connect.IsSuccess) {
            System.out.println("connect failed:" + connect.Message);
            return;
        }

        siemensS7.Write("M10.0", Boolean.TRUE); // BOOL型占 1 Bit,可以存在小空间的M区(位存储区)
        siemensS7.Write("V100",100); // 整形 int = 4Byte
        siemensS7.Write("V104",(long) 10000); // 整形 long = 4Byte
        siemensS7.Write("V112", (float) 4.44); // 浮点型(实数), float = 4Byte
        siemensS7.Write("V116", (double) 8.88); // 浮点型(实数), double = 8Byte
        siemensS7.Write("V124", "zidan"); // UTF-8编码下,一个英文字母为一个字符,一个英文字符 = 1Byte;但是VW起始位必须要偶数
        siemensS7.Write("VW130", "jiguiquan"); // UTF-8编码下,一个英文字母为一个字符,一个英文字符 = 1Byte;一个中文汉字 = 3字节;但是VW起始位必须要偶数
        siemensS7.Write("VW140", "吉桂权", Charset.forName("UTF-8")); // UTF-8编码下,一个英文字母为一个字符,一个英文字符 = 1Byte;一个中文汉字 = 3字节;但是VW起始位必须要偶数

        Boolean m10 = siemensS7.ReadBool("M10.0").Content;
        Integer v100 = siemensS7.ReadInt32( "VB100" ).Content;  // V100 = VB100
        Long v104 = siemensS7.ReadInt64( "VB104" ).Content; // V104 = VB104
        Float v112 = siemensS7.ReadFloat("V112").Content;
        Double v116 = siemensS7.ReadDouble("V116").Content;
        String vw124 = siemensS7.ReadString("VW124").Content; // V124 = VW124
        String vw130 = siemensS7.ReadString("V130").Content;  // VW130 = V130
        String vw140 = siemensS7.ReadString("V140", Charset.forName("UTF-8")).Content;
        // 底层会自己判断,我们只需要根据JAVA中的数据类型,区判断字节数即可;

        System.out.println("M10.0: " + m10);
        System.out.println("V100: " + v100);
        System.out.println("V104: " + v104);
        System.out.println("V112: " + v112);
        System.out.println("V116: " + v116);
        System.out.println("VW124: " + vw124);
        System.out.println("VW130: " + vw130);
        System.out.println("VW140: " + vw140);

        siemensS7.ConnectClose( ); // 关闭长连接
    }
}

输出结果与短连接相同:

M10.0: true
V100: 100
V104: 10000
V112: 4.44
V116: 8.88
VW124: zidan
VW130: jiguiquan
VW140: 吉桂权

但是只建立了一次连接:

1692156674832847.png

显然,我们工作中,应该更多的使用长连接的方式对PLC进行读写操作!

4、正确且更优雅的方式对PLC进行操作:

// 实际上所有的读写都是返回是否成功的标记的,在实际的开发中,需要严格的判定,怎么判定呢?如下方代码:
OperateResultExOne<Boolean> readM20 = siemensS7.ReadBool("M20");
if (readM20.IsSuccess) {
    // 读取成功,这时候获取Content才是正确的值
    Boolean m20 = readM20.Content;
} else {
    String message = readM20.Message;
}

jiguiquan@163.com

文章作者信息...

留下你的评论

*评论支持代码高亮<pre class="prettyprint linenums">代码</pre>

相关推荐