2025年JAVA采用S7通信协议访问西门子PLC

JAVA采用S7通信协议访问西门子PLC简介 采用 java 的方式实现西门子 S7 协议 链接地址 iot communicatio github https github com xingshuangs iot communicatio gitee https gitee com xingshuang iot communicatio 支持单数据读写

大家好,我是讯享网,很高兴认识大家。

简介

采用java的方式实现西门子S7协议

链接地址:iot-communication
github: https://github.com/xingshuangs/iot-communication
gitee: https://gitee.com/xingshuang/iot-communication

  • 支持单数据读写,多数据读写,大数据量自动分包读写
  • 支持序列化批量多地址且地址不连续的读写
  • 支持读取DB区,I区,Q区,M区,V
  • 支持读取西门子S1200,200Smart
  • 支持PLC自动重连

引入依赖包

<dependency> <groupId>com.github.xingshuangs</groupId> <artifactId>iot-communication</artifactId> <version>1.5.1</version> </dependency> 

讯享网

简单入门示例

讯享网class Demo { 
    public static void main(String[] args) { 
    // 创建PLC对象 S7PLC s7PLC = new S7PLC(EPlcType.S1200, "127.0.0.1"); // 读写boolean s7PLC.writeBoolean("DB1.2.0", true); boolean boolData = s7PLC.readBoolean("DB1.2.0"); // 读写字节 s7PLC.writeByte("DB2.1", (byte) 0x11); byte byteData = s7PLC.readByte("DB2.1"); } } 

知识点1:地址读写格式以及对应含义(兼容大小写)

简写 区域 字节索引 位索引 PLC
DB1.1.2 DB1区 1 2 1200
DB2 DB2区 0 0 1200
DB3.3 DB3区 3 0 1200
D1.1.2 DB1区 1 2 1200
Q1.6 Q区 1 6 1200
Q1 Q区 1 0 1200
I2.5 I区 2 5 1200
I2 I区 2 0 1200
M3.2 M区 3 2 1200
M3 M区 3 0 1200
V2.1 V区 2 1 200Smart
V2 V区 2 0 200Smart

知识点2:访问数据类型与JAVA数据类型和PLC数据类型对应关系

访问数据类型 数据类型名称 数据大小(位) 数据大小(字节) 对应JAVA数据类型 对应PLC数据类型 示例
boolean 布尔类型 1 1/8 Boolean BOOL true
byte 字节类型 8 1 Byte BYTE 0x11
uint16 无符号2字节整型 16 2 Integer WORD/UINT 65535
int16 有符号2字节整型 16 2 Short WORD/INT -32760
uint32 无符号4字节整型 32 4 Long DWORD/UDINT 70000
int32 有符号4字节整型 32 4 Integer DWORD/DINT -70000
float32 4字节浮点型 32 4 Float REAL 3.14
float64 8字节浮点型 64 8 Double LREAL 3.14
string 字符型 8 1 String String ABC

多种方式PLC数据访问示例

1. 单地址数据读写

// 创建PLC对象 S7PLC s7PLC = new S7PLC(EPlcType.S1200, "127.0.0.1"); // read boolean boolean boolData = s7PLC.readBoolean("DB1.2.0"); // read byte byte byteData = s7PLC.readByte("DB14.0"); byte iByteData = s7PLC.readByte("I0"); byte qByteData = s7PLC.readByte("Q0"); byte mByteData = s7PLC.readByte("M0"); byte vByteData = s7PLC.readByte("V0"); // 200smart有V区 // read byte byte[] byteDatas = s7PLC.readByte("DB14.0", 4); // read UInt16 int intData = s7PLC.readUInt16("DB14.0"); // read UInt32 long int32Data = s7PLC.readUInt32("DB1.0"); // read float32 float float32Data = s7PLC.readFloat32("DB1.0"); // read float64 double float64Data = s7PLC.readFloat64("DB1.0"); // read String String strData = s7PLC.readString("DB14.4"); // write boolean s7PLC.writeBoolean("DB2.0.7", true); s7PLC.writeBoolean("Q0.7", true); s7PLC.writeBoolean("M1.4", true); // write byte s7PLC.writeByte("DB2.1", (byte) 0x11); s7PLC.writeByte("M1", (byte) 0x11); s7PLC.writeByte("V1", (byte) 0x11); // 200smart有V区 // write UInt16 s7PLC.writeUInt16("DB2.0", 0x2222); // write UInt32 s7PLC.writeUInt32("DB2.0", 0x); // write float32 s7PLC.writeFloat32("DB2.0", 12); // write float64 s7PLC.writeFloat64("DB2.0", 12.02); // write String s7PLC.writeString("DB14.4", "demo"); 

2. 多地址数据读写

讯享网// 创建PLC对象 S7PLC s7PLC = new S7PLC(EPlcType.S1200, "127.0.0.1"); // read boolean List<Boolean> boolDatas = s7PLC.readBoolean("DB1.2.0", "DB1.2.1", "DB1.2.7"); List<Boolean> iDatas = s7PLC.readBoolean("I0.0", "I0.1", "I0.2", "I0.3", "I0.4", "I0.5"); List<Boolean> qDatas = s7PLC.readBoolean("Q0.0", "Q0.1", "Q0.2", "Q0.3", "Q0.4", "Q0.5", "Q0.6", "Q0.7"); List<Boolean> mDatas = s7PLC.readBoolean("M1.0", "M1.1", "M1.2", "M1.3", "M1.4", "M1.5", "M1.6", "M1.7"); List<Boolean> vDatas = s7PLC.readBoolean("V1.0", "V1.1", "V1.2", "V1.3", "V1.4", "V1.5", "V1.6", "V1.7"); // 200smart有V区 // read UInt16 List<Integer> intDatas = s7PLC.readUInt16("DB1.0", "DB1.2"); // read UInt32 List<Long> int32Datas = s7PLC.readUInt32("DB1.0", "DB1.4"); // read float32 List<Float> float32Datas = s7PLC.readFloat32("DB1.0", "DB1.4"); // read float64 List<Double> float64Datas = s7PLC.readFloat64("DB1.0", "DB1.4"); // read multi address MultiAddressRead addressRead = new MultiAddressRead(); addressRead.addData("DB1.0", 1) .addData("DB1.2", 3) .addData("DB1.3", 5); List<byte[]> multiByte = s7PLC.readMultiByte(addressRead); // write multi address MultiAddressWrite addressWrite = new MultiAddressWrite(); addressWrite.addByte("DB2.0", (byte) 0x11) .addUInt16("DB2.2", 88) .addBoolean("DB2.1.0", true); s7PLC.writeMultiData(addressWrite); 

3. 序列化方式小数据量批量读写

小数据量是指单次数据请求的报文中PDU大小未超过指定PLC的最大值限制,例如单次请求PDULength小于240,不同PLC的限制各有不同,有240,480,960

先构建数据对象

@Data public class DemoBean { 
    @S7Variable(address = "DB1.0.1", type = EDataType.BOOL) private boolean bitData; @S7Variable(address = "DB1.1", type = EDataType.BYTE, count = 3) private byte[] byteData; @S7Variable(address = "DB1.4", type = EDataType.UINT16) private int uint16Data; @S7Variable(address = "DB1.6", type = EDataType.INT16) private short int16Data; @S7Variable(address = "DB1.8", type = EDataType.UINT32) private long uint32Data; @S7Variable(address = "DB1.12", type = EDataType.INT32) private int int32Data; @S7Variable(address = "DB1.16", type = EDataType.FLOAT32) private float float32Data; @S7Variable(address = "DB1.20", type = EDataType.FLOAT64) private double float64Data; } 

然后构建序列化对象,接着数据读写

讯享网class Demo { 
    public static void main(String[] args) { 
    S7PLC s7PLC = new S7PLC(EPlcType.S1200, "127.0.0.1"); S7Serializer s7Serializer = S7Serializer.newInstance(s7PLC); // 小数据量批量读取 DemoBean bean = s7Serializer.read(DemoBean.class); // 修改指定数据内容 bean.setBitData(true); bean.setByteData(new byte[]{ 
   (byte) 0x01, (byte) 0x02, (byte) 0x03}); bean.setUint16Data(42767); bean.setInt16Data((short) 32767); bean.setUint32Data(L); bean.setInt32Data(); bean.setFloat32Data(3.14f); bean.setFloat64Data(4.15); // 小数据量批量写入 s7Serializer.write(bean); } } 

4. 序列化方式大数据量批量读写

大数据量是指单次数据请求的报文中PDU大小超过指定PLC的最大值限制,例如单次请求PDULength不得超过240,不同PLC的限制各有不同,有240,480,960

先构建数据对象

@Data public class DemoLargeBean { 
    @S7Variable(address = "DB1.0.1", type = EDataType.BOOL) private boolean bitData; @S7Variable(address = "DB1.10", type = EDataType.BYTE, count = 50) private byte[] byteData1; @S7Variable(address = "DB1.60", type = EDataType.BYTE, count = 65) private byte[] byteData2; @S7Variable(address = "DB1.125", type = EDataType.BYTE, count = 200) private byte[] byteData3; @S7Variable(address = "DB1.325", type = EDataType.BYTE, count = 322) private byte[] byteData4; @S7Variable(address = "DB1.647", type = EDataType.BYTE, count = 99) private byte[] byteData5; @S7Variable(address = "DB1.746", type = EDataType.BYTE, count = 500) private byte[] byteData6; @S7Variable(address = "DB1.1246", type = EDataType.BYTE, count = 44) private byte[] byteData7; } 

然后构建序列化对象,接着数据读写


讯享网

讯享网class Demo { 
    public static void main(String[] args) { 
    S7PLC s7PLC = new S7PLC(EPlcType.S1200, "127.0.0.1"); S7Serializer s7Serializer = S7Serializer.newInstance(s7PLC); // 大数据量批量读取 DemoLargeBean bean = s7Serializer.read(DemoLargeBean.class); // 指定地址数据更改 bean.getByteData2()[64] = (byte) 0x02; bean.getByteData3()[199] = (byte) 0x03; bean.getByteData4()[321] = (byte) 0x04; bean.getByteData5()[98] = (byte) 0x05; bean.getByteData6()[499] = (byte) 0x06; bean.getByteData7()[43] = (byte) 0x07; // 大数据量批量写入 s7Serializer.write(bean); } } 

5. 自定义读写方式(开发效率低)

class Demo { 
    public static void main(String[] args) { 
    S7PLC s7PLC = new S7PLC(EPlcType.S1200, "127.0.0.1"); // bit数据读写 byte[] expect = new byte[]{ 
   (byte) 0x00}; this.s7PLC.writeRaw(EParamVariableType.BIT, 1, EArea.DATA_BLOCKS, 1, 0, 3, EDataVariableType.BIT, expect); byte[] actual = this.s7PLC.readRaw(EParamVariableType.BIT, 1, EArea.DATA_BLOCKS, 1, 0, 3); // byte数据读写 expect = new byte[]{ 
   (byte) 0x02, (byte) 0x03}; this.s7PLC.writeRaw(EParamVariableType.BYTE, 2, EArea.DATA_BLOCKS, 1, 1, 0, EDataVariableType.BYTE_WORD_DWORD, expect); actual = this.s7PLC.readRaw(EParamVariableType.BYTE, 2, EArea.DATA_BLOCKS, 1, 1, 0); } } 

6. 控制指令

讯享网class Demo { 
    public static void main(String[] args) { 
    S7PLC s7PLC = new S7PLC(EPlcType.S1200, "127.0.0.1"); // hot restart s7PLC.hotRestart(); // cold restart s7PLC.coldRestart(); // plc stop s7PLC.plcStop(); // copy ram to rom s7PLC.copyRamToRom(); // compress s7PLC.compress(); } } 

字节数据解析

当采集的数据量比较大且都是字节数组数据时,需要将字节数据转换成所需的数据,可以采用ByteReadBuff工具;
该工具采用大端模式,4字节数据解析采用DCBA,可根据需求自行修改;

1. boolean数据类型

ByteReadBuff buff = new ByteReadBuff(new byte[]{ 
   (byte) 0x55}); // 直接字节解析获取,内部索引自动后移 boolean b1 = buff.getBoolean(0); // 指定字节索引地址后解析获取 boolean b2 = buff.getBoolean(0, 1); 

2. byte数据类型

讯享网ByteReadBuff buff = new ByteReadBuff(new byte[]{ 
   (byte) 0x55, (byte) 0x33, (byte) 0x22}); // 先提取第一个字节 buff.getByte(); // 再提取后两个字节 byte[] actual = buff.getBytes(2); assertArrayEquals(new byte[]{ 
   (byte) 0x33, (byte) 0x22}, actual); buff = new ByteReadBuff(new byte[]{ 
   (byte) 0x55, (byte) 0x33, (byte) 0x22}); // 先提取第一个字节 buff.getByte(); // 再提取剩余所有字节 actual = buff.getBytes(); assertArrayEquals(new byte[]{ 
   (byte) 0x33, (byte) 0x22}, actual); 

