![JAR search and dependency download from the Maven repository](/logo.png)
org.jpac.plc.LobRxTx Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of elbfisch.core Show documentation
Show all versions of elbfisch.core Show documentation
Open-source runtime system for component-based implementation of automation solutions with Java
The newest version!
/**
* PROJECT : jPac PLC communication library
* MODULE : LobRxTx.java
* VERSION : -
* DATE : -
* PURPOSE :
* AUTHOR : Bernd Schuster, MSK Gesellschaft fuer Automatisierung mbH, Schenefeld
* REMARKS : -
* CHANGES : CH#n
*
* This file is part of the jPac process automation controller.
* jPac is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* jPac is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the jPac If not, see .
*/
package org.jpac.plc;
import io.netty.buffer.ByteBuf;
import java.io.IOException;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
import org.jpac.IndexOutOfRangeException;
import org.jpac.Value;
import org.jpac.plc.Request.DATATYPE;
/**
* Used to transfer a large data item between the java application and the plc or other device.
* "Large" means, that the size of the data item exceeds the maximum pdu size,
* which is the size of data which can be transferred by a
* single transaction.
* For transfer, large data items are splitted into smaller chunks of data,
* which then are transferred sequentially within multiple transactions.
* CAUTION: During this transmission sequence, the data will be inconsistent on
* the partcular receiving side (critical section). Make sure, that the software
* of the receiving side waits until the transmission completed, before
* processing the data
*/
public class LobRxTx implements Value{
static Logger Log = LoggerFactory.getLogger("jpac.plc");
protected Connection conn;
protected Data data;
protected WriteRequest txReq;
protected ReadRequest rxReq;
protected TransmitTransaction txTrans;
protected ReceiveTransaction rxTrans;
protected Address address;
protected int dataOffset;
/**
* useful in situations, where the instance is part of complex data structure (STRUCT)
* @param conn an open TCP/IP connection to the plc or other device
* @param address the address of the data item inside the plc or other device
* @param dataOffset the byte offset inside data, holding the data item to be exchanged with the plc or other device
* @param data instance of Data used to hold the data item exchanged with the plc or other device.
* @throws IndexOutOfRangeException
*/
public LobRxTx(Connection conn, Address address, int dataOffset, Data data) throws IndexOutOfRangeException{
this.conn = conn;
this.data = data;
this.txReq = null;
this.rxReq = null;
this.txTrans = null;
this.rxTrans = null;
if (address.getBitIndex() != Address.NA || dataOffset < 0)
throw new IndexOutOfRangeException();
this.dataOffset = dataOffset;
this.address = address;
}
public static int getSize(){
throw new UnsupportedOperationException("must be implemented by subclasses !!!!!");
}
/**
* used to write the represented data item to the plc or other device.
* @throws IOException
*/
public void write() throws IOException {
boolean done = false;
boolean requestAssigned = false;
int chunkSize = conn.getMaxTransferLength();
TransmitTransaction trans = getTxTrans();
int txOffset = 0;//remove : address.getByteIndex();
//prepare command (may have been used in previous read, write operations
trans.removeAllRequests();
//and write out the data object in 1 to n chunks of data
try{
WriteRequest req = getWriteRequest();
do{
if (address.getSize() - txOffset > chunkSize){
//prepare a chunk of data to transmit
req.setByteAddress(address.getByteIndex() + txOffset);
req.setDataOffset(dataOffset + txOffset);
req.setDataLength(chunkSize);
txOffset += chunkSize;
}
else{
//prepare the remaining bytes
req.setByteAddress(address.getByteIndex() + txOffset);
req.setDataOffset(dataOffset + txOffset);
req.setDataLength(address.getSize() - txOffset);
done = true;
}
//assign the request to the cmd once
if (!requestAssigned){
try{trans.addRequest(req);
}
catch(TooManyRequestsException exc)
{Log.error("Error:",exc);
throw new IOException();
}
requestAssigned = true;
}
//write the chunk out to the plc or other device
trans.transact();
}
while(!done);
}
catch(Exception exc){
Log.error("Error:",exc);
throw new IOException(exc);
}
//clear command
trans.removeAllRequests();
}
/**
* used to read the represented data item from the plc or other device.
* @throws IOException
*/
public LobRxTx read() throws IOException {
boolean done = false;
boolean requestAssigned = false;
int chunkSize = conn.getMaxTransferLength();
ReceiveTransaction trans = getRxTrans();
int txOffset = 0;
//prepare command (may have been used in previous read, write operations
trans.removeAllRequests();
//and write out the data object in 1 to n chunks of data
try{
ReadRequest req = getReadRequest();
do{
if (address.getSize() - txOffset > chunkSize){
//prepare a chunk of data to transmit
req.setByteAddress(address.getByteIndex() + txOffset);
req.setDataOffset(dataOffset + txOffset);
req.setDataLength(chunkSize);
txOffset += chunkSize;
}
else{
//prepare the remaining bytes
req.setByteAddress(address.getByteIndex() + txOffset);
req.setDataOffset(dataOffset + txOffset);
req.setDataLength(address.getSize() - txOffset);
done = true;
}
//assign the request to the cmd once
if (!requestAssigned){
trans.addRequest(req);
requestAssigned = true;
}
//write the chunk out to the plc or other device
trans.transact();
}
while(!done);
}
catch(Exception exc){
Log.error("Error:",exc);
throw new IOException(exc);
}
//clear command
trans.removeAllRequests();
return this;
}
/**
* adds this LobRxTx to the data items to be written to the plc on next getTxTrans().transact() operation
* multiple writeDeferred() calls for different parts of a complex data item may be issued before transacting them collectively
* CAUTION: the transaction buffer must be cleared before the first writeDeferred() call.
* Intermediate write() operations are not permitted.
* The size of the LobRxtx must not exceed the maximum transfer length of the connection
* somedata.getTxTrans().removeAllRequests();
* ...
* somedata.something.set(...);
* somedata.something.writeDeferred();
* ...
* somedata.somethingelse.set(...);
* somedata.somethingelse.writeDeferred();
* ...
* somedata.getTxTrans().transact();
* @throws IOException
*/
public void writeDeferred() throws IOException{
if (address.getSize() > conn.getMaxTransferLength()){
throw new IOException("size of data structure exceeds max. transfer length: " + getSize() + " > " + conn.getMaxTransferLength());
}
TransmitTransaction trans = getTxTrans();
try{
WriteRequest req = getWriteRequest();
trans.addRequest(req);
}
catch(Exception exc)
{Log.error("Error:",exc);
throw new IOException(exc);
}
}
protected Connection getConnection() {
return conn;
}
public Data getData() {
return data;
}
protected void setData(Data data) {
this.data = data;
}
/**
* returns the {@link WriteRequest}, used to write the data item to the plc or other device
*/
@SuppressWarnings("empty-statement")
public WriteRequest getWriteRequest() throws ValueOutOfRangeException, IndexOutOfRangeException{
Address reqAddress = null;
if (txReq == null){
try{reqAddress = (Address) address.clone();}catch(CloneNotSupportedException exc){};
txReq = getConnection().generateWriteRequest(DATATYPE.BYTE, reqAddress , dataOffset, data);
}
return txReq;
}
/**
* returns the {@link ReadRequest}, used to read the data item from the plc or other device
*/
@SuppressWarnings("empty-statement")
public ReadRequest getReadRequest() throws ValueOutOfRangeException, IndexOutOfRangeException{
Address reqAddress = null;
if (rxReq == null){
try{reqAddress = (Address) address.clone();}catch(CloneNotSupportedException exc){};
rxReq = getConnection().generateReadRequest(DATATYPE.BYTE, reqAddress, dataOffset, data);
}
return rxReq;
}
/**
* @return the txTrans
*/
protected TransmitTransaction getTxTrans() {
if (txTrans == null)
txTrans = conn.generateTransmitTransaction();
return txTrans;
}
/**
* @return the rxTrans
*/
protected ReceiveTransaction getRxTrans() {
if (rxTrans == null)
rxTrans = conn.generateReceiveTransaction();
return rxTrans;
}
public Address getAddress(){
return address;
}
/**
* used to get a copy of this LobRxTx. Copied are it's data item, it's address and it's offset in a containing data LobRxTx
* @param aValue
*/
@Override
public void copy(Value aValue){
this.data.copy(((LobRxTx)aValue).getData());
this.address.copy(((LobRxTx)aValue).getAddress());
this.dataOffset = ((LobRxTx)aValue).dataOffset;
};
/**
* used to check the equality of of this LobRxTx to aValue. Both values a said to be equal, if their type, data, address and offset are identical
* @param aValue
* @return
*/
@Override
public boolean equals(Value aValue){
return aValue instanceof LobRxTx &&
this.data.equals(((LobRxTx)aValue).getData()) &&
this.address.equals(((LobRxTx)aValue).getAddress()) &&
this.dataOffset == ((LobRxTx)aValue).dataOffset;
};
/**
* used to clone this LobRxTx. Cloneing comprises its address, its offset inside a containing data structure and its data
* REMARKS: the connection related properties such like Read-, WriteRequest or the connection itself is not cloned to avoid
* access from several threads. I/O over the connection should be done by the owner of the assigned signal
* @return
* @throws CloneNotSupportedException
*/
@Override
public Value clone() throws CloneNotSupportedException{
LobRxTx clonedLobRxTx = null;
try{
clonedLobRxTx = new LobRxTx(null, (Address) address.clone(), dataOffset, data.clone());
clonedLobRxTx.conn = null;//connection related data not cloned
clonedLobRxTx.rxReq = null;
clonedLobRxTx.rxTrans = null;
clonedLobRxTx.txReq = null;
clonedLobRxTx.txTrans = null;
}
catch(IndexOutOfRangeException exc){
Log.error("Error: ", exc);
}
return clonedLobRxTx;
};
@Override
public Object getValue(){
throw new UnsupportedOperationException();
}
@Override
public void setValue(Object value) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public void setValid(boolean valid) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public boolean isValid() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public void encode(ByteBuf byteBuf) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public void decode(ByteBuf byteBuf) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy