Xpressnet Poll support

Hi, I’m finally testing my Oscilloscopio.it DCC-A510 interface. It basically emulates Lenz LI100F Xpressnet to USB with 9600 baud rate.

My previous tests failed because I did not understand how bad the protocol is: if locomotive is not driven by traintastic, it will have to constantly poll for its status (unless special command station is used like Hornby Elite, stated by JMRI).

JMRI Poll scheduling

JMRI tracks which locomotive is not owned by itself and polls at 1 second rate.
Well, at 9600 baud interface, you easily see how it goes of you need to poll many locomotives.

I suggest an enhancement: if loco is idle for more than N seconds, acquire it automatically, so it’s one less loco to be polled.

If interested, we could also organize a poll priority list, like if loco in in active train and multiple traction, set to high priority then will be polled more often. But code would get complicated…

Hi,

Yes, XpressNet is not ideal for this kind of operations.

Polling needs to be added for sure, we should add a setting to configure the poll interval, 1000ms seems a good default to me. Range 500ms-5000ms, 100ms steps?

That is a nice feature, I suggest we add a setting for it, so users can modify it it required. Default to 30s, 1s steps, 5s minimum, 900s maximum?

A low impact trick could be just to cut the normal poll time in half for these trains when driven by an XpressNet throttle.

For the best (multiple traction) train control experiance the advice must be: Use a throttle that communicates with Traintastic, not directly with the command station.

Greetings,
Reinder

I like it! Should we poll just the basic status or also function status? They are at least 2 different messages and possibly more if you want to query higher number function.

Maybe we base this on decoder registered functions, take highest number.
It’s difficult to say what does JMRI because it does not have a single receive() function for Xpressnet. It seems however that poll timer just sends basic information request (speed, dir, F0-12 more or less) then when receives a response it sends higher function status request on same locomotive. I think this is done to avoid sending too many messages togheter.

Also each decoder has it’s own poll timer. Should we do this too? Or take one common timer for everyone? Having decoder specific timer helps spreading timeout times, they will not timeout at the same time all together so less traffic spike on the bus I think.

Should the timer live in interface (Eventloop thread, use postSend() to Kernel) or inside Kernel (Use send() directly which is good but we can’t query how many function a decoder has).

How does a decoder know if it’s in a train, should we go through it’s rail vehicle? Like check it at every poll timeout?

Yes of course, it’s just that I have this interface at my club so for now I work on this, then I will move to test DR5000.
Also because they use JMRI for WiThrottle (And for programming CVs I must say it’s really good) but I would like to replace it with Traintastic.

Hi, I’ve opened a draft PR for new Xpressnet messages.

Another cool thing of this protocol is that reply from command station about locomotive info does not have an address field!
So you must remember which locomotive you’ve asked for.
Also this poses a problem about querying multiple locomotives together. If we trust strict message ordering on the bus and no message drop, we could keep a queue of queried locomotives and match replies as they come.

I really don’t understand how does JMRI handle this. It passes a replyTo paramenter when sending but I can’t seem to find send function implementation to see how it tracks replies.

I prefer to poll both, else it partly synchronized.

Yes, it would be nice to only poll groups of functions that are known by Traintastic.

The timer should be in the interface or kernel, kernel has my preference. The decoder doesn’t need to know about polling, it is a interface/protocol issue.

In newer interface implementation (CBUS and Dinamo, both still branches) I introduced a more strict separation of interface/kernel logic. There the kernel just does the protocol handling and has callback for the interface to use to update *Controller stuff.

The interface can tell the kernel which addresses/functions groups
need to be polled, then the kernel can do the polling and notify if something changes.

That’s a bit hard at the moment so, for now I think it is best to only do the basic polling. After CBUS is merged (I’d hope this week, working on one more thing), I’ll have a look at the TrainRailVehicleDecoder relation, as I said I think it is best to merge RailVehicle and Decoder, the current structure isn’t working well for this polling stuff and the (CBUS) throttle acquire/release support.

What I think will work best is create a list of everything that needs to be polled. Sent the first one, wait for reply, move it to the back of the list, set a timer, send the next one. In the list you can also record the next poll time (= reply time+poll interval), and use that for the timer, if the next poll is already expired send it directly.

I’ll have a look at the PR.

Greetings,
Reinder