Technical insights and software architecture

Deep dives into PHP development, Horde Framework evolution and practical software engineering. Focused on real-world solutions for complex technical challenges. “Always close to the source”.

Core Topics

PHP, Horde Framework, authentication systems, composer workflows and modern development practices.

Long-form Analysis

Comprehensive technical articles exploring architectural decisions, migration strategies and lessons learned from real projects.

Code & Community

Open source contributions, framework development and sharing knowledge with the PHP developer community.

JMRI with new Märklin MS2 features

—

by

in

It’s been a while since I last mentioned JMRI on here. Back in early 2025 I was working on Mobile Station 2 support and a Track Tile editor.

Unfortunately I had to postpone the Track Tile editor topic due to too many things on my plate – my job, my private life, Horde software development and some other stuff – but as indoor season approaches, there’s some good news.

I already got a large piece of new code merged into JMRI and there’s more on the way. If everything works out as planned, the winter release (5.18) will have some interesting new features.

JMRI now has a much more complete grasp of the Märklin CAN protocol which connects all the different gear you may have – TrackBox, Mobile Station 2, Central Station 2 or 3, Booster 60175, third party equipment… I did a lot of traffic observation between these components and learned a lot about how it works. I also read a lot of other people’s work, online forums, software and hardware documentation and alternative foss solutions on the market. Research is quite a rabbit hole.

A clean library for most bus commands

The new mcan library provides a nice object model for working with Märklin CAN frames, both commands and replies. Along with the more modern CS2/CS3/MS2 protocol the library also handles some basic CS1/MS1 and third party traffic.

A bridge across programs

There’s also a new bridge utility which turns your USB CAN connection into an extensible hub for multiple software or hardware consumers. As a side effect, I do no longer need to run JMRI on the computer which connects the USB CAN device and I can run purpose built diagnosis and simulation software alongside JMRI and my actual hardware connection. But this is all developer stuff, where’s the user value?

Detecting Gear

There’s a new window for MCAN Devices. It offers you to probe two different classes of device (Marklin native and third party). It also lists any devices JMRI might have noticed by passively listening to the traffic on the system connection bus.

Configuring Gear

For some types of commercial third party gear I implemented a config screen to read and change settings. The screen follows the design language of the vendor’s own tools.

Throttle Seniority

Now that JMRI knows the devices on the bus, it needs to understand the Märklin system’s rules about which Mobile Station 2 or Central Station 2/3/3+ is the most senior throttle.

The most senior throttle holds the active roster and performs Mfx Protocol binding. Mfx Protocol is Märklin’s way of making locomotives and some types of turnout decoders and other gear announce themselves to the most senior throttle.

There are two main scenarios I am interested in:

  • Layouts with a Gleisbox (track box, creates the actual track signals) and zero, one or many Mobile Station 2 (or Mobile Station WLAN)
  • Layouts with a Central Station 2, Central Station 3, Central Station 3+ and optionally boosters and Mobile Station 2 throttles

In a Gleisbox layout, multiple Mobile Station 2 devices agree about who is currently the most senior device. New devices can join and old devices can be disconnected and this makes them agree anew who is most senior.

In a Central Station 2/3/3+ layout, all mobile stations agree the central station is the most senior throttle. There’s also rules in case you combine multiple Central Station devices and JMRI has started to learn some of them.

Querying the most senior throttle

When a Mobile Station 2 is the most senior throttle, all other Mobile Station 2 devices will ask for its list of locomotives and will temporarily stash their own list of locomotives in some corner of their minds until they are most senior (or alone) themselves. They will instead use the senior’s list. JMRI has learned the same capability recently. It can read the most senior throttle’s list of locomotives. Caveat: This has only been verified with Mobile Station 2 devices. The Central Station 2 or 3 might have a more intricate roster file which works differently. I am still figuring.

Importing locomotives to JMRI

Now that JMRI has a basic understanding of a Mobile Station 2 device’s locomotive roster, the next step is obviously importing locomotives from the roster. Users can now select a locomotive entry from the most senior Mobile Station 2 throttle’s roster and copy it into JMRI. This works for DCC and Märklin/Motorola protocol locomotives but not for Mfx locomotives. By purpose I decided not toll allow mfx imports yet. Mfx protocol uses two different types of address: A permanent long address called the Uid which is unique to a device and an ephemeral short address, the SID. The SID is agreed upon when you put an mfx loco on a track with a Gleisbox or Central Station 2 or 3. The same locomotive can have different SIDs in different layouts and even in the same layout if it has been absent for long enough. Storing a SID permanently into JMRI is kind of wrong, it doesn’t work like a DCC or MM address. Storing the Uid doesn’t work either and it would be wrong as well. It will need some additional logic to make this work

Where in the world is …

There’s a lot of JMRI improvements from other people, way more than mine. Keith has worked on making JMRI smarter when it figures out which locomotive is where exactly on the layout. It’s still not on par with commercial solutions such as iTrain or the now-decontinued TrainController Gold but it’s getting there. There is also lots of work in LCC, an NMRA approved standard protocol for layout gear which I find very intriguing. LCC isn’t popular in Europe yet. I think it would be possible to tunnel LCC through Märklin’s CAN bus but only with custom grown gear – the official LCC CAN standard is a different speed than Märklin’s CAN. JMRI already supports the official LCC CAN standard.

Where are we going from here?

I have an exhibition to exhibit at, there’s end of year stress at work, there’s family events which don’t ask for schedule and I am one of the main drivers of Horde 6 development – I cannot easily commit to timetables for JMRI.

That said, it’s fun and I am in it both for the joy and the challenge. I also actually want to use these features.

Now that reading from Mobile Station 2 works, reading from a Central Station 3 is next. Can JMRI also write back to a throttle? From what I understand, that is not possible. JMRI can only make a throttle do what it is built to do. A Mobile Station may stash its own roster and use a more senior device’s roster as long as it’s present. It cannot import or store roster entries permanently without user interaction on the throttle itself. But that may be the trick: JMRI may want to assume the role of most senior throttle itself, emit the necessary CAN traffic and make everybody accept a roster provided by JMRI. But to step into that role in a useful way, JMRI needs to learn how to perform Mfx binding and hold an Mfx roster. At the moment JMRI forgets everything about MCAN devices on each restart. That won’t provide a good user experience with Mfx locomotives so we may want to change that.

There’s also so much Central Station 3 data I want to import. And then again, there’s the Track Tiles – building a JMRI layout from the commercially available pieces of track, making them snap at the correct angles, automatically computing the length of a block from its parts… it’s still planned, I just don’t know about some puzzles to solve first and the time it requires.

In it for the fun

The JMRI community is very welcoming and assisting in my attempts to add features most core contributors are not directly interested in. It’s a great project and I feel good about accepting their advice. I am a minor external contributor and an advanced user. It works out well for me.

I decided not to bother with projects which don’t work this way. Not in my spare time, not for fun. This railroad hobby is full of people who sometimes come off as a bit adversial and I have a very limited mental budget for that.

That’s why I decided to limit my efforts in third party gears when the vendor isn’t supportive. I will do what works for me. I may be interested to design my own homegrown solutions but I don’t want to make this a business or a second job. By choice, things I build outside my job are usually free and open. Everybody may adopt, adapt, critique or improve upon it and that’s the way I like it.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *