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