JMRI® connects to...

Supported Hardware

Devices, command stations, networks, and protocols:


By the community of


JMRI tools for working with your layout:

Layout Automation

Use JMRI to automate parts of your layout and operations:

JMRI Help:
Contents/ Index
Glossary/ FAQ

Donate to JMRI Donate to

Hardware Support: MQTT

JMRI can connect to IOT devices via the MQTT protocol.


The default system letter is "M", so we'll use that in examples.


Older code (i.e. JMRI 4.12 and later) only supports Turnouts. We hope to add Sensor, Light and Reporter support soon.


You tell JMRI about how to connect to your MQTT hardware via the Connections pane in the Preferences window. Select "MQTT" as the manufacturer name.

Currently, JMRI can handle only one MQTT connection at a time. You can combine that MQTT connection with other connection types, but two MQTT connections won't work properly. This may be improved at some later point if people find a reason to need two MQTT connections.


JMRI MQTT Turnouts are specified with JMRI system names like "MTabcd". The "M" is the system connection letter, "T" specifies Turnout, and all after that is a suffix that is used to generate the specific topic which JMRI publishes and subscribes to when communicating with the layout.

By default, the MQTT topic for a Turnout is constructed by prepending "/trains/track/turnout/" to the suffix. For example, a JMRI Turnout with system name MTabcd will publish and subscribe to the "topic /trains/track/turnout/abcd". There are two parts to that: A base topic common to everything JMRI does on that connection, and a type-specific topic specific to each type.

By default the base topic is "/trains/"; the turnout-specific part is "track/turnout/", leading to a complete prefix of "/trains/track/turnout/".

Sensors are similar, with system names like "MS123" and a topic type-specific part of "track/sensor/". For example, by default MS123 will subscribe to the topic "/trains/track/sensor/123".

Since JMRI 4.15.5 You can change the base topic by going to the JMRI Connection preferences, selecting your MQTT connection's preference pane, checking the "Additional Connection Settings" box, and then entering the desired value in the "MQTT channel" selection box.
You then must save your changes and restart the program; the program won't continue to operate normally after changing the base prefix until you restart it.

Note that the default value of "/trains/" is the default for all JMRI instances. If you use a common broker (like the test server mentioned below) keeping that default prefix will show you traffic from every other JMRI instance connected to that broker. You should probably change that default to something like your own railroad name. You might also want to omit the leading slash; it's present in the default for historical reasons, but the MQTT authorities recommend not having a slash there.

You can change the type-specific part of the prepended string using the other fields in the preferences. There are separate fields for specifying what JMRI should send (the "transmit" field) and what JMRI should recognize back from the layout (the "receive" field). If you enter a string, the suffix of the Turnout's system name will be appended: "track/turnout/" for MT123 will result in a topic of "/trains/track/turnout/123". If you include "{0}" in the string, the suffix will be expanded there, which allows you to do things like enter "track/turnout/{0}/state" and have that expand to "track/turnout/123/state".s Save the preferences and restart JMRI to put changes into effect.

You can also change the type-specific part of the prepended string using a script at startup time. See the jython/ sample script for an example. Note that any changes should be made at startup time before creating any Turnout objects, i.e. the script must be run as the first startup action before any panel files are loaded. Changing the prefix only affects Turnouts that are created after the change.

Message Content


By default, the message content for turnouts is "CLOSED" and "THROWN".


By default, the message content for sensors is "ACTIVE" and "INACTIVE".

Changing the Coding

Since JMRI 4.15.5 You can use scripting to install a new jmri.jmrix.mqtt.MqttContentParser object to code and decode the content of messages. You might want to use JSON format, or need to adapt to specific messages from some already-existing devise; you can create a custom parser to do any of that. See the jython/ sample script for how to do that. For a Java example, see the inner class implementation in MqttTurnout.

Note that you can call setParser(...) on the jmri.jmrix.mqtt.MqttTurnoutManager or on an individual jmri.jmrix.mqtt.MqttTurnout object. If you call it on an individual MqttTurnout, that's the only one that's affected. If you call it on the MqttTurnoutManager all later created MqttTurnout objects will use the new parser; earlier-created ones will not be changed. This means you should call a script to change this before loading any panel files if you want all MqttTurnouts to be modified.


If you don't have an MQTT system, and want to play with this connection type, you can enter "" for the host name to use a publicly-available (non-JMRI) test server. For more information on this server, see the web page.

If you install the mosquitto tools on your machine, you can use a command like

    mosquitto_sub -h -v -t '/trains/#'
to subscribe and print JMRI turnout info as it's published. To publish a change for JMRI to pick up:
    mosquitto_pub -h -t /trains/track/turnout/123 -r -m "CLOSED"
    mosquitto_pub -h -t /trains/track/turnout/123 -r -m "THROWN"
These commands can be run on the same machine as JMRI, or on a separate machine.

There are also MQTT tools available for iOS devices and Android devices that can be useful for monitoring, testing and operating your layout.