3. uint16数据类型

ByteReadBuff buff = new ByteReadBuff(new byte[]{ 
   (byte) 0x5F, (byte) 0xF5}); int actual = buff.getUInt16(); assertEquals(24565, actual); 

4. int16数据类型

讯享网ByteReadBuff buff = new ByteReadBuff(new byte[]{ 
   (byte) 0x5F, (byte) 0xF5}); short actual = buff.getInt16(); assertEquals(24565, actual); 

5. uint32数据类型

ByteReadBuff buff = new ByteReadBuff(new byte[]{ 
   (byte) 0x00, (byte) 0x20, (byte) 0x37, (byte) 0x36}); long actual = buff.getUInt32(); assertEquals(L, actual); 

6. int32数据类型

讯享网ByteReadBuff buff = new ByteReadBuff(new byte[]{ 
   (byte) 0x00, (byte) 0x20, (byte) 0x37, (byte) 0x36}); int actual = buff.getInt32(); assertEquals(, actual); 

7. float32数据类型

ByteReadBuff buff = new ByteReadBuff(new byte[]{ 
   (byte) 0x42, (byte) 0x04, (byte) 0xA3, (byte) 0xD7}); float actual = buff.getFloat32(); assertEquals(33.16f, actual, 0.001); 

8. float64数据类型

