180 lines
7.2 KiB
Plaintext
180 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">
|
|
<title>Jython access to JMRI Tools</title>
|
|
<meta name="author" content="Bob Jacobsen">
|
|
<meta name="keywords" content="JMRI technical code Python Jython scripting">
|
|
<!--#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">
|
|
<h1>Jython access to JMRI Tools</h1>
|
|
|
|
<p>This page discusses access to the JMRI libraries from Jython, a Java version of Python.
|
|
The emphasis is on using JMRI capabilities from a command-line Jython interpreter.
|
|
<strong>This page is not about scripting with Jython inside JMRI.</strong> See the <a href=
|
|
"../../tools/scripting/index.shtml">scripting pages</a> if you are more interested in Jython
|
|
scripting within JMRI.</p>
|
|
|
|
<p>Note that this page is somewhat out of date; version numbers, etc may not be current.</p>
|
|
|
|
<h2>Introduction</h2>
|
|
<a href="http://www.python.org">Python</a> is a widely used scripting language that's
|
|
available on many types of computers. A Java-based varient, called <a href=
|
|
"http://www.jython.org">Jython</a>, has been integrated with JMRI to make it easy to control
|
|
a model railroad from the command line of a computer. Jython and Python bring some
|
|
simplifications to using JMRI code. The Java member function:
|
|
|
|
<pre>
|
|
turnout.setCommandedState(jmri.Turnout.CLOSED);
|
|
</pre>can also be expressed in Jython as:
|
|
|
|
<pre>
|
|
turnout.commandedState = CLOSED
|
|
</pre><br>
|
|
This results in much easier-to-read code.
|
|
<p>There are a lot of useful Python books and online tutorials. For more information on the
|
|
Jython language and it's relations with Java, the best reference is the <a href=
|
|
"http://www.oreilly.com/catalog/jythoness/">Jython Essentials</a> book published by O'Reilly.
|
|
The <a href="http://www.jython.org/">jython.org website</a> is also very useful.</p>
|
|
|
|
<h2>Using Jython directly</h2>
|
|
This section of the page is a pile of useful information on controlling JMRI from Jython
|
|
directly.
|
|
<p>Note that you don't need most of this when running the PanelPro.py or similar scripts, as
|
|
they handle starting a complete application.</p>
|
|
|
|
<h3>Initialization</h3>
|
|
JMRI uses the LogJ system extensively for logging information during program execution. To
|
|
configure that when running with Jython, you should do:
|
|
|
|
<pre>
|
|
import org.apache.logging.log4j.core.config.Configurator
|
|
Configurator.initialize(null, "default_lcf.xml");
|
|
</pre>before starting any of the JMRI classes.
|
|
|
|
The "default.lcf" is the name of the logging control file to be used.
|
|
<p>To make JMRI classes available, you have to do:</p>
|
|
|
|
<pre>
|
|
import jmri
|
|
</pre>As currently set up, this does not run any initialization code to start the hardware
|
|
connections, etc. One way to do that is to load a configuration file, perhaps one you've created
|
|
earlier via the PanelPro preferences panel:
|
|
|
|
<pre>
|
|
import java.io
|
|
configfile = java.io.File(jmri.util.FileUtil.getPreferencesPath()+"PanelProConfig2.xml")
|
|
jmri.InstanceManager.setConfigureManager(jmri.configurexml.ConfigXmlManager())
|
|
jmri.InstanceManager.getDefault(jmri.ConfigureManager.class).load(configfile)
|
|
</pre>to activate the JMRI classes and connect to your layout hardware. "PanelProConfig2.xml" is
|
|
the name of the configuration file from the PanelPro program; you can use another name if desired.
|
|
The configuration file controls the layout connection, and any other options that may have been set
|
|
when it was created.
|
|
<p>Alternately, if you want to start the complete PanelPro application, including the menu
|
|
bar, spash screen, etc, you can do:</p>
|
|
|
|
<pre>
|
|
import apps
|
|
apps.PanelPro.PanelPro.main([])
|
|
</pre>
|
|
<p>This will start the program, including its startup configuration, etc.</p>
|
|
|
|
<p>To simplify this startup even further, you can do:</p>
|
|
|
|
<pre>
|
|
execfile("PanelPro.py")
|
|
</pre>to invoke these commands.
|
|
<h3>Access to JMRI</h3>
|
|
JMRI uses the factory-pattern extensively to get access to objects. In Java this results in
|
|
verbose code like
|
|
|
|
<pre>
|
|
Turnout t2 = InstanceManager.getDefault(jmri.TurnoutManager.class).newTurnout("LT2", "turnout 2");
|
|
t2.setCommandedState(Turnout.THROWN)
|
|
</pre>Jython simplifies that by allowing us to provide useful variables, and by shortening certain
|
|
method calls.
|
|
<p>To get access to the SignalHead, Sensor and Turnout managers and the CommandStation
|
|
object, several shortcut variables are defined in the .py scripts listed above:</p>
|
|
|
|
<ul>
|
|
<li>sensors</li>
|
|
|
|
<li>signals</li>
|
|
|
|
<li>turnouts</li>
|
|
|
|
<li>lights</li>
|
|
|
|
<li>reporters</li>
|
|
|
|
<li>memories</li>
|
|
|
|
<li>dcc</li>
|
|
|
|
<li>audio</li>
|
|
</ul>
|
|
These can then be referenced directly in Jython as
|
|
|
|
<pre>
|
|
t2 = turnouts.provideTurnout("12");
|
|
|
|
dcc.
|
|
</pre>Note that the variable t2 did not need to be declared.
|
|
<p>Juthon provides a shortcut for parameters that have been defined with Java-Bean-like get
|
|
and set methods:</p>
|
|
|
|
<pre>
|
|
t2.setCommandedState(Turnout.THROWN)
|
|
</pre>can be written as
|
|
|
|
<pre>
|
|
t2.commandedState = THROWN
|
|
</pre>where the assignment is actually invoking the set method. Also note that THROWN was defined
|
|
when running the Python script at startup; CLOSED, ACTIVE, INACTIVE, RED, YELLOW and GREEN are also
|
|
defined.
|
|
<p>A similar mechanism can be used to check the state of something:</p>
|
|
|
|
<pre>
|
|
>>> print sensors.provideSensor("3").knownState == ACTIVE
|
|
1
|
|
>>> print sensors.provideSensor("3").knownState == INACTIVE
|
|
0
|
|
</pre>Note that Jython uses "1" to indicate true, and "0" to indicate false, so sensor 3 is
|
|
currently active in this example
|
|
<p>You can also directly invoke methods, e.g. to send a DCC packet to the rails you type:</p>
|
|
|
|
<pre>
|
|
|
|
dcc.sendPacket([0x01, 0x03, 0xbb], 4)
|
|
</pre>This sends that three-byte packet four times, and then returns to the command line.
|
|
<p>To exit, either ^C from the command line, or use the exit command from the menu.</p>
|
|
|
|
<h2>Using Python for signal logic and automation</h2>
|
|
The existing JMRI "<a href=
|
|
"https://jmri.org/JavaDoc/doc/jmri/jmrit/automat/package-summary.html">Automat</a>" classes
|
|
provide hooks for user layout automation, including signaling. But they require that you
|
|
write Java code and compile it into .class files, or write Jython code and import it.
|
|
<h3>Termination</h3>
|
|
|
|
<p>Once the JMRI main thread (or Swing GUI thread?) has started, ^D is not sufficient to
|
|
exist the program. You have to select "Quit" from the actual file menu, or ^C the
|
|
program.</p>
|
|
|
|
<p>It would be good to understand what's preventing the program from stopping when it gets
|
|
the <code>^D</code>.</p>
|
|
<!--#include virtual="/help/en/parts/Footer.shtml" -->
|
|
</div>
|
|
<!-- closes #mainContent-->
|
|
</div>
|
|
<!-- closes #mBody-->
|
|
<script src="/js/help.js"></script>
|
|
</body>
|
|
</html>
|