001package jmri.jmrix.lenz;
002
003import org.slf4j.Logger;
004import org.slf4j.LoggerFactory;
005
006/**
007 * Converts Stream-based I/O to/from XNet messages. The "XNetInterface" side
008 * sends/receives XNetMessage objects. The connection to an XNetPortController is
009 * via a pair of Streams, which then carry sequences of characters for
010 * transmission.
011 * <p>
012 * Messages come to this via the main GUI thread, and are forwarded back to
013 * listeners in that same thread. Reception and transmission are handled in
014 * dedicated threads by RcvHandler and XmtHandler objects. Those are internal
015 * classes defined here. The thread priorities are:
016 * <ul>
017 *   <li> RcvHandler - at highest available priority
018 *   <li> XmtHandler - down one, which is assumed to be above the GUI
019 *   <li> (everything else)
020 * </ul>
021 *
022 * @author Bob Jacobsen Copyright (C) 2001
023 */
024public class XNetPacketizer extends XNetTrafficController {
025
026    public XNetPacketizer(LenzCommandStation pCommandStation) {
027        super(pCommandStation);
028        // The instance method (from XNetTrafficController) is deprecated
029    }
030
031// The methods to implement the XNetInterface
032
033    /**
034     * Forward a preformatted XNetMessage to the actual interface.
035     * <p>
036     * Checksum is computed and overwritten here, then the message is converted
037     * to a byte array and queue for transmission
038     *
039     * @param m Message to send; will be updated with CRC
040     */
041    @Override
042    public void sendXNetMessage(XNetMessage m, XNetListener reply) {
043        if (m.length() != 0) {
044            sendMessage(m, reply);
045            java.lang.Thread.yield();
046        }
047    }
048
049    /**
050     * Add trailer to the outgoing byte stream. This version adds the checksum
051     * to the last byte.
052     *
053     * @param msg    The output byte stream
054     * @param offset the first byte not yet used
055     */
056    @Override
057    protected void addTrailerToOutput(byte[] msg, int offset, jmri.jmrix.AbstractMRMessage m) {
058        if (m.getNumDataElements() == 0) {
059            return;
060        }
061        ((XNetMessage) m).setParity();
062        msg[offset - 1] = (byte) m.getElement(m.getNumDataElements() - 1);
063    }
064
065    /**
066     * {@inheritDoc}
067     */
068    @Override
069    public boolean portReadyToSend(jmri.jmrix.AbstractPortController p) {
070        if( !(p instanceof XNetPortController)) {
071            return false;
072        }
073        if (((XNetPortController) p).okToSend()) {
074            ((XNetPortController) p).setOutputBufferEmpty(false);
075            return true;
076        } else {
077            log.debug("XpressNet port not ready to receive");
078            return false;
079        }
080    }
081
082    private static final Logger log = LoggerFactory.getLogger(XNetPacketizer.class);
083
084}