Java使用S7协议连接西门子PLC1200、1500
1.引入s7包
使用
https://github.com/s7connector/s7connector
<!-- https://mvnrepository.com/artifact/com.github.s7connector/s7connector -->
<dependency>
<groupId>com.github.s7connector</groupId>
<artifactId>s7connector</artifactId>
<version>2.1</version>
</dependency>
2.测试代码(可参考使用)
package 你的包路径;
import com.github.s7connector.api.DaveArea;
import com.github.s7connector.api.S7Connector;
import com.github.s7connector.api.S7Serializer;
import com.github.s7connector.api.factory.S7ConnectorFactory;
import com.github.s7connector.api.factory.S7SerializerFactory;
import junit.framework.TestCase;
import org.apache.commons.lang.StringUtils;
import org.springframework.security.core.parameters.P;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
/**
* 测试PLC通信,使用s7 connectorl,支持西门子plc1200,1500。其他PLC平台请参考使用
* xiaohelong2005@126.com(咨询技术问题可邮件沟通) 湖南一秒智能科技有限公司 湖南长沙
* 更新于20221209
*/
public class s7connectorTest extends TestCase {
public S7Connector initConnect(){
//PLC地址
String ipAddress = "192.168.1.50";
//默认端口
int port = 102;
int rack=0;
int slot=1;
int timeout=10000;
S7Connector s7connector=
S7ConnectorFactory
.buildTCPConnector()
.withHost(ipAddress)
.withPort(port) //optional
.withRack(rack) //optional
.withSlot(slot) //optional
.withTimeout(timeout) //连接超时时间
.build();
S7Serializer s7Serializer2L = S7SerializerFactory.buildSerializer(s7connector);
return s7connector;
}
/**
* 读取PLC中的整型数据
*
**/
public void testReadPlcIntData() {
S7Connector s7Connector = initConnect();
//第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB
//第二个参数:DB块地址,若plc中是DB1000,则填1000
//第三个参数:数据长度
//第四个参数:偏移量
byte[] getBytes = s7Connector.read(DaveArea.DB, 150, 2, 0);
Integer intData = new BigInteger(getBytes).intValue();
System.out.println("getIntData:"+intData);
try {
s7Connector.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 向PLC中写短整型(2字节,对应PLC INT类型)数据
*
**/
public void testWritePlcShortIntData() {
S7Connector s7Connector = initConnect();
//第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB
//第二个参数:DB块地址,若plc中是DB1000,则填1000
//第三个参数:偏移量
//第四个参数:写入的数据 二进制数组byte[]
short data=15;
byte[] bytes = ByteBuffer.allocate(2).putShort(data).array();
System.out.println("bytes length:"+bytes.length);
s7Connector.write(DaveArea.DB,150, 0,bytes);
try {
s7Connector.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 向PLC中写整型(4字节,对应PLC DINT类型)数据
*
**/
public void testWritePlcIntData() {
S7Connector s7Connector = initConnect();
//第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB
//第二个参数:DB块地址,若plc中是DB1000,则填1000
//第三个参数:偏移量
//第四个参数:写入的数据 二进制数组byte[]
int data=15;
byte[] bytes = ByteBuffer.allocate(4).putInt(data).array();
System.out.println("bytes length:"+bytes.length);
s7Connector.write(DaveArea.DB,6, 0,bytes);
try {
s7Connector.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 向PLC中读字符串
约定协议: 对于字符串,第一个字节是总长度值,此值包括标志位,第二个字节是有效数据位,紧跟有效数据字节数。
**/
public void testReadPlcStrData() {
S7Connector s7Connector = initConnect();
//第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB
//第二个参数:DB块地址,若plc中是DB1000,则填1000
//第三个参数:数据长度
//第四个参数:偏移量
byte[] getBytes = s7Connector.read(DaveArea.DB, 150, 10, 20);
String retString="";
if(getBytes!=null&&getBytes.length<3) {
retString= new String(getBytes,StandardCharsets.US_ASCII);
}else if(getBytes!=null)
{
int charCount=Integer.valueOf(getBytes[1]);//第一个字节是总长度,第二个字节是有效字节数,获取有效字节数
StringBuilder stringBuilder=new StringBuilder(charCount);
for(int i=0;i<charCount;i++){
stringBuilder.append((char)getBytes[i+2]);
}
retString=stringBuilder.toString();
}
System.out.println("getStringData:"+retString);
try {
s7Connector.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 向PLC中写字符串
约定协议: 对于字符串,第一个字节是总长度值,此值包括标志位,第二个字节是有效数据位,紧跟有效数据字节数。
**/
public void testWritePlcStrData() {
S7Connector s7Connector = initConnect();
//第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB
//第二个参数:DB块地址,若plc中是DB1000,则填1000
//第三个参数:偏移量
//第四个参数:写入的数据 二进制数组byte[] ,总长度为10的话,有效数据只能是10-8,第一位代表总长,第二位,代表有效数据字节
String str = "59";
int writeStrLength=10;//地址块大小
byte[] writeBytes=new byte[writeStrLength];
writeBytes[0]=(byte)writeStrLength;//写入本字符串块总宽度
str=str.trim();//清除掉两边的空串
int availableEffectCharLength=0;//有效字符数控制
if(str.length()>writeStrLength-2)
{//>writeStrLength-2 截断到最大有效数据位
availableEffectCharLength=writeStrLength-2;
}else{//<=writeStrLength-2
availableEffectCharLength=str.length();
}
writeBytes[1]=(byte)availableEffectCharLength;//写入有效字节数
byte[] strBytes=str.getBytes(StandardCharsets.US_ASCII);
for(int i=0;i<availableEffectCharLength;i++){
writeBytes[i+2]=strBytes[i];
}
s7Connector.write(DaveArea.DB,150, 20,writeBytes);
System.out.println("write str:"+(new String(writeBytes)));
try {
s7Connector.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 读取PLC中的浮点型float(real 4字节)数据
* java float : plc Real 4 字节
* java double : plc LReal 8 字节
**/
public void testReadPlcRealData() {
S7Connector s7Connector = initConnect();
//第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB
//第二个参数:DB块地址,若plc中是DB1000,则填1000
//第三个参数:数据长度
//第四个参数:偏移量
//byte [] bytes = ByteBuffer.allocate(8).putDouble(1729.1729).array();
//byte [] bytes = { 64, -101, 4, -79, 12, -78, -107, -22 };
//System.out.println();
byte[] getBytes = s7Connector.read(DaveArea.DB, 150, 4, 64);
Float getValue = ByteBuffer.wrap(getBytes).getFloat();
System.out.println("getFloatData:"+getValue);
try {
s7Connector.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 读取PLC中的浮点型Double(8字节)数据
* java float : plc Real 4 字节
* java double : plc LReal 8 字节
**/
public void testReadPlcLRealData() {
S7Connector s7Connector = initConnect();
//第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB
//第二个参数:DB块地址,若plc中是DB1000,则填1000
//第三个参数:数据长度
//第四个参数:偏移量
//byte [] bytes = ByteBuffer.allocate(8).putDouble(1729.1729).array();
//byte [] bytes = { 64, -101, 4, -79, 12, -78, -107, -22 };
//System.out.println();
byte[] getBytes = s7Connector.read(DaveArea.DB, 6, 8, 4);
Double getValue = ByteBuffer.wrap(getBytes).getDouble();
System.out.println("getDoubleData:"+getValue);
try {
s7Connector.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 写入PLC中的浮点型数据
* java float : plc Real 4 字节
* java double : plc LReal 8 字节
**/
public void testWritePlcRealData() {
S7Connector s7Connector = initConnect();
//第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB
//第二个参数:DB块地址,若plc中是DB1000,则填1000
//第三个参数:偏移量
//第四个参数:写入的数据 二进制数组byte[]
float data=new Float(5.54);
byte[] bytes = ByteBuffer.allocate(4).putFloat(data).array();
System.out.println("bytes length:"+bytes.length);
s7Connector.write(DaveArea.DB,150, 64,bytes);
try {
s7Connector.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 写入PLC中的浮点型LREAL(java中是double)数据
* java float : plc Real 4 字节
* java double : plc LReal 8 字节
**/
public void testWritePlcLRealData() {
S7Connector s7Connector = initConnect();
//第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB
//第二个参数:DB块地址,若plc中是DB1000,则填1000
//第三个参数:偏移量
//第四个参数:写入的数据 二进制数组byte[]
float data=new Float(15.5);
byte[] bytes = ByteBuffer.allocate(8).putDouble(data).array();
System.out.println("bytes length:"+bytes.length);
s7Connector.write(DaveArea.DB,6, 4,bytes);
try {
s7Connector.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}