001package jmri.jmrit.automat;
002
003import jmri.InstanceManager;
004import jmri.JmriException;
005import jmri.Programmer;
006import jmri.Sensor;
007import org.slf4j.Logger;
008import org.slf4j.LoggerFactory;
009
010/**
011 * This sample Automaton watches a Sensor, and adjusts the momentum of a
012 * locomotive using ops-mode programming when the sensor state changes.
013 * <p>
014 * The sensor and decoder are hardcoded, as this is an example of just the
015 * Automaton function. Adding a GUI to configure these would be
016 * straight-forward. The values could be passed via the constructor, or the
017 * constructor (which can run in any required thread) could invoke a dialog.
018 * <p>
019 * For test purposes, one of these objects can be created and invoked by a
020 * SampleAutomaton2Action.
021 * <p>
022 * For more information on JMRI support for automation classes, please see the
023 * <a href="http://jmri.org/help/en/html/tools/automation/viaJava.shtml">JMRI
024 * Layout Automation in Java page</a>.
025 *
026 * @author Bob Jacobsen Copyright (C) 2003
027 * @see jmri.jmrit.automat.SampleAutomaton2Action
028 */
029public class SampleAutomaton2 extends AbstractAutomaton {
030
031    /**
032     * References the locomotive decoder to be controlled
033     */
034    Programmer programmer;
035    /**
036     * References the sensor to be monitored
037     */
038    Sensor sensor;
039
040    /**
041     * By default, monitors sensor "31"
042     */
043    String sensorName = "31";
044
045    /**
046     * By default, controls locomotive 1234(long).
047     */
048    int locoNumber = 1234;
049    boolean locoLong = true;
050
051    /**
052     * By default, monitors sensor "32" and controls locomotive 1234(long).
053     *
054     */
055    @Override
056    protected void init() {
057        // get references to sample layout objects
058
059        sensor = InstanceManager.sensorManagerInstance().
060                provideSensor(sensorName);
061
062        programmer = InstanceManager.getDefault(jmri.AddressedProgrammerManager.class)
063                .getAddressedProgrammer(locoLong, locoNumber);
064
065        // set up the initial correlation
066        now = sensor.getKnownState();
067        setMomentum(now);
068    }
069
070    int now;
071
072    /**
073     * Watch "sensor", and when it changes the momentum CV to match.
074     *
075     * @return Always returns true to continue operation
076     */
077    @Override
078    protected boolean handle() {
079        log.debug("Waiting for state change");
080
081        // wait until the sensor changes state
082        waitSensorChange(now, sensor);
083
084        // get new value
085        now = sensor.getKnownState();
086        log.debug("Found new state: {}", now);
087
088        // match the decoder's momentum
089        setMomentum(now);
090
091        return true;   // never terminate voluntarily
092    }
093
094    /**
095     * Set CV3, acceleration momentum, to match the sensor state. When the
096     * sensor is active, set the momentum to 30; when inactive, set the momentum
097     * to 0.
098     *
099     * @param now The current value of the sensor state.
100     */
101    void setMomentum(int now) {
102        try {
103            if (now == Sensor.ACTIVE) {
104                programmer.writeCV("3", 30, null);
105            } else {
106                programmer.writeCV("3", 0, null);
107            }
108        } catch (JmriException e) {
109            log.error("exception setting turnout", e);
110        }
111    }
112
113    // initialize logging
114    private final static Logger log = LoggerFactory.getLogger(SampleAutomaton2.class);
115}