001package jmri.jmrix.tams;
002
003import java.util.ArrayList;
004import java.util.List;
005import javax.annotation.Nonnull;
006
007import jmri.AddressedProgrammer;
008import jmri.ProgListener;
009import jmri.ProgrammerException;
010import jmri.ProgrammingMode;
011import org.slf4j.Logger;
012import org.slf4j.LoggerFactory;
013
014/**
015 * Provide an Ops Mode Programmer via a wrapper what works with the TAMS command
016 * station object.
017 * <p>
018 * Functionally, this just creates packets to send via the command station.
019 *
020 * @see jmri.Programmer Based on work by Bob Jacobsen
021 * @author Kevin Dickerson Copyright (C) 2012
022 */
023public class TamsOpsModeProgrammer extends TamsProgrammer implements AddressedProgrammer {
024
025    int mAddress;
026    boolean mLongAddr;
027
028    public TamsOpsModeProgrammer(TamsTrafficController tc, int pAddress, boolean pLongAddr) {
029        super(tc);
030        log.debug("TAMs ops mode programmer {} {}", pAddress, pLongAddr);
031        mAddress = pAddress;
032        mLongAddr = pLongAddr;
033    }
034
035    /**
036     * {@inheritDoc}
037     *
038     * Forward a write request to an ops-mode write operation
039     */
040    @Override
041    public synchronized void writeCV(String CVname, int val, ProgListener p) throws ProgrammerException {
042        final int CV = Integer.parseInt(CVname);
043        if (log.isDebugEnabled()) {
044            log.debug("write CV={} val={}", CV, val);
045        }
046        useProgrammer(p);
047        _progRead = false;
048        _val = val;
049        _cv = CV;
050        progState = COMMANDSENT;
051
052        // start the error timer
053        startShortTimer();
054
055        // format and send the write message
056        tc.sendTamsMessage(TamsMessage.getWriteOpsModeCVMsg(mAddress, CV, val), this);
057
058    }
059
060    /**
061     * {@inheritDoc}
062     */
063    @Override
064    public synchronized void readCV(String CVname, ProgListener p) throws ProgrammerException {
065        final int CV = Integer.parseInt(CVname);
066        if (log.isDebugEnabled()) {
067            log.debug("read CV={}", CV);
068        }
069        log.error("readCV not available in this protocol");
070        throw new ProgrammerException();
071    }
072
073    /**
074     * {@inheritDoc}
075     */
076    @Override
077    public synchronized void confirmCV(String CV, int val, ProgListener p) throws ProgrammerException {
078        if (log.isDebugEnabled()) {
079            log.debug("confirm CV={}", CV);
080        }
081        log.error("confirmCV not available in this protocol");
082        throw new ProgrammerException();
083    }
084
085    /**
086     * {@inheritDoc}
087     */
088    // add 200mSec between commands, so NCE command station queue doesn't get overrun
089    @Override
090    protected void notifyProgListenerEnd(int value, int status) {
091        if (log.isDebugEnabled()) {
092            log.debug("TamsOpsModeProgrammer adds 200mSec delay to response");
093        }
094        try {
095            wait(200);
096        } catch (InterruptedException e) {
097            log.debug("unexpected exception", e);
098        }
099        super.notifyProgListenerEnd(value, status);
100    }
101
102    /**
103     * {@inheritDoc}
104     */
105    @Override
106    @Nonnull
107    public List<ProgrammingMode> getSupportedModes() {
108        List<ProgrammingMode> ret = new ArrayList<ProgrammingMode>();
109        ret.add(ProgrammingMode.OPSBYTEMODE);
110        return ret;
111    }
112
113    /**
114     * {@inheritDoc}
115     *
116     * Can this ops-mode programmer read back values? For now, no, but maybe
117     * later.
118     *
119     * @return always false for now
120     */
121    @Override
122    public boolean getCanRead() {
123        return false;
124    }
125
126    /**
127     * {@inheritDoc}
128     */
129    @Override
130    public boolean getLongAddress() {
131        return mLongAddr;
132    }
133
134    /**
135     * {@inheritDoc}
136     */
137    @Override
138    public int getAddressNumber() {
139        return mAddress;
140    }
141
142    /**
143     * {@inheritDoc}
144     */
145    @Override
146    public String getAddress() {
147        return "" + getAddressNumber() + " " + getLongAddress();
148    }
149
150    /**
151     * {@inheritDoc}
152     *
153     * Ops-mode programming doesn't put the command station in programming mode,
154     * so we don't have to send an exit-programming command at end. Therefore,
155     * this routine does nothing except to replace the parent routine that does
156     * something.
157     */
158    @Override
159    void cleanup() {
160    }
161
162    // initialize logging
163    private final static Logger log = LoggerFactory.getLogger(TamsOpsModeProgrammer.class);
164
165}