001package jmri.jmrix.can.adapters.loopback;
002
003import jmri.jmrix.AbstractMRListener;
004import jmri.jmrix.AbstractMRMessage;
005import jmri.jmrix.AbstractMRReply;
006import jmri.jmrix.can.CanListener;
007import jmri.jmrix.can.CanMessage;
008import jmri.jmrix.can.CanReply;
009import org.slf4j.Logger;
010import org.slf4j.LoggerFactory;
011
012/**
013 * Traffic controller for loopback CAN simulation.
014 *
015 * @author Bob Jacobsen Copyright (C) 2008
016 */
017public class LoopbackTrafficController extends jmri.jmrix.can.TrafficController {
018
019    public LoopbackTrafficController() {
020        super();
021    }
022
023    protected jmri.jmrix.can.CanSystemConnectionMemo adaptermemo;
024
025    /**
026     * Forward a CanMessage to all registered CanInterface listeners.
027     * {@inheritDoc}
028     */
029    @Override
030    protected void forwardMessage(AbstractMRListener client, AbstractMRMessage m) {
031        ((CanListener) client).message((CanMessage) m);
032    }
033
034    /**
035     * Forward a CanReply to all registered CanInterface listeners.
036     * {@inheritDoc}
037     */
038    @Override
039    protected void forwardReply(AbstractMRListener client, AbstractMRReply r) {
040        ((CanListener) client).reply((CanReply) r);
041    }
042
043    public boolean isBootMode() {
044        return false;
045    }
046
047    /**
048     * Forward a preformatted message to the actual interface.
049     * {@inheritDoc}
050     */
051    @Override
052    public void sendCanMessage(CanMessage m, CanListener reply) {
053        log.debug("TrafficController sendCanMessage() {}", m.toString());
054        notifyMessage(m, reply);
055    }
056
057    /**
058     * Forward a preformatted reply to the actual interface.
059     * {@inheritDoc}
060     */
061    @Override
062    public void sendCanReply(CanReply r, CanListener reply) {
063        log.debug("TrafficController sendCanReply() {}", r.toString());
064        notifyReply(r, reply);
065    }
066
067    /**
068     * Add trailer to the outgoing byte stream.
069     *
070     * @param msg    The output byte stream
071     * @param offset the first byte not yet used
072     */
073    @Override
074    protected void addTrailerToOutput(byte[] msg, int offset, AbstractMRMessage m) {
075    }
076
077    /**
078     * Determine how many bytes the entire message will take, including
079     * space for header and trailer
080     *
081     * @param m The message to be sent
082     * @return Number of bytes
083     */
084    @Override
085    protected int lengthOfByteStream(AbstractMRMessage m) {
086        return m.getNumDataElements();
087    }
088
089    // New message for hardware protocol
090    @Override
091    protected AbstractMRMessage newMessage() {
092        log.debug("New CanMessage created");
093        return new CanMessage(getCanid());
094    }
095
096    /**
097     * Make a CanReply from a system-specific reply.
098     * loop back returns null.
099     * {@inheritDoc}
100     */
101    @Override
102    public CanReply decodeFromHardware(AbstractMRReply m) {
103        log.error("decodeFromHardware unexpected");
104        return null;
105    }
106
107    /**
108     * Encode a CanMessage for the hardware.
109     * loop back returns null.
110     * {@inheritDoc}
111     */
112    @Override
113    public AbstractMRMessage encodeForHardware(CanMessage m) {
114        log.error("encodeForHardware unexpected");
115        return null;
116    }
117
118    // New reply from hardware
119    @Override
120    protected AbstractMRReply newReply() {
121        log.debug("New CanReply created");
122        return new CanReply();
123    }
124
125    /**
126     * Dummy; loopback doesn't parse serial messages.
127     * {@inheritDoc}
128     */
129    @Override
130    protected boolean endOfMessage(AbstractMRReply r) {
131        log.error("endOfMessage unexpected");
132        return true;
133    }
134
135    private final static Logger log = LoggerFactory.getLogger(LoopbackTrafficController.class);
136
137}