Class CipRequest
- java.lang.Object
-
- com.automation_pros.odva.cip.requests.CipRequest
-
- All Implemented Interfaces:
CipReplyConsumer
,CipMessage
,java.io.Externalizable
,java.io.Serializable
- Direct Known Subclasses:
CxMgrReq
,GetAttrListReq
,GetGenericReq
,GetInstAttrListReq
,MultipleReq
public class CipRequest extends java.lang.Object implements java.io.Externalizable, CipMessage, CipReplyConsumer
A CIP Request cannot carry an exception. It has only a target path and a payload. Replies are consumed, reparsed by subclasses, and passed on to registered callbacks.- Author:
- philip
- See Also:
- Serialized Form
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static class
CipRequest.CallbackException
static class
CipRequest.ChainedException
static class
CipRequest.ReplyFuture
A callback object that delivers its asynchronous CipReply to a Future for retrieval or synchronization.
-
Field Summary
Fields Modifier and Type Field Description protected java.lang.Exception
acceptTrace
long
acceptTS
protected java.util.List<CipReplyConsumer>
callbacks
protected java.lang.Exception
creationTrace
long
deadline
protected int
forecastReply
int
maxreply
protected CipPath
path
protected static java.util.concurrent.ScheduledThreadPoolExecutor
scheduler
long
sentTS
static org.slf4j.Logger
sLogger
protected int
svccode
-
Constructor Summary
Constructors Constructor Description CipRequest()
Externalizable types must have a public no-arg constructor.CipRequest(CipPath target, int service)
Construct a new request for a given target and service code.CipRequest(CipPath target, int service, BaseDataType<?> data)
Construct a request from a target, service, and data for the payload.CipRequest(CipPath target, int service, java.nio.ByteBuffer source)
Construct a request from a target, service, and payload buffer.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description void
accept(CipException e)
As a convenience to synchronous services, construct a CIP reply from a CIP Exception.void
accept(CipReply reply)
Applications and routers call this method with the actual reply to pass back up the chain of callers.void
accept(java.nio.ByteBuffer reply)
As a convenience to synchronous services, construct a success CIP reply from a given byte buffer.CipRequest
addCallback(int idx, CipReplyConsumer callback)
Requests are expected to generate a reply some time after submission to an Origin.CipRequest
addCallback(CipReplyConsumer callback)
Requests are expected to generate a reply some time after submission to an Origin.CipRequest.ReplyFuture
addFutureCallback()
int
bytes()
CipRequest
clone()
static CipRequest
decode(java.nio.ByteBuffer source, CipReplyConsumer callback)
Given a byte buffer expected to contain a CIP request in Message Router Request format, targeting a Message Router or in an Unconnected Message Manager, return the decoded request, with the given callback attached, rewrapping UCMM requests.void
forecast(int expectedReply)
java.nio.ByteBuffer
getPayload()
Object services typically want to decode the payload into their own field(s).int
getServiceCode()
CIP messages always have a service code, either requesting or replying.CipReply
getSyncReply(CipMsgProcessor msgproc)
CipReply
getSyncReply(CipObject appContext, int nesting)
CipPath
getTarget()
Obtain the application path in this request.byte[]
payloadBytes()
Encode the message payload for transmission and return it as an array of bytes.int
payloadLength()
Subclasses must override this unless they populate the payload and payloadActual fields.protected java.lang.String
payloadString()
void
put(java.nio.ByteBuffer dest)
Encode the entire message for transmission.void
putPayload(java.nio.ByteBuffer dest)
Subclasses that encode fields into their payloads must override this.void
putSyncReplyPayload(CipMsgProcessor msgproc, java.nio.ByteBuffer dest)
void
putSyncReplyPayload(CipObject appContext, int nesting, java.nio.ByteBuffer dest)
void
readExternal(java.io.ObjectInput in)
CIP requests are deserialized by retrieving the byte array and decoding it directly.int
replyLength()
Subclasses that know how big a reply message will be may override this to enable automatic optimization into multiple request packets.static CipRequest
rewrapRequest(CipRequest req)
Given a request and optional port instance, convert instances that should be one of the subclasses into that subclass.java.util.concurrent.CompletableFuture<CipReply>
service(CipMsgProcessor msgproc)
Execute this request on a generic message processor, typically aPort
or aMessaging Connection
.java.util.concurrent.CompletableFuture<CipReply>
service(CipObject appContext, int nesting)
Execute this request on a given device hierarchy, optionally skipping some leading path elements.protected java.lang.String
serviceName()
CipRequest
set(java.nio.ByteBuffer source)
void
setPayload(java.nio.ByteBuffer source)
Subclasses should override this method to permit reparsing of protocol packets into the desired request type.CipRequest
takeCallbacks(CipRequest other)
When a request is wrapped in another request that will simply hand off the reply, the outer request must take the callbacks of the inner request.byte[]
toBytes()
Encode the entire message for transmission and return it as an array of bytes.java.lang.String
toString()
void
writeExternal(java.io.ObjectOutput out)
CIP requests may be placed "on the wire" in serialized form, but callbacks and any other information that is not explicitly part of the CIP Message Router Request format are discarded.
-
-
-
Field Detail
-
sLogger
public static final org.slf4j.Logger sLogger
-
scheduler
protected static java.util.concurrent.ScheduledThreadPoolExecutor scheduler
-
sentTS
public long sentTS
-
acceptTS
public long acceptTS
-
deadline
public long deadline
-
maxreply
public int maxreply
-
svccode
protected int svccode
-
path
protected CipPath path
-
callbacks
protected java.util.List<CipReplyConsumer> callbacks
-
creationTrace
protected java.lang.Exception creationTrace
-
acceptTrace
protected java.lang.Exception acceptTrace
-
forecastReply
protected int forecastReply
-
-
Constructor Detail
-
CipRequest
public CipRequest()
Externalizable types must have a public no-arg constructor.
-
CipRequest
public CipRequest(CipPath target, int service)
Construct a new request for a given target and service code. Suitable for requests that need no payload or for which the payload generation will be overridden.- Parameters:
target
-service
-
-
CipRequest
public CipRequest(CipPath target, int service, java.nio.ByteBuffer source)
Construct a request from a target, service, and payload buffer. Ideal for parsed requests that will be routed, needing no interpretation of the payload.- Parameters:
target
-service
-source
-
-
CipRequest
public CipRequest(CipPath target, int service, BaseDataType<?> data)
Construct a request from a target, service, and data for the payload.- Parameters:
target
-service
-data
-
-
-
Method Detail
-
rewrapRequest
public static CipRequest rewrapRequest(CipRequest req)
Given a request and optional port instance, convert instances that should be one of the subclasses into that subclass.- Parameters:
req
-- Returns:
-
decode
public static CipRequest decode(java.nio.ByteBuffer source, CipReplyConsumer callback)
Given a byte buffer expected to contain a CIP request in Message Router Request format, targeting a Message Router or in an Unconnected Message Manager, return the decoded request, with the given callback attached, rewrapping UCMM requests.- Parameters:
source
-callback
-- Returns:
-
set
public CipRequest set(java.nio.ByteBuffer source)
-
getTarget
public CipPath getTarget()
Obtain the application path in this request. Unconnected messages may start with one or more port segments for routing.- Returns:
- A list of path segments.
-
getServiceCode
public int getServiceCode()
Description copied from interface:CipMessage
CIP messages always have a service code, either requesting or replying. In the protocol, replies have bit seven turned on. In reply classes implementing this interface, the bit is stripped.- Specified by:
getServiceCode
in interfaceCipMessage
- Returns:
- The unsigned byte service code as an integer.
-
put
public void put(java.nio.ByteBuffer dest)
Description copied from interface:CipMessage
Encode the entire message for transmission.- Specified by:
put
in interfaceCipMessage
- Parameters:
dest
- Destination buffer for the encoded message.
-
bytes
public int bytes()
- Specified by:
bytes
in interfaceCipMessage
- Returns:
- The total byte length of the encoded message.
-
addCallback
public CipRequest addCallback(CipReplyConsumer callback)
Requests are expected to generate a reply some time after submission to an Origin. The caller must add the callbacks that will consume the corresponding reply. For the consumer's convenience, the reply will have this request attached.- Parameters:
callback
-- Returns:
- Returns the request to allow method chaining.
-
addFutureCallback
public CipRequest.ReplyFuture addFutureCallback()
-
addCallback
public CipRequest addCallback(int idx, CipReplyConsumer callback)
Requests are expected to generate a reply some time after submission to an Origin. The caller must add the callbacks that will consume the corresponding reply. For the consumer's convenience, the reply will have this request attached. This overloaded form allows a callback to be inserted at any desired point.- Parameters:
idx
-callback
-- Returns:
- Returns the request to allow method chaining.
-
takeCallbacks
public CipRequest takeCallbacks(CipRequest other)
When a request is wrapped in another request that will simply hand off the reply, the outer request must take the callbacks of the inner request.When such an outer request is unwrapped to process the inner request, the inner request must take the callbacks of the outer request.
- Parameters:
other
-- Returns:
-
clone
public CipRequest clone()
- Overrides:
clone
in classjava.lang.Object
-
accept
public void accept(CipReply reply)
Applications and routers call this method with the actual reply to pass back up the chain of callers. Routers must embed some form of ID code in their protocol packets to associate requests with replies. DeviceNet uses originator node address and a 16-bit transaction ID. Ethernet/IP uses the 64-bit Sender Context field of its encapsulation header. CIP over DF1 uses the 16-bit Transaction Number inside of PCCC encapsulation.- Specified by:
accept
in interfaceCipReplyConsumer
-
accept
public void accept(java.nio.ByteBuffer reply)
As a convenience to synchronous services, construct a success CIP reply from a given byte buffer. Generally not overridden by subclasses.- Parameters:
reply
-
-
accept
public void accept(CipException e)
As a convenience to synchronous services, construct a CIP reply from a CIP Exception. Generally not overridden by subclasses.- Parameters:
e
-
-
service
public java.util.concurrent.CompletableFuture<CipReply> service(CipObject appContext, int nesting)
Execute this request on a given device hierarchy, optionally skipping some leading path elements.- Parameters:
appContext
- The hierarchy root that will execute this request and will will be passed to any nested lookup operations.nesting
- Number of path elements in the request target to skip.- Returns:
- A completable future that can be interrogated for the reply.
-
service
public java.util.concurrent.CompletableFuture<CipReply> service(CipMsgProcessor msgproc)
Execute this request on a generic message processor, typically aPort
or aMessaging Connection
.- Parameters:
msgproc
-- Returns:
- A completable future that can be interrogated for the reply.
-
getSyncReply
public CipReply getSyncReply(CipMsgProcessor msgproc)
-
putSyncReplyPayload
public void putSyncReplyPayload(CipObject appContext, int nesting, java.nio.ByteBuffer dest)
-
putSyncReplyPayload
public void putSyncReplyPayload(CipMsgProcessor msgproc, java.nio.ByteBuffer dest)
-
setPayload
public void setPayload(java.nio.ByteBuffer source)
Subclasses should override this method to permit reparsing of protocol packets into the desired request type.- Specified by:
setPayload
in interfaceCipMessage
- Parameters:
source
- Source buffer containing the encoded new payload.
-
getPayload
public java.nio.ByteBuffer getPayload()
Object services typically want to decode the payload into their own field(s).- Returns:
- A buffer containing the payload ready to read. Callers should deliver it to ByteBuffersSoftCache.release() if known to not be used further.
-
putPayload
public void putPayload(java.nio.ByteBuffer dest)
Subclasses that encode fields into their payloads must override this.- Specified by:
putPayload
in interfaceCipMessage
- Parameters:
dest
- Destination buffer for the encoded payload.
-
payloadLength
public int payloadLength()
Subclasses must override this unless they populate the payload and payloadActual fields.- Specified by:
payloadLength
in interfaceCipMessage
- Returns:
- The byte length of the encoded payload only.
-
replyLength
public int replyLength()
Subclasses that know how big a reply message will be may override this to enable automatic optimization into multiple request packets. Or fill the protected field "forecastReply".- Returns:
-
forecast
public void forecast(int expectedReply)
-
payloadString
protected java.lang.String payloadString()
-
payloadBytes
public byte[] payloadBytes()
Description copied from interface:CipMessage
Encode the message payload for transmission and return it as an array of bytes.- Specified by:
payloadBytes
in interfaceCipMessage
- Returns:
- The encoded payload as a byte array.
-
toBytes
public byte[] toBytes()
Description copied from interface:CipMessage
Encode the entire message for transmission and return it as an array of bytes.- Specified by:
toBytes
in interfaceCipMessage
- Returns:
- The entire encoded message as a byte array.
-
serviceName
protected java.lang.String serviceName()
-
toString
public java.lang.String toString()
- Overrides:
toString
in classjava.lang.Object
-
readExternal
public void readExternal(java.io.ObjectInput in) throws java.io.IOException, java.lang.ClassNotFoundException
CIP requests are deserialized by retrieving the byte array and decoding it directly.- Specified by:
readExternal
in interfacejava.io.Externalizable
- Throws:
java.io.IOException
java.lang.ClassNotFoundException
-
writeExternal
public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException
CIP requests may be placed "on the wire" in serialized form, but callbacks and any other information that is not explicitly part of the CIP Message Router Request format are discarded.- Specified by:
writeExternal
in interfacejava.io.Externalizable
- Throws:
java.io.IOException
-
-