RailSignalAPI/component-drivers.md

5.1 KiB

Component Drivers

This document describes the general methodology for writing component drivers that operate within your rail system to connect it to the online system's up- and down-link services.

The following types of components are supported by Rail Signal:

  • SIGNAL
  • SEGMENT_BOUNDARY
  • SWITCH

The following information is generally required for any driver to be able to connect to the system and operate nominally:

  • A valid link token
  • The base URL of the system's API. Usually http://localhost:8080 or whatever you've configured it to be.
  • Live connection information. This differs depending on what type of communication your device supports.
    • For devices with websocket support, you will need the base URL of the websocket. Usually ws://localhost:8080 or whatever you've configured your server to use.
    • For devices with TCP socket support, you will need the hostname and port of the system's server socket. By default, this is localhost:8081.

A device is not limited to a single component, but will act as a relay for all components linked to the device's link token. Generally, there is no limit to the number of components that a single device can manage, but more components will lead to more load on the device.

Live Communication

The main purpose of component drivers is to relay real-time messages between actual component devices, and their representations in the online rail system. While multiple types of communication are available, in general, all messages are sent as JSON UTF-8 encoded strings. Devices must present their link token when they initiate the connection.

If the link token is valid, the connection will be initiated, and the device will immediately receive a COMPONENT_DATA message for each component that the token is linked to.

Websocket

Websocket connections should be made to {BASE_WS_URL}/api/ws/component?token={token}, where {BASE_WS_URL} is the base websocket URL, such as ws://localhost:8080, and {token} is the device's link token.

  • If the link token is missing or improperly formatted, a 400 Bad Request response is given.
  • If the link token is not correct or not active or otherwise set to reject connections, a 401 Unauthorized response is given.

TCP Socket

TCP socket connections should be made to the server's TCP socket address, which by default is localhost:8081. The device should immediately send 2 bytes indicating the length of its token string, followed by the token string's bytes. The client should expect to receive in response a connect message:

{
  "valid": true,
  "message": "Connection established."
}
  • If the token is invalid, a "valid": false is returned and the server closes the socket.

Note: All messages sent via TCP are sent as JSON messages with a 2-byte length header.

Components

Each device should be designed to handle multiple independent components concurrently. The device may receive messages at any time pertaining to any of the components, and the device may send messages at any time, pertaining to any of the components. Messages are only sent regarding a single component.

Every component message should contain at least the following two properties:

{
  "cId": 123,
  "type": "COMPONENT_DATA",
  ...
}

cId is the id of the component that this message is about. type is the type of message. This defines what additional structure to expect.

All components may receive COMPONENT_DATA messages. For example, the following could be a message regarding a signal:

{
  "cId": 123,
  "type": "COMPONENT_DATA",
  "data": {
    "id": 123,
    "position": {"x": 0, "y": 0, "z": 0},
    "name": "my-component",
    "type": "SIGNAL",
    "online": true,
    "segment": {
      "id": 4,
      "name": "my-segment",
      "occupied": false
    }
  }
}

The following sections will provide more detail about the other types of messages that can be sent and received by the different components.

Signal

Signals display the status of a connected segment, and as such can only receive data. They will receive SEGMENT_STATUS messages:

{
  "cId": 123,
  "type": "SEGMENT_STATUS",
  "segmentId": 4,
  "occupied": true
}

sId is the id of the segment that was updated. occupied contains the current status of the segment.

Segment Boundary

Segment boundaries send updates as trains pass them, in order to provide information to the system about the state of connected segments.

{
  "cId": 123,
  "type": "SEGMENT_BOUNDARY_UPDATE",
  "toSegmentId": 3,
  "eventType": "ENTERING"
}

toSegmentId is the id of the segment a train is moving towards. eventType is the type of boundary event. This can either be ENTERING if a train has just begun entering the segment, or ENTERED if a train has just left the boundary and completely entered the segment.

Switch

Switches can send information about their status, if it's been updated, and they can also receive messages that direct them to change their status.

{
  "cId": 123,
  "type": "SWITCH_UPDATE",
  "activeConfigId": 497238
}

activeConfigId is the id of the switch configuration that's active. This message can be sent by either the system or the switch.