讯享网ByteReadBuff buff = new ByteReadBuff(new byte[]{ 
   (byte) 0x41, (byte) 0x03, (byte) 0x1F, (byte) 0xCA, (byte) 0xD6, (byte) 0x21, (byte) 0x39, (byte) 0xB7}); double actual = buff.getFloat64(); assertEquals(., actual, 0.001); 

9. string数据类型

ByteReadBuff buff = new ByteReadBuff(new byte[]{ 
   (byte) 0x30, (byte) 0x31, (byte) 0x32, (byte) 0x33}); String actual = buff.getString(4); assertEquals("0123", actual); 

Springboot中简单使用

1. 普通模式

先构建Springboot的工程,添加maven依赖

讯享网 <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/com.github.xingshuangs/iot-communication --> <dependency> <groupId>com.github.xingshuangs</groupId> <artifactId>iot-communication</artifactId> <version>1.5.1</version> </dependency> </dependencies> 

添加PLC相关配置,主要是对连接对象实例化,创建bean

package com.github.xingshuangs.s7.demo.config; import com.github.xingshuangs.iot.protocol.s7.enums.EPlcType; import com.github.xingshuangs.iot.protocol.s7.serializer.S7Serializer; import com.github.xingshuangs.iot.protocol.s7.service.S7PLC; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; / * @author xingshuang */ @Configuration public class S7Config { 
    @Bean public S7PLC s7PLC() { 
    return new S7PLC(EPlcType.S1200, "127.0.0.1"); } } 

