Files
JIMRI/help/en/html/doc/Technical/NewSystem.shtml
T
2026-06-17 14:00:51 +02:00

342 lines
13 KiB
Plaintext

<!DOCTYPE html>
<html lang="en">
<head>
<meta name="generator" content="HTML Tidy for HTML5 for Apple macOS version 5.8.0">
<title>JMRI: Adding A New System</title>
<meta name="author" content="Bob Jacobsen">
<meta name="keywords" content="JMRI technical system add"><!--#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>JMRI Code: Adding A New System</h1>
<p>This page describes the steps to add a new data-type, e.g. Powerline devices, to JMRI.</p>
<p>It uses as an example the addition of the "powerline" type in January 2008. This was
before several important migrations (SVN to Git; changes to the internal support for multiple
connections; changes to how the Preferences mechanism works; etc) so this may need
significant updating.</p>
<p>Some parts may also be useful if you're adding a new connection (e.g. through a network
link) to an existing system. If you do that, please mark those sections here for the next
person to come along.</p>
<p>Note that we don't do this very often, and the specifics are more important than the
generalities here. You should should make sure you understand the <a href=
"SystemStructure.shtml">intended system connection structure</a> which is documented on
<a href="SystemStructure.shtml">another page</a>.</p>
<p>We list the files that are modified and created in the order they were done in this case;
other orders may also work, and you might not need to do all these.</p>
<p>In this particular case, we started by copying an existing system implementation (SECSI).
This effects how we ordered this, and made the basic process move pretty quickly.</p>
<h3>Duplicate an existing system</h3>
<dl>
<dt>Create a duplicate file tree</dt>
<dd>
<p>Using whatever tool that useful to you, duplicate the src/jmri/jmrix subtree
corresponding to the existing system you want to copy.</p>
</dd>
<dt>Change the package name information</dt>
<dd>
<p>Using your favorite editor, change all the package names in the new files to their new
location. In this example, that was a bulk replace of "jmri.jmrix.secsi" with
"jmri.jmrix.powerline".</p>
</dd>
<dd>
<p>At this point, make sure you can compile. This code isn't consistent yet, but it
should compile.</p>
</dd>
<dt>Check copyright dates</dt>
<dd>
<p>Because you've copied a system that might not have been touched for a while, go
through and add the current year (and if need be, your name) to the copyright notices in
all the files.</p>
</dd>
<dt>Create Git structure</dt>
<dd>
<p>In this step, we put the basic Git structure in place.</p>
<ul>
<li>Add all the directories you've created to Git. In the example, this was:<br>
<code>git add powerline powerline/serialdriver powerline/serialmon<br>
git add powerline/configurexml powerline/serialdriver/configurexml</code></li>
<li>Add all the COPYING files:<br>
<code>git add powerline/COPYING powerline/*/COPYING powerline/*/*/COPYING</code></li>
<li>Finally, commmit those files (but only those files):<br>
<code>git commit -m"usual file" powerline</code></li>
</ul>
</dd>
<dd>
<p>At this point, make sure you can compile.</p>
</dd>
<!-- (The dl vs h3 structure is really messed up here and below) -->
</dl>
<h3>Do Basic Migration</h3>
<dl>
<dt>Migrate names</dt>
<dd>
<p>Using your favorite editor, change all occurances of the old system name into the new
one.</p>
<code>bbedit `grep -irl secsi powerline/`</code>
<p>Then search for and replace, perhaps not literally, all the occurances.</p>
<p>At this point, make sure you can compile.</p>
</dd>
<dt>Register system for preferences</dt>
<dd>
<p>Add the line <code>@ServiceProvider(service = ConnectionTypeList)</code> just before
the class definition so that the preferences system sees your new connection types. You
may also need to add the following import statements:<br>
<code>import org.openide.util.lookup.ServiceProvider;</code><br>
<code>import jmri.jmrix.ConnectionTypeList;</code></p>
</dd>
<dt>Update the documentation</dt>
<dd>
<ul>
<li>Most important, make an entry in the <a href="Names.shtml">Names.shtml</a> page for
the system letter.
</li>
<li>Add at least one page of documentation to the help/en/html/hardware area.</li>
<li>Link that from the <a href=
"../../hardware/index.shtml">help/en/html/hardware/index.shtml</a> hardware home page.
Include a link to the manufacturer's website if possible.
</li>
</ul>
</dd>
<dt>Create Basic JUnit Tests</dt>
<dd>
<p>For more information on this, see the <a href="JUnit.shtml">testing page</a>.</p>
</dd>
<dt>Duplicate directory</dt>
<dd>
<p>Following the steps above, duplicate the directory for the previous systems tests,
creating a new directory in test/jmri/jmrix to contain the tests. Change the package
names, check the copyright dates, create the Git structure, and migrate the names.</p>
</dd>
<dd>
<p>At this point, make sure you can compile both the main code (which wasn't changed in
this step) and the tests.</p>
<p>You should also be able to successfully run the tests in your new system (although
they were created for the old system's functionality): <code>ant tests
&amp;&amp;./runtest.csh jmri.jmrix.powerline.SerialTest</code></p>
<p>There is also a PowerShell script available, see the <a href="JUnit.shtml">JUnit</a>
page for more information</p>
</dd>
</dl>
<h3>Connect Basics to Rest of System</h3>
<dl>
<dt>Connect to configuration menus</dt>
<dd>
<p>Edit the jmri/jmrix/ActiveSystemsMenu.java file (two places),
src/jmri/jmrix/JmrixConfigPane.java (one place) and src/jmri/jmrix/SystemsMenu.java (one
place) files to add the new system.</p>
<p>Don't commit this to Git yet!</p>
</dd>
<dd>
<p>At this point, make sure you can compile and run DecoderPro, and that your new system
appears in the preferences panel.</p>
</dd>
<dt>Connect to test tree</dt>
<dd>
<p>Edit the test/jmri/jmrix/JmrixTest.java file to invoke your new system tests.</p>
<p>Don't commit this to Git yet!</p>
</dd>
<dd>
<p>At this point, when you "ant alltest", your new system's test should be run.</p>
</dd>
</dl>
<h3>Migrate to Basic Functionality</h3>
<dl>
<dt>Update connection options</dt>
<dd>
<p>Speeds, etc, in powerline/serialdriver/SerialDriverAdapter.java.</p>
</dd>
<dt>Get send/receive communications working</dt>
<dd>
<p>The first step is to get communications working so that you can send a message from
the "Send Command" window, and see it and the response in the "Monitor" window.</p>
</dd>
</dl>
<h3>Make It Easy to Use</h3>
<dl>
<dt>Add Possible Startup Items</dt>
<dd>
<p>Create a new system-specific `ActionListBundle.properties` file
(src/jmri/jmrix/powerline/PowerlineActionListBundle.properties) to add appropriate action
items. Make sure to update the <code>getActionModelResourceBundle()</code> method of the
SystemConnectionMemo to reference this newly created ActionListBundle.</p>
</dd>
</dl>
<h3>Complete the documentation</h3>
<dl>
<dt>Create The Help Tree</dt>
<dd>
<p>Start by duplicating, then edit, don't forget to update the index.</p>
<p>You'll also have to change the locations on the various frames</p>
</dd>
<dt>ant javadoc</dt>
<dd>
<p>Create the Javadocs, and fix any new (or old) problems.</p>
</dd>
<dt>Add the system to the "hardware" web pages</dt>
<dd>
<p>Edit help/en/html/hardware/index.shtml</p>
</dd>
</dl>
<h2>Adding a TCP/IP connection to an existing system</h2>
These are rough notes from adding a TCP/IP connection to the RFID type, by copying the
architecture of the C/MRI system.
<ol>
<li>Create a "networkdriver" directory in parallel to the "serialdriver" directory.<br>
<code>cp java/src/jmri/jmrix/cmri/serial/networkdriver/
java/src/jmri/jmrix/rfid/</code></li>
<li>Edit the package and import statements, all files. ".cmri.serial." to ".rfid.", then
".cmri." to ".rfid.".</li>
<li>Change the "setManufacturer" call in NetworkDriverAdapter.</li>
<li>C/MRI might not have been the best starting point, but it's what we've got. Some
specific edits needed:
<ul>
<li>Change CMRISystemConnectionMemo to RfidSystemConnectionMemo</li>
<li>Remove the reference to NodeConfigAction in ConnectionConfig (or use this as the
base for any special configuration you need; it was adding a "Configure Nodes"
button)</li>
<li>Change the name of SerialSensorManager throughout</li>
<li>Remove the SerialTurnoutManager SerialLightManager references (there aren't any in
RFID)</li>
<li>Add RfidReporterManager</li>
</ul>
</li>
<li>Needs a network driver:<br>
<code>cp java/src/jmri/jmrix/cmri/serial/SerialNetworkPortController.java
java/src/jmri/jmrix/rfid/RfidNetworkPortController.java</code><br>
and edit as above.</li>
<li>java/src/jmri/jmrix/rfid/networkdriver/configurexml/ConnectionConfigXml.java contains
dead code for configuring the C/MRI nodes (again, maybe not the right system to copy from).
Leave that for later by commenting out the body of extendElement(Element e) and
unpackElement(Element e).</li>
<li>Change references to SerialTrafficController to RfidTrafficController.</li>
<li>Another problem with C/MRI as a prototype is that it still has an instance() call in
NetworkDriverAdapter. Go to the RFID (multi-system capable) SerialDriverAdapter and copy
the structure there.
<pre>
<code>
// connect to the traffic controller
this.getSystemConnectionMemo().setRfidTrafficController(control);
control.setAdapterMemo(this.getSystemConnectionMemo());
control.connectPort(this);
control.sendInitString();
// declare up
jmri.jmrix.rfid.ActiveFlag.setActive();
</code>
</pre>(There's also a bunch of stuff before this in the configure() method that should just be
copied over, because the RFID connections also need some complicated configuration); the ctor also
needs some parts copied over.
</li>
<li>Add jmri.jmrix.rfid.networkdriver.ConnectionConfig to
java/src/jmri/jmrix/rfid//RfidConnectionTypeList.java</li>
<li>Change "RFID Device Connection" to "Direct Serial Connection" in
ConnectionConfig.name() The network connection will default to "Network Connection".</li>
<li>Check that configure/save/restart brings back all the configuration options. It should,
you copied the necessary code above, but check.</li>
</ol>
<h2>Connections with Complicated Setup</h2>
Some connection types need more configuration and/or setup than you can get with the usual
option1/option2/option3 mechanism. Tools available are:
<ul>
<li>loadDetails() in ConnectionConfig. This is invoked when setting up the preferences
window, and can be used to add additional controls. C/MRI uses this to add a "Configure
Nodes" button. RFID uses it to add listeners that control which combinations of options are
available.</li>
<li>extendElement(Element e) and unpackElement(Element e) in ConnectionConfigXml can be
used to store additional information and reload it, respectively. C/MRI uses this to store
its node information.</li>
</ul>
<!--#include virtual="/help/en/parts/Footer.shtml" -->
</div>
<!-- closes #mainContent-->
</div>
<!-- closes #mBody-->
<script src="/js/help.js"></script>
</body>
</html>