Implementation in Train control software

Here are some suggestions on implementing RemoteSign support in layout control software, based on how I have implemented it in my own software. These note should be read in conjunction with the SDK which describes the command syntax.

In the lines below, DC1 and DC2 characters separating fields have been omitted for legibility.

On connecting, my program sends these commands:

{NAME}Betreibswerk
{VER}3.7.32
{CH?}

The RemoteSign responds with its name etc...
{NAME}RemoteSign
{VER}2.7.13
{ASPECT}625
{READY}

My program sets up the RemoteSign with 26 rows, analog clock and syncs the time, etc.
{ROWS} 26
{CLEAR}H
{STUCK}0
{CLOCK}F
{CLOCK}A 5
{SOUND}1
{TIME}20:40:43

It then sends the screen layout. In this example, the RemoteSign is in fact handling two separate stations.
  • For each station it displays the name of the station, and column headings
  • For each track it displays the track number, and if a train is present, the train name
  • In this example, in the first station (Wilsnack Hbf.), one train is present (SZ Wür) and does not yet have any destination so it displays "NICHT EINSTEIGEN" (= Do not board)
  • In the second station (Wilsnack Tief) there are trains in both tracks, both also without destinations.
I allocate 8 characters for train names.

{TEXT} 1 Wilsnack Hbf. 5 1 20 L 65535 0 200
{TEXT} 2 Gl 6 1 3 L 12632256 0 75
{TEXT} 3 Zug 6 4 8 L 12632256 0 75
{TEXT} 4 Von/Nach 6 13 20 L 12632256 0 75
{ROW} 7 01 22833333333833333333333333333333811822422 0 0
{ROW} 7 01 SZ Wür NICHT EINSTEIGEN 22833333333833333333333333333333811822422 1
{ROW} 8 02 22833333333833333333333333333333811822422 0 0
{ROW} 8 02 22833333333833333333333333333333811822422 1
{ROW} 9 03 22833333333833333333333333333333811822422 0 0
{ROW} 9 03 22833333333833333333333333333333811822422 1
{ROW} 10 04 22833333333833333333333333333333811822422 0 0
{ROW} 10 04 22833333333833333333333333333333811822422 1
{ROW} 11 05 22833333333833333333333333333333811822422 0 0
{ROW} 11 05 22833333333833333333333333333333811822422 1
{ROW} 12 0 1
{TEXT} 5 Wilsnack Tief 13 1 20 L 65535 0 200
{TEXT} 6 Gl 14 1 3 L 12632256 0 75
{TEXT} 7 Zug 14 4 8 L 12632256 0 75
{TEXT} 8 Von/Nach 14 13 20 L 12632256 0 75
{ROW} 15 01 22833333333833333333333333333333811822422 0 0
{ROW} 15 01 S1 NICHT EINSTEIGEN 22833333333833333333333333333333811822422 1
{ROW} 16 02 22833333333833333333333333333333811822422 0 0
{ROW} 16 02 S3 NICHT EINSTEIGEN 22833333333833333333333333333333811822422 1
{ROW} 17 0 1
{ROW} 18 0 1
{ROW} 19 0 1
{ROW} 20 0 1
{ROW} 21 0 1
{ROW} 22 0 1
{ROW} 23 0 1
{ROW} 24 0 1
{ROW} 25 0 1
{ROW} 26 0 1

The RemoteSign responds with the channel data requested earlier, stating that it is a Regular RemoteSign on Ch 1, and Ch 2 has 10 sensors. (A sign will always be channel 1 so you can probably ignore this data initially. People may find the sensor data very useful though for triggering all sorts of stuff very cheaply, but I suggest handling that later!)
{CH}1 R 40 48 RemoteSign 2.7.13
{CH}2 S 10

Now, a train gets scheduled to arrive in track 2 of the main station. My program sends one line:
The train name is "ICE 1355", and it is coming from Göppingen, arriving at 20:48

{ROW} 8 02 ICE 1355 Göppingen An 20:48 22833333333833333333333333333333811822422 1

After it has arrived, and it is scheduled to depart, its destination is displayed:

{ROW} 8 02 ICE 1355 Köln Hbf. Ab 20:54 22833333333833333333333333333333811822422 1

Once it has left, the row is cleared:

{ROW} 8 02 22833333333833333333333333333333811822422 1


Here is an example of a RemoteSign that is dedicated as a platform sign (Typically a small ESP8266 sign in the actual station)
In this example it is a platform sign for the same track as above, so you can see corresponding details:

This time, it sets up the screen with just 4 rows, and a digital clock:
{ROWS} 4
{CLEAR}H
{STUCK}0
{CLOCK}F
{CLOCK}D
{SOUND}1
{TIME}20:45:38