添加控制层业务

讯享网package com.github.xingshuangs.s7.demo.controller; import com.github.xingshuangs.iot.protocol.s7.service.S7PLC; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.Random; / * @author xingshuang */ @RestController @RequestMapping("/normal") public class S7NormalComController { 
    Random random = new Random(); @Autowired private S7PLC s7PLC; @GetMapping("/uint16") public ResponseEntity uint16() { 
    this.s7PLC.writeUInt16("DB1.0", random.nextInt(255)); int res = this.s7PLC.readUInt16("DB1.0"); return ResponseEntity.ok(res); } @GetMapping("/boolean") public ResponseEntity booleanTest() { 
    this.s7PLC.writeBoolean("DB1.0.0", random.nextInt(255) % 2 == 0); boolean res = this.s7PLC.readBoolean("DB1.0.0"); return ResponseEntity.ok(res); } @GetMapping("/float32") public ResponseEntity float32Test() { 
    this.s7PLC.writeFloat32("DB1.0", random.nextFloat()); float res = this.s7PLC.readFloat32("DB1.0"); return ResponseEntity.ok(res); } @GetMapping("/string") public ResponseEntity stringTest() { 
    this.s7PLC.writeString("DB1.0", String.valueOf(random.nextInt(20))); String res = this.s7PLC.readString("DB1.0"); return ResponseEntity.ok(res); } } 

