167 lines
7.2 KiB
Plaintext
167 lines
7.2 KiB
Plaintext
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta name="generator" content="HTML Tidy for HTML5 for Apple macOS version 5.8.0">
|
|
<!-- Copyright Bob Jacobsen, John Plocher 2005, 2006, 2008 -->
|
|
|
|
<title>JMRI: Layout Automation in Java</title><!--#include virtual="/help/en/parts/Style.shtml" -->
|
|
</head>
|
|
<body>
|
|
<!--#include virtual="/help/en/parts/Header.shtml" -->
|
|
|
|
<div id="mBody">
|
|
<!--#include virtual="Sidebar.shtml" -->
|
|
|
|
<div id="mainContent">
|
|
<!-- Page Body -->
|
|
|
|
<h2>JMRI: Layout Automation in Java</h2>
|
|
|
|
<p>The JMRI library provides a very powerful set of tools for automating your layout. If the
|
|
tools built into <a href="../../apps/PanelPro/index.shtml">PanelPro</a> or the <a href=
|
|
"../scripting/index.shtml">scripting capability</a> aren't sufficient to do what you want,
|
|
writing your own control program certainly will be.</p>
|
|
|
|
<p>This page describes the JMRI Java classes that support writing "automation" code in Java.
|
|
That's things like operating signals, running trains, and even subtle things like changing
|
|
decoder sound volumes when a train goes into a tunnel.</p>
|
|
|
|
<p>Note that you can also write your automation code using Jython as <a href=
|
|
"../scripting/index.shtml">JMRI "scripts"</a>. For many purposes, this can be simpler because
|
|
it's more interactive and has better debugging support. Java is really best for large and/or
|
|
complex cases, or if you're writing something that you want to eventually contribute to JMRI
|
|
itself.</p>
|
|
|
|
<dl>
|
|
<dt class="left">Introduction</dt>
|
|
|
|
<dd class="first">
|
|
<p>The "Automat" class provides an easy way to write Java automation for your layout
|
|
using JMRI.</p>
|
|
|
|
<p>The key class is <a href=
|
|
"https://www.jmri.org/JavaDoc/doc/jmri/jmrit/automat/AbstractAutomaton.html">AbstractAutomaton</a>,
|
|
which provides threading support to simplify custom automation code.</p>
|
|
|
|
<p>Key aspect: These run in a separate thread, so they can wait for something to happen
|
|
while the rest of the program proceeds. Effectively, each Automat is a separate program
|
|
running when it needs to.</p>
|
|
|
|
<p>There are several examples:</p>
|
|
|
|
<ul>
|
|
<li>SampleAutomaton - watches a Sensor, and adjusts the state of a Turnout so that it
|
|
matches the Sensor's state.</li>
|
|
|
|
<li>SampleAutomaton2 - watches a Sensor, and adjusts the momentum of a locomotive
|
|
decoder using ops-mode programming when the sensor state changes.</li>
|
|
|
|
<li>SampleAutomaton3 - runs a locomotive back and forth on a piece of track by watching
|
|
two sensors, reversing the locomotive when they change state.</li>
|
|
</ul>
|
|
|
|
<p>Note that they may not do anything useful on your railroad, as they have block and
|
|
locomotive numbers hard-coded. They're meant to be examples for your own programming, not
|
|
useful tools.</p>
|
|
</dd>
|
|
|
|
<dt class="left">Controlling Locomotives</dt>
|
|
|
|
<dd>
|
|
<p class="example">// get the throttle instance for short address 3<br>
|
|
throttle = getThrottle(3, false);</p>
|
|
|
|
<p>This code snippet assigns "short address 3" to the "throttle" variable (the "false"
|
|
selects short address; long address would have been "true"). If this doesn't work for
|
|
some reason, you'll get a periodic "still waiting for throttle" message in the Java
|
|
window, and the program will wait.</p>
|
|
</dd>
|
|
|
|
<dt class="left">Interacting with the user</dt>
|
|
|
|
<dd>
|
|
<p>You can put up some message boxes directly from Java, but it takes a little code to do
|
|
it. To simplify it at the start, I've added a "MsgFrame" helper class to the JMRI
|
|
library.</p>
|
|
|
|
<p>To make a message box, you first make an object of the "MsgFrame" class:</p>
|
|
|
|
<p class="example">MsgFrame box = new MsgFrame();</p>
|
|
|
|
<p>(You can call it whatever you'd like, of course). That line should go with the other
|
|
declarations, e.g. right after the "DccThrottle throttle = null;" line.</p>
|
|
|
|
<p>Then, inside the test routines, there are a few things you can do. To show a message
|
|
and wait for the user to click a "Continue" button, do:</p>
|
|
|
|
<p class="example">box.show("my message text goes here", true);</p>
|
|
|
|
<p>The 2nd argument shows the "Continue button and waits if true, and just continues if
|
|
false. So if you'd like to show a status message while the program continues to run,
|
|
do:</p>
|
|
|
|
<p class="example">box.show("status message text", false);</p>
|
|
|
|
<p>If you've done that, you can change the message with another "show", or you can make
|
|
the box go away with:</p>
|
|
|
|
<p class="example">box.hide();</p>
|
|
|
|
<p>Java actually has to do some work to pop the box and draw it. We don't want that to
|
|
delay the main test program, so I've written this helper class to do all that kind of
|
|
work as a 2nd, lower priority. You should be able to put messages up on the screen
|
|
without significantly slowing operation down (unless the program waits for the "Continue"
|
|
button to be pressed, of course). And waiting for "Continue" to be pressed won't stop the
|
|
operation of the rest of the program.</p>
|
|
</dd>
|
|
|
|
<dt class="left">Running Your Code</dt>
|
|
|
|
<dd>
|
|
There are two parts to doing this: Making your Java code available to JMRI, and invoking
|
|
it.
|
|
<p>The easiest way to make your code accessible is to make a .jar file and place that in
|
|
the "lib" directory in the JMRI program directory. Alternately, you can create a
|
|
"classes" directory, and compile your Java class into that. In that case, it should end
|
|
up in:</p>
|
|
|
|
<pre style="font-family: monospace;">
|
|
classes/MyCode.class
|
|
</pre>if you've specified no code in your package, or
|
|
|
|
<pre style="font-family: monospace;">
|
|
classes/MyCode.class
|
|
</pre>or
|
|
|
|
<pre style="font-family: monospace;">
|
|
classes/jmri/jmrit/automat/SampleAutomaton.class
|
|
</pre>as an example of how code in a specific package gets stored.
|
|
<p>The easiest way to invoke your code is to use JMRI's scripting support. Open a
|
|
<strong>Script Output</strong> window (so you can see errors) from the
|
|
<strong>Scripting</strong> {<em>Old: <strong>Panels</strong></em>} menu, then in a
|
|
<strong>Script Entry</strong> window, enter:</p>
|
|
|
|
<pre style="font-family: monospace;">
|
|
MyCode().start()
|
|
</pre>or
|
|
|
|
<pre style="font-family: monospace;">
|
|
import jmri.jmrit.automat
|
|
jmri.jmrit.automat.SampleAutomaton().start()
|
|
</pre>and hit Execute. The 2nd line creates an instance of your class and tells it to start
|
|
running.
|
|
<p>Once you've got that working, you can put that in a little script file and invoke it
|
|
at startup, via a Logix, or whenever you desire.</p>
|
|
</dd>
|
|
</dl>
|
|
|
|
<p>Back to the <a href="index.shtml">Automation Help page</a>.</p>
|
|
<!--#include virtual="/help/en/parts/Footer.shtml" -->
|
|
</div>
|
|
<!-- closes #mainContent-->
|
|
</div>
|
|
<!-- closes #mBody-->
|
|
<script src="/js/help.js"></script>
|
|
</body>
|
|
</html>
|