Software documentation

Development tools

Structure

Techniques and Standards

How To

Functional Info

Background Info

JMRI: Adding A New System

This page describes the steps to add a new data-type, e.g. Powerline devices, to JMRI.

It uses as an example the addition of the "powerline" type in January 2008.

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.

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.

Duplicate an existing system

Create a duplicate file tree

Using whatever tool that useful to you, duplicate the src/jmri/jmrix subtree corresponding to the existing system you want to copy.

Change the package name information

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".

At this point, make sure you can compile. This code isn't consistent yet, but it should compile.

Check copyright dates

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.

Create SVN structure

In this step, we put the basic SVN structure in place.

  • Add all the directories you've created to SVN. In the example, this was:
    svn add powerline powerline/serialdriver powerline/serialmon
    svn add powerline/configurexml powerline/serialdriver/configurexml
  • Add all the COPYING files:
    svn add powerline/COPYING powerline/*/COPYING powerline/*/*/COPYING
  • Finally, commmit those files (but only those files):
    svn commit -m"usual file" powerline

At this point, make sure you can compile.

Do Basic Migration

Migrate names

Using your favorite editor, change all occurances of the old system name into the new one.

bbedit `grep -irl secsi powerline/`

Then search for and replace, perhaps not literally, all the occurances.

At this point, make sure you can compile.

Create Basic Tests

Duplicate directory

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 SVN structure, and migrate the names.

At this point, make sure you can compile both the main code (which wasn't changed in this step) and the tests.

You should also be able to successfully run the tests in your new system (although they were created for the old system's functionality): ant tests &&./runtest.csh jmri.jmrix.powerline.SerialTest

Connect Basics to Rest of System

Connect to configuration menus

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.

Don't commit this to SVN yet!

At this point, make sure you can compile and run DecoderPro, and that your new system appears in the preferences panel.

Connect to test tree

Edit the test/jmri/jmrix/JmrixTest.java file to invoke your new system tests.

Don't commit this to SVN yet!

At this point, when you "ant alltest", your new system's test should be run.

Migrate to Basic Functionality

Update connection options
Speeds, etc, in powerline/serialdriver/SerialDriverAdapter.java.
Get send/receive communications working
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.

Make It Easy to Use

Add Possible Startup Items

Create a new system-specific `ActionListBundle.properties` file (src/jmri/jmrix/powerline/PowerlineActionListBundle.properties) to add appropriate action items. Make sure to update the `getActionModelResourceBundle()` method of the SystemConnectionMemo to reference this newly created ActionListBundle.

Complete the documentation

Create The Help Tree

Start by duplicating, then edit, don't forget to update the index.

You'll also have to change the locations on the various frames

ant javadoc

Create the Javadocs, and fix any new (or old) problems.

Add the system to the "hardware" web pages

Edit help/en/html/hardware/index.shtml

Adding a TCP/IP connection to an existing system

These are rough notes from adding a TCP/IP connection to the RFID type, by copying the architecture of the C/MRI system.
  1. Create a "networkdriver" directory in parallel to the "serialdriver" directory.
    svn cp java/src/jmri/jmrix/cmri/serial/networkdriver/ java/src/jmri/jmrix/rfid/
  2. Edit the package and import statements, all files. ".cmri.serial." to ".rfid.", then ".cmri." to ".rfid.".
  3. Change the "setManufacturer" call in NetworkDriverAdapter.
  4. C/MRI might not have been the best starting point, but it's what we've got. Some specific edits needed:
    • Change CMRISystemConnectionMemo to RfidSystemConnectionMemo
    • 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)
    • Change the name of SerialSensorManager throughout
    • Remove the SerialTurnoutManager SerialLightManager references (there aren't any in RFID)
    • Add RfidReporterManager
  5. Needs a network driver:
    svn cp java/src/jmri/jmrix/cmri/serial/SerialNetworkPortController.java java/src/jmri/jmrix/rfid/RfidNetworkPortController.java
    and edit as above.
  6. 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).
  7. Change references to SerialTrafficController to RfidTrafficController.
  8. 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.
    
            // 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();
    
    
    (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.
  9. Add jmri.jmrix.rfid.networkdriver.ConnectionConfig to java/src/jmri/jmrix/rfid//RfidConnectionTypeList.java
  10. Change "RFID Device Connection" to "Direct Serial Connection" in ConnectionConfig.name() The network connection will default to "Network Connection".
  11. Check that configure/save/restart brings back all the configuration options. It should, you copied the necessary code above, but check.

Connections with Complicated Setup

Some connection types need more configuration and/or setup than you can get with the usual option1/option2/option3 mechanism. Tools available are:
  • 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.
  • 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.