Class AbstractAutomaton

  • All Implemented Interfaces:
    java.lang.Runnable
    Direct Known Subclasses:
    SampleAutomaton, SampleAutomaton2, SampleAutomaton3

    public class AbstractAutomaton
    extends java.lang.Object
    implements java.lang.Runnable
    Abstract base for user automaton classes, which provide individual bits of automation.

    Each individual automaton runs in a separate thread, so they can operate independently. This class handles thread creation and scheduling, and provides a number of services for the user code.

    Subclasses provide a "handle()" function, which does the needed work, and optionally a "init()" function. These can use any JMRI resources for input and output. It should not spin on a condition without explicit wait requests; it is more efficient to use the explicit wait services when waiting for some specific condition.

    handle() is executed repeatedly until either the Automate object is halted(), or it returns "false". Returning "true" will just cause handle() to be invoked again, so you can cleanly restart the Automaton by returning from multiple points in the function.

    Since handle() executes outside the GUI thread, it is important that access to GUI (AWT, Swing) objects be scheduled through the various service routines.

    Services are provided by public member functions, described below. They must only be invoked from the init and handle methods, as they must be used in a delayable thread. If invoked from the GUI thread, for example, the program will appear to hang. To help ensure this, a warning will be logged if they are used before the thread starts.

    For general use, e.g. in scripts, the most useful functions are:

    Although this is named an "Abstract" class, it's actually concrete so scripts can easily use some of the methods.

    • Nested Class Summary

      Nested Classes 
      Modifier and Type Class Description
      class  AbstractAutomaton.MsgFrame
      Internal class to show a Frame
    • Method Summary

      All Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      (package private) void defaultName()  
      (package private) void done()
      Part of the internal implementation; not for general use.
      int getCount()
      Get the number of times the handle routine has executed.
      java.lang.String getName()
      Get the thread name.
      DccThrottle getThrottle​(int address, boolean longAddress)  
      DccThrottle getThrottle​(int address, boolean longAddress, int waitSecs)
      Obtains a DCC throttle, including waiting for the command station response.
      DccThrottle getThrottle​(BasicRosterEntry re)  
      DccThrottle getThrottle​(BasicRosterEntry re, int waitSecs)
      Obtains a DCC throttle, including waiting for the command station response.
      protected boolean handle()
      User-provided main routine.
      protected void init()
      User-provided initialization routine.
      boolean isRunning()  
      boolean isWaiting()
      Indicates that object is waiting on a waitSomething call.
      int readServiceModeCV​(java.lang.String CV)
      Read a CV on the service track, including waiting for completion.
      void run()
      Part of the implementation; not for general use.
      void setName​(java.lang.String name)
      Update the name of this object.
      void setTurnouts​(Turnout[] closed, Turnout[] thrown)
      Convenience function to set a bunch of turnouts and wait until they are all in a consistent state
      void start()
      Start this automat processing.
      void stop()
      Stop the thread immediately.
      protected void wait​(int milliseconds)
      Part of the internal implementation, not intended for users.
      void waitChange​(NamedBean[] mInputs)
      Wait forever for one of a list of NamedBeans (sensors, signal heads and/or turnouts) to change, or for a specific time to pass.
      void waitChange​(NamedBean[] mInputs, int maxDelay)
      Wait, up to a specified time, for one of a list of NamedBeans (sensors, signal heads and/or turnouts) to change their state.
      void waitChangePrecheck​(NamedBean[] mInputs)
      Wait forever for one of a list of NamedBeans (sensors, signal heads and/or turnouts) to change, or for a specific time to pass.
      void waitMsec​(int milliseconds)
      Wait for a specified time and then return control.
      void waitSensorActive​(Sensor mSensor)
      Wait for a sensor to be active.
      void waitSensorActive​(Sensor[] mSensors)
      Wait for one of a list of sensors to be be active.
      int waitSensorChange​(int mState, Sensor mSensor)
      Wait for a sensor to change state.
      void waitSensorChange​(Sensor[] mSensors)
      Wait for one of an array of sensors to change.
      void waitSensorInactive​(Sensor mSensor)
      Wait for a sensor to be inactive.
      void waitSensorInactive​(Sensor[] mSensors)
      Wait for one of a list of sensors to be be inactive.
      void waitSensorState​(Sensor[] mSensors, int state)
      Wait for one of a list of sensors to be be in a selected state.
      void waitSensorState​(Sensor mSensor, int state)
      Internal service routine to wait for one sensor to be in (or become in) a specific state.
      void waitSignalHeadState​(SignalHead mSignalHead, int state)
      Internal service routine to wait for one SignalHead to be in (or become in) a specific state.
      void waitSignalMastState​(SignalMast mSignalMast, java.lang.String aspect)
      Internal service routine to wait for one signal mast to be showing a specific aspect
      void waitTurnoutConsistent​(Turnout[] mTurnouts)
      Wait for a list of turnouts to all be in a consistent state
      void waitWarrantBlock​(Warrant warrant, java.lang.String block, boolean occupied)
      Wait for a warrant to enter a named block.
      java.lang.String waitWarrantBlockChange​(Warrant warrant)
      Wait for a warrant to either enter a new block or to stop running.
      void waitWarrantRunState​(Warrant warrant, int state)
      Wait for a warrant to change into or out of running state.
      boolean writeOpsModeCV​(java.lang.String CV, int value, boolean longAddress, int loco)
      Write a CV in ops mode, including waiting for completion.
      boolean writeServiceModeCV​(java.lang.String CV, int value)
      Write a CV on the service track, including waiting for completion.
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Method Detail

      • start

        public void start()
        Start this automat processing.

        Overrides the superclass method to do local accounting.

      • run

        public void run()
        Part of the implementation; not for general use.

        This is invoked on currentThread.

        Specified by:
        run in interface java.lang.Runnable
      • stop

        public void stop()
        Stop the thread immediately.

        Overrides superclass method to handle local accounting.

      • done

        void done()
        Part of the internal implementation; not for general use.

        Common internal end-time processing

      • getCount

        public int getCount()
        Get the number of times the handle routine has executed.

        Used by classes such as jmri.jmrit.automat.monitor to monitor progress.

        Returns:
        the number of times handle() has been called on this AbstractAutomation
      • getName

        public java.lang.String getName()
        Get the thread name. Used by classes monitoring this AbstractAutomation, such as jmri.jmrit.automat.monitor.
        Returns:
        the name of this thread
      • setName

        public void setName​(java.lang.String name)
        Update the name of this object.

        name is not a bound parameter, so changes are not notified to listeners.

        Parameters:
        name - the new name
        See Also:
        getName()
      • init

        protected void init()
        User-provided initialization routine.

        This is called exactly once for each object created. This is where you put all the code that needs to be run when your object starts up: Finding sensors and turnouts, getting a throttle, etc.

      • handle

        protected boolean handle()
        User-provided main routine.

        This is run repeatedly until it signals the end by returning false. Many automata are intended to run forever, and will always return true.

        Returns:
        false to terminate the automaton, for example due to an error.
      • waitMsec

        public void waitMsec​(int milliseconds)
        Wait for a specified time and then return control.
        Parameters:
        milliseconds - the number of milliseconds to wait
      • isWaiting

        public boolean isWaiting()
        Indicates that object is waiting on a waitSomething call.

        Specifically, the wait has progressed far enough that any change to the waited-on-condition will be detected.

        Returns:
        true if waiting; false otherwise
      • wait

        protected void wait​(int milliseconds)
        Part of the internal implementation, not intended for users.

        This handles exceptions internally, so they needn't clutter up the code. Note that the current implementation doesn't guarantee the time, either high or low.

        Because of the way Jython access handles synchronization, this is explicitly synchronized internally.

        Parameters:
        milliseconds - the number of milliseconds to wait
      • waitSensorChange

        public int waitSensorChange​(int mState,
                                    Sensor mSensor)
        Wait for a sensor to change state.

        The current (OK) state of the Sensor is passed to avoid a possible race condition. The new state is returned for a similar reason.

        This works by registering a listener, which is likely to run in another thread. That listener then interrupts the automaton's thread, who confirms the change.

        Parameters:
        mState - Current state of the sensor
        mSensor - Sensor to watch
        Returns:
        newly detected Sensor state
      • waitSensorActive

        public void waitSensorActive​(Sensor mSensor)
        Wait for a sensor to be active. (Returns immediately if already active)
        Parameters:
        mSensor - Sensor to watch
      • waitSensorInactive

        public void waitSensorInactive​(Sensor mSensor)
        Wait for a sensor to be inactive. (Returns immediately if already inactive)
        Parameters:
        mSensor - Sensor to watch
      • waitSensorState

        public void waitSensorState​(Sensor mSensor,
                                    int state)
        Internal service routine to wait for one sensor to be in (or become in) a specific state.

        Used by waitSensorActive and waitSensorInactive

        This works by registering a listener, which is likely to run in another thread. That listener then interrupts this thread to confirm the change.

        Parameters:
        mSensor - the sensor to wait for
        state - the expected state
      • waitSensorInactive

        public void waitSensorInactive​(@Nonnull
                                       Sensor[] mSensors)
        Wait for one of a list of sensors to be be inactive.
        Parameters:
        mSensors - sensors to wait on
      • waitSensorActive

        public void waitSensorActive​(@Nonnull
                                     Sensor[] mSensors)
        Wait for one of a list of sensors to be be active.
        Parameters:
        mSensors - sensors to wait on
      • waitSensorState

        public void waitSensorState​(@Nonnull
                                    Sensor[] mSensors,
                                    int state)
        Wait for one of a list of sensors to be be in a selected state.

        This works by registering a listener, which is likely to run in another thread. That listener then interrupts the automaton's thread, who confirms the change.

        Parameters:
        mSensors - Array of sensors to watch
        state - State to check (static value from jmri.Sensors)
      • waitSignalHeadState

        public void waitSignalHeadState​(SignalHead mSignalHead,
                                        int state)
        Internal service routine to wait for one SignalHead to be in (or become in) a specific state.

        This works by registering a listener, which is likely to run in another thread. That listener then interrupts this thread to confirm the change.

        Parameters:
        mSignalHead - the signal head to wait for
        state - the expected state
      • waitSignalMastState

        public void waitSignalMastState​(@Nonnull
                                        SignalMast mSignalMast,
                                        @Nonnull
                                        java.lang.String aspect)
        Internal service routine to wait for one signal mast to be showing a specific aspect

        This works by registering a listener, which is likely to run in another thread. That listener then interrupts this thread to confirm the change.

        Parameters:
        mSignalMast - the mast to wait for
        aspect - the expected aspect
      • waitWarrantRunState

        public void waitWarrantRunState​(@Nonnull
                                        Warrant warrant,
                                        int state)
        Wait for a warrant to change into or out of running state.

        This works by registering a listener, which is likely to run in another thread. That listener then interrupts the automaton's thread, who confirms the change.

        Parameters:
        warrant - The name of the warrant to watch
        state - State to check (static value from jmri.logix.warrant)
      • waitWarrantBlock

        public void waitWarrantBlock​(@Nonnull
                                     Warrant warrant,
                                     @Nonnull
                                     java.lang.String block,
                                     boolean occupied)
        Wait for a warrant to enter a named block.

        This works by registering a listener, which is likely to run in another thread. That listener then interrupts this thread to confirm the change.

        Parameters:
        warrant - The name of the warrant to watch
        block - block to check
        occupied - Determines whether to wait for the block to become occupied or unoccupied
      • waitWarrantBlockChange

        public java.lang.String waitWarrantBlockChange​(@Nonnull
                                                       Warrant warrant)
        Wait for a warrant to either enter a new block or to stop running.

        This works by registering a listener, which is likely to run in another thread. That listener then interrupts the automaton's thread, who confirms the change.

        Parameters:
        warrant - The name of the warrant to watch
        Returns:
        The name of the block that was entered or null if the warrant is no longer running.
      • waitTurnoutConsistent

        public void waitTurnoutConsistent​(@Nonnull
                                          Turnout[] mTurnouts)
        Wait for a list of turnouts to all be in a consistent state

        This works by registering a listener, which is likely to run in another thread. That listener then interrupts the automaton's thread, who confirms the change.

        Parameters:
        mTurnouts - list of turnouts to watch
      • setTurnouts

        public void setTurnouts​(@Nonnull
                                Turnout[] closed,
                                @Nonnull
                                Turnout[] thrown)
        Convenience function to set a bunch of turnouts and wait until they are all in a consistent state
        Parameters:
        closed - turnouts to set to closed state
        thrown - turnouts to set to thrown state
      • waitChange

        public void waitChange​(@Nonnull
                               NamedBean[] mInputs,
                               int maxDelay)
        Wait, up to a specified time, for one of a list of NamedBeans (sensors, signal heads and/or turnouts) to change their state.

        Registers a listener on each of the NamedBeans listed. The listener is likely to run in another thread. Each fired listener then queues a check to the automaton's thread.

        Parameters:
        mInputs - Array of NamedBeans to watch
        maxDelay - maximum amount of time (milliseconds) to wait before continuing anyway. -1 means forever
      • waitChangePrecheck

        public void waitChangePrecheck​(NamedBean[] mInputs)
        Wait forever for one of a list of NamedBeans (sensors, signal heads and/or turnouts) to change, or for a specific time to pass.
        Parameters:
        mInputs - Array of NamedBeans to watch
      • waitChange

        public void waitChange​(NamedBean[] mInputs)
        Wait forever for one of a list of NamedBeans (sensors, signal heads and/or turnouts) to change, or for a specific time to pass.
        Parameters:
        mInputs - Array of NamedBeans to watch
      • waitSensorChange

        public void waitSensorChange​(Sensor[] mSensors)
        Wait for one of an array of sensors to change.

        This is an older method, now superceded by waitChange, which can wait for any NamedBean.

        Parameters:
        mSensors - Array of sensors to watch
      • getThrottle

        public DccThrottle getThrottle​(int address,
                                       boolean longAddress,
                                       int waitSecs)
        Obtains a DCC throttle, including waiting for the command station response.
        Parameters:
        address - Numeric address value
        longAddress - true if this is a long address, false for a short address
        waitSecs - number of seconds to wait for throttle to acquire before returning null
        Returns:
        A usable throttle, or null if error
      • getThrottle

        public DccThrottle getThrottle​(BasicRosterEntry re,
                                       int waitSecs)
        Obtains a DCC throttle, including waiting for the command station response.
        Parameters:
        re - specifies the desired locomotive
        waitSecs - number of seconds to wait for throttle to acquire before returning null
        Returns:
        A usable throttle, or null if error
      • writeServiceModeCV

        public boolean writeServiceModeCV​(java.lang.String CV,
                                          int value)
        Write a CV on the service track, including waiting for completion.
        Parameters:
        CV - Number 1 through 512
        value - Value 0-255 to be written
        Returns:
        true if completed OK
      • readServiceModeCV

        public int readServiceModeCV​(java.lang.String CV)
        Read a CV on the service track, including waiting for completion.
        Parameters:
        CV - Number 1 through 512
        Returns:
        -1 if error, else value
      • writeOpsModeCV

        public boolean writeOpsModeCV​(java.lang.String CV,
                                      int value,
                                      boolean longAddress,
                                      int loco)
        Write a CV in ops mode, including waiting for completion.
        Parameters:
        CV - Number 1 through 512
        value - 0-255 value to be written
        loco - Locomotive decoder address
        longAddress - true is the locomotive is using a long address
        Returns:
        true if completed OK