Class AbstractMRTrafficController
- Direct Known Subclasses:
AbstractCanTrafficController,AbstractMRNodeTrafficController,Dcc4PcTrafficController,DCCppTrafficController,EasyDccTrafficController,EcosTrafficController,JMRIClientTrafficController,MarklinTrafficController,NceTrafficController,RfidTrafficController,SerialTrafficController,SerialTrafficController,SRCPTrafficController,TamsTrafficController,XNetTrafficController,Z21TrafficController
Two threads are used for the actual communication. The "Transmit" thread handles pushing characters to the port, and also changing the mode. The "Receive" thread converts characters from the input stream into replies.
The constructor registers a shutdown task to trigger the necessary cleanup code
The internal state machine handles changes of mode, automatic retry of certain messages, time outs, and sending poll messages when otherwise idle.
"Mode" refers to the state of the command station communications. "Normal"
and "Programming" are the two modes, used if the command station requires
messages to go back and forth between them.
The key methods for the basic operation are:
- If needed for formatting outbound messages,
addHeaderToOutput(byte[], AbstractMRMessage)andaddTrailerToOutput(byte[], int, AbstractMRMessage) -
newReply()creates an empty reply message (of the proper concrete type) to fill with incoming data - The
endOfMessage(AbstractMRReply)method is used to parse incoming messages. If it needs information on e.g. the last message sent, that can be stored in member variables byforwardToPort(AbstractMRMessage, AbstractMRListener). forwardMessage(AbstractMRListener, AbstractMRMessage)andforwardReply(AbstractMRListener, AbstractMRReply)handle forwarding of specific types of objects
If your command station requires messages to go in and out of
"programming mode", those should be provided by
enterProgMode() and enterNormalMode().
If you want to poll for information when the line is otherwise idle,
implement pollMessage() and pollReplyHandler().
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprotected static classInternal class to remember the Reply object and destination listener with a reply is received.protected static classInternal class to remember the Message object and destination listener when a message is queued for notification. -
Field Summary
FieldsModifier and TypeFieldDescriptionprotected booleanstatic final intprotected final Vector<AbstractMRListener>protected booleanprotected booleanstatic final intprotected DataInputStreamprotected LinkedList<AbstractMRListener>protected intprotected intprotected intprotected AbstractMRListenerprotected LinkedList<AbstractMRMessage>Messages to be transmitted.protected intstatic final intstatic final intstatic final intprotected OutputStreamstatic final intstatic final intprotected booleanprotected Threadprotected booleanprotected booleanFlag that threads should terminate as soon as they can.protected booleanprotected intstatic final intstatic final intstatic final intprotected longprotected booleanprotected Runnableprotected Thread -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprotected voidAdd a Listener to start of the Listener list.protected intaddHeaderToOutput(byte[] msg, AbstractMRMessage m) Add header to the outgoing byte stream.protected voidAdd a Listener to the Listener list.protected voidaddTrailerToOutput(byte[] msg, int offset, AbstractMRMessage m) Add trailer to the outgoing byte stream.protected booleanOverride in the system specific code if necessaryprotected voidvoidMake connection to an existing PortController object.voidBreak connection to existing PortController object.protected voidExecutes a reply distribution action on the appropriate thread for JMRI.protected abstract booleanprotected abstract AbstractMRMessageSets the system to normal mode during programming while in IDLESTATE.protected abstract AbstractMRMessageSet the system to programming mode.protected intGet the delay (wait time) after enabling the programming track.protected abstract voidforwardMessage(AbstractMRListener client, AbstractMRMessage m) Implement this to forward a specific message type to a protocol-specific listener interface.protected abstract voidforwardReply(AbstractMRListener client, AbstractMRReply m) protected voidforwardToPort(AbstractMRMessage m, AbstractMRListener reply) Actually transmit the next message to the port.for testing purposes, let us be able to find out what the last sender was.Get the port name for this connection from the TrafficController.protected booleanvoidHandle each reply when complete.protected voidbooleanDetermine if the interface is down.protected intDetermine how many bytes the entire message will take, including space for header and trailer.protected voidloadChars(AbstractMRReply msg, DataInputStream istream) Get characters from the input source, and file a message.protected AbstractMRTrafficController.RcvNotifiernewRcvNotifier(AbstractMRReply pMsg, AbstractMRListener pDest, AbstractMRTrafficController pTc) protected abstract AbstractMRReplynewReply()protected voidnotifyMessage(AbstractMRMessage m, AbstractMRListener notMe) Forward a Message to registered listeners.protected voidnotifyReply(AbstractMRReply r, AbstractMRListener dest) Forward a "Reply" from layout to registered listeners.protected abstract AbstractMRMessageInvoked if it's appropriate to do low-priority polling of the command station, this should return the next message to send, or null if the TrafficController should just sleep.protected abstract AbstractMRListenerbooleanCheck if PortController object can be sent to.protected voidprotected voidprotected booleanCheck if the programmer is idle.protected bytereadByteProtected(DataInputStream istream) Read a single byte, protecting against various timeouts, etc.voidHandle incoming characters.protected final voidrecovery()Disconnect and reset the current PortController.protected voidRemove a Listener from the Listener list.protected voidReport an error on the receive loop.protected voidprotected voidsendMessage(AbstractMRMessage m, AbstractMRListener reply) Forward message to the port.protected voidsetAllowUnexpectedReply(boolean expected) Set whether the command station may send messages without a request sent to it.protected voidsetSynchronizeRx(boolean val) booleanstatus()protected voidvoidTerminate the receive and transmit threads.protected voidPermanent loop for the transmit thread.protected voidtransmitWait(int waitTime, int state, String interruptMessage) protected voidunexpectedReplyStateError(int State, String msgString) Log an error message for a message received in an unexpected state.protected voidwaitForStartOfReply(DataInputStream istream) Dummy routine, to be filled by protocols that have to skip some start-of-message characters.protected void
-
Field Details
-
cmdListeners
-
mLastSender
-
mCurrentMode
-
NORMALMODE
- See Also:
-
PROGRAMINGMODE
- See Also:
-
mCurrentState
-
IDLESTATE
- See Also:
-
NOTIFIEDSTATE
- See Also:
-
WAITMSGREPLYSTATE
- See Also:
-
WAITREPLYINPROGMODESTATE
- See Also:
-
WAITREPLYINNORMMODESTATE
- See Also:
-
OKSENDMSGSTATE
- See Also:
-
AUTORETRYSTATE
- See Also:
-
POLLSTATE
- See Also:
-
allowUnexpectedReply
-
msgQueue
Messages to be transmitted. -
listenerQueue
-
replyInDispatch
-
timeoutFlag
-
timeouts
-
flushReceiveChars
-
mWaitBeforePoll
-
waitTimePoll
-
xmtException
-
connectionError
-
controller
-
xmtThread
-
rcvThread
-
xmtRunnable
-
istream
-
ostream
-
rcvException
-
maxRcvExceptionCount
-
threadStopRequest
Flag that threads should terminate as soon as they can.
-
-
Constructor Details
-
AbstractMRTrafficController
public AbstractMRTrafficController()Create a new unnamed MRTrafficController.
-
-
Method Details
-
setSynchronizeRx
-
getSynchronizeRx
-
addListener
Add a Listener to the Listener list.- Parameters:
l- The Listener to be added, not null.
-
addConsoleListener
Add a Listener to start of the Listener list. Intended for use only by system Consoles which may prefer notification before other objects have processed a Message and sent a Reply.- Parameters:
l- The Listener to be added, not null.
-
removeListener
Remove a Listener from the Listener list. The Listener will receive no further notifications.- Parameters:
l- The Listener to be removed.
-
notifyMessage
Forward a Message to registered listeners.- Parameters:
m- Message to be forwarded intactnotMe- One (optional) listener to be skipped, usually because it's the originating object.
-
forwardMessage
Implement this to forward a specific message type to a protocol-specific listener interface. This puts the casting into the concrete class.- Parameters:
client- abstract listener.m- message to forward.
-
pollMessage
Invoked if it's appropriate to do low-priority polling of the command station, this should return the next message to send, or null if the TrafficController should just sleep.- Returns:
- Formatted poll message
-
pollReplyHandler
-
enterProgMode
Set the system to programming mode.- Returns:
- any message that needs to be returned to the Command Station to change modes. If no message is needed, returns null.
- See Also:
-
enterNormalMode
Sets the system to normal mode during programming while in IDLESTATE. IfprogrammerIdle()returns true, enterNormalMode() is called after a timeout.- Returns:
- any message that needs to be returned to the Command Station to change modes. If no message is needed, returns null.
- See Also:
-
programmerIdle
Check if the programmer is idle. Override in the system specific code if necessary (see notes forenterNormalMode().- Returns:
- true if not busy programming
-
enterProgModeDelayTime
Get the delay (wait time) after enabling the programming track. Override in subclass to add a longer delay.- Returns:
- 0 as default delay
-
setAllowUnexpectedReply
Set whether the command station may send messages without a request sent to it.- Parameters:
expected- true to allow messages without a prior request
-
notifyReply
Forward a "Reply" from layout to registered listeners.- Parameters:
r- Reply to be forwarded intactdest- One (optional) listener to be skipped, usually because it's the originating object.
-
forwardReply
-
sendMessage
Forward message to the port. Messages are queued and then the transmission thread is notified.- Parameters:
m- the message to sendreply- the Listener sending the message, often provided as 'this'- See Also:
-
transmitLoop
Permanent loop for the transmit thread. -
transmitWait
-
hasTimeouts
Determine if the interface is down.- Returns:
- timeoutFlag
-
handleTimeout
-
warnOnTimeout
-
resetTimeout
-
addHeaderToOutput
Add header to the outgoing byte stream.- Parameters:
msg- the output byte streamm- Message results- Returns:
- next location in the stream to fill
-
addTrailerToOutput
Add trailer to the outgoing byte stream.- Parameters:
msg- the output byte streamoffset- the first byte not yet usedm- output message to extend
-
lengthOfByteStream
Determine how many bytes the entire message will take, including space for header and trailer.- Parameters:
m- the message to be sent- Returns:
- number of bytes
-
forwardToPort
Actually transmit the next message to the port.- Parameters:
m- the message to sendreply- the Listener sending the message, often provided as 'this'- See Also:
-
connectionWarn
-
portWarn
-
portWarnTCP
-
status
-
connectPort
Make connection to an existing PortController object.- Parameters:
p- the PortController
-
getPortName
Get the port name for this connection from the TrafficController.- Returns:
- the name of the port
-
disconnectPort
Break connection to existing PortController object. Once broken, attempts to send via "message" member will fail.- Parameters:
p- the PortController
-
portReadyToSend
Check if PortController object can be sent to.- Parameters:
p- the PortController- Returns:
- true if ready, false otherwise May throw an Exception.
-
receiveLoop
Handle incoming characters. This is a permanent loop, looking for input messages in character form on the stream connected to the PortController viaconnectPort(AbstractPortController).Each turn of the loop is the receipt of a single message.
-
recovery
Disconnect and reset the current PortController. Invoked at abnormal ending of receiveLoop. -
reportReceiveLoopException
Report an error on the receive loop. Separated so tests can suppress, even though message is asynchronous.- Parameters:
e- Exception encountered at lower level to trigger error, or null
-
newReply
-
endOfMessage
-
waitForStartOfReply
Dummy routine, to be filled by protocols that have to skip some start-of-message characters.- Parameters:
istream- input source- Throws:
IOException- from underlying operations
-
readByteProtected
Read a single byte, protecting against various timeouts, etc.When a port is set to have a receive timeout, some will return zero bytes, an EOFException or a InterruptedIOException at the end of the timeout. In that case, the read() should be repeated to get the next real character.
- Parameters:
istream- stream to read- Returns:
- the byte read
- Throws:
IOException- if unable to read
-
loadChars
Get characters from the input source, and file a message.Returns only when the message is complete.
Only used in the Receive thread.
Handles timeouts on read by ignoring zero-length reads.
- Parameters:
msg- message to fillistream- character source.- Throws:
IOException- when presented by the input source.
-
canReceive
Override in the system specific code if necessary- Returns:
- true if it is okay to buffer receive characters into a reply message. When false, discard char received
-
distributeReply
Executes a reply distribution action on the appropriate thread for JMRI.- Parameters:
r- a runnable typically encapsulating a MRReply and the iteration code needed to send it to all the listeners.
-
handleOneIncomingReply
Handle each reply when complete.(This is public for testing purposes) Runs in the "Receive" thread.
- Throws:
IOException- on error.
-
unexpectedReplyStateError
Log an error message for a message received in an unexpected state.- Parameters:
State- message state.msgString- message string.
-
getLastSender
for testing purposes, let us be able to find out what the last sender was.- Returns:
- last sender, mLastSender.
-
terminate
-
newRcvNotifier
protected AbstractMRTrafficController.RcvNotifier newRcvNotifier(AbstractMRReply pMsg, AbstractMRListener pDest, AbstractMRTrafficController pTc) -
terminateThreads
Terminate the receive and transmit threads.This is intended to be used only by testing subclasses.
-