001package jmri.implementation;
002
003import jmri.CommandStation;
004import jmri.InstanceManager;
005import jmri.Turnout;
006import jmri.TurnoutOperator;
007import org.slf4j.Logger;
008import org.slf4j.LoggerFactory;
009
010/**
011 * Concrete subclass of TurnoutOperator for a turnout that has no feedback. This
012 * operator sends raw NMRA accessory decoder packets to the layout instead of
013 * using the built in turnout code. It should be used only with turnouts with
014 * DIRECT, ONESENSOR or TWOSENSOR feedback. This class is based on the
015 * NoFeedbackTurnoutOperator class.
016 *
017 * @author Paul Bender Copyright 2008
018 */
019public class RawTurnoutOperator extends TurnoutOperator {
020
021    long interval;
022    int maxTries;
023    int tries = 0;
024    int address = 0;
025    CommandStation c;
026
027    public RawTurnoutOperator(AbstractTurnout t, long i, int mt) {
028        super(t);
029        String sysName = t.getSystemName();
030        int startAddress = sysName.lastIndexOf("T");
031        address = Integer.parseInt(sysName.substring(startAddress + 1, sysName.length()));
032        String prefix = t.getSystemName().substring(0, startAddress);
033        java.util.List<jmri.CommandStation> connList = jmri.InstanceManager.getList(jmri.CommandStation.class);
034        for (int x = 0; x < connList.size(); x++) {
035            jmri.CommandStation station = connList.get(x);
036            if (station.getSystemPrefix().equals(prefix)) {
037                c = station;
038                break;
039            }
040        }
041        if (c == null) {
042            c = InstanceManager.getNullableDefault(CommandStation.class);
043            log.error("No match against the command station for {}, so will use the default", sysName);
044        }
045        interval = i;
046        maxTries = mt;
047    }
048
049    private void sendCommand() {
050        byte pkt[] = jmri.NmraPacket.accDecoderPkt(address, myTurnout.getCommandedState() == Turnout.CLOSED);
051        c.sendPacket(pkt, 1);
052    }
053
054    /**
055     * Do the autmation for a turnout with no feedback. This means try maxTries
056     * times at an interval of interval. Note the call to operatorCheck each
057     * time we're about to actually do something - if we're no longer the
058     * current operator this throws TurnoutOperatorException which just
059     * terminates the thread.
060     */
061    @Override
062    public void run() {
063        try {
064            operatorCheck();
065            sendCommand();
066            while (++tries < maxTries) {
067                try {
068                    Thread.sleep(interval);
069                } catch (InterruptedException e) {
070                    Thread.currentThread().interrupt(); // retain if needed later
071                }
072                operatorCheck();
073                sendCommand();
074            }
075            myTurnout.setKnownStateToCommanded();
076        } catch (TurnoutOperatorException e) {
077        }
078    }
079
080    private final static Logger log = LoggerFactory.getLogger(RawTurnoutOperator.class);
081}