2. 序列化模式

添加S7序列化对象

package com.github.xingshuangs.s7.demo.config; import com.github.xingshuangs.iot.protocol.s7.enums.EPlcType; import com.github.xingshuangs.iot.protocol.s7.serializer.S7Serializer; import com.github.xingshuangs.iot.protocol.s7.service.S7PLC; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; / * @author xingshuang */ @Configuration public class S7Config { 
    @Bean public S7PLC s7PLC() { 
    return new S7PLC(EPlcType.S1200, "127.0.0.1"); } @Bean public S7Serializer s7Serializer(S7PLC s7PLC) { 
    return new S7Serializer(s7PLC); } } 

添加数据采集类,添加注解配置

讯享网package com.github.xingshuangs.s7.demo.model; import com.github.xingshuangs.iot.common.enums.EDataType; import com.github.xingshuangs.iot.protocol.s7.serializer.S7Variable; import lombok.Data; / * 测试对象 * * @author xingshuang */ @Data public class DemoBean { 
    @S7Variable(address = "DB1.0.1", type = EDataType.BOOL) private boolean bitData; @S7Variable(address = "DB1.4", type = EDataType.UINT16) private int uint16Data; @S7Variable(address = "DB1.6", type = EDataType.INT16) private short int16Data; @S7Variable(address = "DB1.8", type = EDataType.UINT32) private long uint32Data; @S7Variable(address = "DB1.12", type = EDataType.INT32) private int int32Data; @S7Variable(address = "DB1.16", type = EDataType.FLOAT32) private float float32Data; @S7Variable(address = "DB1.20", type = EDataType.FLOAT64) private double float64Data; @S7Variable(address = "DB1.28", type = EDataType.BYTE, count = 3) private byte[] byteData; } 

添加控制层业务

package com.github.xingshuangs.s7.demo.controller; import com.github.xingshuangs.iot.protocol.s7.serializer.S7Serializer; import com.github.xingshuangs.s7.demo.model.DemoBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; / * @author xingshuang */ @RestController @RequestMapping("/serializer") public class S7SerializerComController { 
    @Autowired private S7Serializer s7Serializer; @GetMapping("/bean") public ResponseEntity<DemoBean> demoBean() { 
    DemoBean bean = this.s7Serializer.read(DemoBean.class); return ResponseEntity.ok(bean); } } 
小讯
上一篇 2025-03-22 23:24
下一篇 2025-03-06 13:56

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/59435.html