- Java 85.4%
- JavaScript 9.4%
- HTML 5.2%
| src | ||
| .gitignore | ||
| config.json | ||
| data.example.json | ||
| data.json | ||
| pom.xml | ||
| README.md | ||
wiFred Server 0.3
Spring-Boot/Java-21 command-station front end for WiThrottle and the public Roco Z21 LAN protocol. It keeps the rail side behind RailBackend; the current backend is in-memory so the network protocols and mappings can be tested before LocoNet is attached.
Start
Requirements: Java 21 and Maven 3.9+.
mvn clean package
java -jar target/wifred-server-0.3.0-SNAPSHOT.jar
or:
mvn spring-boot:run
Open http://localhost:8080.
Server config vs. assignment data
config.json is the real server configuration:
{
"http_port": 8080,
"withrottle_port": 12090,
"z21_enabled": true,
"z21_port": 21105,
"active_timeout_seconds": 30,
"heartbeat_seconds": 16,
"mdns_enabled": true,
"server_name": "wiFred Server",
"data_file": "data.json",
"default_mapping_mode": "PASSTHROUGH",
"default_legacy": true
}
The mutable Fred/client assignments are stored in data_file, normally data.json. Writes are done through a temporary file and a .bak copy is retained.
Mapping model
There are now three user-facing modes:
PASSTHROUGH: requested DCC address is the real DCC address.MANAGED: only for managed wiFreds. VirtualS1…S4selectslots.1…slots.4;slots.fallbackis used for empty/unassigned slots.ADDRESS_MAP: intended for legacy WiThrottle and Z21 clients. An incoming DCC address maps directly to an output assignment/traction.address_map.fallbackhandles all addresses without an explicit entry.
The previous ADDRESS_TO_SLOT data format is accepted on load and migrated in memory to ADDRESS_MAP by copying the referenced slot assignments.
Example direct mapping:
{
"legacy": true,
"mapping_mode": "ADDRESS_MAP",
"address_map": {
"L218": {
"locos": [
{"address": 64, "type": "SHORT", "invert_direction": false, "speed_multiplier": 1.0}
]
},
"fallback": {
"locos": [
{"address": 100, "type": "LONG", "invert_direction": false, "speed_multiplier": 1.0}
]
}
}
}
Each assignment can contain multiple locomotives. Speed is multiplied per member, direction can be inverted per member, and functions/E-stop go to all members.
Z21 support
The server listens on UDP 21105 by default. Z21 is based on Roco's public LAN protocol V1.13.
Implemented in this first pass:
- multiple Z21 datasets in one UDP datagram
LAN_GET_SERIAL_NUMBERLAN_GET_HWINFOLAN_LOGOFFLAN_SET_BROADCASTFLAGS/LAN_GET_BROADCASTFLAGSLAN_SYSTEMSTATE_GETDATALAN_GET_LOCOMODE(DCC)LAN_X_GET_VERSIONLAN_X_GET_STATUS- track power on/off status and broadcasts
- global stop
LAN_X_GET_FIRMWARE_VERSIONLAN_X_GET_LOCO_INFOand subscribedLAN_X_LOCO_INFObroadcastsLAN_X_SET_LOCO_DRIVEfor 14/28/128 stepsLAN_X_SET_LOCO_FUNCTION(off/on/toggle)LAN_X_SET_LOCO_E_STOPLAN_X_PURGE_LOCO
A Z21 client is intentionally treated like a legacy WiThrottle client. Its stable configuration key is currently z21@<IP address> while the UDP source port is runtime information. This means two independent Z21 apps behind the same source IP share one mapping profile; that can be generalized later if needed.
For Z21 input addresses, values below 128 are represented as S... and values >=128 as L.... ADDRESS_MAP also accepts bare numeric keys, and the resolver permits S/L aliases below 128 because the Z21 packet format cannot reliably distinguish that case.
The server does not advertise itself as a Z21 through WiThrottle mDNS. Configure the server PC's IP in the Z21 client/app and use UDP port 21105. On Windows, allow Java on private networks and allow UDP 21105 through the firewall.
WiThrottle
The WiThrottle implementation remains focused on the subset needed by wiFred and generic clients such as Engine Driver. It identifies as HTJMRI for broad client compatibility, supports heartbeat, multi-throttle acquire/release, speed, direction, F0-F28, momentary function semantics and emergency stop. Unsupported packets are logged and ignored rather than terminating the connection.
Managed wiFred firmware can probe:
GET /api/v1/ident(alias/api/v1/capabilities)POST /api/v1/freds/identify(alias/api/v1/identify)
An Identify call creates a new device entry as non-legacy MANAGED if it does not already exist.
UI
The UI uses the full page width with a left diagnostics column for Identify, the packet/server log and a placeholder for a future LocoNet terminal. Z21 clients are marked Legacy and cannot select MANAGED. ADDRESS_MAP edits incoming addresses directly and each target can still be a traction.
Saving closes the editor immediately after a successful write.
Sources used for protocol behavior
- Roco Z21 LAN Protocol Specification V1.13: https://www.z21.eu/de/downloads/anleitungen
- ZIMO's independent MPL-2.0 server implementation was used only as a behavioral reference: https://github.com/ZIMO-Elektronik/Z21
- The supplied JMRI source tree was used as a behavior reference for WiThrottle, not copied as a fork.
Next steps
- Test with the official Z21 app and inspect the left-side packet log for commands the app expects beyond the current subset.
- Attach LocoNet behind
RailBackend. - Add the Excel locomotive import and activate the existing “Lok auswählen” workflow.