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方法在寫的時候沒有寫成功