Concept
RailCommand gives every layout a set of JMRI-style object tables — one per object type: Signals, Turnouts, Sensors, and Toggles. Each is the authoritative list of that object's addresses and settings for the layout. You reach them per layout at /app/railcommand/layouts/{LayoutId}/signals, /turnouts, /sensors, and /toggles.
The most important idea is what is derived versus authored. Signal aspects are data-driven: the aspect a signal shows is computed from the layout's derived graph topology, not from anything you set by hand. Each signal cell maps to a mast, the mast maps to a derived SignalingRelation naming its protected block(s) and the next block, and block occupancy resolves the aspect — Stop when a protected block is occupied, Approach when the next block is occupied, otherwise Clear. When a signal has no derived relation it stays dark/unknown — it never falls back to a proximity guess. What you author is the signal's identity and wiring: name, style, signaling system, DCC addresses, aspect colours, and — in the Layout Editor — its facing.
How To
- Open Signal Configuration at
/app/railcommand/layouts/{LayoutId}/signals. The summary cards show Signal Cells, Configured, Bound To Hardware, Missing DCC Address, and By Type. Signal Cells counts the signal cells standing on this layout's switchboard panels, which is not the same population as the decoded signal records a TrainController import reports: a record the file gave no switchboard position can never be a cell here, and the import summary itemizes every difference between the two counts. Every object table names its population the same way (Signal Cells, Turnout Cells, Sensor Cells and Block Sensors, Toggle Cells), each says the cells it counts are those placed on a switchboard panel, and each carries a line under its summary cards saying what the import counts instead. The Sensor table is the one whose population is not cells alone: a sensor a block owns has no contact cell of its own, so that table names both halves and counts them apart. Use the Status, Type, Style, and Connection filters to narrow the list. Configured is layout knowledge (address and aspects on the cell); Bound To Hardware is what the operating engine will actually drive (a live hardware binding exists). An addressed signal with no binding shows an Unbound chip: re-import the layout, or apply the import's bindings step, to create the missing bindings. A signal that is on a panel but attached to no track shows an attached to no track chip: it is drawn and its head can be driven, but it protects no block, because nothing on the graph tells it which run it governs. Place it on the run it governs in the Layout Editor, or import the file again and answer the question on the Signals tab. The chip is a live reading of the layout rather than a record of the import: it clears once the signal attaches, and it appears on any signal that is detached later. - Click a signal row to open its inline editor. Set Signal Name, Signal Style (Color Light, Searchlight, Position, Semaphore, Dwarf), and Signaling System (Default, NORAC, GCOR, CROR, and the European/Japanese presets).
- Enter DCC Address 1, and DCC Address 2 for 4-aspect signals; tick Stop Restricted Mode if the signal drops to restricting rather than stop. Since 2026-08-29 the Layout Editor's signal dialog also shows the Aspect outputs grid: per aspect, which Thrown or Closed state each of the two addresses is set to. TrainController imports fill it automatically; author it here for hand-built signals. A connected multi-aspect signal whose map is missing, short, or names Address 2 with no second address stored shows a Map incomplete chip on the Signal Configuration list until it is finished.
- Under Signal Aspects, set each aspect's colour and name. Restricting shown as picks how this mast displays a Restricting indication — the system default, flashing red, red over yellow, or flashing yellow (railroads legitimately use any of these; heads without a lunar lamp, like the SE8c's, can never show steady lunar). Choosing a non-default forks a tenant mast type carrying the choice. Use the Aspect Output Map (Index / Name / Addr 1 State / Addr 2 State) to name the decoded head wiring so the colour ordering matches the physical head. Click Save.
- For Turnouts / Sensors / Toggles, open the matching table and click Add: the add-at-position form takes Panel, Type, Column, Row, Orientation (0-7), Name, and DCC Address (turnouts also take a Normal route). Placement is collision-guarded and re-derives topology. On the Turnout table the Addressed card counts the addresses standing on cells, not the addresses a file held: a switch TrainController marks Without Connection keeps its stored address in the file and is imported with none, because that stored value is stale by the file's own account.
- Wrong aspect family on an imported signal? Reassign it in place — no delete-and-replace. On the web, open the signal on the Layout Editor canvas and set Element type / Aspect Family on the General tab. On the desktop, select the signal and use Aspect family in the cell-properties panel. The cell keeps its identity: name, DCC addresses, authored facing, and its physical head configuration all ride through (lamp count is not aspect count). Only the family-scoped parts re-gate — the stale aspect rows are cleared and re-prepopulated from the new family's preset, and the mast re-binds to the new family's default mast type. A signal carrying a specialized or regional type (searchlight, dwarf, position-light, semaphore, Ks, Hp0/Hp1/Hp2, or a British/French/Dutch/Italian/Japanese/Swiss type) is named as itself in the picker, and converting it to a plain 2/3/4-aspect family asks for confirmation first, because that replaces the specialized type and the glyph drawn on the switchboard.
- Author signal facing in the Layout Editor; the facing picker offers the real ports of the signal's graph node (compass ports for track, role ports like Normal/Reverse for turnouts).
- Driving heads from a Digitrax SE8c? Use SE8c Board Setup (button in the Signal Configuration header, or
/app/railcommand/layouts/{LayoutId}/se8c-setup) before binding: it walks the board's factory reset, Board ID, head wiring types, and the required 4th-aspect-Dark option switches — automated (RailCommand sends every switch command through the running operating session's layout host) or guided (it shows the exact throttle commands). The final step drives the test mast and asks what you see; the Dark answer is the proof the board is configured for RailCommand.
Troubleshooting
A signal shows dark or "unknown" — It has no derived SignalingRelation. Confirm it is placed on the graph and its facing points into a real block; re-open the Layout Editor so topology re-derives.
An "attached to no track" chip appears: this signal is on a panel but attached to nothing on the track graph, so it protects no block. TrainController records no association between a drawn signal and the run beside it, so an import attaches a signal to the track under it or the one cell perpendicular to its facing, and one with neither is imported flagged rather than quietly. Move it onto the run it governs in the Layout Editor, then re-open the editor so topology re-derives. The chip is a live reading of the layout rather than a record of the import: it clears once the signal attaches, and it appears on any signal that is detached later.
"Missing DCC Address" count is red — One or more signals have no DCC Address 1. Open each and set the address, or mark it as a dispatcher-driven signal.
A "No conn" badge appears — That signal (or turnout) is Without connection: driven by the dispatcher group, not a LocoNet/DCC address. That is expected for virtual dispatcher objects.
Add-at-position rejects the cell — The Column/Row is occupied. Pick an empty cell; the form will not overwrite an existing object.
The Sensor table's count looks far too high, or shows hundreds of sensors "without connection". The sensor table counts feedback contacts plus the sensors each block owns; a block's occupancy marker is a block, not a sensor, and is counted in the Block Editor at /app/railcommand/layouts/{LayoutId}/blocks. A sensor a block owns is listed under its block's name, because TrainController decodes it as a block member and it has no contact cell of its own; its row links to that block's Block Detail panel, where its kind and its address (board, input and mode) are set, and where it can instead be placed on a contact cell of its own. Where the imported block sat on its own occupancy contact, the block took that contact's cell and its address: the detector is still listed, under its block, and its address is corrected on that row. Contacts whose occupancy is computed (a virtual contact, or a block's flagman) are shown as Computed with no address: they have nothing to wire, so they are never counted as missing a connection.
An imported signal has the wrong number of aspects — Reassign its aspect family in place rather than deleting and re-placing it (step 6). Deleting would mint a new cell and lose the anchors, facing, and wiring that hang off the old one.
The aspect family will not change on a head-extension cell — Head extensions belong to a multi-head mast, so the family is a property of the anchor. Change it on the anchor signal, or ungroup the mast first.
A specialized or regional signal type is not in the family picker — The picker offers the three plain families plus the type the cell already has. It converts away from a specialized type (with a confirmation), but it cannot convert into one: to change a signal to a regional type, place that type from the palette.
Safety Notes
These pages are authoring surfaces only. Editing a signal, adding a turnout, or naming an aspect updates the layout's stored configuration; it does not move hardware and does not change what a live signal is showing. During an operating session the local/UE5 runtime owns aspect resolution and any physical signal output — the web and the Avalonia desktop present state and forward intent, they never actuate hardware. Because aspects are derived from topology, an incorrect facing or a mis-placed block can change what a signal protects. Treat facing and block placement as safety-relevant: verify them in the editor before an operating session, and never hand-edit an aspect to "fix" a wrong indication — correct the topology instead.