001package jmri.jmrix.sprog;
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;
011
012/**
013 * Provide an Ops Mode Programmer via a wrapper what works with the SPROG
014 * command station object.
015 * <p>
016 * Functionally, this just creates packets to send via the command station.
017 *
018 * @see jmri.Programmer
019 * @author Andrew Crosland Copyright (C) 2006
020 */
021public class SprogOpsModeProgrammer extends SprogProgrammer implements AddressedProgrammer {
022
023    int mAddress;
024    boolean mLongAddr;
025    private SprogSystemConnectionMemo _memo = null;
026
027    public SprogOpsModeProgrammer(int pAddress, boolean pLongAddr, SprogSystemConnectionMemo memo) {
028        super(memo);
029        mAddress = pAddress;
030        mLongAddr = pLongAddr;
031        _memo = memo;
032    }
033
034    /** 
035     * {@inheritDoc}
036     *
037     * Forward a write request to an ops-mode write operation
038     */
039    @Override
040    synchronized public void writeCV(String CVname, int val, ProgListener p) throws ProgrammerException {
041        final int CV = Integer.parseInt(CVname);
042        log.debug("write CV={} val={}", CV, val);
043
044        // record state.  COMMANDSENT is just waiting for a reply...
045        useProgrammer(p);
046        progState = COMMANDSENT;
047        _val = val;
048
049        // Add the packet to the queue rather than send it directly
050        // [AC 23/01/16] Check that there is a free slot for the ops mode packet.
051        // Delay the reply to allow time for the ops mode packet to be sent and prevent all slots from filling up
052        // when writing multiple CVs, e.g. writing a sheet in the comprehensive programmer.
053        if (_memo.getCommandStation().opsModepacket(mAddress, mLongAddr, CV, val) != null) {
054            javax.swing.Timer t = new javax.swing.Timer(250, (java.awt.event.ActionEvent evt)->{notifyProgListenerEnd(_val, jmri.ProgListener.OK);});
055            t.setRepeats(false);
056            t.start();
057        } else {
058            progState = NOTPROGRAMMING;
059            notifyProgListenerEnd(_val, jmri.ProgListener.FailedTimeout);
060        }
061    }
062
063    /** 
064     * {@inheritDoc}
065     */
066    @Override
067    synchronized public void readCV(String CVname, ProgListener p) throws ProgrammerException {
068        // final int CV = Integer.parseInt(CVname);
069        log.error("readCV not available in this protocol");
070        throw new ProgrammerException();
071    }
072
073    /** 
074     * {@inheritDoc}
075     */
076    @Override
077    synchronized public void confirmCV(String CV, int val, ProgListener p) throws ProgrammerException {
078        log.error("confirmCV not available in this protocol");
079        throw new ProgrammerException();
080    }
081
082    /** 
083     * {@inheritDoc}
084     *
085     * Types implemented here.
086     */
087    @Override
088    @Nonnull
089    public List<ProgrammingMode> getSupportedModes() {
090        List<ProgrammingMode> ret = new ArrayList<ProgrammingMode>();
091        ret.add(ProgrammingMode.OPSBYTEMODE);
092        return ret;
093    }
094
095    /** 
096     * {@inheritDoc}
097     */
098    @Override
099    synchronized public void notifyReply(SprogReply m) {
100        // We will not see any replies
101    }
102
103    /** 
104     * {@inheritDoc}
105     *
106     * Can this ops-mode programmer read back values? For now, no, but maybe
107     * later.
108     *
109     * @return always false for now
110     */
111    @Override
112    public boolean getCanRead() {
113        return false;
114    }
115
116    /** 
117     * {@inheritDoc}
118     */
119    @Override
120    public boolean getLongAddress() {
121        return mLongAddr;
122    }
123
124    /** 
125     * {@inheritDoc}
126     */
127    @Override
128    public int getAddressNumber() {
129        return mAddress;
130    }
131
132    /** 
133     * {@inheritDoc}
134     */
135    @Override
136    public String getAddress() {
137        return "" + getAddressNumber() + " " + getLongAddress();
138    }
139
140    /**
141     * Ops-mode programming doesn't put the command station in programming mode,
142     * so we don't have to send an exit-programming command at end. Therefore,
143     * this routine does nothing except to replace the parent routine that does
144     * something.
145     */
146    void cleanup() {
147    }
148
149    // initialize logging
150    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(SprogOpsModeProgrammer.class);
151
152}