001package jmri.jmrix.can.cbus;
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 jmri.jmrix.can.CanReply;
012
013/**
014 * Provide an Ops Mode Programmer via a wrapper what works with the CBUS command
015 * station object.
016 * <p>
017 * Functionally, this just creates packets to send via the command station.
018 *
019 * @see jmri.Programmer
020 * @author Andrew Crosland Copyright (C) 2009
021 */
022public class CbusDccOpsModeProgrammer extends CbusDccProgrammer implements AddressedProgrammer {
023
024    int mAddress;
025    boolean mLongAddr;
026
027    public CbusDccOpsModeProgrammer(int pAddress, boolean pLongAddr, jmri.jmrix.can.TrafficController tc) {
028        super(tc);
029        mAddress = pAddress;
030        mLongAddr = pLongAddr;
031    }
032
033    /** 
034     * {@inheritDoc}
035     *
036     * Forward a write request to an ops-mode write operation
037     */
038    @Override
039    synchronized public void writeCV(String CVname, int val, ProgListener p) throws ProgrammerException {
040        final int CV = Integer.parseInt(CVname);
041        log.debug("ops mode write CV={} val={}", CV, val);
042
043        // record state.  COMMANDSENT is just waiting for a reply...
044        useProgrammer(p);
045        _progRead = false;
046        progState = COMMANDSENT;
047        _val = val;
048        _cv = CV;
049
050        // send the programming command
051        tc.sendCanMessage(CbusMessage.getOpsModeWriteCV(mAddress, mLongAddr, CV, val, tc.getCanid()), this);
052        notifyProgListenerEnd(_val, jmri.ProgListener.OK);
053    }
054
055    /** 
056     * {@inheritDoc}
057     */
058    @Override
059    synchronized public void readCV(String CVname, ProgListener p) throws ProgrammerException {
060        log.error("readCV {} not available for MERG CBUS, a query to track would return all locos",CVname);
061        throw new ProgrammerException();
062    }
063
064    /** 
065     * {@inheritDoc}
066     */
067    @Override
068    synchronized public void confirmCV(String CV, int val, ProgListener p) throws ProgrammerException {
069        log.error("confirmCV {} not available for MERG CBUS, a query to track would return all locos",CV);
070        throw new ProgrammerException();
071    }
072
073    /** 
074     * {@inheritDoc}
075     *
076     * Types implemented here.
077     */
078    @Override
079    @Nonnull
080    public List<ProgrammingMode> getSupportedModes() {
081        List<ProgrammingMode> ret = new ArrayList<>(1);
082        ret.add(ProgrammingMode.OPSBYTEMODE);
083        return ret;
084    }
085
086    /** 
087     * {@inheritDoc}
088     */
089    @Override
090    synchronized public void reply(CanReply m) {
091        // We will not see any replies
092    }
093
094    /** 
095     * {@inheritDoc}
096     *
097     * Can this ops-mode programmer read back values?
098     *
099     * @return always false
100     */
101    @Override
102    public boolean getCanRead() {
103        return false;
104    }
105
106    /** 
107     * {@inheritDoc}
108     */
109    @Override
110    public boolean getLongAddress() {
111        return mLongAddr;
112    }
113
114    /** 
115     * {@inheritDoc}
116     */
117    @Override
118    public int getAddressNumber() {
119        return mAddress;
120    }
121
122    /** 
123     * {@inheritDoc}
124     */
125    @Override
126    public String getAddress() {
127        return "" + getAddressNumber() + " " + getLongAddress();
128    }
129
130    /**
131     * Ops-mode programming doesn't put the command station in programming mode,
132     * so we don't have to send an exit-programming command at end. Therefore,
133     * this routine does nothing except to replace the parent routine that does
134     * something.
135     */
136    void cleanup() {
137    }
138    
139    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CbusDccOpsModeProgrammer.class);
140}