java使用S7Connector进行西门子设备读写点位。
S7Connector本质上是一个利用socket发送tcp报文,接受报文的过程。读写都是先发一小段读写标识的标识(参见TCPConnection的exchange方法)我需要操作数据,然后进行读取/写入。
本文中所有读写操作都在一个DB区内。
POM 坐标:
<dependency>
<groupId>com.github.s7connector</groupId>
<artifactId>s7connector</artifactId>
<version>2.1</version>
</dependency>
1、建立实体,在读写数据过程中,一个实体代表你这次要读的所有点位(原因后面解析会见到)。当然在写数据时可以使用写一个或多个点位(对应pojo中的某一个字段,比如DBX00)的方式进行写.
实体主要的作用就是用来寻址,确认读的位置和要读的块数(blocksize)
public class PlcToAgvVo {
@S7Variable(type=S7Type.BOOL,byteOffset = 0,bitOffset = 0)//Type是这个点位的长度,对应jar包中变量blocksize,byteOffset指位偏移,bitOffset指第几个bit.
public Boolean DBX00;//bool型的值不要用private
@S7Variable(type=S7Type.BOOL,byteOffset = 0,bitOffset = 1)
public Boolean DBX01;
}
2、创建连接器 S7Connector
类成员变量:
private S7Connector connector;//接口有两个实现方法:S7BaseConnection、S7TCPConnection。
读方法中:
this.connector = S7ConnectorFactory.buildTCPConnector().
withHost(ip).//PLC设备IP
withPort(Integer.parseInt(port)).//PLC设备端口
withRack(0).withSlot(0).//固定
withTimeout(3000).//超时时间
build();//build方法返回S7TCPConnection对象。
3、创建序列化对象 S7Serializer
S7Serializer serializer =S7SerializerFactory.buildSerializer(this.connector);
4、进行读操作:
PlcToAgvVo plcdb1 = serializer.dispense(PlcToAgvVo.class, DB_NUM, BYTE_OFFSET);//这里dispense方法,传入实体类型,DB_NUM是设备的DB区,BYTE_OFFSET,默认设为0.
//需要指定PLC某个DB区某个偏移量最后读取指定Blocksize。传入了实体类,底层原理使用了反射获取这个类blocksize,blocksize根据实体变量类型也就是第一步的Type确定的。
//注意到返回一个实体,那么可以知道一次性读出实体的所有位置的数据。需要一个一个读的话,有两种方式可以考虑
//1、一次性读出一个实体,通过get字段的方式,获取一个字段
//2、改写dispense方法。思路就是S7Serializer实现这个接口,然后在调用S7connector的read方法时,传入,一个点位的blocksize.返回一个 byte[] buffer。这样,参考extactBytes方法,获取指定数据,
// 获取blocksize方法可以参考BeanParser的parser方法。
5、进行写操作:
AgvToPlcVo plcdata =new AgvToPlcVo();
plcdata.setDBX00(true);//写一个点位
serializer.store(plcdata,DB_NUM, BYTE_OFFSET);//使用store方法,参数的意义与读方法一致,写也是以一个实体为单位的,
注意:
1、关于把S7Connector做成连接池,初始化的时候用一个MAP去盛。会出现部分写数据失效的情况,具体原因未知(实际生产出现过)
2、使用Springcloud的定时任务去定时读的时候,会出现Connection reset by peer的情况。主要是读操作握手协议中往socket的输出流写读报文失败。需要主动调用S7Connector的close方法进行套接字的关闭操作。这也可能是连接池出现不可靠写的原因。
具体可参考 2.1、PLCinterface的read方法在0.5秒内没读到数据报的连接被重置。
2.2、TCPConnection的exchange方法在写的时候没有写成功