JMRI: "What...Where" of Jython Scripting with JMRI
Other interesting tidbits about scripting in JMRI with Jython
- Where should I store my JMRI Jython scripts?
- Where can I find more information on the JMRI classes?
- What do the words "
import
" and "class
" mean? - What's the difference between the "Siglet" and "AbstractAutomaton" classes?
See the examples page for many sample scripts. Also, the introductory page shows some of the basic commands.
See also JMRI Scripting "How To..."
See also Jython/Python Language for general info about the language.
Where should I store my JMRI Jython scripts?
You CAN use any location for your own scripts, including locations within a Dropbox (or other file sharing system) folder where they will be available across multiple computers. [Instructions on using Dropbox with various JMRI files can be found at JMRI Setup: Sharing Files with Dropbox.]
However, you should NEVER store your own scripts (or any other user-created files) anywhere within your Program Location as they will be lost in a JMRI upgrade. Unfortunately, JMRI currently defaults the Scripts Location to the Jython sample scripts folder located within your JMRI Program Location. To resolve this, change the Scripts Location in Preferences (Preferences->Locations) so that your location will be displayed automatically.
Where can I find more information on the JMRI classes?
There are a lot of classes! To help you find things, it might be useful to look at the page on JMRI structure, which is part of the JMRI technical documentation. Note the references on the left-hand side.
Additional information can be found in the JavaDocs for specific types of classes, for example:
http://jmri.org/JavaDoc/doc/index.html?jmri/SensorManager.html
http://jmri.org/JavaDoc/doc/index.html?jmri/TurnoutManager.html
http://jmri.org/JavaDoc/doc/index.html?jmri/LightManager.html
http://jmri.org/JavaDoc/doc/index.html?jmri/BlockManager.html
What do the words "import
",
"class
" mean?
"import" allow you to refer to things by shorter names, essentially telling jython "search the imported packages (e.g. jarray and jmri) packages and recognize all the names there". For somebody trying to understand this script, you can just treat them as "ensuring the program can find parts we want".
"class" means "start the definition of a group of things that go together" (all you other experts, please don't jump on me about this; I understand both intrinsic/extrinsic polymorphism, I'm just trying to get the general idea across).
For example, in the SigletExample.py file is a description of a "class" called SigletExample, which contains two routines/functions/members: A subroutine called "defineIO", and one called "setOutput"
This "class" is associated with another called "Siglet" (actually jmri.jmrit.automat.Siglet; that's that long naming thing again), which knows when to invoke routines by those two names to get done what you want.
Essentially, you're defining two parts ("defineIO" & "setOutput") that plug into a pre-existing structure to drive signals. That pre-existing structure is very powerful, and lets you do all sorts of things, but also provides this method to try to keep it simpler.
OK, at this point most people's eyes are fully glazed over. Your best bet when starting with this stuff is to use the "copy and modify" approach to software development. It's good to try to understand the entire content of the file, but don't worry about understanding it well enough to be able to recreate it from scratch. Instead, just modify little bits and play with it.
What's the difference between the "Siglet" and "AbstractAutomaton" classes?
Some examples use the AbstractAutomaton class as a base, while others use the Siglet class. This is because those are intended for two different purposes.
"Siglet" is meant to be used for driving signals. You provide two pieces of code:
- defineIO
- which defines the various sensors, turnouts and signals that the output signal depends on as input when calculating the appearance of the signal.
- setOutout
- which recalculates the signal appearance from the defined inputs.
The Siglet base class then handles all of the listening for changes, setting up for parallel execution, etc. Your defineIO routine will be called once at the beginning, and after than any time one or more of the inputs changes, your setOutput routine will be called to recalculate the signal appearance.
Of course, you can use this class to calculate other things than signal appearances. But the key element is that the calculation is redone when the inputs change, and only when the inputs change.
AbstractAutomaton is a more general class that's intended to allow more powerful operations (and Siglet actually uses that more powerful base). You define two functions:
- init
- which is called exactly once to do any one-time setup you need
- handle
- which is called over and over and over again until it returns FALSE.
For more info on the routines that AbstractAutomaton provides to help you, see the Javadocs for the class. (Scroll down to the section called "Method Summary")