When the train "ICE 1355" is scheduled, it sends these commands
{CLEAR}
{ROWS}4
{CLOCK}D

It defines the platform number as 2 on reverse video, 200% size
{TEXT}1 2 2 1 5 C 0 16711680 200

Ensures no scrolling text is active
{SCROLL}0

Displays the arrival time
{TEXT}2 20:48 1 7 5 L 16777215 0 100

Displays the train name
{TEXT}3 ICE 1355 2 7 9 L 16777215 0 100

Displays "from" in German in small text
{TEXT}4 von 2 18 3 L 16777215 0 50

Displays the origin city, centered
{TEXT}5 Göppingen 4 1 25 C 16777215 0 100


If no train is present, (say it just departed), it clears the screen, keeps the platform number in place, and displays an advert in scrolling text:
(The scrolling text is placed on row 3 or 4 randomly)

{CLEAR}
{ROWS}4
{CLOCK}D
{TEXT}1 2 2 1 5 C 0 16711680 200
{SCROLL} 3 City-Ticket: Nahverkehr inklusive - jetzt bei Sparpreis und Flexpreis im Fernverkehr.


When my program decides to disconnect from a RemoteSign it sends:
{BYE}


Platform states

The states I handle for a track in my layout software are:
  • no train present
  • train scheduled to arrive from some origin
  • train present and scheduled to depart to some destination
  • train present but not scheduled to go anywhere (route cancelled, or none yet set)
  • train schedule to pass through
Other states may be more appropriate for your software.

General notes

  • I maintain an array of RemoteSigns, sending different commands to each sign as needed. (I initially coded for just one, but found one can have a bunch of them!)
  • For animated rows (with the flap boards) use the mask data to tune the characters that get flipped through, or blank columns.
  • Monitor the events for connections and disconnections so that when a sign connects, you can set up its screen for its intended purpose once. (rows, clock type, etc)
  • I also send a {PING} command periodically in case a RemoteSign disconnected in such a manner that I never got a disconnect event. If it has disconnected, this typically generates an error event that I can use to clean up the disconnection.
  • For RemoteSigns that have been set up, but are not connected, I periodically (60s) try to connect. Sometimes the machine running the RemoteSign has not been powered up.
  • For each RemoteSign, I allow the user to define the IP/host name, a name for that RemoteSign (used in logging, and displaying {MSG} or {ERROR} content), pick lists etc., how many rows to use, the type of clock, (digital/analog/none) and if analog, the clock colors, etc.
  • When adding a new RemoteSign, I also offer a way to locate them on the network, by sending connection request on port 50601 to all the IP addresses on the LAN, when RemoteSigns respond, I put their IP address (and host name) into a list in the UI for the user to pick. (Initially I just provided a place to enter the IP address or hostname!)

Data Structures

Typical data structure in (Visual Basic syntax) I use for each RemoteSign:

Name As String
IPaddress As String
Port As Long ' TCPIP port number
ScreenRows As Byte ' current number of rows in the RemoteSign
Clock As ClockSettingsType
Sensors() As Integer ' index 0 = count. Sensors available via this RemoteSign

' data from other end
HostAppName As String
HostVersion As String
' these fields will be populated with data {CH} the remote device
CH() As RemoteSignChannelType
LastError As String ' last winsock error

Dirty As Boolean ' true if this RemoteSign has been edited in the UI and needs to be saved

Typical structure of clock settings:

Analog As Boolean ' analog or digital?
H24 As Boolean ' 24 hour or not
FaceColor As Long
HandColor As Long
TickColor As Long
SecondHandColor As Long
SecondHand As Boolean ' show second hand or not
Size As Integer ' screen rows
Speed As Byte ' fast speed. zero or 1 = real time. 2 = 2x etc.
StartTime As Date ' a time value to force into the clock


Hopefully your software provides the events and hooks needed to know when to update the status of a track in a station.

Events

My layout software also has what I call events - these can be almost any sort of action that can be triggered by various things. For example I can play a sound effect, start a route, etc. I also allow RemoteSign events to be defined, so the user can enter any RemoteSign commands they like, for example, if someone wants to display a welcome message for their club they can enter a {SCROLL} command with their desired row number and text. I provide buttons to insert DC1 and DC2 characters. I also allow multiple lines to be defined in a single event, using \r to indicate the line breaks. Before sending any commands to a RemoteSign I replace " \r " with carriage returns. This could be an unsophisticated way of allowing people to define screens that get triggered by other events. This feature allows people to create sound players allowing sound effects to be played on demand (using {PLAY} command)!